diff --git a/src/Protocol/Response/DataStream.php b/src/Protocol/Response/DataStream.php index a84e67c..fc54b72 100644 --- a/src/Protocol/Response/DataStream.php +++ b/src/Protocol/Response/DataStream.php @@ -67,11 +67,79 @@ public function readShort() { public function readInt($isCollectionElement = false) { if ($isCollectionElement) { $length = $this->readShort(); - return unpack('N', $this->read($length))[1]; + $toReturn = unpack('l', strrev($this->read($length)))[1]; + if($toReturn == -1) + $toReturn = 0; + return $toReturn; } - return unpack('N', $this->read(4))[1]; + $toReturn = unpack('l', strrev($this->read(4)))[1]; + if($toReturn == -1) + $toReturn = 0; + return $toReturn; } + /** + * Read unsigned big int; + * + * @return int; + */ + function readBigInt() { + $data = $this->data; + $arr = unpack('N2', $data); + + if (PHP_INT_SIZE == 4) { + $hi = $arr[1]; + $lo = $arr[2]; + $isNeg = $hi < 0; + + // Check for a negative + if ($isNeg) { + $hi = ~$hi & (int)0xffffffff; + $lo = ~$lo & (int)0xffffffff; + + if ($lo == (int)0xffffffff) { + $hi++; + $lo = 0; + } else { + $lo++; + } + } + + // Force 32bit words in excess of 2G to pe positive - we deal wigh sign + // explicitly below + if ($hi & (int)0x80000000) { + $hi &= (int)0x7fffffff; + $hi += 0x80000000; + } + + if ($lo & (int)0x80000000) { + $lo &= (int)0x7fffffff; + $lo += 0x80000000; + } + + $value = $hi * 4294967296 + $lo; + + if ($isNeg) { + $value = 0 - $value; + } + } else { + if ($arr[2] & 0x80000000) { + $arr[2] = $arr[2] & 0xffffffff; + } + + if ($arr[1] & 0x80000000) { + $arr[1] = $arr[1] & 0xffffffff; + $arr[1] = $arr[1] ^ 0xffffffff; + $arr[2] = $arr[2] ^ 0xffffffff; + $value = 0 - $arr[1]*4294967296 - $arr[2] - 1; + } else { + $value = $arr[1]*4294967296 + $arr[2]; + } + } + + return $value; + } + /** * Read string. * @@ -236,6 +304,7 @@ public function readByType(array $type, $isCollectionElement = false) { case DataTypeEnum::TEXT: return $isCollectionElement ? $this->readString() : $this->data; case DataTypeEnum::BIGINT: + return $this->readBigInt(); case DataTypeEnum::COUNTER: case DataTypeEnum::VARINT: return $this->readVarint(); @@ -270,4 +339,47 @@ public function readByType(array $type, $isCollectionElement = false) { trigger_error('Unknown type ' . var_export($type, true)); return null; } + + public function getTypeEmptyValue(array $type) { + switch ($type['type']) { + case DataTypeEnum::ASCII: + case DataTypeEnum::VARCHAR: + case DataTypeEnum::TEXT: + return null; + case DataTypeEnum::BIGINT: + return 0; + case DataTypeEnum::COUNTER: + case DataTypeEnum::VARINT: + return 0; + case DataTypeEnum::CUSTOM: + case DataTypeEnum::BLOB: + return null; + case DataTypeEnum::BOOLEAN: + return false; + case DataTypeEnum::DECIMAL: + return 0; + case DataTypeEnum::DOUBLE: + return 0; + case DataTypeEnum::FLOAT: + return 0; + case DataTypeEnum::INT: + return 0; + case DataTypeEnum::TIMESTAMP: + return 0; + case DataTypeEnum::UUID: + return null; + case DataTypeEnum::TIMEUUID: + return null; + case DataTypeEnum::INET: + return null; + case DataTypeEnum::COLLECTION_LIST: + case DataTypeEnum::COLLECTION_SET: + return null; + case DataTypeEnum::COLLECTION_MAP: + return null; + } + + trigger_error('Unknown type ' . var_export($type, true)); + return null; + } } \ No newline at end of file diff --git a/src/Protocol/Response/Rows.php b/src/Protocol/Response/Rows.php index 359cf0e..1878689 100644 --- a/src/Protocol/Response/Rows.php +++ b/src/Protocol/Response/Rows.php @@ -38,7 +38,7 @@ public function __construct(DataStream $stream, array $metadata) { try { $row[$this->columns[$j]['name']] = $stream->readBytes(); } catch (\Exception $e) { - $row[$this->columns[$j]['name']] = null; + $row[$this->columns[$j]['name']] = $stream->getTypeEmptyValue($this->columns[$j]['type']); } } $this->rows[] = $row; @@ -63,7 +63,7 @@ public function current() { $row[$this->columns[$i]['name']] = $data->readByType($this->columns[$i]['type']); } catch (\Exception $e) { trigger_error($e->getMessage()); - $row[$this->columns[$i]['name']] = null; + $row[$this->columns[$i]['name']] = $data->getTypeEmptyValue($this->columns[$i]['type']); } } return $row;