diff options
author | Andrey Hristov <andrey@php.net> | 2014-04-10 16:49:13 +0300 |
---|---|---|
committer | Andrey Hristov <andrey@php.net> | 2014-04-10 16:49:13 +0300 |
commit | 090c3e87c0449e6eadf83815bb57c8a6eff4b56e (patch) | |
tree | 946fdc55ed17d2dc07a99b388565cc96197026dd /ext/mysqli | |
parent | 63791d055ad64762c3f63e08ca7ad8ba1f44e0ab (diff) | |
parent | 3204ad5858a5abc50b11b8527d22c82eb07a80cc (diff) | |
download | php-git-090c3e87c0449e6eadf83815bb57c8a6eff4b56e.tar.gz |
Merge branch 'PHP-5.6' of git.php.net:php-src into PHP-5.6
Conflicts:
ext/mysqli/tests/mysqli_begin_transaction.phpt
Diffstat (limited to 'ext/mysqli')
-rw-r--r-- | ext/mysqli/mysqli.c | 21 | ||||
-rw-r--r-- | ext/mysqli/mysqli_api.c | 82 | ||||
-rw-r--r-- | ext/mysqli/mysqli_nonapi.c | 46 | ||||
-rw-r--r-- | ext/mysqli/tests/mysqli_begin_transaction.phpt | 57 | ||||
-rw-r--r-- | ext/mysqli/tests/mysqli_commit_oo.phpt | 60 |
5 files changed, 169 insertions, 97 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 120c194964..b23d7e3139 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -1297,19 +1297,12 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags fci.symbol_table = NULL; fci.object_ptr = return_value; fci.retval_ptr_ptr = &retval_ptr; + fci.params = NULL; + fci.param_count = 0; + fci.no_separation = 1; + if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) { - if (Z_TYPE_P(ctor_params) == IS_ARRAY) { - HashTable *params_ht = Z_ARRVAL_P(ctor_params); - Bucket *p; - - fci.param_count = 0; - fci.params = safe_emalloc(sizeof(zval*), params_ht->nNumOfElements, 0); - p = params_ht->pListHead; - while (p != NULL) { - fci.params[fci.param_count++] = (zval**)p->pData; - p = p->pListNext; - } - } else { + if (zend_fcall_info_args(&fci, ctor_params TSRMLS_CC) == FAILURE) { /* Two problems why we throw exceptions here: PHP is typeless * and hence passing one argument that's not an array could be * by mistake and the other way round is possible, too. The @@ -1319,11 +1312,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC); return; } - } else { - fci.param_count = 0; - fci.params = NULL; } - fci.no_separation = 1; fcc.initialized = 1; fcc.function_handler = ce->constructor; diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index d14625e0f7..309d9b9f06 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -34,30 +34,31 @@ #include "php_mysqli_structs.h" #include "mysqli_priv.h" + #if !defined(MYSQLI_USE_MYSQLND) /* {{{ mysqli_tx_cor_options_to_string */ static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str * str, const unsigned int mode) { if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) { if (str->len) { - smart_str_appendl(str, ", ", sizeof(", ") - 1); + smart_str_appendl(str, " ", sizeof(" ") - 1); } smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1); } else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) { if (str->len) { - smart_str_appendl(str, ", ", sizeof(", ") - 1); + smart_str_appendl(str, " ", sizeof(" ") - 1); } smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1); } if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) { if (str->len) { - smart_str_appendl(str, ", ", sizeof(", ") - 1); + smart_str_appendl(str, " ", sizeof(" ") - 1); } smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1); } else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) { if (str->len) { - smart_str_appendl(str, ", ", sizeof(", ") - 1); + smart_str_appendl(str, " ", sizeof(" ") - 1); } smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1); } @@ -66,8 +67,50 @@ static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str /* }}} */ -/* {{{ proto bool mysqli_commit_or_rollback_libmysql */ -static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const unsigned int mode, const char * const name) +/* {{{ mysqlnd_escape_string_for_tx_name_in_comment */ +char * +mysqli_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC) +{ + char * ret = NULL; + if (name) { + zend_bool warned = FALSE; + const char * p_orig = name; + char * p_copy; + p_copy = ret = emalloc(strlen(name) + 1 + 2 + 2 + 1); /* space, open, close, NullS */ + *p_copy++ = ' '; + *p_copy++ = '/'; + *p_copy++ = '*'; + while (1) { + register char v = *p_orig; + if (v == 0) { + break; + } + if ((v >= '0' && v <= '9') || + (v >= 'a' && v <= 'z') || + (v >= 'A' && v <= 'Z') || + v == '-' || + v == '_' || + v == ' ' || + v == '=') + { + *p_copy++ = v; + } else if (warned == FALSE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Transaction name truncated. Must be only [0-9A-Za-z\\-_=]+"); + warned = TRUE; + } + ++p_orig; + } + *p_copy++ = '*'; + *p_copy++ = '/'; + *p_copy++ = 0; + } + return ret; +} +/* }}} */ + + +/* {{{ mysqli_commit_or_rollback_libmysql */ +static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const unsigned int mode, const char * const name TSRMLS_DC) { int ret; smart_str tmp_str = {0, 0, 0}; @@ -75,23 +118,27 @@ static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, co smart_str_0(&tmp_str); { - char * commented_name = NULL; - unsigned int commented_name_len = name? spprintf(&commented_name, 0, " /*%s*/", name):0; char * query; - unsigned int query_len = spprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"), - commented_name? commented_name:"", tmp_str.c? tmp_str.c:""); + char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name TSRMLS_CC); + size_t query_len; + + query_len = spprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"), + name_esc? name_esc:"", tmp_str.c? tmp_str.c:""); smart_str_free(&tmp_str); + if (name_esc) { + efree(name_esc); + name_esc = NULL; + } ret = mysql_real_query(conn, query, query_len); efree(query); - if (commented_name) { - efree(commented_name); - } } + return ret; } /* }}} */ #endif + /* {{{ proto mixed mysqli_affected_rows(object link) Get number of affected rows in previous MySQL operation */ PHP_FUNCTION(mysqli_affected_rows) @@ -660,7 +707,7 @@ void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status TSRM if (MyG(rollback_on_cached_plink) && #if !defined(MYSQLI_USE_MYSQLND) - mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL)) + mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL TSRMLS_CC)) #else FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL)) #endif @@ -704,7 +751,8 @@ PHP_FUNCTION(mysqli_close) } /* }}} */ -/* {{{ proto bool mysqli_commit(object link) + +/* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]]) Commit outstanding actions and close transaction */ PHP_FUNCTION(mysqli_commit) { @@ -720,7 +768,7 @@ PHP_FUNCTION(mysqli_commit) MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID); #if !defined(MYSQLI_USE_MYSQLND) - if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name)) { + if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name TSRMLS_CC)) { #else if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) { #endif @@ -1970,7 +2018,7 @@ PHP_FUNCTION(mysqli_rollback) MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID); #if !defined(MYSQLI_USE_MYSQLND) - if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) { + if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name TSRMLS_CC)) { #else if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) { #endif diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 25a88c0984..00cbcf204c 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -1051,12 +1051,14 @@ PHP_FUNCTION(mysqli_get_charset) /* }}} */ #endif - #if !defined(MYSQLI_USE_MYSQLND) +extern char * mysqli_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC); + /* {{{ proto bool mysqli_begin_transaction_libmysql */ -static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name) +static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name TSRMLS_DC) { int ret; + zend_bool err = FALSE; smart_str tmp_str = {0, 0, 0}; if (mode & TRANS_START_WITH_CONSISTENT_SNAPSHOT) { if (tmp_str.len) { @@ -1064,33 +1066,37 @@ static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mo } smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1); } - if (mode & TRANS_START_READ_WRITE) { - if (tmp_str.len) { - smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1); - } - smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1); - } - if (mode & TRANS_START_READ_ONLY) { - if (tmp_str.len) { - smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1); + if (mode & (TRANS_START_READ_WRITE | TRANS_START_READ_ONLY)) { + if (mysql_get_server_version(conn) < 50605L) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required"); + err = TRUE; + } else if (mode & TRANS_START_READ_WRITE) { + if (tmp_str.len) { + smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1); + } + smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1); + } else if (mode & TRANS_START_READ_ONLY) { + if (tmp_str.len) { + smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1); + } + smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1); } - smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1); } smart_str_0(&tmp_str); - { - char * commented_name = NULL; - unsigned int commented_name_len = name? spprintf(&commented_name, 0, " /*%s*/", name):0; + if (err == FALSE){ + char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name TSRMLS_CC); char * query; unsigned int query_len = spprintf(&query, 0, "START TRANSACTION%s %s", - commented_name? commented_name:"", tmp_str.c? tmp_str.c:""); + name_esc? name_esc:"", tmp_str.c? tmp_str.c:""); + smart_str_free(&tmp_str); + if (name_esc) { + efree(name_esc); + } ret = mysql_real_query(conn, query, query_len); efree(query); - if (commented_name) { - efree(commented_name); - } } return ret; } @@ -1125,7 +1131,7 @@ PHP_FUNCTION(mysqli_begin_transaction) } #if !defined(MYSQLI_USE_MYSQLND) - if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name)) { + if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name TSRMLS_CC)) { RETURN_FALSE; } #else diff --git a/ext/mysqli/tests/mysqli_begin_transaction.phpt b/ext/mysqli/tests/mysqli_begin_transaction.phpt index 7e708316b4..c92e718d57 100644 --- a/ext/mysqli/tests/mysqli_begin_transaction.phpt +++ b/ext/mysqli/tests/mysqli_begin_transaction.phpt @@ -67,61 +67,50 @@ if (!have_innodb($link)) var_dump($res->fetch_assoc()); /* valid flags */ - $flags = array( - MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT, - MYSQLI_TRANS_START_READ_WRITE, - MYSQLI_TRANS_START_READ_ONLY, - MYSQLI_TRANS_COR_AND_CHAIN, - MYSQLI_TRANS_COR_AND_NO_CHAIN, - MYSQLI_TRANS_COR_RELEASE, - MYSQLI_TRANS_COR_NO_RELEASE); + $flags = array(MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT); + + if (mysqli_get_server_version($link) >= 50605) { + $flags[] = MYSQLI_TRANS_START_READ_WRITE; + $flags[] = MYSQLI_TRANS_START_READ_ONLY; + } /* just coverage */ foreach ($flags as $flag) { if (!mysqli_begin_transaction($link, $flag, sprintf("flag %d", $flag))) { printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } - if (!mysqli_query($link, 'SELECT * FROM test') || - !mysqli_rollback($link)) { + if (!mysqli_query($link, 'SELECT * FROM test') || !mysqli_rollback($link)) { printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } } /* does it really set a flag? */ - if (mysqli_get_server_version($link) >= 50600) { + if (mysqli_get_server_version($link) >= 50605) { if (!mysqli_begin_transaction($link, MYSQLI_TRANS_START_READ_ONLY, sprintf("flag %d", $flag))) { printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } - if (!mysqli_query($link, "INSERT INTO test(id) VALUES (2)") || - !mysqli_commit($link)) { + if (mysqli_query($link, "INSERT INTO test(id) VALUES (2)")) { printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); + } else if (!mysqli_commit($link)) { + printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } else { $res = mysqli_query($link, "SELECT id FROM test WHERE id = 2"); - var_dump($res->fetch_assoc()); } } - - /* invalid flag */ - do { - $invalid_flag = mt_rand(0, 10000); - } while (isset(array_flip($flags)[$invalid_flag])); - /* we may or may not hit an invalid combination provoking a SQL error */ - if (!mysqli_begin_transaction($link, $invalid_flag, sprintf("flag %d", $invalid_flag))) { - printf("[018] invalid_flag = %d [%d] %s\n", $invalid_flag, mysqli_errno($link), mysqli_error($link)); - } else { - printf("[018] invalid_flag = %d [%d] %s\n", $invalid_flag, mysqli_errno($link), mysqli_error($link)); - } + if (!mysqli_begin_transaction($link, -1)) { printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } - /* does it like stupid names? */ - if (!$link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "*/trick me?\n\0")) - printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); + if (mysqli_get_server_version($link) >= 50605) { + /* does it like stupid names? */ + if (@!$link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "*/trick me?\n\0")) + printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); - /* does it like stupid names? */ - if (!$link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "az09")) - printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); + /* does it like stupid names? */ + if (@!$link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "az09")) + printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); + } print "done!"; ?> @@ -131,10 +120,16 @@ if (!have_innodb($link)) ?> --EXPECTF-- NULL +<<<<<<< HEAD [017] [1792] %s [018] invalid_flag = %d [%d]%A Warning: mysqli_begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d [019] [%d]%A [020] [%d]%A +======= + +Warning: mysqli_begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d +[019] [%d]%A +>>>>>>> 3204ad5858a5abc50b11b8527d22c82eb07a80cc done!
\ No newline at end of file diff --git a/ext/mysqli/tests/mysqli_commit_oo.phpt b/ext/mysqli/tests/mysqli_commit_oo.phpt index e19f698e81..77bcf412e7 100644 --- a/ext/mysqli/tests/mysqli_commit_oo.phpt +++ b/ext/mysqli/tests/mysqli_commit_oo.phpt @@ -21,49 +21,78 @@ if (!have_innodb($link)) $link = NULL; $mysqli = new mysqli(); - if (!is_null($tmp = @$mysqli->commit())) + if (!is_null($tmp = @$mysqli->commit())) { printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp); + } - if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) + if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) { printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket); + } - if (true !== ($tmp = $mysqli->commit())) + if (true !== ($tmp = $mysqli->commit())) { printf("[002] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp); + } - if (true !== ($tmp = $mysqli->autocommit(false))) + if (true !== ($tmp = $mysqli->autocommit(false))) { printf("[003] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp); + } - if (!$mysqli->query('DROP TABLE IF EXISTS test')) + if (!$mysqli->query('DROP TABLE IF EXISTS test')) { printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error); + } - if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB')) + if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB')) { printf("[005] Cannot create test table, [%d] %s\n", $mysqli->errno, $mysqli->error); + } - if (!$mysqli->query('INSERT INTO test(id) VALUES (1)')) + if (!$mysqli->query('INSERT INTO test(id) VALUES (1)')) { printf("[006] [%d] %s\n", $mysqli->errno, $mysqli->error); + } $tmp = $mysqli->commit(); - if ($tmp !== true) + if ($tmp !== true) { printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); + } if (!$mysqli->query('ROLLBACK')) printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error); - if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test')) + if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test')) { printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error); + } + $tmp = $res->fetch_assoc(); - if (1 != $tmp['num']) + if (1 != $tmp['num']) { printf("[010] Expecting 1 row in table test, found %d rows\n", $tmp['num']); + } $res->free(); - if (!$mysqli->query('DROP TABLE IF EXISTS test')) + if (!$mysqli->query('DROP TABLE IF EXISTS test')) { printf("[011] [%d] %s\n", $mysqli->errno, $mysqli->error); + } + + if (!$mysqli->commit(0 , "tx_name0123")) { + printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error); + } + if (!$mysqli->commit(0 , "*/ nonsense")) { + printf("[013] [%d] %s\n", $mysqli->errno, $mysqli->error); + } + if (!$mysqli->commit(0 , "tx_name ulf вендел")) { + printf("[014] [%d] %s\n", $mysqli->errno, $mysqli->error); + } + if (!$mysqli->commit(0 , "tx_name \t\n\r\b")) { + printf("[015] [%d] %s\n", $mysqli->errno, $mysqli->error); + } + if (!$mysqli->commit(MYSQLI_TRANS_COR_AND_CHAIN | MYSQLI_TRANS_COR_NO_RELEASE , "tx_name")) { + printf("[016] [%d] %s\n", $mysqli->errno, $mysqli->error); + } $mysqli->close(); - if (NULL !== ($tmp = @$mysqli->commit())) - printf("[012] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + if (NULL !== ($tmp = @$mysqli->commit())) { + printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + } print "done!"; ?> @@ -72,4 +101,9 @@ if (!have_innodb($link)) require_once("clean_table.inc"); ?> --EXPECTF-- +Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d + +Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d + +Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d done!
\ No newline at end of file |