evseevnn-zz / php-cassandra-binary Goto Github PK
View Code? Open in Web Editor NEWPHP library for Cassandra database via a binary protocol.
Home Page: http://evseevnn.github.io/php-cassandra-binary/
License: MIT License
PHP library for Cassandra database via a binary protocol.
Home Page: http://evseevnn.github.io/php-cassandra-binary/
License: MIT License
Hi,
What is the equivalent of Java multi-threading or executeAsync() when using php-cassandra-binary or developing for Cassandra in PHP in general?
How do I achieve non-blocking, concurrent read/writes to boost throughput?
Thanks,
Edwin
A note: I'm using a backported version of this code release v0.1.0 to PHP 5.3 (made by me), I'm using this with Cassandra 2.0.9, so I don't know if this is very related to my architecture.
Seems like that contrary to the statement in CQL BINARY PROTOCOL v1: Each entry is composed of two short bytes representing the key and the value of the entry map, where short bytes is a [short] n, followed by n bytes if n >= 0; the timestamp supporting function readTimestamp in this case not call readShort and thus it causes a bad data cursor alignment that breaks the subsequent operations and can't build a correct map as associative array.
diff --git a/Cassandra/Protocol/Response/DataStream.php b/Cassandra/Protocol/Response/DataStream.php
index d5d34dd..9510541 100644
--- a/Cassandra/Protocol/Response/DataStream.php
+++ b/Cassandra/Protocol/Response/DataStream.php
@@ -130,8 +130,16 @@ class DataStream {
*
* @return int
*/
- public function readTimestamp() {
- return round($this->readInt() * 4294967.296 + ($this->readInt() / 1000));
+ public function readTimestamp($isShort) {
+ if($isShort) {
+ $short = $this->readShort();
+ }
+ else {
+ $short = 8;
+ }
+
+ $tmp = round(($this->readInt() * pow(2, 32) + ($this->readInt())) / 1000);
+ return $tmp;
}
/**
@@ -160,7 +168,7 @@ class DataStream {
$map = array();
$count = $this->readShort();
for ($i = 0; $i < $count; ++$i) {
- $map[$this->readByType($keyType)] = $this->readByType($valueType);
+ $map[$this->readByType($keyType, true)] = $this->readByType($valueType, true);
}
return $map;
}
@@ -229,11 +237,14 @@ class DataStream {
* @param array $type
* @return mixed
*/
- public function readByType(array $type) {
+ public function readByType(array $type, $isShort = false) {
switch ($type['type']) {
case DataTypeEnum::ASCII:
case DataTypeEnum::VARCHAR:
case DataTypeEnum::TEXT:
+ if($isShort) {
+ return $this->readString();
+ }
return $this->data;
case DataTypeEnum::BIGINT:
case DataTypeEnum::COUNTER:
@@ -253,7 +264,7 @@ class DataStream {
case DataTypeEnum::INT:
return $this->readInt();
case DataTypeEnum::TIMESTAMP:
- return $this->readTimestamp();
+ return $this->readTimestamp($isShort);
case DataTypeEnum::UUID:
return $this->readUuid();
case DataTypeEnum::TIMEUUID:
@@ -270,4 +281,5 @@ class DataStream {
trigger_error('Unknown type ' . var_export($type, true));
return null;
}
+
}
\ No newline at end of file
Hi I am trying to create a key space from php code if it does not exist.
When I do the following
$temp_connection = new \evseevnn\Cassandra\Database($this->getNodes()); $temp_connection->query("CREATE KEYSPACE " . $keyspace . " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };");
I get lots and lots of the following error
Warning: socket_read() expects parameter 1 to be resource, null given in vendor/evseevnn/php-cassandra-binary/src/Connection.php on line 75
The first line (the connection) works fine no issues it appears to be when I call "->query()"
Is this something I am doing wrong?
Wenn I try to read a field of type Map<text,text> I get the error Reading while at end of stream by reading. This happens at line 65 in class Protocol/Response/Rows.php because something with the length is wrong.
May you can help me with it.
Thx
Pascal
Hi, I hope you're ok with questions through github issues.
How is the performance of this library compared to the alternatives? I notice that this is native php, without any C-bindings, somewhat worried that this convencience comes at the cost of poor performance.
I really like the design of the library though, the support for composer, etc.
Thanks!
new Cassandra\Database([
'192.168.0.2:8882' => [
'username' => 'admin',
'password' => 'pass',
], 'my_keyspace');
The use of array_shuffle
in Cluster::getRandomNode()
squashes the '192.168.0.2:8882' array key.
Here is my code. I think there is a encoding/decoding or response parse problem.
require_once 'vendor/autoload.php';
$nodes = array(
'127.0.0.1:9042' => array(
'username' => 'cassandra',
'password' => 'cassandra'
)
);
try {
$database = new evseevnn\Cassandra\Database($nodes, 'test');
$database->connect();
$users = $database->query('SELECT * FROM user');
var_dump($users);
} catch (evseevnn\Cassandra\Exception\CassandraException $e) {
echo $e->getMessage() . PHP_EOL;
}
And exception message is:
Unavailable exception. Error data: array (
'consistency' => 2573153,
'node' => 1852731252,
'replica' => 543253352,
)
CQL shell output:
cqlsh:test> SELECT * FROM user;
id | activated | name | password | regdate | status | username
--------------------------------------+-----------+--------------+----------+--------------------------+--------+----------
ef8949f0-09da-11e4-8132-e76149b7842c | False | Tarık Yılmaz | pass1234 | 2014-01-01 13:45:12+0200 | False | tarik
(1 rows)
and finally stack trace
#0 /home/tarik/Desktop/cass/index.php(15): evseevnn\Cassandra\Database->query('SELECT * FROM u...')
#1 {main}
I have this table:
CREATE TABLE user (
user_username text,
user_created timestamp,
user_mail text,
user_pass_hash text,
user_pass_salt text,
user_updated timestamp,
PRIMARY KEY ((user_username))
);
I used this query, but the data are stored incorrectly.
INSERT INTO user (user_username,user_created,user_mail,user_pass_hash,user_pass_salt,user_updated)
VALUES (:user_username,:user_created,:user_mail,:user_pass_hash,:user_pass_salt,:user_updated);
Array
(
[user_username] => foo
[user_created] => 0
[user_mail] => [email protected]
[user_pass_hash] => abcd
[user_pass_salt] => abcd
[user_updated] => 1405586785
)
For now timeout defined hardcoded. Please add option timeout for constructor
When I'm using this library at Laravel framework I'm getting:
Node list is empty, possibly because nodes are unreachable.
But outside of laravel It's working great, Do you know what can cause it?
Thanks!
This is my code
namespace evseevnn;
include_once(DIR.DIRECTORY_SEPARATOR."vendor".DIRECTORY_SEPARATOR."autoload.php");
$nodes = [
'127.0.0.1',
'127.0.0.1:9042' => [
'username' => '',
'password' => ''
]
];
// Connect to database.
$database = new Cassandra\Database($nodes, 'keyspace1');
$database->connect();
// Run query.
$users = $database->query('SELECT * FROM "test"');
var_dump($users);
Hi,
I keep getting a connection timeout problem coming from evseevnn\Cassandra\Cluster\Node::getConnection
I'm aware it could be due to server issues. But we only get it at peak times. I wonder if anybody can give us any hints ? or should we upgrade to latest release ?
Also we aim to open/close connections only when necessary.
When write timeout occurrs, Cassandra sends the error message "timed out...". Your code reads the first two bytes, interpreting them as number. Then it tries to get the error message of length 29801, throwing an exception.
This probably applies to some other error messages as well - not all of them return the length bytes.
Hey,
I'm playing around with your driver double checking if it fits our needs and just found out that when doing batches with preparedstatements and with more than 95 statements PHP crashes with "PHP Fatal error: Maximum function nesting level", this is coming from the recursive call to appendQueryToStack. This is working fine with normal statements though.
Is there any way you can remove that recursion? I don't really like the idea of tune php configuration to support as many recursive calls as my biggest batch.
Thanks
I am trying your php client.
My code:
$nodes = ['127.0.0.1:9042'];
$database = new \evseevnn\Cassandra\Database($nodes, 'people');
$database->connect();
I get this exception error:
evseevnn\Cassandra\Exception\ConnectionException: Protocol error: Invalid or unsupported protocol version (1); the lowest supported version is 3 and the greatest is 4
Where do I set protocol version?
Thank you.
R.
Before I do any work on a pull request, would you be open to the idea of me adding PHPUnit as a dev dependency in composer.json and contributing unit tests back to the project?
Hi
CREATE TABLE users_log (
session_token ascii,
user_id int,
site_id int,
role_id int,
user_name varchar,
date_start timestamp,
date_stop timestamp,
ip varchar,
agent text,
tags list<text>,
PRIMARY KEY (session_token)
);
SELECT * FROM "users_log" WHERE "site_id" = 3 ALLOW FILTERING ;
in cqlsh - OK
by php-cassandra-binary - "Reading while at end of stream"
file "/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/Rows.php"
line 65
trace:
#0 vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php(59): evseevnn\Cassandra\Protocol\Response\DataStream->read(2)
#1 vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php(142): evseevnn\Cassandra\Protocol\Response\DataStream->readShort()
#2 vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php(261): evseevnn\Cassandra\Protocol\Response\DataStream->readList(Array)
#3 vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/Rows.php(63): evseevnn\Cassandra\Protocol\Response\DataStream->readByType(Array)
#4 vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/Rows.php(132): evseevnn\Cassandra\Protocol\Response\Rows->current()
#5 vendor/evseevnn/php-cassandra-binary/src/Database.php(182): evseevnn\Cassandra\Protocol\Response\Rows->asArray()
#6 src/Base/Cassandra/Collection.php(98): evseevnn\Cassandra\Database->query('SELECT * FROM "...', Array)
Thanks
hi,
I'm trying this lib with cassandra 2.1.1 Maybe there is a cql protocol change, because I can't get a simple query that returns multiple rows to return the correct data. Maybe the NULL value is a problem?
in cqlsh:
cqlsh:testkeyspace> insert into animals(name,species,genus,family) values('pippi','dog', 'male','tiger');
cqlsh:testkeyspace> insert into animals(name,species,genus,family) values('pippi2','dog', 'male','tiger');
cqlsh:testkeyspace> select * from animals;
name | family | genus | species | subspieces
--------+--------+-------+---------+------------
pippi | tiger | male | dog | null
pippi2 | tiger | male | dog | null
In php:
$database = new evseevnn\Cassandra\Database($nodes, 'testkeyspace');
$database->connect();
$user2 = $database->query('SELECT * FROM animals ');
var_dump($user2);
result:
array(2) {
[0]=>
array(5) {
["name"]=>
string(5) "pippi"
["family"]=>
string(5) "tiger"
["genus"]=>
string(4) "male"
["species"]=>
string(3) "dog"
["subspieces"]=>
string(37) "�pippi2�tiger�male�dog���"
}
[1]=>
array(5) {
["name"]=>
NULL
["family"]=>
NULL
["genus"]=>
NULL
["species"]=>
NULL
["subspieces"]=>
NULL
}
}
API does not work for me, I try to make connection but is carrying up to timeout error, debugging api, I realized that the fetchData method of the Connection class, this code
while (strlen ($ data) <$ length) {
$ Data = socket_read ($ this-> connection, $ length).;
}
socket_read returns empty, then the infinite loop.
I'm trying to make the connection in ec2 my localhost;
In a bigint column, add an negative value (I had: -2066057944), then read it. The value returned will be -1.
The problem is that in "Cassandra\Protocol\Response\DataStream.php" in readByType method, bigints are read as varints.
can't connect to cassandra if I use host as a key and username, password as a value
$nodes = [
'192.168.0.2:8882' => [ 'username' => 'admin', 'password' => 'pass']
];
The bug in Cassandra/Cluster.php in method getRandomNode
after shuffle($this->nodes); the host become zero
I noticed that LOCAL_ONE consistency level does not work due to an error in ConsistencyEnum.php.
The correct value for it is:
const CONSISTENCY_LOCAL_ONE = 0xA;
the current value is 0x0010, and this leads to this cassandra error message: "Protocol error: Unknown code 16 for a consistency level"
Please, fix this. Thank you!
The following query:
$cassandraDatabase->query('UPDATE users SET field_to_delete = :empty_value;', array('empty_value' => NULL));
causes the following error:
BigInt value 0 not an int in /home/pako_www/live/vendor/evseevnn/php-cassandra-binary/src/Protocol/BinaryData.php on line 145
I have table:
CREATE TABLE test (
activity_id varint,
updated_at timestamp,
PRIMARY KEY (activity_id)
);
I used this code for insert
$database->query(
'INSERT INTO "test" ("activity_id", "updated_at") VALUES (:activity_id, :updated_at);',
[
'activity_id' => 14150269410000000000003002,
'updated_at' => time(),
],
\evseevnn\Cassandra\Enum\ConsistencyEnum::CONSISTENCY_ONE
);
But the exception is thrown.
The problem is in evseevnn\Cassandra\Protocol\BinaryData in method getBigInt()
If i used code
$database->query('INSERT INTO "example" ("activity_id", "updated_at") VALUES (14150269410000000000003002, time());',
array(),
\evseevnn\Cassandra\Enum\ConsistencyEnum::CONSISTENCY_ONE
);
everything works.
Can you fix it?
Created a column family in cassandra cqlsh:
create table test(id uuid primary key, data map <text, text>);
Insert works fine from php as an array bind parameter
Trying to select data and result are really strange, looks like it came straight from socket
testtest: testtest
{'test': 'test'} epected array or anything ?
Any thoughts ?
Thanks
When using new \Cassandra\Database(["10.10.0.1"], 'keyspace') the connection fails, because it tries to connect to "0" (the array key).
The error is in Cluster.php on line 41:
Should be $node = new Node($node); instead of $node = new Node($nodeKey);
Fatal error: Uncaught exception 'evseevnn\Cassandra\Exception\ConnectionException' with message 'Protocol error: Invalid or unsupported protocol version (1); the lowest supported version is 3 and the greatest is 4' in C:\wamp\www\vendor\evseevnn\php-cassandra-binary\src\Database.php:75
I'm starting try use this lib, but it have that error at index.php file
My php is 5.5
My code here:
$nodes = [
127.0.0.1'
];
try {
// Connect to database.
$database = new \evseevnn\Cassandra\Database($nodes, 'demodb');
$database->connect();
Please tell me how to fix!
Thanks
Hi,
I try to use the php cassandra binary, but i've some problems... I'm new on symfony and when i write :
$nodes = ['127.0.0.1'];
$database = new evseevnn\Cassandra\Database($nodes, 'keyspace');
I've this error:
Attempted to load class "Database" from namespace "Projet\HomepageBundle\Controller\evseevnn\Cassandra".
Did you forget a "use" statement for "evseevnn\Cassandra\Database"
If anyone have a idea?
Thanks!
PHP Fatal error: Uncaught exception 'Exception' with message 'Reading while at end of stream' in my-project/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php:40
Stack trace:
#0 my-project/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php(154): evseevnn\Cassandra\Protocol\Response\DataStream->read(29801)
#1 my-project/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response.php(131): evseevnn\Cassandra\Protocol\Response\DataStream->readString()
#2 my-project/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response.php(164): evseevnn\Cassandra\Protocol\Response->evseevnn\Cassandra\Protocol{closure}(Object(evseevnn\Cassandra\Protocol\Response\DataStream))
#3 my-project/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response.php(50): evseevnn\Cassandra\Protocol\Response->getErrorData()
#4 my-project/vendor/evseevnn/php-cassandra-binary/src/Database.php(199): evseevnn\Cassandra\Pro in my-project/vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php on line 40
It happens when I'm trying to insert for example 200 batches of 1200 entries each.
My environment:
Do you have any idea if this is a bug, or how can I fix it?
Thanks a lot!
I'm attempting to insert a value into a column with datatype decimal and am trouble getting the correct outcome...
cqlsh:test_keyspace> DESCRIBE TABLE test_decimal ;
CREATE TABLE test_decimal (
id int,
value decimal,
PRIMARY KEY (id)
) WITH
bloom_filter_fp_chance=0.010000 AND
caching='KEYS_ONLY' AND
comment='' AND
dclocal_read_repair_chance=0.100000 AND
gc_grace_seconds=864000 AND
index_interval=128 AND
read_repair_chance=0.000000 AND
replicate_on_write='true' AND
populate_io_cache_on_flush='false' AND
default_time_to_live=0 AND
speculative_retry='99.0PERCENTILE' AND
memtable_flush_period_in_ms=0 AND
compaction={'class': 'SizeTieredCompactionStrategy'} AND
compression={'sstable_compression': 'LZ4Compressor'};
// Insert using the php-cassandra-binary package
$database->query('INSERT INTO test_decimal (id, value) VALUES (:id, :value);', ['id' => 1, 'value' => 1.23]);
cqlsh:test_keyspace> INSERT INTO test_decimal (id, value) VALUES (2, 1.23);
cqlsh:test_keyspace> SELECT * FROM test_decimal ;
id | value
----+-------
1 | 1
2 | 1.23
(2 rows)
It appears that the decimal part is always lost when inserting via this package.
(I'm using dev-master at revision 7185308)
Am I doing something wrong or is this a genuine bug?
Thanks for an awesome library that is helping me get away from pdo_cassandra and the Thrift protocol!
Regards,
Adam
I've been stepping through the library code all morning trying to determine where the transformation from binary string to array is taking place but haven't been able to isolate it. Suffice it to say that when unpacking a column with data type map<text,text> you do get an array, but it's got one element where the keys and values are composited. I think the screenshot attached explains it best. Any ideas?
https://www.dropbox.com/s/x2clgppr3kwjabe/Screenshot%202014-07-27%2015.16.06.png
Hi!
It has been a while since there was a release created. Could you create a new release?
Thanks!
Koen
Hi,
I've just created an UDT to use into my application but it seems there is something wrong when retrieving the data.
The UDT has a very simple structure:
CREATE TYPE mytype (a int, b text);
I've then run the insert command and I can see (using Datastax DevCenter) that the data in the table looks right, infact in the column I have something like {a: 125, b: '3'}.
When unpacking though I get an array with value string(4) "}"
I've also tried to use my UDT into a map, but I've got a similar result.
I'm using Cassandra 2.1.0
Is there a way to insert new record in the prepared statment with now() function?
Thanks!
Hi Guys,
Using Cassandra 2.1.2 and trying to get UDTs to work in the library, and since everyone is busy figured I would give it a shot. However, having trouble.
Looking at the v3 Binary Protocol (https://git-wip-us.apache.org/repos/asf?p=cassandra.git;a=blob_plain;f=doc/native_protocol_v3.spec;hb=HEAD), I notice a new column type.
0x0030 UDT: the value is < ks >< udt_name >< n >< name_1 >< type_1 >...< name_n >< type_n >
However, in evseevnn\Cassandra\Protocol\Response\DataStream\TypeReader class, public static function readFromStream(DataStream $stream) {...} always reads a UDT type as '0' instead of the expected '48'.
Thus, I can't get the library to differentiate a 'custom' column from a 'UDT' column when generating the column meta-data; and so I can't properly process 'reading' the datastream. Any ideas? Am I on the right track?
Hi,
If I've a collection value how can I insert the data?
Do I need to convert to json or just pass an array?
Nothing works..
CREATE TABLE test(
sample map<\text, text>,
);
Thanks!
It is advantageous, particularly in development environments to allow the Cassandra/Database object have it's default consistency level (currently coded to QUORUM) set to a different level without passing in a parameter on all ->query() method calls.
I propose adding setDefaultWriteConsistency($level) and setDefaultReadConsistency($level) which would be respected by Database::query()
I will create a PR if this meets approval.
Hi I just pulled the latest version of dev-master and I now get this error
Warning: unpack(): Type l: not enough input, need 4, have 0 in vendor/evseevnn/php-cassandra-binary/src/Protocol/Response/DataStream.php on line 77
When I run a pretty simple CQL query
SELECT * FROM basket WHERE global_id = :global_id AND tag = :tag ORDER BY id,hotel_id, room_id
I tried to debug it but got a bit lost in what is going on in there.
Hi,
Is there any function to paginate results?
I've a table for client that belongs to project that belong to user:
CREATE TABLE project_clients(
user_id int,
project_id int,
client_id text,
PRIMARY KEY ((user_id, project_id), client_id)
);
How can I paginate throw the results?
Thanks!
Is there a way to make Conditional updates supported?
When I'm adding IF NOT EXISTS I'm getting:
Invalid: Conditional updates are not supported by the protocol version in use. You need to upgrade to a driver using the native protocol v2.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.