From: Michael Wallner Date: Thu, 14 Feb 2013 13:54:22 +0000 (+0100) Subject: tests & fixes X-Git-Tag: v0.1.0~12 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=commitdiff_plain;h=3024b0b5a903a2bcb082b01e1787410dc9508a9d tests & fixes --- diff --git a/src/php_pq.c b/src/php_pq.c index fda1313..a0d18a5 100644 --- a/src/php_pq.c +++ b/src/php_pq.c @@ -49,8 +49,12 @@ static int php_pqconn_event(PGEventId id, void *e, void *data); #define PHP_PQclear(_r) \ do { \ - zval *_resinszv = PQresultInstanceData((_r), php_pqconn_event); \ - if (!_resinszv) PQclear((_r)); \ + php_pqres_object_t *_o = PQresultInstanceData((_r), php_pqconn_event); \ + if (_o) { \ + php_pq_object_delref(_o TSRMLS_CC); \ + } else { \ + PQclear(_r); \ + } \ } while (0) /* @@ -89,7 +93,6 @@ static zend_class_entry *php_pqlob_class_entry; static zend_class_entry *php_pqcopy_class_entry; typedef enum php_pqexc_type { - EX_DEFAULT, EX_INVALID_ARGUMENT, EX_RUNTIME, EX_CONNECTION_FAILED, @@ -102,7 +105,6 @@ typedef enum php_pqexc_type { } php_pqexc_type_t; static zend_class_entry *php_pqexc_interface_class_entry; -static zend_class_entry *php_pqexc_default_class_entry; static zend_class_entry *php_pqexc_invalid_argument_class_entry; static zend_class_entry *php_pqexc_runtime_class_entry; static zend_class_entry *php_pqexc_bad_methodcall_class_entry; @@ -111,9 +113,7 @@ static zend_class_entry *php_pqexc_domain_class_entry; static zend_class_entry *exce(php_pqexc_type_t type) { switch (type) { - case EX_DEFAULT: default: - return php_pqexc_default_class_entry; case EX_INVALID_ARGUMENT: return php_pqexc_invalid_argument_class_entry; case EX_RUNTIME: @@ -283,8 +283,8 @@ typedef struct php_pqcancel_object { typedef struct php_pqevent { php_pq_callback_t cb; - php_pqconn_object_t *conn; char *type; + ulong h; } php_pqevent_t; typedef struct php_pqevent_object { @@ -396,10 +396,14 @@ static STATUS 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); - if (PQresultStatus(obj->intern->res) != PGRES_TUPLES_OK) { - return FAILURE; - } - if (PQntuples(obj->intern->res) <= iter->index) { + switch (PQresultStatus(obj->intern->res)) { + case PGRES_TUPLES_OK: + case PGRES_SINGLE_TUPLE: + if (PQntuples(obj->intern->res) <= iter->index) { + return FAILURE; + } + break; + default: return FAILURE; } @@ -543,6 +547,40 @@ static STATUS php_pqres_success(PGresult *res TSRMLS_DC) } } +/* +static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id TSRMLS_DC) +{ + zval **evhs; + + if (SUCCESS == zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) { + zend_hash_index_del(Z_ARRVAL_PP(evhs), id); + } +} +*/ + +static ulong php_pqconn_add_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, zval *zevent TSRMLS_DC) +{ + zval **evhs; + ulong h; + + if (SUCCESS == zend_hash_find(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) { + Z_ADDREF_P(zevent); + h = zend_hash_next_free_element(Z_ARRVAL_PP(evhs)); + add_next_index_zval(*evhs, zevent); + } else { + zval *evh; + + MAKE_STD_ZVAL(evh); + array_init(evh); + Z_ADDREF_P(zevent); + h = zend_hash_next_free_element(Z_ARRVAL_P(evh)); + add_next_index_zval(evh, zevent); + zend_hash_add(&obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evh, sizeof(zval *), NULL); + } + + return h; +} + static void php_pq_callback_dtor(php_pq_callback_t *cb) { if (cb->fci.size > 0) { zend_fcall_info_args_clear(&cb->fci, 1); @@ -576,6 +614,20 @@ static void php_pq_object_to_zval(void *o, zval **zv TSRMLS_DC) (*zv)->value.obj = obj->zv; } +static void php_pq_object_to_zval_no_addref(void *o, zval **zv TSRMLS_DC) +{ + php_pq_object_t *obj = o; + + if (!*zv) { + MAKE_STD_ZVAL(*zv); + } + + /* no add ref */ + + (*zv)->type = IS_OBJECT; + (*zv)->value.obj = obj->zv; +} + static void php_pq_object_addref(void *o TSRMLS_DC) { php_pq_object_t *obj = o; @@ -591,7 +643,9 @@ static void php_pq_object_delref(void *o TSRMLS_DC) static void php_pqconn_object_free(void *o TSRMLS_DC) { php_pqconn_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE conn(#%d) %p\n", obj->zv.handle, obj); +#endif if (obj->intern) { php_resource_factory_handle_dtor(&obj->intern->factory, obj->intern->conn TSRMLS_CC); php_resource_factory_dtor(&obj->intern->factory); @@ -608,7 +662,9 @@ static void php_pqconn_object_free(void *o TSRMLS_DC) static void php_pqtypes_object_free(void *o TSRMLS_DC) { php_pqtypes_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE types(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); +#endif if (obj->intern) { zend_hash_destroy(&obj->intern->types); php_pq_object_delref(obj->intern->conn TSRMLS_CC); @@ -622,19 +678,14 @@ static void php_pqtypes_object_free(void *o TSRMLS_DC) static void php_pqres_object_free(void *o TSRMLS_DC) { php_pqres_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE res(#%d) %p\n", obj->zv.handle, obj); +#endif if (obj->intern) { if (obj->intern->res) { - zval *res = PQresultInstanceData(obj->intern->res, php_pqconn_event); - if (res) { - if (1 == Z_REFCOUNT_P(res)) { - PQresultSetInstanceData(obj->intern->res, php_pqconn_event, NULL); - } - zval_ptr_dtor(&res); - } else { - PQclear(obj->intern->res); - obj->intern->res = NULL; - } + PQresultSetInstanceData(obj->intern->res, php_pqconn_event, NULL); + PQclear(obj->intern->res); + obj->intern->res = NULL; } if (obj->intern->iter) { @@ -654,7 +705,9 @@ static void php_pqres_object_free(void *o TSRMLS_DC) static void php_pqstm_object_free(void *o TSRMLS_DC) { php_pqstm_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE stm(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); +#endif if (obj->intern) { char *quoted_name = PQescapeIdentifier(obj->intern->conn->intern->conn, obj->intern->name, strlen(obj->intern->name)); @@ -688,7 +741,9 @@ static void php_pqstm_object_free(void *o TSRMLS_DC) static void php_pqtxn_object_free(void *o TSRMLS_DC) { php_pqtxn_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE txn(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); +#endif if (obj->intern) { if (obj->intern->open) { PGresult *res = PQexec(obj->intern->conn->intern->conn, "ROLLBACK"); @@ -708,7 +763,9 @@ static void php_pqtxn_object_free(void *o TSRMLS_DC) static void php_pqcancel_object_free(void *o TSRMLS_DC) { php_pqcancel_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE cancel(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); +#endif if (obj->intern) { PQfreeCancel(obj->intern->cancel); php_pq_object_delref(obj->intern->conn TSRMLS_CC); @@ -722,10 +779,11 @@ static void php_pqcancel_object_free(void *o TSRMLS_DC) static void php_pqevent_object_free(void *o TSRMLS_DC) { php_pqevent_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE event(#%d) %p\n", obj->zv.handle, obj); +#endif if (obj->intern) { php_pq_callback_dtor(&obj->intern->cb); - php_pq_object_delref(obj->intern->conn TSRMLS_CC); efree(obj->intern->type); efree(obj->intern); obj->intern = NULL; @@ -737,7 +795,9 @@ static void php_pqevent_object_free(void *o TSRMLS_DC) static void php_pqlob_object_free(void *o TSRMLS_DC) { php_pqlob_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE lob(#%d) %p (txn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->txn->zv.handle, obj->intern->txn); +#endif if (obj->intern) { if (obj->intern->lofd) { lo_close(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd); @@ -753,7 +813,9 @@ static void php_pqlob_object_free(void *o TSRMLS_DC) static void php_pqcopy_object_free(void *o TSRMLS_DC) { php_pqcopy_object_t *obj = o; - +#if DBG_GC + fprintf(stderr, "FREE copy(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); +#endif if (obj->intern) { efree(obj->intern->expression); efree(obj->intern->options); @@ -1017,36 +1079,16 @@ static zend_object_value php_pqcopy_create_object(zend_class_entry *class_type T return php_pqcopy_create_object_ex(class_type, NULL, NULL TSRMLS_CC); } -static int apply_ph_to_debug(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) -{ - php_pq_object_prophandler_t *ph = p; - HashTable *ht = va_arg(argv, HashTable *); - zval **return_value, *object = va_arg(argv, zval *); - php_pq_object_t *obj = va_arg(argv, php_pq_object_t *); - - if (SUCCESS == zend_hash_find(ht, key->arKey, key->nKeyLength, (void *) &return_value)) { - - if (ph->read) { - zval_ptr_dtor(return_value); - MAKE_STD_ZVAL(*return_value); - ZVAL_NULL(*return_value); - - ph->read(object, obj, *return_value TSRMLS_CC); - } - } - - return ZEND_HASH_APPLY_KEEP; -} - -static int apply_pi_to_debug(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +static int apply_pi_to_ht(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) { zend_property_info *pi = p; HashTable *ht = va_arg(argv, HashTable *); zval *object = va_arg(argv, zval *); php_pq_object_t *obj = va_arg(argv, php_pq_object_t *); + int addref = va_arg(argv, int); zval *property = zend_read_property(obj->zo.ce, object, pi->name, pi->name_length, 0 TSRMLS_CC); - if (1||!Z_REFCOUNT_P(property)) { + if (addref) { Z_ADDREF_P(property); } zend_hash_add(ht, pi->name, pi->name_length + 1, (void *) &property, sizeof(zval *), NULL); @@ -1063,8 +1105,7 @@ static HashTable *php_pq_object_debug_info(zval *object, int *temp TSRMLS_DC) ALLOC_HASHTABLE(ht); ZEND_INIT_SYMTABLE(ht); - zend_hash_apply_with_arguments(&obj->zo.ce->properties_info TSRMLS_CC, apply_pi_to_debug, 3, ht, object, obj); - zend_hash_apply_with_arguments(obj->prophandler TSRMLS_CC, apply_ph_to_debug, 3, ht, object, obj); + zend_hash_apply_with_arguments(&obj->zo.ce->properties_info TSRMLS_CC, apply_pi_to_ht, 4, ht, object, obj, 1); return ht; } @@ -1160,7 +1201,15 @@ static void php_pqconn_object_write_encoding(zval *object, void *o, zval *value zval *zenc = value; if (Z_TYPE_P(value) != IS_STRING) { - convert_to_string_ex(&zenc); + if (Z_REFCOUNT_P(value) > 1) { + zval *tmp; + MAKE_STD_ZVAL(tmp); + ZVAL_ZVAL(tmp, zenc, 1, 0); + convert_to_string(tmp); + zenc = tmp; + } else { + convert_to_string_ex(&zenc); + } } if (0 > PQsetClientEncoding(obj->intern->conn, Z_STRVAL_P(zenc))) { @@ -1186,7 +1235,7 @@ static void php_pqconn_object_write_unbuffered(zval *object, void *o, zval *valu obj->intern->unbuffered = zend_is_true(value); } -static void php_pqconn_object_read_db(zval *objec, void *o, zval *return_value TSRMLS_DC) +static void php_pqconn_object_read_db(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqconn_object_t *obj = o; char *db = PQdb(obj->intern->conn); @@ -1198,7 +1247,7 @@ static void php_pqconn_object_read_db(zval *objec, void *o, zval *return_value T } } -static void php_pqconn_object_read_user(zval *objec, void *o, zval *return_value TSRMLS_DC) +static void php_pqconn_object_read_user(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqconn_object_t *obj = o; char *user = PQuser(obj->intern->conn); @@ -1210,7 +1259,7 @@ static void php_pqconn_object_read_user(zval *objec, void *o, zval *return_value } } -static void php_pqconn_object_read_pass(zval *objec, void *o, zval *return_value TSRMLS_DC) +static void php_pqconn_object_read_pass(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqconn_object_t *obj = o; char *pass = PQpass(obj->intern->conn); @@ -1222,7 +1271,7 @@ static void php_pqconn_object_read_pass(zval *objec, void *o, zval *return_value } } -static void php_pqconn_object_read_host(zval *objec, void *o, zval *return_value TSRMLS_DC) +static void php_pqconn_object_read_host(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqconn_object_t *obj = o; char *host = PQhost(obj->intern->conn); @@ -1234,7 +1283,7 @@ static void php_pqconn_object_read_host(zval *objec, void *o, zval *return_value } } -static void php_pqconn_object_read_port(zval *objec, void *o, zval *return_value TSRMLS_DC) +static void php_pqconn_object_read_port(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqconn_object_t *obj = o; char *port = PQport(obj->intern->conn); @@ -1246,7 +1295,7 @@ static void php_pqconn_object_read_port(zval *objec, void *o, zval *return_value } } -static void php_pqconn_object_read_options(zval *objec, void *o, zval *return_value TSRMLS_DC) +static void php_pqconn_object_read_options(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqconn_object_t *obj = o; char *options = PQoptions(obj->intern->conn); @@ -1258,6 +1307,14 @@ static void php_pqconn_object_read_options(zval *objec, void *o, zval *return_va } } +static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *return_value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + array_init(return_value); + zend_hash_copy(Z_ARRVAL_P(return_value), &obj->intern->eventhandlers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); +} + static void php_pqtypes_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqtypes_object_t *obj = o; @@ -1265,7 +1322,7 @@ static void php_pqtypes_object_read_connection(zval *object, void *o, zval *retu php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC); } -static int has_dimension(HashTable *ht, zval *member, char **key_str, int *key_len, long *index TSRMLS_DC) +static int has_dimension(HashTable *ht, zval *member, char **key_str, int *key_len, ulong *index TSRMLS_DC) { long lval = 0; zval *tmp = member; @@ -1276,18 +1333,21 @@ static int has_dimension(HashTable *ht, zval *member, char **key_str, int *key_l /* no break */ case IS_STRING: if (!is_numeric_string(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &lval, NULL, 0)) { - if (member != tmp) { - zval_ptr_dtor(&tmp); - } + int exists = zend_hash_exists(ht, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) + 1); + if (key_str) { *key_str = estrndup(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); if (key_len) { *key_len = Z_STRLEN_P(tmp) + 1; } } - return zend_hash_exists(ht, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) + 1); + if (member != tmp) { + zval_ptr_dtor(&tmp); + } + + return exists; } - /* no break */ + break; case IS_LONG: lval = Z_LVAL_P(member); break; @@ -1307,7 +1367,7 @@ static int php_pqtypes_object_has_dimension(zval *object, zval *member, int chec php_pqtypes_object_t *obj = zend_object_store_get_object(object TSRMLS_CC); char *key_str = NULL; int key_len = 0; - long index = 0; + ulong index = 0; if (check_empty) { if (has_dimension(&obj->intern->types, member, &key_str, &key_len, &index TSRMLS_CC)) { @@ -1320,11 +1380,14 @@ static int php_pqtypes_object_has_dimension(zval *object, zval *member, int chec } efree(key_str); } else { - if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) data)) { + if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) &data)) { return Z_TYPE_PP(data) != IS_NULL; } } } + if (key_str) { + efree(key_str); + } } else { return has_dimension(&obj->intern->types, member, NULL, NULL, NULL TSRMLS_CC); } @@ -1334,7 +1397,7 @@ static int php_pqtypes_object_has_dimension(zval *object, zval *member, int chec static zval *php_pqtypes_object_read_dimension(zval *object, zval *member, int type TSRMLS_DC) { - long index = 0; + ulong index = 0; char *key_str = NULL; int key_len = 0; php_pqtypes_object_t *obj = zend_object_store_get_object(object TSRMLS_CC); @@ -1352,6 +1415,9 @@ static zval *php_pqtypes_object_read_dimension(zval *object, zval *member, int t return *data; } } + if (key_str) { + efree(key_str); + } } return NULL; @@ -1420,8 +1486,16 @@ static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value php_pqres_object_t *obj = o; zval *zfetch_type = value; - if (Z_TYPE_P(zfetch_type) != IS_LONG) { - convert_to_long_ex(&zfetch_type); + if (Z_TYPE_P(value) != IS_LONG) { + if (Z_REFCOUNT_P(value) > 1) { + zval *tmp; + MAKE_STD_ZVAL(tmp); + ZVAL_ZVAL(tmp, zfetch_type, 1, 0); + convert_to_long(tmp); + zfetch_type = tmp; + } else { + convert_to_long_ex(&zfetch_type); + } } if (!obj->intern->iter) { @@ -1467,14 +1541,14 @@ static void php_pqtxn_object_read_readonly(zval *object, void *o, zval *return_v { php_pqtxn_object_t *obj = o; - RETVAL_LONG(obj->intern->readonly); + RETVAL_BOOL(obj->intern->readonly); } static void php_pqtxn_object_read_deferrable(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqtxn_object_t *obj = o; - RETVAL_LONG(obj->intern->deferrable); + RETVAL_BOOL(obj->intern->deferrable); } static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value TSRMLS_DC) @@ -1485,18 +1559,26 @@ static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value PGresult *res; if (Z_TYPE_P(zisolation) != IS_LONG) { - convert_to_long_ex(&zisolation); + if (Z_REFCOUNT_P(value) > 1) { + zval *tmp; + MAKE_STD_ZVAL(tmp); + ZVAL_ZVAL(tmp, zisolation, 1, 0); + convert_to_long(tmp); + zisolation = tmp; + } else { + convert_to_long_ex(&zisolation); + } } switch ((obj->intern->isolation = Z_LVAL_P(zisolation))) { case PHP_PQTXN_READ_COMMITTED: - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION READ COMMITED"); + res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL READ COMMITED"); break; case PHP_PQTXN_REPEATABLE_READ: - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION REPEATABLE READ"); + res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); break; case PHP_PQTXN_SERIALIZABLE: - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION SERIALIZABLE"); + res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); break; default: obj->intern->isolation = orig; @@ -1555,13 +1637,6 @@ static void php_pqcancel_object_read_connection(zval *object, void *o, zval *ret php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC); } -static void php_pqevent_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC) -{ - php_pqevent_object_t *obj = o; - - php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC); -} - static void php_pqevent_object_read_type(zval *object, void *o, zval *return_value TSRMLS_DC) { php_pqevent_object_t *obj = o; @@ -1732,24 +1807,20 @@ static void php_pqconn_event_connreset(PGEventConnReset *event) } } -static zval *result_instance_zval(PGresult *res TSRMLS_DC) +static void php_pqres_init_instance_data(PGresult *res, php_pqres_object_t **ptr TSRMLS_DC) { - zval *rid = PQresultInstanceData(res, php_pqconn_event); + php_pqres_object_t *obj; + php_pqres_t *r = ecalloc(1, sizeof(*r)); - if (!rid) { - 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); - MAKE_STD_ZVAL(rid); - r->res = res; - ZEND_INIT_SYMTABLE(&r->bound); - rid->type = IS_OBJECT; - rid->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC); + PQresultSetInstanceData(res, php_pqconn_event, obj); - PQresultSetInstanceData(res, php_pqconn_event, rid); + if (ptr) { + *ptr = obj; } - - Z_ADDREF_P(rid); - return rid; } static void php_pqconn_event_resultcreate(PGEventResultCreate *event) @@ -1757,17 +1828,21 @@ static void php_pqconn_event_resultcreate(PGEventResultCreate *event) php_pqconn_event_data_t *data = PQinstanceData(event->conn, php_pqconn_event); if (data) { + php_pqres_object_t *obj; zval **evhs; TSRMLS_DF(data); + php_pqres_init_instance_data(event->result, &obj TSRMLS_CC); + /* event listener */ if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("result"), (void *) &evhs)) { - zval *args, *connection = NULL, *res = result_instance_zval(event->result TSRMLS_CC); + zval *args, *connection = NULL, *res = NULL; MAKE_STD_ZVAL(args); array_init(args); php_pq_object_to_zval(data->obj, &connection TSRMLS_CC); add_next_index_zval(args, connection); + php_pq_object_to_zval(obj, &res TSRMLS_CC); add_next_index_zval(args, res); zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs), apply_event, args TSRMLS_CC); zval_ptr_dtor(&args); @@ -1775,12 +1850,23 @@ static void php_pqconn_event_resultcreate(PGEventResultCreate *event) /* async callback */ if (data->obj->intern->onevent.fci.size > 0) { - zval *res = result_instance_zval(event->result TSRMLS_CC); + zval *res = NULL; + php_pq_object_to_zval(obj, &res TSRMLS_CC); zend_fcall_info_argn(&data->obj->intern->onevent.fci TSRMLS_CC, 1, &res); zend_fcall_info_call(&data->obj->intern->onevent.fci, &data->obj->intern->onevent.fcc, NULL, NULL TSRMLS_CC); zval_ptr_dtor(&res); } + + } +} + +static void php_pqconn_event_resultdestroy(PGEventResultDestroy *event) +{ + php_pqres_object_t *obj = PQresultInstanceData(event->result, php_pqconn_event); + + if (obj) { + obj->intern->res = NULL; } } @@ -1793,6 +1879,9 @@ static int php_pqconn_event(PGEventId id, void *e, void *data) case PGEVT_RESULTCREATE: php_pqconn_event_resultcreate(e); break; + case PGEVT_RESULTDESTROY: + php_pqconn_event_resultdestroy(e); + break; default: break; } @@ -2297,12 +2386,9 @@ static PHP_METHOD(pqconn, exec) { if (!res) { throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn)); } else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - php_pqres_t *r = ecalloc(1, sizeof(*r)); - - r->res = res; - ZEND_INIT_SYMTABLE(&r->bound); - return_value->type = IS_OBJECT; - return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC); + php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC); + } else { + PHP_PQclear(res); } php_pqconn_notify_listeners(obj TSRMLS_CC); @@ -2331,12 +2417,7 @@ static PHP_METHOD(pqconn, getResult) { if (!res) { RETVAL_NULL(); } else { - php_pqres_t *r = ecalloc(1, sizeof(*r)); - - r->res = res; - ZEND_INIT_SYMTABLE(&r->bound); - return_value->type = IS_OBJECT; - return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC); + php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC); } php_pqconn_notify_listeners(obj TSRMLS_CC); @@ -2527,12 +2608,9 @@ static PHP_METHOD(pqconn, execParams) { throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn)); } else { if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - php_pqres_t *r = ecalloc(1, sizeof(*r)); - - r->res = res; - ZEND_INIT_SYMTABLE(&r->bound); - return_value->type = IS_OBJECT; - return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC); + php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC); + } else { + PHP_PQclear(res); } php_pqconn_notify_listeners(obj TSRMLS_CC); @@ -3741,13 +3819,7 @@ static PHP_METHOD(pqstm, exec) { if (!res) { throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - php_pqres_t *r = ecalloc(1, sizeof(*r)); - - r->res = res; - ZEND_INIT_SYMTABLE(&r->bound); - return_value->type = IS_OBJECT; - return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC); - + php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC); php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); } } @@ -4552,24 +4624,6 @@ static zend_function_entry php_pqcancel_methods[] = { {0} }; -static void php_pqconn_add_eventhandler(zval *zconn, php_pqconn_object_t *conn_obj, const char *type_str, size_t type_len, zval *zevent TSRMLS_DC) -{ - zval **evhs; - - if (SUCCESS == zend_hash_find(&conn_obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evhs)) { - Z_ADDREF_P(zevent); - add_next_index_zval(*evhs, zevent); - } else { - zval *evh; - - MAKE_STD_ZVAL(evh); - array_init(evh); - Z_ADDREF_P(zevent); - add_next_index_zval(evh, zevent); - zend_hash_add(&conn_obj->intern->eventhandlers, type_str, type_len + 1, (void *) &evh, sizeof(zval *), NULL); - } -} - ZEND_BEGIN_ARG_INFO_EX(ai_pqevent_construct, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0) ZEND_ARG_INFO(0, type) @@ -4598,11 +4652,8 @@ static PHP_METHOD(pqevent, __construct) { obj->intern = ecalloc(1, sizeof(*obj->intern)); php_pq_callback_addref(&cb); obj->intern->cb = cb; - php_pq_object_addref(conn_obj TSRMLS_CC); - obj->intern->conn = conn_obj; obj->intern->type = estrdup(type_str); - - php_pqconn_add_eventhandler(zconn, conn_obj, type_str, type_len, getThis() TSRMLS_CC); + obj->intern->h = php_pqconn_add_eventhandler(conn_obj, type_str, type_len, getThis() TSRMLS_CC); } } } @@ -5086,10 +5137,15 @@ static PHP_MINIT_FUNCTION(pq) INIT_NS_CLASS_ENTRY(ce, "pq", "Exception", php_pqexc_methods); php_pqexc_interface_class_entry = zend_register_internal_interface(&ce TSRMLS_CC); - memset(&ce, 0, sizeof(ce)); - INIT_NS_CLASS_ENTRY(ce, "pq\\Exception", "Exception", php_pqexc_methods); - php_pqexc_default_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), "Exception" TSRMLS_CC); - zend_class_implements(php_pqexc_default_class_entry TSRMLS_CC, 1, php_pqexc_interface_class_entry); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("INVALID_ARGUMENT"), EX_INVALID_ARGUMENT TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("RUNTIME"), EX_RUNTIME TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("CONNECTION_FAILED"), EX_CONNECTION_FAILED TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("IO"), EX_IO TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("ESCAPE"), EX_ESCAPE TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("BAD_METHODCALL"), EX_BAD_METHODCALL TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("UNINITIALIZED"), EX_UNINITIALIZED TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("DOMAIN"), EX_DOMAIN TSRMLS_CC); + zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("SQL"), EX_SQL TSRMLS_CC); memset(&ce, 0, sizeof(ce)); INIT_NS_CLASS_ENTRY(ce, "pq\\Exception", "InvalidArgumentException", php_pqexc_methods); @@ -5124,7 +5180,7 @@ static PHP_MINIT_FUNCTION(pq) php_pqconn_object_handlers.get_property_ptr_ptr = NULL; php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqconn_object_prophandlers, 13, NULL, NULL, 1); + zend_hash_init(&php_pqconn_object_prophandlers, 14, NULL, NULL, 1); zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC TSRMLS_CC); ph.read = php_pqconn_object_read_status; @@ -5182,6 +5238,10 @@ static PHP_MINIT_FUNCTION(pq) ph.read = php_pqconn_object_read_options; zend_hash_add(&php_pqconn_object_prophandlers, "options", sizeof("options"), (void *) &ph, sizeof(ph), NULL); + zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC TSRMLS_CC); + ph.read = php_pqconn_object_read_event_handlers; + zend_hash_add(&php_pqconn_object_prophandlers, "eventHandlers", sizeof("eventHandlers"), (void *) &ph, sizeof(ph), NULL); + zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC); zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC); zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC); @@ -5334,19 +5394,19 @@ static PHP_MINIT_FUNCTION(pq) ph.write = php_pqtxn_object_write_isolation; zend_hash_add(&php_pqtxn_object_prophandlers, "isolation", sizeof("isolation"), (void *) &ph, sizeof(ph), NULL); - zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("readonly"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_bool(php_pqtxn_class_entry, ZEND_STRL("readonly"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); ph.read = php_pqtxn_object_read_readonly; ph.write = php_pqtxn_object_write_readonly; zend_hash_add(&php_pqtxn_object_prophandlers, "readonly", sizeof("readonly"), (void *) &ph, sizeof(ph), NULL); - zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("deferrable"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_bool(php_pqtxn_class_entry, ZEND_STRL("deferrable"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); ph.read = php_pqtxn_object_read_deferrable; ph.write = php_pqtxn_object_write_deferrable; zend_hash_add(&php_pqtxn_object_prophandlers, "deferrable", sizeof("deferrable"), (void *) &ph, sizeof(ph), NULL); ph.write = NULL; zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("READ_COMMITTED"), PHP_PQTXN_READ_COMMITTED TSRMLS_CC); - zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("REPEATABLE READ"), PHP_PQTXN_REPEATABLE_READ TSRMLS_CC); + zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("REPEATABLE_READ"), PHP_PQTXN_REPEATABLE_READ TSRMLS_CC); zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("SERIALIZABLE"), PHP_PQTXN_SERIALIZABLE TSRMLS_CC); memset(&ce, 0, sizeof(ce)); @@ -5379,11 +5439,7 @@ static PHP_MINIT_FUNCTION(pq) php_pqevent_object_handlers.get_property_ptr_ptr = NULL; php_pqevent_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqevent_object_prophandlers, 2, NULL, NULL, 1); - - zend_declare_property_null(php_pqevent_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC); - ph.read = php_pqevent_object_read_connection; - zend_hash_add(&php_pqevent_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL); + zend_hash_init(&php_pqevent_object_prophandlers, 1, NULL, NULL, 1); zend_declare_property_null(php_pqevent_class_entry, ZEND_STRL("type"), ZEND_ACC_PUBLIC TSRMLS_CC); ph.read = php_pqevent_object_read_type; diff --git a/tests/_setup.inc b/tests/_setup.inc index 0af687a..4fb26f8 100644 --- a/tests/_setup.inc +++ b/tests/_setup.inc @@ -1,2 +1,2 @@ getMessage()); +} diff --git a/tests/basic001.phpt b/tests/basic001.phpt index 8712cb9..4bea211 100644 --- a/tests/basic001.phpt +++ b/tests/basic001.phpt @@ -14,6 +14,7 @@ $res = $con->exec("SELECT 1 as one, 2 as two from generate_series(1,2)"); var_dump($res->status == pq\Result::TUPLES_OK); var_dump($res->numRows); var_dump($res->numCols); +var_dump(count($res) == $res->count(), $res->numRows == count($res)); foreach ($res as $rowNum => $rowData) { printf("%d.0 => %d\n", $rowNum, $rowData[0]); @@ -36,6 +37,8 @@ Test bool(true) int(2) int(2) +bool(true) +bool(true) 0.0 => 1 0.1 => 2 1.0 => 1 diff --git a/tests/cancel001.phpt b/tests/cancel001.phpt index e1c9bb3..89c4931 100644 --- a/tests/cancel001.phpt +++ b/tests/cancel001.phpt @@ -17,7 +17,7 @@ $c->execAsync("SELECT pg_sleep(2)"); $x->cancel(); var_dump($c->getResult()); - +printf("%s\n", $c->errorMessage); ?> DONE --EXPECTF-- @@ -38,4 +38,5 @@ object(pq\Result)#%d (7) { ["fetchType"]=> int(0) } +ERROR: canceling statement due to user request DONE diff --git a/tests/encoding001.phpt b/tests/encoding001.phpt new file mode 100644 index 0000000..57f24c5 --- /dev/null +++ b/tests/encoding001.phpt @@ -0,0 +1,28 @@ +--TEST-- +encoding +--SKIPIF-- + +--FILE-- +encoding); +$c->encoding = "utf8"; +var_dump($c->encoding); +var_dump($c->exec("SELECT 'ßüpä…'")->fetchCol()); +$tmp = 12345; +$c->encoding = $tmp; +var_dump($c->encoding); +?> +DONE +--EXPECTF-- +Test +string(%d) "%s" +string(4) "UTF8" +string(10) "ßüpä…" + +Notice: Unrecognized encoding '12345' in %s on line %d +string(4) "UTF8" +DONE diff --git a/tests/exceptions001.phpt b/tests/exceptions001.phpt new file mode 100644 index 0000000..ac643ff --- /dev/null +++ b/tests/exceptions001.phpt @@ -0,0 +1,51 @@ +--TEST-- +exceptions +--SKIPIF-- + +--FILE-- +getCode() == pq\Exception::INVALID_ARGUMENT, $e->getCode()."!=".pq\Exception::INVALID_ARGUMENT); +} +try { + new pq\Connection(1,2,3,4); + foo(); +} catch (pq\Exception\InvalidArgumentException $e) { + assert($e->getCode() == pq\Exception::INVALID_ARGUMENT, $e->getCode()."!=".pq\Exception::INVALID_ARGUMENT); +} + +class c extends pq\Connection { + function __construct() { + } + function open($dsn) { + parent::__construct($dsn); + } +} +$c = new c; +try { + $c->reset(); + foo(); +} catch (pq\Exception\BadMethodCallException $e) { + assert($e->getCode() == pq\Exception::UNINITIALIZED, $e->getCode()."!=".pq\Exception::UNINITIALIZED); +} + +$c->open(PQ_DSN); +try { + $c->open(PQ_DSN); + foo(); +} catch (pq\Exception\BadMethodCallException $e) { + assert($e->getCode() == pq\Exception::BAD_METHODCALL, $e->getCode()."!=".pq\Exception::BAD_METHODCALL); +} + +?> +DONE +--EXPECT-- +Test +DONE diff --git a/tests/exceptions002.phpt b/tests/exceptions002.phpt new file mode 100644 index 0000000..8954571 --- /dev/null +++ b/tests/exceptions002.phpt @@ -0,0 +1,26 @@ +--TEST-- +sql exception +--SKIPIF-- + +--FILE-- +exec("SELECT 1 FROM probably_non_existent_table"); +} catch (pq\Exception $e) { + var_dump($e instanceof pq\Exception\DomainException); + var_dump($e->getCode() == pq\Exception::SQL); + var_dump($e->sqlstate); +} +?> +DONE +--EXPECT-- +Test +bool(true) +bool(true) +string(5) "42P01" +DONE diff --git a/tests/fetch001.phpt b/tests/fetch001.phpt new file mode 100644 index 0000000..31494c6 --- /dev/null +++ b/tests/fetch001.phpt @@ -0,0 +1,54 @@ +--TEST-- +fetch type +--SKIPIF-- + +--FILE-- +exec("SELECT a,b, NULL as c from generate_series(1,2) a, generate_series(2,4) b"); + +$r->fetchType = pq\Result::FETCH_ARRAY; +foreach ($r as $k => $v) { + printf("%s => %s,%s,%s\n", $k, $v[0], $v[1], $v[2]); + $r->fetchType = (string) $r->fetchType; +} + +$r->fetchType = pq\Result::FETCH_ASSOC; +foreach ($r as $k => $v) { + printf("%s => %s,%s,%s\n", $k, $v["a"], $v["b"], $v["c"]); + $r->fetchType = (string) $r->fetchType; +} + +$r->fetchType = pq\Result::FETCH_OBJECT; +foreach ($r as $k => $v) { + printf("%s => %s,%s,%s\n", $k, $v->a, $v->b, $v->c); + $r->fetchType = (string) $r->fetchType; +} + +?> +DONE +--EXPECT-- +Test +0 => 1,2, +1 => 1,3, +2 => 1,4, +3 => 2,2, +4 => 2,3, +5 => 2,4, +0 => 1,2, +1 => 1,3, +2 => 1,4, +3 => 2,2, +4 => 2,3, +5 => 2,4, +0 => 1,2, +1 => 1,3, +2 => 1,4, +3 => 2,2, +4 => 2,3, +5 => 2,4, +DONE diff --git a/tests/info001.phpt b/tests/info001.phpt new file mode 100644 index 0000000..a16c59c --- /dev/null +++ b/tests/info001.phpt @@ -0,0 +1,23 @@ +--TEST-- +connection info +--SKIPIF-- + +--FILE-- +db, + $c->user, + $c->pass, + $c->host, + $c->port, + $c->options +); +?> +DONE +--EXPECTF-- +Test +%s +DONE diff --git a/tests/lob001.phpt b/tests/lob001.phpt index e1f5a15..7f91f64 100644 --- a/tests/lob001.phpt +++ b/tests/lob001.phpt @@ -1,7 +1,7 @@ --TEST-- large objects --SKIPIF-- - + --FILE-- startTransaction(); $lob = $t->createLOB(); $lob->write(file_get_contents(__FILE__)); var_dump($lob->tell()); + $lob->seek(0, SEEK_SET); $dat = $lob->read(filesize(__FILE__)); -var_dump(hash("md5", $dat)); -var_dump(hash_file("md5", __FILE__)); +var_dump(hash("md5", $dat)==hash_file("md5", __FILE__)); + $lob->truncate(5); + $lob = new pq\Lob($t, $lob->oid); var_dump($lob->read(123)); + +$t->commit(); +$t->unlinkLOB($lob->oid); + ?> DONE ---EXPECT-- +--EXPECTF-- Test -int(416) -string(32) "d422937493386635bd56b9a9885e7614" -string(32) "d422937493386635bd56b9a9885e7614" -string(5) "listen("chan", function($chan, $msg) { + // dummy + }); + $e = new pq\Event($c, pq\Event::RESULT, function($c, $res) { + }); } + + if (!($i%10)) gc_collect_cycles(); $c->exec(""); } @@ -23,7 +30,7 @@ DONE --EXPECTF-- Test array(1) { - ["%s"]=> + ["%S"]=> array(2) { ["used"]=> int(1) diff --git a/tests/reset001.phpt b/tests/reset001.phpt index 359b1a8..9527ccb 100644 --- a/tests/reset001.phpt +++ b/tests/reset001.phpt @@ -11,6 +11,7 @@ include "_setup.inc"; $c = new pq\Connection(PQ_DSN); $c->reset(); var_dump($c->status); +new pq\Event($c, pq\Event::RESET, function ($c) { print "RESET!\n"; }); $c->reset(); var_dump($c->status); @@ -19,5 +20,6 @@ DONE --EXPECT-- Test int(0) +RESET! int(0) DONE diff --git a/tests/trans001.phpt b/tests/trans001.phpt index d927d2e..719bcb3 100644 --- a/tests/trans001.phpt +++ b/tests/trans001.phpt @@ -13,7 +13,9 @@ $c->exec("DROP TABLE IF EXISTS test"); new pq\Event($c, pq\Event::NOTICE, function($c, $notice) { echo "Got notice: $notice\n"; }); +var_dump($c->transactionStatus == pq\Connection::TRANS_IDLE); $t = new pq\Transaction($c); +var_dump($t->connection->transactionStatus == pq\Connection::TRANS_INTRANS); $c->exec("DROP TABLE IF EXISTS test"); $c->exec("CREATE TABLE test (id serial, data text)"); $s = $c->prepare("test_insert", "INSERT INTO test (data) VALUES (\$1)", array((new pq\Types($c))["text"]->oid)); @@ -25,13 +27,17 @@ while ($row = $r->fetchRow(pq\Result::FETCH_OBJECT)) { printf("%d => %s\n", $row->id, $row->data); } $t->rollback(); +var_dump($c->transactionStatus == pq\Connection::TRANS_IDLE); ?> DONE --EXPECT-- Test +bool(true) +bool(true) Got notice: NOTICE: table "test" does not exist, skipping Got notice: NOTICE: CREATE TABLE will create implicit sequence "test_id_seq" for serial column "test.id" 1 => a 2 => b 3 => c +bool(true) DONE diff --git a/tests/trans002.phpt b/tests/trans002.phpt new file mode 100644 index 0000000..b06fb01 --- /dev/null +++ b/tests/trans002.phpt @@ -0,0 +1,100 @@ +--TEST-- +txn properties +--SKIPIF-- + +--FILE-- +connection, + $t->isolation, + $t->readonly, + $t->deferrable +); + +$t->isolation = pq\Transaction::SERIALIZABLE; +$t->readonly = true; +$t->deferrable = true; +var_dump( + $t->connection, + $t->isolation, + $t->readonly, + $t->deferrable +); +?> +DONE +--EXPECTF-- +Test +object(pq\Connection)#%d (14) { + ["status"]=> + int(0) + ["transactionStatus"]=> + int(2) + ["socket"]=> + resource(%d) of type (stream) + ["errorMessage"]=> + string(0) "" + ["busy"]=> + bool(false) + ["encoding"]=> + string(4) "%s" + ["unbuffered"]=> + bool(false) + ["db"]=> + string(4) "%S" + ["user"]=> + string(4) "%S" + ["pass"]=> + string(0) "%S" + ["host"]=> + string(0) "%S" + ["port"]=> + string(4) "%S" + ["options"]=> + string(0) "%S" + ["eventHandlers"]=> + array(0) { + } +} +int(0) +bool(false) +bool(false) +object(pq\Connection)#%d (14) { + ["status"]=> + int(0) + ["transactionStatus"]=> + int(2) + ["socket"]=> + resource(%d) of type (stream) + ["errorMessage"]=> + string(0) "" + ["busy"]=> + bool(false) + ["encoding"]=> + string(4) "%s" + ["unbuffered"]=> + bool(false) + ["db"]=> + string(4) "%S" + ["user"]=> + string(4) "%S" + ["pass"]=> + string(0) "%S" + ["host"]=> + string(0) "%S" + ["port"]=> + string(4) "%S" + ["options"]=> + string(0) "%S" + ["eventHandlers"]=> + array(0) { + } +} +int(2) +bool(true) +bool(true) +DONE diff --git a/tests/types001.phpt b/tests/types001.phpt new file mode 100644 index 0000000..951bf1f --- /dev/null +++ b/tests/types001.phpt @@ -0,0 +1,31 @@ +--TEST-- +types functionality +--SKIPIF-- + +--FILE-- +connection === $c); +var_dump(isset($t["int4"]), empty($t["int4"])); +var_dump(isset($t["whatthahell"]), empty($t["whatthahell"])); + +var_dump(isset($t[25]), empty($t[25])); +var_dump(isset($t[0]), empty($t[0])); +?> +DONE +--EXPECT-- +Test +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +DONE diff --git a/tests/unbuffered001.phpt b/tests/unbuffered001.phpt new file mode 100644 index 0000000..0754d8a --- /dev/null +++ b/tests/unbuffered001.phpt @@ -0,0 +1,62 @@ +--TEST-- +unbuffered result +--SKIPIF-- + +--FILE-- +unbuffered ? true : false); +$c->unbuffered = 1; +var_dump($c->unbuffered); + +$c->execAsync("SELECT a from generate_series(1,10) a", function($res) { + switch ($res->status) { + case pq\Result::SINGLE_TUPLE: + printf("%s\n", $res->fetchCol()); + break; + case pq\Result::TUPLES_OK: + printf("-> fetching done\n"); + break; + default: + printf("!! %s\n", $res->errorMessage); + break; + } +}); +do { + while ($c->busy) { + switch ($c->poll()) { + case pq\Connection::POLLING_READING: + $w=$e=array(); + $r=array($c->socket); + stream:select($r,$w,$e,1); + break; + case pq\Connection::POLLING_WRITING: + $r=$e=array(); + $w=array($c->socket); + stream_select($r,$w,$e,1); + break; + } + } +} while ($c->getResult()); +?> +DONE +--EXPECTF-- +Test +bool(false) +bool(true) +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +-> fetching done +DONE