+ php_pq_object_addref(conn_obj TSRMLS_CC);
+ stm->conn = conn_obj;
+ stm->name = estrdup(name_str);
+ obj->intern = stm;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec, 0, 0, 0)
+ ZEND_ARG_ARRAY_INFO(0, params, 1)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqstm, exec) {
+ zend_error_handling zeh;
+ zval *zparams = NULL;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &zparams)) {
+ php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ if (obj->intern->conn->intern) {
+ int count = 0;
+ char **params = NULL;
+ HashTable zdtor;
+ PGresult *res;
+
+ if (zparams) {
+ ZEND_INIT_SYMTABLE(&zdtor);
+ count = php_pq_params_to_array(Z_ARRVAL_P(zparams), ¶ms, &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);
+ }
+ if (zparams) {
+ zend_hash_destroy(&zdtor);
+ }
+
+ php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
+
+ if (res) {
+ if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
+ php_pqres_t *r = ecalloc(1, sizeof(*r));
+
+ r->res = res;
+ return_value->type = IS_OBJECT;
+ return_value->value.obj = php_pqres_create_object_ex(php_pqres_class_entry, r, NULL TSRMLS_CC);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Statement not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec_async, 0, 0, 0)
+ ZEND_ARG_ARRAY_INFO(0, params, 1)
+ ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqstm, execAsync) {
+ zend_error_handling zeh;
+ zval *zparams = NULL;
+ php_pq_callback_t resolver = {{0}};
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!f", &zparams, &resolver.fci, &resolver.fcc)) {
+ php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ if (obj->intern->conn->intern) {
+ int count;
+ char **params = NULL;
+ HashTable zdtor;
+
+ if (zparams) {
+ ZEND_INIT_SYMTABLE(&zdtor);
+ count = php_pq_params_to_array(Z_ARRVAL_P(zparams), ¶ms, &zdtor TSRMLS_CC);
+ }
+
+ 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);
+ }
+
+ obj->intern->conn->intern->poller = PQconsumeInput;
+
+ if (PQsendQueryPrepared(obj->intern->conn->intern->conn, obj->intern->name, count, (const char *const*) params, NULL, NULL, 0)) {
+ if (obj->intern->conn->intern->unbuffered) {
+ if (!PQsetSingleRowMode(obj->intern->conn->intern->conn)) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ }
+ RETVAL_TRUE;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ RETVAL_FALSE;
+ }
+
+ if (params) {
+ efree(params);
+ }
+ if (zparams) {
+ zend_hash_destroy(&zdtor);
+ }
+
+ php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
+
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ RETVAL_FALSE;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Statement not initialized");
+ RETVAL_FALSE;
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqstm, desc) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ if (obj->intern->conn->intern) {
+ PGresult *res = PQdescribePrepared(obj->intern->conn->intern->conn, obj->intern->name);
+
+ php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
+
+ if (res) {
+ if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
+ int p, params;
+
+ array_init(return_value);
+ for (p = 0, params = PQnparams(res); p < params; ++p) {
+ add_next_index_long(return_value, PQparamtype(res, p));
+ }
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not describe statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Statement not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+static zend_function_entry php_pqstm_methods[] = {
+ PHP_ME(pqstm, __construct, ai_pqstm_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+ PHP_ME(pqstm, exec, ai_pqstm_exec, ZEND_ACC_PUBLIC)
+ PHP_ME(pqstm, desc, ai_pqstm_desc, ZEND_ACC_PUBLIC)
+ PHP_ME(pqstm, execAsync, ai_pqstm_exec_async, ZEND_ACC_PUBLIC)
+ {0}
+};
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_construct, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
+ ZEND_ARG_INFO(0, async)
+ ZEND_ARG_INFO(0, isolation)
+ ZEND_ARG_INFO(0, readonly)
+ ZEND_ARG_INFO(0, deferrable)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, __construct) {
+ zend_error_handling zeh;
+ zval *zconn;
+ long isolation = PHP_PQTXN_READ_COMMITTED;
+ zend_bool async = 0, readonly = 0, deferrable = 0;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|blbb", &zconn, php_pqconn_class_entry, &async, &isolation, &readonly, &deferrable)) {
+ STATUS rv;
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
+
+ if (conn_obj->intern) {
+ if (async) {
+ rv = php_pqconn_start_transaction_async(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC);
+ } else {
+ rv = php_pqconn_start_transaction(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC);
+ }
+
+ if (SUCCESS == rv) {
+ obj->intern = ecalloc(1, sizeof(*obj->intern));
+
+ php_pq_object_addref(conn_obj TSRMLS_CC);
+ obj->intern->conn = conn_obj;
+ obj->intern->isolation = isolation;
+ obj->intern->readonly = readonly;
+ obj->intern->deferrable = deferrable;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_savepoint, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, savepoint) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ char *cmd;
+ PGresult *res;
+
+ spprintf(&cmd, 0, "SAVEPOINT \"%u\"", ++obj->intern->savepoint);
+ res = PQexec(obj->intern->conn->intern->conn, cmd);
+
+ if (res) {
+ php_pqres_success(res TSRMLS_CC);
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to create %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+
+ efree(cmd);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_savepoint_async, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, savepointAsync) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ char *cmd;
+
+ spprintf(&cmd, 0, "SAVEPOINT \"%u\"", ++obj->intern->savepoint);
+ if (!PQsendQuery(obj->intern->conn->intern->conn, cmd)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to create %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+
+ efree(cmd);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_commit, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, commit) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ PGresult *res;
+
+ if (obj->intern->savepoint) {
+ char *cmd;
+
+ spprintf(&cmd, 0, "RELEASE SAVEPOINT \"%u\"", obj->intern->savepoint--);
+ res = PQexec(obj->intern->conn->intern->conn, cmd);
+
+ if (res) {
+ php_pqres_success(res TSRMLS_CC);
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+
+ efree(cmd);
+ } else {
+ res = PQexec(obj->intern->conn->intern->conn, "COMMIT");
+
+ if (res) {
+ php_pqres_success(res TSRMLS_CC);
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to commit transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_commit_async, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, commitAsync) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ obj->intern->conn->intern->poller = PQconsumeInput;
+
+ if (obj->intern->savepoint) {
+ char *cmd;
+
+ spprintf(&cmd, 0, "RELEASE SAVEPOINT \"%u\"", obj->intern->savepoint--);
+ if (!PQsendQuery(obj->intern->conn->intern->conn, cmd)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+
+ efree(cmd);
+ } else {
+ if (!PQsendQuery(obj->intern->conn->intern->conn, "COMMIT")) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to commit transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_rollback, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, rollback) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ PGresult *res;
+
+ if (obj->intern->savepoint) {
+ char *cmd;
+
+ spprintf(&cmd, 0, "ROLLBACK TO SAVEPOINT \"%u\"", obj->intern->savepoint--);
+ res = PQexec(obj->intern->conn->intern->conn, cmd);
+
+ if (res) {
+ php_pqres_success(res TSRMLS_CC);
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+
+ efree(cmd);
+ } else {
+ res = PQexec(obj->intern->conn->intern->conn, "ROLLBACK");
+
+ if (res) {
+ php_pqres_success(res TSRMLS_CC);
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to rollback transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_rollback_async, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, rollbackAsync) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ obj->intern->conn->intern->poller = PQconsumeInput;
+
+ if (obj->intern->savepoint) {
+ char *cmd;
+
+ spprintf(&cmd, 0, "ROLLBACK TO SAVEPOINT \"%u\"", obj->intern->savepoint--);
+ if (!PQsendQuery(obj->intern->conn->intern->conn, cmd)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+
+ efree(cmd);
+ } else {
+ if (!PQsendQuery(obj->intern->conn->intern->conn, "ROLLBACK")) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not rollback transaction (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_export_snapshot, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, exportSnapshot) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ PGresult *res = PQexec(obj->intern->conn->intern->conn, "SELECT pg_export_snapshot()");
+
+ if (res) {
+ if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
+ RETVAL_STRING(PQgetvalue(res, 0, 0), 1);
+ }
+
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_export_snapshot_async, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, exportSnapshotAsync) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ obj->intern->conn->intern->poller = PQconsumeInput;
+
+ if (!PQsendQuery(obj->intern->conn->intern->conn, "SELECT pg_export_snapshot()")) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_import_snapshot, 0, 0, 1)
+ ZEND_ARG_INFO(0, snapshot_id)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, importSnapshot) {
+ zend_error_handling zeh;
+ char *snapshot_str;
+ int snapshot_len;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snapshot_str, &snapshot_len)) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ if (obj->intern->isolation >= PHP_PQTXN_REPEATABLE_READ) {
+ char *cmd, *sid = PQescapeLiteral(obj->intern->conn->intern->conn, snapshot_str, snapshot_len);
+ PGresult *res;
+
+ spprintf(&cmd, 0, "SET TRANSACTION SNAPSHOT %s", sid);
+ res = PQexec(obj->intern->conn->intern->conn, cmd);
+
+ if (res) {
+ php_pqres_success(res TSRMLS_CC);
+ PHP_PQclear(res);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "A transaction must have at least isolation level REPEATABLE READ to be able to import a snapshot");
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_import_snapshot_async, 0, 0, 1)
+ ZEND_ARG_INFO(0, snapshot_id)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, importSnapshotAsync) {
+ zend_error_handling zeh;
+ char *snapshot_str;
+ int snapshot_len;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snapshot_str, &snapshot_len)) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ if (obj->intern->isolation >= PHP_PQTXN_REPEATABLE_READ) {
+ char *sid = PQescapeLiteral(obj->intern->conn->intern->conn, snapshot_str, snapshot_len);
+
+ if (sid) {
+ char *cmd;
+ obj->intern->conn->intern->poller = PQconsumeInput;
+
+ spprintf(&cmd, 0, "SET TRANSACTION SNAPSHOT %s", sid);
+ if (!PQsendQuery(obj->intern->conn->intern->conn, cmd)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to %s (%s)", cmd, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ efree(cmd);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to quote snapshot identifier (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "A transaction must have at least isolation level REPEATABLE READ to be able to import a snapshot");
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_open_lob, 0, 0, 1)
+ ZEND_ARG_INFO(0, oid)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, openLOB) {
+ zend_error_handling zeh;
+ long mode = INV_WRITE|INV_READ, loid;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &loid, &mode)) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ int lofd = lo_open(obj->intern->conn->intern->conn, loid, mode);
+
+ if (lofd >= 0) {
+ php_pqlob_t *lob = ecalloc(1, sizeof(*lob));
+
+ lob->lofd = lofd;
+ lob->loid = loid;
+ php_pq_object_addref(obj TSRMLS_CC);
+ lob->txn = obj;
+
+ return_value->type = IS_OBJECT;
+ return_value->value.obj = php_pqlob_create_object_ex(php_pqlob_class_entry, lob, NULL TSRMLS_CC);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open large object with mode '%s' (%s)",
+ (mode & (INV_READ|INV_WRITE) ? "rw" :
+ (mode & INV_READ ? "r" :
+ (mode & INV_WRITE ? "w" : "-"))),
+ PHP_PQerrorMessage(obj->intern->conn->intern->conn)
+ );
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_create_lob, 0, 0, 0)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, createLOB) {
+ zend_error_handling zeh;
+ long mode = INV_WRITE|INV_READ;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode)) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ Oid loid = lo_creat(obj->intern->conn->intern->conn, mode);
+
+ if (loid != InvalidOid) {
+ int lofd = lo_open(obj->intern->conn->intern->conn, loid, mode);
+
+ if (lofd >= 0) {
+ php_pqlob_t *lob = ecalloc(1, sizeof(*lob));
+ lob->lofd = lofd;
+ lob->loid = loid;
+ php_pq_object_addref(obj TSRMLS_CC);
+ lob->txn = obj;
+
+ return_value->type = IS_OBJECT;
+ return_value->value.obj = php_pqlob_create_object_ex(php_pqlob_class_entry, lob, NULL TSRMLS_CC);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open large object with mode '%s': %s",
+ (mode & (INV_READ|INV_WRITE) ? "rw" :
+ (mode & INV_READ ? "r" :
+ (mode & INV_WRITE ? "w" : "-"))),
+ PHP_PQerrorMessage(obj->intern->conn->intern->conn)
+ );
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to create large object with mode '%s': %s",
+ (mode & (INV_READ|INV_WRITE) ? "rw" :
+ (mode & INV_READ ? "r" :
+ (mode & INV_WRITE ? "w" : "-"))),
+ PHP_PQerrorMessage(obj->intern->conn->intern->conn)
+ );
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_unlink_lob, 0, 0, 1)
+ ZEND_ARG_INFO(0, oid)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqtxn, unlinkLOB) {
+ long loid;
+
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &loid)) {
+ php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ if (1 == lo_unlink(obj->intern->conn->intern->conn, loid)) {
+ RETVAL_TRUE;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to unlink LOB (oid=%ld): %s", loid, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
+ RETVAL_FALSE;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Transaction not initialized");
+ RETVAL_FALSE;
+ }
+ }
+}
+
+static zend_function_entry php_pqtxn_methods[] = {
+ PHP_ME(pqtxn, __construct, ai_pqtxn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+ PHP_ME(pqtxn, commit, ai_pqtxn_commit, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, rollback, ai_pqtxn_rollback, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, commitAsync, ai_pqtxn_commit_async, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, rollbackAsync, ai_pqtxn_rollback_async, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, savepoint, ai_pqtxn_savepoint, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, savepointAsync, ai_pqtxn_savepoint_async, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, exportSnapshot, ai_pqtxn_export_snapshot, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, exportSnapshotAsync, ai_pqtxn_export_snapshot_async, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, importSnapshot, ai_pqtxn_import_snapshot, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, importSnapshotAsync, ai_pqtxn_import_snapshot_async, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, openLOB, ai_pqtxn_open_lob, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, createLOB, ai_pqtxn_create_lob, ZEND_ACC_PUBLIC)
+ PHP_ME(pqtxn, unlinkLOB, ai_pqtxn_unlink_lob, ZEND_ACC_PUBLIC)
+ {0}
+};
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqcancel_construct, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqcancel, __construct) {
+ zend_error_handling zeh;
+ zval *zconn;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zconn, php_pqconn_class_entry)) {
+ php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
+
+ if (conn_obj->intern) {
+ PGcancel *cancel = PQgetCancel(conn_obj->intern->conn);
+
+ if (cancel) {
+ php_pqcancel_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ obj->intern = ecalloc(1, sizeof(*obj->intern));
+ obj->intern->cancel = cancel;
+ php_pq_object_addref(conn_obj TSRMLS_CC);
+ obj->intern->conn = conn_obj;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not acquire cancel (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqcancel_cancel, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqcancel, cancel) {
+ zend_error_handling zeh;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters_none()) {
+ php_pqcancel_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ char err[256];
+
+ if (!PQcancel(obj->intern->cancel, err, sizeof(err))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not request cancellation: %s", err);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Cancel not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+static zend_function_entry php_pqcancel_methods[] = {
+ PHP_ME(pqcancel, __construct, ai_pqcancel_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+ PHP_ME(pqcancel, cancel, ai_pqcancel_cancel, ZEND_ACC_PUBLIC)
+ {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)
+ ZEND_ARG_INFO(0, callable)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqevent, __construct) {
+ zend_error_handling zeh;
+ zval *zconn;
+ char *type_str;
+ int type_len;
+ php_pq_callback_t cb;
+
+ zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Osf", &zconn, php_pqconn_class_entry, &type_str, &type_len, &cb.fci, &cb.fcc)) {
+ php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC);
+
+ if (conn_obj->intern) {
+ php_pqevent_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ 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);
+
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "pq\\Connection not initialized");
+ }
+ }
+ zend_restore_error_handling(&zeh TSRMLS_CC);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(ai_pqevent_trigger, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, args, 1)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqevent, trigger) {
+ zval *args;
+
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &args)) {
+ php_pqevent_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (obj->intern) {
+ zval *rv = NULL;
+
+ if (SUCCESS == zend_fcall_info_call(&obj->intern->cb.fci, &obj->intern->cb.fcc, &rv, args TSRMLS_CC)) {
+ if (rv) {
+ RETVAL_ZVAL(rv, 0, 1);
+ } else {
+ RETVAL_TRUE;
+ }