summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/mysqlnd/mysqlnd.c66
-rw-r--r--ext/mysqlnd/mysqlnd.h2
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h4
3 files changed, 72 insertions, 0 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index 959f3e0256..ccd8af51c6 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -2761,6 +2761,70 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
/* }}} */
+/* {{{ mysqlnd_conn_data::tx_savepoint */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint)(MYSQLND_CONN_DATA * conn, const char * const name TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_savepoint);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::tx_savepoint");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ char * query;
+ unsigned int query_len;
+ if (!name) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Savepoint name not provided");
+ break;
+ }
+ query_len = mnd_sprintf(&query, 0, "SAVEPOINT `%s`", name);
+ if (!query) {
+ SET_OOM_ERROR(*conn->error_info);
+ break;
+ }
+ ret = conn->m->query(conn, query, query_len TSRMLS_CC);
+ mnd_sprintf_free(query);
+ } while (0);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::tx_savepoint_release */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint_release)(MYSQLND_CONN_DATA * conn, const char * const name TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_savepoint_release);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::tx_savepoint_release");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ char * query;
+ unsigned int query_len;
+ if (!name) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Savepoint name not provided");
+ break;
+ }
+ query_len = mnd_sprintf(&query, 0, "RELEASE SAVEPOINT `%s`", name);
+ if (!query) {
+ SET_OOM_ERROR(*conn->error_info);
+ break;
+ }
+ ret = conn->m->query(conn, query, query_len TSRMLS_CC);
+ mnd_sprintf_free(query);
+ } while (0);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn_data::local_tx_start */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC)
@@ -2878,6 +2942,8 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, tx_begin),
MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback),
MYSQLND_METHOD(mysqlnd_conn_data, tx_cor_options_to_string),
+ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint),
+ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint_release),
MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start),
MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end),
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index 7adf3b6840..40933630ed 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -195,6 +195,8 @@ PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, con
#define mysqlnd_begin_transaction(conn,flags,name) ((conn)->data)->m->tx_begin((conn)->data, (flags), (name) TSRMLS_CC)
#define mysqlnd_commit(conn, flags, name) ((conn)->data)->m->tx_commit_or_rollback((conn)->data, TRUE, (flags), (name) TSRMLS_CC)
#define mysqlnd_rollback(conn, flags, name) ((conn)->data)->m->tx_commit_or_rollback((conn)->data, FALSE, (flags), (name) TSRMLS_CC)
+#define mysqlnd_savepoint(conn, name) ((conn)->data)->m->tx_savepoint((conn)->data, (name) TSRMLS_CC)
+#define mysqlnd_release_savepoint(conn, name) ((conn)->data)->m->tx_savepoint_release((conn)->data, (name) TSRMLS_CC)
#define mysqlnd_list_dbs(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
#define mysqlnd_list_fields(conn, tab,wild) ((conn)->data)->m->list_fields((conn)->data, (tab), (wild) TSRMLS_CC)
#define mysqlnd_list_processes(conn) ((conn)->data)->m->list_method((conn)->data, "SHOW PROCESSLIST", NULL, NULL TSRMLS_CC)
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 7d22dafb8f..55775d97e1 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -486,6 +486,8 @@ typedef enum_func_status (*func_mysqlnd_conn_data__tx_rollback)(MYSQLND_CONN_DAT
typedef enum_func_status (*func_mysqlnd_conn_data__tx_begin)(MYSQLND_CONN_DATA * conn, const unsigned int mode, const char * const name TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_conn_data__tx_commit_or_rollback)(MYSQLND_CONN_DATA * conn, const zend_bool commit, const unsigned int flags, const char * const name TSRMLS_DC);
typedef void (*func_mysqlnd_conn_data__tx_cor_options_to_string)(const MYSQLND_CONN_DATA * const conn, smart_str * tmp_str, const unsigned int mode TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__tx_savepoint)(MYSQLND_CONN_DATA * conn, const char * const name TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__tx_savepoint_release)(MYSQLND_CONN_DATA * conn, const char * const name TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status TSRMLS_DC);
@@ -575,6 +577,8 @@ struct st_mysqlnd_conn_data_methods
func_mysqlnd_conn_data__tx_begin tx_begin;
func_mysqlnd_conn_data__tx_commit_or_rollback tx_commit_or_rollback;
func_mysqlnd_conn_data__tx_cor_options_to_string tx_cor_options_to_string;
+ func_mysqlnd_conn_data__tx_savepoint tx_savepoint;
+ func_mysqlnd_conn_data__tx_savepoint_release tx_savepoint_release;
func_mysqlnd_conn_data__local_tx_start local_tx_start;
func_mysqlnd_conn_data__local_tx_end local_tx_end;