From d613997b3072b8093bca3fe9d8aca115e2a579aa Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 12 Sep 2014 10:52:18 +0200 Subject: [PATCH] add default propoerties to connection For pq\Result: pq\Connection->$defaultFetchType For pq\Transaction: pq\Connection->$defaultTransactionIsolation pq\Connection->$defaultTransactionReadonly pq\Connection->$defaultTransactionDeferrable --- src/php_pqconn.c | 127 +++++++++++++++++++++++++++++++++++++++++--- src/php_pqconn.h | 4 ++ src/php_pqres.c | 12 +++-- src/php_pqres.h | 1 + src/php_pqtxn.c | 14 +++++ tests/trans002.phpt | 20 ++++++- 6 files changed, 163 insertions(+), 15 deletions(-) diff --git a/src/php_pqconn.c b/src/php_pqconn.c index 5d5da7a..e730dcd 100644 --- a/src/php_pqconn.c +++ b/src/php_pqconn.c @@ -349,6 +349,92 @@ static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *r zend_hash_apply_with_arguments(&obj->intern->eventhandlers TSRMLS_CC, apply_read_event_handlers, 1, Z_ARRVAL_P(return_value) TSRMLS_CC); } +static void php_pqconn_object_read_def_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + RETVAL_LONG(obj->intern->default_fetch_type); +} +static void php_pqconn_object_write_def_fetch_type(zval *object, void *o, zval *value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + zval *zft = value; + + if (Z_TYPE_P(zft) != IS_LONG) { + if (Z_REFCOUNT_P(zft) > 1) { + zval *tmp; + MAKE_STD_ZVAL(tmp); + ZVAL_ZVAL(tmp, zft, 1, 0); + convert_to_long(tmp); + zft = tmp; + } else { + convert_to_long_ex(&zft); + } + } + + obj->intern->default_fetch_type = Z_LVAL_P(zft) & 0x2; /* two bits only */ + + if (zft != value) { + zval_ptr_dtor(&zft); + } +} + +static void php_pqconn_object_read_def_txn_isolation(zval *object, void *o, zval *return_value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + RETVAL_LONG(obj->intern->default_txn_isolation); +} +static void php_pqconn_object_write_def_txn_isolation(zval *object, void *o, zval *value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + zval *zti = value; + + if (Z_TYPE_P(zti) != IS_LONG) { + if (Z_REFCOUNT_P(zti) > 1) { + zval *tmp; + MAKE_STD_ZVAL(tmp); + ZVAL_ZVAL(tmp, zti, 1, 0); + convert_to_long(tmp); + zti = tmp; + } else { + convert_to_long_ex(&zti); + } + } + + obj->intern->default_txn_isolation = Z_LVAL_P(zti) & 0x2; /* two bits only */ + + if (zti != value) { + zval_ptr_dtor(&zti); + } +} + +static void php_pqconn_object_read_def_txn_readonly(zval *object, void *o, zval *return_value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + RETVAL_BOOL(obj->intern->default_txn_readonly); +} +static void php_pqconn_object_write_def_txn_readonly(zval *object, void *o, zval *value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + obj->intern->default_txn_readonly = zend_is_true(value); +} + +static void php_pqconn_object_read_def_txn_deferrable(zval *object, void *o, zval *return_value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + RETVAL_BOOL(obj->intern->default_txn_deferrable); +} +static void php_pqconn_object_write_def_txn_deferrable(zval *object, void *o, zval *value TSRMLS_DC) +{ + php_pqconn_object_t *obj = o; + + obj->intern->default_txn_deferrable = zend_is_true(value); +} + static STATUS php_pqconn_update_socket(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC) { zval *zsocket, zmember; @@ -1559,8 +1645,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqconn, startTransaction) { zend_error_handling zeh; - long isolation = PHP_PQTXN_READ_COMMITTED; - zend_bool readonly = 0, deferrable = 0; + php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED; + zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0; + zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0; STATUS rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); @@ -1568,8 +1656,6 @@ static PHP_METHOD(pqconn, startTransaction) { zend_restore_error_handling(&zeh TSRMLS_CC); if (SUCCESS == rv) { - php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); - rv = php_pqconn_start_transaction(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC); if (SUCCESS == rv) { @@ -1595,16 +1681,17 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqconn, startTransactionAsync) { zend_error_handling zeh; - long isolation = PHP_PQTXN_READ_COMMITTED; - zend_bool readonly = 0, deferrable = 0; + php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + long isolation = obj->intern ? obj->intern->default_txn_isolation : PHP_PQTXN_READ_COMMITTED; + zend_bool readonly = obj->intern ? obj->intern->default_txn_readonly : 0; + zend_bool deferrable = obj->intern ? obj->intern->default_txn_deferrable : 0; STATUS rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lbb", &isolation, &readonly, &deferrable); zend_restore_error_handling(&zeh TSRMLS_CC); - if (SUCCESS == rv) { - php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + if (SUCCESS == rv) { rv = php_pqconn_start_transaction_async(getThis(), obj, isolation, readonly, deferrable TSRMLS_CC); if (SUCCESS == rv) { @@ -1872,6 +1959,30 @@ PHP_MINIT_FUNCTION(pqconn) 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_property_long(php_pqconn_class_entry, ZEND_STRL("defaultFetchType"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + ph.read = php_pqconn_object_read_def_fetch_type; + ph.write = php_pqconn_object_write_def_fetch_type; + zend_hash_add(&php_pqconn_object_prophandlers, "defaultFetchType", sizeof("defaultFetchType"), (void *) &ph, sizeof(ph), NULL); + ph.write = NULL; + + zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultTransactionIsolation"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + ph.read = php_pqconn_object_read_def_txn_isolation; + ph.write = php_pqconn_object_write_def_txn_isolation; + zend_hash_add(&php_pqconn_object_prophandlers, "defaultTransactionIsolation", sizeof("defaultTransactionIsolation"), (void *) &ph, sizeof(ph), NULL); + ph.write = NULL; + + zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionReadonly"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + ph.read = php_pqconn_object_read_def_txn_readonly; + ph.write = php_pqconn_object_write_def_txn_readonly; + zend_hash_add(&php_pqconn_object_prophandlers, "defaultTransactionReadonly", sizeof("defaultTransactionReadonly"), (void *) &ph, sizeof(ph), NULL); + ph.write = NULL; + + zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + ph.read = php_pqconn_object_read_def_txn_deferrable; + ph.write = php_pqconn_object_write_def_txn_deferrable; + zend_hash_add(&php_pqconn_object_prophandlers, "defaultTransactionDeferrable", sizeof("defaultTransactionDeferrable"), (void *) &ph, sizeof(ph), NULL); + ph.write = 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); diff --git a/src/php_pqconn.h b/src/php_pqconn.h index c9f1e15..1a283d0 100644 --- a/src/php_pqconn.h +++ b/src/php_pqconn.h @@ -30,6 +30,10 @@ typedef struct php_pqconn { HashTable eventhandlers; php_pq_callback_t onevent; unsigned unbuffered:1; + unsigned default_fetch_type:2; + unsigned default_txn_isolation:2; + unsigned default_txn_readonly:1; + unsigned default_txn_deferrable:1; } php_pqconn_t; typedef struct php_pqconn_object { diff --git a/src/php_pqres.c b/src/php_pqres.c index 67dac34..b365f3d 100644 --- a/src/php_pqres.c +++ b/src/php_pqres.c @@ -272,8 +272,10 @@ 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->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 +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); } } @@ -600,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); @@ -760,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) { @@ -857,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); diff --git a/src/php_pqres.h b/src/php_pqres.h index 9786249..f5b9b6e 100644 --- a/src/php_pqres.h +++ b/src/php_pqres.h @@ -33,6 +33,7 @@ typedef struct php_pqres { php_pqres_iterator_t *iter; HashTable bound; HashTable converters; + unsigned default_fetch_type:2; } php_pqres_t; typedef struct php_pqres_object { diff --git a/src/php_pqtxn.c b/src/php_pqtxn.c index 41b4950..fcf7a4b 100644 --- a/src/php_pqtxn.c +++ b/src/php_pqtxn.c @@ -229,6 +229,20 @@ static PHP_METHOD(pqtxn, __construct) { if (!conn_obj->intern) { throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized"); } else { + + switch (ZEND_NUM_ARGS()) { + case 1: + case 2: + isolation = conn_obj->intern->default_txn_isolation; + /* no break */ + case 3: + readonly = conn_obj->intern->default_txn_readonly; + /* no break */ + case 4: + deferrable = conn_obj->intern->default_txn_deferrable; + break; + } + if (async) { rv = php_pqconn_start_transaction_async(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC); } else { diff --git a/tests/trans002.phpt b/tests/trans002.phpt index b06fb01..d65cde5 100644 --- a/tests/trans002.phpt +++ b/tests/trans002.phpt @@ -29,7 +29,7 @@ var_dump( DONE --EXPECTF-- Test -object(pq\Connection)#%d (14) { +object(pq\Connection)#%d (18) { ["status"]=> int(0) ["transactionStatus"]=> @@ -59,11 +59,19 @@ object(pq\Connection)#%d (14) { ["eventHandlers"]=> array(0) { } + ["defaultFetchType"]=> + int(0) + ["defaultTransactionIsolation"]=> + int(0) + ["defaultTransactionReadonly"]=> + bool(false) + ["defaultTransactionDeferrable"]=> + bool(false) } int(0) bool(false) bool(false) -object(pq\Connection)#%d (14) { +object(pq\Connection)#%d (18) { ["status"]=> int(0) ["transactionStatus"]=> @@ -93,6 +101,14 @@ object(pq\Connection)#%d (14) { ["eventHandlers"]=> array(0) { } + ["defaultFetchType"]=> + int(0) + ["defaultTransactionIsolation"]=> + int(0) + ["defaultTransactionReadonly"]=> + bool(false) + ["defaultTransactionDeferrable"]=> + bool(false) } int(2) bool(true) -- 2.30.2