X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pqres.c;h=6e1fa681090aa1f476f1362e6b26e80ae277d03c;hp=0197732f510d2f63dfd12d8977ca86cf7a646afc;hb=8056f4e71952a5c0f0ef0e81b7b21a0c09878947;hpb=94be2af75078af30116718bb2df201d9e5a47e5b diff --git a/src/php_pqres.c b/src/php_pqres.c index 0197732..6e1fa68 100644 --- a/src/php_pqres.c +++ b/src/php_pqres.c @@ -17,7 +17,10 @@ #include #include -#include +#if PHP_PQ_HAVE_PHP_JSON_H +#include /* we've added the include directory to INCLUDES */ +#endif + #include #include "php_pq.h" @@ -40,8 +43,8 @@ static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval iter = ecalloc(1, sizeof(*iter)); iter->zi.funcs = &php_pqres_iterator_funcs; - iter->zi.data = object; - /* do not addref, because the iterator lives inside this object anyway */ + iter->zi.data = zend_object_store_get_object(object TSRMLS_CC); + zend_objects_store_add_ref(object TSRMLS_CC); zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC); if (Z_TYPE_P(zfetch_type) != IS_LONG) { @@ -64,22 +67,26 @@ static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; + php_pqres_object_t *obj = i->data; if (iter->current_val) { zval_ptr_dtor(&iter->current_val); iter->current_val = NULL; } + zend_objects_store_del_ref_by_handle_ex(obj->zv.handle, obj->zv.handlers TSRMLS_CC); efree(iter); } -static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC) +static ZEND_RESULT_CODE php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC); + php_pqres_object_t *obj = i->data; switch (PQresultStatus(obj->intern->res)) { case PGRES_TUPLES_OK: +#ifdef HAVE_PGRES_SINGLE_TUPLE case PGRES_SINGLE_TUPLE: +#endif if (PQntuples(obj->intern->res) <= iter->index) { return FAILURE; } @@ -91,6 +98,9 @@ static STATUS php_pqres_iterator_valid(zend_object_iterator *i TSRMLS_DC) return SUCCESS; } +#define PHP_PQRES_JSON_OPTIONS(res) \ + (php_pqres_fetch_type(res) != PHP_PQRES_FETCH_OBJECT ? PHP_JSON_OBJECT_AS_ARRAY:0) + zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRMLS_DC) { zval *zv, **zconv; @@ -98,10 +108,13 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM MAKE_STD_ZVAL(zv); if (SUCCESS == zend_hash_index_find(&res->converters, typ, (void *) &zconv)) { - zval *tmp = NULL; + zval *ztype, *tmp = NULL; + MAKE_STD_ZVAL(ztype); + ZVAL_LONG(ztype, typ); ZVAL_STRINGL(zv, val, len, 1); - zend_call_method_with_1_params(zconv, NULL, NULL, "convertfromstring", &tmp, zv); + zend_call_method_with_2_params(zconv, NULL, NULL, "convertfromstring", &tmp, zv, ztype); + zval_ptr_dtor(&ztype); if (tmp) { zval_ptr_dtor(&zv); @@ -118,10 +131,9 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM } 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: @@ -129,7 +141,21 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM if (!(res->auto_convert & PHP_PQRES_CONV_INT)) { goto noconversion; } - ZVAL_LONG(zv, zend_atol(val, len)); + { + long lval; + double dval; + + switch (is_numeric_string(val, len, &lval, &dval, 0)) { + case IS_LONG: + ZVAL_LONG(zv, lval); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(zv, dval); + break; + default: + goto noconversion; + } + } break; case PHP_PQ_OID_FLOAT4: @@ -144,31 +170,31 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM if (!(res->auto_convert & PHP_PQRES_CONV_DATETIME)) { goto noconversion; } - php_pqdt_from_string(val, len, "Y-m-d", zv TSRMLS_CC); + php_pqdt_from_string(zv, NULL, val, len, "Y-m-d", NULL 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); + php_pqdt_from_string(zv, NULL, val, len, "Y-m-d H:i:s", NULL 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); + php_pqdt_from_string(zv, NULL, val, len, "Y-m-d H:i:s.u", NULL 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); + php_pqdt_from_string(zv, NULL, val, len, "Y-m-d H:i:s.uO", NULL TSRMLS_CC); break; -#ifdef PHP_PQ_OID_JSON +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) # ifdef PHP_PQ_OID_JSONB case PHP_PQ_OID_JSONB: # endif @@ -176,7 +202,7 @@ zval *php_pqres_typed_zval(php_pqres_t *res, char *val, size_t len, Oid typ TSRM if (!(res->auto_convert & PHP_PQRES_CONV_JSON)) { goto noconversion; } - php_json_decode_ex(zv, val, len, 0, 512 /* PHP_JSON_DEFAULT_DEPTH */ TSRMLS_CC); + php_json_decode_ex(zv, val, len, PHP_PQRES_JSON_OPTIONS(res), 512 /* PHP_JSON_DEFAULT_DEPTH */ TSRMLS_CC); break; #endif @@ -281,7 +307,7 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_object_t *obj = zend_object_store_get_object(iter->zi.data TSRMLS_CC); + php_pqres_object_t *obj = i->data; if (!iter->current_val) { iter->current_val = php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type, NULL TSRMLS_CC); @@ -361,7 +387,7 @@ static int php_pqres_count_elements(zval *object, long *count TSRMLS_DC) } } -STATUS php_pqres_success(PGresult *res TSRMLS_DC) +ZEND_RESULT_CODE php_pqres_success(PGresult *res TSRMLS_DC) { zval *zexc; @@ -398,6 +424,11 @@ void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj, } } +php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res) +{ + return res->iter ? res->iter->fetch_type : res->default_fetch_type; +} + static void php_pqres_object_free(void *o TSRMLS_DC) { php_pqres_object_t *obj = o; @@ -505,11 +536,7 @@ static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return { php_pqres_object_t *obj = o; - if (obj->intern->iter) { - RETVAL_LONG(obj->intern->iter->fetch_type); - } else { - RETVAL_LONG(obj->intern->default_fetch_type); - } + RETVAL_LONG(php_pqres_fetch_type(obj->intern)); } static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC) @@ -571,9 +598,9 @@ static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value } } -static STATUS php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval ***row TSRMLS_DC) +static ZEND_RESULT_CODE php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval ***row TSRMLS_DC) { - STATUS rv; + ZEND_RESULT_CODE rv; php_pqres_fetch_t orig_fetch; if (!obj) { @@ -601,7 +628,7 @@ typedef struct php_pqres_col { int num; } php_pqres_col_t; -static STATUS column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col TSRMLS_DC) +static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col TSRMLS_DC) { long index = -1; char *name = NULL; @@ -656,7 +683,7 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, bind) { zval *zcol, *zref; zend_error_handling zeh; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z", &zcol, &zref); @@ -679,7 +706,7 @@ static PHP_METHOD(pqres, bind) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to bind column %s@%d", col.name, col.num); RETVAL_FALSE; } else { - zend_hash_sort(&obj->intern->bound, zend_qsort, compare_index, 0 TSRMLS_CC); + zend_hash_sort(&obj->intern->bound, zend_qsort, php_pq_compare_index, 0 TSRMLS_CC); RETVAL_TRUE; } } @@ -691,7 +718,7 @@ static int apply_bound(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key { zval **zvalue, **zbound = p; zval **zrow = va_arg(argv, zval **); - STATUS *rv = va_arg(argv, STATUS *); + ZEND_RESULT_CODE *rv = va_arg(argv, ZEND_RESULT_CODE *); if (SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrow), key->h, (void *) &zvalue)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column ad index %lu", key->h); @@ -713,7 +740,7 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_bound, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchBound) { zend_error_handling zeh; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters_none(); @@ -749,7 +776,7 @@ static PHP_METHOD(pqres, fetchRow) { zend_error_handling zeh; php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); long fetch_type = -1; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type); @@ -762,7 +789,7 @@ static PHP_METHOD(pqres, fetchRow) { zval **row = NULL; if (fetch_type == -1) { - fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type; + fetch_type = php_pqres_fetch_type(obj->intern); } zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); @@ -801,7 +828,7 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchCol) { zend_error_handling zeh; zval *zcol = NULL, *zref; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z/!", &zref, &zcol); @@ -816,7 +843,7 @@ static PHP_METHOD(pqres, fetchCol) { zval **row = NULL; zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); - php_pqres_iteration(getThis(), obj, obj->intern->iter ? obj->intern->iter->fetch_type : 0, &row TSRMLS_CC); + php_pqres_iteration(getThis(), obj, php_pqres_fetch_type(obj->intern), &row TSRMLS_CC); if (row) { php_pqres_col_t col; @@ -845,7 +872,7 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchAllCols) { zend_error_handling zeh; zval *zcol = NULL; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!", &zcol); @@ -873,37 +900,41 @@ static PHP_METHOD(pqres, fetchAllCols) { } } -static int apply_to_col(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +struct apply_to_col_arg { + php_pqres_object_t *obj; + php_pqres_col_t *cols; + ZEND_RESULT_CODE status; +}; + +static int apply_to_col(void *p, void *a TSRMLS_DC) { zval **c = p; - php_pqres_object_t *obj = va_arg(argv, php_pqres_object_t *); - php_pqres_col_t *col, **cols = va_arg(argv, php_pqres_col_t **); - STATUS *rv = va_arg(argv, STATUS *); - - col = *cols; + struct apply_to_col_arg *arg = a; - if (SUCCESS != column_nn(obj, *c, col TSRMLS_CC)) { - *rv = FAILURE; + if (SUCCESS != column_nn(arg->obj, *c, arg->cols TSRMLS_CC)) { + arg->status = FAILURE; return ZEND_HASH_APPLY_STOP; } else { - *rv = SUCCESS; - ++*cols; + arg->status = SUCCESS; + ++arg->cols; return ZEND_HASH_APPLY_KEEP; } } static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashTable *ht TSRMLS_DC) { - php_pqres_col_t *tmp, *cols = ecalloc(zend_hash_num_elements(ht), sizeof(*cols)); - STATUS rv = SUCCESS; + struct apply_to_col_arg arg = {NULL}; + php_pqres_col_t *tmp; - tmp = cols; - zend_hash_apply_with_arguments(ht TSRMLS_CC, apply_to_col, 2, obj, &tmp, &rv); + arg.obj = obj; + arg.cols = ecalloc(zend_hash_num_elements(ht), sizeof(*tmp)); + tmp = arg.cols; + zend_hash_apply_with_argument(ht, apply_to_col, &arg TSRMLS_CC); - if (SUCCESS == rv) { - return cols; + if (SUCCESS == arg.status) { + return tmp; } else { - efree(cols); + efree(tmp); return NULL; } } @@ -917,7 +948,7 @@ static PHP_METHOD(pqres, map) { zend_error_handling zeh; zval *zkeys = 0, *zvals = 0; long fetch_type = -1; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/!z/!l", &zkeys, &zvals, &fetch_type); @@ -954,7 +985,7 @@ static PHP_METHOD(pqres, map) { } if (fetch_type == -1) { - fetch_type = obj->intern->iter ? obj->intern->iter->fetch_type : obj->intern->default_fetch_type; + fetch_type = php_pqres_fetch_type(obj->intern); } if (keys) { @@ -1037,7 +1068,7 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchAll) { zend_error_handling zeh; long fetch_type = -1; - STATUS rv; + ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type); @@ -1051,7 +1082,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 : obj->intern->default_fetch_type; + fetch_type = php_pqres_fetch_type(obj->intern); } array_init(return_value); @@ -1065,7 +1096,14 @@ static PHP_METHOD(pqres, fetchAll) { ZEND_BEGIN_ARG_INFO_EX(ai_pqres_count, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, count) { - if (SUCCESS == zend_parse_parameters_none()) { + zend_error_handling zeh; + ZEND_RESULT_CODE rv; + + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + rv = zend_parse_parameters_none(); + zend_restore_error_handling(&zeh TSRMLS_CC); + + if (SUCCESS == rv) { long count; if (SUCCESS != php_pqres_count_elements(getThis(), &count TSRMLS_CC)) { @@ -1079,7 +1117,14 @@ static PHP_METHOD(pqres, count) { ZEND_BEGIN_ARG_INFO_EX(ai_pqres_desc, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, desc) { - if (SUCCESS == zend_parse_parameters_none()) { + zend_error_handling zeh; + ZEND_RESULT_CODE rv; + + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + rv = zend_parse_parameters_none(); + zend_restore_error_handling(&zeh TSRMLS_CC); + + if (SUCCESS == rv) { php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); if (!obj->intern) { @@ -1182,8 +1227,12 @@ PHP_MINIT_FUNCTION(pqres) zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC); zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC); zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC); +#ifdef HAVE_PGRES_COPY_BOTH zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC); +#endif +#ifdef HAVE_PGRES_SINGLE_TUPLE zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC); +#endif zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC); zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC); @@ -1195,7 +1244,9 @@ PHP_MINIT_FUNCTION(pqres) 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); +#if PHP_PQ_HAVE_PHP_JSON_H zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON TSRMLS_CC); +#endif zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL TSRMLS_CC); return SUCCESS;