X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pqres.c;h=b365f3d2e36a1379f40fad1745775550bf4631a2;hp=aee753d0acd0c78f42272bffa8de246633e57215;hb=d613997b3072b8093bca3fe9d8aca115e2a579aa;hpb=5aa292d5bc46cd8fe266d682397dba19dc1e1d36 diff --git a/src/php_pqres.c b/src/php_pqres.c index aee753d..b365f3d 100644 --- a/src/php_pqres.c +++ b/src/php_pqres.c @@ -38,7 +38,7 @@ 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; - Z_ADDREF_P(object); + /* do not addref, because the iterator lives inside this object anyway */ zfetch_type = prop = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0 TSRMLS_CC); if (Z_TYPE_P(zfetch_type) != IS_LONG) { @@ -66,7 +66,6 @@ static void php_pqres_iterator_dtor(zend_object_iterator *i TSRMLS_DC) zval_ptr_dtor(&iter->current_val); iter->current_val = NULL; } - zval_ptr_dtor((zval **) &iter->zi.data); efree(iter); } @@ -93,6 +92,7 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch { zval *data = NULL; int c, cols; + php_pqres_object_t *res_obj = PQresultInstanceData(res, php_pqconn_event); if (data_ptr) { data = *data_ptr; @@ -126,20 +126,35 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch break; } } else { - char *val = PQgetvalue(res, row, c); - int len = PQgetlength(res, row, c); + zval *zv, **zconv; + + 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); + } switch (fetch_type) { case PHP_PQRES_FETCH_OBJECT: - add_property_stringl(data, PQfname(res, c), val, len, 1); + add_property_zval(data, PQfname(res, c), zv); + zval_ptr_dtor(&zv); break; case PHP_PQRES_FETCH_ASSOC: - add_assoc_stringl(data, PQfname(res, c), val, len, 1); + add_assoc_zval(data, PQfname(res, c), zv); break; case PHP_PQRES_FETCH_ARRAY: - add_index_stringl(data, c, val, len ,1); + add_index_zval(data, c, zv); break; } } @@ -248,15 +263,19 @@ STATUS php_pqres_success(PGresult *res TSRMLS_DC) } } -void php_pqres_init_instance_data(PGresult *res, php_pqres_object_t **ptr TSRMLS_DC) +void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj, php_pqres_object_t **ptr TSRMLS_DC) { php_pqres_object_t *obj; php_pqres_t *r = ecalloc(1, sizeof(*r)); r->res = res; - ZEND_INIT_SYMTABLE(&r->bound); - php_pqres_create_object_ex(php_pqres_class_entry, r, &obj TSRMLS_CC); + 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 *)); + + 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) { @@ -283,6 +302,7 @@ static void php_pqres_object_free(void *o TSRMLS_DC) } zend_hash_destroy(&obj->intern->bound); + zend_hash_destroy(&obj->intern->converters); efree(obj->intern); obj->intern = NULL; @@ -373,7 +393,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); } } @@ -441,6 +461,10 @@ static STATUS column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *co char *name = NULL; switch (Z_TYPE_P(zcol)) { + case IS_LONG: + index = Z_LVAL_P(zcol); + break; + default: convert_to_string(zcol); /* no break */ @@ -450,10 +474,6 @@ static STATUS column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *co name = Z_STRVAL_P(zcol); } break; - - case IS_LONG: - index = Z_LVAL_P(zcol); - break; } if (name) { @@ -582,7 +602,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); @@ -614,16 +634,17 @@ static zval **column_at(zval *row, int col TSRMLS_DC) return data; } -ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 0) - ZEND_ARG_INFO(0, col_num) +ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col, 0, 0, 2) + ZEND_ARG_INFO(0, col) + ZEND_ARG_INFO(1, ref) ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchCol) { zend_error_handling zeh; - long fetch_col = 0; + zval *zcol, *zref; STATUS 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_col); + rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z", &zcol, &zref); zend_restore_error_handling(&zeh TSRMLS_CC); if (SUCCESS == rv) { @@ -636,11 +657,23 @@ static PHP_METHOD(pqres, fetchCol) { 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); - if (row) { - zval **col = column_at(*row, fetch_col TSRMLS_CC); + if (!row) { + RETVAL_FALSE; + } else { + php_pqres_col_t col; - if (col) { - RETVAL_ZVAL(*col, 1, 0); + if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) { + RETVAL_FALSE; + } else { + zval **zres = column_at(*row, col.num TSRMLS_CC); + + if (!zres) { + RETVAL_FALSE; + } else { + zval_dtor(zref); + ZVAL_ZVAL(zref, *zres, 1, 0); + RETVAL_TRUE; + } } } zend_restore_error_handling(&zeh TSRMLS_CC); @@ -729,7 +762,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) { @@ -826,7 +859,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); @@ -851,6 +884,25 @@ 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()) { + php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (!obj->intern) { + throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + } else { + int p, params; + + array_init(return_value); + for (p = 0, params = PQnparams(obj->intern->res); p < params; ++p) { + add_next_index_long(return_value, PQparamtype(obj->intern->res, p)); + } + } + } +} + static zend_function_entry php_pqres_methods[] = { PHP_ME(pqres, bind, ai_pqres_bind, ZEND_ACC_PUBLIC) PHP_ME(pqres, fetchBound, ai_pqres_fetch_bound, ZEND_ACC_PUBLIC) @@ -859,9 +911,16 @@ static zend_function_entry php_pqres_methods[] = { PHP_ME(pqres, fetchAll, ai_pqres_fetch_all, ZEND_ACC_PUBLIC) PHP_ME(pqres, count, ai_pqres_count, ZEND_ACC_PUBLIC) PHP_ME(pqres, map, ai_pqres_map, ZEND_ACC_PUBLIC) + PHP_ME(pqres, desc, ai_pqres_desc, ZEND_ACC_PUBLIC) {0} }; +PHP_MSHUTDOWN_FUNCTION(pqres) +{ + zend_hash_destroy(&php_pqres_object_prophandlers); + return SUCCESS; +} + PHP_MINIT_FUNCTION(pqres) { zend_class_entry ce = {0};