X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pqres.c;h=8233d6623b718694eb2d900aa277506f46a858a3;hp=67dac3403b3fd951561d75e89ac1d104f95f1a3c;hb=359b3471d6ed843d8ecf9d5fb0b85f06af446800;hpb=2805a4d1f8dc3e718ba7822040208e9c608358e0 diff --git a/src/php_pqres.c b/src/php_pqres.c index 67dac34..8233d66 100644 --- a/src/php_pqres.c +++ b/src/php_pqres.c @@ -24,6 +24,8 @@ #include "php_pq_object.h" #include "php_pqexc.h" #include "php_pqres.h" +#undef PHP_PQ_TYPE +#include "php_pq_type.h" zend_class_entry *php_pqres_class_entry; static zend_object_handlers php_pqres_object_handlers; @@ -88,6 +90,99 @@ static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC) return SUCCESS; } +zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRMLS_DC) +{ + zval *zv, **zconv; + + MAKE_STD_ZVAL(zv); + + if (SUCCESS == zend_hash_index_find(&res->converters, typ, (void *) &zconv)) { + zval *tmp = NULL; + + ZVAL_STRINGL(zv, val, len, 1); + zend_call_method_with_1_params(zconv, NULL, NULL, "convertfromstring", &tmp, zv); + + if (tmp) { + zval_ptr_dtor(&zv); + zv = tmp; + } + + return zv; + } + + switch (typ) { + case PHP_PQ_OID_BOOL: + if (!(res->auto_convert & PHP_PQRES_CONV_BOOL)) { + goto noconversion; + } + ZVAL_BOOL(zv, *val == 't'); + break; +#if SIZEOF_LONG >= 8 + case PHP_PQ_OID_INT8: + case PHP_PQ_OID_TID: +#endif + case PHP_PQ_OID_INT4: + case PHP_PQ_OID_INT2: + case PHP_PQ_OID_XID: + case PHP_PQ_OID_OID: + if (!(res->auto_convert & PHP_PQRES_CONV_INT)) { + goto noconversion; + } + ZVAL_LONG(zv, zend_atol(val, len)); + break; + + case PHP_PQ_OID_FLOAT4: + case PHP_PQ_OID_FLOAT8: + if (!(res->auto_convert & PHP_PQRES_CONV_FLOAT)) { + goto noconversion; + } + ZVAL_DOUBLE(zv, zend_strtod(val, NULL)); + break; + + case PHP_PQ_OID_DATE: + if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) { + goto noconversion; + } + php_pqdt_from_string(val, len, "Y-m-d", zv TSRMLS_CC); + break; + + case PHP_PQ_OID_ABSTIME: + if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) { + goto noconversion; + } + php_pqdt_from_string(val, len, "Y-m-d H:i:s", zv TSRMLS_CC); + break; + + case PHP_PQ_OID_TIMESTAMP: + if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) { + goto noconversion; + } + php_pqdt_from_string(val, len, "Y-m-d H:i:s.u", zv TSRMLS_CC); + break; + + case PHP_PQ_OID_TIMESTAMPTZ: + if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) { + goto noconversion; + } + php_pqdt_from_string(val, len, "Y-m-d H:i:s.uO", zv TSRMLS_CC); + break; + + default: + if (!(res->auto_convert & PHP_PQRES_CONV_ARRAY)) { + goto noconversion; + } + if (PHP_PQ_TYPE_IS_ARRAY(typ) && (Z_ARRVAL_P(zv) = php_pq_parse_array(res, val, len, PHP_PQ_TYPE_OF_ARRAY(typ) TSRMLS_CC))) { + Z_TYPE_P(zv) = IS_ARRAY; + } else { + noconversion: + ZVAL_STRINGL(zv, val, len, 1); + } + break; + } + + return zv; +} + zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type, zval **data_ptr TSRMLS_DC) { zval *data = NULL; @@ -126,22 +221,9 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch break; } } else { - zval *zv, **zconv; + zval *zv; - if (res_obj && (SUCCESS == zend_hash_index_find(&res_obj->intern->converters, PQftype(res, c), (void *) &zconv))) { - zval *tmp = NULL; - - MAKE_STD_ZVAL(zv); - ZVAL_STRINGL(zv, PQgetvalue(res, row, c), PQgetlength(res, row, c), 1); - zend_call_method_with_1_params(zconv, NULL, NULL, "convertfromstring", &tmp, zv); - - if (tmp) { - zval_ptr_dtor(&zv); - zv = tmp; - } - } else { - zv = php_pq_typed_zval(PQgetvalue(res, row, c), PQgetlength(res, row, c), PQftype(res, c) TSRMLS_CC); - } + zv = php_pqres_typed_zval(res_obj->intern, PQgetvalue(res, row, c), PQgetlength(res, row, c), PQftype(res, c) TSRMLS_CC); switch (fetch_type) { case PHP_PQRES_FETCH_OBJECT: @@ -272,8 +354,11 @@ void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj, zend_hash_init(&r->bound, 0, 0, ZVAL_PTR_DTOR, 0); zend_hash_init(&r->converters, 0, 0, ZVAL_PTR_DTOR, 0); zend_hash_copy(&r->converters, &conn_obj->intern->converters, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); - php_pqres_create_object_ex(php_pqres_class_entry, r, &obj TSRMLS_CC); + r->auto_convert = conn_obj->intern->default_auto_convert; + r->default_fetch_type = conn_obj->intern->default_fetch_type; + + php_pqres_create_object_ex(php_pqres_class_entry, r, &obj TSRMLS_CC); PQresultSetInstanceData(res, php_pqconn_event, obj); if (ptr) { @@ -391,7 +476,7 @@ static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return if (obj->intern->iter) { RETVAL_LONG(obj->intern->iter->fetch_type); } else { - RETVAL_LONG(PHP_PQRES_FETCH_ARRAY); + RETVAL_LONG(obj->intern->default_fetch_type); } } @@ -423,6 +508,37 @@ static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value } } +static void php_pqres_object_read_auto_conv(zval *object, void *o, zval *return_value TSRMLS_DC) +{ + php_pqres_object_t *obj = o; + + RETVAL_LONG(obj->intern->auto_convert); +} + +static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value TSRMLS_DC) +{ + php_pqres_object_t *obj = o; + zval *zauto_conv = value; + + if (Z_TYPE_P(value) != IS_LONG) { + if (Z_REFCOUNT_P(value) > 1) { + zval *tmp; + MAKE_STD_ZVAL(tmp); + ZVAL_ZVAL(tmp, zauto_conv, 1, 0); + convert_to_long(tmp); + zauto_conv = tmp; + } else { + convert_to_long_ex(&zauto_conv); + } + } + + obj->intern->auto_convert = Z_LVAL_P(zauto_conv); + + if (zauto_conv != value) { + zval_ptr_dtor(&zauto_conv); + } +} + static STATUS php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval ***row TSRMLS_DC) { STATUS rv; @@ -600,7 +716,7 @@ static PHP_METHOD(pqres, fetchRow) { zval **row = NULL; if (fetch_type == -1) { - fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : PHP_PQRES_FETCH_ARRAY; + fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type; } zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); @@ -760,7 +876,7 @@ static PHP_METHOD(pqres, map) { } if (fetch_type == -1) { - fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : PHP_PQRES_FETCH_ARRAY; + fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type; } if (keys) { @@ -857,7 +973,7 @@ static PHP_METHOD(pqres, fetchAll) { int r, rows = PQntuples(obj->intern->res); if (fetch_type == -1) { - fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : PHP_PQRES_FETCH_ARRAY; + fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type; } array_init(return_value); @@ -973,6 +1089,12 @@ PHP_MINIT_FUNCTION(pqres) zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL); ph.write = NULL; + zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("autoConvert"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC); + ph.read = php_pqres_object_read_auto_conv; + ph.write = php_pqres_object_write_auto_conv; + zend_hash_add(&php_pqres_object_prophandlers, "autoConvert", sizeof("autoConvert"), (void *) &ph, sizeof(ph), NULL); + ph.write = NULL; + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC); zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC); zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC); @@ -988,6 +1110,14 @@ PHP_MINIT_FUNCTION(pqres) zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC); zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_BOOL"), PHP_PQRES_CONV_BOOL TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_INT"), PHP_PQRES_CONV_INT TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_FLOAT"), PHP_PQRES_CONV_FLOAT TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL TSRMLS_CC); + return SUCCESS; }