evseevnn-zz / php-cassandra-binary

PHP library for Cassandra database via a binary protocol.
http://evseevnn.github.io/php-cassandra-binary/
MIT License
69 stars 33 forks source link

Reading MAP<timestamp, string> data alignment issues #17

Open nicolapetracchi opened 10 years ago

nicolapetracchi commented 10 years ago

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
LarsFronius commented 10 years ago

Hey @nicolapetracchi - can you reevaluate your issue? Pretty sure it is resolved by now.