• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..27-Mar-2020-

bootstrap/H27-Mar-2020-442302

sessions/H27-Mar-2020-279251

.navH A D27-Mar-2020208 1514

README.mdH A D27-Mar-202022.1 KiB535374

batch_statements.featureH A D27-Mar-20202.9 KiB8473

client_side_timestamps.featureH A D27-Mar-20205.6 KiB162142

collections.featureH A D27-Mar-20204.8 KiB164153

consistency_level.featureH A D27-Mar-20203.6 KiB10896

datatypes.featureH A D27-Mar-20205.6 KiB203186

duration.featureH A D27-Mar-20201.5 KiB5243

duration_collections.featureH A D27-Mar-20202.8 KiB7561

function_and_aggregate_metadata.featureH A D27-Mar-20205.1 KiB140131

logging.featureH A D27-Mar-2020693 2521

materialized_view_metadata.featureH A D27-Mar-20202 KiB6660

prepared_statements.featureH A D27-Mar-20202.5 KiB8375

result_paging.featureH A D27-Mar-20205.2 KiB163143

retry_polices.featureH A D27-Mar-20206.6 KiB176157

schema_metadata.featureH A D27-Mar-202011.9 KiB368346

secondary_index_metadata.featureH A D27-Mar-20203.5 KiB113100

simple_statements.featureH A D27-Mar-20206.6 KiB213192

simple_string_queries.featureH A D27-Mar-20204.7 KiB143125

ssl_encryption.featureH A D27-Mar-20203.3 KiB10898

tuples.featureH A D27-Mar-20202.4 KiB8778

user_defined_types.featureH A D27-Mar-20206.5 KiB215199

README.md

