diff --git a/README.md b/README.md index 0255d9d..2c0767a 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,57 @@ A PHP driver for Apache Cassandra. This driver works exclusively with the Cassan ## Building +#### CentOS 6 - Requirements + +Git version >= 1.7.10 + +Check your git version: +``` +git --version +``` + +if git version < 1.7.10 install newer version for example from rpmforge (http://wiki.centos.org/AdditionalResources/Repositories/RPMForge#head-f0c3ecee3dbb407e4eed79a56ec0ae92d1398e01) +``` +wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm +sudo rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt +sudo rpm -K rpmforge-release-0.5.3-1.el6.rf.*.rpm +rpm -i rpmforge-release-0.5.3-1.el6.rf.*.rpm +sudo yum erase git +### Enable RPM extras repo => set enabled=1 +sudo nano /etc/yum.repos.d/rpmforge.repo +sudo yum install git +## Disable RPM extras repo => set enabled=0 +sudo nano /etc/yum.repos.d/rpmforge.repo + +## check new git version +git --version +``` + +Install required packages +``` +yum install cmake gcc-c++ openssl-devel libssh2-devel +``` + +Install boost >= 1.55 +``` +sudo wget http://repo.enetres.net/enetres.repo -O /etc/yum.repos.d/enetres.repo +sudo yum install boost-devel +``` + +Install PHP >= 5.3.10 +``` +wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm +wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm +wget http://rpms.famillecollet.com/RPM-GPG-KEY-remi +sudo rpm --import RPM-GPG-KEY-remi +sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm +## Enable Remi repo => set enabled=1 +sudo nano /etc/yum.repos.d/remi.repo +sudo yum install php-devel +## Disable Remi repo => set enabled=0 +sudo nano /etc/yum.repos.d/remi.repo +``` + The library use official c++ driver by DataStax https://github.com/datastax/cpp-driver Before build php-cassandra you should download and install DataStax C++ Driver for Apache Cassandra. @@ -15,7 +66,7 @@ cmake . && make && make install ``` ``` -git clone https://github.com/aparkhomenko/php-cassandra.git +git clone https://github.com/michaltrmac/php-cassandra.git --branch get_row --single-branch php-cassandra cd php-cassandra phpize && ./configure && make ``` @@ -74,6 +125,8 @@ if (null === $future->getError()) { while ($result->next()) { echo "strategy_options: " . $result->get("strategy_options") . "\n"; + // or you can use $result->get() to get complete row as associative array + // var_dump($result->get()); } } diff --git a/cassandra.cpp b/cassandra.cpp index acbda0c..7e77d96 100644 --- a/cassandra.cpp +++ b/cassandra.cpp @@ -26,11 +26,13 @@ extern "C" { #endif +#define CQL_USE_BOOST_MULTIPRECISION true; + #include "php.h" #include "php_ini.h" +#include "zend_exceptions.h" #include "ext/date/php_date.h" #include "ext/standard/info.h" -#include "php_cassandra.h" #define php_array_init(arg) _array_init((arg), 0 ZEND_FILE_LINE_CC) #ifdef array_init @@ -41,22 +43,7 @@ extern "C" { } #endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -/* If you declare any globals in php_cassandra.h uncomment this: -ZEND_DECLARE_MODULE_GLOBALS(cassandra) -*/ +#include "php_cassandra.hpp" /* True global resources - no need for thread safety here */ static int le_cassandra; @@ -79,40 +66,8 @@ zend_object_handlers cql_query_handlers; zend_object_handlers cql_session_handlers; zend_object_handlers cql_result_handlers; -struct cql_builder_object { - zend_object std; - boost::shared_ptr cql_builder; -}; - -struct cql_cluster_object { - zend_object std; - boost::shared_ptr cql_cluster; -}; - -struct cql_error_object { - zend_object std; - cql::cql_error_t cql_error; -}; - -struct cql_future_result_object { - zend_object std; - boost::shared_future cql_future_result; -}; - -struct cql_query_object { - zend_object std; - boost::shared_ptr cql_query; -}; - -struct cql_session_object { - zend_object std; - boost::shared_ptr cql_session; -}; - -struct cql_result_object { - zend_object std; - boost::shared_ptr cql_result; -}; +/* If you declare any globals in php_cassandra.h uncomment this: */ +ZEND_DECLARE_MODULE_GLOBALS(cassandra) zend_object_value php_cql_builder_object_new(zend_class_entry *type TSRMLS_DC); zend_object_value php_cql_cluster_object_new(zend_class_entry *type TSRMLS_DC); @@ -594,7 +549,15 @@ PHP_METHOD(CqlCluster, __construct) } cql_cluster_object *obj = (cql_cluster_object *) zend_object_store_get_object(getThis() TSRMLS_CC); - obj->cql_cluster = boost::shared_ptr(obj_builder->cql_builder->build()); + try + { + obj->cql_cluster = boost::shared_ptr(obj_builder->cql_builder->build()); + } + catch (cql::cql_no_host_available_exception e) + { + zend_throw_exception(zend_exception_get_default(TSRMLS_C), "CqlCluster: No Host Available", 0 TSRMLS_CC); + RETURN_FALSE; + } } /* }}} */ @@ -603,6 +566,7 @@ PHP_METHOD(CqlCluster, __construct) PHP_METHOD(CqlCluster, connect) { cql_cluster_object *obj = (cql_cluster_object *) zend_object_store_get_object(getThis() TSRMLS_CC); + CASSANDRA_G(g_cluster_object) = obj; if (obj == NULL || obj->cql_cluster == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find obj->cql_cluster in CqlCluster.connect"); @@ -898,6 +862,7 @@ PHP_METHOD(CqlSession, __construct) try { cql_session_object *obj = (cql_session_object *) zend_object_store_get_object(getThis() TSRMLS_CC); + CASSANDRA_G(g_session_object) = obj; obj->cql_session = obj_cql_cluster->cql_cluster->connect(); } @@ -1001,8 +966,9 @@ PHP_METHOD(CqlResult, get) char * column; int column_len; long column_type = cql::CQL_COLUMN_TYPE_UNKNOWN; + long tmp_column_type = column_type; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s|l", &column, &column_len, &column_type) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"|sl", &column, &column_len, &column_type) == FAILURE) { return; } @@ -1017,6 +983,13 @@ PHP_METHOD(CqlResult, get) zval * tmp_zval; char * tmp_key; char * tmp_value_char; + int columns_count = 1; + zval * subarray; + boost::asio::ip::address tmp_value_inet; + cql::cql_decimal_t tmp_value_decimal; + cql::cql_varint_t tmp_value_varint; + double _tmp_value_decimal; + boost::multiprecision::cpp_int _tmp_value_varint; time_t ts = 0; long orig_column_type = 0; @@ -1028,385 +1001,478 @@ PHP_METHOD(CqlResult, get) std::vector< cql::cql_byte_t > data; std::stringstream ss; - cql::cql_column_type_enum type; - obj->cql_result->column_type(column, type); - orig_column_type = static_cast(type); - - if (column_type == cql::CQL_COLUMN_TYPE_UNKNOWN) { - column_type = orig_column_type; + if (ZEND_NUM_ARGS() <= 0) { + columns_count = obj->cql_result->column_count(); } - switch (column_type) { + php_array_init(return_value); + + for (size_t i = 0; i < columns_count; ++i) { + std::string _keyspace, _table, _column; + tmp_value_big_int = NULL; + tmp_value_bool = false; + tmp_value_double = NULL; + tmp_value_float = NULL; + tmp_value_int = NULL; + + if (ZEND_NUM_ARGS() <= 0) { + obj->cql_result->column_name(i, _keyspace, _table, _column); + column = const_cast(_column.c_str()); + } + + cql::cql_column_type_enum type; + obj->cql_result->column_type(column, type); + orig_column_type = static_cast(type); - case cql::CQL_COLUMN_TYPE_BIGINT: + if (column_type == cql::CQL_COLUMN_TYPE_UNKNOWN) { + tmp_column_type = orig_column_type; + } + + switch (tmp_column_type) { + + case cql::CQL_COLUMN_TYPE_BIGINT: + + obj->cql_result->get_bigint(column, tmp_value_big_int); + + if (tmp_column_type != orig_column_type && tmp_value_big_int == 0) { + add_assoc_null(return_value, column); + continue; + } - obj->cql_result->get_bigint(column, tmp_value_big_int); + add_assoc_long(return_value, column, tmp_value_big_int); - if (column_type != orig_column_type && tmp_value_big_int == 0) { - RETURN_NULL(); - return; - } + break; - RETURN_LONG(tmp_value_big_int); + case cql::CQL_COLUMN_TYPE_BOOLEAN: + obj->cql_result->get_bool(column, tmp_value_bool); - break; + if (tmp_column_type != orig_column_type && !tmp_value_bool) { + add_assoc_null(return_value, column); + continue; + } - case cql::CQL_COLUMN_TYPE_BOOLEAN: + add_assoc_bool(return_value, column, tmp_value_bool); - obj->cql_result->get_bool(column, tmp_value_bool); + break; - if (column_type != orig_column_type && !tmp_value_bool) { - RETURN_NULL(); - return; - } + case cql::CQL_COLUMN_TYPE_DOUBLE: + obj->cql_result->get_double(column, tmp_value_double); - RETURN_BOOL(tmp_value_bool); + if (tmp_column_type != orig_column_type && tmp_value_double == 0) { + add_assoc_null(return_value, column); + continue; + } - break; + add_assoc_double(return_value, column, tmp_value_double); - case cql::CQL_COLUMN_TYPE_DOUBLE: + break; - obj->cql_result->get_double(column, tmp_value_double); + case cql::CQL_COLUMN_TYPE_FLOAT: + obj->cql_result->get_float(column, tmp_value_float); - if (column_type != orig_column_type && tmp_value_double == 0) { - RETURN_NULL(); - return; - } + if (tmp_column_type != orig_column_type && tmp_value_float == 0) { + add_assoc_null(return_value, column); + continue; + } - RETURN_DOUBLE(tmp_value_double); + add_assoc_double(return_value, column, tmp_value_float); - break; + break; - case cql::CQL_COLUMN_TYPE_FLOAT: + case cql::CQL_COLUMN_TYPE_INT: - obj->cql_result->get_float(column, tmp_value_float); + obj->cql_result->get_int(column, tmp_value_int); - if (column_type != orig_column_type && tmp_value_float == 0) { - RETURN_NULL(); - return; - } + if (tmp_column_type != orig_column_type && tmp_value_int == 0) { + add_assoc_null(return_value, column); + continue; + } - RETURN_DOUBLE(tmp_value_float); + add_assoc_long(return_value, column, tmp_value_int); - break; + break; - case cql::CQL_COLUMN_TYPE_INT: + case cql::CQL_COLUMN_TYPE_MAP: - obj->cql_result->get_int(column, tmp_value_int); + if (!obj->cql_result->get_map(column, tmp_collection_map) || tmp_collection_map == NULL) { + add_assoc_null(return_value, column); + continue; + } - if (column_type != orig_column_type && tmp_value_int == 0) { - RETURN_NULL(); - return; - } + subarray = NULL; + php_array_init(subarray); + ALLOC_INIT_ZVAL(tmp_zval); + + for (size_t i = 0; i < tmp_collection_map->size(); ++i) { - RETURN_LONG(tmp_value_int); + // detect key type + switch (tmp_collection_map->key_type()) { - break; + case cql::CQL_COLUMN_TYPE_BIGINT: + tmp_collection_map->get_key_bigint(i, tmp_value_big_int); + ZVAL_LONG(tmp_zval, tmp_value_big_int); + break; - case cql::CQL_COLUMN_TYPE_MAP: + case cql::CQL_COLUMN_TYPE_BOOLEAN: + tmp_collection_map->get_key_bool(i, tmp_value_bool); + ZVAL_BOOL(tmp_zval, tmp_value_bool); + break; + + case cql::CQL_COLUMN_TYPE_DOUBLE: + tmp_collection_map->get_key_double(i, tmp_value_double); + ZVAL_DOUBLE(tmp_zval, tmp_value_double); + break; - if (!obj->cql_result->get_map(column, tmp_collection_map) || tmp_collection_map == NULL) { - RETURN_NULL(); - return; - } + case cql::CQL_COLUMN_TYPE_FLOAT: + tmp_collection_map->get_key_float(i, tmp_value_float); + ZVAL_DOUBLE(tmp_zval, tmp_value_float); + break; - php_array_init(return_value); - ALLOC_INIT_ZVAL(tmp_zval); + case cql::CQL_COLUMN_TYPE_INT: + tmp_collection_map->get_key_int(i, tmp_value_int); + ZVAL_LONG(tmp_zval, tmp_value_int); + break; - for (size_t i = 0; i < tmp_collection_map->size(); ++i) { + case cql::CQL_COLUMN_TYPE_TIMESTAMP: + // Driver doesn't have method for getting timestamp [workaround] + tmp_collection_map->get_key_bigint(i, tmp_value_big_int); + ZVAL_LONG(tmp_zval, tmp_value_big_int); + break; - // detect key type - switch (tmp_collection_map->key_type()) { + case cql::CQL_COLUMN_TYPE_TIMEUUID: - case cql::CQL_COLUMN_TYPE_BIGINT: - tmp_collection_map->get_key_bigint(i, tmp_value_big_int); - ZVAL_LONG(tmp_zval, tmp_value_big_int); - break; + // Driver doesn't have method for getting timestamp [workaround] + tmp_collection_map->get_key_bigint(i, tmp_value_big_int); - case cql::CQL_COLUMN_TYPE_BOOLEAN: - tmp_collection_map->get_key_bool(i, tmp_value_bool); - ZVAL_BOOL(tmp_zval, tmp_value_bool); - break; + if (tmp_value_big_int > 1000) { + ts = (time_t) (tmp_value_big_int / 1000); + } + else { + ts = (time_t) 0; + } - case cql::CQL_COLUMN_TYPE_DOUBLE: - tmp_collection_map->get_key_double(i, tmp_value_double); - ZVAL_DOUBLE(tmp_zval, tmp_value_double); - break; + tmp_key = php_format_date("Y-m-d H:i:s", 11, ts, 1 TSRMLS_CC); + ZVAL_STRING(tmp_zval, tmp_key, 1); - case cql::CQL_COLUMN_TYPE_FLOAT: - tmp_collection_map->get_key_float(i, tmp_value_float); - ZVAL_DOUBLE(tmp_zval, tmp_value_float); - break; + break; - case cql::CQL_COLUMN_TYPE_INT: - tmp_collection_map->get_key_int(i, tmp_value_int); - ZVAL_LONG(tmp_zval, tmp_value_int); - break; + case cql::CQL_COLUMN_TYPE_TEXT: + case cql::CQL_COLUMN_TYPE_VARCHAR: + tmp_collection_map->get_key_string(i, tmp_value_string); + ZVAL_STRING(tmp_zval, tmp_value_string.c_str(), 1); + break; - case cql::CQL_COLUMN_TYPE_TIMESTAMP: - case cql::CQL_COLUMN_TYPE_TIMEUUID: + } - // Driver doesn't have method for getting timestamp [workaround] - tmp_collection_map->get_key_bigint(i, tmp_value_big_int); + if (tmp_zval->type != IS_STRING) { + convert_to_string_ex(&tmp_zval); + } - if (tmp_value_big_int > 1000) { - ts = (time_t) (tmp_value_big_int / 1000); - } - else { - ts = (time_t) 0; - } + tmp_key = Z_STRVAL_P(tmp_zval); - tmp_key = php_format_date("Y-m-d H:i:s", 11, ts, 1 TSRMLS_CC); - ZVAL_STRING(tmp_zval, tmp_key, 1); + // detect value type and add new element to array + switch (tmp_collection_map->value_type()) { - break; + case cql::CQL_COLUMN_TYPE_BIGINT: + tmp_collection_map->get_value_bigint(i, tmp_value_big_int); + add_assoc_long(subarray, tmp_key, tmp_value_big_int); + break; - case cql::CQL_COLUMN_TYPE_TEXT: - case cql::CQL_COLUMN_TYPE_VARCHAR: - tmp_collection_map->get_key_string(i, tmp_value_string); - ZVAL_STRING(tmp_zval, tmp_value_string.c_str(), 1); - break; + case cql::CQL_COLUMN_TYPE_BOOLEAN: + tmp_collection_map->get_value_bool(i, tmp_value_bool); + add_assoc_bool(subarray, tmp_key, tmp_value_bool); + break; + + case cql::CQL_COLUMN_TYPE_DOUBLE: + tmp_collection_map->get_value_double(i, tmp_value_double); + add_assoc_double(subarray, tmp_key, tmp_value_double); + break; + + case cql::CQL_COLUMN_TYPE_FLOAT: + tmp_collection_map->get_value_float(i, tmp_value_float); + add_assoc_double(subarray, tmp_key, tmp_value_float); + break; + + case cql::CQL_COLUMN_TYPE_INT: + tmp_collection_map->get_value_int(i, tmp_value_int); + add_assoc_long(subarray, tmp_key, tmp_value_int); + break; + + case cql::CQL_COLUMN_TYPE_TIMESTAMP: + // Driver doesn't have method for getting timestamp [workaround] + tmp_collection_map->get_value_bigint(i, tmp_value_big_int); + add_assoc_long(subarray, tmp_key, tmp_value_big_int); + break; + + case cql::CQL_COLUMN_TYPE_TIMEUUID: + + // Driver doesn't have method for getting timestamp [workaround] + tmp_collection_map->get_value_bigint(i, tmp_value_big_int); + + if (tmp_value_big_int > 1000) { + ts = (time_t) (tmp_value_big_int / 1000); + } + else { + ts = (time_t) 0; + } + + tmp_value_char = php_format_date("Y-m-d H:i:s", 11, ts, 1 TSRMLS_CC); + add_assoc_string(subarray, tmp_key, tmp_value_char, 1); + + break; + + case cql::CQL_COLUMN_TYPE_TEXT: + case cql::CQL_COLUMN_TYPE_VARCHAR: + tmp_collection_map->get_value_string(i, tmp_value_string); + add_assoc_string(subarray, tmp_key, (char *) tmp_value_string.c_str(), 1); + break; + + } } - if (tmp_zval->type != IS_STRING) { - convert_to_string_ex(&tmp_zval); + add_assoc_zval(return_value, column, subarray); + + break; + + case cql::CQL_COLUMN_TYPE_LIST: + + if (!obj->cql_result->get_list(column, tmp_collection_list) || tmp_collection_list == NULL) { + add_assoc_null(return_value, column); + continue; } - tmp_key = Z_STRVAL_P(tmp_zval); + subarray = NULL; + php_array_init(subarray); - // detect value type and add new element to array - switch (tmp_collection_map->value_type()) { + for (size_t i = 0; i < tmp_collection_list->size(); ++i) { - case cql::CQL_COLUMN_TYPE_BIGINT: - tmp_collection_map->get_value_bigint(i, tmp_value_big_int); - add_assoc_long(return_value, tmp_key, tmp_value_big_int); - break; + switch (tmp_collection_list->element_type()) { - case cql::CQL_COLUMN_TYPE_BOOLEAN: - tmp_collection_map->get_value_bool(i, tmp_value_bool); - add_assoc_bool(return_value, tmp_key, tmp_value_bool); - break; + case cql::CQL_COLUMN_TYPE_BIGINT: + tmp_collection_list->get_bigint(i, tmp_value_big_int); + add_next_index_long(subarray, tmp_value_big_int); + break; - case cql::CQL_COLUMN_TYPE_DOUBLE: - tmp_collection_map->get_value_double(i, tmp_value_double); - add_assoc_double(return_value, tmp_key, tmp_value_double); - break; + case cql::CQL_COLUMN_TYPE_BOOLEAN: + tmp_collection_list->get_bool(i, tmp_value_bool); + add_next_index_bool(subarray, tmp_value_bool); + break; - case cql::CQL_COLUMN_TYPE_FLOAT: - tmp_collection_map->get_value_float(i, tmp_value_float); - add_assoc_double(return_value, tmp_key, tmp_value_float); - break; + case cql::CQL_COLUMN_TYPE_DOUBLE: + tmp_collection_list->get_double(i, tmp_value_double); + add_next_index_double(subarray, tmp_value_double); + break; - case cql::CQL_COLUMN_TYPE_INT: - tmp_collection_map->get_value_int(i, tmp_value_int); - add_assoc_long(return_value, tmp_key, tmp_value_int); - break; + case cql::CQL_COLUMN_TYPE_FLOAT: + tmp_collection_list->get_float(i, tmp_value_float); + add_next_index_double(subarray, tmp_value_float); + break; - case cql::CQL_COLUMN_TYPE_TIMESTAMP: - case cql::CQL_COLUMN_TYPE_TIMEUUID: + case cql::CQL_COLUMN_TYPE_INT: + tmp_collection_list->get_int(i, tmp_value_int); + add_next_index_long(subarray, tmp_value_int); + break; - // Driver doesn't have method for getting timestamp [workaround] - tmp_collection_map->get_value_bigint(i, tmp_value_big_int); + case cql::CQL_COLUMN_TYPE_VARCHAR: + case cql::CQL_COLUMN_TYPE_TEXT: + tmp_collection_list->get_string(i, tmp_value_string); + add_next_index_string(subarray, tmp_value_string.c_str(), 1); + break; - if (tmp_value_big_int > 1000) { - ts = (time_t) (tmp_value_big_int / 1000); - } - else { - ts = (time_t) 0; - } + } + + } - tmp_value_char = php_format_date("Y-m-d H:i:s", 11, ts, 1 TSRMLS_CC); - add_assoc_string(return_value, tmp_key, tmp_value_char, 1); + add_assoc_zval(return_value, column, subarray); - break; + break; - case cql::CQL_COLUMN_TYPE_TEXT: - case cql::CQL_COLUMN_TYPE_VARCHAR: - tmp_collection_map->get_value_string(i, tmp_value_string); - add_assoc_string(return_value, tmp_key, (char *) tmp_value_string.c_str(), 1); - break; + case cql::CQL_COLUMN_TYPE_SET: + if (!obj->cql_result->get_set(column, tmp_collection_set) || tmp_collection_set == NULL) { + add_assoc_null(return_value, column); + continue; } - } + subarray = NULL; + php_array_init(subarray); - return; + for (size_t i = 0; i < tmp_collection_set->size(); ++i) { - break; + switch (tmp_collection_set->element_type()) { - case cql::CQL_COLUMN_TYPE_LIST: + case cql::CQL_COLUMN_TYPE_BIGINT: + tmp_collection_set->get_bigint(i, tmp_value_big_int); + add_next_index_long(subarray, tmp_value_big_int); + break; - if (!obj->cql_result->get_list(column, tmp_collection_list) || tmp_collection_list == NULL) { - RETURN_NULL(); - return; - } + case cql::CQL_COLUMN_TYPE_BOOLEAN: + tmp_collection_set->get_bool(i, tmp_value_bool); + add_next_index_bool(subarray, tmp_value_bool); + break; - php_array_init(return_value); + case cql::CQL_COLUMN_TYPE_DOUBLE: + tmp_collection_set->get_double(i, tmp_value_double); + add_next_index_double(subarray, tmp_value_double); + break; - for (size_t i = 0; i < tmp_collection_list->size(); ++i) { + case cql::CQL_COLUMN_TYPE_FLOAT: + tmp_collection_set->get_float(i, tmp_value_float); + add_next_index_double(subarray, tmp_value_float); + break; - switch (tmp_collection_list->element_type()) { + case cql::CQL_COLUMN_TYPE_INT: + tmp_collection_set->get_int(i, tmp_value_int); + add_next_index_long(subarray, tmp_value_int); + break; - case cql::CQL_COLUMN_TYPE_BIGINT: - tmp_collection_list->get_bigint(i, tmp_value_big_int); - add_next_index_long(return_value, tmp_value_big_int); - break; + case cql::CQL_COLUMN_TYPE_VARCHAR: + case cql::CQL_COLUMN_TYPE_TEXT: + tmp_collection_set->get_string(i, tmp_value_string); + add_next_index_string(subarray, tmp_value_string.c_str(), 1); + break; - case cql::CQL_COLUMN_TYPE_BOOLEAN: - tmp_collection_list->get_bool(i, tmp_value_bool); - add_next_index_bool(return_value, tmp_value_bool); - break; + } - case cql::CQL_COLUMN_TYPE_DOUBLE: - tmp_collection_list->get_double(i, tmp_value_double); - add_next_index_double(return_value, tmp_value_double); - break; + } - case cql::CQL_COLUMN_TYPE_FLOAT: - tmp_collection_list->get_float(i, tmp_value_float); - add_next_index_double(return_value, tmp_value_float); - break; + add_assoc_zval(return_value, column, subarray); - case cql::CQL_COLUMN_TYPE_INT: - tmp_collection_list->get_int(i, tmp_value_int); - add_next_index_long(return_value, tmp_value_int); - break; + break; - case cql::CQL_COLUMN_TYPE_VARCHAR: - case cql::CQL_COLUMN_TYPE_TEXT: - tmp_collection_list->get_string(i, tmp_value_string); - add_next_index_string(return_value, tmp_value_string.c_str(), 1); - break; + case cql::CQL_COLUMN_TYPE_TIMESTAMP: + // Driver doesn't have method for getting timestamp [workaround] + obj->cql_result->get_bigint(column, tmp_value_big_int); + if (tmp_column_type != orig_column_type && tmp_value_big_int == 0) { + add_assoc_null(return_value, column); + continue; } - } + add_assoc_long(return_value, column, tmp_value_big_int); + + break; - return; + case cql::CQL_COLUMN_TYPE_TIMEUUID: - break; + // Driver doesn't have method for getting timestamp [workaround] + obj->cql_result->get_bigint(column, tmp_value_big_int); - case cql::CQL_COLUMN_TYPE_SET: + if (tmp_column_type != orig_column_type && tmp_value_big_int == 0) { + add_assoc_null(return_value, column); + continue; + } - if (!obj->cql_result->get_set(column, tmp_collection_set) || tmp_collection_set == NULL) { - RETURN_NULL(); - return; - } + if (tmp_value_big_int > 1000) { + ts = (time_t) (tmp_value_big_int / 1000); + } + else { + ts = (time_t) 0; + } - php_array_init(return_value); + tmp_value_char = php_format_date("Y-m-d H:i:s", 11, ts, 1 TSRMLS_CC); + add_assoc_string(return_value, column, tmp_value_char, 1); - for (size_t i = 0; i < tmp_collection_set->size(); ++i) { + break; - switch (tmp_collection_set->element_type()) { + case cql::CQL_COLUMN_TYPE_ASCII: + case cql::CQL_COLUMN_TYPE_BLOB: + case cql::CQL_COLUMN_TYPE_TEXT: + case cql::CQL_COLUMN_TYPE_VARCHAR: - case cql::CQL_COLUMN_TYPE_BIGINT: - tmp_collection_set->get_bigint(i, tmp_value_big_int); - add_next_index_long(return_value, tmp_value_big_int); - break; + obj->cql_result->get_string(column, tmp_value_string); - case cql::CQL_COLUMN_TYPE_BOOLEAN: - tmp_collection_set->get_bool(i, tmp_value_bool); - add_next_index_bool(return_value, tmp_value_bool); - break; + if (tmp_value_string.length() < 1) { + add_assoc_null(return_value, column); + continue; + } - case cql::CQL_COLUMN_TYPE_DOUBLE: - tmp_collection_set->get_double(i, tmp_value_double); - add_next_index_double(return_value, tmp_value_double); - break; + add_assoc_string(return_value, column, const_cast(tmp_value_string.c_str()), 1); - case cql::CQL_COLUMN_TYPE_FLOAT: - tmp_collection_set->get_float(i, tmp_value_float); - add_next_index_double(return_value, tmp_value_float); - break; + break; - case cql::CQL_COLUMN_TYPE_INT: - tmp_collection_set->get_int(i, tmp_value_int); - add_next_index_long(return_value, tmp_value_int); - break; + case cql::CQL_COLUMN_TYPE_INET: - case cql::CQL_COLUMN_TYPE_VARCHAR: - case cql::CQL_COLUMN_TYPE_TEXT: - tmp_collection_set->get_string(i, tmp_value_string); - add_next_index_string(return_value, tmp_value_string.c_str(), 1); - break; + obj->cql_result->get_inet(column, tmp_value_inet); + if (tmp_value_inet.is_unspecified()) { + add_assoc_null(return_value, column); + continue; } - } + add_assoc_string(return_value, column, const_cast(tmp_value_inet.to_string().c_str()), 1); - return; + break; - break; + case cql::CQL_COLUMN_TYPE_DECIMAL: - case cql::CQL_COLUMN_TYPE_TIMESTAMP: - case cql::CQL_COLUMN_TYPE_TIMEUUID: + obj->cql_result->get_decimal(column, tmp_value_decimal); - // Driver doesn't have method for getting timestamp [workaround] - obj->cql_result->get_bigint(column, tmp_value_big_int); + if (!tmp_value_decimal.is_convertible_to_double()) { + add_assoc_null(return_value, column); + continue; + } - if (column_type != orig_column_type && tmp_value_big_int == 0) { - RETURN_NULL(); - return; - } + tmp_value_decimal.convert_to_double(_tmp_value_decimal); - if (tmp_value_big_int > 1000) { - ts = (time_t) (tmp_value_big_int / 1000); - } - else { - ts = (time_t) 0; - } + add_assoc_double(return_value, column, _tmp_value_decimal); - tmp_value_char = php_format_date("Y-m-d H:i:s", 11, ts, 1 TSRMLS_CC); - RETURN_STRING(tmp_value_char, 1); + break; - break; + case cql::CQL_COLUMN_TYPE_VARINT: - case cql::CQL_COLUMN_TYPE_TEXT: - case cql::CQL_COLUMN_TYPE_VARCHAR: + obj->cql_result->get_varint(column, tmp_value_varint); - obj->cql_result->get_string(column, tmp_value_string); + tmp_value_varint.convert_to_boost_multiprecision(_tmp_value_varint); - if (tmp_value_string.length() < 1) { - RETURN_NULL(); - return; - } + if (_tmp_value_varint.is_zero() && !tmp_value_varint.is_convertible_to_int64()) { + add_assoc_null(return_value, column); + continue; + } - RETURN_STRING(tmp_value_string.c_str(), 1); + add_assoc_string(return_value, column, const_cast(_tmp_value_varint.str().c_str()), 1); - break; + break; - case cql::CQL_COLUMN_TYPE_UUID: + case cql::CQL_COLUMN_TYPE_UUID: - obj->cql_result->get_data(column, data); + for (size_t i = 0; i < data.size(); ++i) { - for (size_t i = 0; i < data.size(); ++i) { + unsigned char * ch = reinterpret_cast(&data[i]); - unsigned char * ch = reinterpret_cast(&data[i]); + int c = (int) *ch; + ss << std::setfill('0') << std::setw(2) << std::hex << c; - int c = (int) *ch; - ss << std::setfill('0') << std::setw(2) << std::hex << c; + if (i == 3 || i == 5 || i == 7 || i == 9) { + ss << "-"; + } - if (i == 3 || i == 5 || i == 7 || i == 9) { - ss << "-"; } - } - - tmp_value_string = ss.str(); + tmp_value_string = ss.str(); - if (tmp_value_string.length() < 1) { - RETURN_NULL(); - return; - } + if (tmp_value_string.length() < 1) { + add_assoc_null(return_value, column); + continue; + } - RETURN_STRING(tmp_value_string.c_str(), 1); + add_assoc_string(return_value, column, const_cast(tmp_value_string.c_str()), 1); - break; + break; + } } - RETURN_NULL(); + if (ZEND_NUM_ARGS() > 0) { + zval **d = NULL; + const char * cname = (const char *)column; + zend_hash_find(Z_ARRVAL_P(return_value), cname, (column_len + 1), (void **)&d); + if (d) { + RETURN_ZVAL(*d, true, true); + } + RETURN_NULL(); + } } PHP_METHOD(CqlResult, getColumnCount) @@ -1617,6 +1683,15 @@ PHP_RINIT_FUNCTION(cassandra) */ PHP_RSHUTDOWN_FUNCTION(cassandra) { + try { + if (CASSANDRA_G(g_cluster_object)) + CASSANDRA_G(g_cluster_object)->cql_cluster->shutdown(-1); + + if (CASSANDRA_G(g_session_object)) + CASSANDRA_G(g_session_object)->cql_session->close(); + + } + catch (std::exception & e) {} return SUCCESS; } /* }}} */ diff --git a/php_cassandra.h b/php_cassandra.hpp similarity index 63% rename from php_cassandra.h rename to php_cassandra.hpp index 77fd0c6..8ebcc39 100644 --- a/php_cassandra.h +++ b/php_cassandra.hpp @@ -1,83 +1,134 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2012 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifndef PHP_CASSANDRA_H -#define PHP_CASSANDRA_H - -extern zend_module_entry cassandra_module_entry; -#define phpext_cassandra_ptr &cassandra_module_entry - -#ifdef PHP_WIN32 -# define PHP_CASSANDRA_API __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_CASSANDRA_API __attribute__ ((visibility("default"))) -#else -# define PHP_CASSANDRA_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(cassandra); -PHP_MSHUTDOWN_FUNCTION(cassandra); -PHP_RINIT_FUNCTION(cassandra); -PHP_RSHUTDOWN_FUNCTION(cassandra); -PHP_MINFO_FUNCTION(cassandra); - -PHP_FUNCTION(confirm_cassandra_compiled); /* For testing, remove later. */ - -/* - Declare any global variables you may need between the BEGIN - and END macros here: - -ZEND_BEGIN_MODULE_GLOBALS(cassandra) - long global_value; - char *global_string; -ZEND_END_MODULE_GLOBALS(cassandra) -*/ - -/* In every utility function you add that needs to use variables - in php_cassandra_globals, call TSRMLS_FETCH(); after declaring other - variables used by that function, or better yet, pass in TSRMLS_CC - after the last function argument and declare your utility function - with TSRMLS_DC after the last declared argument. Always refer to - the globals in your function as CASSANDRA_G(variable). You are - encouraged to rename these macros something shorter, see - examples in any other php module directory. -*/ - -#ifdef ZTS -#define CASSANDRA_G(v) TSRMG(cassandra_globals_id, zend_cassandra_globals *, v) -#else -#define CASSANDRA_G(v) (cassandra_globals.v) -#endif - -#endif /* PHP_CASSANDRA_H */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2012 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_CASSANDRA_H +#define PHP_CASSANDRA_H + +extern zend_module_entry cassandra_module_entry; +#define phpext_cassandra_ptr &cassandra_module_entry + +#ifdef PHP_WIN32 +# define PHP_CASSANDRA_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_CASSANDRA_API __attribute__ ((visibility("default"))) +#else +# define PHP_CASSANDRA_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +PHP_MINIT_FUNCTION(cassandra); +PHP_MSHUTDOWN_FUNCTION(cassandra); +PHP_RINIT_FUNCTION(cassandra); +PHP_RSHUTDOWN_FUNCTION(cassandra); +PHP_MINFO_FUNCTION(cassandra); + +PHP_FUNCTION(confirm_cassandra_compiled); /* For testing, remove later. */ + +struct cql_builder_object { + zend_object std; + boost::shared_ptr cql_builder; +}; + +struct cql_cluster_object { + zend_object std; + boost::shared_ptr cql_cluster; +}; + +struct cql_error_object { + zend_object std; + cql::cql_error_t cql_error; +}; + +struct cql_future_result_object { + zend_object std; + boost::shared_future cql_future_result; +}; + +struct cql_query_object { + zend_object std; + boost::shared_ptr cql_query; +}; + +struct cql_session_object { + zend_object std; + boost::shared_ptr cql_session; +}; + +struct cql_result_object { + zend_object std; + boost::shared_ptr cql_result; +}; + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + + */ +ZEND_BEGIN_MODULE_GLOBALS(cassandra) + cql_cluster_object *g_cluster_object; + cql_session_object *g_session_object; +ZEND_END_MODULE_GLOBALS(cassandra) + +/* In every utility function you add that needs to use variables + in php_cassandra_globals, call TSRMLS_FETCH(); after declaring other + variables used by that function, or better yet, pass in TSRMLS_CC + after the last function argument and declare your utility function + with TSRMLS_DC after the last declared argument. Always refer to + the globals in your function as CASSANDRA_G(variable). You are + encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ + +#ifdef ZTS +#define CASSANDRA_G(v) TSRMG(cassandra_globals_id, zend_cassandra_globals *, v) +#else +#define CASSANDRA_G(v) (cassandra_globals.v) +#endif + +#endif /* PHP_CASSANDRA_H */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */