update from docs
[m6w6/ext-pq] / src / php_pqstm.c
index 016b5b7e6b07428907804548664a67d6d67d03ed..4b71038a63f10167c2266b5d2fb966f834c75707 100644 (file)
@@ -58,6 +58,9 @@ static void php_pqstm_object_free(void *o TSRMLS_DC)
                php_pq_object_delref(obj->intern->conn TSRMLS_CC);
                efree(obj->intern->name);
                zend_hash_destroy(&obj->intern->bound);
+               if (obj->intern->params) {
+                       php_pq_params_free(&obj->intern->params);
+               }
                efree(obj->intern);
                obj->intern = NULL;
        }
@@ -110,7 +113,7 @@ static void php_pqstm_object_read_connection(zval *object, void *o, zval *return
 
 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct, 0, 0, 3)
        ZEND_ARG_OBJ_INFO(0, Connection, pq\\Connection, 0)
-       ZEND_ARG_INFO(0, type)
+       ZEND_ARG_INFO(0, name)
        ZEND_ARG_INFO(0, query)
        ZEND_ARG_ARRAY_INFO(0, types, 1)
        ZEND_ARG_INFO(0, async)
@@ -134,10 +137,12 @@ static PHP_METHOD(pqstm, __construct) {
                if (!conn_obj->intern) {
                        throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
                } else {
+                       php_pq_params_t *params = php_pq_params_init(&conn_obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC);
+
                        if (async) {
-                               rv = php_pqconn_prepare_async(zconn, conn_obj, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC);
+                               rv = php_pqconn_prepare_async(zconn, conn_obj, name_str, query_str, params TSRMLS_CC);
                        } else {
-                               rv = php_pqconn_prepare(zconn, conn_obj, name_str, query_str, ztypes ? Z_ARRVAL_P(ztypes) : NULL TSRMLS_CC);
+                               rv = php_pqconn_prepare(zconn, conn_obj, name_str, query_str, params TSRMLS_CC);
                        }
 
                        if (SUCCESS == rv) {
@@ -146,6 +151,7 @@ static PHP_METHOD(pqstm, __construct) {
                                php_pq_object_addref(conn_obj TSRMLS_CC);
                                stm->conn = conn_obj;
                                stm->name = estrdup(name_str);
+                               stm->params = params;
                                ZEND_INIT_SYMTABLE(&stm->bound);
                                obj->intern = stm;
                        }
@@ -159,8 +165,14 @@ ZEND_END_ARG_INFO();
 static PHP_METHOD(pqstm, bind) {
        long param_no;
        zval *param_ref;
+       zend_error_handling zeh;
+       STATUS rv;
+
+       zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
+       rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &param_no, &param_ref);
+       zend_restore_error_handling(&zeh TSRMLS_CC);
 
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &param_no, &param_ref)) {
+       if (SUCCESS == rv) {
                php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                if (!obj->intern) {
@@ -191,25 +203,11 @@ static PHP_METHOD(pqstm, exec) {
                if (!obj->intern) {
                        throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
                } else {
-                       int count = 0;
-                       char **params = NULL;
-                       HashTable zdtor;
                        PGresult *res;
 
-                       ZEND_INIT_SYMTABLE(&zdtor);
-
-                       if (zparams) {
-                               count = php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &zdtor TSRMLS_CC);
-                       } else {
-                               count = php_pq_params_to_array(&obj->intern->bound, &params, &zdtor TSRMLS_CC);
-                       }
-
-                       res = PQexecPrepared(obj->intern->conn->intern->conn, obj->intern->name, count, (const char *const*) params, NULL, NULL, 0);
-
-                       if (params) {
-                               efree(params);
-                       }
-                       zend_hash_destroy(&zdtor);
+                       php_pq_params_set_params(obj->intern->params, zparams ? Z_ARRVAL_P(zparams) : &obj->intern->bound);
+                       res = PQexecPrepared(obj->intern->conn->intern->conn, obj->intern->name, obj->intern->params->param.count, (const char *const*) obj->intern->params->param.strings, NULL, NULL, 0);
+                       php_pq_params_set_params(obj->intern->params, NULL);
 
                        if (!res) {
                                throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
@@ -241,35 +239,21 @@ static PHP_METHOD(pqstm, execAsync) {
                if (!obj->intern) {
                        throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized");
                } else {
-                       int count;
-                       char **params = NULL;
-                       HashTable zdtor;
+                       int rc;
 
-                       if (zparams) {
-                               ZEND_INIT_SYMTABLE(&zdtor);
-                               count = php_pq_params_to_array(Z_ARRVAL_P(zparams), &params, &zdtor TSRMLS_CC);
-                       }
+                       php_pq_params_set_params(obj->intern->params, zparams ? Z_ARRVAL_P(zparams) : &obj->intern->bound);
+                       rc = PQsendQueryPrepared(obj->intern->conn->intern->conn, obj->intern->name, obj->intern->params->param.count, (const char *const*) obj->intern->params->param.strings, NULL, NULL, 0);
+                       php_pq_params_set_params(obj->intern->params, NULL);
 
-                       if (!PQsendQueryPrepared(obj->intern->conn->intern->conn, obj->intern->name, count, (const char *const*) params, NULL, NULL, 0)) {
+                       if (!rc) {
                                throw_exce(EX_IO TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
                        } else if (obj->intern->conn->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn->intern->conn)) {
                                throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
                        } else {
-                               php_pq_callback_dtor(&obj->intern->conn->intern->onevent);
-                               if (resolver.fci.size > 0) {
-                                       obj->intern->conn->intern->onevent = resolver;
-                                       php_pq_callback_addref(&obj->intern->conn->intern->onevent);
-                               }
+                               php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver TSRMLS_CC);
                                obj->intern->conn->intern->poller = PQconsumeInput;
                        }
 
-                       if (params) {
-                               efree(params);
-                       }
-                       if (zparams) {
-                               zend_hash_destroy(&zdtor);
-                       }
-
                        php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
                }
        }
@@ -311,14 +295,16 @@ static PHP_METHOD(pqstm, desc) {
        }
 }
 
-ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc_async, 0, 0, 0)
+ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc_async, 0, 0, 1)
+       ZEND_ARG_INFO(0, callable)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(pqstm, descAsync) {
        zend_error_handling zeh;
+       php_pq_callback_t resolver = {{0}};
        STATUS rv;
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC);
-       rv = zend_parse_parameters_none();
+       rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", &resolver.fci, &resolver.fcc);
        zend_restore_error_handling(&zeh TSRMLS_CC);
 
        if (SUCCESS == rv) {
@@ -329,6 +315,7 @@ static PHP_METHOD(pqstm, descAsync) {
                } else if (!PQsendDescribePrepared(obj->intern->conn->intern->conn, obj->intern->name)) {
                        throw_exce(EX_IO TSRMLS_CC, "Failed to describe statement: %s", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
                } else {
+                       php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver TSRMLS_CC);
                        obj->intern->conn->intern->poller = PQconsumeInput;
                        php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
                }
@@ -345,6 +332,12 @@ static zend_function_entry php_pqstm_methods[] = {
        {0}
 };
 
+PHP_MSHUTDOWN_FUNCTION(pqstm)
+{
+       zend_hash_destroy(&php_pqstm_object_prophandlers);
+       return SUCCESS;
+}
+
 PHP_MINIT_FUNCTION(pqstm)
 {
        zend_class_entry ce = {0};
@@ -359,6 +352,8 @@ PHP_MINIT_FUNCTION(pqstm)
        php_pqstm_object_handlers.write_property = php_pq_object_write_prop;
        php_pqstm_object_handlers.clone_obj = NULL;
        php_pqstm_object_handlers.get_property_ptr_ptr = NULL;
+       php_pqstm_object_handlers.get_gc = NULL;
+       php_pqstm_object_handlers.get_properties = php_pq_object_properties;
        php_pqstm_object_handlers.get_debug_info = php_pq_object_debug_info;
 
        zend_hash_init(&php_pqstm_object_prophandlers, 2, NULL, NULL, 1);