1# Features
2
3## Usage
4
5### Specifying addresses of Cassandra nodes
6
7[`withContactPoints()`](/api/Cassandra/Cluster/class.Builder/#method.withContactPoints) and [`withPort()`](/api/Cassandra/Cluster/class.Builder/#method.withPort) methods of the [`Cassandra\Cluster\Builder`](/api/Cassandra/Cluster/class.Builder/) are used to specify IP addresses or hostnames and port number of the nodes in a given Cassandra cluster.
8
9Note that you don't have to specify the addresses of all hosts in your cluster. Once the driver has established a connection to any host, it will perform auto-discovery and connect to all hosts in the cluster.
10
11```php
12<?php
13
14$cluster = Cassandra::cluster()
15               ->withContactPoints('10.0.1.24', 'example.com', 'localhost')
16               ->withPort(9042)
17               ->build();
18$session = $cluster->connect();
19```
20
21### Discovering nodes in the cluster
22
23After the initial connection to one of the hosts specified via `withContactPoints()` succeeds, the driver discovers the addresses and connects to all members of the cluster automatically. You can also see the nodes that the driver discovered by running `SELECT * FROM system.peers`.
24
25### Persistent sessions
26
27In order to limit the startup time and total number of connections to a Cassandra cluster, the PHP Driver enables persistent sessions by default. All cluster and sessions using the same initial configuration will be shared across requests when persistent sessions are enabled. You can toggle this setting using [`Cassandra\Cluster\Builder::withPersistentSessions()`](/api/Cassandra/Cluster/class.Builder/#method.withPersistentSessions).
28
29```php
30<?php
31
32$cluster = Cassandra::cluster()
33               ->withPersistentSessions(false)
34               ->build();
35$session = $cluster->connect();
36```
37
38Note that disabling persistent sessions will cause a significant slow down of cluster initialization as the connections will be forced to get re-established for every request.
39
40Once persistent sessions are enabled, you can view how many of them are currently active. They will be exposed in the Cassandra extension section of `phpinfo()`.
41
42Persistent sessions stay alive for the duration of the parent process, typically a php-fpm worker or apache worker. These sessions will be reused for all requests served by that worker process. Once a worker process has reached its end of life, sessions will get cleaned up automatically and will be re-create in the new process.
43
44### Configuring load balancing policy
45
46The PHP Driver comes with a variety of load balancing policies. By default it uses a combination of latency aware, token aware and data center aware round robin load balancing.
47
48The token aware load balancing policy uses the same hashing algorithms as the Apache Cassandra to directly route the execution of prepared statements to the replica node, avoiding an additional network hop to/from the coordinator. You can toggle its usage with [`Cassandra\Cluster\Builder::withTokenAwareRouting()`](/api/Cassandra/Cluster/class.Builder/#method.withTokenAwareRouting).
49
50```php
51<?php
52
53$cluster = Cassandra::cluster()
54               ->withTokenAwareRouting(false)
55               ->build();
56$session = $cluster->connect();
57```
58
59The default datacenter aware round robin load balancing policy is configured to keep all traffic in the same datacenter. Upon connecting to a host from the initial list of contact points, the driver will consider that host's datacenter to be local. Only hosts from the same datacenter will be connected to and used for executing statements. You can override the name of the local datacenter. The number of hosts from remote datacenters that the driver may use and whether it should execute statements with local consistencies on those hosts in case none of the local hosts are available. All of that is configurable via [`Cassandra\Cluster\Builder::withDatacenterAwareRoundRobinLoadBalancingPolicy()`](/api/Cassandra/Cluster/class.Builder/#method.withDatacenterAwareRoundRobinLoadBalancingPolicy).
60
61```php
62<?php
63
64$cluster = Cassandra::cluster()
65               ->withDatacenterAwareRoundRobinLoadBalancingPolicy("us-west", 2, true)
66               ->build();
67$session = $cluster->connect();
68```
69
70You may disable datacenter awareness by calling [`Cassandra\Cluster\Builder::withRoundRobinLoadBalancingPolicy()`](/api/Cassandra/Cluster/class.Builder/#method.withRoundRobinLoadBalancingPolicy).
71
72```php
73<?php
74
75$cluster = Cassandra::cluster()
76               ->withRoundRobinLoadBalancingPolicy()
77               ->build();
78$session = $cluster->connect();
79```
80
81Finally, latency-aware routing ensures that requests are routed to the hosts that respond the fastest. You can switch it off via [`Cassandra\Cluster\Builder::withLatencyAwareRouting()`](/api/Cassandra/Cluster/class.Builder/#method.withLatencyAwareRouting).
82
83```php
84<?php
85
86$cluster = Cassandra::cluster()
87               ->withLatencyAwareRouting(false)
88               ->build();
89$session = $cluster->connect();
90```
91
92### Setting protocol version
93
94The PHP driver will automatically negotiate native protocol version of TCP connections to the latest supported by both the driver and Apache Cassandra servers. It does this by attempting connection at the highest supported protocol version (currently 2) and negotiating it down upon unsupported version responses from the server.
95
96In a scenario with an Apache Cassandra cluster consisting of nodes of mixed versions (e.g. 1.2.x and 2.0.x), this might pose problems as the driver could establish native protocol version to be 2, while some of the nodes don't support it, causing connections to the rest of the cluster to fail.
97
98You can force the driver to start negotiation at a lower protocol version by using [`Cassandra\Cluster\Builder::withProtocolVersion()`](/api/Cassandra/Cluster/class.Builder/#method.withProtocolVersion).
99
100```php
101<?php
102
103$cluster = Cassandra::cluster()
104               ->withProtocolVersion(1)
105               ->build();
106$session = $cluster->connect();
107```
108
109### Tweaking driver's throughput
110
111There are a few variables affecting the total throughput of the driver that can be tweaked client-side. The maximum number of requests that can be executed at the same time is calculated with the following formula:
112
113```
114inflight_requests = io_threads * requests_per_connection * maximum_number_of_connections_per_host * connected_hosts
115```
116
117Where `io_threads` by default is `1`, `requests_per_connection` for the currently supported protocol versions is `128`, `maximum_number_of_connections_per_host` by default is `2` and `connected_hosts` is the total number of hosts that can be connected to. This last variable depends on the load balancing policy used, data center aware policy only connects to the hosts in the same data center by default.
118
119You can change the value of `io_threads` from the formula above by using [`Cassandra\Cluster\Builder::withIOThreads()`](/api/Cassandra/Cluster/class.Builder/#method.withIOThreads).
120
121```php
122<?php
123
124$cluster = Cassandra::cluster()
125               ->withIOThreads(4)
126               ->build();
127$session = $cluster->connect();
128```
129
130You can change the value of `maximum_number_of_connections_per_host` from the formula above by using [`Cassandra\Cluster\Builder::withConnectionsPerHost()`](/api/Cassandra/Cluster/class.Builder/#method.withConnectionsPerHost).
131
132```php
133<?php
134
135$cluster = Cassandra::cluster()
136               ->withConnectionsPerHost(4, 8)
137               ->build();
138$session = $cluster->connect();
139```
140
141### Disabling TCP nodelay
142
143By default, the driver enables TCP nodelay (Nagle's algorithm) on all connections it uses. Disabling it is not recommended but possible via [`Cassandra\Cluster\Builder::withTCPNodelay()`](/api/Cassandra/Cluster/class.Builder/#method.withTCPNodelay).
144
145```php
146<?php
147
148$cluster = Cassandra::cluster()
149               ->withTCPNodelay(false)
150               ->build();
151$session = $cluster->connect();
152```
153
154### Enabling TCP keepalive
155
156By default, TCP keepalive is disabled. It can be useful to make sure TCP connections are not silently dropped by a firewall or some other intermediary network device. You can enable it using [`Cassandra\Cluster\Builder::withTCPKeepalive()`](/api/Cassandra/Cluster/class.Builder/#method.withTCPKeepalive).
157
158```php
159<?php
160
161// enable keepalive with a 10 second interval.
162
163$cluster = Cassandra::cluster()
164               ->withTCPKeepalive(10)
165               ->build();
166$session = $cluster->connect();
167```
168
169### Authenticating via `PasswordAuthenticator`
170
171The PHP Driver supports Apache Cassandra's built-in password authentication mechanism. To enable it, use [`Cassandra\Cluster\Builder::withCredentials()`](/api/Cassandra/Cluster/class.Builder/#method.withCredentials).
172
173```php
174<?php
175
176$cluster = Cassandra::cluster()
177               ->withCredentials("username", "password")
178               ->build();
179$session = $cluster->connect();
180```
181
182### Enabling SSL encryption
183
184The PHP Driver supports SSL encryption of network connections. You must configure [`Cassandra\SSLOptions`](/api/Cassandra/class.SSLOptions/) using the [`Cassandra\SSLOptions\Builder`](/api/Cassandra/SSLOptions/class.Builder/).
185
186```php
187<?php
188
189$ssl     = Cassandra::ssl()
190               ->withTrustedCerts('node1.pem', 'node2.pem')
191               ->withVerifyFlags(Cassandra::VERIFY_PEER_CERT | Cassandra::VERIFY_PEER_IDENTITY)
192               ->withClientCert('client.pem')
193               ->withPrivateKey('id_rsa', 'passphrase')
194               ->build()
195$cluster = Cassandra::cluster()
196               ->withSSL($ssl)
197               ->build();
198$session = $cluster->connect();
199```
200
201### Executing queries
202
203You run CQL statements by passing them to [`Cassandra\Session::execute()`](/api/Cassandra/interface.Session/).
204
205```php
206<?php
207
208$result = $session->execute('SELECT keyspace_name, columnfamily_name FROM system.schema_columnfamilies');
209
210foreach ($result as $row) {
211    printf("The keyspace \"%s\" has a table \"%s\".\n", $row['keyspace_name'], $row['columnfamily_name']);
212}
213```
214
215### Parameterized queries
216
217**If you're using Cassandra 2.0 or later** you no longer have to build CQL strings when you want to insert a value in a query, there's a new feature that lets you bind values with regular statements:
218
219```php
220<?php
221
222$session->execute(
223    "UPDATE users SET age = ? WHERE user_name = ?",
224    array('arguments' => array(41, 'Sam'))
225);
226```
227
228For frequently executed queries, it's strongly recommended to use prepared statements. As a rule of thumb, if your application is sending a request more than once, a prepared statement is almost always the right choice.
229
230### Prepared statements
231
232The driver supports prepared statements. Use [`Cassandra\Session::prepare()`](/api/Cassandra/interface.Session/#method.prepare) to create a [`Cassandra\PreparedStatement`](/api/Cassandra/class.PreparedStatement/) object, and then call [`Cassandra\Session::execute()`](/api/Cassandra/interface.Session/#method.execute).
233
234```php
235<?php
236
237$statement = $session->prepare('INSERT INTO users (username, email) VALUES (?, ?)');
238
239$session->execute($statement, array(
240    'arguments' => array('avalanche123', 'bulat.shakirzyanov@datastax.com')
241));
242```
243
244A prepared statement can be run many times, but the CQL parsing will only be done once on each node. Use prepared statements for queries you run over and over again.
245
246### Executing statements in parallel
247
248With fully asynchronous API, it is very easy to run queries in parallel:
249
250```php
251<?php
252
253$data = array(
254    array(41, 'Sam'),
255    array(35, 'Bob')
256);
257
258$statement = $session->prepare("UPDATE users SET age = ? WHERE user_name = ?");
259$futures   = array();
260
261// execute all statements in background
262foreach ($data as $arguments) {
263    $futures[] = $session->executeAsync($statement, array(
264                     'arguments' => $arguments
265                ));
266}
267
268// wait for all statements to complete
269foreach ($futures as $future) {
270    // we will not wait for each result for more than 5 seconds
271    $future->get(5);
272}
273```
274
275Note that it is not enough to simply create a [`Cassandra\Future`](/api/Cassandra/interface.Future/) by calling one of the `*Async()` methods, you must ensure that this future has enough time to be executed by calling [`Cassandra\Future::get()`](/api/Cassandra/interface.Future/#method.get).
276
277### Creating keyspaces and tables
278
279There is no special facility for creating keyspaces and tables, they are created by executing CQL:
280
281```php
282<?php
283
284$createKeyspace = <<<EOD
285CREATE KEYSPACE measurements
286WITH replication = {
287  'class': 'SimpleStrategy',
288  'replication_factor': 1
289}
290EOD;
291
292$createTable = <<<EOD
293CREATE TABLE events (
294  id INT,
295  date DATE,
296  comment VARCHAR,
297  PRIMARY KEY (id)
298)
299EOD;
300
301$session->execute($createKeyspace);
302$session->execute('USE measurements');
303$session->execute($createTable);
304```
305
306You can also `ALTER` keyspaces and tables, and you can read more about that in the [CQL3 syntax documentation](https://github.com/apache/cassandra/blob/cassandra-2.0/doc/cql3/CQL.textile).
307
308### Batch statements
309
310**If you're using Cassandra 2.0 or later** you can build batch requests, either from simple or prepared statements. Batches must not contain any select statements, only `INSERT`, `UPDATE` and `DELETE` statements are allowed.
311
312You can mix any combination of statements in a batch:
313
314```php
315<?php
316
317$batch = new Cassandra\BatchStatement();
318
319$statement = $session->prepare("UPDATE users SET name = ? WHERE user_id = ?");
320$batch->add($statement, array('Sue', 'unicorn31'));
321
322$batch->add("UPDATE users SET age = 19 WHERE user_id = 'unicorn31'");
323
324$batch->add(
325    "INSERT INTO activity (user_id, what, when) VALUES (?, 'login', NOW())",
326    array('unicorn31')
327);
328
329$session->execute($batch);
330```
331
332Batches can have one of three different types: `logged`, `unlogged` or `counter`, where `logged` is the default. Their exact semantics are defined in the [Cassandra documentation](http://docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html), but this is how you specify which one you want:
333
334```php
335<?php
336
337$batch = new Cassandra\BatchStatement(Cassandra::BATCH_LOGGED);
338$batch = new Cassandra\BatchStatement(Cassandra::BATCH_UNLOGGED);
339$batch = new Cassandra\BatchStatement(Cassandra::BATCH_COUNTER);
340```
341
342[Read more about `Cassandra\BatchStatement`](/api/Cassandra/class.BatchStatement/)
343
344Cassandra 1.2 also supported batching, but only as a CQL feature, you had to build the batch as a string, and it didn't really play well with prepared statements.
345
346### Result paging
347
348**If you're using Cassandra 2.0** or later you can page your query results.
349
350By default, a page size of 5000 will be used, you can override the default page size via [`Cassandra\Cluster\Builder::withDefaultPageSize()`](/api/Cassandra/Cluster/class.Builder/#method.withDefaultPageSize).
351
352```php
353<?php
354
355$cluster = Cassandra::cluster()
356               ->withDefaultPageSize(200)
357               ->build();
358$session = $cluster->connect();
359```
360
361You can also override the page size on a per-execute basis by adding the `page_size` execution option to a call to
362[`Cassandra\Session.executeAsync`](/api/Cassandra/interface.Session/#method-executeAsync) or [`Cassandra\Session.execute`](/api/Cassandra/interface.Session/#method-execute):
363
364```php
365<?php
366
367$statement = "SELECT * FROM large_table WHERE id = 'partition_with_lots_of_data'";
368$result    = $session->execute($statement, array('page_size' => 100));
369
370while ($result) {
371    foreach ($result as $row) {
372        var_dump($row);
373    }
374    $result = $result->nextPage();
375}
376```
377
378[Read more about `Cassandra\Rows::nextPage()`](/api/Cassandra/class.Rows/#method.nextPage)
379
380### Consistency
381
382You can specify the default consistency to use for statements execution when you create a new `Cassandra\Cluster`:
383
384```php
385<?php
386
387$cluster = Cassandra::cluster()
388               ->withDefaultConsistency(Cassandra::CONSISTENCY_LOCAL_QUORUM)
389               ->build();
390$session = $cluster->connect();
391```
392
393[Read more `Cassandra\Cluster\Builder::withDefaultConsistency()`](/api/Cassandra/Cluster/class.Builder/#method.withDefaultConsistency)
394
395Consistency can also be passed via execution options.
396
397```php
398<?php
399
400$session->execute(
401    'SELECT * FROM users',
402    array('consistency' => Cassandra::CONSISTENCY_LOCAL_QUORUM)
403);
404
405$statement = $session->prepare('SELECT * FROM users');
406$session->execute($statement, array(
407    'consistency' => Cassandra::CONSISTENCY_LOCAL_QUORUM
408));
409
410$batch = new Cassandra\BatchStatement();
411$batch->add("UPDATE users SET email = 'sue@foobar.com' WHERE id = 'sue'");
412$batch->add("UPDATE users SET email = 'tom@foobar.com' WHERE id = 'tom'");
413$session->execute($batch, array(
414    'consistency' => Cassandra::CONSISTENCY_LOCAL_QUORUM
415));
416```
417
418[Read more about `Cassandra\ExecutionOptions`](/api/Cassandra/class.ExecutionOptions/)
419
420[Read more about `Cassandra\Session::execute()`](/api/Cassandra/interface.Session/#method.execute)
421
422The default consistency level unless you've set it yourself is `Cassandra::CONSISTENCY_LOCAL_ONE`.
423
424Consistency is ignored for `USE`, `TRUNCATE`, `CREATE` and `ALTER` statements, and some (like `Cassandra::CONSISTENCY_ANY`) aren't allowed in all situations.
425
426### Schema Metadata
427
428The DataStax PHP driver exposes schema metadata via [`Cassandra\Schema`](/api/Cassandra/interface.Schema/) object, available using [`Cassandra\Session::schema()`](/api/Cassandra/interface.Session/#method.schema).
429Schema metadata includes information about keyspace, tables and columns and it automatically kept up-to-date with the Cassandra cluster.
430
431```php
432<?php
433
434$schema = $session->schema();
435
436foreach ($schema->keyspaces() as $keyspace) {
437    printf("Keyspace: %s\n", $keyspace->name());
438    printf("    Replication Strategy: %s\n", $keyspace->replicationClassName());
439    printf("    Replication Options:\n");
440    $options = $keyspace->replicationOptions();
441    $keys    = $options->keys();
442    $values  = $options->values();
443    foreach (array_combine($keys, $values) as $key => $value) {
444        printf("        %s: %s\n", $key, $value);
445    }
446    printf("    Durable Writes:       %s\n", $keyspace->hasDurableWrites() ? 'true' : 'false');
447
448    foreach ($keyspace->tables() as $table) {
449        printf("    Table: %s\n", $table->name());
450        printf("        Comment:                    %s\n", $table->comment());
451        printf("        Read Repair Chance:         %f\n", $table->readRepairChance());
452        printf("        Local Read Repair Chance:   %f\n", $table->localReadRepairChance());
453        printf("        GC Grace Seconds:           %d\n", $table->gcGraceSeconds());
454        printf("        Caching:                    %s\n", $table->caching());
455        printf("        Bloom Filter FP Chance:     %f\n", $table->bloomFilterFPChance());
456        printf("        Memtable Flush Period Ms:   %d\n", $table->memtableFlushPeriodMs());
457        printf("        Default Time To Live:       %d\n", $table->defaultTTL());
458        printf("        Speculative Retry:          %s\n", $table->speculativeRetry());
459        printf("        Index Interval:             %d\n", $table->indexInterval());
460        printf("        Compaction Strategy:        %s\n", $table->compactionStrategyClassName());
461        printf("        Populate IO Cache On Flush: %s\n", $table->populateIOCacheOnFlush() ? 'yes' : 'no');
462        printf("        Replicate On Write:         %s\n", $table->replicateOnWrite() ? 'yes' : 'no');
463        printf("        Max Index Interval:         %d\n", $table->maxIndexInterval());
464        printf("        Min Index Interval:         %d\n", $table->minIndexInterval());
465
466        foreach ($table->columns() as $column) {
467            printf("        Column: %s\n", $column->name());
468            printf("            Type:          %s\n", $column->type());
469            printf("            Order:         %s\n", $column->isReversed() ? 'desc' : 'asc');
470            printf("            Frozen:        %s\n", $column->isFrozen() ? 'yes' : 'no');
471            printf("            Static:        %s\n", $column->isStatic() ? 'yes' : 'no');
472
473            if ($column->indexName()) {
474                printf("            Index:         %s\n", $column->indexName());
475                printf("            Index Options: %s\n", $column->indexOptions());
476            }
477        }
478    }
479}
480```
481
482**NOTE** A new instance of [`Cassandra\Schema`](/api/Cassandra/interface.Schema/) is returned each time [`Cassandra\Session::schema()`](/api/Cassandra/interface.Session/#method.schema) is called. This instance is a simple value object and its information, such as keyspaces, tables and columns will not be kept up-to-date with the state of the cluster. In order to obtain the latest schema metadata, you have to call [`Cassandra\Session::schema()`](/api/Cassandra/interface.Session/#method.schema) again.
483
484### Data Types
485
486The PHP driver for Apache Cassandra supports [a variety of datatypes](/features/datatypes/).
487
488You can also use the rich type metadata API to define and inspect types, as well as validate data objects.
489
490The example below defines and creates a [`Cassandra\Map`](/api/Cassandra/class.Map/) using [`Cassandra\Type`](/api/Cassandra/class.Type/) interface.
491
492```php
493<?php
494
495$map = Cassandra\Type::map(Cassandra\Type::varchar(), Cassandra\Type::int())
496           ->create('a', 1, 'b', 2, 'c', 3, 'd', 4);
497
498var_dump(array_combine($map->keys(), $map->values()));
499```
500
501**NOTE** The `create()` method or various types validates and coerces provided values into the target type.
502
503### Logging
504
505You can configure the location of the log file for the driver as well as the log level using the following `php.ini` settings:
506
507```ini
508[cassandra]
509cassandra.log=syslog
510cassandra.log_level=INFO
511```
512
513You can specify any file path as `cassandra.log`.
514
515The special value `syslog` can be used to for the driver to use syslog for logging. Syslog is only supported on \*nix systems.
516
517The possible log levels are:
518
519* CRITICAL
520* ERROR
521* WARN
522* INFO
523* DEBUG
524* TRACE
525
526Most of the logging will be when the driver connects and discovers new nodes, when connections fail and so on. The logging is designed to not cause much overhead and only relatively rare events are logged (e.g. normal requests are not logged).
527
528## Architecture
529
530The PHP Driver follows the architecture of [the C/C++ Driver](http://datastax.github.io/cpp-driver/topics/#architecture) that it wraps.
531
532### Persistent sessions
533
534By default, the driver uses persistent sessions to prevent each request from creating completely new TCP connections to a Cassandra cluster. You can toggle this functionality using [`Cassandra\Cluster\Builder::withPersistentSessions`](/api/Cassandra/Cluster/class.Builder/#method.withPersistentSessions)
535