Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/Cassandra/Cluster/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ public function withPersistentSessions($enabled) { }
*
* NOTE: Apache Cassandra 3.x supports protocol version 3 and 4 only
*
* @param int $version The protocol version
* @param \Cassandra\ProtocolVersion|int $version The protocol version
*
* @return \Cassandra\Cluster\Builder self
*/
Expand Down
1 change: 1 addition & 0 deletions include/php_scylladb_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_core_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_cluster_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_default_cluster_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_cluster_builder_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_protocol_version_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_ssl_options_builder_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_future_ce;
extern PHP_SCYLLADB_API zend_class_entry *php_scylladb_future_prepared_statement_ce;
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ target_sources(src PRIVATE
UuidGen.c
DefaultSession.c
PreparedStatement.c
ProtocolVersion.c
Set.c
SimpleStatement.c
Tuple.c
Expand Down Expand Up @@ -89,6 +90,7 @@ php_scylladb_generate_arginfo(src
Blob.stub.php
Map.stub.php
Cassandra.stub.php
ProtocolVersion.stub.php
PreparedStatement.stub.php
Collection.stub.php
Session.stub.php
Expand Down Expand Up @@ -127,6 +129,7 @@ php_scylladb_generate_descriptor(src
Tuple.stub.php
UserTypeValue.stub.php
Cassandra.stub.php
ProtocolVersion.stub.php
Future.stub.php
FuturePreparedStatement.stub.php
FutureRows.stub.php
Expand Down
16 changes: 12 additions & 4 deletions src/Cluster/Builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include <zend_smart_str.h>
#include <Zend/zend_enum.h>

#include <cassandra.h>

Expand Down Expand Up @@ -528,22 +529,29 @@ ZEND_METHOD(Cassandra_Cluster_Builder, withPersistentSessions)
}
ZEND_METHOD(Cassandra_Cluster_Builder, withProtocolVersion)
{
zend_long version;
zend_object *versionCase = nullptr;
zend_long version = 0;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(version)
Z_PARAM_OBJ_OF_CLASS_OR_LONG(versionCase, php_scylladb_protocol_version_ce, version)
ZEND_PARSE_PARAMETERS_END();

if (version < 1)
if (versionCase != nullptr)
{
version = Z_LVAL_P(zend_enum_fetch_case_value(versionCase));
}
else if (version < 1)
{
/* An int still gets through for versions the enum does not name, such
* as the DSE ones — so it keeps its own range check. */
zval val;
ZVAL_LONG(&val, version);
throw_invalid_argument(&val, "version", "a positive number");
return;
}

auto self = PHP_SCYLLADB_GET_CLUSTER_BUILDER(getThis());
self->protocol_version = version;
self->protocol_version = (uint32_t)version;

RETURN_ZVAL(getThis(), 1, 0);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Cluster/Builder.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function withPersistentSessions(bool $enabled = true): static
{
}

public function withProtocolVersion(int $version): static
public function withProtocolVersion(\Cassandra\ProtocolVersion|int $version): static
{
}

Expand Down
15 changes: 14 additions & 1 deletion src/Cluster/BuilderHandlers.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <php.h>
#include <Zend/zend_enum.h>

#include <php_scylladb.h>
#include <php_scylladb_globals.h>
Expand Down Expand Up @@ -127,7 +128,19 @@ HashTable *php_scylladb_cluster_builder_properties(zend_object *object)
}

ZVAL_BOOL(&usePersistentSessions, self->persist);
ZVAL_LONG(&protocolVersion, self->protocol_version);

zend_object *protocolVersionCase = nullptr;
if (zend_enum_get_case_by_value(&protocolVersionCase, php_scylladb_protocol_version_ce,
(zend_long)self->protocol_version, nullptr, true) == SUCCESS
&& protocolVersionCase != nullptr)
{
ZVAL_OBJ_COPY(&protocolVersion, protocolVersionCase);
}
else
{
ZVAL_LONG(&protocolVersion, self->protocol_version);
}

ZVAL_LONG(&ioThreads, self->io_threads);
ZVAL_LONG(&coreConnectionPerHost, self->core_connections_per_host);
ZVAL_LONG(&maxConnectionsPerHost, self->max_connections_per_host);
Expand Down
13 changes: 13 additions & 0 deletions src/ProtocolVersion.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <cassandra.h>

#include <php_scylladb.h>
#include <php_scylladb_types.h>

/* gen_stub ignores docblocks on enum cases, so `@cvalue` cannot bind a case to
* a CASS_* macro the way it does for class constants. The cases carry literal
* values and these assertions hold them to the driver header instead. */
static_assert(CASS_PROTOCOL_VERSION_V1 == 1, "Cassandra\\ProtocolVersion::V1 no longer matches CASS_PROTOCOL_VERSION_V1");
static_assert(CASS_PROTOCOL_VERSION_V2 == 2, "Cassandra\\ProtocolVersion::V2 no longer matches CASS_PROTOCOL_VERSION_V2");
static_assert(CASS_PROTOCOL_VERSION_V3 == 3, "Cassandra\\ProtocolVersion::V3 no longer matches CASS_PROTOCOL_VERSION_V3");
static_assert(CASS_PROTOCOL_VERSION_V4 == 4, "Cassandra\\ProtocolVersion::V4 no longer matches CASS_PROTOCOL_VERSION_V4");
static_assert(CASS_PROTOCOL_VERSION_V5 == 5, "Cassandra\\ProtocolVersion::V5 no longer matches CASS_PROTOCOL_VERSION_V5");
24 changes: 24 additions & 0 deletions src/ProtocolVersion.stub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* @generate-class-entries
*/

declare(strict_types=1);

namespace Cassandra {
/**
* Native protocol version used on the wire.
*
* The backing value is the version byte the protocol itself defines, so it
* matches CASS_PROTOCOL_VERSION_V1 … CASS_PROTOCOL_VERSION_V5.
*/
enum ProtocolVersion: int
{
case V1 = 1;
case V2 = 2;
case V3 = 3;
case V4 = 4;
case V5 = 5;
}
}
70 changes: 70 additions & 0 deletions tests/Unit/ClusterBuilderProtocolVersionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace Cassandra\Tests\Unit;

use Cassandra;
use Cassandra\ProtocolVersion;

describe('Cassandra\ProtocolVersion', function () {

it('is an int-backed enum whose cases match the protocol version byte', function () {
expect(ProtocolVersion::V1->value)->toBe(1);
expect(ProtocolVersion::V2->value)->toBe(2);
expect(ProtocolVersion::V3->value)->toBe(3);
expect(ProtocolVersion::V4->value)->toBe(4);
expect(ProtocolVersion::V5->value)->toBe(5);
});

it('exposes exactly the five native protocol versions', function () {
expect(array_column(ProtocolVersion::cases(), 'name'))
->toBe(['V1', 'V2', 'V3', 'V4', 'V5']);
});

it('resolves a case from its backing value', function () {
expect(ProtocolVersion::from(4))->toBe(ProtocolVersion::V4);
expect(ProtocolVersion::tryFrom(9))->toBeNull();
});
});

describe('Cassandra\Cluster\Builder protocol version', function () {

it('defaults to v4', function () {
$props = (array) Cassandra::cluster();

expect($props['protocolVersion'])->toBe(ProtocolVersion::V4);
});

it('stores the version passed as an enum case', function () {
$props = (array) Cassandra::cluster()->withProtocolVersion(ProtocolVersion::V5);

expect($props['protocolVersion'])->toBe(ProtocolVersion::V5);
});

it('returns the builder so calls chain', function () {
$builder = Cassandra::cluster();

expect($builder->withProtocolVersion(ProtocolVersion::V3))->toBe($builder);
});

it('still accepts a plain integer', function () {
$props = (array) Cassandra::cluster()->withProtocolVersion(3);

expect($props['protocolVersion'])->toBe(ProtocolVersion::V3);
});

it('keeps an integer the enum does not name', function () {
$props = (array) Cassandra::cluster()->withProtocolVersion(0x41);

expect($props['protocolVersion'])->toBe(0x41);
});

it('rejects a non-positive integer', function () {
Cassandra::cluster()->withProtocolVersion(0);
})->throws(\Cassandra\Exception\InvalidArgumentException::class);

it('rejects a value that is neither an int nor a ProtocolVersion', function () {
Cassandra::cluster()->withProtocolVersion('v4');
})->throws(\TypeError::class);
});
Loading
Loading