package.xml0000664000175000017500000021250412161007456012531 0ustar andreyandrey mysqlnd_ms pecl.php.net A replication and load balancing plugin for mysqlnd The mysqlnd_ms replication and load balancing plugin can be used with PHP MySQL extensions (ext/mysql, ext/mysqli, ext/pdo_mysql) if they are compiled to use mysqlnd. The plugin inspects queries and does read-write splitting. Read-only queries are sent to MySQL replication slave servers while all other queries are redirected to the MySQL replication master server. Very few, if any, application changes are required, depending on the usage scenario. Andrey Hristov andrey andrey@php_net yes Ulf Wendel uw uw@php_net yes Johannes Schlüter johannes johannes@php.net yes 2013-06-21 1.5.2 1.5.0 stable stable PHP License Fix hardcoded version number 5.3.6-dev 1.4.0 mysqlnd_ms 1.5.2 1.5.0 GA GA 2013-06-21 PHP License Fix hardcoded version number 1.5.1 1.5.0 GA GA 2013-06-18 PHP License GA release 1.5.0 1.5.0 alpha alpha 2012-08-15 PHP License alpha 1.4.1 1.4.0 beta beta 2012-08-01 PHP License Beta release, stable API, for testing 1.4.0 1.4.0 alpha alpha 2012-07-16 PHP License Small change to fix the build in case MS is built/used together with QC 1.3.1 1.3.0 alpha alpha 2012-04-16 PHP License Small change to fix the build in case MS is built/used together with QC 1.3.0 1.3.0 alpha alpha 2012-04-12 PHP License New feature release with QoS and QC integration 1.2.1 1.2.0 beta beta 2012-01-24 PHP License beta release 1.2.0 1.2.0 alpha alpha 2011-12-14 PHP License Global Transaction ID injection and quality-of-service concept 1.1.2 1.1.0 stable stable 2011-11-04 PHP License Fixed the build for 5.4. Declaring the code as stable. Refer to CHANGES for more information 1.1.1 1.1.0 beta stable 2011-10-11 PHP License The same as 1.1.0 code-wise. A note added to config.m4 for an experimental and currently unsupported option 1.1.0 1.1.0 beta stable 2011-09-29 PHP License Numerous feature enhancements. Refer to CHANGES for more information 1.0.1 1.0.0 alpha stable 2011-04-21 PHP License Fixed debug build (credits to Vladimir Getmanshchuk). All 1.0 features implemented. 1.0.0 1.0.0 alpha stable 2011-04-20 PHP License Initial package release. All 1.0 features implemented. mysqlnd_ms-1.5.2/examples/config.php0000664000175000017500000000012612161007456017032 0ustar andreyandrey mysqlnd_ms-1.5.2/examples/failover.php0000664000175000017500000000520012161007456017372 0ustar andreyandreyquery($query); /* After the query has been send, $conn either points to master or slave. By recording the connection thread id we can reverse-engineer which queries have been send via which connection. One cannot tell based on the thread id if a connection is a master or slave connection but common sense will tell you if you look at the recorded data... */ if (!isset($queries[$conn->thread_id])) $queries[$conn->thread_id] = array($query); else $queries[$conn->thread_id][] = $query; if (!$ret) /* KLUDGE - you will do proper error handling, won't you? */ die(sprintf("[%d] %s\n", $conn->errno, $conn->error)); return $ret; } require_once("./config.php"); printf("\n"); if (!($conn = new mysqli("myapp", DB_USER, DB_PASSWORD, DB_SCHEMA)) || mysqli_connect_errno()) { die(sprintf("Please check the *config.json used and config.php, failed to connect: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); } $queries = array(); printf("Creating a test table. Statements should be send to the master...\n"); run_query($conn, "DROP TABLE IF EXISTS test"); run_query($conn, "CREATE TABLE test(id INT)"); run_query($conn, "INSERT INTO test(id) VALUES (1)"); printf("Dumping list of connections. Should be only one, the master connection...\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("\nRunning a SELECT, it should be send to the slaves...\n"); printf("NOTE: A warning is emitted but script continues without interruption. You can suppress the warning using @. The plugin cannot control it.\n"); $res = run_query($conn, "SELECT '\tWarning but resultset' AS _hint FROM DUAL"); $row = $res->fetch_assoc(); echo $row['_hint'] . "\n"; printf("\nRunning SELECT but plugin has learned that slave1 is unavailable...\n"); $res = run_query($conn, "SELECT '\tNo warning' AS _hint FROM DUAL"); $row = $res->fetch_assoc(); echo $row['_hint'] . "\n"; printf("\nDropping the test table. Statement should be send to the master...\n"); run_query($conn, "DROP TABLE IF EXISTS test"); printf("\nDumping list of connections. Should be two: master and slave...\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("\n"); ?>mysqlnd_ms-1.5.2/examples/multi_master.php0000664000175000017500000000325512161007456020300 0ustar andreyandreyquery($query); /* After the query has been send, $conn either points to master or slave. By recording the connection thread id we can reverse-engineer which queries have been send via which connection. One cannot tell based on the thread id if a connection is a master or slave connection but common sense will tell you if you look at the recorded data... */ if (!isset($queries[$conn->thread_id])) $queries[$conn->thread_id] = array($query); else $queries[$conn->thread_id][] = $query; if (!$ret) /* KLUDGE - you will do proper error handling, won't you? */ die(sprintf("[%d] %s\n", $conn->errno, $conn->error)); return $ret; } require_once("./config.php"); printf("\n"); if (!($conn = new mysqli("myapp", DB_USER, DB_PASSWORD, DB_SCHEMA)) || mysqli_connect_errno()) { die(sprintf("Please check the *config.json used and config.php, failed to connect: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); } $queries = array(); printf("Running some statements in a roundrobin fashion\n"); run_query($conn, "SELECT 'Query 1, round robin: master1'"); run_query($conn, "SELECT 'Query 2, round robin: master2'"); run_query($conn, "SELECT 'Query 3, round robin: master1'"); printf("Dumping list of connections. Should be two. Queries distributed in a roundrobin fashion.\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("\n"); ?>mysqlnd_ms-1.5.2/examples/mysqlnd_ms_multi_master_config.json0000664000175000017500000000061012161007456024245 0ustar andreyandrey{ "myapp": { "master": { "master_1": { "host": "localhost", "socket": "\/tmp\/mysql57.sock" }, "master_2": { "host": "192.168.2.28", "port": 3306 } }, "slave": { }, "filters": { "roundrobin": { } }, "failover": { "strategy": "loop_before_master", "remember_failed": true } } }mysqlnd_ms-1.5.2/examples/mysqlnd_ms_single_master_config_failover.json0000664000175000017500000000077412161007456026276 0ustar andreyandrey{ "myapp": { "master": { "master_1": { "host": "localhost", "socket": "\/tmp\/mysql57.sock" } }, "slave": { "slave_0": { "host": "unavailable_to_trigger_failover", "port": 9999 }, "slave_1": { "host": "192.168.2.28", "port": 3306 } }, "filters": { "random": { "sticky": "1" } }, "failover": { "strategy": "loop_before_master", "remember_failed": true } } }mysqlnd_ms-1.5.2/examples/mysqlnd_ms_single_master_config.json0000664000175000017500000000060712161007456024402 0ustar andreyandrey{ "myapp": { "master": { "master_1": { "host": "localhost", "socket": "\/tmp\/mysql57.sock" } }, "slave": { "slave_0": { "host": "127.0.0.1", "port": 3308 }, "slave_1": { "host": "192.168.2.28", "port": 3306 } }, "filters": { "random": { "sticky": "1" } } } }mysqlnd_ms-1.5.2/examples/mysqlnd_ms_single_master_config_sharding.json0000664000175000017500000000076312161007456026264 0ustar andreyandrey{ "myapp": { "master": { "master_1": { "host": "localhost", "socket": "\/tmp\/mysql57.sock" } }, "slave": { "slave_0": { "host": "127.0.0.1", "port": 3308 }, "slave_1": { "host": "192.168.2.28", "port": 3306 } }, "filters": { "node_groups": { "Partition_A" : { "master": ["master_1"], "slave": ["slave_0"] } }, "roundrobin": [] } } }mysqlnd_ms-1.5.2/examples/README0000664000175000017500000000726012161007456015742 0ustar andreyandreyThe examples try to help you getting started with the mysqlnd plugin. *Find more in the manual!* Please, find more examples at: http://php.net/mysqlnd_ms The examples given here cover a fraction of the functionality only. Explanations are kept to a bare minimum. *Preconditions* Make sure you have compiled PHP with PECL/mysqlnd_ms support, the extension is loaded and the PHP MySQL extensions are configured to use the mysqlnd library when building PHP: ./configure --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --enable-mysqlnd-ms If you are unfamiliar with the mysqlnd library, please consult the PHP manual: http://php.net/mysqlnd_ms *Setup* Edit the server settings in the configuration file you plan to use: mysqlnd_ms_single_master_config.json mysqlnd_ms_single_master_config_client_failover.json mysqlnd_ms_multi_master_config.json mysqlnd_ms_single_master_config_sharding.json Use the single_master configuration files if running a lazy primary copy (asynchronous master slave) cluster of MySQL such as MySQL Replication. Use the multi_master configuration file if running a non-lazy update-anywhere (synchronous multi master) cluster of MySQL, for example, MySQL Cluster. Further cluster topologies are supported but beyond the scope of the examples. Edit the server settings. It is assumed that you have configured one MySQL user on all servers using the same password on all servers. Using different users on different servers is explained in the documentation. Edit config.php to set username and password. All examples include config.php. *Running* The examples and tests make use of the mysqli extension and its API. mysqli is the most feature-complete of the three PHP MySQL extensions (mysql, mysqli, PDO_MYSQL). Because PECL/mysqlnd_ms is a plugin for the mysqlnd library and all of the three PHP MySQL extensions can be configured to use the mysqlnd library "under the hood" at the C level, the plugin can be used with any of the three extensions. However, mysqli is the most powerful of the breed and I'm familiar with it. Thus, I'm always using mysqli in the examples and in the tests. Single master with read-write splitting enabled: php -d mysqlnd_ms.enable=1 \ -d mysqlnd_ms.config_file=mysqlnd_ms_single_master_config.json \ rw_split.php Single master with failover (see documentation notes!): php -d mysqlnd_ms.enable=1 \ -d mysqlnd_ms.config_file=mysqlnd_ms_single_master_config_failover.json \ failover.php Single master with manual partitioning/sharding (see documentation notes!): php -d mysqlnd_ms.enable=1 \ -d mysqlnd_ms.config_file=mysqlnd_ms_single_master_config_sharding.json \ sharding.php Multi master with read-write splitting disabled: php -d mysqlnd_ms.enable=1 \ -d mysqlnd_ms.multi_master=1 \ -d mysqlnd_ms.disable_rw_split=1 \ -d mysqlnd_ms.config_file=mysqlnd_ms_multi_master_config.json \ multi_master.php *Pitfall* Unfortunately the plugin cannot emit a proper warning if a config file is not a valid JSON document! Instead you will get an error message such as: Warning: mysqli::mysqli(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /home/nixnutz/php-src/pecl/mysqlnd_ms/trunk/examples/multi_master.php on line 34 Warning: mysqli::mysqli(): (HY000/2002): php_network_getaddresses: getaddrinfo failed: Name or service not known in /home/nixnutz/php-src/pecl/mysqlnd_ms/trunk/examples/multi_master.php on line 34 Please check the *config.json used and config.php, failed to connect: [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known Thus, double check your changes if you make edits to the configuration files! mysqlnd_ms-1.5.2/examples/rw_split.php0000664000175000017500000000417312161007456017436 0ustar andreyandreyquery($query); /* After the query has been send, $conn either points to master or slave. By recording the connection thread id we can reverse-engineer which queries have been send via which connection. One cannot tell based on the thread id if a connection is a master or slave connection but common sense will tell you if you look at the recorded data... */ if (!isset($queries[$conn->thread_id])) $queries[$conn->thread_id] = array($query); else $queries[$conn->thread_id][] = $query; if (!$ret) /* KLUDGE - you will do proper error handling, won't you? */ die(sprintf("[%d] %s\n", $conn->errno, $conn->error)); return $ret; } require_once("./config.php"); printf("\n"); if (!($conn = new mysqli("myapp", DB_USER, DB_PASSWORD, DB_SCHEMA)) || mysqli_connect_errno()) { die(sprintf("Please check the *config.json used and config.php, failed to connect: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); } $queries = array(); printf("Creating a test table. Statements should be send to the master...\n"); run_query($conn, "DROP TABLE IF EXISTS test"); run_query($conn, "CREATE TABLE test(id INT)"); run_query($conn, "INSERT INTO test(id) VALUES (1)"); printf("Dumping list of connections. Should be only one, the master connection...\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("Running a SELECT, it should be send to the slaves...\n"); run_query($conn, "SELECT 1 FROM DUAL"); printf("Dropping the test table. Statement should be send to the master...\n"); run_query($conn, "DROP TABLE IF EXISTS test"); printf("Dumping list of connections. Should be two: master and slave...\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("\n"); ?>mysqlnd_ms-1.5.2/examples/sharding.php0000664000175000017500000000621312161007456017367 0ustar andreyandreyquery($query); /* After the query has been send, $conn either points to master or slave. By recording the connection thread id we can reverse-engineer which queries have been send via which connection. One cannot tell based on the thread id if a connection is a master or slave connection but common sense will tell you if you look at the recorded data... */ if (!isset($queries[$conn->thread_id])) $queries[$conn->thread_id] = array($query); else $queries[$conn->thread_id][] = $query; if (!$ret) /* KLUDGE - you will do proper error handling, won't you? */ die(sprintf("[%d] %s\n", $conn->errno, $conn->error)); return $ret; } require_once("./config.php"); printf("\n"); if (!($conn = new mysqli("myapp", DB_USER, DB_PASSWORD, DB_SCHEMA)) || mysqli_connect_errno()) { die(sprintf("Please check the *config.json used and config.php, failed to connect: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); } $queries = array(); printf("Creating a test table. Statements should be send to the master...\n"); run_query($conn, "DROP TABLE IF EXISTS test"); run_query($conn, "CREATE TABLE test(id INT)"); run_query($conn, "INSERT INTO test(id) VALUES (1)"); printf("Dumping list of connections. Should be only one, the master connection...\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("Running a SELECT, it should be send to the first slave...\n"); run_query($conn, "SELECT 'slave1' FROM DUAL"); printf("Running a SELECT, it should be send to the second slave because of round robin...\n"); run_query($conn, "SELECT 'slave2' FROM DUAL"); printf("Dumping list of connections. Should be three: master and both slaves, one SELECT on each slave\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf("\n"); printf("Running a SELECT, it should be send the slaves configured for partition A only. This is the first slave only...\n"); run_query($conn, "/*Partition_A*/SELECT 'slave1' FROM DUAL"); printf("Running a SELECT, it should be send the slaves configured for partition A only. This is the first slave only...\n"); run_query($conn, "/*Partition_A*/SELECT 'slave1' FROM DUAL"); printf("Dumping list of connections. Should be three: master and both slaves, three queries for slave one, one query for slave two\n"); foreach ($queries as $thread_id => $details) { printf("\t... Connection %d has run\n", $thread_id); foreach ($details as $query) printf("\t\t... %s\n", $query); } printf(" If everything has gone right, you should see how the queries prefixed with the SQL hint /*Partition_A*/ have been executed on the only slave that can handle this partition. This can be used for partitioning, including manual sharding but also to work around hotspots.\n"); printf("\n"); ?>mysqlnd_ms-1.5.2/tests/bench/framework/web/rb_create_csv.php0000664000175000017500000001554612161007456023557 0ustar andreyandreygetRunList(); $binaries = (isset($_REQUEST['binaries'])) ? $_REQUEST['binaries'] : NULL; $binarylist = ($run_id) ? $storage->getBinaryList($run_id) : NULL; $labels = (isset($_REQUEST['labels'])) ? $_REQUEST['labels'] : NULL; $labellist = ($binaries) ? $storage->getMeasuredTimeLabels($run_id) : NULL; if ($run_id && $binaries && $labels) { $lines = array(); $sep = ';'; $first = true; foreach ($binaries as $k => $run_id) { $run_info = $storage->getRunInfoByRunID($run_id); if ($first) { $line = ''; foreach ($run_info as $label => $v) $line .= sprintf("%s%s", $label, $sep); $line = substr($line, 0, strlen($sep) * -1); $lines[] = $line; $first = false; } $lines[] = implode($sep, $run_info); } $lines[] = ''; $file = sys_get_temp_dir() . '/version.php'; $fp = fopen($file, 'w'); fwrite($fp, ''); fclose($fp); $line1 = $line2 = $line3 = $line4 = ''; $line_bin_label = $sep; $mysqlnd_run_id = null; foreach ($binaries as $k => $run_id) { foreach ($binarylist as $k => $binaryinfo) { if ($binaryinfo['run_id'] == $run_id) { $line1 .= sprintf("%s%s", $binaryinfo['binary_label'], $sep); $line2 .= sprintf("%s%s", $binaryinfo['binary_file'], $sep); $cmd = sprintf('%s -f %s', $binaryinfo['binary_file'], $file); $output = array(); exec($cmd, $output); $line3 .= sprintf("%s%s", $output[0], $sep); $line4 .= sprintf("%s%s", $output[1], $sep); if (stristr($output[1], 'mysqlnd')) $mysqlnd_run_id = $run_id; } } } $line_bin_label .= substr($line1, 0, strlen($sep) * -1); $lines[] = substr($line1, 0, strlen($sep) * -1); $lines[] = substr($line2, 0, strlen($sep) * -1); $lines[] = substr($line3, 0, strlen($sep) * -1); $lines[] = substr($line4, 0, strlen($sep) * -1); $lines[] = ''; if (!$mysqlnd_run_id) { reset($binaries); list($k, $mysqlnd_run_id) = each($binaries); } unlink($file); /* HACK */ $runtimes = array(); foreach ($labels as $k => $label) { foreach ($binaries as $k => $run_id) { $runtime = $storage->getRuntimeByRunIDAndLabel($run_id, $label); $runtimes[$label][$run_id] = $runtime['runtime']; } } $lines[] = $line_bin_label; foreach ($labels as $k => $label) { $fac = (0 == $runtimes[$label][$mysqlnd_run_id]) ? 0 : 100 / $runtimes[$label][$mysqlnd_run_id]; $line = sprintf("%s%s", $label, $sep); foreach ($binaries as $k => $run_id) { if ($run_id == $mysqlnd_run_id) { if (0 == $fac) $line .= sprintf("%s%s", number_format(0, 3, ',', ''), $sep); else $line .= sprintf("%s%s", number_format(100, 3, ',', ''), $sep); } else { $line .= sprintf("%s%s", number_format($runtimes[$label][$run_id] * $fac, 3, ',', ''), $sep); } } $lines[] = substr($line, 0, strlen($sep) * -1); } $lines[] = ''; $lines[] = $line_bin_label; foreach ($labels as $k => $label) { $line = sprintf("%s%s", $label, $sep); foreach ($binaries as $k => $run_id) { $line .= sprintf("%s%s", str_replace('.', ',', sprintf("%f", $runtimes[$label][$run_id])), $sep); } $lines[] = substr($line, 0, strlen($sep) * -1); } $lines[] = ''; $csv = implode("\n", $lines); header("Content-type: application/vnd.ms-excel"); header("Content-Length: " . strlen($csv)); header("Content-disposition: attachment; filename=mysqlnd.csv"); die($csv); } } catch (Exception $e) { printf('

Error

%s

', nl2br(htmlspecialchars($e->getMessage()))); } ?> Bench: Extract CVS data for Excel and Co.

Extract CSV data for Excel and Co.

Back

Back to the overview page

Select Run, Binary and Measured Times

Run
Binaries
Measured times
mysqlnd_ms-1.5.2/tests/bench/framework/abstract.php0000664000175000017500000002054512161007456021777 0ustar andreyandreylink = mysqli_connect(RB_DB_HOST, RB_DB_USER, RB_DB_PASSWD, RB_DB_DB, RB_DB_PORT, RB_DB_SOCKET)) { throw new Exception(sprintf('Cannot connect to database, [%d] %s\n', mysqli_connect_errno(), mysqli_connect_error())); } } public function init() { if (!mysqli_query($this->link, " CREATE TABLE IF NOT EXISTS rb_res_run ( run_id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, run datetime not null, file varchar(255) not null, label varchar(255) not null, sysinfo varchar(255) not null, binary_file varchar(255) not null, binary_label varchar(255) not null, unique index(run, file, label, binary_file, binary_label), index(binary_label, file), index(binary_file, file) ) Engine = InnoDB")) { throw new Exception(sprintf("Cannot create table rb_res_run, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } abstract public function save($run_label, $run_datetime, $file, $binary_file, $binary_label, $data) ; public function delete($run_label) { if (!mysqli_query($this->link, sprintf(" DELETE FROM rb_res_run WHERE label = '%s'", mysqli_real_escape_string($this->link, $run_label)))) { throw new Exception(sprintf("Cannot delete from rb_res_run, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function deleteBefore($run_datetime) { if (!mysqli_query($this->link, sprintf(" DELETE FROM rb_res_run WHERE label <= '%s'", mysqli_real_escape_string($this->link, $run_datetime)))) { throw new Exception(sprintf("Cannot delete from rb_res_run, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function deleteAll() { if (!mysqli_query("DELETE FROM rb_res_run")) { throw new Exception(sprintf("Cannot delete from rb_res_run, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function reset() { if (!mysqli_query($this->link, "DROP TABLE IF EXISTS rb_res_run")) { throw new Exception(sprintf("Cannot drop table rb_res_run, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function getBinaries($run_label, $run_file, $run_datetime) { if (!$res = mysqli_query($this->link, $this->mySprintf('SELECT DISTINCT binary_file, binary_label FROM rb_res_run WHERE label = "%s" AND file = "%s" AND run = "%s" ORDER by binary_label, binary_file', $run_label, $run_file, $run_datetime))) { throw new Exception(sprintf("Cannot get distinct binaries, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $binaries = array(); while ($row = mysqli_fetch_assoc($res)) { $binaries[$row['binary_label']] = $row['binary_file']; } mysqli_free_result($res); return $binaries; } public function getRunInfo($run_label, $run_file, $run_datetime) { if (!$res = mysqli_query($this->link, $this->mySprintf('SELECT * FROM rb_res_run WHERE label = "%s" AND file = "%s" AND run = "%s"', $run_label, $run_file, $run_datetime))) { throw new Exception(sprintf("Cannot get run info, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } if (!$info = mysqli_fetch_assoc($res)) throw new Exception(sprintf("Cannot fetch run info,[%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); mysqli_free_result($res); return $info; } public function getRunInfoByRunID($run_id) { if (!$res = mysqli_query($this->link, sprintf('SELECT * FROM rb_res_run WHERE run_id = %d', $run_id))) { throw new Exception(sprintf("Cannot get run info, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } if (!$info = mysqli_fetch_assoc($res)) throw new Exception(sprintf("Cannot fetch run info,[%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); mysqli_free_result($res); return $info; } public function getRunList($min_run_datetime = null, $sort = 'desc', $limit = 30) { if (is_null($min_run_datetime)) $min_run_datetime = mktime(date('H'), date('i'), date('s'), date('m') - 1, date('d'), date('Y')); if (!$res = mysqli_query($this->link, $this->mySprintf(' SELECT run_id, run, SUBSTRING(file FROM LOCATE("micro_benches", file) + 14) AS bench_file, label, binary_label, binary_file FROM rb_res_run GROUP BY CONCAT(run, file) ORDER BY run %s, file ASC LIMIT %d', ('desc' == strtolower($sort)) ? 'DESC' : 'ASC', ($limit > 0) ? $limit : 30))) { throw new Exception(sprintf("Cannot get list of runs, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $run_list = array(); while ($info = mysqli_fetch_assoc($res)) $run_list[] = $info; mysqli_free_result($res); return $run_list; } public function getBinaryList($run_id) { if (!$res = mysqli_query($this->link, sprintf(' SELECT r1.run_id, r1.binary_label, r1.binary_file FROM rb_res_run AS r1, rb_res_run AS r2 WHERE r1.run = r2.run AND r1.file = r2.file AND r2.run_id = %d ORDER BY r1.binary_label', $run_id))) { throw new Exception(sprintf("Cannot get list of binaries, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $binary_list = array(); while ($info = mysqli_fetch_assoc($res)) $binary_list[] = $info; return $binary_list; } public function getMeasuredTimeLabels($run_id) { if (!$res = mysqli_query($this->link, sprintf(' SELECT DISTINCT(label) FROM rb_res_normal_times WHERE fk_run_id = %d ORDER BY id', $run_id))) { throw new Exception(sprintf("Cannot get list of measured times, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $labellist = array(); while ($labellist[] = mysqli_fetch_assoc($res)) ; return $labellist; } // // protected // protected function saveRuninfo($run_label, $run_datetime, $file, $binary_file, $binary_label) { $sysinfo = ''; if (function_exists("posix_uname")) { foreach (posix_uname() as $k => $v) $sysinfo .= sprintf("%s ", $v); $sysinfo = substr($sysinfo, 0, -2); } else { $sysinfo = "(posix_uname() unavailable, likely some Windows OS)"; } if (!mysqli_query($this->link, $sql = $this->mySprintf('INSERT INTO rb_res_run (run, file, label, sysinfo, binary_file, binary_label) VALUES ("%s", "%s", "%s", "%s", "%s", "%s")', $run_datetime, $file, $run_label, $sysinfo, $binary_file, $binary_label))) { throw new Exception(sprintf("Cannot insert into table rb_res_run, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } return mysqli_insert_id($this->link); } protected function mySprintf() { $args = func_get_args(); $pattern = array_shift($args); $call_args = array($pattern); foreach ($args as $k => $v) $call_args[] = mysqli_real_escape_string($this->link, $v); $ret = call_user_func_array('sprintf', $call_args); return $ret; } } ?>mysqlnd_ms-1.5.2/tests/bench/framework/config.php0000664000175000017500000000621012161007456021432 0ustar andreyandrey array( 'binary' => getenv("TEST_PHP_EXECUTABLE"), 'ini' => getcwd() . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR . 'micro_benches' . DIRECTORY_SEPARATOR . 'mysqlnd_ms_php.ini' ), 'PHP' => array( 'binary' => getenv("TEST_PHP_EXECUTABLE"), 'ini' => NULL ), ); */ $rb_binary = array(); if (empty($rb_binaries) && RB_USE_TEST_ENV) { // fallback to run-test settings // Format: rb_binaries[display name] = array('binary' => executable, 'ini' => ini file or NULL) $rb_binaries['PHP'] = array('binary' => getenv("TEST_PHP_EXECUTABLE"), 'ini' => NULL); } if (!RB_USE_TEST_ENV) { // // Database connection parameter // // database user define('RB_DB_USER', 'root'); // database password define('RB_DB_PASSWD', 'root'); // database define('RB_DB_DB', 'microbench'); // host, for mysqlnd: localhost = socket, 127.0.0.1 = tcp/ip define('RB_DB_HOST', '127.0.0.1'); // port define('RB_DB_PORT', 3306); // socket define('RB_DB_SOCKET', ''); // database engine define('RB_DB_ENGINE', 'InnoDB'); } else { // let the environment define the settings if ($tmp = getenv('MYSQL_TEST_USER')) define('RB_DB_USER', $tmp); else define('RB_DB_USER', 'root'); if ($tmp = getenv('MYSQL_TEST_PASSWD')) define('RB_DB_PASSWD', $tmp); else define('RB_DB_PASSWD', 'root'); if ($tmp = getenv('MYSQL_TEST_DB')) define('RB_DB_DB', $tmp); else define('RB_DB_DB', 'microbench'); if ($tmp = getenv('MYSQL_TEST_HOST')) define('RB_DB_HOST', $tmp); else define('RB_DB_HOST', '127.0.0.1'); if ($tmp = getenv('MYSQL_TEST_PORT')) define('RB_DB_PORT', $tmp); else define('RB_DB_PORT', 3306); if ($tmp = getenv('MYSQL_TEST_SOCKET')) define('RB_DB_SOCKET', $tmp); else define('RB_DB_SOCKET', '/tmp/mysql.sock'); if ($tmp = getenv('MYSQL_TEST_ENGINE')) define('RB_DB_ENGINE', $tmp); else define('RB_DB_ENGINE', 'InnoDB'); } // // oprofile profiling // // run oprofile by default? define('RB_DEFAULT_OPROFILE', false); // binaries and co define('RB_OPROFILE_OPCONTROL', (RB_USE_TEST_ENV && getenv('MYSQL_TEST_OPCONTROL')) ? getenv('MYSQL_TEST_OPCONTROL') : '/usr/bin/opcontrol'); define('RB_OPROFILE_OPREPORT', (RB_USE_TEST_ENV && getenv('MYSQL_TEST_OPREPORT')) ? getenv('MYSQL_TEST_OPREPORT') : '/usr/bin/opreport'); define('RB_OPROFILE_VMLINUX', (RB_USE_TEST_ENV && getenv('MYSQL_TEST_VMLINUX')) ? getenv('MYSQL_TEST_VMLINUX') : '/usr/src/linux/vmlinux'); // // program options // // activate HTML output generation by default? define('RB_DEFAULT_OUTPUT_HTML', true); // where to store the HTML files define('RB_OUTPUT_HTML_DIR', './web/'); // where to store the HTML that can be used for some wikis define('RB_OUTPUT_WIKI_DIR', './web/wiki/'); // activate storing results into the DB by default? define('RB_DEFAULT_STORAGE_DB', true); ?> mysqlnd_ms-1.5.2/tests/bench/framework/main.php0000664000175000017500000000060412161007456021112 0ustar andreyandreyparseArgs($argc, $argv); printf("Config:\n%s\n", implode("\n", $rb->getConfig())); $rb->runTests(true); } catch (Exception $e) { printf("%s\n\n", $e->getMessage()); printf("%s\n", $rb->getCommandlineSyntax()); exit(1); } exit(0); ?> mysqlnd_ms-1.5.2/tests/bench/framework/rb_main.php0000664000175000017500000001676712161007456021616 0ustar andreyandreyrun_label = ($run_label) ? $run_label : date('Y-m-d H:i:s'); $this->run_datetime = ($run_datetime) ? $run_datetime : date('Y-m-d H:i:s'); $this->initOptions(); } public function runTests($save_results, $render = true) { if (!$testrunner = $this->createTestrunner()) throw new Exception(sprintf("No test runner specified!\n")); sort($this->files); foreach ($this->options['binaries'] as $binary_label => $binary) { if (!file_exists($binary['binary'])) throw new Exception(sprintf("Cannot find binary '%s' => '%s'\n", $binary_label, $binary['binary'])); if (!is_null($binary['ini']) && !file_exists($binary['ini'])) throw new Exception(sprintf("Cannot find ini '%s' => '%s'\n", $binary_label, $binary['ini'])); foreach ($testrunner as $k => $runner) { if ($this->options['verbose']) { printf("\n"); printf("[%s] Starting run for binary '%s' and runner '%s'...\n", date('Y-m-d H:i:s'), $binary_label, get_class($runner)); flush(); } foreach ($this->files as $k => $file) { $results = $runner->runTest($file, $binary, $this->options); if ($save_results) $runner->saveResults($this->run_label, $this->run_datetime, $file, $binary['binary'], $binary_label, $results); } } } if ($render) { if ($this->options['verbose']) { printf("\n"); printf("[%s] Starting to render results...\n", date('Y-m-d H:i:s')); flush(); } foreach ($testrunner as $k => $runner) { $runner->getRenderer()->renderOverviewTxt($this->run_label, $this->run_datetime); if (RB_DEFAULT_OUTPUT_HTML) { $runner->getRenderer()->renderOverviewHTML($this->run_label, $this->run_datetime); $runner->getRenderer()->renderOverviewWiki($this->run_label, $this->run_datetime); } foreach ($this->files as $k => $file) { $runner->getRenderer()->renderRunTxt($this->run_label, $file, $this->run_datetime); if (RB_DEFAULT_OUTPUT_HTML) { $runner->getRenderer()->renderRunHTML($this->run_label, $file, $this->run_datetime); $runner->getRenderer()->renderRunWiki($this->run_label, $file, $this->run_datetime); } } } } return true; } public function createTestrunner() { $testrunner = array(); if ($this->options['run_normal']) $testrunner[] = new rb_testrunner_normal(); /* if ($this->options['run_oprofile']) $this->testrunne[] = new rb_testrunner_oprofile(); */ return $testrunner; } public function parseArgs($argc, $argv) { $this->initOptions(); $this->files = array(); // Fetch options specified directly after the run-bench.php script name // which we are going to shiff off the array first array_shift($argv); if (empty($argv)) throw new Exception(sprintf("Missing file and/or directory specification!")); while (!empty($argv) && substr($argv[0], 0, 1) == '-') { $opt = substr($argv[0], 0, 2); switch ($opt) { case '-v': $this->options['verbose'] = true; array_shift($argv); break; case '-h': return sprintf("No error, but you asked for help... :-)\n"); break; case '-q': $this->options['output_html'] = false; $this->options['output_txt'] = false; $this->options['verbose'] = false; array_shift($argv); break; case '-p': $this->options['oprofile'] = true; array_shift($argv); break; default: break; } } if (empty($argv)) throw new Exception(sprintf("Missing file and/or directory specification!")); while ($tmp = array_shift($argv)) { if (is_file($tmp) && !$this->addFile($tmp, $this->options['name'])) throw new Exception(sprintf("Cannot read '%s'\n", $tmp)); if (is_dir($tmp) && !$this->addDir($tmp, $this->options['name'])) throw new Exception(sprintf("Cannot read '%s'\n", $tmp)); } if (empty($this->files)) throw new Exception(sprintf("No benchmark files found!\n")); } public function getConfig() { return array( 'RB_DB_USER' => RB_DB_USER, 'RB_DB_PASSWD' => RB_DB_PASSWD, 'RB_DB_DB' => RB_DB_DB, 'RB_DB_HOST' => RB_DB_HOST, 'RB_DB_PORT' => RB_DB_PORT, 'RB_DB_SOCKET' => RB_DB_SOCKET, 'RB_DB_ENGINE' => RB_DB_ENGINE, ); } public function getCommandlineSyntax() { $syntax = "Syntax:\n"; $syntax.= " program [options] dir_or_file [dir_or_file [dir_or_file ...]]\n"; $syntax.= "\n"; $syntax.= "Options:\n"; $syntax.= " -v - Verbose\n"; $syntax.= " -h - Help\n"; $syntax.= " -q - Quiet, suppress output\n"; // $syntax.= " -o html[=dir] - Create HTML output. Default: " . ((RB_DEFAULT_OUTPUT_HTML) ? 'on' : 'off') . "(see config.php)\n"; // $syntax.= " -o txt - Print textual results. Default: on\n"; // $syntax.= " -b label=path - Test binary [path], use the [label] to refer to it\n"; // $syntax.= " -n name - File name pattern. Default: .*\\.php\n"; $syntax.= " -p - Profile with oprofile (see config.php)\n"; $syntax.= "\n"; // $syntax.= "Watch the defaults defined in config.php!\n\n"; /* $syntax.= "Examples:\n"; $syntax.="\n"; $syntax.= " -o html=/usr/local/apache/htdocs/rb/\n"; $syntax.= " Write HTML output to /usr/local/apache/htdocs/rb/.\n"; $syntax.= "\n"; $syntax.= "\n"; $syntax.= " -b mysqlnd=../php/sapi/cli/php -b libmysql=/usr/bin/php -o html\n"; $syntax.= " Run benchmarks with two binaries, label results for binaries\n"; $syntax.= " with 'mysqlnd' and 'libmysql'. Create HTML output in the current directory\n"; */ return $syntax; } protected function initOptions() { $this->options = array( 'output_html' => RB_DEFAULT_OUTPUT_HTML, 'output_txt' => true, 'recursive' => true, 'verbose' => false, 'run_oprofile' => false, 'run_normal' => true, 'storage_db' => RB_DEFAULT_STORAGE_DB, 'name' => '/.*\.php$/i', 'oprofile' => RB_DEFAULT_OPROFILE, 'binaries' => $GLOBALS['rb_binaries'], ); } protected function addDir($dirname, $pattern) { if (!is_dir($dirname)) return false; try { $dir = new DirectoryIterator($dirname); foreach ($dir as $file) { if ($dir->isDot()) continue; $ffile = $file->getPathname(); if ($file->isDir() && !$this->addDir($ffile, $pattern)) return false; $this->addFile($ffile, $pattern); } } catch (Exception $e) { return false; } return true; } protected function addFile($filename, $pattern) { if (!is_file($filename)) return false; if (!is_readable($filename)) return false; if (!preg_match($pattern, $filename)) return false; $this->files[] = realpath($filename); return true; } } // end class rb_main ?> mysqlnd_ms-1.5.2/tests/bench/framework/rb_renderer_normal.php0000664000175000017500000004144312161007456024035 0ustar andreyandreystorage = $storage; } public function renderRunTxt($run_label, $file, $run_datetime) { $binaries = $this->storage->getBinaries($run_label, $file, $run_datetime); $num_repeat = (41 + count($binaries) * 17); printf("\n"); printf("%s\n", str_repeat('=', $num_repeat)); printf("%-16s: %-40s\n", "File", basename($file)); printf("%s\n", str_repeat('=', $num_repeat)); printf("\n"); if (count($binaries) > 4) { reset($binaries); list($master_bin_label, $master_bin_file) = each($binaries); $master_times = $this->storage->getRuntimes($run_label, $file, $run_datetime, $master_bin_label, $master_bin_file); $this->renderTimesTxt($master_times, $master_bin_label, $master_bin_label, $master_bin_file, $master_times); $this->renderRunInfoTxt($this->storage->getRunInfo($run_label, $file, $run_datetime)); foreach ($binaries as $binary_label => $binary_file) { $times = $this->storage->getRuntimes($run_label, $file, $run_datetime, $binary_label, $binary_file); $this->renderTimesTxt($master_times, $master_bin_label, $binary_label, $binary_file, $times); } return; } $this->renderRunInfoTxt($this->storage->getRunInfo($run_label, $file, $run_datetime)); reset($binaries); list($master_bin_label, $master_bin_file) = each($binaries); $all_runtimes[$master_bin_label] = $this->storage->getRuntimes($run_label, $file, $run_datetime, $master_bin_label, $master_bin_file); while (list($bin_label, $bin_file) = each($binaries)) { $all_runtimes[$bin_label] = $this->storage->getRuntimes($run_label, $file, $run_datetime, $bin_label, $bin_file); } foreach($binaries as $bin_label => $bin_file) { printf("%-16s: %s\n", $bin_label, $bin_file); } printf("\n"); printf(" WARNING: 'Total' SAYS NOTHING, CHECK '* overall' VALUES!\n"); printf("\n"); printf("%-40s ", ""); foreach ($binaries as $bin_label => $bin_file) { printf("%-17s ", $bin_label); } printf("\n"); printf("%s\n", str_repeat('-', $num_repeat)); array_shift($binaries); foreach ($all_runtimes[$master_bin_label] as $runtime_label => $master_runtime) { printf("%-40s", $runtime_label); printf(" %03.4fs ( 100%%) ", $master_runtime); foreach ($binaries as $bin_label => $bin_file) { printf(" %03.4fs (%4d%%) ", $all_runtimes[$bin_label][$runtime_label], (($master_runtime > 0) ? (100 / $master_runtime) * $all_runtimes[$bin_label][$runtime_label] : 0)); } printf("\n"); } printf("%s\n", str_repeat('=', $num_repeat)); printf("%-40s", "Total"); $master_sum = array_sum($all_runtimes[$master_bin_label]); printf(" %03.4fs ( 100%%) ", $master_sum); foreach ($binaries as $bin_label => $bin_file) { printf(" %03.4fs (%4d%%) ", array_sum($all_runtimes[$bin_label]), (($master_sum > 0) ? (100 / $master_sum) * array_sum($all_runtimes[$bin_label]) : 0)); } printf("\n"); printf("%s\n", str_repeat('-', $num_repeat)); printf("\n"); } public function renderOverviewTxt($run_label, $run_datetime) { $fastest = $this->storage->getFastestBinaries($run_label, $run_datetime); list($file, ) = each($fastest); $binaries = $this->storage->getBinaries($run_label, $file, $run_datetime); $num_repeat = 44 + count($binaries) * 16; printf("%s\n", str_repeat("=", $num_repeat)); printf("Summary %s (%s)\n", $run_label, $run_datetime); printf("%s\n", str_repeat("=", $num_repeat)); printf("\n"); $clean_stats = array(); foreach ($binaries as $bin_label => $bin_file) { printf("%-20s: %s\n", $bin_label, substr($bin_file, 0, $num_repeat - 20)); $clean_stats[$bin_label] = 0; } printf("\n"); printf(" Counters show for how many time figures a certain binary\n"); printf(" has been the fastest. For example, the following says that\n"); printf(" three figures are available for 'file.php' and for one figure\n"); printf(" 'Binary A' was faster than the other binaries and for the\n"); printf(" other two figures 'Binary C' was the fastest:\n\n"); printf(" Binary A Binary B Binary C\n"); printf(" ---------------------------------------------------------\n"); printf(" file.php (03 = 100%%): 1 (33%%) 0 (0%%) 2 (66%%)\n"); printf("\n\n"); printf("%-44s", ""); foreach ($binaries as $bin_label => $bin_file) printf("%16s", $bin_label); printf("\n"); printf("%s\n", str_repeat("-", $num_repeat)); foreach ($fastest as $file => $filestats) { $stats = $clean_stats; foreach ($filestats as $time_label => $bin_label) $stats[$bin_label]++; $total = array_sum($stats); printf("%-30s (%02d = 100%%): ", substr(basename($file), 0, 30), $total); foreach ($binaries as $bin_label => $bin_file) printf("%16s", sprintf("%d (%3d%%)", $stats[$bin_label], ($total) ? (100 / $total) * $stats[$bin_label] : 0)); printf("\n"); } printf("%s\n", str_repeat("-", $num_repeat)); printf("\n"); } public function renderRunHTML($run_label, $file, $run_datetime) { if (!file_exists(RB_OUTPUT_HTML_DIR) && !mkdir(RB_OUTPUT_HTML_DIR, 0644, true)) throw new Exception(sprintf("Cannot create output directory '%s'", RB_OUTPUT_HTML_DIR)); $htmlfile = sprintf('%s/%s.html', RB_OUTPUT_HTML_DIR, str_replace('.', '_', basename($file))); if (!$fp = fopen($htmlfile, 'w')) throw new Exception(sprintf("Cannot open output file '%s'", $htmlfile)); $info = $this->storage->getRunInfo($run_label, $file, $run_datetime); $binaries = $this->storage->getBinaries($run_label, $file, $run_datetime); $short_file = basename($file); $html = << Bench: $run_label ($run_datetime) $file

$run_label ($run_datetime)

Bench: $short_file

Run information

Run-ID {$info['run_id']}
Label {$info['label']}
Datetime {$info['run']}
System {$info['sysinfo']}
EOT; reset($binaries); list($master_bin_label, $master_bin_file) = each($binaries); $all_runtimes[$master_bin_label] = $this->storage->getRuntimes($run_label, $file, $run_datetime, $master_bin_label, $master_bin_file); while (list($bin_label, $bin_file) = each($binaries)) { $all_runtimes[$bin_label] = $this->storage->getRuntimes($run_label, $file, $run_datetime, $bin_label, $bin_file); } $html.= <<Binaries EOT; foreach ($binaries as $bin_label => $bin_file) { $anchor = urlencode($bin_label); $html.= << EOT; } $html .= '
$bin_label $bin_file
' . "\n"; $html .= '

Run times

' . "\n"; $html .= '' . "\n"; $html .= '' . "\n"; $html .= '' . "\n"; foreach ($binaries as $bin_label => $bin_file) { $html .= sprintf('', $bin_label); } $html .= '' . "\n"; array_shift($binaries); $i = 0; foreach ($all_runtimes[$master_bin_label] as $runtime_label => $master_runtime) { $i++; if ($i % 2 == 0) { $html .= '' . "\n"; } else { $html .= '' . "\n"; } $html .= sprintf('', $runtime_label); $html .= sprintf('', $master_runtime); $html .= sprintf(''); foreach ($binaries as $bin_label => $bin_file) { $html .= sprintf('', $all_runtimes[$bin_label][$runtime_label]); $html .= sprintf('', (($master_runtime > 0) ? (100 / $master_runtime) * $all_runtimes[$bin_label][$runtime_label] : 0)); } $html .= '' . "\n"; } $html .= '
 %s
%s%3.5fs(100%%)%3.5fs(%4d%%)
' . "\n"; $html.= <<Source code of the micro benchmark

EOT; $html .= highlight_file($file, true); $html.= '

'; $sql = sprintf(' SELECT r1.run_id AS run_id, r1.run AS run, RIGHT(r1.file, 40) AS file, r1.binary_label AS binary_label, t1.label AS label, t1.runtime AS runtime FROM rb_res_run AS r1 INNER JOIN rb_res_normal_times AS t1 ON (r1.run_id = t1.fk_run_id) WHERE r1.run_id = %d AND r1.file = "%s" ORDER BY t1.label', $info['run_id'], $file); $html.= <<Database

Use the following SQL statement as a starting point, if you want to analyze the results manually.

$sql
      

EOT; $html .= <<php -i for every binary EOT; $binaries = array_merge(array($master_bin_label => $master_bin_file), $binaries); $i = 0; foreach ($binaries as $bin_label => $bin_file) { $color = (++$i % 2) ? ' bgcolor="#f0f0f0" ' : ''; $anchor = urlencode($bin_label); $cmd = sprintf("%s -i", $bin_file); $output = array(); $ret = 0; exec($cmd, $output, $ret); $output = htmlspecialchars(implode("\n", $output)); $html.= << EOT; } $html.= << EOT; fwrite($fp, $html); fclose($fp); } public function renderOverviewHTML($run_label, $run_datetime) { $fastest = $this->storage->getFastestBinaries($run_label, $run_datetime); list($file, ) = each($fastest); $binaries = $this->storage->getBinaries($run_label, $file, $run_datetime); if (!file_exists(RB_OUTPUT_HTML_DIR) && !mkdir(RB_OUTPUT_HTML_DIR, 0755, true)) throw new Exception(sprintf("Cannot create output directory '%s'", RB_OUTPUT_HTML_DIR)); $htmlfile = sprintf('%s/index.html', RB_OUTPUT_HTML_DIR); if (!$fp = fopen($htmlfile, 'w')) throw new Exception(sprintf("Cannot open output file '%s'", $htmlfile)); $html = << Bench: $run_label ($run_datetime) $file

$run_label ($run_datetime)

Binaries

$bin_label ($bin_file)
$output
EOT; $clean_stats = array(); foreach ($binaries as $bin_label => $bin_file) { $anchor = urlencode($bin_label); $html .= << EOT; $clean_stats[$bin_label] = 0; } $html .= <<

Data export

Export test results

Summary

Counters show for how many time figures a certain binary has been the fastest. For example, the following says that three figures are available for 'file.php' and for one figure 'Binary A' was faster than the other binaries and for the other two figures 'Binary C' was the fastest:

$bin_label $bin_file
  Binary A Binary B Binary C
file.php 1 (33%) 0 (0%) 2 (66%)

EOT; foreach ($binaries as $bin_label => $bin_file) $html .= sprintf('', $bin_label); $html .= '' . "\n"; $i = 0; foreach ($fastest as $file => $filestats) { $stats = $clean_stats; $color = (++$i % 2) ? ' bgcolor="#f0f0f0" ' : ''; foreach ($filestats as $time_label => $bin_label) $stats[$bin_label]++; $total = array_sum($stats); $html .= sprintf('', $color, str_replace('.', '_', basename($file)), basename($file), $total); foreach ($binaries as $bin_label => $bin_file) { $html .= sprintf('', $stats[$bin_label], ($total) ? (100 / $total) * $stats[$bin_label] : 0); } $html .= '' . "\n"; } $html.= <<php -i for every binary
 %s
%s %d 100%%%d%3d%%
EOT; $i = 0; foreach ($binaries as $bin_label => $bin_file) { $color = (++$i % 2) ? ' bgcolor="#f0f0f0" ' : ''; $anchor = urlencode($bin_label); $cmd = sprintf("%s -i", $bin_file); $output = array(); $ret = 0; exec($cmd, $output, $ret); $output = htmlspecialchars(implode("\n", $output)); $html.= << EOT; } $html.= << EOT; fwrite($fp, $html); fclose($fp); } public function renderRunWiki($run_label, $file, $run_datetime) { $this->renderRunHTML($run_label, $file, $run_datetime); $htmlfile = sprintf('%s/%s.html', RB_OUTPUT_HTML_DIR, str_replace('.', '_', basename($file))); $wikifile = sprintf('%s/%s_wiki.txt', RB_OUTPUT_HTML_DIR, str_replace('.', '_', basename($file))); preg_match_all("=]*>(.*)=siU", file_get_contents($htmlfile), $a); $body = explode("\n", $a[1][0]); foreach ($body as $k => $line) $body[$k] = '|' . str_replace('|', '', $line) . "\n"; $fp = fopen($wikifile, 'w'); fwrite($fp, implode('', $body)); fclose($fp); } public function renderOverviewWiki($run_label, $run_datetime) { $this->renderOverviewHTML($run_label, $run_datetime); $htmlfile = sprintf('%s/index.html', RB_OUTPUT_HTML_DIR); $wikifile = sprintf('%s/index_wiki.txt', RB_OUTPUT_HTML_DIR); preg_match_all("=]*>(.*)=siU", file_get_contents($htmlfile), $a); $body = explode("\n", $a[1][0]); foreach ($body as $k => $line) $body[$k] = '|' . str_replace('|', '', $line) . "\n"; $fp = fopen($wikifile, 'w'); fwrite($fp, implode('', $body)); fclose($fp); } protected function renderTimesTxt($master_times, $master_bin_label, $binary_label, $binary_file, $times) { $master_sum = array_sum($master_times); $times_sum = array_sum($times); printf("Binary : %-20s %3.5fs (vs. %-20s: %3.5fs = %02d%%)\n", $binary_label, $times_sum, $master_bin_label, $master_sum, (($master_sum != 0) ? ((100 / $master_sum) * $times_sum) : 0) ); printf("\n"); foreach ($times as $label => $runtime) { printf("%-40s %3.5fs (%3.5fs = %02d%%)\n", $label, $runtime, $master_times[$label], (($master_times[$label] != 0) ? (100 / $master_times[$label]) * $runtime : 0)); } } } ?>mysqlnd_ms-1.5.2/tests/bench/framework/rb_storage_db_normal.php0000664000175000017500000001633712161007456024344 0ustar andreyandreylink, " CREATE TABLE IF NOT EXISTS rb_res_normal_times ( id INT AUTO_INCREMENT PRIMARY KEY, fk_run_id INT NOT NULL, label VARCHAR(255) NOT NULL, runtime DECIMAL(9,6) NOT NULL, INDEX(fk_run_id), FOREIGN KEY (fk_run_id) REFERENCES rb_res_run(run_id), INDEX(label), INDEX(runtime) ) Engine = InnoDB")) { throw new Exception(sprintf("Cannot create table rb_res_normal_times, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function save($run_label, $run_datetime, $file, $binary_file, $binary_label, $data) { $fk_run_id = $this->saveRuninfo($run_label, $run_datetime, $file, $binary_file, $binary_label); foreach ($data['times'] as $label => $time) { if (!mysqli_query($this->link, sprintf('INSERT INTO rb_res_normal_times (fk_run_id, label, runtime) VALUES (%d, "%s", %f)', $fk_run_id, mysqli_real_escape_string($this->link, $label), $time))) { $msg = sprintf("Cannot insert into rb_res_normal_times, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link)); try { $this->delete($run_label); } catch (Exception $e) { throw new Exception(sprintf("%s\n%s\n", $msg, $e->getMessage())); } throw new Exception($msg); } } } public function delete($run_label) { if (!mysqli_query($this->link, sprintf('DELETE FROM rb_res_normal_times WHERE label = "%s"', mysqli_real_escape_string($this->link, $run_label)))) { throw new Exception(sprintf("Cannot delete from rb_res_normal_times, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function deleteBefore($run_datetime) { if (!mysqli_query($this->link, sprintf('DELETE FROM rb_res_normal_times WHERE runtime <= "%s"', mysqli_real_escape_string($this->link, $run_datetime)))) { throw new Exception(sprintf("Cannot delete from rb_res_normal_times, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function deleteAll() { if (!mysqli_query($this->link, sprintf('DELETE FROM rb_res_normal_times'))) { throw new Exception(sprintf("Cannot delete from rb_res_normal_times, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } } public function reset() { if (!mysqli_query($this->link, "DROP TABLE IF EXISTS rb_res_normal_times")) { throw new Exception(sprintf("Cannot create table, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } try { parent::reset(); } catch (Exception $e) { // igore issues dropping rb_res_run ? print $e->getMessage(); } } public function getRuntimes($run_label, $file, $run_datetime, $binary_label, $binary_file) { if (!$res = mysqli_query($this->link, $sql = $this->mySprintf(' SELECT r2.label AS label, r2.runtime AS runtime FROM rb_res_run r1, rb_res_normal_times r2 WHERE r1.run = "%s" AND r1.file = "%s" AND r1.label = "%s" AND r1.binary_label = "%s" AND r1.binary_file = "%s" AND r2.fk_run_id = r1.run_id ORDER BY r2.id', $run_datetime, $file, $run_label, $binary_label, $binary_file))) { throw new Exception(sprintf("Cannot fetch runtimes, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $runtimes = array(); while ($row = mysqli_fetch_assoc($res)) { $runtimes[$row['label']] = $row['runtime']; } mysqli_free_result($res); return $runtimes; } public function getRuntimeByRunIDAndLabel($run_id, $label) { if (!$res = mysqli_query($this->link, $sql = $this->mySprintf(' SELECT runtime FROM rb_res_normal_times WHERE fk_run_id = %d AND label = "%s"', $run_id, $label ))) { throw new Exception(sprintf("Cannot fetch runtimes, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $runtime = mysqli_fetch_assoc($res); mysqli_free_result($res); return $runtime; } public function getFastestBinaries($run_label, $run_datetime) { if (!$res = mysqli_query($this->link, $this->mySprintf(' SELECT COUNT(*) AS num, r1.file AS file, r1.binary_label AS binary_label, t1.label AS time_label FROM rb_res_run AS r1 INNER JOIN rb_res_normal_times AS t1 ON (t1.fk_run_id = r1.run_id) INNER JOIN rb_res_run AS r2 ON (r1.run_id <> r2.run_id AND r1.run = r2.run AND r1.label = r2.label AND r1.file = r2.file) INNER JOIN rb_res_normal_times AS t2 ON (t2.fk_run_id = r2.run_id AND t1.label = t2.label AND t1.runtime < t2.runtime) WHERE r1.run = "%s" AND r1.label = "%s" GROUP BY r1.binary_label, t1.label HAVING num = (SELECT (COUNT(DISTINCT(binary_label)) - 1) FROM rb_res_run WHERE run = "%s" AND label = "%s") ORDER BY r1.file ', $run_datetime, $run_label, $run_datetime, $run_label))) { throw new Exception(sprintf("Cannot find fastest, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } // var_dump($sql); $fastest = array(); while ($row = mysqli_fetch_assoc($res)) { $fastest[$row['file']][$row['time_label']] = $row['binary_label']; } mysqli_free_result($res); return $fastest; } public function getFastestBinaryByFile($run_label, $run_datetime, $file) { if (!$res = mysqli_query($this->link, $this->mySprintf(' SELECT COUNT(*) AS num, r1.binary_label AS binary_label, t1.label AS time_label FROM rb_res_run AS r1 INNER JOIN rb_res_normal_times AS t1 ON (t1.fk_run_id = r1.run_id) INNER JOIN rb_res_run AS r2 ON (r1.run_id <> r2.run_id AND r1.run = r2.run AND r1.label = r2.label AND r1.file = r2.file) INNER JOIN rb_res_normal_times AS t2 ON (t2.fk_run_id = r2.run_id AND t1.label = t2.label AND t1.runtime < t2.runtime) WHERE r1.run = "%s" AND r1.label = "%s" AND r1.file = "%s" GROUP BY r1.binary_label, t1.label HAVING num = (SELECT (COUNT(*) - 1) FROM rb_res_run WHERE run = "%s" AND label = "%s" AND file = "%s")', $run_datetime, $run_label, $file, $run_datetime, $run_label, $file))) { throw new Exception(sprintf("Cannot find fastest, [%d] %s\n", mysqli_errno($this->link), mysqli_error($this->link))); } $fastest = array(); while ($row = mysqli_fetch_assoc($res)) { $fastest[$row['time_label']] = $row['binary_label']; } mysqli_free_result($res); return $fastest; } } ?>mysqlnd_ms-1.5.2/tests/bench/framework/rb_testrunner_normal.php0000664000175000017500000000731612161007456024441 0ustar andreyandrey $times, "errors" => $errors, "memory" => (isset($memory)) ? $memory : NULL);%s', "\n"); $code.= sprintf('$fp = fopen("%s" . ".res", "w");%s', $file, "\n"); $code.= sprintf('fwrite($fp, serialize($all));%s', "\n"); $code.= sprintf('fclose($fp);%s', "\n"); $code.= sprintf('print "done!";%s', "\n"); $code.= sprintf('?>%s', "\n"); $mycode = str_replace('.', '_', $file) . '_run_normal.php'; @unlink($mycode); $results = sprintf('%s.res', $file); @unlink($results); if (!$fp = fopen($mycode, 'w')) throw new Exception("Cannot create temporary file\n"); fwrite($fp, $code); fclose($fp); $cmd = sprintf('%s %s -f %s', $binary['binary'], (is_null($binary['ini'])) ? '' : sprintf(' -c %s ', $binary['ini']), $mycode); if ($options['verbose']) { printf(" ...'%s'\n", $cmd); flush(); } exec($cmd, $output, $ret); if ($ret !== 0 || empty($output) || $output[0] != 'done!') { throw new Exception(sprintf("Cannot fetch output from %s, return code: %d, output: %s\n", $binary['binary'], $ret, implode('', $output))); } if (!$tmp = file_get_contents($results)) throw new Exception("Cannot read data exchange file"); if (!$all = unserialize($tmp)) throw new Exception("Cannot unserialize data exchange file contents"); unlink($results); unlink($mycode); if (!empty($all['errors'])) throw new Exception(sprintf("Errors during bench run: %s\n", implode("\n", $all['errors']))); if ($options['verbose']) { printf(" ... microbench finished, %d errors, %d times recorded, %d mem info recorded\n", count($all['errors']), count($all['times']), count($all['memory'])); flush(); } return $all; } public function saveResults($run_label, $run_datetime, $file, $binary_file, $binary_label, $data) { $this->initStorage(); $this->storage->init(); $this->storage->save($run_label, $run_datetime, $file, $binary_file, $binary_label, $data); } public function getRenderer() { if (!$this->renderer) { $this->initStorage(); $this->renderer = new rb_renderer_normal($this->storage); } return $this->renderer; } public function clearOldResults() {} protected function initStorage() { if (is_null($this->storage)) $this->storage = new rb_storage_db_normal(); } } ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/andrey_stmt1.php0000664000175000017500000000673512161007456023416 0ustar andreyandrey shown in reports like 'select() : 0.01s' */ $times = array(); /* It's recommended to initialize the times hash with 0 values for all entries. This often makes debugging easier. Make sure you have one 'overall' entry in your list which holds the 'entire runtime' of you test (e.g. create table + insert + select) and not only a fraction of it (e.g. select). */ foreach ($rows as $k => $num_rows) { $times[sprintf("%7d: overall", $num_rows)] = 0; $times[sprintf("%7d: query", $num_rows)] = 0; $times[sprintf("%7d: fetch()", $num_rows)] = 0; } /* List of errors that happened during the test run. You should stop the benchmark after the first error */ $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE IF EXISTS failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "CREATE TABLE test(a INT, b CHAR(1), c CHAR(1), d CHAR(1))")) { $errors[] = sprintf("CREATE TABLE failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($rows as $k => $num_rows) { if (!mysqli_query($link, "TRUNCATE TABLE test")) { $errors[] = sprintf("TRUNCATE failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, sprintf("INSERT INTO test(a, b, c, d) VALUES (%d, 'a', 'b', 'c')", $i))) { $errors[] = sprintf("TRUNCATE failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 3; } } $times[sprintf("%7d: overall", $num_rows)] = $start = microtime(true); if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("stmt_init() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } if (!mysqli_stmt_prepare($stmt, 'SELECT * FROM test')) { $errors[] = sprintf("stmt_prepare() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("stmt_execute() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } $row = array(0 => null, 1 => null, 2 => null, 3 => null); if (!mysqli_stmt_bind_result($stmt, $row[0], $row[1], $row[2], $row[3])) { $errors[] = sprintf("stmt_execute() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } $times[sprintf("%7d: query", $num_rows)] = (microtime(true) - $start); $start = microtime(true); while (mysqli_stmt_fetch($stmt)) ; $times[sprintf("%7d: stmt_fetch()", $num_rows)] = (microtime(true) - $start); $times[sprintf("%7d: overall", $num_rows)] = (microtime(true) - $times[sprintf("%7d: overall", $num_rows)]); } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/andrey_stmt1_php_run_normal.php0000664000175000017500000000112412161007456026504 0ustar andreyandrey $times, "errors" => $errors, "memory" => (isset($memory)) ? $memory : NULL); $fp = fopen("/home/nixnutz/src/mysqlnd/tests/ext/mysqli/bench/micro_benches/andrey_stmt1.php" . ".res", "w"); fwrite($fp, serialize($all)); fclose($fp); print "done!"; ?> mysqlnd_ms-1.5.2/tests/bench/micro_benches/andrey_stmt2.php0000664000175000017500000000706212161007456023411 0ustar andreyandrey shown in reports like 'select() : 0.01s' */ $times = array(); /* It's recommended to initialize the times hash with 0 values for all entries. This often makes debugging easier. Make sure you have one 'overall' entry in your list which holds the 'entire runtime' of you test (e.g. create table + insert + select) and not only a fraction of it (e.g. select). */ foreach ($rows as $k => $num_rows) { $times[sprintf("%7d: overall", $num_rows)] = 0; $times[sprintf("%7d: query", $num_rows)] = 0; $times[sprintf("%7d: fetch()", $num_rows)] = 0; } /* List of errors that happened during the test run. You should stop the benchmark after the first error */ $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE IF EXISTS failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "CREATE TABLE test(a INT, b CHAR(255), c CHAR(255), d CHAR(255))")) { $errors[] = sprintf("CREATE TABLE failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($rows as $k => $num_rows) { if (!mysqli_query($link, "TRUNCATE TABLE test")) { $errors[] = sprintf("TRUNCATE failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } $label = str_repeat('a', 255); for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, sprintf("INSERT INTO test(a, b, c, d) VALUES (%d, '%s', '%s', '%s')", $i, $label, $label, $label))) { $errors[] = sprintf("TRUNCATE failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 3; } } $times[sprintf("%7d: overall", $num_rows)] = $start = microtime(true); if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("stmt_init() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } if (!mysqli_stmt_prepare($stmt, 'SELECT * FROM test')) { $errors[] = sprintf("stmt_prepare() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("stmt_execute() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } $row = array(0 => null, 1 => null, 2 => null, 3 => null); if (!mysqli_stmt_bind_result($stmt, $row[0], $row[1], $row[2], $row[3])) { $errors[] = sprintf("stmt_execute() failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } $times[sprintf("%7d: query", $num_rows)] = (microtime(true) - $start); $start = microtime(true); while (mysqli_stmt_fetch($stmt)) ; $times[sprintf("%7d: stmt_fetch()", $num_rows)] = (microtime(true) - $start); $times[sprintf("%7d: overall", $num_rows)] = (microtime(true) - $times[sprintf("%7d: overall", $num_rows)]); } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/georg_bench1.php0000664000175000017500000000417212161007456023320 0ustar andreyandrey 0, 'INSERT' => 0, 'Connect and SELECT' => 0, ); do { $times['overall'] = microtime(true); if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Cannot connect: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); break; } if (!$mysqli->query("DROP TABLE IF EXISTS t1")) { $errors[] = sprintf("Cannot DROP: [%d] %s\n", $mysqli->errno, $mysqli->error); break; } if (!$mysqli->query("CREATE TABLE t1 (a int not null auto_increment primary key, b varchar(48), c varchar(48), d varchar(48))")) { $errors[] = sprintf("Cannot CREATE: [%d] %s\n", $mysqli->errno, $mysqli->error); break; } $times['INSERT'] = microtime(true); for ($i = 0; $i < $runs; $i++) { $val = md5(microtime(true)); if (!$mysqli->query("INSERT INTO t1 VALUES (0, '$val', '$val', '$val')")) { $errors[] = sprintf("Cannot INSERT: [%d] %s\n", $mysqli->errno, $mysqli->error); break; } } $times['INSERT'] = microtime(true) - $times['INSERT']; $mysqli->close(); $client = mysqli_get_client_info(); $host = ((substr($client, 0, 7) == 'mysqlnd')) ? 'p:' . $host : $host; $times['Connect and SELECT'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Cannot connect (2): [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); break 2; } $val = md5(microtime()); if (!$result = $mysqli->query("SELECT * FROM t1 LIMIT 3")) { $errors[] = sprintf("Cannot SELECT: [%d] %s\n", $mysqli->errno, $mysqli->error); break 2; } $j = 0; while ($row = $result->fetch_row()) $j++; if ($j != 3) { $errors[] = sprintf("Fetching failed: [%d] %s\n", $mysqli->errno, $mysqli->error); break 2; } $result->close(); $mysqli->close(); } $times['Connect and SELECT'] = microtime(true) - $times['Connect and SELECT']; $times['overall'] = microtime(true) - $times['overall']; } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/georg_bench2.php0000664000175000017500000000467012161007456023324 0ustar andreyandrey 0, 'INSERT warmup' => 0, 'SELECT count(*)' => 0, 'TRUNCATE' => 0, 'INSERT final' => 0, ); do { $times['overall'] = microtime(true); if (!$conn = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Cannot connect: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); break; } if (!mysqli_query($conn, "DROP TABLE IF EXISTS t1")) { $errors[] = sprintf("Cannot drop: [%d] %s\n", mysqli_errno($conn), mysqli_error($conn)); break; } if (!mysqli_query($conn, "CREATE TABLE t1 (a int not null auto_increment primary key, b varchar(48), c varchar(48), d varchar(48))")) { $errors[] = sprintf("Cannot create table: [%d] %s\n", mysqli_errno($conn), mysqli_error($conn)); break; } $times['INSERT warmup'] = microtime(true); for ($i = 0; $i < $rows; $i++) { $val = md5(microtime(true)); if (!mysqli_query($conn, "INSERT INTO t1 VALUES (0, '$val', '$val', '$val')")) { $errors[] = sprintf("Cannot insert (1): [%d] %s\n", mysqli_errno($conn), mysqli_error($conn)); break 2; } } $times['INSERT warmup'] = microtime(true) - $times['INSERT warmup']; $times['SELECT count(*)'] = microtime(true); if (!$result = mysqli_query($conn, "SELECT count(*) FROM t1")) { $errors[] = sprintf("SELECT failed: [%d] %s\n", mysqli_errno($conn), mysqli_error($conn)); break; } if (!$row = mysqli_fetch_row($result)) { $errors[] = sprintf("Fetch failed: [%d] %s\n", mysqli_errno($conn), mysqli_error($conn)); break; } $times['SELECT count(*)'] = microtime(true) - $times['SELECT count(*)']; $times['TRUNCATE'] = microtime(true); mysqli_query($conn, "truncate table t1"); $times['TRUNCATE'] = microtime(true) - $times['TRUNCATE']; $times['INSERT final'] = microtime(true); for ($i = 0; $i < $rows; $i++) { $val = md5(microtime(true)); if (!mysqli_query($conn, "INSERT INTO t1 VALUES (0, '$val', '$val', '$val')")) { $errors[] = sprintf("Cannot insert (2): [%d] %s\n", mysqli_errno($conn), mysqli_error($conn)); break 2; } } $times['INSERT final'] = microtime(true) - $times['INSERT final']; mysqli_close($conn); $times['overall'] = microtime(true) - $times['overall']; } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_affected_rows.php0000664000175000017500000000521712161007456025207 0ustar andreyandrey $num_runs) { foreach ($rows as $k => $num_rows) { $times[$num_rows . ' rows: ' . $num_runs . 'x overall'] = 0; $times[$num_rows . ' rows: ' . $num_runs . 'x affected_rows()'] = 0; } } $description = 'Connect, n-times INSERT a row and call m-times mysqli_affected_rows() after the INSERT, close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } if (!mysqli_query($link, "CREATE TABLE test(id INT, label char(1))")) { $errors[] = sprintf("CREATE TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $num_runs) { // create n-rows if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("Connect DELETE (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $times[$num_rows . ' rows: ' . $num_runs . 'x overall'] = microtime(true); for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (" . $i . ", 'a')")) { $errors[] = sprintf("Connect DROP TABLE (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } for ($j = 0; $j < $num_runs; $j++) { $start = microtime(true); if (1 != mysqli_affected_rows($link)) { $errors[] = sprintf("Connect DROP TABLE (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } $times[$num_rows . ' rows: ' . $num_runs . 'x affected_rows()'] += (microtime(true) - $start); } } $times[$num_rows . ' rows: ' . $num_runs . 'x overall'] = microtime(true) - $times[$num_rows . ' rows: ' . $num_runs . 'x overall']; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_connect_and_close.php0000664000175000017500000000373512161007456026037 0ustar andreyandrey 0, 'Connect TCP/IP failure' => 0, 'Connect Socket success' => 0, 'Connect Socket failure' => 0, ); $description = 'Connect with mysqli_connect() and close, no query.'; $errors = array(); $times['Connect TCP/IP success'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'Connect TCP/IP success' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } mysqli_close($link); } $times['Connect TCP/IP success'] = microtime(true) - $times['Connect TCP/IP success']; $times['Connect TCP/IP failure'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if ($link = @mysqli_connect($host, $user, $passwd . '_unknown', $db, $port)) { $errors[] = sprintf("'Connect TCP/IP failure' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect TCP/IP failure'] = microtime(true) - $times['Connect TCP/IP failure']; $times['Connect Socket success'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'Connect Socket success' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } mysqli_close($link); } $times['Connect Socket success'] = microtime(true) - $times['Connect Socket success']; $times['Connect Socket failure'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if ($link = @mysqli_connect($host, $user, $passwd . '_unknown', $db, $port, $socket)) { $errors[] = sprintf("'Connect Socket failure' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect Socket failure'] = microtime(true) - $times['Connect Socket failure']; // sort by runtime in descending order arsort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_connect.php0000664000175000017500000000365112161007456024025 0ustar andreyandrey 0, 'Connect TCP/IP failure' => 0, 'Connect Socket success' => 0, 'Connect Socket failure' => 0, ); $description = 'Connect without closing.'; $errors = array(); $times['Connect TCP/IP success'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'Connect TCP/IP success' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect TCP/IP success'] = microtime(true) - $times['Connect TCP/IP success']; $times['Connect TCP/IP failure'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if ($link = @mysqli_connect($host, $user, $passwd . '_unknown', $db, $port, $socket)) { $errors[] = sprintf("'Connect TCP/IP failure' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect TCP/IP failure'] = microtime(true) - $times['Connect TCP/IP failure']; $times['Connect Socket success'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'Connect Socket success' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect Socket success'] = microtime(true) - $times['Connect Socket success']; $times['Connect Socket failure'] = microtime(true); for ($i = 0; $i < $runs; $i++) { if ($link = @mysqli_connect($host, $user, $passwd . '_unknown', $db, $port, $socket)) { $errors[] = sprintf("'Connect Socket failure' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect Socket failure'] = microtime(true) - $times['Connect Socket failure']; // sort by runtime in descending order arsort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_data_seek_random.php0000664000175000017500000001155212161007456025653 0ustar andreyandrey 'varchar(16)', 32 => 'varchar(32)', 64 => 'varchar(64)', 128 => 'varchar(128)', 256 => 'varchar(256)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4192 => 'varchar(4192)', 8384 => 'varchar(8384)', 16768 => 'varchar(16768)', 33536 => 'varchar(33536)', 65500 => 'varchar(65500)' ); foreach ($runs as $k => $num_runs) { foreach ($rows as $k => $num_rows) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = 0; $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] = 0; } } } $description = 'Connect, create n-rows with varchar(m), SELECT all, o-times [$runs] mysqli_data_seek(mt_rand()), close. n, m and o vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($types as $len => $type) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } $sql = sprintf("CREATE TABLE test(id INT, label %s)", $type); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("CREATE TABLE (%s) failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $num_runs) { // create n-rows if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } $label = str_repeat('a', $len); for ($i = 0; $i < $num_rows; $i++) { $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, '%s')", $i, $label); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("INSERT failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } } if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } mt_srand(); $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true); for ($i = 0; $i < $num_runs; $i++) { $pos = mt_rand(0, $num_rows - 1); $start = microtime(true); if (!mysqli_data_seek($res, $pos)) { $errors[] = sprintf("seek() to %d of %d rows failed (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] += (microtime(true) - $start); if (!$row = mysqli_fetch_assoc($res)) { $errors[] = sprintf("fetch_assoc() for %dth of %d rows failed (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } if ($row['id'] != $pos) { $errors[] = sprintf("seek() + fetch() for %dth of %d rows did not work (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); var_dump($row); var_dump($pos); break 5; } } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true) - $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall']; mysqli_free_result($res); } } } // end foreach types mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_data_seek_random_php_run_normal.php0000664000175000017500000000117112161007456030752 0ustar andreyandrey $times, "errors" => $errors, "memory" => (isset($memory)) ? $memory : NULL); $fp = fopen("/home/nixnutz/src/mysqlnd/tests/ext/mysqli/bench/micro_benches/mysqli_data_seek_random.php" . ".res", "w"); fwrite($fp, serialize($all)); fclose($fp); print "done!"; ?> mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_data_seek_sequential.php0000664000175000017500000001160012161007456026537 0ustar andreyandrey 'varchar(16)', 32 => 'varchar(32)', 64 => 'varchar(64)', 128 => 'varchar(128)', 256 => 'varchar(256)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4192 => 'varchar(4192)', 8384 => 'varchar(8384)', 16768 => 'varchar(16768)', 33536 => 'varchar(33536)', 65500 => 'varchar(65500)' ); foreach ($runs as $k => $num_runs) { foreach ($rows as $k => $num_rows) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = 0; $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] = 0; } } } $description = 'Connect, create n-rows with varchar(m), SELECT all, fetch them in reverse order using o-times [$runs] mysqli_data_seek(n...0), close. n, m and o vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($types as $len => $type) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } $sql = sprintf("CREATE TABLE test(id INT, label %s)", $type); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("CREATE TABLE (%s) failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $num_runs) { // create n-rows if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } $label = str_repeat('a', $len); for ($i = 0; $i < $num_rows; $i++) { $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, '%s')", $i, $label); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("INSERT failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } } if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } mt_srand(); $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true); for ($i = $num_rows - 1; $i >= 0; $i--) { $pos = $i; $start = microtime(true); if (!mysqli_data_seek($res, $pos)) { $errors[] = sprintf("seek() to %d of %d rows failed (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] += (microtime(true) - $start); if (!$row = mysqli_fetch_assoc($res)) { $errors[] = sprintf("fetch_assoc() for %dth of %d rows failed (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } if ($row['id'] != $pos) { $errors[] = sprintf("seek() + fetch() for %dth of %d rows did not work (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); var_dump($row); var_dump($pos); break 5; } } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true) - $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall']; mysqli_free_result($res); } } } // end foreach types mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_fetch_all_vs_fetch_array.php0000664000175000017500000001735112161007456027376 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', 65000 => 'varchar(65000)', ); $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() overall'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() SELECT'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() fetch'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() overall'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() SELECT'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() fetch'] = 0; } } } $description = 'Connect, create n rows with varchar of size m, o-times SELECT all rows (buffered) - with fetch_all and fetch_array, close. n, m, o vary.'; $errors = array(); function mysqli_fetch_all_vs_fetch_array($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code) { $errors = $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("%d rows: SELECT %s %dx connect failure (original code = %s)", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 3; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("%d rows: SELECT %s %dx drop table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("%d rows: SELECT %s %dx create table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); $label = mysqli_real_escape_string($link, $label); for ($i = 1; $i <= $num_rows; $i++) { if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, '$label')")) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } $client = mysqli_get_client_info(); $have_mysqlnd = ((substr($client, 0, 7) == 'mysqlnd')) ? true : false; if ($have_mysqlnd) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() overall'] = microtime(true); for ($i = 0; $i < $run; $i++) { $start = microtime(true); $res = mysqli_query($link, "SELECT id, label FROM test"); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() SELECT'] += (microtime(true) - $start); if (!$res) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); $result1 = mysqli_fetch_all($res, MYSQLI_NUM); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() fetch'] += (microtime(true) - $start); if ((count($result1) != $num_rows) || ($result1[0][0] != 1)) { $errors[] = sprintf("%d rows: fetch_all() results seem faulty %s %dx failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } mysqli_free_result($res); } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() overall'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() overall']; } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() overall'] = microtime(true); for ($i = 0; $i < $run; $i++) { $start = microtime(true); $res = mysqli_query($link, "SELECT id, label FROM test"); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() SELECT'] += (microtime(true) - $start); if (!$res) { $errors[] = sprintf("%d rows: SELECT %s %dx failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); $result2 = array(); while ($result2[] = mysqli_fetch_array($res, MYSQLI_NUM)) ; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() fetch'] += (microtime(true) - $start); // we have one NULL at the end of result2[] because of the loop if ((count($result2) != ($num_rows + 1)) || ($result2[0][0] != 1)) { $errors[] = sprintf("%d rows: fetch_array() results seem faulty %s %dx failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } mysqli_free_result($res); } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() overall'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() overall']; if (!$have_mysqlnd) { // NOTE: for mysqli @ libmysql (which does not have a fetch_all()), we use the fetch_array values! $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() overall'] = $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() overall']; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() SELECT'] = $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() SELECT']; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_all() fetch'] = $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_array() fetch']; } mysqli_close($link); } while (false); } } return array($errors, $times); } foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_fetch_all_vs_fetch_array($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } // sort by labels ksort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_fetch_field_direct.php0000664000175000017500000000766012161007456026166 0ustar andreyandrey 'varchar(16)', 255 => 'varchar(255)'); foreach ($runs as $k => $num_runs) { foreach ($fields as $k => $num_fields) { foreach ($types as $len => $type) { $times[$num_fields . ' fields: ' . $num_runs . 'x ' . $type . ' overall'] = 0; $times[$num_fields . ' fields: ' . $num_runs . 'x ' . $type . ' data_seek()'] = 0; } } } $description = 'Connect, create 1 row with n varchar(m) columns, SELECT all, o-times mysqli_fetch_field_direct(n...0), close. n, m and o vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($types as $len => $type) { foreach ($fields as $k => $num_fields) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } // create 1 row with n varchar(m) columns $sql = 'CREATE TABLE test('; for ($i = 0; $i < $num_fields; $i++) { $sql .= sprintf("c%d %s, ", $i, $type); } $sql = substr($sql, 0, -2) . ')'; if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $label = str_repeat('a', $len); $columns = $values = ''; for ($i = 0; $i < $num_fields; $i++) { $columns .= sprintf("c%d, ", $i); $values .= sprintf("'%s', ", $label); } $sql = sprintf("INSERT INTO test(%s) VALUES (%s)", substr($columns, 0, -2), substr($values, 0, -2)); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("INSERT failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $times[$num_fields . ' fields: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true); if (!$res = mysqli_query($link, "SELECT * FROM test")) { $errors[] = sprintf("SELECT failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } foreach ($runs as $k => $num_runs) { for ($i = $num_fields - 1; $i >= 0; $i--) { $start = microtime(true); for ($j = 0; $j < $num_runs; $j++) { if (!is_object($obj = mysqli_fetch_field_direct($res, $i))) { $errors[] = sprintf("fetch_field_direct() failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 6; } } $times[$num_fields . ' fields: ' . $num_runs . 'x ' . $type . ' data_seek()'] += (microtime(true) - $start); if ($obj->name != "c$i") { $errors[] = sprintf("fetched object seems wrong (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } } } mysqli_free_result($res); $times[$num_fields . ' fields: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true) - $times[$num_fields . ' fields: ' . $num_runs . 'x ' . $type . ' overall']; } } // end foreach types mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_fetch_long_buffered.php0000664000175000017500000001070212161007456026341 0ustar andreyandrey $num_rows) { foreach ($long_lengths as $k => $len) { $times[$num_rows . " row[s]: " . $len . " k SELECT overall"] = 0; $times[$num_rows . " row[s]: " . $len . " k SELECT query()"] = 0; } } $description = 'Connect, create n-rows with one m-kb LONG column, SELECT all (buffered), close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } $sql = "CREATE TABLE test(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, label LONGBLOB)"; if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } sort($long_lengths); $max_len = end($long_lengths) * 1024; if (!mysqli_query($link, $sql = sprintf("SET GLOBAL max_allowed_packet = %d", $max_len + 100))) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } foreach ($rows as $k => $num_rows) { foreach ($long_lengths as $k => $len) { if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $length_bytes = $len * 1024; $current_len = 20; if (!mysqli_query($link, "INSERT INTO test(label) VALUES ('12345678901234567890')")) { $errors[] = sprintf("INSERT failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $id = mysqli_insert_id($link); while ($current_len < ($length_bytes / 2)) { if (!mysqli_query($link, "UPDATE test SET label = CONCAT(label, label)")) { $errors[] = sprintf("UPDATE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } $current_len += $current_len; } if (!mysqli_query($link, sprintf("UPDATE test SET label = CONCAT(label, LEFT(label, %d))", ($length_bytes - $current_len)))) { $errors[] = sprintf("UPDATE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } for ($i = 1; $i < $num_rows; $i++) { if (!mysqli_query($link, sprintf("INSERT INTO test(label) SELECT label FROM test WHERE id = %d", $id))) { $errors[] = sprintf("INSERT rows failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } } $times[$num_rows . " row[s]: " . $len . " k SELECT overall"] = $start = microtime(true); if (!$res = mysqli_query($link, "SELECT id, label FROM test")) { $errors[] = sprintf("SELECT failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $times[$num_rows . " row[s]: " . $len . " k SELECT query()"] += (microtime(true) - $start); while ($row = mysqli_fetch_assoc($res)) if (strlen($row['label']) != $length_bytes) { $errors[] = sprintf("fetch() failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } mysqli_free_result($res); $times[$num_rows . " row[s]: " . $len . " k SELECT overall"] = microtime(true) - $times[$num_rows . " row[s]: " . $len . " k SELECT overall"]; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_fetch_long_unbuffered.php0000664000175000017500000001074712161007456026715 0ustar andreyandrey $num_rows) { foreach ($long_lengths as $k => $len) { $times[$num_rows . " row[s]: " . $len . " k SELECT overall"] = 0; $times[$num_rows . " row[s]: " . $len . " k SELECT query()"] = 0; } } $description = 'Connect, create n-rows with one m-kb LONG column, SELECT all (buffered), close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } $sql = "CREATE TABLE test(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, label LONGBLOB)"; if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } sort($long_lengths); $max_len = end($long_lengths) * 1024; if (!mysqli_query($link, $sql = sprintf("SET GLOBAL max_allowed_packet = %d", $max_len + 100))) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } foreach ($rows as $k => $num_rows) { foreach ($long_lengths as $k => $len) { if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $length_bytes = $len * 1024; $current_len = 20; if (!mysqli_query($link, "INSERT INTO test(label) VALUES ('12345678901234567890')")) { $errors[] = sprintf("INSERT failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $id = mysqli_insert_id($link); while ($current_len < ($length_bytes / 2)) { if (!mysqli_query($link, "UPDATE test SET label = CONCAT(label, label)")) { $errors[] = sprintf("UPDATE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } $current_len += $current_len; } if (!mysqli_query($link, sprintf("UPDATE test SET label = CONCAT(label, LEFT(label, %d))", ($length_bytes - $current_len)))) { $errors[] = sprintf("UPDATE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } for ($i = 1; $i < $num_rows; $i++) { if (!mysqli_query($link, sprintf("INSERT INTO test(label) SELECT label FROM test WHERE id = %d", $id))) { $errors[] = sprintf("INSERT rows failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } } $times[$num_rows . " row[s]: " . $len . " k SELECT overall"] = $start = microtime(true); if (!mysqli_real_query($link, "SELECT id, label FROM test")) { $errors[] = sprintf("SELECT failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $times[$num_rows . " row[s]: " . $len . " k SELECT query()"] += (microtime(true) - $start); $res = mysqli_use_result($link); while ($row = mysqli_fetch_assoc($res)) if (strlen($row['label']) != $length_bytes) { $errors[] = sprintf("fetch() failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } mysqli_free_result($res); $times[$num_rows . " row[s]: " . $len . " k SELECT overall"] = microtime(true) - $times[$num_rows . " row[s]: " . $len . " k SELECT overall"]; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_fetch_long_unbuffered_php_run_normal.php0000664000175000017500000000116412161007456032011 0ustar andreyandrey $times, "errors" => $errors, "memory" => (isset($memory)) ? $memory : NULL); $fp = fopen("/home/nixnutz/src/mysqlnd/tests/ext/mysqli/bench/micro_benches/mysqli_fetch_long_unbuffered.php" . ".res", "w"); fwrite($fp, serialize($all)); fclose($fp); print "done!"; ?> mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_insert_id.php0000664000175000017500000000443012161007456024350 0ustar andreyandrey $num_rows) { $times[$num_rows . 'rows: overall'] = 0; $times[$num_rows . 'rows: insert_id()'] = 0; } $description = 'Connect, n-times INSERT a row and call insert_id(), close.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } $sql = "CREATE TABLE test(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, label varchar(2))"; if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } foreach ($rows as $k => $num_rows) { if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $num_rows, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } $times[$num_rows . 'rows: overall'] = microtime(true); for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, "INSERT INTO test(label) VALUES ('a')")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $num_rows, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $start = microtime(true); if (0 == mysqli_insert_id($link)) { $errors[] = sprintf("insert_id() failed (%s) (converted code: %s): [%d] %s\n", $num_rows, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $times[$num_rows . 'rows: insert_id()'] += (microtime(true) - $start); } $times[$num_rows . 'rows: overall'] = microtime(true) - $times[$num_rows . 'rows: overall']; } } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_many_cols_buf.php0000664000175000017500000001655112161007456025217 0ustar andreyandrey 1, "name" => "c_tinyint", "type" => "TINYINT", "value" => 1), array("len" => 2, "name" => "c_smallint", "type" => "SMALLINT", "value" => 1), array("len" => 200, "name" => "c_varchar_199", "type" => "varchar(199)", "value" => "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 3, "name" => "c_mediumint", "type" => "MEDIUMINT", "value" => 1), array("len" => 20, "name" => "c_varchar_19", "type" => "varchar(19)", "value" => "0123456789012345678"), array("len" => 4, "name" => "c_int", "type" => "INT", "value" => 1), array("len" => 8, "name" => "c_bigint", "type" => "BIGINT", "value" => 1), array("len" => 50, "name" => "c_varchar_49", "type" => "varchar(49)", "value" => "0123456789012345678901234567890123456789012345678"), array("len" => 4, "name" => "c_float_24", "type" => "FLOAT(24)", "value" => 1), array("len" => 150, "name" => "c_varchar_149", "type" => "varchar(149)", "value" => "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 8, "name" => "c_float_25", "type" => "FLOAT(25)", "value" => 1), array("len" => 4, "name" => "c_float", "type" => "FLOAT", "value" => 1), array("len" => 8, "name" => "c_double", "type" => "DOUBLE", "value" => 1), array("len" => 100, "name" => "c_varchar_99", "type" => "varchar(99)", "value" => "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 3, "name" => "c_date", "type" => "DATE", "value" => "2007-01-17"), array("len" => 8, "name" => "c_datetime", "type" => "DATETIME", "value" => "2007-01-17 11:53:00"), array("len" => 4, "name" => "c_timestamp", "type" => "TIMESTAMP", "value" => "2007-01-17 11:54:00"), array("len" => 3, "name" => "c_time", "type" => "TIME", "value" => "11:54:00"), array("len" => 1, "name" => "c_year", "type" => "YEAR", "value" => "2007"), array("len" => 10, "name" => "c_char_10", "type" => "CHAR(10)", "value" => "0123456789"), array("len" => 1, "name" => "c_enum", "type" => "ENUM('true', 'false')", "value" => "true"), // let's assume latin1 array("len" => 300, "name" => "c_varchar_99", "type" => "varchar(298)", "value" => "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"), ); $rows = array(2000); foreach ($rows as $k => $num_rows) { foreach ($columns as $k => $num_columns) { $num_column_types = count($column_types); $total_len = 0; for ($i = 0; $i < $num_columns; $i++) { $total_len += $column_types[$i % $num_column_types]['len']; } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = 0; $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) fetch()'] = 0; } } $description = 'Connect, create n-rows with one m-columns of different types, SELECT all (buffered), close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($rows as $k => $num_rows) { foreach ($columns as $k => $num_columns) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $num_column_types = count($column_types); $total_len = 0; $column_names = $column_defs = $column_values = ''; for ($i = 0; $i < $num_columns; $i++) { $index = $i % $num_column_types; $total_len += $column_types[$index]['len']; $column_names .= sprintf("%s_%d, ", $column_types[$index]['name'], $i); $column_defs .= sprintf("%s_%d %s, ", $column_types[$index]['name'], $i, $column_types[$index]['type']); $column_values .= sprintf("%s%s%s, ", (is_string($column_types[$index]['value'])) ? '"' : '', $column_types[$index]['value'], (is_string($column_types[$index]['value'])) ? '"' : '' ); } $last_column = sprintf("%s_%d", $column_types[$index]['name'], $i - 1); $last_value = $column_types[$index]['value']; $sql = sprintf("CREATE TABLE test(%s)", substr($column_defs, 0, -2)); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $sql = sprintf("INSERT INTO test(%s) VALUES (%s)", substr($column_names, 0, -2), substr($column_values, 0, -2)); for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = microtime(true); if (!$res = mysqli_query($link, 'SELECT * FROM test')) { $errors[] = sprintf("SELECT failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $start = microtime(true); while ($row = mysqli_fetch_assoc($res)) if ($row[$last_column] != $last_value) { $errors[] = sprintf("fetch() failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); var_dump($row); var_dump($last_column); var_dump($last_value); break 4; } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) fetch()'] += (microtime(true) - $start); mysqli_free_result($res); $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = microtime(true) - $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall']; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_many_cols_unbuf.php0000664000175000017500000001717712161007456025567 0ustar andreyandrey 1, "name" => "c_tinyint", "type" => "TINYINT", "value" => 1), array("len" => 2, "name" => "c_smallint", "type" => "SMALLINT", "value" => 1), array("len" => 200, "name" => "c_varchar_199", "type" => "varchar(199)", "value" => "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 3, "name" => "c_mediumint", "type" => "MEDIUMINT", "value" => 1), array("len" => 20, "name" => "c_varchar_19", "type" => "varchar(19)", "value" => "0123456789012345678"), array("len" => 4, "name" => "c_int", "type" => "INT", "value" => 1), array("len" => 8, "name" => "c_bigint", "type" => "BIGINT", "value" => 1), array("len" => 50, "name" => "c_varchar_49", "type" => "varchar(49)", "value" => "0123456789012345678901234567890123456789012345678"), array("len" => 4, "name" => "c_float_24", "type" => "FLOAT(24)", "value" => 1), array("len" => 150, "name" => "c_varchar_149", "type" => "varchar(149)", "value" => "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 8, "name" => "c_float_25", "type" => "FLOAT(25)", "value" => 1), array("len" => 4, "name" => "c_float", "type" => "FLOAT", "value" => 1), array("len" => 8, "name" => "c_double", "type" => "DOUBLE", "value" => 1), array("len" => 100, "name" => "c_varchar_99", "type" => "varchar(99)", "value" => "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 3, "name" => "c_date", "type" => "DATE", "value" => "2007-01-17"), array("len" => 8, "name" => "c_datetime", "type" => "DATETIME", "value" => "2007-01-17 11:53:00"), array("len" => 4, "name" => "c_timestamp", "type" => "TIMESTAMP", "value" => "2007-01-17 11:54:00"), array("len" => 3, "name" => "c_time", "type" => "TIME", "value" => "11:54:00"), array("len" => 1, "name" => "c_year", "type" => "YEAR", "value" => "2007"), array("len" => 10, "name" => "c_char_10", "type" => "CHAR(10)", "value" => "0123456789"), array("len" => 1, "name" => "c_enum", "type" => "ENUM('true', 'false')", "value" => "true"), // let's assume latin1 array("len" => 300, "name" => "c_varchar_99", "type" => "varchar(298)", "value" => "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"), ); $rows = array(2000); foreach ($rows as $k => $num_rows) { foreach ($columns as $k => $num_columns) { $num_column_types = count($column_types); $total_len = 0; for ($i = 0; $i < $num_columns; $i++) { $total_len += $column_types[$i % $num_column_types]['len']; } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = 0; $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) fetch()'] = 0; } } $description = 'Connect, create n-rows with one m-columns of different types, SELECT all (buffered), close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($rows as $k => $num_rows) { foreach ($columns as $k => $num_columns) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $num_column_types = count($column_types); $total_len = 0; $column_names = $column_defs = $column_values = ''; for ($i = 0; $i < $num_columns; $i++) { $index = $i % $num_column_types; $total_len += $column_types[$index]['len']; $column_names .= sprintf("%s_%d, ", $column_types[$index]['name'], $i); $column_defs .= sprintf("%s_%d %s, ", $column_types[$index]['name'], $i, $column_types[$index]['type']); $column_values .= sprintf("%s%s%s, ", (is_string($column_types[$index]['value'])) ? '"' : '', $column_types[$index]['value'], (is_string($column_types[$index]['value'])) ? '"' : '' ); } $last_column = sprintf("%s_%d", $column_types[$index]['name'], $i - 1); $last_value = $column_types[$index]['value']; $sql = sprintf("CREATE TABLE test(%s)", substr($column_defs, 0, -2)); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $sql = sprintf("INSERT INTO test(%s) VALUES (%s)", substr($column_names, 0, -2), substr($column_values, 0, -2)); for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = microtime(true); if (!mysqli_real_query($link, 'SELECT * FROM test')) { $errors[] = sprintf("SELECT failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } if (!$res = mysqli_use_result($link)) { $errors[] = sprintf("use_result() failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $start = microtime(true); while ($row = mysqli_fetch_assoc($res)) if ($row[$last_column] != $last_value) { $errors[] = sprintf("fetch() failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); var_dump($row); var_dump($last_column); var_dump($last_value); break 4; } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) fetch()'] += (microtime(true) - $start); mysqli_free_result($res); $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = microtime(true) - $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall']; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_query_insert_varchar.php0000664000175000017500000000601512161007456026630 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', ); foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times['INSERT ' . $type . ' ' . $run . 'x = #rows query()'] = 0; $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall'] = 0; } } $description = 'Connect, n-times INSERT varchar of size m, close. n and m vary.'; $errors = array(); function mysqli_query_insert($type, $len, $runs, $host, $user, $passwd, $db, $port, $socket) { $errors = $times = array(); foreach ($runs as $k => $run) { $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("INSERT %s %dx = #rows connect failure (original code = %s)", $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 2; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("INSERT %s %dx = #rows drop table failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("INSERT %s %dx = #rows create table failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); $label = mysqli_real_escape_string($link, $label); for ($i = 1; $i <= $run; $i++) { $start = microtime(true); $ret = mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, '$label')"); $times['INSERT ' . $type . ' ' . $run . 'x = #rows query()'] += microtime(true) - $start; if (!$ret) { $errors[] = sprintf("INSERT %s %dx = #rows insert failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } mysqli_close($link); } while (false); $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall'] = microtime(true) - $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall']; } return array($errors, $times); } ksort($types); foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_insert($type, $len, $runs, $host, $user, $passwd, $db, $port, $socket); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_query_update_varchar.php0000664000175000017500000000675412161007456026620 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', 65000 => 'varchar(65000)', ); foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times['UPDATE ' . $type . ' ' . $run . 'x query()'] = 0; $times['UPDATE ' . $type . ' ' . $run . 'x overall'] = 0; } } $description = 'Connect, create 100 random rows with varchar of size m, o-times UPDATE random row, close. n, m, o vary.'; $errors = array(); function mysqli_query_update($type, $len, $runs, $host, $user, $passwd, $db, $port, $socket) { $errors = $times = array(); foreach ($runs as $k => $run) { $times['UPDATE ' . $type . ' ' . $run . 'x overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("UPDATE %s %dx connect failure (original code = %s)", $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 2; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("UPDATE %s %dx drop table failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("UPDATE %s %dx create table failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); $label = mysqli_real_escape_string($link, $label); for ($i = 1; $i <= 100; $i++) { if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, '$label')")) { $errors[] = sprintf("UPDATE %s %dx insert failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } $label = str_repeat('a', $len); $id = 0; for ($i = 0; $i < $run; $i++) { $id = (++$id > 100) ? 1 : $id; $sql = "UPDATE test SET label = '" . $label . "' WHERE id = " . $id; $start = microtime(true); $ret = mysqli_query($link, $sql); $times['UPDATE ' . $type . ' ' . $run . 'x query()'] += microtime(true) - $start; if (!$ret) { $errors[] = sprintf("UPDATE %s %dx insert failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } mysqli_close($link); $times['UPDATE ' . $type . ' ' . $run . 'x overall'] = microtime(true) - $times['UPDATE ' . $type . ' ' . $run . 'x overall']; } while (false); } return array($errors, $times); } ksort($types); foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_update($type, $len, $runs, $host, $user, $passwd, $db, $port, $socket); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } // sort by labels ksort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_real_connect_and_close.php0000664000175000017500000000416112161007456027034 0ustar andreyandrey 0, 'Connect TCP/IP failure' => 0, 'Connect Socket success' => 0, 'Connect Socket failure' => 0, ); $description = 'Connect with mysqli_init() + mysqli_real_connect() and close, no query.'; $errors = array(); $times['Connect TCP/IP success'] = microtime(true); for ($i = 0; $i < $runs; $i++) { $link = mysqli_init(); if (!@mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'Connect TCP/IP success' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } mysqli_close($link); } $times['Connect TCP/IP success'] = microtime(true) - $times['Connect TCP/IP success']; $times['Connect TCP/IP failure'] = microtime(true); for ($i = 0; $i < $runs; $i++) { $link = mysqli_init(); if (@mysqli_real_connect($link, $host, $user, $passwd . '_unknown', $db, $port, $socket)) { $errors[] = sprintf("'Connect TCP/IP failure' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no' ); break; } } $times['Connect TCP/IP failure'] = microtime(true) - $times['Connect TCP/IP failure']; $times['Connect Socket success'] = microtime(true); for ($i = 0; $i < $runs; $i++) { $link = mysqli_init(); if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'Connect Socket success' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } mysqli_close($link); } $times['Connect Socket success'] = microtime(true) - $times['Connect Socket success']; $times['Connect Socket failure'] = microtime(true); for ($i = 0; $i < $runs; $i++) { $link = mysqli_init(); if (@mysqli_real_connect($link, $host, $user, $passwd . '_unknown', $db, $port, $socket)) { $errors[] = sprintf("'Connect Socket failure' failure [original code: %s]", ($flag_original_code) ? 'yes' : 'no'); break; } } $times['Connect Socket failure'] = microtime(true) - $times['Connect Socket failure']; // sort by runtime in descending order arsort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_real_query.php0000664000175000017500000000170112161007456024536 0ustar andreyandrey $num_runs) { $times[$num_runs . 'x overall'] = 0; $times[$num_runs . 'x mysqli_real_query()'] = 0; } $description = 'Connect, n-times mysqli_real_query(SELECT 1) [no payload], close. n varies.'; $errors = array(); foreach ($runs as $k => $num_runs) { $times[$num_runs . 'x overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("'SELECT 1' connect failure"); break 2; } for ($i = 0; $i < $num_runs; $i++) { $start = microtime(true); mysqli_real_query($link, "SELECT 1"); $times[$num_runs . 'x mysqli_real_query()'] += (microtime(true) - $start); } mysqli_close($link); } while (false); $times[$num_runs . 'x overall'] = microtime(true) - $times[$num_runs . 'x overall']; } // sort by runtime in descending order arsort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_select_varchar_buffered.php0000664000175000017500000001542312161007456027223 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', 65000 => 'varchar(65000)', ); $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall simple query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall real_query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x real_query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x store_result()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc() @ store_result()'] = 0; } } } $description = 'Connect, create n rows with varchar of size m, o-times SELECT all rows (buffered), close. n, m, o vary.'; $errors = array(); function mysqli_query_select_varchar_buffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code) { $errors = $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("%d rows: SELECT %s %dx connect failure (original code = %s)", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 3; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("%d rows: SELECT %s %dx drop table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("%d rows: SELECT %s %dx create table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); $label = mysqli_real_escape_string($link, $label); for ($i = 1; $i <= $num_rows; $i++) { if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, '$label')")) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall simple query()'] = microtime(true); for ($i = 0; $i < $run; $i++) { $start = microtime(true); $res = mysqli_query($link, "SELECT id, label FROM test"); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x query()'] += (microtime(true) - $start); if (!$res) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); while ($row = mysqli_fetch_assoc($res)) ; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc()'] += (microtime(true) - $start); mysqli_free_result($res); } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall simple query()'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall simple query()']; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall real_query()'] = microtime(true); for ($i = 0; $i < $run; $i++) { $start = microtime(true); $res = mysqli_real_query($link, "SELECT id, label FROM test"); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x real_query()'] += (microtime(true) - $start); if (!$res) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); if (!$res = mysqli_store_result($link)) { $errors[] = sprintf("%d rows: store_result() failed (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x store_result()'] += (microtime(true) - $start); $start = microtime(true); while ($row = mysqli_fetch_assoc($res)) ; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc() @ store_result()'] += (microtime(true) - $start); mysqli_free_result($res); } $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall real_query()'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall real_query()']; mysqli_close($link); } while (false); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall']; } } return array($errors, $times); } foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_select_varchar_buffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } // sort by labels ksort($times); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_sel_unbuf.php0000664000175000017500000001055312161007456024355 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', 65000 => 'varchar(65000)', ); $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc()'] = 0; } } } $description = 'Connect, create n rows with varchar of size m, o-times SELECT all rows (unbuffered), close. n, m, o vary.'; $errors = array(); function mysqli_query_select_varchar_unbuffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code) { $errors = $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("%d rows: SELECT %s %dx connect failure (original code = %s)", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 3; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("%d rows: SELECT %s %dx drop table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("%d rows: SELECT %s %dx create table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); $label = mysqli_real_escape_string($link, $label); for ($i = 1; $i <= $num_rows; $i++) { if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, '$label')")) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } for ($i = 0; $i < $run; $i++) { $start = microtime(true); mysqli_real_query($link, "SELECT id, label FROM test"); $res = mysqli_use_result($link); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x query()'] += (microtime(true) - $start); if (!$res) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); while ($row = mysqli_fetch_assoc($res)) ; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc()'] += (microtime(true) - $start); } mysqli_close($link); } while (false); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall']; } } return array($errors, $times); } foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_select_varchar_unbuffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } // sort by labels ksort($times); ?> mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_skeleton.php0000664000175000017500000000335212161007456024216 0ustar andreyandrey shown in reports like 'select() : 0.01s' */ $times = array(); /* It's recommended to initialize the times hash with 0 values for all entries. This often makes debugging easier. Make sure you have one 'overall' entry in your list which holds the 'entire runtime' of you test (e.g. create table + insert + select) and not only a fraction of it (e.g. select). */ $times['overall'] = 0; $times['select'] = 0; /* List of errors that happened during the test run. You should stop the benchmark after the first error */ $errors = array(); do { $times['overall'] = microtime(true); /* Use this to connect to the database. The variables $host, ... $socket and $flag_original_code are provided by the framework */ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } for ($i = 0; $i < $rows; $i++) { $start = microtime(true); if (!$res = mysqli_query($link, "SELECT $i")) { $errors[] = sprintf("SELECT failed for row = %d (converted code: %s)\n", $i, ($flag_original_code) ? 'no' : 'yes'); break 2; } $times['select'] += (microtime(true) - $start); mysqli_free_result($res); } mysqli_close($link); $times['overall'] = (microtime(true) - $times['overall']); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_data_seek_random.php0000664000175000017500000001265312161007456026725 0ustar andreyandrey 'varchar(16)', 32 => 'varchar(32)', 64 => 'varchar(64)', 128 => 'varchar(128)', 256 => 'varchar(256)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4192 => 'varchar(4192)', 8384 => 'varchar(8384)', 16768 => 'varchar(16768)', 33536 => 'varchar(33536)', 65500 => 'varchar(65500)' ); foreach ($runs as $k => $num_runs) { foreach ($rows as $k => $num_rows) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = 0; $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] = 0; } } } $description = 'Connect, create n-rows with varchar(m), SELECT all, o-times [$runs] mysqli_stmt_data_seek(mt_rand()), close. n, m and o vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($types as $len => $type) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } $sql = sprintf("CREATE TABLE test(id INT, label %s)", $type); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("CREATE TABLE (%s) failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $num_runs) { // create n-rows if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } $label = str_repeat('a', $len); for ($i = 0; $i < $num_rows; $i++) { $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, '%s')", $i, $label); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("INSERT failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } } if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("stmt_init() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test ORDER BY id')) { $errors[] = sprintf("stmt_prepare() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("stmt_execute() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } $id = $label = null; if (!mysqli_stmt_bind_result($stmt, $id, $label)) { $errors[] = sprintf("stmt_bind_result() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } if (!mysqli_stmt_store_result($stmt)) { $errors[] = sprintf("stmt_store_result() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } mt_srand(); $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true); for ($i = 0; $i < $num_runs; $i++) { $pos = mt_rand(0, $num_rows - 1); $start = microtime(true); mysqli_stmt_data_seek($stmt, $pos); $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] += (microtime(true) - $start); if (!mysqli_stmt_fetch($stmt)) { $errors[] = sprintf("fetch() for %dth of %d rows failed (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); break 5; } if ($id != $pos) { $errors[] = sprintf("seek() + fetch() for %dth of %d rows did not work (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); var_dump($id); var_dump($pos); break 5; } } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true) - $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall']; mysqli_stmt_close($stmt); } } } // end foreach types mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_execute.php0000664000175000017500000000401512161007456025100 0ustar andreyandrey shown in reports like 'select() : 0.01s' */ $times = array(); /* It's recommended to initialize the times hash with 0 values for all entries. This often makes debugging easier. Make sure you have one 'overall' entry in your list which holds the 'entire runtime' of you test (e.g. create table + insert + select) and not only a fraction of it (e.g. select). */ $times['overall'] = 0; $times['execute'] = 0; /* List of errors that happened during the test run. You should stop the benchmark after the first error */ $errors = array(); do { $times['overall'] = microtime(true); /* Use this to connect to the database. The variables $host, ... $socket and $flag_original_code are provided by the framework */ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("stmt_init() (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (!mysqli_stmt_prepare($stmt, "SELECT 1")) { $errors[] = sprintf("stmt_prepare() (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } $start = microtime(true); for ($i = 0; $i < $runs; $i++) { if (!@mysqli_stmt_execute($stmt)) { $errors[] = sprintf("stmt_execute() (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } mysqli_stmt_free_result($stmt); } $times['execute'] = microtime(true) - $start; @mysqli_stmt_close($stmt); mysqli_close($link); $times['overall'] = (microtime(true) - $times['overall']); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_insert.php0000664000175000017500000001023712161007456024745 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', ); foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times['INSERT ' . $type . ' ' . $run . 'x = #rows query()'] = 0; $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall'] = 0; } } $description = 'Connect, n-times INSERT varchar of size m, close. n and m vary.'; $errors = array(); function mysqli_query_insert($type, $len, $runs, $host, $user, $passwd, $db, $port, $socket) { $errors = $times = array(); foreach ($runs as $k => $run) { $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("INSERT %s %dx = #rows connect failure (original code = %s)", $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 2; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("INSERT %s %dx = #rows drop table failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("INSERT %s %dx = #rows create table failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); $start = microtime(true); if (!$stmt = mysqli_stmt_init($link)) { $error[] = sprintf("INSERT %s %dx = #rows mysqli_stmt_init() failed (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } $ret = mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"); $times['INSERT ' . $type . ' ' . $run . 'x = #rows stmt_init() + stmt_prepare()'] += microtime(true) - $start; if (!$ret) { $error[] = sprintf("INSERT %s %dx = #rows mysqli_stmt_init() failed (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } $start = microtime(true); $ret = mysqli_stmt_bind_param($stmt, 'is', $i, $label); $times['INSERT ' . $type . ' ' . $run . 'x = #rows stmt_bind_param()'] += microtime(true) - $start; if (!$ret) { $error[] = sprintf("INSERT %s %dx = #rows mysqli_stmt_bind_param failed (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 2; } for ($i = 1; $i <= $run; $i++) { $start = microtime(true); $ret = mysqli_stmt_execute($stmt); $times['INSERT ' . $type . ' ' . $run . 'x = #rows stmt_execute()'] += microtime(true) - $start; if (!$ret) { $errors[] = sprintf("INSERT %s %dx = #rows stmt_execute failure (original code = %s): [%d] %s", $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } } mysqli_stmt_close($stmt); mysqli_close($link); } while (false); $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall'] = microtime(true) - $times['INSERT ' . $type . ' ' . $run . 'x = #rows overall']; } return array($errors, $times); } ksort($types); foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_insert($type, $len, $runs, $host, $user, $passwd, $db, $port, $socket); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_many_col.php0000664000175000017500000001702312161007456025242 0ustar andreyandrey 1, "name" => "c_tinyint", "type" => "TINYINT", "value" => 1), array("len" => 2, "name" => "c_smallint", "type" => "SMALLINT", "value" => 1), array("len" => 200, "name" => "c_varchar_199", "type" => "varchar(199)", "value" => "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 3, "name" => "c_mediumint", "type" => "MEDIUMINT", "value" => 1), array("len" => 20, "name" => "c_varchar_19", "type" => "varchar(19)", "value" => "0123456789012345678"), array("len" => 4, "name" => "c_int", "type" => "INT", "value" => 1), array("len" => 8, "name" => "c_bigint", "type" => "BIGINT", "value" => 1), array("len" => 50, "name" => "c_varchar_49", "type" => "varchar(49)", "value" => "0123456789012345678901234567890123456789012345678"), array("len" => 4, "name" => "c_float_24", "type" => "FLOAT(24)", "value" => 1), array("len" => 150, "name" => "c_varchar_149", "type" => "varchar(149)", "value" => "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 8, "name" => "c_float_25", "type" => "FLOAT(25)", "value" => 1), array("len" => 4, "name" => "c_float", "type" => "FLOAT", "value" => 1), array("len" => 8, "name" => "c_double", "type" => "DOUBLE", "value" => 1), array("len" => 100, "name" => "c_varchar_99", "type" => "varchar(99)", "value" => "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"), array("len" => 3, "name" => "c_date", "type" => "DATE", "value" => "2007-01-17"), array("len" => 8, "name" => "c_datetime", "type" => "DATETIME", "value" => "2007-01-17 11:53:00"), array("len" => 4, "name" => "c_timestamp", "type" => "TIMESTAMP", "value" => "2007-01-17 11:54:00"), array("len" => 3, "name" => "c_time", "type" => "TIME", "value" => "11:54:00"), array("len" => 1, "name" => "c_year", "type" => "YEAR", "value" => "2007"), array("len" => 10, "name" => "c_char_10", "type" => "CHAR(10)", "value" => "0123456789"), array("len" => 1, "name" => "c_enum", "type" => "ENUM('true', 'false')", "value" => "true"), // let's assume latin1 array("len" => 300, "name" => "c_varchar_99", "type" => "varchar(298)", "value" => "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"), ); $rows = array(2000); foreach ($rows as $k => $num_rows) { foreach ($columns as $k => $num_columns) { $num_column_types = count($column_types); $total_len = 0; for ($i = 0; $i < $num_columns; $i++) { $total_len += $column_types[$i % $num_column_types]['len']; } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = 0; $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) fetch()'] = 0; } } $description = 'Connect, create n-rows with one m-columns of different types, SELECT all (buffered), close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($rows as $k => $num_rows) { foreach ($columns as $k => $num_columns) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $num_column_types = count($column_types); $total_len = 0; $column_names = $column_defs = $column_values = ''; for ($i = 0; $i < $num_columns; $i++) { $index = $i % $num_column_types; $total_len += $column_types[$index]['len']; $column_names .= sprintf("%s_%d, ", $column_types[$index]['name'], $i); $column_defs .= sprintf("%s_%d %s, ", $column_types[$index]['name'], $i, $column_types[$index]['type']); $column_values .= sprintf("%s%s%s, ", (is_string($column_types[$index]['value'])) ? '"' : '', $column_types[$index]['value'], (is_string($column_types[$index]['value'])) ? '"' : '' ); } $last_column = sprintf("%s_%d", $column_types[$index]['name'], $i - 1); $last_value = $column_types[$index]['value']; $sql = sprintf("CREATE TABLE test(%s)", substr($column_defs, 0, -2)); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 3; } $sql = sprintf("INSERT INTO test(%s) VALUES (%s)", substr($column_names, 0, -2), substr($column_values, 0, -2)); for ($i = 0; $i < $num_rows; $i++) { if (!mysqli_query($link, $sql)) { $errors[] = sprintf("%s failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } } $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = microtime(true); if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("stmt_init() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 3; } if (!mysqli_stmt_prepare($stmt, 'SELECT * FROM test')) { $errors[] = sprintf("stmt_prepare() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 3; } if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("stmt_execute() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 3; } $row = array(); $cmd = 'mysqli_stmt_bind_result($stmt, '; for ($i = 0; $i < $num_columns; $i++) $cmd .= sprintf('$row[%d], ', $i); $cmd = (substr($cmd, 0, -2) . ');'); eval($cmd); $start = microtime(true); while (mysqli_stmt_fetch($stmt)) ; $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) fetch()'] += (microtime(true) - $start); mysqli_stmt_close($stmt); $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall'] = microtime(true) - $times[$num_rows . ' row[s]: ' . $num_columns . ' column[s] (' . $total_len . ' bytes) overall']; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_seek_seq.php0000664000175000017500000001271012161007456025236 0ustar andreyandrey 'varchar(16)', 32 => 'varchar(32)', 64 => 'varchar(64)', 128 => 'varchar(128)', 256 => 'varchar(256)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4192 => 'varchar(4192)', 8384 => 'varchar(8384)', 16768 => 'varchar(16768)', 33536 => 'varchar(33536)', 65500 => 'varchar(65500)' ); foreach ($runs as $k => $num_runs) { foreach ($rows as $k => $num_rows) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = 0; $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] = 0; } } } $description = 'Connect, create n-rows with varchar(m), SELECT all, fetch them in reverse order using o-times [$runs] mysqli_stmt_data_seek(n...0), close. n, m and o vary.'; $errors = array();$errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($types as $len => $type) { if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("DROP TABLE failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } $sql = sprintf("CREATE TABLE test(id INT, label %s)", $type); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("CREATE TABLE (%s) failed (converted code: %s): [%d] %s\n", $sql, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 2; } foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $num_runs) { // create n-rows if (!mysqli_query($link, "DELETE FROM test")) { $errors[] = sprintf("DELETE failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 4; } $label = str_repeat('a', $len); for ($i = 0; $i < $num_rows; $i++) { $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, '%s')", $i, $label); if (!mysqli_query($link, $sql)) { $errors[] = sprintf("INSERT failed (%s) (converted code: %s): [%d] %s\n", $type, ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break 5; } } if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("stmt_init() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test ORDER BY id')) { $errors[] = sprintf("stmt_prepare() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("stmt_execute() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } $id = $label = null; if (!mysqli_stmt_bind_result($stmt, $id, $label)) { $errors[] = sprintf("stmt_bind_result() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } if (!mysqli_stmt_store_result($stmt)) { $errors[] = sprintf("stmt_store_result() failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 4; } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true); for ($i = 0; $i < $num_runs; $i++) { $pos = $num_runs - $i - 1; $start = microtime(true); mysqli_stmt_data_seek($stmt, $pos); $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' data_seek()'] += (microtime(true) - $start); if (!mysqli_stmt_fetch($stmt)) { $errors[] = sprintf("fetch() for %dth of %d rows failed (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); break 5; } if ($id != $pos) { $errors[] = sprintf("seek() + fetch() for %dth of %d rows did not work (%s) (converted code: %s): [%d] %s\n", $pos, $num_rows, $type, ($flag_original_code) ? 'no' : 'yes', mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); var_dump($id); var_dump($pos); break 5; } } $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall'] = microtime(true) - $times[$num_rows . ' rows: ' . $num_runs . 'x ' . $type . ' overall']; mysqli_stmt_close($stmt); } } } // end foreach types mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_sel_buf.php0000664000175000017500000001576212161007456025070 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', 65000 => 'varchar(65000)', ); $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc()'] = 0; } } } $description = 'Connect, create n rows with varchar of size m, o-times SELECT all rows (unbuffered), close. n, m, o vary.'; $errors = array(); function mysqli_query_select_varchar_unbuffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code) { $errors = $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("%d rows: SELECT %s %dx connect failure (original code = %s)", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 3; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("%d rows: SELECT %s %dx drop table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("%d rows: SELECT %s %dx create table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_init() for INSERT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_prepare() for INSERT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_stmt_bind_param($stmt, "is", $i, $label)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_bind_param() for INSERT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } for ($i = 1; $i <= $num_rows; $i++) { if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } } mysqli_stmt_close($stmt); for ($i = 0; $i < $run; $i++) { if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_init() for SELECT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_prepare() for SELECT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); $ret = mysqli_stmt_execute($stmt); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x stmt_execute()'] += (microtime(true) - $start); if (!$ret) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); $ret = mysqli_stmt_store_result($stmt); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x stmt_store_result()'] += (microtime(true) - $start); if (!$ret) { $errors[] = sprintf("%d rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } if (!mysqli_stmt_bind_result($stmt, $id2, $label2)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_prepare() for SELECT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); while (mysqli_stmt_fetch($stmt)) ; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x stmt_fetch()'] += (microtime(true) - $start); mysqli_stmt_close($stmt); } mysqli_close($link); } while (false); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall']; } } return array($errors, $times); } foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_select_varchar_unbuffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } // sort by labels ksort($times); ?> mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_stmt_sel_unbuf.php0000664000175000017500000001504212161007456025422 0ustar andreyandrey 'varchar(127)', 255 => 'varchar(255)', 512 => 'varchar(512)', 1024 => 'varchar(1024)', 2048 => 'varchar(2048)', 4096 => 'varchar(4096)', 8192 => 'varchar(8192)', 16384 => 'varchar(16384)', 32768 => 'varchar(32768)', 65000 => 'varchar(65000)', ); $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { foreach ($types as $len => $type) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x query()'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = 0; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x fetch_assoc()'] = 0; } } } $description = 'Connect, create n rows with varchar of size m, o-times SELECT all rows (unbuffered), close. n, m, o vary.'; $errors = array(); function mysqli_query_select_varchar_unbuffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code) { $errors = $times = array(); foreach ($rows as $k => $num_rows) { foreach ($runs as $k => $run) { $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true); do { if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("%d rows: SELECT %s %dx connect failure (original code = %s)", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no'); break 3; } if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { $errors[] = sprintf("%d rows: SELECT %s %dx drop table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label %s)", $type))) { $errors[] = sprintf("%d rows: SELECT %s %dx create table failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } $label = ''; for ($i = 0; $i < $len; $i++) $label .= chr(mt_rand(65, 90)); if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_init() for INSERT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_prepare() for INSERT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } if (!mysqli_stmt_bind_param($stmt, "is", $i, $label)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_bind_param() for INSERT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 3; } for ($i = 1; $i <= $num_rows; $i++) { if (!mysqli_stmt_execute($stmt)) { $errors[] = sprintf("%d - $i rows: SELECT %s %dx insert failure (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } } mysqli_stmt_close($stmt); for ($i = 0; $i < $run; $i++) { if (!$stmt = mysqli_stmt_init($link)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_init() for SELECT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_prepare() for SELECT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); $ret = mysqli_stmt_execute($stmt); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x stmt_execute()'] += (microtime(true) - $start); if (!$ret) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_execute() SELECT failure (original code = %s): [%d] %s", $rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $id2 = $label2 = null; if (!mysqli_stmt_bind_result($stmt, $id2, $label2)) { $errors[] = sprintf("%d rows: SELECT %s %dx stmt_prepare() for SELECT failed (original code = %s): [%d] %s", $num_rows, $type, $run, ($flag_original_code) ? 'yes' : 'no', mysqli_errno($link), mysqli_error($link)); break 4; } $start = microtime(true); while (mysqli_stmt_fetch($stmt)) ; $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x stmt_fetch()'] += (microtime(true) - $start); mysqli_stmt_close($stmt); } mysqli_close($link); } while (false); $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall'] = microtime(true) - $times[$num_rows . ' rows: SELECT ' . $type . ' ' . $run . 'x overall']; } } return array($errors, $times); } foreach ($types as $len => $type) { list ($errors, $tmp_times) = mysqli_query_select_varchar_unbuffered($type, $len, $runs, $rows, $host, $user, $passwd, $db, $port, $socket, $flag_original_code); $times = array_merge($times, $tmp_times); if (!empty($errors)) { break; } } // sort by labels ksort($times); ?> mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqli_variable_command_size.php0000664000175000017500000000345012161007456026706 0ustar andreyandrey $run) { foreach ($query_lengths as $k => $len) { $times[$run . "x, " . $len . " characters long SELECT overall"] = 0; $times[$run . "x, " . $len . " characters long SELECT query()"] = 0; } } $description = 'Connect, run n times >SELECT "aaaa..."< command with a total length of m-characters, close. n and m vary.'; $errors = array(); do { if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } foreach ($runs as $k => $run) { foreach ($query_lengths as $k => $len) { $sql = 'SELECT "a'; $where = ' FROM DUAL WHERE 1 = 2'; $remaining = $len - strlen($sql) - strlen($where) - 7; $sql = sprintf('%s%s" AS a %s', $sql, str_repeat('a', $remaining), $where); $times[$run . "x, " . $len . " characters long SELECT overall"] = microtime(true); for ($i = 0; $i < $run; $i++) { $start = microtime(true); if (!$res = mysqli_query($link, $sql)) { $errors[] = sprintf("SELECT failed (converted code: %s): [%d] %s\n", ($flag_original_code) ? 'no' : 'yes', mysqli_errno($link), mysqli_error($link)); break; } $times[$run . "x, " . $len . " characters long SELECT query()"] += (microtime(true) - $start); mysqli_free_result($res); } $times[$run . "x, " . $len . " characters long SELECT overall"] = microtime(true) - $times[$run . "x, " . $len . " characters long SELECT overall"]; } } mysqli_close($link); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqlnd_ms_php.ini0000664000175000017500000000002312161007456024011 0ustar andreyandreymysqlnd_ms.enable=1mysqlnd_ms-1.5.2/tests/bench/micro_benches/mysqlnd_ms_slave_hint.php0000664000175000017500000000431212161007456025373 0ustar andreyandrey shown in reports like 'select() : 0.01s' */ $times = array(); /* It's recommended to initialize the times hash with 0 values for all entries. This often makes debugging easier. Make sure you have one 'overall' entry in your list which holds the 'entire runtime' of you test (e.g. create table + insert + select) and not only a fraction of it (e.g. select). */ $times['overall'] = 0; $times['select'] = 0; /* List of errors that happened during the test run. You should stop the benchmark after the first error */ $errors = array(); do { $times['overall'] = microtime(true); /* Use this to connect to the database. The variables $host, ... $socket and $flag_original_code are provided by the framework */ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) { $errors[] = sprintf("Connect failure (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break; } if (defined('MYSQLND_MS_SLAVE_SWITCH')) { /* make sure all binaries have mysqlnd_ms compiled in */ $hint = sprintf('/*%s*/', MYSQLND_MS_SLAVE_SWITCH); } else { /* make an educated guess... */ $hint = '/*ms=slave*/'; } $sql = $hint . 'SELECT 1 FROM DUAL'; for ($i = 0; $i < $queries; $i++) { $start = microtime(true); if (!$res = mysqli_query($link, $sql)) { $errors[] = sprintf("SELECT failed (converted code: %s)\n", ($flag_original_code) ? 'no' : 'yes'); break 2; } $times['select'] += (microtime(true) - $start); mysqli_free_result($res); } mysqli_close($link); $times['overall'] = (microtime(true) - $times['overall']); } while (false); ?>mysqlnd_ms-1.5.2/tests/bench/README0000664000175000017500000000716312161007456016347 0ustar andreyandreyABOUT This directory contains a tiny, very complicated framework for micro benchmarks. In this document we mean by micro benchmarks PHP scripts that test certain functions of the ext/mysqli API and record the runtimes of them. The tests have not much in common with real-life applications, unless you run the same query like 1.000 times in your applications and you fetch over and over the same results or you call mysqli_connect() 10.000 times at the beginning of your scripts. Therefore the micro benchmarks say nothing about real-life performance. BUT they can give hints for bottle-neck analysis. THE BASIC IDEA The basic idea here is to have several PHP binaries compiled with different options and compare how fast they can execute the micro benchmarks. The micro benchmarks are the PHP scripts contained in the directory micro_benches/. For every PHP binaries, configured in framework/config.php the framework basically does: exec('/configured/php -f my_micro_bench.php') With my_micro_bench.php being something like (pseudo-code): $host = ; $user = ; [...] include('micro_bench_eg_mysqli_connect.php'); $tmp = serialize(array('times' => $times)); [...] fwrite('data_exchange_file.txt', $tmp) Then the runtimes are read from the data exchange file: - stored in a database for manual post-processing - shown on the command line - written to HTML files CONFIGURATION / INSTALLATION Edit framework/config.php . Read the notes in the file. The framework requires a MySQL database to store results. Install it, if needed. The default name for the database is 'runbench', see the config.php. RUNNING Make sure you have adapted framework/config.php to your needs and followed the other INSTALLATION steps. With the default settings, runtime is about 15 minutes on a single CPU 2Ghz P4 system. The maximum memory usage is just a bit above 1GB. Ok, you're warned. Go to the directory framework/: > cd php/ext/mysqli/tests/bench/framework/ Check the syntax of the CLI script main.php: > php main.php -v Missing file and/or directory specification! Syntax: program [options] dir_or_file [dir_or_file [dir_or_file ...]] Options: -v - Verbose -h - Help -q - Quiet, suppress output Try running a micro benchmark, for example mysqli_data_seek_random.php: > php main.php -v ../micro_benches/mysqli_data_seek_random [2011-03-01 15:48:07] Starting run for binary 'mysqli' and runner 'rb_testrunner_normal'... [...] Wait for the results. You can find a HTML representation of the results in the HTML output directory that you configured in framework/config.php. By default: framework/web/ If the run fails, you usually see something like: ...'configured/php -f mysqli_data_seek_random_php_run_normal.php' The file mysqli_data_seek_random_php_run_normal.php is and example of the temporary file that the framework creates (see THE BASIC IDEA). You can start to debug, profile - whatever you want - based on this temporary file. However, before you rerun main.php make sure you removed all of these temporary files! If you want to run all micro benchmarks, do: > php main.php -v ../micro_benches READING AND UNDERSTANDING RESULTS This is difficult! Make sure you have no load on your box for comparable results. Make sure you study the source of the micro benchmark files carefully. Try to understand what the scripts do. WINDOWS? Never tried it on Windows. Good luck, and don't forget to contribute and suggest fixes if need be! OPROFILE SUPPORT? Not yet. We had it once in an older version. Basically you need to write a new testrunner. mysqlnd_ms-1.5.2/tests/bug_60605.phpt0000664000175000017500000000312012161007456016607 0ustar andreyandrey--TEST-- #60605 - mysql_get_server_info() @ PHP 5.3.8 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_bug_60605.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); _skipif_connect($host, $user, $passwd, $db, $port, $socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_bug_60605.ini --FILE-- --CLEAN-- --EXPECTF-- Server info w handle: %s Server info wo handle: %s done!mysqlnd_ms-1.5.2/tests/bug_pecl_22784.phpt0000664000175000017500000000504612161007456017631 0ustar andreyandrey--TEST-- PECL #22784 - mysql_select_db won't work --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_bug_pecl_22784.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_bug_pecl_22784.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_autocommit_kill.phpt0000664000175000017500000000572712161007456022753 0ustar andreyandrey--TEST-- autocommit() and kill() --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_autocommit_kill.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_autocommit_kill.ini --FILE-- thread_id; mst_mysqli_query(4, $link, "SET autocommit=0", MYSQLND_MS_SLAVE_SWITCH); $slave = $link->thread_id; if ($master == $slave) { /* The test relies on different thread ids, try connecting again. try to increase thread id on one of the servers... */ $tmp[] = @mst_mysqli_connect($master_host, $user, $passwd, $db, $master_port, $master_socket); $attempts++; } } while (($master == $slave) && ($attempts < 5)); if ($master == $slave) { printf("[005] Master and slave connection have the same thread id. Please, try running test again.\n"); die(); } if (!$link->kill($link->thread_id)) printf("[006] [%d] %s\n", $link>errno, $link->error); printf("[007] Connected to %s\n", ($link->thread_id == $master) ? 'master' : (($link->thread_id == $slave) ? 'slave' : $link->thread_id)); if (!mysqli_autocommit($link, true)) printf("[008] [%d] %s\n"); printf("[009] Connected to %s\n", ($link->thread_id == $master) ? 'master' : (($link->thread_id == $slave) ? 'slave' : $link->thread_id)); /* slave because SELECT */ $res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role, @@autocommit AS auto_commit"); if ($res) { printf("[011] Who is speaking?\n"); var_dump($res->fetch_assoc()); } /* master because of hint */ $res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role, @@autocommit AS auto_commit", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); if (1 != $row['auto_commit']) printf("[013] Autocommit should be on, got '%s'\n", $row['auto_commit']); print "done!"; ?> --CLEAN-- --EXPECTF-- [007] Connected to slave [009] Connected to slave [010] [2006] MySQL server has gone away done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_autocommit.phpt0000664000175000017500000000670212161007456021732 0ustar andreyandrey--TEST-- autocommit - handled as of PHP 5.3.99 --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_autocommit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_autocommit.ini --FILE-- fetch_assoc(); if (1 != $row['_auto_commit']) printf("[009] Autocommit should be on, got '%s'\n", $row['auto_commit']); printf("[010] Got a reply from %s\n", $row['_role']); /* master because of hint */ $res = mst_mysqli_query(11, $link, "SELECT @myrole AS _role, @@autocommit AS _auto_commit", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); if (1 != $row['_auto_commit']) printf("[012] Autocommit should be on, got '%s'\n", $row['auto_commit']); printf("[013] Got a reply from %s\n", $row['_role']); $link->close(); /* no plugin magic */ if (!($link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket))) printf("[014] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if (!mysqli_autocommit($link, false)) printf("[015] Failed to change autocommit setting\n"); mst_mysqli_query(16, $link, "SET autocommit=0"); if (!mysqli_autocommit($link, false)) printf("[017] Failed to change autocommit setting\n"); $res = mst_mysqli_query(18, $link, "SELECT @@autocommit AS auto_commit"); $row = $res->fetch_assoc(); if (0 != $row['auto_commit']) printf("[019] Autocommit should be off, got '%s'\n", $row['auto_commit']); if (!mysqli_autocommit($link, true)) printf("[020] Failed to change autocommit setting\n"); $res = mst_mysqli_query(21, $link, "SELECT @@autocommit AS auto_commit"); $row = $res->fetch_assoc(); if (1 != $row['auto_commit']) printf("[022] Autocommit should be on, got '%s'\n", $row['auto_commit']); print "done!"; ?> --CLEAN-- --EXPECTF-- [010] Got a reply from slave [013] Got a reply from master done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_begin_mysqli_fail.phpt0000664000175000017500000001273312161007456023227 0ustar andreyandrey--TEST-- mysqli_begin failure (mysqlnd tx_begin) --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_begin_mysqli_fail.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_begin_mysqli_fail.ini --FILE-- thread_id] = true; $i++; } while (($i < 10) && (count($slaves) < 2)); if ((10 == $i) && (count($slaves) < 2)) { die("[007] Two connections happen to have the same thread id, ignore and run again!"); } printf("... plain trx commit, begin fails\n"); $ret = $link->begin_transaction(-1); printf("[008] %s '%s'\n", gettype($ret), var_export($ret, true)); mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role")); printf("... plain trx commit, begin success, rollback\n"); $ret = $link->begin_transaction(); printf("[011] %s '%s'\n", gettype($ret), var_export($ret, true)); mst_mysqli_fech_role(mst_mysqli_query(12, $link, "SELECT @myrole AS _role")); if (isset($slaves[$link->thread_id])) { printf("[013] SELECT on slave during transaction\n"); } mst_mysqli_query(14, $link, "INSERT INTO test(id) VALUES (1)"); $link->rollback(); $res = mst_mysqli_query(15, $link, "SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(16, $link, "SELECT @myrole AS _role")); printf("... plain trx commit, begin fails\n"); $ret = $link->begin_transaction(-1); printf("[017] %s '%s'\n", gettype($ret), var_export($ret, true)); mst_mysqli_fech_role(mst_mysqli_query(18, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(19, $link, "SELECT @myrole AS _role")); printf("... plain trx commit, begin success, commit\n"); $ret = $link->begin_transaction(); printf("[020] %s '%s'\n", gettype($ret), var_export($ret, true)); mst_mysqli_fech_role(mst_mysqli_query(21, $link, "SELECT @myrole AS _role")); if (isset($slaves[$link->thread_id])) { printf("[022] SELECT on slave during transaction\n"); } mst_mysqli_query(23, $link, "INSERT INTO test(id) VALUES (2)"); $link->commit(); $res = mst_mysqli_query(24, $link, "SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(25, $link, "SELECT @myrole AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- ... plain trx commit, begin fails Warning: mysqli::begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d [008] boolean 'false' This is 'slave' speaking This is 'slave' speaking ... plain trx commit, begin success, rollback [011] boolean 'true' This is 'master' speaking array(1) { ["MAX(id)"]=> NULL } This is 'slave' speaking ... plain trx commit, begin fails Warning: mysqli::begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d [017] boolean 'false' This is 'slave' speaking This is 'slave' speaking ... plain trx commit, begin success, commit [020] boolean 'true' This is 'master' speaking array(1) { ["MAX(id)"]=> string(1) "2" } This is 'slave' speaking done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_begin_mysqli.phpt0000664000175000017500000002626412161007456022240 0ustar andreyandrey--TEST-- mysqli_begin (mysqlnd tx_begin) --SKIPIF-- array( 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_begin_mysqli.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_begin_mysqli.ini --FILE-- thread_id] = true; $i++; } while (($i < 10) && (count($server['master']) < 2)); if ((10 == $i) && (count($server['master']) < 2)) { die("[005] Two connections happen to have the same thread id, ignore and run again!"); } $i = 0; do { mst_mysqli_query(6, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(6, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); $server['slave'][$link->thread_id] = true; $i++; } while (($i < 10) && (count($server['slave']) < 2)); if ((10 == $i) && (count($server['slave']) < 2)) { die("[007] Two connections happen to have the same thread id, ignore and run again!"); } printf("... plain trx commit\n"); $link->begin_transaction(); mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT @myrole AS _role")); mst_mysqli_query(8, $link, "INSERT INTO test(id) VALUES (1)"); $link->commit(); $res = mst_mysqli_query(9, $link, "SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT @myrole AS _role")); $link->begin_transaction(); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role")); mst_mysqli_query(11, $link, "INSERT INTO test(id) VALUES (2)"); $link->commit(); $res = mst_mysqli_query(12, $link, "SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(13, $link, "SELECT @myrole AS _role")); printf("... plain trx rollback\n"); $link->begin_transaction(); mst_mysqli_fech_role(mst_mysqli_query(14, $link, "SELECT @myrole AS _role")); mst_mysqli_query(15, $link, "INSERT INTO test(id) VALUES (3)"); $link->rollback(); $res = mst_mysqli_query(16, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($row['_id'] > 2) { printf("[017] No rollback!"); } mst_mysqli_fech_role(mst_mysqli_query(18, $link, "SELECT @myrole AS _role")); printf("... named trx rollback\n"); $link->begin_transaction(0, "foobar"); mst_mysqli_fech_role(mst_mysqli_query(19, $link, "SELECT @myrole AS _role")); mst_mysqli_query(20, $link, "INSERT INTO test(id) VALUES (4)"); $link->rollback(); $res = mst_mysqli_query(21, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($row['_id'] > 2) { printf("[022] No rollback!"); } mst_mysqli_fech_role(mst_mysqli_query(23, $link, "SELECT @myrole AS _role")); printf("... named trx rollback started many times\n"); $link->begin_transaction(0, "foobar"); $link->begin_transaction(0, "foobar20101002928282384gdsgfhdgjhgjh"); $link->begin_transaction(0, "abc"); mst_mysqli_fech_role(mst_mysqli_query(19, $link, "SELECT @myrole AS _role")); mst_mysqli_query(20, $link, "INSERT INTO test(id) VALUES (5)"); $link->rollback(); $res = mst_mysqli_query(21, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($row['_id'] > 2) { printf("[022] No rollback!"); } mst_mysqli_fech_role(mst_mysqli_query(23, $link, "SELECT @myrole AS _role")); printf("... named trx commit started many times\n"); $link->begin_transaction(0, "foobar"); $link->begin_transaction(0, "foobar20101002928282384gdsgfhdgjhgjh"); $link->begin_transaction(0, "abc"); mst_mysqli_fech_role(mst_mysqli_query(24, $link, "SELECT @myrole AS _role")); mst_mysqli_query(25, $link, "INSERT INTO test(id) VALUES (6)"); $link->commit(); $res = mst_mysqli_query(26, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(28, $link, "SELECT @myrole AS _role")); /* May use slave */ printf("... read only transaction commit\n"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); mst_mysqli_fech_role(mst_mysqli_query(29, $link, "SELECT @myrole AS _role")); $link->commit(); printf("... read only transaction rollback\n"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); mst_mysqli_fech_role(mst_mysqli_query(30, $link, "SELECT @myrole AS _role")); $link->commit(); printf("... named read only transaction commit\n"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY, "a"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY, "abcdefghijklmnopqrstuvwxyz"); mst_mysqli_fech_role(mst_mysqli_query(31, $link, "SELECT @myrole AS _role")); $link->commit(); printf("... autocommit off, begin, commit\n"); $link->autocommit(false); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aobc"); mst_mysqli_fech_role(mst_mysqli_query(32, $link, "SELECT @myrole AS _role")); $link->commit(); $res = mst_mysqli_query(33, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); printf("... autocommit off, begin, rollback\n"); $link->autocommit(false); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aobr"); mst_mysqli_fech_role(mst_mysqli_query(34, $link, "SELECT @myrole AS _role")); mst_mysqli_query(35, $link, "INSERT INTO test(id) VALUES (7)"); $link->rollback(); $res = mst_mysqli_query(36, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); $res = mst_mysqli_query(37, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); printf("... autocommit on, begin, rollback\n"); $link->autocommit(true); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbr"); mst_mysqli_fech_role(mst_mysqli_query(38, $link, "SELECT @myrole AS _role")); mst_mysqli_query(39, $link, "INSERT INTO test(id) VALUES (8)"); $link->rollback(); $res = mst_mysqli_query(40, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); $res = mst_mysqli_query(41, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); printf("... autocommit on, begin, begin (= implicit commit), rollback\n"); $link->autocommit(true); $last = NULL; $i = 0; do { /* picks either master one or master two */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbbr"); mst_mysqli_query(43, $link, "INSERT INTO test(id) VALUES (9)"); /* implicit commit */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbbr"); $i++; if (is_null($last)) { $last = $link->thread_id; } else if ($last != $link->thread_id) { /* both masters got the insert */ break; } } while ($i < 20); if (20 == $i) { printf("[044] No connection switch, test will fail, ignore and run again\n"); } /* one of the masters */ mst_mysqli_fech_role(mst_mysqli_query(44, $link, "SELECT @myrole AS _role")); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbbr"); mst_mysqli_fech_role(mst_mysqli_query(45, $link, "SELECT @myrole AS _role")); mst_mysqli_query(46, $link, "INSERT INTO test(id) VALUES (10)"); $link->rollback(); $res = mst_mysqli_query(47, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); $res = mst_mysqli_query(48, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- ... plain trx commit This is 'master' speaking array(1) { ["MAX(id)"]=> string(1) "1" } This is 'slave' speaking This is 'master' speaking array(1) { ["MAX(id)"]=> string(1) "2" } This is 'slave' speaking ... plain trx rollback This is 'master' speaking This is 'slave' speaking ... named trx rollback This is 'master' speaking This is 'slave' speaking ... named trx rollback started many times This is 'master' speaking This is 'slave' speaking ... named trx commit started many times This is 'master' speaking array(1) { ["_id"]=> string(1) "6" } This is 'slave' speaking ... read only transaction commit This is 'slave' speaking ... read only transaction rollback This is 'slave' speaking ... named read only transaction commit This is 'slave' speaking ... autocommit off, begin, commit This is 'master' speaking array(1) { ["_autocommit"]=> string(1) "0" } ... autocommit off, begin, rollback This is 'master' speaking array(1) { ["_id"]=> string(1) "6" } array(1) { ["_autocommit"]=> string(1) "0" } ... autocommit on, begin, rollback This is 'master' speaking array(1) { ["_id"]=> string(1) "6" } array(1) { ["_autocommit"]=> string(1) "1" } ... autocommit on, begin, begin (= implicit commit), rollback This is 'master' speaking This is 'master' speaking array(1) { ["_id"]=> string(1) "9" } array(1) { ["_autocommit"]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_begin_mysqli_rr.phpt0000664000175000017500000002673312161007456022744 0ustar andreyandrey--TEST-- mysqli_begin (mysqlnd tx_begin), round robin --SKIPIF-- array( 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_begin_mysqli_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_begin_mysqli_rr.ini --FILE-- thread_id] = true; } if (count($server['master']) < 2) { die("[005] Two connections happen to have the same thread id, ignore and run again!"); } /* after this, next master is master0 (= wrap) */ for ($i = 0; $i< 2; $i++) { mst_mysqli_query(6, $link, sprintf("SET @myrole='slave%d'", $i), MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(6, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); $server['slave'][$link->thread_id] = true; } if (count($server['slave']) < 2) { die("[007] Two connections happen to have the same thread id, ignore and run again!"); } /* next slave is slave0 (= wrap) */ /* master 0, slave 0 */ printf("... plain trx commit\n"); $link->begin_transaction(); mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT @myrole AS _role")); mst_mysqli_query(8, $link, "INSERT INTO test(id) VALUES (1)"); $link->commit(); $res = mst_mysqli_query(9, $link, "SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT @myrole AS _role")); /* master 1, slave 1, slave 1 */ $link->begin_transaction(); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role")); mst_mysqli_query(11, $link, "INSERT INTO test(id) VALUES (2)"); $link->commit(); $res = mst_mysqli_query(12, $link, "SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(13, $link, "SELECT @myrole AS _role")); /* maaster 0, master 0, slave 0 */ printf("... plain trx rollback\n"); $link->begin_transaction(); mst_mysqli_fech_role(mst_mysqli_query(14, $link, "SELECT @myrole AS _role")); mst_mysqli_query(15, $link, "INSERT INTO test(id) VALUES (3)"); $link->rollback(); $res = mst_mysqli_query(16, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($row['_id'] > 2) { printf("[017] No rollback!"); } mst_mysqli_fech_role(mst_mysqli_query(18, $link, "SELECT @myrole AS _role")); /* master 1, master 1, slave 1 */ printf("... named trx rollback\n"); $link->begin_transaction(0, "foobar"); mst_mysqli_fech_role(mst_mysqli_query(19, $link, "SELECT @myrole AS _role")); mst_mysqli_query(20, $link, "INSERT INTO test(id) VALUES (4)"); $link->rollback(); $res = mst_mysqli_query(21, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($row['_id'] > 2) { printf("[022] No rollback!"); } mst_mysqli_fech_role(mst_mysqli_query(23, $link, "SELECT @myrole AS _role")); /* master 0, master 0, master 0, slave 0 */ printf("... named trx rollback started many times\n"); $link->begin_transaction(0, "foobar"); $link->begin_transaction(0, "foobar20101002928282384gdsgfhdgjhgjh"); $link->begin_transaction(0, "abc"); mst_mysqli_fech_role(mst_mysqli_query(19, $link, "SELECT @myrole AS _role")); mst_mysqli_query(20, $link, "INSERT INTO test(id) VALUES (5)"); $link->rollback(); $res = mst_mysqli_query(21, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($row['_id'] > 2) { printf("[022] No rollback!"); } mst_mysqli_fech_role(mst_mysqli_query(23, $link, "SELECT @myrole AS _role")); /* master 1, master 1, master 1, slave 1 */ printf("... named trx commit started many times\n"); $link->begin_transaction(0, "foobar"); $link->begin_transaction(0, "foobar20101002928282384gdsgfhdgjhgjh"); $link->begin_transaction(0, "abc"); mst_mysqli_fech_role(mst_mysqli_query(24, $link, "SELECT @myrole AS _role")); mst_mysqli_query(25, $link, "INSERT INTO test(id) VALUES (6)"); $link->commit(); $res = mst_mysqli_query(26, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(28, $link, "SELECT @myrole AS _role")); /* May use slave */ /* slave 0 */ printf("... read only transaction commit\n"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); mst_mysqli_fech_role(mst_mysqli_query(29, $link, "SELECT @myrole AS _role")); $link->commit(); /* slave 1 */ printf("... read only transaction rollback\n"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); mst_mysqli_fech_role(mst_mysqli_query(30, $link, "SELECT @myrole AS _role")); $link->commit(); /* slave 0, master 0, master 0 */ printf("... named read only transaction commit\n"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY, "a"); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY, "abcdefghijklmnopqrstuvwxyz"); mst_mysqli_fech_role(mst_mysqli_query(31, $link, "SELECT @myrole AS _role")); $link->commit(); printf("... autocommit off, begin, commit\n"); $link->autocommit(false); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aobc"); mst_mysqli_fech_role(mst_mysqli_query(32, $link, "SELECT @myrole AS _role")); $link->commit(); /* switch between trx: master 1, last used ignored! */ $res = mst_mysqli_query(33, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); mst_mysqli_fech_role(mst_mysqli_query(34, $link, "SELECT @myrole AS _role")); /* master 0, master 0, master 1 */ printf("... autocommit off, begin, rollback\n"); $link->autocommit(false); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aobr"); mst_mysqli_fech_role(mst_mysqli_query(35, $link, "SELECT @myrole AS _role")); mst_mysqli_query(36, $link, "INSERT INTO test(id) VALUES (7)"); $link->rollback(); ; /* switch between trx?, master 0 */ $res = mst_mysqli_query(37, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); $res = mst_mysqli_query(38, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); /* master 1, master 1, master 1 */ printf("... autocommit on, begin, rollback\n"); $link->autocommit(true); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbr"); mst_mysqli_fech_role(mst_mysqli_query(38, $link, "SELECT @myrole AS _role")); mst_mysqli_query(39, $link, "INSERT INTO test(id) VALUES (8)"); $link->rollback(); $res = mst_mysqli_query(40, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); $res = mst_mysqli_query(41, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); printf("... autocommit on, begin, begin (= implicit commit), rollback\n"); $link->autocommit(true); $last = NULL; for ($i = 0; $i < 3; $i++) { /* master 0, master 1, master 0 */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbbr"); mst_mysqli_query(43, $link, "INSERT INTO test(id) VALUES (9)"); /* implicit commit */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbbr"); } /* one of the masters */ mst_mysqli_fech_role(mst_mysqli_query(44, $link, "SELECT @myrole AS _role")); /* master 1, master 1, master 1 */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "aonbbr"); mst_mysqli_fech_role(mst_mysqli_query(45, $link, "SELECT @myrole AS _role")); mst_mysqli_query(46, $link, "INSERT INTO test(id) VALUES (10)"); $link->rollback(); $res = mst_mysqli_query(47, $link, "SELECT MAX(id) AS _id FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); $res = mst_mysqli_query(48, $link, "SELECT @@autocommit AS _autocommit FROM test", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- ... plain trx commit This is 'master0' speaking array(1) { ["MAX(id)"]=> string(1) "1" } This is 'slave0' speaking This is 'master1' speaking array(1) { ["MAX(id)"]=> string(1) "2" } This is 'slave1' speaking ... plain trx rollback This is 'master0' speaking This is 'slave0' speaking ... named trx rollback This is 'master1' speaking This is 'slave1' speaking ... named trx rollback started many times This is 'master0' speaking This is 'slave0' speaking ... named trx commit started many times This is 'master1' speaking array(1) { ["_id"]=> string(1) "6" } This is 'slave1' speaking ... read only transaction commit This is 'slave0' speaking ... read only transaction rollback This is 'slave1' speaking ... named read only transaction commit This is 'slave0' speaking ... autocommit off, begin, commit This is 'master0' speaking array(1) { ["_autocommit"]=> string(1) "0" } This is 'master1' speaking ... autocommit off, begin, rollback This is 'master0' speaking array(1) { ["_id"]=> string(1) "6" } array(1) { ["_autocommit"]=> string(1) "0" } ... autocommit on, begin, rollback This is 'master0' speaking array(1) { ["_id"]=> string(1) "6" } array(1) { ["_autocommit"]=> string(1) "1" } ... autocommit on, begin, begin (= implicit commit), rollback This is 'master0' speaking This is 'master1' speaking array(1) { ["_id"]=> string(1) "9" } array(1) { ["_autocommit"]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_begin_pdo_rr.phpt0000664000175000017500000001016612161007456022201 0ustar andreyandrey--TEST-- beginTransaction, trx_stickiness=on (UNSUPPORTED!) --SKIPIF-- array( 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_begin_pdo_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_begin_pdo_rr.ini --FILE-- query(sprintf("/*%s*/SET @myrole='master%d'", MYSQLND_MS_MASTER_SWITCH, $i)); $pdo->query(sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH)); $pdo->query(sprintf("/*%s*/CREATE TABLE test(id INT) ENGINE=InnoDB", MYSQLND_MS_LAST_USED_SWITCH)); } /* after this, next master is master0 (= wrap) */ for ($i = 0; $i< 2; $i++) { $pdo->query(sprintf("/*%s*/SET @myrole='slave%d'", MYSQLND_MS_SLAVE_SWITCH, $i)); $pdo->query(sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH)); $pdo->query(sprintf("/*%s*/CREATE TABLE test(id INT) ENGINE=InnoDB", MYSQLND_MS_LAST_USED_SWITCH)); } /* next slave is slave0 (= wrap) */ /* master 0, slave 0 */ $pdo->beginTransaction(); var_dump($pdo->query("SELECT @myrole AS _role")->fetch(PDO::FETCH_ASSOC)['_role']); var_dump($pdo->query("SELECT @myrole AS _role")->fetch(PDO::FETCH_ASSOC)['_role']); $pdo->query("INSERT INTO test(id) VALUES(1)"); $pdo->commit(); var_dump($pdo->query(sprintf("/*%s*/SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH))->fetch(PDO::FETCH_ASSOC)); var_dump($pdo->query("SELECT @myrole AS _role")->fetch(PDO::FETCH_ASSOC)['_role']); /* master 1, slave 1, slave 1 */ $pdo->beginTransaction(); var_dump($pdo->query("SELECT @myrole AS _role")->fetch(PDO::FETCH_ASSOC)['_role']); var_dump($pdo->query("SELECT @myrole AS _role")->fetch(PDO::FETCH_ASSOC)['_role']); $pdo->query("INSERT INTO test(id) VALUES(1)"); $pdo->commit(); var_dump($pdo->query(sprintf("/*%s*/SELECT MAX(id) FROM test", MYSQLND_MS_LAST_USED_SWITCH))->fetch(PDO::FETCH_ASSOC)); var_dump($pdo->query("SELECT @myrole AS _role")->fetch(PDO::FETCH_ASSOC)['_role']); } catch (Exception $e) { printf("[001] %s\n", $e->__toString()); } } $options = array(PDO::ATTR_EMULATE_PREPARES => true); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); $options = array(PDO::ATTR_EMULATE_PREPARES => false); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); print "done!"; ?> --CLEAN-- --XFAIL-- Unsupported - PDO has not yet been modified to use appropriate mysqlnd calls --EXPECTF-- Unsupported feature string(6) "slave0" string(6) "slave1" array(1) { ["MAX(id)"]=> string(1) "1" } string(6) "slave0" string(6) "slave1" string(6) "slave0" array(1) { ["MAX(id)"]=> string(1) "1" } string(6) "slave1" string(6) "slave0" string(6) "slave1" array(1) { ["MAX(id)"]=> int(1) } string(6) "slave0" string(6) "slave1" string(6) "slave0" array(1) { ["MAX(id)"]=> int(1) } string(6) "slave1" done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_change_user_fail.phpt0000664000175000017500000000760212161007456023027 0ustar andreyandrey--TEST-- change_user() - failure --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_change_user_fail.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); function test_unknown_access($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect to %s (port '%d', socket '%s') [%d] %s", $host, $port, $socket, mysqli_connect_errno(), mysqli_connect_error())); return $link->select_db("please_do_no_create_such_db"); } if (test_unknown_access($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die("skip Master server account can access 'please_do_no_create_such_db' database"); if (test_unknown_access($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die("skip Slave server account can access 'please_do_no_create_such_db' database"); require_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_change_user_fail.ini --FILE-- change_user($user, $passwd, 'please_do_no_create_such_db')) printf("[006] Failed to change user, [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(7, $link, "SELECT @myrole AS _role, DATABASE() as _database"); if (!$row = $res->fetch_assoc()) printf("[008] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != $db) printf("[009] Expecting database '%s' got '%s'\n", $db, $row['_database']); /* NOTE: we must not check for SQL variables. They may or may not have been reset. Do not consider change_user() an atomic call which either works and resets all state information or fails and does not reset anything. */ $server_id = mst_mysqli_get_emulated_id(10, $link); if ($server_id != $slave_id) printf("[011] Expecting slave connection found '%s'\n", $server_id); $res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[013] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != $db) printf("[014] Expecting database '%s' got '%s'\n", $db, $row['_database']); $server_id = mst_mysqli_get_emulated_id(15, $link); if ($server_id != $master_id) printf("[016] Expecting slave connection found '%s'\n", $server_id); print "done!"; ?> --CLEAN-- --EXPECTF-- [006] Failed to change user, [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_change_user.phpt0000664000175000017500000000723312161007456022034 0ustar andreyandrey--TEST-- change_user() - covered by the prototype --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_change_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); function test_mysql_access($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect to %s (port '%d', socket '%s') [%d] %s", $host, $port, $socket, mysqli_connect_errno(), mysqli_connect_error())); return $link->select_db("mysql"); } if (!test_mysql_access($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die("skip Master server account cannot access mysql database"); if (!test_mysql_access($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket)) die("skip Slave server account cannot access mysql database"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_change_user.ini --FILE-- thread_id; mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $slave_thread = $link->thread_id; if ($master_thread == $slave_thread) { /* The test relies on different thread ids, try connecting again. try to increase thread id on one of the servers... */ $tmp[] = @mst_mysqli_connect($master_host, $user, $passwd, $db, $master_port, $master_socket); $attempts++; } } while (($master_thread == $slave_thread) && ($attempts < 5)); if ($attempts >= 5) die("False-positive, please rerun"); if (!$link->change_user($user, $passwd, 'mysql')) printf("[005] Failed to change user, [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_SLAVE_SWITCH); if (!$row = $res->fetch_assoc()) printf("[007] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[008] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != '') printf("[009] Expecting role '' got '%s'\n", $row['_role']); if ($link->thread_id != $slave_thread) printf("[010] Expecting slave connection thread id %d got %d\n", $slave_thread, $link->thread_id); $res = mst_mysqli_query(11, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[012] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[013] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != '') printf("[014] Expecting role '' got '%s'\n", $row['_role']); if ($link->thread_id != $master_thread) printf("[015] Expecting master connection thread id %d got %d\n", $master_thread, $link->thread_id); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_charsets_fail.phpt0000664000175000017500000001067112161007456022360 0ustar andreyandrey--TEST-- Charsets, choosing invalid --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_charsets_fail.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); function test_for_charset($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) || !($tmp = mysqli_fetch_assoc($res))) { mysqli_close($link); die(sprintf("skip Cannot check server version, [%d] %s\n", mysqli_errno($link), mysqli_error($link))); } mysqli_free_result($res); $version = explode('.', $tmp['server_version']); if (empty($version)) { mysqli_close($link); die(sprintf("skip Cannot check server version, based on '%s'", $tmp['server_version'])); } if ($version[0] <= 4 && $version[1] < 1) { mysqli_close($link); die(sprintf("skip Requires MySQL Server 4.1+\n")); } if (($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "pleasenot"', MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) { die(sprintf("skip WOW, server has charset 'pleasenot'!\n")); } if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset')) die(sprintf("skip Cannot select current charset, [%d] %s\n", $link->errno, $link->error)); if (!$row = mysqli_fetch_assoc($res)) die(sprintf("skip Cannot detect current charset, [%d] %s\n", $link->errno, $link->error)); return $row['charset']; } test_for_charset($master_host_only, $user, $passwd, $db, $master_port, $master_socket); test_for_charset($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_charsets_fail.ini --FILE-- errno, $link->error); $row = $res->fetch_assoc(); if ('slave' != $row['_role']) printf("[006] Expecting reply from slave not from '%s'\n", $row['_role']); $current_charset = $row['_charset']; $new_charset = 'pleasenot'; /* shall be run on *all* configured machines - all masters, all slaves */ if (!$link->set_charset($new_charset)) printf("[007] [%d] %s\n", $link->errno, $link->error); /* slave */ if ($res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset", MYSQLND_MS_LAST_USED_SWITCH)) { $row = $res->fetch_assoc(); if ('slave' != $row['_role']) printf("[009] Expecting reply from slave not from '%s'\n", $row['_role']); if ($row['_charset'] != $current_charset) printf("[010] Expecting charset '%s' got '%s'\n", $current_charset, $row['_charset']); } if ($link->character_set_name() != $current_charset) printf("[011] Expecting charset '%s' got '%s'\n", $current_charset, $link->character_set_name()); if ($res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset", MYSQLND_MS_MASTER_SWITCH)) { $row = $res->fetch_assoc(); if ('master' != $row['_role']) printf("[013] Expecting reply from master not from '%s'\n", $row['_role']); if ($row['_charset'] != $current_charset) printf("[014] Expecting charset '%s' got '%s'\n", $current_charset, $row['_charset']); } if ($link->character_set_name() != $current_charset) printf("[015] Expecting charset '%s' got '%s'\n", $current_charset, $link->character_set_name()); print "done!"; ?> --CLEAN-- --EXPECTF-- [007] [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_charsets_kill.phpt0000664000175000017500000001241012161007456022371 0ustar andreyandrey--TEST-- Charsets and kill() - TODO --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'failover' => array('strategy' => 'disabled'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_charsets_kill.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); function test_for_charset($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) || !($tmp = mysqli_fetch_assoc($res))) { mysqli_close($link); die(sprintf("skip Cannot check server version, [%d] %s\n", mysqli_errno($link), mysqli_error($link))); } mysqli_free_result($res); $version = explode('.', $tmp['server_version']); if (empty($version)) { mysqli_close($link); die(sprintf("skip Cannot check server version, based on '%s'", $tmp['server_version'])); } if ($version[0] <= 4 && $version[1] < 1) { mysqli_close($link); die(sprintf("skip Requires MySQL Server 4.1+\n")); } if ((($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin1"', MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) || (($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin2"', MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) ) { // ok, required latin1 or latin2 are available } else { die(sprintf("skip Requires character set latin1 or latin2\n")); } if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset')) die(sprintf("skip Cannot select current charset, [%d] %s\n", $link->errno, $link->error)); if (!$row = mysqli_fetch_assoc($res)) die(sprintf("skip Cannot detect current charset, [%d] %s\n", $link->errno, $link->error)); return $row['charset']; } $master_charset = test_for_charset($master_host_only, $user, $passwd, $db, $master_port, $master_socket); $slave_charset = test_for_charset($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if ($master_charset != $slave_charset) { die(sprintf("skip Master (%s) and slave (%s) must use the same default charset.", $master_charset, $slave_charset)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_charsets_kill.ini --FILE-- errno, $link->error); $row = $res->fetch_assoc(); $current_charset = $row['_charset']; $new_charset = ('latin1' == $current_charset) ? 'latin2' : 'latin1'; printf("%s: thread %d, current %s, new: %s\n", $row['_role'], $link->thread_id, $current_charset, $new_charset); if (!$link->kill($link->thread_id)) printf("[006] [%d] %s\n", $link->errno, $link->error); printf("%s: thread %d\n", $row['_role'], $link->thread_id); /* shall be run on *all* configured machines - all masters, all slaves */ if (!$link->set_charset($new_charset)) printf("[007] [%d] %s\n", $link->errno, $link->error); printf("%s: thread %d\n", $row['_role'], $link->thread_id); /* slave connection has been killed... - this shall report an error */ if (!$res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset", MYSQLND_MS_LAST_USED_SWITCH)) printf("[009] [%d] %s\n", $link->errno, $link->error); /* slave connection has been killed... - this shall report an error */ if (!$res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset")) printf("[011] [%d] %s\n", $link->errno, $link->error); /* slave connection has been killed... - this shall report an error */ if (!$res = mst_mysqli_query(11, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset", MYSQLND_MS_MASTER_SWITCH)) printf("[012] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); $current_charset = $row['_charset']; if ($current_charset != $new_charset) printf("[013] Master character set has not been changed."); $new_charset = ('latin1' == $current_charset) ? 'latin2' : 'latin1'; printf("%s: thread %d, current %s, new: %s\n", $row['_role'], $link->thread_id, $current_charset, $new_charset); print "done!"; ?> --CLEAN-- --EXPECTF-- slave: thread %d, current latin%d, new: latin%d slave: thread %d slave: thread %d [008] [%d] %s [009] [%d] %s [010] [%d] %s [011] [%d] %s master: thread %d, current latin%d, new: latin%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_charsets_pdo_fail.phpt0000664000175000017500000000537212161007456023224 0ustar andreyandrey--TEST-- Charsets, invalid using PDO --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_charsets_pdo_fail.ini", $settings)) die(sprintf("SKIP %s\n", $error)); function test_for_charset($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) || !($tmp = mysqli_fetch_assoc($res))) { mysqli_close($link); die(sprintf("skip Cannot check server version, [%d] %s\n", mysqli_errno($link), mysqli_error($link))); } mysqli_free_result($res); $version = explode('.', $tmp['server_version']); if (empty($version)) { mysqli_close($link); die(sprintf("skip Cannot check server version, based on '%s'", $tmp['server_version'])); } if ($version[0] <= 4 && $version[1] < 1) { mysqli_close($link); die(sprintf("skip Requires MySQL Server 4.1+\n")); } if (($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "pleasenot"', MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) { die(sprintf("skip WOW, server has charset 'pleasenot'!\n")); } if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset')) die(sprintf("skip Cannot select current charset, [%d] %s\n", $link->errno, $link->error)); if (!$row = mysqli_fetch_assoc($res)) die(sprintf("skip Cannot detect current charset, [%d] %s\n", $link->errno, $link->error)); return $row['charset']; } test_for_charset($master_host_only, $user, $passwd, $db, $master_port, $master_socket); test_for_charset($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_charsets_pdo_fail.ini --FILE-- quote("a")); print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2019] Unknown character set' in %s:%d Stack trace: #0 %s(%d): PDO->__construct('mysql:host=%s', '%s', '%s') #1 {main} thrown in %s on line 5mysqlnd_ms-1.5.2/tests/mysqlnd_ms_charsets.phpt0000664000175000017500000001277412161007456021373 0ustar andreyandrey--TEST-- Charsets - covered by plugin prototype --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_charsets.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); function test_for_charset($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) || !($tmp = mysqli_fetch_assoc($res))) { mysqli_close($link); die(sprintf("skip Cannot check server version, [%d] %s\n", mysqli_errno($link), mysqli_error($link))); } mysqli_free_result($res); $version = explode('.', $tmp['server_version']); if (empty($version)) { mysqli_close($link); die(sprintf("skip Cannot check server version, based on '%s'", $tmp['server_version'])); } if ($version[0] <= 4 && $version[1] < 1) { mysqli_close($link); die(sprintf("skip Requires MySQL Server 4.1+\n")); } if ((($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin1"', MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) || (($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin2"', MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) ) { // ok, required latin1 or latin2 are available } else { die(sprintf("skip Requires character set latin1 or latin2\n")); } if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset')) die(sprintf("skip Cannot select current charset, [%d] %s\n", $link->errno, $link->error)); if (!$row = mysqli_fetch_assoc($res)) die(sprintf("skip Cannot detect current charset, [%d] %s\n", $link->errno, $link->error)); return $row['charset']; } $master_charset = test_for_charset($master_host_only, $user, $passwd, $db, $master_port, $master_socket); $slave_charset = test_for_charset($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if ($master_charset != $slave_charset) { die(sprintf("skip Master (%s) and slave (%s) must use the same default charset.", $master_charset, $slave_charset)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_charsets.ini --FILE-- errno, $link->error); $row = $res->fetch_assoc(); if ('slave' != $row['_role']) printf("[006] Expecting reply from slave not from '%s'\n", $row['_role']); $current_charset = $row['_charset']; $new_charset = ('latin1' == $current_charset) ? 'latin2' : 'latin1'; /* shall be run on *all* configured machines - all masters, all slaves */ if (!$link->set_charset($new_charset)) printf("[007] [%d] %s\n", $link->errno, $link->error); /* slave */ if (!$res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset", MYSQLND_MS_LAST_USED_SWITCH)) printf("[009] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('slave' != $row['_role']) printf("[010] Expecting reply from slave not from '%s'\n", $row['_role']); $current_charset = $row['_charset']; if ($current_charset != $new_charset) printf("[011] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); if ($link->character_set_name() != $new_charset) printf("[012] Expecting charset '%s' got '%s'\n", $new_charset, $link->character_set_name()); if (!$res = mst_mysqli_query(13, $link, "SELECT @myrole AS _role, @@character_set_connection AS _charset", MYSQLND_MS_MASTER_SWITCH)) printf("[014] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('master' != $row['_role']) printf("[015] Expecting reply from master not from '%s'\n", $row['_role']); $current_charset = $row['_charset']; if ($current_charset != $new_charset) printf("[016] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); if ($link->character_set_name() != $new_charset) printf("[017] Expecting charset '%s' got '%s'\n", $new_charset, $link->character_set_name); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_commit.phpt0000664000175000017500000000677112161007456021047 0ustar andreyandrey--TEST-- commit() --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_commit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_commit.ini --FILE-- commit())) printf("[003] [%d] %s\n", $link->errno, $link->error); /* master */ if (!mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test") || !mst_mysqli_query(5, $link, "CREATE TABLE test(id INT) ENGINE=InnoDB") || !mst_mysqli_query(6, $link, "INSERT INTO test(id) VALUES (1), (2), (3)")) printf("[007] [%d] %s\n", $link->errno, $link->error); if (!$link->autocommit(FALSE)) printf("[008] [%d] %s\n", $link->errno, $link->error); if (!mst_mysqli_query(9, $link, "INSERT INTO test(id) VALUES (4)")) printf("[010] [%d] %s\n", $link->errno, $link->error); if (!$link->commit()) printf("[011] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(12, $link, "SELECT id FROM test ORDER BY id ASC", MYSQLND_MS_MASTER_SWITCH); while ($row = $res->fetch_assoc()) printf("[013] %d\n", $row['id']); if (!mst_mysqli_query(14, $link, "DROP TABLE IF EXISTS test")) printf("[015] [%d] %s\n", $link->errno, $link->error); /* give dear mysql replication time to catch up */ sleep(1); /* slave */ if (!mst_mysqli_query(16, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH) || !mst_mysqli_query(17, $link, "CREATE TABLE test(id INT) ENGINE=InnoDB", MYSQLND_MS_SLAVE_SWITCH) || !mst_mysqli_query(18, $link, "INSERT INTO test(id) VALUES (1), (2), (3)", MYSQLND_MS_SLAVE_SWITCH)) printf("[019] [%d] %s\n", $link->errno, $link->error); if (!mst_mysqli_query(20, $link, "INSERT INTO test(id) VALUES (4)", MYSQLND_MS_SLAVE_SWITCH)) printf("[021] [%d] %s\n", $link->errno, $link->error); if (!$link->commit()) printf("[022] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(23, $link, "SELECT id FROM test ORDER BY id ASC"); while ($row = $res->fetch_assoc()) printf("[024] %d\n", $row['id']); if (!mst_mysqli_query(25, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH)) printf("[026] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [013] 1 [013] 2 [013] 3 [013] 4 [024] 1 [024] 2 [024] 3 [024] 4 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_config_access.phpt0000664000175000017500000000505112161007456022333 0ustar andreyandrey--TEST-- Concurrent config file access --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_config_access.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_config_access.ini --FILE-- errno, $clink->error); else { if (!$row = $res->fetch_assoc()) printf("[004] Child cannot fetch results\n"); if ($row['_message'] != 'child') printf("[005] Expecting 'child' got '%s'\n", $row['_message']); $res->free(); } $clink->close(); } exit(0); break; default: /* parent */ $status = null; $wait_id = pcntl_waitpid($pid, $status); if (pcntl_wifexited($status) && (0 != ($tmp = pcntl_wexitstatus($status)))) { printf("Exit code: %s\n", (pcntl_wifexited($status)) ? pcntl_wexitstatus($status) : 'n/a'); printf("Signal: %s\n", (pcntl_wifsignaled($status)) ? pcntl_wtermsig($status) : 'n/a'); printf("Stopped: %d\n", (pcntl_wifstopped($status)) ? pcntl_wstopsig($status) : 'n/a'); } break; } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_connection_references.phpt0000664000175000017500000000306312161007456024106 0ustar andreyandrey--TEST-- Many connections and references to them --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_connection_references.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_connection_references.ini --FILE-- --CLEAN-- --EXPECTF-- done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_constants.phpt0000664000175000017500000000361712161007456021567 0ustar andreyandrey--TEST-- Constants --SKIPIF-- --FILE-- true, "MYSQLND_MS_VERSION_ID" => true, /* SQL hints */ "MYSQLND_MS_MASTER_SWITCH" => true, "MYSQLND_MS_SLAVE_SWITCH" => true, "MYSQLND_MS_LAST_USED_SWITCH" => true, /* Return values of mysqlnd_ms_is_select() */ "MYSQLND_MS_QUERY_USE_LAST_USED" => true, "MYSQLND_MS_QUERY_USE_MASTER" => true, "MYSQLND_MS_QUERY_USE_SLAVE" => true, ); if (defined("MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION")) { $expected["MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION"] = false; } if (defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { $expected["MYSQLND_MS_HAVE_CACHE_SUPPORT"] = false; } if (version_compare(PHP_VERSION, '5.3.99', ">")) { $expected["MYSQLND_MS_QOS_CONSISTENCY_STRONG"] = false; $expected["MYSQLND_MS_QOS_CONSISTENCY_SESSION"] = false; $expected["MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL"] = false; $expected["MYSQLND_MS_QOS_OPTION_GTID"] = false; $expected["MYSQLND_MS_QOS_OPTION_AGE"] = false; $expected["MYSQLND_MS_QOS_OPTION_CACHE"] = false; } $constants = get_defined_constants(true); $constants = (isset($constants['mysqlnd_ms'])) ? $constants['mysqlnd_ms'] : array(); ksort($constants); foreach ($constants as $name => $value) { if (!isset($expected[$name])) { printf("[001] Unexpected constants: %s/%s\n", $name, $value); } else { if ($expected[$name]) printf("%s = '%s'\n", $name, $value); unset($expected[$name]); } } if (!empty($expected)) { printf("[002] Dumping list of missing constants\n"); var_dump($expected); } print "done!"; ?> --EXPECTF-- MYSQLND_MS_LAST_USED_SWITCH = 'ms=last_used' MYSQLND_MS_MASTER_SWITCH = 'ms=master' MYSQLND_MS_QUERY_USE_LAST_USED = '2' MYSQLND_MS_QUERY_USE_MASTER = '0' MYSQLND_MS_QUERY_USE_SLAVE = '1' MYSQLND_MS_SLAVE_SWITCH = 'ms=slave' MYSQLND_MS_VERSION = '1.5.2' MYSQLND_MS_VERSION_ID = '10502' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_disable_rw_rr.phpt0000664000175000017500000000672112161007456022370 0ustar andreyandrey--TEST-- No RW-split, random --SKIPIF-- array( 'master' => array($master_host, "unreachable", $master_host), 'slave' => array(), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_disable_rw_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.disable_rw_split=1 mysqlnd_ms.config_file=test_mysqlnd_ms_disable_rw_rr.ini --FILE-- thread_id); mst_mysqli_query(4, $link, "SET @myrole='master2'", NULL, true, true, true, true); $connections['master2'] = array($link->thread_id); mst_mysqli_query(5, $link, "SET @myrole='master3'"); $connections['master3'] = array($link->thread_id); $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); $connections['master1'][] = $link->thread_id; $row = $res->fetch_assoc(); if ($row['_role'] != 'master1') printf("[007] [%d] %s, wrong results\n", $link->errno, $link->error); mst_mysqli_query(8, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH, true, true, true, true); $connections['master2'][] = $link->thread_id; $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role"); $connections['master3'][] = $link->thread_id; $row = $res->fetch_assoc(); if ($row['_role'] != 'master3') printf("[010] [%d] %s, wrong results\n", $link->errno, $link->error); mst_mysqli_query(11, $link, "SET @myrole='master1'"); $connections['master1'][] = $link->thread_id; mst_mysqli_query(12, $link, "SET @myrole='master2'", NULL, true, true, true, true); $connections['master2'][] = $link->thread_id; $res = mst_mysqli_query(14, $link, "SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH); $connections['master3'][] = $link->thread_id; $row = $res->fetch_assoc(); if ($row['_role'] != 'master3') printf("[015] [%d] %s, wrong results\n", $link->errno, $link->error); $res = mst_mysqli_query(16, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $connections['master3'][] = $link->thread_id; $row = $res->fetch_assoc(); if ($row['_role'] != 'master3') printf("[017] [%d] %s, wrong results\n", $link->errno, $link->error); mst_mysqli_query(18, $link, "SET @myrole='master1'"); $connections['master1'][] = $link->thread_id; foreach ($connections as $role => $ids) { printf("Role: %s\n", $role); $last_thread_id = NULL; foreach ($ids as $k => $thread_id) { printf(" %d\n", $thread_id); if (is_null($last_thread_id)) { $last_thread_id = $thread_id; } else if ($last_thread_id != $thread_id) { printf(" [016] wrong thread id!\n"); } } } print "done!"; ?> --CLEAN-- --EXPECTF-- Role: master1 %d %d %d %d Role: master2 %d %d %d Role: master3 %d %d %d %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_empty_slave_list.phpt0000664000175000017500000000261512161007456023133 0ustar andreyandrey--TEST-- Empty slave list, no config error, user wants to run multi-master only --SKIPIF-- array( 'master' => array($master_host), 'slaves' => array(), ), ); if ($error = mst_create_config("test_mysqlnd_ms_empty_slave_list.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_empty_slave_list.ini --FILE-- query("SELECT 'Greetings from the master'"))) { printf("[002] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_row(); printf("[003] %s\n", $row[0]); } } print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Section [slave] doesn't exist for host [name_of_a_config_section] in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_enable_rw_rr_failover.phpt0000664000175000017500000000441412161007456024077 0ustar andreyandrey--TEST-- RW-split, random, no slaves, fail over --SKIPIF-- array( 'master' => array($master_host, $master_host), 'slave' => array(), 'pick' => array("roundrobin"), 'failover' => array('strategy' => 'master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_enable_rw_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.disable_rw_split=0 mysqlnd_ms.config_file=test_mysqlnd_ms_enable_rw_random.ini --FILE-- thread_id); @mst_mysqli_query(4, $link, "SET @myrole='master2'", MYSQLND_MS_MASTER_SWITCH); $connections['master2'] = array($link->thread_id); $res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role"); $connections['master1'][] = $link->thread_id; if ($res && ($row = $res->fetch_assoc()) && ($row['_role'] != 'master1')) printf("[006] [%d] %s, wrong results\n", $link->errno, $link->error); mst_mysqli_query(7, $link, "SELECT @myrole AS _role"); $connections['master2'][] = $link->thread_id; foreach ($connections as $role => $ids) { printf("Role: %s\n", $role); $last_thread_id = NULL; foreach ($ids as $k => $thread_id) { printf(" %d\n", $thread_id); if (is_null($last_thread_id)) { $last_thread_id = $thread_id; } else if ($last_thread_id != $thread_id) { printf(" [008] wrong thread id!\n"); } } } print "done!"; ?> --CLEAN-- --EXPECTF-- Role: master1 %d %d Role: master2 %d %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_enable_rw_rr.phpt0000664000175000017500000000555312161007456022215 0ustar andreyandrey--TEST-- RW-split, random, no slaves --SKIPIF-- array( 'master' => array($master_host, $master_host), 'slave' => array(), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_enable_rw_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.disable_rw_split=0 mysqlnd_ms.config_file=test_mysqlnd_ms_enable_rw_random.ini --FILE-- thread_id); @mst_mysqli_query(4, $link, "SET @myrole='master2'", MYSQLND_MS_MASTER_SWITCH); $connections['master2'] = array($link->thread_id); $res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role"); $connections['master1'][] = $link->thread_id; if ($res && ($row = $res->fetch_assoc()) && ($row['_role'] != 'master1')) printf("[006] [%d] %s, wrong results\n", $link->errno, $link->error); mst_mysqli_query(7, $link, "SELECT @myrole AS _role"); $connections['master2'][] = $link->thread_id; foreach ($connections as $role => $ids) { printf("Role: %s\n", $role); $last_thread_id = NULL; foreach ($ids as $k => $thread_id) { printf(" %d\n", $thread_id); if (is_null($last_thread_id)) { $last_thread_id = $thread_id; } else if ($last_thread_id != $thread_id) { printf(" [008] wrong thread id!\n"); } } } print "done!"; ?> --CLEAN-- --EXPECTF-- [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [005] [2000] (mysqlnd_ms) No connection selected by the last filter [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [007] [2000] (mysqlnd_ms) No connection selected by the last filter Role: master1 %d %d Role: master2 %d %d [008] wrong thread id! done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_error_errno_sqlstate.phpt0000664000175000017500000001057712161007456024034 0ustar andreyandrey--TEST-- error, errno, sqlstate --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_error_errno_sqlstate.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); if (!function_exists("iconv")) die("SKIP needs iconv extension\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_error_errno_sqlstate.ini --FILE-- "master", "errno" => $link->errno, "error" => $link->error, "sqlstate" => $link->sqlstate, ); $threads[mst_mysqli_get_emulated_id(12, $link)] = $tmp; } if (mst_mysqli_query(20, $link, "role=slave1 I_HOPE_THIS_IS_INVALID_SQL", MYSQLND_MS_SLAVE_SWITCH)) { printf("[021] Query should have failed\n"); } else { $tmp = array( "role" => "slave1", "errno" => $link->errno, "error" => $link->error, "sqlstate" => $link->sqlstate, ); $threads[mst_mysqli_get_emulated_id(22, $link)] = $tmp; } if (mst_mysqli_query(30, $link, "role=slave2 I_HOPE_THIS_IS_INVALID_SQL", MYSQLND_MS_SLAVE_SWITCH)) { printf("[031] Query should have failed\n"); } else { $tmp = array( "role" => "slave2", "errno" => $link->errno, "error" => $link->error, "sqlstate" => $link->sqlstate, ); $threads[mst_mysqli_get_emulated_id(32, $link)] = $tmp; } foreach ($threads as $thread_id => $details) { printf("%s - %s\n", $thread_id, $details['role']); if (!$details['errno']) printf("[032] Errno missing\n"); if (!$details['error']) printf("[033] Error message missing\n"); if (false === stristr($details['error'], "role=" . $details['role'])) printf("[034] Suspicious error message '%s'. Check manually, update test, if need be,", $details['error']); if ('00000' == $details['sqlstate'] || !$details['sqlstate']) printf("[034] Suspicious sqlstate '%s'. Check manually, update test, if need be,", $details['sqlstate']); } print "done!"; ?> --CLEAN-- --EXPECTF-- [010] [1064] You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'role=master I_HOPE_THIS_IS_INVALID_SQL' at line 1 [020] [1064] You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'role=slave1 I_HOPE_THIS_IS_INVALID_SQL' at line 1 [030] [1064] You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'role=slave2 I_HOPE_THIS_IS_INVALID_SQL' at line 1 master-%d - master slave[1,2]-%d - slave1 slave[1,2]-%d - slave2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_error_message.phpt0000664000175000017500000000315212161007456022402 0ustar andreyandrey--TEST-- error, errno, sqlstate --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_error_message.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_error_message.ini --FILE-- query("SELECT first_unknown_column FROM test")) printf("[002] Expected error, [%d] %s\n", $link->errno, $link->error); if (!$link->query("SELECT second_unknown_column FROM test")) printf("[003] Expected error, [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [002] Expected error, [%d] %sfirst_unknown_column%s [003] Expected error, [%d] %ssecond_unknown_column%s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_failover_old_syntax_default.phpt0000664000175000017500000000354412161007456025331 0ustar andreyandrey--TEST-- Failover=default, old syntax --SKIPIF-- array( 'master' => array("unreachable:7033"), 'slave' => array("unreachable:6033", $emulated_slave_host), 'lazy_connections' => 1, 'pick' => array('roundrobin'), 'failover' => array(), ), ); if ($error = mst_create_config("test_mysqlnd_ms_failover_old_syntax_default.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_failover_old_syntax_default.ini mysqlnd_ms.collect_statistics=1 --FILE-- ")); /* tries first, fails */ mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); /* picks second */ mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [002] %s Connect error, [005] %s This is '' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_failover_old_syntax_disabled.phpt0000664000175000017500000000362112161007456025450 0ustar andreyandrey--TEST-- Failover=disabled, old syntax --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'lazy_connections' => 1, 'pick' => array('roundrobin'), 'failover' => array('disabled'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_failover_old_syntax_disabled.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_failover_old_syntax_disabled.ini mysqlnd_ms.collect_statistics=1 --FILE-- "))); /* picks second */ mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [005] %s This is '' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_failover_old_syntax_loop.phpt0000664000175000017500000000400212161007456024644 0ustar andreyandrey--TEST-- Failover=loop_before_master, old syntax --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'lazy_connections' => 1, 'pick' => array('roundrobin'), 'failover' => array('loop_before_master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_failover_old_syntax_loop.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_failover_old_syntax_loop.ini mysqlnd_ms.collect_statistics=1 --FILE-- "))); /* tries first again..., fails, picks second */ mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); print "done!"; ?> --CLEAN-- --EXPECTF-- This is '' speaking This is '' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_failover_old_syntax_master.phpt0000664000175000017500000000306312161007456025174 0ustar andreyandrey--TEST-- Failover=master, old syntax --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033"), 'lazy_connections' => 1, 'failover' => array('master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_failover_old_syntax_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_failover_old_syntax_master.ini mysqlnd_ms.collect_statistics=1 --FILE-- "))); print "done!"; ?> --CLEAN-- --EXPECTF-- This is 'master %d' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_field_count.phpt0000664000175000017500000001034512161007456022042 0ustar andreyandrey--TEST-- last query field count (without PS) --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_field_count.ini --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_field_count.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); /* Emulated ID does not work with replication */ include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --FILE-- field_count) printf("[003] Expecting 0 got field_count = %d\n", $link->field_count); $res = mst_mysqli_query(4, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($res->field_count != $link->field_count) printf("[005] res->field_count = %d, link->field_count = %d\n", $res->field_count, $link->field_count); $threads[mst_mysqli_get_emulated_id(6, $link)] = array("role" => $row['_role'], "fields" => $res->field_count); $res->close(); mst_mysqli_query(7, $link, "SET @myrole='Master 1'"); if (0 !== $link->field_count) printf("[008] Expecting 0 got field_count = %d\n", $link->field_count); $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role, 1 as _one", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($res->field_count != $link->field_count) printf("[010] res->field_count = %d, link->field_count = %d\n", $res->field_count, $link->field_count); $threads[mst_mysqli_get_emulated_id(11, $link)] = array("role" => $row['_role'], "fields" => $res->field_count); $res->close(); mst_mysqli_query(12, $link, "SET @myrole='Slave 2'", MYSQLND_MS_SLAVE_SWITCH); if (0 !== $link->field_count) printf("[013] Expecting 0 got field_count = %d\n", $link->field_count); $res = mst_mysqli_query(14, $link, "SELECT @myrole AS _role, 1 AS _one, 2 as _two", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($res->field_count != $link->field_count) printf("[015] res->field_count = %d, link->field_count = %d\n", $res->field_count, $link->field_count); $threads[mst_mysqli_get_emulated_id(16, $link)] = array("role" => $row['_role'], "fields" => $res->field_count); $res->close(); mst_mysqli_query(17, $link, "SET @myrole='Slave 1'", MYSQLND_MS_SLAVE_SWITCH); if (0 !== $link->field_count) printf("[018] Expecting 0 got field_count = %d\n", $link->field_count); foreach ($threads as $thread_id => $details) printf("%s - %s: %d\n", $thread_id, $details["role"], $details["fields"]); print "done!"; ?> --CLEAN-- --EXPECTF-- slave[1,2]-%d - Slave 1: 1 master-%d - Master 1: 2 slave[1,2]-%d - Slave 2: 3 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_empty_lazy.phpt0000664000175000017500000000650012161007456023307 0ustar andreyandrey--TEST-- Empty filters section, lazy = 1 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_empty_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); /* Emulated ID does not work with replication */ include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_empty_lazy.ini --FILE-- errno, $link->error); $res = mst_mysqli_query(7, $link, "SELECT 1 FROM DUAL"); $threads[mst_mysqli_get_emulated_id(8, $link)][] = "slave"; if (!$res) printf("[009] [%d] %s\n", $link->errno, $link->error); foreach ($threads as $id => $roles) { printf("%s: ", $id); foreach ($roles as $role) printf("%s\n", $role); } print "done!"; ?> --CLEAN-- --EXPECTF-- master-%d: master slave[1,2]-%d: slave slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_empty_non_lazy.phpt0000664000175000017500000000651712161007456024171 0ustar andreyandrey--TEST-- Empty filters section, lazy = 0 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_empty_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); /* Emulated ID does not work with replication */ include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_empty_non_lazy.ini --FILE-- errno, $link->error); $res = mst_mysqli_query(7, $link, "SELECT 1 FROM DUAL"); $threads[mst_mysqli_get_emulated_id(8, $link)][] = "slave"; if (!$res) printf("[009] [%d] %s\n", $link->errno, $link->error); foreach ($threads as $id => $roles) { printf("%s: ", $id); foreach ($roles as $role) printf("%s\n", $role); } print "done!"; ?> --CLEAN-- --EXPECTF-- master-%d: master slave[1,2]-%d: slave slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups_no_master.phpt0000664000175000017500000000633412161007456024505 0ustar andreyandrey--TEST-- Filter: node_groups, no master --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "node_groups" => array( "A" => array( 'slave' => array('slave1'), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups_no_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=0 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups_no_master.ini --FILE-- errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role"); if (!$res) { printf("[007] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(8, $link, "/*A*/SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); if (!$res) { printf("[009] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) No masters configured in node group 'A' for 'node_groups' filter. Please, verify the setup in %s on line %d [001] [2000] (mysqlnd_ms) No masters configured in node group 'A' for 'node_groups' filter. Please, verify the setup array(1) { ["_role"]=> string(7) "master1" } array(1) { ["_role"]=> string(6) "slave1" } [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. 0 masters to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [008] [2000] (mysqlnd_ms) No connection selected by the last filter [009] [2000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups_no_slave.phpt0000664000175000017500000000677112161007456024331 0ustar andreyandrey--TEST-- Filter: node_groups, no slave --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "node_groups" => array( "A" => array( 'master' => array('master1'), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups_no_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=0 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups_no_slave.ini --FILE-- errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role"); if (!$res) { printf("[007] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(8, $link, "/*A*/SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH); if (!$res) { printf("[009] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(10, $link, "/*A*/SELECT @myrole AS _role"); if (!$res) { printf("[011] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { ["_role"]=> string(7) "master1" } array(1) { ["_role"]=> string(6) "slave1" } [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [008] [2000] (mysqlnd_ms) No connection selected by the last filter [009] [2000] (mysqlnd_ms) No connection selected by the last filter [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [010] [2000] (mysqlnd_ms) No connection selected by the last filter [011] [2000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups.phpt0000664000175000017500000001244612161007456022437 0ustar andreyandrey--TEST-- Filter: node_groups --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "node_groups" => array( "A" => array( 'master' => array('master2'), 'slave' => array('slave1'), ), "B" => array( 'master' => array('master1', 'master2'), 'slave' => array('slave2'), ), "C" => array( 'master' => array('master1'), 'slave' => array('slave2', 'slave1'), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups.ini --FILE-- fetch_assoc())) { if ($row['_role'] != $query['_role']) { printf("[%03d + 1] Expecting '%s' got '%s'\n", $offset, $query['_role'], $row['_role']); } } else { printf("[%03d + 2] [%d] %s, no result\n", $offset, $link->errno, $link->error); } } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* mark all connections, masters first, we use round robin */ mst_mysqli_query(2, $link, "SET @myrole='master1'"); mst_mysqli_query(3, $link, "SET @myrole='master2'"); mst_mysqli_query(4, $link, "SET @myrole='slave1'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(5, $link, "SET @myrole='slave2'", MYSQLND_MS_SLAVE_SWITCH); /* unfiltered: one query for each host using rr */ $sql = "SELECT @myrole AS _role"; $queries = array( array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "slave1", "switch" => NULL), array("_role" => "slave2", "switch" => NULL), ); run_queries(10, $link, $sql, $queries); /* group A: master1 and slave1 in it */ $sql = "/*A*/SELECT @myrole AS _role"; $queries = array( array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "slave1", "switch" => NULL), array("_role" => "slave1", "switch" => NULL), ); run_queries(20, $link, $sql, $queries); $sql = "/*B*/SELECT @myrole AS _role"; $queries = array( array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "slave2", "switch" => NULL), array("_role" => "slave2", "switch" => NULL), ); run_queries(30, $link, $sql, $queries); /* group C: master1 and slave2, slave1 */ $sql = "/*C*/SELECT @myrole AS _role"; $queries = array( array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "slave1", "switch" => NULL), array("_role" => "slave2", "switch" => NULL), array("_role" => "slave1", "switch" => NULL), ); run_queries(40, $link, $sql, $queries); /* group D: there is no such group, default to all. The node order is due to the prev run */ $sql = "/*D*/SELECT @myrole AS _role"; $queries = array( array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "slave2", "switch" => NULL), array("_role" => "slave1", "switch" => NULL), array("_role" => "slave2", "switch" => NULL), ); run_queries(50, $link, $sql, $queries); /* no group */ $sql = "SELECT @myrole AS _role"; $queries = array( array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "slave1", "switch" => NULL), array("_role" => "slave2", "switch" => NULL), ); run_queries(60, $link, $sql, $queries); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups_qos_rr.phpt0000664000175000017500000000714112161007456024020 0ustar andreyandrey--TEST-- Filter: node_groups, qos, rr --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'failover' => array('strategy' => 'loop_before_master'), 'filters' => array( "node_groups" => array( "C" => array( 'master' => array('master1'), 'slave' => array('slave2', 'slave1'), ), ), "quality_of_service" => array( "strong_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups_qos_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups_qos_rr.ini --FILE-- fetch_assoc())) { if ($row['_role'] != $query['_role']) { printf("[%03d + 1] Expecting '%s' got '%s'\n", $offset, $query['_role'], $row['_role']); } } else { printf("[%03d + 2] [%d] %s, no result\n", $offset, $link->errno, $link->error); } } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $masters = array(); /* setup: mark all connections, masters first, we use round robin */ mst_mysqli_query(2, $link, "SET @myrole='master1'"); $masters[$link->thread_id] = "master1"; mst_mysqli_query(3, $link, "SET @myrole='master2'"); $masters[$link->thread_id] = "master2"; /* groups filter not used */ $sql = "SELECT @myrole AS _role"; $queries = array( array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master2", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master1"), array("_role" => "master2"), array("_role" => "master1"), ); run_queries(10, $link, $sql, $queries); /* groups used */ $sql = "/*C*/SELECT @myrole AS _role"; $queries = array( array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master1", "switch" => MYSQLND_MS_MASTER_SWITCH), array("_role" => "master1"), /* provoke error */ array("_role" => "master1", "switch" => MYSQLND_MS_SLAVE_SWITCH), ); run_queries(20, $link, $sql, $queries); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups_setup_mess.phpt0000664000175000017500000001064312161007456024703 0ustar andreyandrey--TEST-- Filter: node_groups, invalid group name, empty group --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "node_groups" => array( "\0" => array( 'master' => array('master1'), 'slave' => array('slave1'), ), "\n" => array( 'master' => array(), 'slave' => array('slave1'), ), "A\n" => array( 'master' => array('master1'), 'slave' => array('slave1'), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups_setup_mess.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=0 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups_setup_mess.ini --FILE-- errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(7, $link, "SELECT 7, @myrole AS _role"); if (!$res) { printf("[008] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(9, $link, "SELECT 9, @myrole AS _role"); if (!$res) { printf("[010] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(11, $link, "/*\0*/SELECT 11, @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); if (!$res) { printf("[012] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(13, $link, "/*\0*/SELECT 13, @myrole AS _role"); if (!$res) { printf("[014] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(15, $link, "/*\n*/SELECT 15, @myrole AS _role"); if (!$res) { printf("[016] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(17, $link, "/*A\n*/SELECT 17, @myrole AS _role"); if (!$res) { printf("[018] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) No masters configured in node group ' ' for 'node_groups' filter. Please, verify the setup in %s on line %d [001] [2000] (mysqlnd_ms) No masters configured in node group %A array(2) { [5]=> string(1) "5" ["_role"]=> string(7) "master1" } array(2) { [7]=> string(1) "7" ["_role"]=> string(6) "slave1" } array(2) { [9]=> string(1) "9" ["_role"]=> string(6) "slave2" } array(2) { [11]=> string(2) "11" ["_role"]=> string(7) "master1" } array(2) { [13]=> string(2) "13" ["_role"]=> string(6) "slave1" } array(2) { [15]=> string(2) "15" ["_role"]=> string(6) "slave1" } array(2) { [17]=> string(2) "17" ["_role"]=> string(6) "slave1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups_unknown_master.phpt0000664000175000017500000000667312161007456025576 0ustar andreyandrey--TEST-- Filter: node_groups, unknown master --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "node_groups" => array( "A" => array( 'master' => array('master2'), 'slave' => array('slave1'), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups_unknown_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=0 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups_unknown_master.ini --FILE-- errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role"); if (!$res) { printf("[007] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(8, $link, "/*A*/SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); if (!$res) { printf("[009] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Unknown master 'master2' (section 'A') in 'node_groups' filter configuration. Stopping in %s on line %d [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) No masters configured in node group 'A' for 'node_groups' filter. Please, verify the setup in %s on line %d [001] [2000] (mysqlnd_ms) No masters configured in node group 'A' for 'node_groups' filter. Please, verify the setup array(1) { ["_role"]=> string(7) "master1" } array(1) { ["_role"]=> string(6) "slave1" } [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. 0 masters to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [008] [2000] (mysqlnd_ms) No connection selected by the last filter [009] [2000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_groups_unknown_slave.phpt0000664000175000017500000000750412161007456025407 0ustar andreyandrey--TEST-- Filter: node_groups, unknown slave --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "node_groups" => array( "A" => array( 'master' => array('master1'), 'slave' => array('slave2'), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_groups_unknown_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=0 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_groups_unknown_slave.ini --FILE-- errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role"); if (!$res) { printf("[007] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(8, $link, "/*A*/SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH); if (!$res) { printf("[009] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(10, $link, "/*A*/SELECT @myrole AS _role"); if (!$res) { printf("[011] [%d] %s\n", $link->errno, $link->error); } else { var_dump($res->fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Unknown slave 'slave2' (section 'A') in 'node_groups' filter configuration. Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown slave 'slave2' (section 'A') in 'node_groups' filter configuration. Stopping array(1) { ["_role"]=> string(7) "master1" } array(1) { ["_role"]=> string(6) "slave1" } [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [008] [2000] (mysqlnd_ms) No connection selected by the last filter [009] [2000] (mysqlnd_ms) No connection selected by the last filter [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [010] [2000] (mysqlnd_ms) No connection selected by the last filter [011] [2000] (mysqlnd_ms) No connection selected by the last filter done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_multi_last.phpt0000664000175000017500000000333312161007456023270 0ustar andreyandrey--TEST-- Filter: last multi --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1, ), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_multi_last.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_multi_last.ini --FILE-- --CLEAN-- --EXPECTF-- %AWarning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Error in configuration. Last filter is multi filter. Needs to be non-multi one. Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Error in configuration. Last filter is multi filter. Needs to be non-multi one. Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_config_conflict1.phpt0000664000175000017500000000315712161007456025210 0ustar andreyandrey--TEST-- Filter QOS, conflicting config --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, "eventual_consistency" => 1, ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_config_conflict1.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_config_conflict1.ini --FILE-- --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'quality_of_service', 'eventual_consistency' clashes with previous setting. Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_config_conflict2.phpt0000664000175000017500000000315412161007456025206 0ustar andreyandrey--TEST-- Filter QOS, conflicting config --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, "strong_consistency" => 1, ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_config_conflict2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_config_conflict2.ini --FILE-- --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'quality_of_service', 'session_consistency' clashes with previous setting. Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_config_conflict3.phpt0000664000175000017500000000315412161007456025207 0ustar andreyandrey--TEST-- Filter QOS, conflicting config --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "strong_consistency" => 1, "session_consistency" => 1, ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_config_conflict3.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_config_conflict3.ini --FILE-- --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'quality_of_service', 'session_consistency' clashes with previous setting. Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_config_conflict4.phpt0000664000175000017500000000315612161007456025212 0ustar andreyandrey--TEST-- Filter QOS, conflicting config --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1, "strong_consistency" => 1, ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_config_conflict4.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_config_conflict4.ini --FILE-- --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'quality_of_service', 'eventual_consistency' clashes with previous setting. Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_config.phpt0000664000175000017500000000322312161007456023240 0ustar andreyandrey--TEST-- Filter QOS, invalid config --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "gurkensalat" => array(), ), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_config.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_config.ini --FILE-- --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'quality_of_service', can't find section 'strong_consistency', 'session_consistency' or 'eventual_consistency' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_age.phpt0000664000175000017500000000557012161007456024441 0ustar andreyandrey--TEST-- Filter QOS, eventual consistency, age --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => array( 'age' => 123 ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_age.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_age.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); /* GTID */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_AGE, 4))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); printf("Got reply from '%s'\n", mst_mysqli_get_emulated_id(8, $link)); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' Got reply from '%s' done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_cache_conflict.phpt0000664000175000017500000000506712161007456026632 0ustar andreyandrey--TEST-- Filter QOS, eventual consistency, cache - age conflict --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_check_extensions(array("mysqlnd_qc")); if (!defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { die("SKIP Cache support not compiled in"); } $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => array( 'cache' => 123, 'age' => 3 ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_cache_conflict.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_cache_conflict.ini apc.use_request_time=0 mysqlnd_qc.use_request_time=0 mysqlnd_qc.collect_statistics=1 mysqlnd_qc.ttl=99 --FILE-- --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'quality_of_service', 'eventual_consistency' has conflicting entries for cache and age. Stopping in %s on line %d mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_cache.phpt0000664000175000017500000001254212161007456024745 0ustar andreyandrey--TEST-- Filter QOS, eventual consistency, cache --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_check_extensions(array("mysqlnd_qc")); if (!defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { die("SKIP Cache support not compiled in"); } $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => array( 'cache' => 123 ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_cache.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_cache.ini apc.use_request_time=0 mysqlnd_qc.use_request_time=0 mysqlnd_qc.collect_statistics=1 mysqlnd_qc.ttl=99 --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (!mysqlnd_qc_set_storage_handler("default")) { printf("[003] Failed to switch to default QC handler\n"); } /* TTL JSON vs. mysqlnd_qc.ttl */ dump_put_hit(); $now = time(); /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(4, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[004] [%d] '%s'\n", $link->errno, $link->error); dump_put_hit(); /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(4, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[005] [%d] '%s'\n", $link->errno, $link->error); $ignore = array(); $info = mysqlnd_qc_get_cache_info(); $entries = $info['data']; foreach ($entries as $key => $entry) { $ttl = $entry['statistics']['valid_until'] - $now; /* Allow some fuzzyness and accept TTL=100 (mysqlnd_qc.ttl + 1) although TTL should be 123 most of the time */ if ($ttl <= 99) { printf("[006] Cache entry TTL is %d (expected: >= 123)\n", $ttl); } $ignore[$key] = true; } /* TTL API call vs. mysqlnd_qc.ttl */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_CACHE, 4))) { printf("[007] [%d] %s\n", $link->errno, $link->error); } $now = time(); /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(8, $link, "SELECT id FROM test WHERE id = 1")) var_dump($res->fetch_all()); printf("[009] [%d] '%s'\n", $link->errno, $link->error); dump_put_hit(); /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(8, $link, "SELECT id FROM test WHERE id = 1")) var_dump($res->fetch_all()); printf("[010] [%d] '%s'\n", $link->errno, $link->error); dump_put_hit(); $info = mysqlnd_qc_get_cache_info(); $entries = $info['data']; foreach ($entries as $key => $entry) { if (isset($ignore[$key])) continue; $ttl = $entry['statistics']['valid_until'] - $now; /* Allow some fuzzyness and accept TTL=5 although TTL should be 4 most of the time */ if ($ttl > 5) { printf("[011] Cache entry TTL is %d (expected: <= 5)\n", $ttl); } } print "done!"; ?> --CLEAN-- --EXPECTF-- cache_put 0 cache_hit 0 array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [004] [0] '' cache_put 1 cache_hit 0 array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [005] [0] '' array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [009] [0] '' cache_put 2 cache_hit 1 array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [010] [0] '' cache_put 2 cache_hit 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_consistency.phpt0000664000175000017500000000614112161007456026241 0ustar andreyandrey--TEST-- Filter QOS, eventual consistency --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1, ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_consistency.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_consistency.ini --FILE-- fetch_assoc()); /* slave */ $res = mst_mysqli_query(6, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_SLAVE_SWITCH); var_dump($res->fetch_assoc()); /* master, allowed */ $res = mst_mysqli_query(8, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_MASTER_SWITCH); var_dump($res->fetch_assoc()); /* master */ $res = mst_mysqli_query(10, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[012] [%d] %s\n", $link->errno, $link->error); /* master */ $res = mst_mysqli_query(14, $link, "SELECT @myrole FROM DUAL"); var_dump($res->fetch_assoc()); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[016] [%d] %s\n", $link->errno, $link->error); /* slave */ $res = mst_mysqli_query(18, $link, "SELECT @myrole FROM DUAL"); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { ["@myrole"]=> NULL } array(1) { ["@myrole"]=> NULL } array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> NULL } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_consistency_rr.phpt0000664000175000017500000001130612161007456026743 0ustar andreyandrey--TEST-- Filter QOS, eventual consistency --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_consistency_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_consistency_rr.ini --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* master */ mst_mysqli_query(2, $link, "SET @myrole='master'"); /* slave 1 */ mst_mysqli_query(4, $link, "SET @myrole='slave 1'", MYSQLND_MS_SLAVE_SWITCH); /* slave 2 */ mst_mysqli_query(6, $link, "SET @myrole='slave 2'", MYSQLND_MS_SLAVE_SWITCH); $servers = array(); /* slave 1 */ $role = fetch_role(8, $link); $server_id = mst_mysqli_get_emulated_id(9, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* slave 2 */ $role = fetch_role(10, $link); $server_id = mst_mysqli_get_emulated_id(11, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master */ $role = fetch_role(12, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(13, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[014] [%d] %s\n", $link->errno, $link->error); /* master */ $role = fetch_role(16, $link); $server_id = mst_mysqli_get_emulated_id(17, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[018] [%d] %s\n", $link->errno, $link->error); /* slave 1 */ $role = fetch_role(19, $link); $server_id = mst_mysqli_get_emulated_id(20, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); foreach ($servers as $server_id => $roles) { foreach ($roles as $role => $num_queries) { printf("%s (%s) has run %d queries\n", $role, $server_id, $num_queries); } } print "done!"; ?> --CLEAN-- --EXPECTF-- slave 1 (%s) has run 2 queries slave 2 (%s) has run 1 queries master (%s) has run 2 queries done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_disable_rw_split.phpt0000664000175000017500000000644412161007456027234 0ustar andreyandrey--TEST-- Filter QOS, eventual, no rw split --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1 ), 'user' => array('callback' => 'pick_server') ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_disable_rw_split.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_disable_rw_split.ini mysqlnd_ms.disable_rw_split=1 --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); $master_id = mst_mysqli_get_emulated_id(3, $link); if ($res = mst_mysqli_query(4, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(5, $link); if ($server_id != $master_id) printf("[006] Query should have been executed on master because rw split is disabled\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', 'DROP TABLE IF EXISTS test', 1, 1) pick_server('myapp', 'CREATE TABLE test(id INT)', 1, 1) pick_server('myapp', 'INSERT INTO test(id) VALUES (1)', 1, 1) pick_server('myapp', '/*ms=last_used*//*3*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles', 1, 1) pick_server('myapp', '/*4*/SELECT id FROM test', 1, 1) array(1) { [0]=> array(1) { [0]=> string(1) "1" } } pick_server('myapp', '/*ms=last_used*//*5*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles', 1, 1) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_failover.phpt0000664000175000017500000001053412161007456031340 0ustar andreyandrey--TEST-- Filter QOS, eventual, trx_stickiness=on, failover --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array("unknown:7033"), 'lazy_connections' => 1, 'trx_stickiness' => 'on', 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1 ), 'random' => 1 ), 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_failover.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_failover.ini --FILE-- query("SET @myrole='master'")) printf("[002] [%d] %s\n", $link->errno, $link->error); $master_id = mst_mysqli_get_emulated_id(3, $link); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); if ($res = mst_mysqli_query(4, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(5, $link); if ($server_id != $master_id) printf("[006] Query should have been executed on master because of failover\n"); $link->commit(); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE); if ($res = mst_mysqli_query(7, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(8, $link); if ($server_id != $master_id) printf("[009] Query should have been executed on master because of trx stickiness\n"); $link->rollback(); if ($res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d array(1) { [0]=> array(1) { [0]=> string(6) "master" } } array(1) { [0]=> array(1) { [0]=> string(6) "master" } } array(1) { [0]=> array(1) { [0]=> string(6) "master" } } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_failover_rr.phpt0000664000175000017500000001061012161007456032036 0ustar andreyandrey--TEST-- Filter QOS, eventual, trx_stickiness=on, failover --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array("unknown:7033"), 'lazy_connections' => 1, 'trx_stickiness' => 'on', 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1 ), 'roundrobin' => 1 ), 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_failover_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_failover_rr.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); if ($res = mst_mysqli_query(4, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $link->commit(); /* master 1 */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE); if ($res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $link->rollback(); /* master 0 */ if ($res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); /* try slave and failover to master 1, stick with master 1 */ $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); if ($res = mst_mysqli_query(7, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); if ($res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $link->commit(); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d array(1) { [0]=> array(1) { [0]=> string(7) "master0" } } array(1) { [0]=> array(1) { [0]=> string(7) "master1" } } array(1) { [0]=> array(1) { [0]=> string(7) "master0" } } array(1) { [0]=> array(1) { [0]=> string(7) "master1" } } array(1) { [0]=> array(1) { [0]=> string(7) "master1" } } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_trx_stickiness_on.phpt0000664000175000017500000000777512161007456027466 0ustar andreyandrey--TEST-- Filter QOS, eventual, trx_stickiness=on --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'trx_stickiness' => 'on', 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1 ), 'random' => 1 ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on.ini --FILE-- query("SET @myrole='master'")) printf("[002] [%d] %s\n", $link->errno, $link->error); $master_id = mst_mysqli_get_emulated_id(3, $link); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); if ($res = mst_mysqli_query(4, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(5, $link); if ($server_id == $master_id) printf("[006] Query should have been executed on slave\n"); $link->commit(); $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE); if ($res = mst_mysqli_query(7, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(8, $link); if ($server_id != $master_id) printf("[009] Query should have been executed on master because of trx stickiness\n"); $link->rollback(); if ($res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> NULL } } array(1) { [0]=> array(1) { [0]=> string(6) "master" } } array(1) { [0]=> array(1) { [0]=> NULL } } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_rr.phpt0000664000175000017500000001003012161007456030143 0ustar andreyandrey--TEST-- Filter QOS, eventual, trx_stickiness=on, roundrobin --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'trx_stickiness' => 'on', 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1 ), 'roundrobin' => 1 ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.multi_master=1 mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_trx_stickiness_on_rr.ini --FILE-- query("SET @myrole='master0'")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (!$link->query("SET @myrole='master1'")) printf("[003] [%d] %s\n", $link->errno, $link->error); mst_mysqli_query(4, $link, "SET @myrole='slave0'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(5, $link, "SET @myrole='slave1'", MYSQLND_MS_SLAVE_SWITCH); /* slave 0 */ $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); if ($res = mst_mysqli_query(4, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $link->commit(); /* master 0 */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE); if ($res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); $link->rollback(); /* slave 1 */ if ($res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role")) var_dump($res->fetch_all()); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(6) "slave0" } } array(1) { [0]=> array(1) { [0]=> string(7) "master0" } } array(1) { [0]=> array(1) { [0]=> string(6) "slave1" } } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_eventual_trx_stickiness.phpt0000664000175000017500000000647712161007456026770 0ustar andreyandrey--TEST-- Filter QOS, eventual, trx_stickiness=master --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'trx_stickiness' => 'master', 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1 ), 'roundrobin' => 1 ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_eventual_trx_stickiness.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_eventual_trx_stickiness.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); $master_id = mst_mysqli_get_emulated_id(3, $link); $link->autocommit(false); if ($res = mst_mysqli_query(4, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(5, $link); if ($server_id != $master_id) printf("[006] Query should have been executed on master because of trx stickiness\n"); $link->autocommit(true); if ($res = mst_mysqli_query(6, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_all()); $server_id = mst_mysqli_get_emulated_id(7, $link); if ($server_id == $master_id) printf("[008] Query should have been executed on slave because of autocommit mode\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } array(1) { [0]=> array(1) { [0]=> string(1) "1" } } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_multi_master.phpt0000664000175000017500000000653712161007456024513 0ustar andreyandrey--TEST-- Filter QOS, session consistency, MM + RR --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'failover' => array('strategy' => 'master'), 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_multi_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_multi_master.ini mysqlnd_ms.multi_master=1 --FILE-- fetch_assoc(); printf("[003] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(4, $link)); } else { printf("[005] No result\n"); } if ($res = mst_mysqli_query(6, $link, "SELECT 2 AS _num FROM DUAL")) { $row = $res->fetch_assoc(); printf("[007] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(8, $link)); } else { printf("[009] No result\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [003] 1 - master[1,2]-%d [007] 2 - master[1,2]-%d done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_multi_master_strong_r.phpt0000664000175000017500000000762612161007456026430 0ustar andreyandrey--TEST-- Filter QOS, strong consistency, MM + R --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'failover' => array('strategy' => 'master'), 'filters' => array( "quality_of_service" => array( "strong_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_multi_master_strong_r.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_multi_master_strong_r.ini mysqlnd_ms.multi_master=1 --FILE-- fetch_assoc(); printf("[003] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(4, $link)); } else { printf("[005] No result\n"); } if ($res = mst_mysqli_query(6, $link, "SELECT 2 AS _num FROM DUAL")) { $row = $res->fetch_assoc(); printf("[007] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(8, $link)); } else { printf("[009] No result\n"); } if ($res = mst_mysqli_query(10, $link, "SELECT 2 AS _num FROM DUAL", MYSQLND_MS_SLAVE_SWITCH)) { $row = $res->fetch_assoc(); printf("[011] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(12, $link)); } else { printf("[013] No result\n"); } if ($res = mst_mysqli_query(14, $link, "SELECT 1 AS _num FROM DUAL")) { $row = $res->fetch_assoc(); printf("[015] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(16, $link)); } else { printf("[017] No result\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [003] 1 - master[1,2]-%d [007] 2 - master[1,2]-%d [011] 2 - master[1,2]-%d [015] 1 - master[1,2]-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_multi_master_strong_rr.phpt0000664000175000017500000000764712161007456026615 0ustar andreyandrey--TEST-- Filter QOS, strong consistency, MM + RR --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master'), 'filters' => array( "quality_of_service" => array( "strong_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_multi_master_strong_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_multi_master_strong_rr.ini mysqlnd_ms.multi_master=1 --FILE-- fetch_assoc(); printf("[003] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(4, $link)); } else { printf("[005] No result\n"); } if ($res = mst_mysqli_query(6, $link, "SELECT 2 AS _num FROM DUAL")) { $row = $res->fetch_assoc(); printf("[007] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(8, $link)); } else { printf("[009] No result\n"); } if ($res = mst_mysqli_query(10, $link, "SELECT 2 AS _num FROM DUAL", MYSQLND_MS_SLAVE_SWITCH)) { $row = $res->fetch_assoc(); printf("[011] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(12, $link)); } else { printf("[013] No result\n"); } if ($res = mst_mysqli_query(14, $link, "SELECT 1 AS _num FROM DUAL")) { $row = $res->fetch_assoc(); printf("[015] %d - %s\n", $row['_num'], mst_mysqli_get_emulated_id(16, $link)); } else { printf("[017] No result\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [003] 1 - master[1,2]-%d [007] 2 - master[1,2]-%d [011] 2 - master[1,2]-%d [015] 1 - master[1,2]-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos.phpt0000664000175000017500000000363412161007456021721 0ustar andreyandrey--TEST-- Filter QOS --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "strong_consistency" => 1, ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos.ini --FILE-- fetch_assoc()); /* master - ignore SQL hint */ if ($res = mst_mysqli_query(6, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_SLAVE_SWITCH)) var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> string(6) "master" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_rt_gtid_master_on_write.phpt0000664000175000017500000001001212161007456026702 0ustar andreyandrey--TEST-- Filter QOS, master_on_write, GTID --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to drop GTID table on slave %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'master_on_write' => 1, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_master_on_write.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_master_on_write.ini --FILE-- --CLEAN-- --EXPECTF-- Server: slave-%d Server: master-%d Server: master-%d Server: master-%d Server: master-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_rt_gtid.phpt0000664000175000017500000001154312161007456023433 0ustar andreyandrey--TEST-- Filter QOS, runtime, session GTID --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_drop_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to drop GTID table on slave %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_rt_gtid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_rt_gtid.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB") || !$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[002] [%d] %s\n", $link->errno, $link->error); } $emulated_master_id = mst_mysqli_get_emulated_id(3, $link); if ($res = mst_mysqli_query(4, $link, "SELECT id FROM test", MYSQLND_MS_MASTER_SWITCH)) { var_dump($res->fetch_all()); } if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[005] [%d] %s\n", $link->errno, $link->error); printf("GTID '%s'\n", $gtid); if (false == mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid)) { printf("[006] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(7, $link, "SELECT id FROM test")) { var_dump($res->fetch_all()); } $server_id = mst_mysqli_get_emulated_id(8, $link); /* either master or slave depending on test setup. In any case result from select must be correct */ printf("[009] Run on %s\n", $server_id); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } GTID '5' Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1146/'%s' in %s on line %d array(1) { [0]=> array(1) { [0]=> string(1) "1" } } Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1146/'%s' in %s on line %d [009] Run on master1-%s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_rt_gtid_trx_stickiness.phpt0000664000175000017500000001070312161007456026564 0ustar andreyandrey--TEST-- Filter QOS, trx_stickiness, GTID --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to drop GTID table on slave %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'trx_stickiness' => 'master', 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_tr_gtid_trx_stickiness.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_tr_gtid_trx_stickiness.ini --FILE-- autocommit(false)) { printf("[003] [%d] %s\n", $link->errno, $link->error); } if (mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(5, $link)); } if ($res = mst_mysqli_query(6, $link, "SELECT 6 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(7, $link)); } if (!$link->autocommit(true)) { printf("[008] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(9, $link, "SELECT 9 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(10, $link)); } if ($res = mst_mysqli_query(11, $link, "DROP TABLE IF EXISTS test")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(12, $link)); } print "done!"; ?> --CLEAN-- --EXPECTF-- Server: master1-%d Server: master1-%d Server: master1-%d Server: master1-%d Server: master1-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_rt_gtid_trx_stickiness_rr.phpt0000664000175000017500000001073612161007456027275 0ustar andreyandrey--TEST-- Filter QOS, trx_stickiness=on, GTID, roundrobin --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to drop GTID table on slave %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'trx_stickiness' => 'on', 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_tr_gtid_trx_stickiness_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_tr_gtid_trx_stickiness_rr.ini --FILE-- autocommit(false)) { printf("[003] [%d] %s\n", $link->errno, $link->error); } if (mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(5, $link)); } if ($res = mst_mysqli_query(6, $link, "SELECT 6 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(7, $link)); } if (!$link->autocommit(true)) { printf("[008] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(9, $link, "SELECT 9 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(10, $link)); } if ($res = mst_mysqli_query(11, $link, "DROP TABLE IF EXISTS test")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(12, $link)); } print "done!"; ?> --CLEAN-- --EXPECTF-- Server: master1-%d Server: master1-%d Server: master1-%d Server: master1-%d Server: master1-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_rt_gtid_wait_for_fail.phpt0000664000175000017500000001264412161007456026323 0ustar andreyandrey--TEST-- Filter QOS, GTID with timeout (fail) --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to setup GTID table on slave %s\n", $error)); if ($error = mst_mysqli_drop_test_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("Failed to drop test table on slave %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid_wait'], 'wait_for_gtid_timeout' => $sql['wait_for_gtid_fail'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_rt_gtid_wait_for_fail.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_rt_gtid_wait_for_fail.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB") || !$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[002] [%d] %s\n", $link->errno, $link->error); } $emulated_master_id = mst_mysqli_get_emulated_id(3, $link); if ($res = mst_mysqli_query(4, $link, "SELECT id FROM test", MYSQLND_MS_MASTER_SWITCH)) { var_dump($res->fetch_all()); } if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[005] [%d] %s\n", $link->errno, $link->error); printf("GTID '%s'\n", $gtid); /* DO NOT fake a GTID entry on slave - we want to see it fail fetching */ if (false == mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid)) { printf("[006] [%d] %s\n", $link->errno, $link->error); } /* MS shall try to fetch from slave but run into timeout */ $run_time = microtime(true); if ($res = mst_mysqli_query(7, $link, "SELECT id FROM test")) { var_dump($res->fetch_all()); } $run_time = microtime(true) - $run_time; $sql = mst_get_gtid_sql($db); if ($run_time < $sql['wait_for_gtid_fail']) { printf("[008] Runtime %.2fs < %.2fs\n", $run_time, $sql['wait_for_gtid_fail']); } $server_id = mst_mysqli_get_emulated_id(8, $link); /* must be master */ printf("[009] Run on %s\n", $server_id); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } GTID '%s' array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [009] Run on master1-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_rt_gtid_wait_for.phpt0000664000175000017500000001342012161007456025321 0ustar andreyandrey--TEST-- Filter QOS, GTID with timeout (succeed) --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to setup GTID table on slave %s\n", $error)); if ($error = mst_mysqli_drop_test_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("Failed to drop test table on slave %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid_wait'], 'wait_for_gtid_timeout' => $sql['wait_for_gtid_succeed'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_rt_gtid_wait_for.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_rt_gtid_wait_for.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB") || !$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[002] [%d] %s\n", $link->errno, $link->error); } $emulated_master_id = mst_mysqli_get_emulated_id(3, $link); if ($res = mst_mysqli_query(4, $link, "SELECT id FROM test", MYSQLND_MS_MASTER_SWITCH)) { var_dump($res->fetch_all()); } if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[005] [%d] %s\n", $link->errno, $link->error); printf("GTID '%s'\n", $gtid); /* Fake GTID entry on slave to make sure we see the wait situation */ $link_no_ms = new mysqli($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (mysqli_connect_errno()) { printf("[006] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $sql = mst_get_gtid_sql($db); $query = str_replace('#GTID', $gtid, $sql['set']); if (!$link_no_ms->query($query)) { printf("[007] [%d] %s, %s\n", $link->errno, $link->error, $query); } if (false == mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid)) { printf("[008] [%d] %s\n", $link->errno, $link->error); } $run_time = microtime(true); /* goes to the emulated slave which does not have a table test */ if ($res = mst_mysqli_query(9, $link, "SELECT id FROM test")) { var_dump($res->fetch_all()); } $run_time = microtime(true) - $run_time; $sql = mst_get_gtid_sql($db); if ($run_time >= $sql['wait_for_gtid_fail']) { printf("[010] Runtime %.2fs >= %.2fs\n", $run_time, $sql['wait_for_gtid_fail']); } $server_id = mst_mysqli_get_emulated_id(11, $link); /* must be slave */ printf("[012] Run on %s\n", $server_id); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } GTID '%s' [009] [1146] %s [012] Run on slave1-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_runtime.phpt0000664000175000017500000000500012161007456023451 0ustar andreyandrey--TEST-- Filter QOS --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "strong_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_runtime.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_runtime.ini --FILE-- fetch_assoc()); var_dump(mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_STRONG)); /* master */ $res = mst_mysqli_query(7, $link, "SELECT @myrole FROM DUAL"); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No mysqlnd_ms connection in %s on line %d bool(false) bool(true) array(1) { ["@myrole"]=> NULL } bool(true) array(1) { ["@myrole"]=> string(6) "master" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_session_consistency_mm_rr.phpt0000664000175000017500000001471212161007456027300 0ustar andreyandrey--TEST-- Filter QOS, session consistency, MM + RR --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'failover' => array('strategy' => 'master'), 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_session_consistency_mm_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_session_consistency_mm_rr.ini mysqlnd_ms.multi_master=1 --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* master 1 */ mst_mysqli_query(2, $link, "SET @myrole='master 1'"); /* master 2 */ mst_mysqli_query(4, $link, "SET @myrole='master 2'"); $servers = array(); /* master 1 */ $role = fetch_role(6, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 2 */ $role = fetch_role(8, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(9, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 1 */ $role = fetch_role(10, $link); $server_id = mst_mysqli_get_emulated_id(11, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 2 */ $role = fetch_role(12, $link); $server_id = mst_mysqli_get_emulated_id(13, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 2 */ $role = fetch_role(14, $link, MYSQLND_MS_LAST_USED_SWITCH); $server_id = mst_mysqli_get_emulated_id(15, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[016] [%d] %s\n", $link->errno, $link->error); /* slave 1 */ $role = fetch_role(16, $link); $server_id = mst_mysqli_get_emulated_id(17, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 1 */ $role = fetch_role(18, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(19, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[020] [%d] %s\n", $link->errno, $link->error); /* master 2 */ $role = fetch_role(22, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(23, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 1 */ mst_mysqli_query(24, $link, "DROP TABLE IF EXISTS test"); $role = fetch_role(27, $link, MYSQLND_MS_LAST_USED_SWITCH); $server_id = mst_mysqli_get_emulated_id(28, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); foreach ($servers as $server_id => $roles) { foreach ($roles as $role => $num_queries) { printf("%s (%s) has run %d queries\n", $role, $server_id, $num_queries); } } print "done!"; ?> --CLEAN-- --EXPECTF-- master 1 (master[1,2]-%d) has run 4 queries master 2 (master[1,2]-%d) has run 4 queries (slave1-%d) has run 1 queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_session_consistency_no_slaves.phpt0000664000175000017500000000753712161007456030164 0ustar andreyandrey--TEST-- Filter QOS, session consistency, MM + RR --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_session_consistency_no_slaves.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_session_consistency_no_slaves.ini --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* master 1 */ mst_mysqli_query(2, $link, "SET @myrole='master 1'"); /* slave 1 */ mst_mysqli_query(4, $link, "SET @myrole='master 2'", MYSQLND_MS_SLAVE_SWITCH); $servers = array(); /* master 1 */ $role = fetch_role(6, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 1 */ $role = fetch_role(8, $link, MYSQLND_MS_SLAVE_SWITCH); $server_id = mst_mysqli_get_emulated_id(9, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); foreach ($servers as $server_id => $roles) { foreach ($roles as $role => $num_queries) { printf("%s (%s) has run %d queries\n", $role, $server_id, $num_queries); } } print "done!"; ?> --CLEAN-- --EXPECTF-- master 2 (master-%d) has run 2 queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_session_consistency.phpt0000664000175000017500000001121512161007456026077 0ustar andreyandrey--TEST-- Filter QOS, session consistency --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_session_consistency.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_session_consistency.ini --FILE-- fetch_assoc(); printf("Greetings from '%s'\n", $row['_msg']); } else { printf("[%d] %s\n", $link->errno, $link->error); } $server_id = mst_mysqli_get_emulated_id(8, $link); if ($server_id != $emulated_master_id) { printf("[009] Expecting master use, found %s used\n", $server_id); } if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[010] [%d] %s\n", $link->errno, $link->error); /* eventual consistency --- slave may be used */ mst_mysqli_query(12, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $server_id = mst_mysqli_get_emulated_id(15, $link); if ($server_id == $emulated_master_id) { printf("[016] Expecting slave use, found %s used\n", $server_id); } /* slave */ if ($res = mst_mysqli_query(17, $link, "SELECT @myrole AS _msg")) { $row = $res->fetch_assoc(); printf("Greetings from '%s'\n", $row['_msg']); } else { printf("[%d] %s\n", $link->errno, $link->error); } /* master */ mst_mysqli_query(19, $link, "SET @myrole='master'"); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[021] [%d] %s\n", $link->errno, $link->error); /* slave */ if ($res = mst_mysqli_query(22, $link, "SELECT @myrole AS _msg")) { $row = $res->fetch_assoc(); printf("Greetings from '%s'\n", $row['_msg']); } else { printf("[%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Greetings from 'slave' Greetings from 'slave' Greetings from 'master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_session_consistency_trx_stickiness_on.phpt0000664000175000017500000001353612161007456031737 0ustar andreyandrey--TEST-- Filter QOS, session consistency, trx_stickiness=on --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'trx_stickiness' => 'on', 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_session_consistency_trx_stickiness_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_session_consistency_trx_stickiness_on.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* session consistency --- master only if no other consistency criteria is set */ mst_mysqli_query(4, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $server_id = mst_mysqli_get_emulated_id(5, $link); if ($server_id != $emulated_master_id) { printf("[006] Expecting master use, found %s used\n", $server_id); } /* By default slave shall not be used but last set has overwritten previous one */ if ($res = mst_mysqli_query(7, $link, "SELECT @myrole AS _msg")) { $row = $res->fetch_assoc(); printf("Greetings from '%s'\n", $row['_msg']); } else { printf("[%d] %s\n", $link->errno, $link->error); } $server_id = mst_mysqli_get_emulated_id(8, $link); if ($server_id != $emulated_master_id) { printf("[009] Expecting master use, found %s used\n", $server_id); } if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[010] [%d] '%s'\n", $link->errno, $link->error); /* eventual consistency --- slave may be used */ mst_mysqli_query(12, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $server_id = mst_mysqli_get_emulated_id(15, $link); if ($server_id != $emulated_master_id) { printf("[016] Expecting master use, found %s used\n", $server_id); } /* master */ if ($res = mst_mysqli_query(17, $link, "SELECT @myrole AS _msg")) { $row = $res->fetch_assoc(); printf("Greetings from '%s'\n", $row['_msg']); } else { printf("[%d] %s\n", $link->errno, $link->error); } /* master */ mst_mysqli_query(19, $link, "SET @myrole='master'"); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[021] [%d] '%s'\n", $link->errno, $link->error); /* slave */ if ($res = mst_mysqli_query(22, $link, "SELECT @myrole AS _msg")) { $row = $res->fetch_assoc(); printf("Greetings from '%s'\n", $row['_msg']); } else { printf("[%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Greetings from 'slave' Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [010] [0] '' Greetings from 'slave' Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [021] [0] '' Greetings from 'master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_session_consistency_trx_stickiness_on_rr.phpt0000664000175000017500000001357312161007456032443 0ustar andreyandrey--TEST-- Filter QOS, session consistency, trx_stickiness=on --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'trx_stickiness' => 'on', 'filters' => array( "quality_of_service" => array( "session_consistency" => 1, ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_session_consistency_trx_stickiness_on_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.multi_master=1 mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_session_consistency_trx_stickiness_on_rr.ini --FILE-- errno, $link->error); mst_mysqli_query(5, $link, "SET @myrole='slave0'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(6, $link, "SET @myrole='slave1'", MYSQLND_MS_SLAVE_SWITCH); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[007] [%d] '%s'\n", $link->errno, $link->error); $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* master 0 */ mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT @myrole AS _role")); /* reject change */ if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[009] [%d] '%s'\n", $link->errno, $link->error); /* master 0, in transaction! */ mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role")); $link->commit(); /* relaxing should be allowed */ if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[011] [%d] '%s'\n", $link->errno, $link->error); /* slave 0, slave 1, slave 0 */ mst_mysqli_fech_role(mst_mysqli_query(12, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(13, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(14, $link, "SELECT @myrole AS _role")); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION))) printf("[015] [%d] '%s'\n", $link->errno, $link->error); /* master 1 */ mst_mysqli_fech_role(mst_mysqli_query(16, $link, "SELECT @myrole AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- This is 'master0' speaking Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [009] [0] '' This is 'master0' speaking This is 'slave0' speaking This is 'slave1' speaking This is 'slave0' speaking This is 'master1' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_strong_consistency.phpt0000664000175000017500000000634412161007456025737 0ustar andreyandrey--TEST-- Filter QOS, strong consistency --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "strong_consistency" => 1, ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_strong_consistency.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_strong_consistency.ini --FILE-- fetch_assoc()); /* master - ignore SQL hint */ $res = mst_mysqli_query(6, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_SLAVE_SWITCH); var_dump($res->fetch_assoc()); /* master - ignore SQL hint */ $res = mst_mysqli_query(8, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL))) printf("[010] [%d] %s\n", $link->errno, $link->error); /* this is an interesting case, should be master */ $res = mst_mysqli_query(12, $link, "SELECT @myrole FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH); var_dump($res->fetch_assoc()); /* slave */ $res = mst_mysqli_query(14, $link, "SELECT @myrole FROM DUAL"); var_dump($res->fetch_assoc()); if (false === ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_STRONG))) printf("[016] [%d] %s\n", $link->errno, $link->error); /* master */ $res = mst_mysqli_query(18, $link, "SELECT @myrole FROM DUAL"); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> string(6) "master" } array(1) { ["@myrole"]=> NULL } array(1) { ["@myrole"]=> string(6) "master" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_qos_trx_stickiness.phpt0000664000175000017500000000607512161007456025057 0ustar andreyandrey--TEST-- Filter QOS, trx_stickiness --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "quality_of_service" => array( "eventual_consistency" => 1, ), "random" => array(), ), 'trx_stickiness' => 'master', ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_qos_trx_stickiness.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_qos_trx_stickiness.ini --FILE-- autocommit(false)) { printf("[003] [%d] %s\n", $link->errno, $link->error); } if (mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(5, $link)); } if ($res = mst_mysqli_query(6, $link, "SELECT 6 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(7, $link)); } if (!$link->autocommit(true)) { printf("[008] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(9, $link, "SELECT 9 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(10, $link)); } if ($res = mst_mysqli_query(11, $link, "DROP TABLE IF EXISTS test")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(12, $link)); } print "done!"; ?> --CLEAN-- --EXPECTF-- Server: slave-%d Server: master-%d Server: master-%d Server: slave-%d Server: master-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_ro_partitioning_rr.phpt0000664000175000017500000000676412161007456025040 0ustar andreyandrey--TEST-- Stacking LB filters and partitioning filter --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array("sticky" => 1), "table" => array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1", "slave2"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_ro_partitioning_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_ro_partitioning_rr.ini --FILE-- fetch_assoc(); printf("[009] Hi folks, %s speaking.\n", $row['_role']); foreach ($threads as $id => $role) printf("%s => %s\n", $id, $role); print "done!"; ?> --CLEAN-- --EXPECTF-- [009] Hi folks, slave%d speaking. master-%d => master slave[1,2]-%d => slave%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_filter_twice.phpt0000664000175000017500000000616412161007456022233 0ustar andreyandrey--TEST-- Two LB filters --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array(), "random" => array("sticky" => "1"), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_filter_twice.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_filter_twice.ini --FILE-- errno, $link->error); } foreach ($threads as $id => $roles) { printf("%s: ", $id); foreach ($roles as $role) printf("%s\n", $role); } print "done!"; ?> --CLEAN-- --EXPECTF-- master-%d: master slave[1,2]-%d: slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_charset.phpt0000664000175000017500000001720112161007456022035 0ustar andreyandrey--TEST-- mysqli_get_charsets() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_charsets.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); function test_for_charset($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) || !($tmp = mysqli_fetch_assoc($res))) { mysqli_close($link); die(sprintf("skip Cannot check server version, [%d] %s\n", mysqli_errno($link), mysqli_error($link))); } mysqli_free_result($res); $version = explode('.', $tmp['server_version']); if (empty($version)) { mysqli_close($link); die(sprintf("skip Cannot check server version, based on '%s'", $tmp['server_version'])); } if ($version[0] <= 4 && $version[1] < 1) { mysqli_close($link); die(sprintf("skip Requires MySQL Server 4.1+\n")); } if ((($res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'latin1'", MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) || (($res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'latin2'", MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) ) { // ok, required latin1 or latin2 are available } else { die(sprintf("skip Requires character set latin1 or latin2\n")); } if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset')) die(sprintf("skip Cannot select current charset, [%d] %s\n", $link->errno, $link->error)); if (!$row = mysqli_fetch_assoc($res)) die(sprintf("skip Cannot detect current charset, [%d] %s\n", $link->errno, $link->error)); return $row['charset']; } $master_charset = test_for_charset($master_host_only, $user, $passwd, $db, $master_port, $master_socket); $slave_charset = test_for_charset($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if ($master_charset != $slave_charset) { die(sprintf("skip Master (%s) and slave (%s) must use the same default charset.", $master_charset, $slave_charset)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_charsets.ini --FILE-- get_charset(); if ($charset->charset != $expected['charset']) printf("[%03d + 01] Expecting charset '%s' got '%s'\n", $offset, $expected['charset'], $charset->charset); if ($charset->collation != $expected['collation']) printf("[%03d + 02] Expecting collation '%s' got '%s'\n", $offset, $expected['collation'], $charset->collation); if ($charset->max_length != $expected['max_length']) printf("[%03d + 03] Expecting max length %d got %d '\n", $offset, $expected['charset'], $charset->max_length); if (($charset->min_length < 0) || ($charset->min_length > $expected['max_length'])) printf("[%03d + 04] Expecting min length 0..%d got %d\n", $offset, $expected['max_length']. $charset->min_length); } /* Charset changes made through the user API are applied to all connections. This is important and a security must because string escaping depends on the current charset. If the plugin would not take care of it, the following sequence would bear a security risk. INSERT - master, charset latin1 $somestring = escape_string(link, "somestring") - would use latin1 from last used connection SELECT * FROM test WHERE column = $somestring - slave, slave may be using latin2, $somestring should have been escaped using latin2 */ if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); mst_mysqli_query(3, $link, "SET @myrole='slave 1'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(4, $link, "SET @myrole='slave 2'", MYSQLND_MS_SLAVE_SWITCH); /* master */ $res = mst_mysqli_query(5, $link, "SHOW CHARACTER SET LIKE 'latin1'"); if (!$row = $res->fetch_assoc()) printf("[006] [%d] %s\n", $link->errno, $link->error); $latin1 = array( 'charset' => (isset($row['Charset'])) ? $row['Charset'] : NULL, 'collation' => (isset($row['Default collation'])) ? $row['Default collation'] : NULL, 'max_length' => (isset($row['Maxlen'])) ? $row['Maxlen'] : NULL, ); /* master */ if (!$res = mst_mysqli_query(7, $link, "SHOW CHARACTER SET LIKE 'latin2'")) printf("[008] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[009] [%d] %s\n", $link->errno, $link->error); $latin2 = array( 'charset' => (isset($row['Charset'])) ? $row['Charset'] : NULL, 'collation' => (isset($row['Default collation'])) ? $row['Default collation'] : NULL, 'max_length' => (isset($row['Maxlen'])) ? $row['Maxlen'] : NULL, ); /* slave 1 */ if (!$res = mst_mysqli_query(4, $link, "SELECT @@character_set_connection AS charset", MYSQLND_MS_SLAVE_SWITCH)) printf("[010] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[011] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; if ('latin1' == $current_charset) { $new_charset = 'latin2'; $new_expected = $latin2; check_charset(12, $link, $latin1); } else { $new_charset = 'latin1'; $new_expected = $latin1; check_charset(12, $link, $latin2); } /* shall be run on *all* configured machines - all masters, all slaves */ $link->set_charset($new_charset); /* slave 1 */ if (!$res = mst_mysqli_query(13, $link, "SELECT @@character_set_connection AS charset", MYSQLND_MS_LAST_USED_SWITCH)) printf("[014] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[015] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; if ($current_charset != $new_charset) printf("[016] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); check_charset(17, $link, $new_expected); /* master */ if (!$res = mst_mysqli_query(11, $link, "SELECT @@character_set_connection AS charset", MYSQLND_MS_MASTER_SWITCH)) printf("[018] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[019] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; if ($current_charset != $new_charset) printf("[020] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); if ($link->character_set_name() != $new_charset) printf("[021] Expecting charset '%s' got '%s'\n", $new_charset, $link->character_set_name); check_charset(22, $link, $new_expected); /* slave 2 */ if (!$res = mst_mysqli_query(13, $link, "SELECT @@character_set_connection AS charset", MYSQLND_MS_SLAVE_SWITCH)) printf("[023] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[024] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; if ($current_charset != $new_charset) printf("[025] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); check_charset(26, $link, $new_expected); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_connection_stats.phpt0000664000175000017500000000674512161007456023774 0ustar andreyandrey--TEST-- mysqlnd connection statistics --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_connection_stats.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_connection_stats.ini --FILE-- 'Slave 1', 'bytes' => $bytes, 'com_query' => $stats['com_query']); /* slave 2 */ mst_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $stats = mysqli_get_connection_stats($link); $bytes_new = $stats['bytes_sent']; if ($bytes_new <= $bytes) printf("[005] Expecting bytes_sent >= %d, got %d\n", $bytes, $bytes_new); $bytes = $bytes_new; $threads[mst_mysqli_get_emulated_id(6, $link)] = array('role' => 'Slave 2', 'bytes' => $bytes, 'com_query' => $stats['com_query']); /* master */ mst_mysqli_query(7, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $stats = mysqli_get_connection_stats($link); $bytes_new = $stats['bytes_sent']; if ($bytes_new <= $bytes) printf("[008] Expecting bytes_sent >= %d, got %d\n", $bytes, $bytes_new); $bytes = $bytes_new; $threads[mst_mysqli_get_emulated_id(9, $link)] = array('role' => 'Master', 'bytes' => $bytes, 'com_query' => $stats['com_query']); foreach ($threads as $thread_id => $details) printf("%s - %s: %d bytes, %d queries\n", $thread_id, $details['role'], $details['bytes'], $details['com_query']); print "done!"; ?> --CLEAN-- --EXPECTF-- slave[1,2]-%d - Slave 1: %d bytes, 1 queries slave[1,2]-%d - Slave 2: %d bytes, 1 queries master-%d - Master: %d bytes, 1 queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_last_gtid_config.phpt0000664000175000017500000001075312161007456023710 0ustar andreyandrey--TEST-- mysqlnd_ms_get_last_gtid(), fetch_last_gtid --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to setup GTID on slave, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => NULL, 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_last_gtid_config.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_last_gtid_config.ini --FILE-- query("DROP TABLE IF EXISTS test")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (false !== ($ret = mysqlnd_ms_get_last_gtid($link))) { printf("[003] Expecting false, got %s\n", var_export($ret, true)); } else { printf("[004] [%d] %s\n", $link->errno, $link->error); } /* check if error on line */ if (!$link->query("CREATE TABLE test(id INT)")) printf("[005] [%d] %s\n", $link->errno, $link->error); /* commit, slave */ if (!$link->autocommit(false)) printf("[006] [%d] %s\n", $link->errno, $link->error); mst_mysqli_query(7, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); if (false !== ($ret = mysqlnd_ms_get_last_gtid($link))) { printf("[009] Expecting false, got %s\n", var_export($ret, true)); } else { printf("[010] [%d] %s\n", $link->errno, $link->error); } mst_mysqli_query(11, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqlnd_ms_get_last_gtid(): SQL to fetch last global transaction ID is not set in %s on line %d [004] [0%A Warning: mysqlnd_ms_get_last_gtid(): SQL to fetch last global transaction ID is not set in %s on line %d [010] [0%A done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_last_gtid_params.phpt0000664000175000017500000000676312161007456023734 0ustar andreyandrey--TEST-- mysqlnd_ms_get_last_gtid() params --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_last_gtid_params.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_last_gtid_params.ini --FILE-- errno, $link->error); } /* non MS connection */ $link = mst_mysqli_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); if (mysqli_connect_errno()) { printf("[007] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } if (false !== ($ret = mysqlnd_ms_get_last_gtid($link))) { printf("[008] Expecting false, got %s\n", var_export($ret, true)); printf("[009] [%d] %s\n", $link->errno, $link->error); } else { printf("[010] [%d] %s\n", $link->errno, $link->error); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[011] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* no connection selected and lazy */ if (false !== ($ret = mysqlnd_ms_get_last_gtid($link))) { printf("[012] Expecting false, got %s\n", var_export($ret, true)); } else { printf("[013] [%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqlnd_ms_get_last_gtid(): (mysqlnd_ms) %s in %s on line %d [005] [0%A [006] [0%A Warning: mysqlnd_ms_get_last_gtid(): (mysqlnd_ms) %s in %s on line %d [010] [0%A Warning: mysqlnd_ms_get_last_gtid(): (mysqlnd_ms) %s in %s on line %d [013] [0%A done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_last_gtid.phpt0000664000175000017500000000770112161007456022362 0ustar andreyandrey--TEST-- mysqlnd_ms_get_last_gtid() --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_last_gtid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_last_gtid.ini --FILE-- query("DROP TABLE IF EXISTS test")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (1 != ($gtid = mysqlnd_ms_get_last_gtid($link))) { printf("[003] Expecting 1, got %s\n", var_export($gtid, true)); } else { printf("[004] [%d] %s\n", $link->errno, $link->error); } $last_gtid = $gtid; $link->autocommit(false); if (!$link->query("CREATE TABLE test(id INT)")) printf("[005] [%d] %s\n", $link->errno, $link->error); if ($last_gtid !== ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[006] Expecting %s got %s, [%d] %s\n", $last_gtid, $gtid, $link->errno, $link->error); if (!$link->rollback()) printf("[007] [%d] %s\n", $link->errno, $link->error); if (!$link->commit()) printf("[008] [%d] %s\n", $link->errno, $link->error); if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[009] [%d] %s\n", $last_gtid, $gtid, $link->errno, $link->error); if ($gtid <= $last_gtid) printf("[010] last %s, new %s\n", $last_gtid, $gtid); print "done!"; ?> --CLEAN-- --EXPECTF-- [004] [0%s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_last_gtid_sql_error.phpt0000664000175000017500000000612512161007456024451 0ustar andreyandrey--TEST-- mysqlnd_ms_get_last_gtid(), sql error --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => 'Hi there!', 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_last_gtid_sql_error.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_last_gtid_sql_error.ini --FILE-- autocommit(false)) printf("[002] [%d] %s\n", $link->errno, $link->error); mst_mysqli_query(3, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); if (false !== ($ret = mysqlnd_ms_get_last_gtid($link))) { printf("[005] Expecting false, got %s\n", var_export($ret, true)); } else { printf("[006] [%d] %s\n", $link->errno, $link->error); } mst_mysqli_query(7, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); if (!$link->autocommit(false)) printf("[009] [%d] %s\n", $link->errno, $link->error); /* autocommit, master */ if (!$link->query("DROP TABLE IF EXISTS test")) printf("[010] [%d] %s\n", $link->errno, $link->error); if (false !== ($ret = mysqlnd_ms_get_last_gtid($link))) { printf("[011] Expecting false, got %s\n", var_export($ret, true)); } else { printf("[012] [%d] %s\n", $link->errno, $link->error); } /* check if error on line */ if (!$link->query("CREATE TABLE test(id INT)")) printf("[013] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [006] [1064] %s [012] [1064] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_last_used_connection.phpt0000664000175000017500000002004112161007456024602 0ustar andreyandrey--TEST-- mysqlnd_ms_get_last_used_connection() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_last_used_connection.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_last_used_connection.ini --FILE-- $value) { if (!empty($ignore_list) && in_array($prop, $ignore_list)) { unset($members[$prop]); continue; } if (isset($members[$prop])) { $type = gettype($value); $type = ("integer" == $type) ? "int" : $type; if ($type != $members[$prop]) { printf("[%03d + 02] Property %s should be of type %s, got %s\n", $offset, $members[$prop], $type); } if (isset($expected[$prop])) { if ($expected[$prop] !== $value) { printf("[%03d + 03] Expecting %s = %s, got %s\n", $offset, $prop, var_export($expected[$prop], true), var_export($value, true)); } unset($expected[$prop]); } else { switch ($members[$prop]) { case "string": if ($value !== "") { printf("[%03d + 04] Expecting %s = , got %s\n", $offset, $prop, var_export($value, true)); } break; case "int": if ($value !== 0) { printf("[%03d + 05] Expecting %s = 0, got %s\n", $offset, $prop, var_export($value, true)); } break; case "array": if (0 !== count($value)) { printf("[%03d + 06] Expecting %s = , got %s\n", $offset, $prop, var_export($value, true)); } break; default: break; } } unset($members[$prop]); } else { if (empty($ignore_list) || !in_array($prop, $ignore_list)) { printf("[%03d + 07] Unexpected %s = %s\n", $offset, $prop, var_export($value, true)); } } } if (!empty($members)) { printf("[%03d + 08] Dumping list of missing properties\n", $offset); var_dump($members); return false; } return true; } if (!is_null($ret = @mysqlnd_ms_get_last_used_connection())) printf("[001] Expecting NULL got %s\n", var_export($ret, true)); if (false !== ($ret = @mysqlnd_ms_get_last_used_connection("test"))) printf("[002] Expecting FALSE got %s\n", var_export($ret, true)); if (!is_null($ret = @mysqlnd_ms_get_last_used_connection("test", "test"))) printf("[003] Expecting NULL got %s\n", var_export($ret, true)); $members = array( "scheme" => "string", "host_info" => "string", "host" => "string", "port" => "int", "socket_or_pipe" => "string", "thread_id" => "int", "last_message" => "string", "errno" => "int", "error" => "string", "sqlstate" => "string", ); /* mysqli */ $link = new mysqli(); $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(4, $conn, $members); /* non MS */ if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[005] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket); $expected = array( "host" => ("localhost" == $host) ? "" : $host, "host_info" => $link->host_info, "port" => (int)$port, "socket_or_pipe" => ("localhost" == $host) ? (($socket) ? $socket : "/tmp/mysql.sock") : "", "thread_id" => $link->thread_id, "errno" => $link->errno, "error" => $link->error, "sqlstate" => $link->sqlstate, ); if ("localhost" != $host && !$socket) { $expected["scheme"] = sprintf("tcp://%s:%d", $host, $port); } $conn = mysqlnd_ms_get_last_used_connection($link); if (!isset($expected["scheme"]) && isset($conn["scheme"])) /* accept whatever "&/"&/"§ default socket there may be... */ $expected["scheme"] = $conn["scheme"]; /* this is hackish but I can't think of a better way of implementing at the C level */ conn_diff(6, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); /* error on non MS */ @$link->query("PLEASE, LET THIS BE INVALID My-S-Q-L"); $expected["errno"] = $link->errno; $expected["error"] = $link->error; $expected["sqlstate"] = $link->sqlstate; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(7, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); @$link->query("YEAH, HEY, OK, HEY, .."); $expected["errno"] = $link->errno; $expected["error"] = $link->error; $expected["sqlstate"] = $link->sqlstate; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(8, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); if (!$link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket)) printf("[011] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket); $expected = array( "host" => ("localhost" == $master_host_only) ? "" : $master_host_only, "host_info" => $link->host_info, "port" => (int)$master_port, "socket_or_pipe" => ("localhost" == $master_host_only) ? (($master_socket) ? $master_socket : "/tmp/mysql.sock") : "", "thread_id" => $link->thread_id, "errno" => $link->errno, "error" => $link->error, "sqlstate" => $link->sqlstate, ); if ("localhost" != $master_host_only && !$master_socket) { $expected["port"] = (int)$master_port; $expected["scheme"] = sprintf("tcp://%s:%d", $master_host_only, $master_port); } $conn = mysqlnd_ms_get_last_used_connection($link); if (!isset($expected["scheme"]) && isset($conn["scheme"])) /* accept whatever "&/"&/"§ default socket there may be... */ $expected["scheme"] = $conn["scheme"]; conn_diff(12, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); /* should go to the master */ /* error on MS */ @$link->query("PLEASE, LET THIS BE INVALID My-S-Q-L"); $expected["errno"] = $link->errno; $expected["error"] = $link->error; $expected["sqlstate"] = $link->sqlstate; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(13, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); /* should go to the master */ @$link->query("PLEASE, LET THIS BE INVALID My-S-Q-L"); $expected["errno"] = $link->errno; $expected["error"] = $link->error; $expected["sqlstate"] = $link->sqlstate; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(14, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); /* should go to the master */ @$link->select_db("My-S-Q-L rocks, My-S-Q-L"); $expected["errno"] = $link->errno; $expected["error"] = $link->error; $expected["sqlstate"] = $link->sqlstate; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(15, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); $link->kill($link->thread_id); /* give server think time */ sleep(1); $expected["errno"] = $link->errno; $expected["error"] = $link->error; $expected["sqlstate"] = $link->sqlstate; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(16, $conn, $members, $expected, (0 == $expected['port']) ? array('port') : array()); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_last_used_connection_switches.phpt0000664000175000017500000002310712161007456026521 0ustar andreyandrey--TEST-- mysqlnd_ms_get_last_used_connection() switching --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'lazy_connections' => 1, 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_last_used_connection_switches.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_last_used_connection_switches.ini --FILE-- $value) { if (!empty($ignore_list) && in_array($prop, $ignore_list)) { unset($members[$prop]); continue; } if (isset($members[$prop])) { $type = gettype($value); $type = ("integer" == $type) ? "int" : $type; if ($type != $members[$prop]) { printf("[%03d + 02] Property %s should be of type %s, got %s\n", $offset, $members[$prop], $type); } if (isset($expected[$prop])) { if ($expected[$prop] !== $value) { printf("[%03d + 03] Expecting %s = %s, got %s\n", $offset, $prop, var_export($expected[$prop], true), var_export($value, true)); } unset($expected[$prop]); } else { switch ($members[$prop]) { case "string": if ($value !== "") { printf("[%03d + 04] Expecting %s = , got %s\n", $offset, $prop, var_export($value, true)); } break; case "int": if ($value !== 0) { printf("[%03d + 05] Expecting %s = 0, got %s\n", $offset, $prop, var_export($value, true)); } break; case "array": if (0 !== count($value)) { printf("[%03d + 06] Expecting %s = , got %s\n", $offset, $prop, var_export($value, true)); } break; default: break; } } unset($members[$prop]); } else { if (empty($ignore_list) || !in_array($prop, $ignore_list)) { printf("[%03d + 07] Unexpected %s = %s\n", $offset, $prop, var_export($value, true)); } } } if (!empty($members)) { printf("[%03d + 08] Dumping list of missing properties\n", $offset); var_dump($members); return false; } return true; } $members = array( "scheme" => "string", "host_info" => "string", "host" => "string", "port" => "int", "socket_or_pipe" => "string", "thread_id" => "int", "last_message" => "string", "errno" => "int", "error" => "string", "sqlstate" => "string", ); if (!$link = mst_mysqli_connect("myapp", $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); /* lazy and no stmt run */ $expected = array("sqlstate" => $link->sqlstate); $conn = mysqlnd_ms_get_last_used_connection($link); /* this is hackish but I can't think of a better way of implementing at the C level */ conn_diff(2, $conn, $members, $expected, (isset($expected['port']) && (0 == $expected['port'])) ? array('port') : array()); /* master */ mst_mysqli_query(3, $link, "SET @myrole='master'"); $expected = array( "host" => ("localhost" == $emulated_master_host_only) ? "" : $emulated_master_host_only, "host_info" => $link->host_info, "port" => (int)$emulated_master_port, "socket_or_pipe" => ("localhost" == $emulated_master_host_only) ? (($emulated_master_socket) ? $emulated_master_socket : "/tmp/mysql.sock") : "", "thread_id" => $link->thread_id, "errno" => $link->errno, "error" => $link->error, "sqlstate" => $link->sqlstate, ); if ("localhost" != $emulated_master_host && !$emulated_master_socket) { $expected["scheme"] = sprintf("tcp://%s:%d", $emulated_master_host_only, $emulated_master_port); } $conn = mysqlnd_ms_get_last_used_connection($link); if (!isset($expected["scheme"]) && isset($conn["scheme"])) /* accept whatever "&/"&/"§ default socket there may be... */ $expected["scheme"] = $conn["scheme"]; conn_diff(4, $conn, $members, $expected, (isset($expected['port']) && (0 == $expected['port'])) ? array('port') : array()); $threads[mst_mysqli_get_emulated_id(5, $link)] = array($link->thread_id, $conn["scheme"]); /* slave 1 */ mst_mysqli_query(6, $link, "SET @myrole='slave1'", MYSQLND_MS_SLAVE_SWITCH); $expected["thread_id"] = $link->thread_id; $expected["host"] = ("localhost" == $emulated_slave_host_only) ? "" : $emulated_slave_host_only; $expected["port"] = (int)$emulated_slave_port; $expected["socket_or_pipe"] = ("localhost" == $emulated_slave_host_only) ? (($emulated_slave_socket) ? $emulated_slave_socket : "/tmp/mysql.sock") : ""; $expected["host_info"] = $link->host_info; if (("localhost" != $emulated_slave_host_only) && (!$emulated_slave_socket)) { $expected["scheme"] = sprintf("tcp://%s:%d", $emulated_slave_host_only, $emulated_slave_port); } else { unset($expected["scheme"]); } $conn = mysqlnd_ms_get_last_used_connection($link); if (!isset($expected["scheme"]) && isset($conn["scheme"])) /* accept whatever "&/"&/"§ default socket there may be... */ $expected["scheme"] = $conn["scheme"]; conn_diff(7, $conn, $members, $expected, (isset($expected['port']) && (0 == $expected['port'])) ? array('port') : array()); $threads[mst_mysqli_get_emulated_id(8, $link)] = array($link->thread_id, $conn["scheme"]); /* slave 2 */ mst_mysqli_query(9, $link, "SET @myrole='slave2'", MYSQLND_MS_SLAVE_SWITCH); $expected["thread_id"] = $link->thread_id; $conn = mysqlnd_ms_get_last_used_connection($link); conn_diff(10, $conn, $members, $expected, (isset($expected['port']) && (0 == $expected['port'])) ? array('port') : array()); $threads[mst_mysqli_get_emulated_id(11, $link)] = array($link->thread_id, $conn["scheme"]); /* rr: slave 1 */ $res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role"); $row = $res->fetch_assoc(); printf("[013] Hi folks, %s speaking.\n", $row['_role']); $conn = mysqlnd_ms_get_last_used_connection($link); $exp = $threads[mst_mysqli_get_emulated_id(14, $link)]; if ($conn["thread_id"] != $exp[0]) { printf("[015] Thread id seems wrong. Check manually.\n"); } if ($conn["scheme"] != $exp[1]) { printf("[016] Scheme seems wrong. Check manually.\n"); } /* rr: slave 2 */ $res = mst_mysqli_query(17, $link, "SELECT @myrole AS _role"); $row = $res->fetch_assoc(); printf("[018] Hi folks, %s speaking.\n", $row['_role']); $conn = mysqlnd_ms_get_last_used_connection($link); $exp = $threads[mst_mysqli_get_emulated_id(19, $link)]; if ($conn["thread_id"] != $exp[0]) { printf("[020] Thread id seems wrong. Check manually.\n"); } if ($conn["scheme"] != $exp[1]) { printf("[021] Scheme seems wrong. Check manually.\n"); } /* master */ $res = mst_mysqli_query(22, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("[023] Hi folks, %s speaking.\n", $row['_role']); $conn = mysqlnd_ms_get_last_used_connection($link); $exp = $threads[mst_mysqli_get_emulated_id(24, $link)]; if ($conn["thread_id"] != $exp[0]) { printf("[025] Thread id seems wrong. Check manually.\n"); } if ($conn["scheme"] != $exp[1]) { printf("[026] Scheme seems wrong. Check manually.\n"); } /* master */ $res = mst_mysqli_query(27, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); printf("[028] Hi folks, %s speaking.\n", $row['_role']); $conn = mysqlnd_ms_get_last_used_connection($link); $exp = $threads[mst_mysqli_get_emulated_id(29, $link)]; if ($conn["thread_id"] != $exp[0]) { printf("[030] Thread id seems wrong. Check manually.\n"); } if ($conn["scheme"] != $exp[1]) { printf("[031] Scheme seems wrong. Check manually.\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [013] Hi folks, slave1 speaking. [018] Hi folks, slave2 speaking. [023] Hi folks, master speaking. [028] Hi folks, master speaking. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_stats_disabled.phpt0000664000175000017500000000051312161007456023367 0ustar andreyandrey--TEST-- mysqlnd_ms_get_stats() and mysqlnd_ms disabled --SKIPIF-- --INI-- mysqlnd_ms.enable=0 mysqlnd_ms.collect_statistics=1 --FILE-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_stats.phpt0000664000175000017500000000702612161007456021546 0ustar andreyandrey--TEST-- mysqlnd_ms_get_stats() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connections' => 0 ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_stats.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_stats.ini mysqlnd_ms.collect_statistics=1 --FILE-- true, "use_master" => true, "use_slave_guess" => true, "use_master_guess" => true, "use_slave_sql_hint" => true, "use_master_sql_hint" => true, "use_last_used_sql_hint" => true, "use_slave_callback" => true, "use_master_callback" => true, "non_lazy_connections_slave_success" => true, "non_lazy_connections_slave_failure" => true, "non_lazy_connections_master_success" => true, "non_lazy_connections_master_failure" => true, "lazy_connections_slave_success" => true, "lazy_connections_slave_failure" => true, "lazy_connections_master_success" => true, "lazy_connections_master_failure" => true, "trx_autocommit_on" => true, "trx_autocommit_off" => true, "trx_master_forced" => true, ); if (MYSQLND_MS_VERSION_ID >= 10200) { $expected["gtid_autocommit_injections_success"] = true; $expected["gtid_autocommit_injections_failure"] = true; $expected["gtid_commit_injections_success"] = true; $expected["gtid_commit_injections_failure"] = true; $expected["gtid_implicit_commit_injections_success"] = true; $expected["gtid_implicit_commit_injections_failure"] = true; } if (NULL !== ($ret = @mysqlnd_ms_get_stats(123))) { printf("[001] Expecting NULL got %s/%s\n", gettype($ret), $ret); } $stats = mysqlnd_ms_get_stats(); $exp_stats = $stats; foreach ($expected as $k => $v) { if (!isset($stats[$k])) { printf("[002] Statistic '%s' missing\n", $k); } else { unset($stats[$k]); } } if (!empty($stats)) { printf("[003] Dumping unknown statistics\n"); var_dump($stats); } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[004] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $exp_stats['non_lazy_connections_slave_success']++; $exp_stats['non_lazy_connections_master_success']++; mst_mysqli_query(5, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); $exp_stats['use_master_sql_hint']++; $exp_stats['use_master']++; mst_mysqli_query(6, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $exp_stats['use_slave_sql_hint']++; $exp_stats['use_slave']++; $res = mst_mysqli_query(7, $link, "SELECT @myrole AS _role"); $exp_stats['use_slave_guess']++; $exp_stats['use_slave']++; $row = $res->fetch_assoc(); $res->close(); if ($row['_role'] != 'slave') printf("[008] Expecting role = slave got role = '%s'\n", $row['_role']); $stats = mysqlnd_ms_get_stats(); foreach ($stats as $k => $v) { if ($exp_stats[$k] != $v) { printf("[009] Expecting %s = '%s', got '%s'\n", $k, $exp_stats[$k], $v); } } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_get_stats_register_shutdown.phpt0000664000175000017500000000571312161007456025406 0ustar andreyandrey--TEST-- mysqlnd_ms_get_stats() + register_shutdown --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connections' => 0 ), ); if ($error = mst_create_config("test_mysqlnd_ms_get_stats_register_shutdown.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_get_stats_register_shutdown.ini mysqlnd_ms.collect_statistics=1 --FILE-- $v) { if ($exp_stats[$k] != $v) { printf("[005] Expecting %s = '%s', got '%s'\n", $k, $exp_stats[$k], $v); } } if (empty($stats)) { printf("[006] Statistics are empty, dumping\n"); var_dump($stats); } printf("shutdown completed!\n"); } register_shutdown_function("check_stats"); /* some stats, not all... we are not much after checking the list */ $expected = array( "use_slave" => true, "use_master" => true, "use_slave_guess" => true, "use_master_guess" => true, "use_slave_sql_hint" => true, "use_master_sql_hint" => true, "use_last_used_sql_hint" => true, "use_slave_callback" => true, "use_master_callback" => true, "non_lazy_connections_slave_success" => true, "non_lazy_connections_slave_failure" => true, "non_lazy_connections_master_success" => true, "non_lazy_connections_master_failure" => true, "lazy_connections_slave_success" => true, "lazy_connections_slave_failure" => true, "lazy_connections_master_success" => true, "lazy_connections_master_failure" => true, "trx_autocommit_on" => true, "trx_autocommit_off" => true, "trx_master_forced" => true, ); $stats = mysqlnd_ms_get_stats(); $exp_stats = $stats; if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $exp_stats['non_lazy_connections_slave_success']++; $exp_stats['non_lazy_connections_master_success']++; mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); $exp_stats['use_master_sql_hint']++; $exp_stats['use_master']++; $stats = mysqlnd_ms_get_stats(); foreach ($stats as $k => $v) { if ($exp_stats[$k] != $v) { printf("[004] Expecting %s = '%s', got '%s'\n", $k, $exp_stats[$k], $v); } } print "done!\n"; ?> --CLEAN-- --EXPECTF-- done! shutdown completed!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_autocommit_stats.phpt0000664000175000017500000002363012161007456024156 0ustar andreyandrey--TEST-- GTID autocommit mode stats --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_autocommit_stats.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_autocommit_stats.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* we need an extra non-MS link for checking GTID. If we use MS link, the check itself will change GTID */ $emulated_master_link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (mysqli_connect_errno()) { printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ $gtid = mst_mysqli_fetch_gtid(5, $emulated_master_link, $db); if (mst_mysqli_query(6, $link, "SET @myrole = 'Master'")) $expected['gtid_autocommit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(8, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[009] GTID has not been incremented on master in auto commit mode\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(10, $stats, $expected); /* commit shall be ignored */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(11, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[013] GTID has not been incremented on master in auto commit mode\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(14, $stats, $expected); /* commit shall be ignored */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(15, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[016] GTID has been incremented on master in auto commit mode\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(18, $stats, $expected); /* autocommit */ if ($res = mst_mysqli_query(19, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH)) $expected['gtid_autocommit_injections_success']++; else printf("[020] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(21, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[023] GTID has not been incremented on master in auto commit mode\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(24, $stats, $expected); $row = $res->fetch_assoc(); printf("Hi there, this is your %s speaking\n", $row['_role']); /* slave query, no increment by default! */ if (!($res = mst_mysqli_query(25, $link, "SELECT 1 AS _one FROM DUAL"))) printf("[027] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Let me be your #%d\n", $row['_one']); $new_gtid = mst_mysqli_fetch_gtid(28, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[029] GTID has been incremented on master in auto commit mode after slave query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(30, $stats, $expected); /* commit shall be ignored - also on the slave (last used) */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(31, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[032] GTID has been incremented on master in auto commit mode after slave commit\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(33, $stats, $expected); $link->autocommit(FALSE); /* autocommit off, stat must not change */ if (!($res = mst_mysqli_query(34, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH))) printf("[020] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(36, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[037] GTID must not change in transaction mode prior to commit\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(38, $stats, $expected); /* implicit commit */ if (!$link->autocommit(TRUE)) printf("[039] [%d] %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(40, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[041] GTID not incremented\n"); } $gtid = $new_gtid; $expected["gtid_implicit_commit_injections_success"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(42, $stats, $expected); $link->kill($link->thread_id); if (!($res = mst_mysqli_query(43, $link, "SELECT @myrorm Makefile; rm -rf autom4te.cache/ ; rm buildconf*; rm configure* ; rm ext/mysqlnd_uh/*.lo; rm ext/mysqlnd_ms/*.lo; svn up && ./buildconf --force && ./configure --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --enable-mysqlnd-ms --with-openssl --enable-pcntl --enable-debug && make clean && make -j4 le AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH))) { $expected['gtid_autocommit_injections_failure']++; } else { printf("[045] Who has run this query?!\n"); var_dump($res->fetch_assoc()); } $new_gtid = mst_mysqli_fetch_gtid(46, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[047] GTID incremented.\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(44, $stats, $expected); $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[045] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* we need an extra non-MS link for checking GTID. If we use MS link, the check itself will change GTID */ $emulated_master_link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (mysqli_connect_errno()) { printf("[046] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $stats = mysqlnd_ms_get_stats(); compare_stats(47, $stats, $expected); $link->autocommit(false); $gtid = mst_mysqli_fetch_gtid(48, $emulated_master_link, $db); mst_mysqli_query(49, $link, "SET @myrole = 'Master'"); $new_gtid = mst_mysqli_fetch_gtid(51, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[052] GTID should not have been incremented\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(53, $stats, $expected); $link->kill($link->thread_id); /* implicit commit */ if (!$link->autocommit(true)) printf("[054] [%d] %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(51, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[052] GTID should not have been incremented\n"); } $gtid = $new_gtid; $expected["gtid_implicit_commit_injections_failure"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(53, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- Hi there, this is your Master speaking Let me be your #1 [043] [%d] %s [054] [2006] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_basics.phpt0000664000175000017500000001327112161007456022023 0ustar andreyandrey--TEST-- Global Transaction ID Injection --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_basics.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_basics.ini --FILE-- autocommit(FALSE); /* run on master. Thus, must increment GTID - regardless if SELECT or not! */ $res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH); if (!$res) { printf("[010] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("Heho from '%s'\n", $row['_role']); $new_gtid = mst_mysqli_fetch_gtid(12, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[013] GTID has changed in non auto commit without commit\n"); } $gtid = $new_gtid; $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(14, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[016] GTID has been not been incremented after commit\n"); } $gtid = $new_gtid; /* we are in manual commit mode, increment on *every* commit */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(17, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[019] GTID has been not been incremented after commit\n"); } $gtid = $new_gtid; /* back to auto commit - implicit commit */ $link->autocommit(TRUE); $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(20, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[022] GTID not incremented\n"); } $gtid = $new_gtid; /* commit shall be ignored, it is not needed. We increment after every master statement */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(23, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[024] GTID increment\n"); } $gtid = $new_gtid; /* increment, tested above ...*/ $res = mst_mysqli_query(25, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH); if (!$res) { printf("[027] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("Heho from '%s'\n", $row['_role']); $gtid = mst_mysqli_fetch_gtid(28, $emulated_master_link, $db); /* commit shall be ignored, it is not needed. We increment after every master statement */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(29, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[030] commit() shall not change GTID in auto commit mode\n"); } $gtid = $new_gtid; print "done!"; ?> --CLEAN-- --EXPECTF-- Heho from 'Master' Heho from 'Master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_begin_mysqli_r.phpt0000664000175000017500000001373412161007456023566 0ustar andreyandrey--TEST-- PS, autocommit, GTID, stmt.store_result --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_begin_mysqli_r.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_begin_mysqli_r.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); /* we have to record START TRANSACTION as a new trx in our GTID table */ $link->begin_transaction(); $expected['gtid_autocommit_injections_success'] += 3; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare(sprintf("/*%s*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH)))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute() || !$stmt->store_result()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $link->commit(); $expected['gtid_commit_injections_success'] += 1; $stats = mysqlnd_ms_get_stats(); compare_stats(7, $stats, $expected); /* autocommit on master but no ps */ if (!$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[008] [%d] %s\n", $link->errno, $link->error); } $expected['gtid_autocommit_injections_success'] += 1; /* Note: transaction stickiness is not set! */ $link->begin_transaction(); $expected['gtid_autocommit_injections_success'] += 1; $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); if (!($res = $link->query(sprintf("/*%s*/SELECT MAX(id) AS _id FROM test", MYSQLND_MS_MASTER_SWITCH)))) { printf("[010] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); if (!$link->query("DELETE FROM test")) { printf("[011] [%d] %s\n", $link->errno, $link->error); } if (!($res = $link->query(sprintf("/*%s*/SELECT MAX(id) AS _id FROM test", MYSQLND_MS_MASTER_SWITCH)))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); /* does not matter whether rollback or commit, no trx stickiness anyway */ $link->rollback(); /* rollback does not change gtid table */ $expected['gtid_commit_injections_success'] += 0; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- id = 1 id = 0 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_begin_mysqli_rr_trx_stickiness_on.phpt0000664000175000017500000001724212161007456027576 0ustar andreyandrey--TEST-- PS, GTID, stmt.store_result, trx_stickiness=on,RR --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to tthe same, see tests/README"); } if ($emulated_master_host == $master_host) { die("SKIP emulated master and master seem to be the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on first master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die(sprintf("SKIP Failed to setup GTID on second master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host, $master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'report_error' => true, ), 'trx_stickiness' => 'on', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_begin_mysqli_rr_trx_stickiness_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_begin_mysqli_rr_trx_stickiness_on.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); /* master 0 */ if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query(sprintf("/*%s*/CREATE TABLE test(id INT) ENGINE=InnoDB", MYSQLND_MS_LAST_USED_SWITCH))) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* master 1 */ if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query(sprintf("/*%s*/CREATE TABLE test(id INT) ENGINE=InnoDB", MYSQLND_MS_LAST_USED_SWITCH))) printf("[003] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* If trx_stickiness is on this will be delayed... */ $link->begin_transaction(); /* triggers start transaction on master0 */ if (!($stmt = $link->prepare("SELECT COUNT(*) AS _num_rows FROM test"))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute() || !$stmt->store_result()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $link->commit(); $expected['gtid_commit_injections_success'] += 1; $stats = mysqlnd_ms_get_stats(); compare_stats(7, $stats, $expected); /* autocommit on master 1 but no ps */ if (!$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[008] [%d] %s\n", $link->errno, $link->error); } $expected['gtid_autocommit_injections_success'] += 1; /* Delayed START ... */ $link->begin_transaction(); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); /* master0 */ if (!($res = $link->query("SELECT MAX(id) AS _id FROM test"))) { printf("[010] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); /* master 0 */ if (!$link->query("DELETE FROM test")) { printf("[011] [%d] %s\n", $link->errno, $link->error); } /* master 0 */ if (!($res = $link->query("SELECT MAX(id) AS _id FROM test"))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); /* does not matter whether rollback or commit */ $link->rollback(); /* rollback does not change gtid table */ $expected['gtid_commit_injections_success'] += 0; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); /* master 1 */ $link->begin_transaction(); $link->begin_transaction(); /* one injection more than we need?! More does not harm much... */ $expected['gtid_implicit_commit_injections_success'] += 1; $expected['gtid_autocommit_injections_success'] += 1; if (!$link->query("INSERT INTO test(id) VALUES (2)")) { printf("[014] [%d] %s\n", $link->errno, $link->error); } $stats = mysqlnd_ms_get_stats(); compare_stats(15, $stats, $expected); if (!($res = $link->query("SELECT MAX(id) AS _id FROM test"))) { printf("[016] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); $link->commit(); $expected['gtid_autocommit_injections_success'] += 1; $stats = mysqlnd_ms_get_stats(); compare_stats(17, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- id = 0 id = 0 id = 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_begin_mysqli_r_trx_stickiness_on.phpt0000664000175000017500000001477412161007456027423 0ustar andreyandrey--TEST-- PS, autocommit, GTID, stmt.store_result, trx_stickiness=on --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "random" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'report_error' => true, ), 'trx_stickiness' => 'on', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_begin_mysqli_r_trx_stickiness_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_begin_mysqli_r_trx_stickiness_on.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* If trx_stickiness is on this will be delayed... */ $link->begin_transaction(); /* triggers start transaction on master */ if (!($stmt = $link->prepare("SELECT COUNT(*) AS _num_rows FROM test"))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute() || !$stmt->store_result()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $link->commit(); $expected['gtid_commit_injections_success'] += 1; $stats = mysqlnd_ms_get_stats(); compare_stats(7, $stats, $expected); /* autocommit on master but no ps */ if (!$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[008] [%d] %s\n", $link->errno, $link->error); } $expected['gtid_autocommit_injections_success'] += 1; /* Delayed START ... */ $link->begin_transaction(); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); /* master */ if (!($res = $link->query("SELECT MAX(id) AS _id FROM test"))) { printf("[010] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); if (!$link->query("DELETE FROM test")) { printf("[011] [%d] %s\n", $link->errno, $link->error); } if (!($res = $link->query("SELECT MAX(id) AS _id FROM test"))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); /* does not matter whether rollback or commit, no trx stickiness anyway */ $link->rollback(); /* rollback does not change gtid table */ $expected['gtid_commit_injections_success'] += 0; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); /* double begin, second begin will give implicit commit */ $link->begin_transaction(); if (!$link->query("INSERT INTO test(id) VALUES (1)")) { printf("[014] [%d] %s\n", $link->errno, $link->error); } $expected['gtid_implicit_commit_injections_success'] += 1; $link->begin_transaction(); if (!($res = $link->query("SELECT MAX(id) AS _id FROM test"))) { printf("[015] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("id = %d\n", $row['_id']); $link->commit(); $expected['gtid_commit_injections_success'] += 1; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- id = 1 id = 0 id = 1 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_commit_stats.phpt0000664000175000017500000002140512161007456023263 0ustar andreyandrey--TEST-- GTID commit mode stats --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], ), 'lazy_connections' => 0, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_commit_stats.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_commit_stats.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* we need an extra non-MS link for checking GTID. If we use MS link, the check itself will change GTID */ $emulated_master_link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (mysqli_connect_errno()) { printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ $gtid = mst_mysqli_fetch_gtid(5, $emulated_master_link, $db); if (mst_mysqli_query(6, $link, "SET @myrole = 'Master'")) $expected['gtid_autocommit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(8, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[009] GTID has been incremented on master in prior to commit\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(10, $stats, $expected); /* auto commit off for the real stuff... */ $link->autocommit(FALSE); /* master statement but it must not increment */ if (!($res = mst_mysqli_query(11, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH))) printf("[013] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(14, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[015] GTID has been incremented on master without commit after master query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); $row = $res->fetch_assoc(); printf("I am the %s of ", $row['_role']); /* slave statement */ if (!($res = mst_mysqli_query(17, $link, "SET @myrole = 'Slave'", MYSQLND_MS_SLAVE_SWITCH))) printf("[019] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(20, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[021] GTID has been incremented on master without commit after slave query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(22, $stats, $expected); if (!($res = mst_mysqli_query(23, $link, "SELECT @myrole AS _role FROM DUAL"))) printf("[025] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(26, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[027] GTID has been incremented on master without commit after slaver query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(28, $stats, $expected); $row = $res->fetch_assoc(); printf("poor me, the %s.\n", $row['_role']); /* do NOT increment - commit goes to the slave! trx stickiness is off! */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(27, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[028] GTID has been incremented on master after commit on slave\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(29, $stats, $expected); /* master statement but it must not increment */ if (!($res = mst_mysqli_query(30, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH))) printf("[032] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(33, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[034] GTID has been incremented on master without commit after master query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(35, $stats, $expected); /* must increment - last used is master, commit goes to master ! */ if ($link->commit()) $expected['gtid_commit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(36, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[038] GTID has not been incremented on master after commit on master\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(40, $stats, $expected); /* must increment - last used is master, commit goes to master ! */ if ($link->commit()) $expected['gtid_commit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(41, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[042] GTID has not been incremented on master after commit on master\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(43, $stats, $expected); /* implicit commit */ $link->autocommit(true); $new_gtid = mst_mysqli_fetch_gtid(44, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[045] GTID not incremented\n"); } $gtid = $new_gtid; $expected["gtid_implicit_commit_injections_success"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(46, $stats, $expected); $link->commit(); $link->autocommit(false); $new_gtid = mst_mysqli_fetch_gtid(47, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[048] GTID incremented\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(49, $stats, $expected); /* failure */ $link->kill($link->thread_id); $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(50, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[051] GTID has must not change because commit was done on dead connection\n"); } $stats = mysqlnd_ms_get_stats(); $expected["gtid_commit_injections_failure"]++; compare_stats(52, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- I am the Master of poor me, the Slave. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_commit_stats_ps.phpt0000664000175000017500000002262112161007456023766 0ustar andreyandrey--TEST-- PS, GTID commit mode stats --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], ), 'lazy_connections' => 0, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_commit_stats_ps.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_commit_stats_ps.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } function mst_mysqli_stmt($offset, $link, $sql, $switch = NULL) { $query = sprintf("/*%d*/%s", $offset, $sql); if ($switch) $query = sprintf("/*%s*/%s", $switch, $query); if (!($stmt = $link->prepare($query))) { printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); return NULL; } if (!$stmt->execute()) { printf("[%03d] [%d] %s\n", $offset, $stmt->errno, $stmt->error); return NULL; } return $stmt; } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* we need an extra non-MS link for checking GTID. If we use MS link, the check itself will change GTID */ $emulated_master_link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (mysqli_connect_errno()) { printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ $gtid = mst_mysqli_fetch_gtid(5, $emulated_master_link, $db); if (mst_mysqli_stmt(6, $link, "SET @myrole = 'Master'")) $expected['gtid_autocommit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(8, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[009] GTID has been incremented on master in prior to commit\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(10, $stats, $expected); /* auto commit off for the real stuff... */ $link->autocommit(false); /* master statement but it must not increment */ $stmt = mst_mysqli_stmt(11, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH); if (!($res = $stmt->get_result())) printf("[013] %d %s\n", $stmt->errno, $stmt->error); $new_gtid = mst_mysqli_fetch_gtid(14, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[015] GTID has been incremented on master without commit after master query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); $row = $res->fetch_assoc(); printf("I am the %s of ", $row['_role']); /* slave statement */ $stmt = mst_mysqli_stmt(17, $link, "SET @myrole = 'Slave'", MYSQLND_MS_SLAVE_SWITCH); $new_gtid = mst_mysqli_fetch_gtid(20, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[021] GTID has been incremented on master without commit after slave query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(22, $stats, $expected); $stmt = mst_mysqli_stmt(23, $link, "SELECT @myrole AS _role FROM DUAL"); if (!($res = $stmt->get_result())) printf("[025] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(26, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[027] GTID has been incremented on master without commit after slaver query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(28, $stats, $expected); $row = $res->fetch_assoc(); printf("poor me, the %s.\n", $row['_role']); /* do NOT increment - commit goes to the slave! trx stickiness is off! */ $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(27, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[028] GTID has been incremented on master after commit on slave\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(29, $stats, $expected); /* master statement but it must not increment */ $stmt = mst_mysqli_stmt(30, $link, "SELECT @myrole AS _role FROM DUAL", MYSQLND_MS_MASTER_SWITCH); if (!($res = $stmt->get_result())) printf("[032] %d %s\n", $link->errno, $link->error); $new_gtid = mst_mysqli_fetch_gtid(33, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[034] GTID has been incremented on master without commit after master query\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(35, $stats, $expected); /* must increment - last used is master, commit goes to master ! */ if ($link->commit()) $expected['gtid_commit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(36, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[038] GTID has not been incremented on master after commit on master\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(40, $stats, $expected); /* must increment - last used is master, commit goes to master ! */ if ($link->commit()) $expected['gtid_commit_injections_success']++; $new_gtid = mst_mysqli_fetch_gtid(41, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[042] GTID has not been incremented on master after commit on master\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(43, $stats, $expected); /* implicit commit */ $link->autocommit(true); $new_gtid = mst_mysqli_fetch_gtid(44, $emulated_master_link, $db); if ($new_gtid <= $gtid) { printf("[045] GTID not incremented\n"); } $gtid = $new_gtid; $expected["gtid_implicit_commit_injections_success"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(46, $stats, $expected); $link->commit(); $stats = mysqlnd_ms_get_stats(); compare_stats(47, $stats, $expected); $link->autocommit(false); $stats = mysqlnd_ms_get_stats(); compare_stats(48, $stats, $expected); $new_gtid = mst_mysqli_fetch_gtid(49, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[050] GTID incremented $new_gtid $gtid\n"); } $gtid = $new_gtid; $stats = mysqlnd_ms_get_stats(); compare_stats(51, $stats, $expected); /* failure */ $link->kill($link->thread_id); $link->commit(); $new_gtid = mst_mysqli_fetch_gtid(52, $emulated_master_link, $db); if ($new_gtid != $gtid) { printf("[053] GTID has must not change because commit was done on dead connection\n"); } $stats = mysqlnd_ms_get_stats(); $expected["gtid_commit_injections_failure"]++; compare_stats(54, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- I am the Master of poor me, the Slave. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_implicit_commit_autocommit.phpt0000664000175000017500000001121712161007456026200 0ustar andreyandrey--TEST-- GTID and autocommit off/on implicit commit --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to drop GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_implicit_commit_autocommit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_implicit_commit_autocommit.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, "gtid_implicit_commit_injections_success" => 0, "gtid_implicit_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ /* 3x master, success */ if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[005] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 3; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); /* NOOP */ if (!$link->autocommit(true)) printf("[007] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(8, $stats, $expected); /* NOOP */ if (!$link->autocommit(false)) printf("[009] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(10, $stats, $expected); /* master, no connection switch */ if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[011] [%d] %s\n", $link->errno, $link->error); /* Attention: implicit commit! */ if (!$link->autocommit(true)) printf("[012] [%d] %s\n", $link->errno, $link->error); $expected['gtid_implicit_commit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); /* Proof of implicit commit */ $res = mst_mysqli_query(14, $link, "SELECT COUNT(*) AS _num FROM test", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num']); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_invalid_check_for_gtid.phpt0000664000175000017500000000512612161007456025217 0ustar andreyandrey--TEST-- GTID, config, invalid check_for_gtid --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'check_for_gtid' => array($sql['update']), ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_invalid_check_for_gtid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_invalid_check_for_gtid.ini --FILE-- --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) 'check_for_gtid' from 'global_transaction_id_injection' must be a string in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_invalid_fetch_last_gtid.phpt0000664000175000017500000000513512161007456025410 0ustar andreyandrey--TEST-- GTID, config, invalid fetch_last_gtid --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'fetch_last_gtid' => array($sql['update']), ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_invalid_fetch_last_gtid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_invalid_fetch_last_gtid.ini --FILE-- --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) 'fetch_last_gtid' from 'global_transaction_id_injection' must be a string in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_invalid_on_commit.phpt0000664000175000017500000000507012161007456024247 0ustar andreyandrey--TEST-- GTID, config, invalid on_commit --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => array($sql['update']), ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_invalid_on_commit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_invalid_on_commit.ini --FILE-- --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) 'on_commit' from 'global_transaction_id_injection' must be a string in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_get_result_mq.phpt0000664000175000017500000001332712161007456026376 0ustar andreyandrey--TEST-- PS, autocommit, GTID, stmt.get_result, mq --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_get_result_mq.ini", $settings)) die(sprintf("SKIP %s\n", $error)); if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) die(sprintf("SKIP Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query("DROP PROCEDURE IF EXISTS p") || !$link->query("CREATE PROCEDURE p(IN ver_in VARCHAR(25)) BEGIN SELECT ver_in AS _ver_out; END;") || !$link->prepare("CALL p(?)")) { unlink("test_mysqlnd_ms_gtid_ps_autocommit_get_result_mq.ini"); die(sprintf("SKIP Not supported, [%d] %s\n", $link->errno, $link->error)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_get_result_mq.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP PROCEDURE IF EXISTS p") || !$link->query("CREATE PROCEDURE p(IN ver_in VARCHAR(25)) BEGIN SELECT ver_in AS _ver_out; SELECT 1; END;")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $expected); if (!($stmt = $link->prepare("CALL p(?)"))) printf("[004] [%d] %s\n", $link->errno, $link->error); $version = '12.3'; if (!$stmt->bind_param('s', $version)) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); if (!$stmt->execute()) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(8, $stats, $expected); do { if ($res = $stmt->get_result()) var_dump($res->fetch_assoc()); } while ($stmt->more_results() && $stmt->next_result()); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); /* check if line is useable */ if (!($res = $link->query(sprintf("/*%s*/SELECT 'Is the line' AS _msg FROM DUAL", MYSQLND_MS_MASTER_SWITCH)))) printf("[010] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(11, $stats, $expected); $row = $res->fetch_assoc(); printf("%s\n", $row['_msg']); /* just for fun */ if (!$link->commit()) printf("[012] [%d] %s\n", $link->errno, $link->error); if (!$stmt->bind_param('s', $version) || !$stmt->execute()) printf("[013] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(14, $stats, $expected); do { if ($res = $stmt->get_result()) var_dump($res->fetch_assoc()); } while ($stmt->more_results() && $stmt->next_result()); $stats = mysqlnd_ms_get_stats(); compare_stats(15, $stats, $expected); /* slave, no increment */ if (!($res = $link->query("SELECT 'still useable?' AS _msg FROM DUAL"))) printf("[016] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(17, $stats, $expected); $row = $res->fetch_assoc(); printf("%s\n", $row['_msg']); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { ["_ver_out"]=> string(4) "12.3" } array(1) { [1]=> int(1) } Is the line array(1) { ["_ver_out"]=> string(4) "12.3" } array(1) { [1]=> int(1) } still useable? done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_get_result.phpt0000664000175000017500000001465112161007456025702 0ustar andreyandrey--TEST-- PS, autocommit, GTID, stmt.get_result --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_get_result.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_get_result.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare(sprintf("/*%s*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH)))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); if (!($res = $stmt->get_result())) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[008] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); if (!$stmt->execute()) printf("[010%A [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(11, $stats, $expected); if (!($res = $stmt->get_result())) printf("[012] [%d] %s\n", $stmt->errno, $stmt->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); if (!($res = $stmt->get_result())) { printf("[013] [%d] %s\n", $stmt->errno, $stmt->error); printf("[014] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); } if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[015] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); if (!$stmt->execute()) printf("[017] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(18, $stats, $expected); if (!($res = $stmt->get_result())) printf("[019] [%d] %s\n", $stmt->errno, $stmt->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); if (!$stmt->execute()) printf("[020%A [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(21, $stats, $expected); /* commands out of sync */ if (!$stmt->execute()) { printf("[022] [%d] %s\n", $stmt->errno, $stmt->error); printf("[023] [%d] %s\n", $link->errno, $link->error); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(24, $stats, $expected); if (!($res = $stmt->get_result())) printf("[025] [%d] %s\n", $stmt->errno, $stmt->error); if (!$link->query("DROP TABLE IF EXISTS test")) printf("[026] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(27, $stats, $expected); if (!$stmt->execute()) printf("[028] [%d] %s\n", $stmt->errno, $stmt->error); /* we do the injection before execute! */ $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(29, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 0 Rows 1 [013] [0%A [014] [2014] %s Rows 2 [022] [2014] %s [023] [2014] %s [028] [1146] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_no_result.phpt0000664000175000017500000001073612161007456025537 0ustar andreyandrey--TEST-- PS, autocommit, GTID --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_no_result.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_no_result.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare("INSERT INTO test(id) VALUES (1)"))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); if (!($res = $link->query(sprintf("/*%s*//*%d*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH, 7)))) printf("[008] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); if (!$link->query("DROP TABLE IF EXISTS test")) printf("[010] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(11, $stats, $expected); if (!$stmt->execute()) printf("[012] [%d] %s\n", $stmt->errno, $stmt->error); /* We do the injection before execute */ $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 1 [012] [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_report_error_off.phpt0000664000175000017500000001742612161007456027106 0ustar andreyandrey--TEST-- PS, autocommit, GTID, error --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => false, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_report_error_off.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_report_error_off.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare(sprintf("/*%s*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH)))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[008] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); while ($stmt->fetch()) printf("[009] Clean line...\n"); if ($err = mst_mysqli_drop_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[010] %s\n", $err); if (!$stmt->execute()) { printf("[011] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[012] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); if (!($res = $stmt->get_result())) printf("[014] [%d] %s\n", $stmt->errno, $stmt->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[015] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); /* execute shall be done although injection gives error */ if (!$stmt->execute()) { printf("[017] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[018] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(19, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[020] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[021] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); while ($stmt->fetch()); ; if (!$link->query("DROP TABLE IF EXISTS test")) printf("[023] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_failure']++; if (!$stmt->execute()) { printf("[024] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[025] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(26, $stats, $expected); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[027] %s\n", $error); if (!$stmt->execute()) { printf("[028] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[029] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(30, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[031] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[033] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); if (!$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[034] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(35, $stats, $expected); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[036] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(37, $stats, $expected); if (!$stmt->execute()) { printf("[038] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[039] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(40, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[041] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[042] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 0 Rows 0 Rows 1 [024] [1146/42S02] %s [025] [1146/42S02] %s [028] [1146/42S02] %s [029] [1146/42S02] %s [033] [2014] %s Rows 0 Rows 1 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_report_error.phpt0000664000175000017500000001522412161007456026246 0ustar andreyandrey--TEST-- PS, autocommit, GTID, error --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_report_error.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_report_error.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare(sprintf("/*%s*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH)))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[008] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); while ($stmt->fetch()) printf("[009] Clean line...\n"); if ($err = mst_mysqli_drop_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[010] %s\n", $err); if (!$stmt->execute()) { printf("[011] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[012] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } else { printf("[013] Expecting error from execute!\n"); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(14, $stats, $expected); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[015] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); if (!$stmt->execute()) { printf("[017] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[018] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } else { printf("[019] Expecting error from execute!\n"); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(20, $stats, $expected); if (!($res = $stmt->get_result())) { printf("[021] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[022] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } else { $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); } if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[023] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(24, $stats, $expected); if (!$stmt->execute()) { printf("[025] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[026] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } else { printf("[027] Expecting error from execute!\n"); } $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(28, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) { printf("[029] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[030] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } if (!($res = $stmt->store_result())) { printf("[031] [%d/%s] %s\n", $stmt->errno, $stmt->sqlstate, $stmt->error); printf("[032] [%d/%s] %s\n", $link->errno, $link->sqlstate, $link->error); } else { printf("Rows %d\n", $num_rows); } print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 0 [011] [1146/42S02] %s [012] [1146/42S02] %s [015] [1146] %s [017] [1146/42S02] %s [018] [1146/42S02] %s [021] [1146/42S02] %s [022] [2014/HY000] %s [023] [1146] %s [025] [1146/42S02] %s [026] [1146/42S02] %s [031] [0/00000%A [032] [2014/HY000] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_store_result.phpt0000664000175000017500000001536612161007456026263 0ustar andreyandrey--TEST-- PS, autocommit, GTID, stmt.store_result --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_store_result.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_store_result.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare(sprintf("/*%s*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH)))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->store_result())) printf("[008] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[009] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[010] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(11, $stats, $expected); if (!$stmt->execute()) printf("[012] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); if (!($res = $stmt->store_result())) printf("[014] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[015] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); if (!$stmt->store_result()) { printf("[016] [%d] %s\n", $stmt->errno, $stmt->error); printf("[017] [%d] %s\n", $link->errno, $link->error); } else { if (!($res = $stmt->fetch())) printf("[018] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); } if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[019] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(20, $stats, $expected); if (!$stmt->execute()) printf("[021] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(22, $stats, $expected); if (!($res = $stmt->store_result())) printf("[023] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[024] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); if (!$stmt->execute()) printf("[025] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(26, $stats, $expected); if (!$stmt->execute()) { printf("[027] [%d] %s\n", $stmt->errno, $stmt->error); printf("[028] [%d] %s\n", $link->errno, $link->error); } /* commands out of sync */ $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(29, $stats, $expected); if (!($res = $stmt->store_result())) printf("[030] [%d] %s\n", $stmt->errno, $stmt->error); if (!$link->query("DROP TABLE IF EXISTS test")) printf("[031] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(32, $stats, $expected); if (!$stmt->execute()) printf("[033] [%d] %s\n", $stmt->errno, $stmt->error); /* injection is done before execute */ $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(34, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 0 Rows 1 [016] [0%A [017] [2014] %s Rows 2 [027] [2014] %s [028] [2014] %s [033] [1146] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_autocommit_use_result.phpt0000664000175000017500000001344612161007456025720 0ustar andreyandrey--TEST-- PS, autocommit, GTID, stmt.use_result --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'filters' => array( "roundrobin" => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_autocommit_use_result.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_autocommit_use_result.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success'] += 2; /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare(sprintf("/*%s*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH)))) printf("[003] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); if (!$stmt->execute()) printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(6, $stats, $expected); $num_rows = NULL; if (!$stmt->bind_result($num_rows)) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $stmt->fetch())) printf("[008] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); while ($stmt->fetch()) printf("[009] Clean line...\n"); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[010] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(11, $stats, $expected); if (!$stmt->execute()) printf("[012] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(13, $stats, $expected); if (!($res = $stmt->fetch())) printf("[014] [%d] %s\n", $stmt->errno, $stmt->error); printf("Rows %d\n", $num_rows); while ($stmt->fetch()) printf("[015] Clean line...\n"); if (!$link->query("INSERT INTO test(id) VALUES (1)")) printf("[016] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(17, $stats, $expected); if (!$stmt->execute()) printf("[018] [%d] %s\n", $stmt->errno, $stmt->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(19, $stats, $expected); if (!$stmt->execute()) printf("[020] [%d] %s\n", $stmt->errno, $stmt->error); /* commands out of sync, injection prior execute failed */ $expected['gtid_autocommit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(21, $stats, $expected); while ($stmt->fetch()) printf("[022] Clean line...\n"); printf("Rows %d\n", $num_rows); if (!$link->query("DROP TABLE IF EXISTS test")) printf("[023] [%d] %s\n", $link->errno, $link->error); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(24, $stats, $expected); if (!$stmt->execute()) printf("[025] [%d] %s\n", $stmt->errno, $stmt->error); /* injection is done before execute */ $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(25, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 0 Rows 1 [020] [2014] %s [022] Clean line... Rows 2 [025] [1146] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_ps_report_errors_on.phpt0000664000175000017500000001022312161007456024656 0ustar andreyandrey--TEST-- GTID, PS and error on stmt --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_ps_report_errors_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_ps_report_errors_on.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* master, autocommit */ if (!($stmt = $link->prepare("DROP TABLE IF EXISTS test"))) printf("[005] [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) { printf("[006] [%d] %s\n", $stmt->errno, $stmt->error); printf("[007] [%d] %s\n", $link->errno, $link->error); } $expected["gtid_autocommit_injections_success"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(8, $stats, $expected); /* provoke error */ if ($error = mst_mysqli_drop_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[009] %s\n", $error); if (!$stmt->execute()) { printf("[010] [%d] %s\n", $stmt->errno, $stmt->error); printf("[011] [%d] %s\n", $link->errno, $link->error); } $expected["gtid_autocommit_injections_failure"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(12, $stats, $expected); /* ... and here comes the trx table back to life */ if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[013] %s\n", $error); if (!$stmt->execute()) { printf("[014] [%d] %s\n", $stmt->errno, $stmt->error); printf("[015] [%d] %s\n", $link->errno, $link->error); } $expected["gtid_autocommit_injections_success"]++; $stats = mysqlnd_ms_get_stats(); compare_stats(16, $stats, $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- [010] [1146] %s [011] [1146] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_report_errors_off_non_lazy.phpt0000664000175000017500000001301412161007456026224 0ustar andreyandrey--TEST-- GTID and report errors off --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); $link = mst_mysqli_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); if (mysqli_connect_errno()) die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query($sql['drop'])) die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error)); $link = mst_mysqli_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if (mysqli_connect_errno()) die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query($sql['drop'])) die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => false, ), 'lazy_connections' => 0, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_report_errors_off_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_report_errors_off_non_lazy.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ mst_mysqli_query(5, $link, "SET @myrole='master'"); $expected['gtid_autocommit_injections_failure']++; mst_mysqli_query(7, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); $link->autocommit(false); /* SET should have not been executed */ if (!$res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role")) printf("[012] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[013] Slave says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(14, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)) printf("[016] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[017] Master says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(18, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)) printf("[020] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[021] Master says again '%s'\n", $row['_role']); mst_mysqli_query(22, $link, "SET @myrole='master'"); if (!$link->commit()) printf("[025] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; $res = mst_mysqli_query(26, $link, "SELECT 1 AS _one FROM DUAL"); $row = $res->fetch_assoc(); printf("Slave says '%d'\n", $row['_one']); if (!$link->commit()) printf("[029] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(30, $link, "SELECT 2 AS _two FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("Master says '%d'\n", $row['_two']); if (!$link->commit()) printf("[033] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(34, $stats, $expected); $link->autocommit(true); /* Note: we inject before the original query, thus we see the inection error */ mst_mysqli_query(36, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(38, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); $link->autocommit(false); mst_mysqli_query(40, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(42, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); print "done!"; ?> --CLEAN-- --EXPECTF-- [013] Slave says 'slave' [017] Master says 'master' [021] Master says again 'master' Slave says '1' Master says '2' [036] [1193] Unknown system variable 'MY' [038] [1193] Unknown system variable 'MY' [040] [1193] Unknown system variable 'MY' [042] [1193] Unknown system variable 'MY' done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_report_errors_off.phpt0000664000175000017500000001412012161007456024312 0ustar andreyandrey--TEST-- GTID and report errors off --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_drop_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to drop GTID on master, %s\n", $error)); if ($error = mst_mysqli_drop_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to drop GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => false, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_report_errors_off.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_report_errors_off.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ mst_mysqli_query(5, $link, "SET @myrole='master'"); $expected['gtid_autocommit_injections_failure']++; mst_mysqli_query(7, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); $link->autocommit(false); /* SET should have not been executed */ if (!$res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role")) printf("[012] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[013] Slave says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(14, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)) printf("[016] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[017] Master says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(18, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)) printf("[020] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[021] Master says again '%s'\n", $row['_role']); mst_mysqli_query(22, $link, "SET @myrole='master'"); if (!$link->commit()) printf("[025] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; $res = mst_mysqli_query(26, $link, "SELECT 1 AS _one FROM DUAL"); $row = $res->fetch_assoc(); printf("Slave says '%d'\n", $row['_one']); if (!$link->commit()) printf("[029] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(30, $link, "SELECT 2 AS _two FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("Master says '%d'\n", $row['_two']); if (!$link->commit()) printf("[033] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(34, $stats, $expected); $link->autocommit(true); /* Note: we inject before the original query, thus we see the inection error */ mst_mysqli_query(36, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(38, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); $expected['gtid_autocommit_injections_failure'] += 2; $stats = mysqlnd_ms_get_stats(); compare_stats(40, $stats, $expected); $link->autocommit(false); mst_mysqli_query(42, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(44, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); /* commit on master connection only */ $link->commit(); $stats = mysqlnd_ms_get_stats(); $expected['gtid_commit_injections_failure']++; compare_stats(46, $stats, $expected); printf("[047] [%d] %s\n", $link->errno, $link->error); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[048] %s\n", $error); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[049] [%d] %s\n", $link->errno, $link->error); $link->autocommit(true); print "done!"; ?> --CLEAN-- --EXPECTF-- [013] Slave says 'slave' [017] Master says 'master' [021] Master says again 'master' Slave says '1' Master says '2' [036] [1193] %s [038] [1193] %s [042] [1193] %s [044] [1193] %s [047] [0%A done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_report_errors_on_non_lazy.phpt0000664000175000017500000001412212161007456026067 0ustar andreyandrey--TEST-- GTID and report errors on --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (mysqli_connect_errno()) die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query($sql['drop'])) die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error)); $link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (mysqli_connect_errno()) die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query($sql['drop'])) die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'lazy_connections' => 0, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_report_errors_on_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_report_errors_on_non_lazy.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ mst_mysqli_query(5, $link, "SET @myrole='master'"); $expected['gtid_autocommit_injections_failure']++; mst_mysqli_query(7, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); $link->autocommit(false); /* SET should have not been executed */ if (!$res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role")) printf("[012] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[013] Slave says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(14, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)) printf("[016] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[017] Master says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(18, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)) printf("[020] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[021] Master says again '%s'\n", $row['_role']); mst_mysqli_query(22, $link, "SET @myrole='master'"); if (!$link->commit()) printf("[025] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; $res = mst_mysqli_query(26, $link, "SELECT 1 AS _one FROM DUAL"); $row = $res->fetch_assoc(); printf("Slave says '%d'\n", $row['_one']); if (!$link->commit()) printf("[029] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(30, $link, "SELECT 2 AS _two FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("Master says '%d'\n", $row['_two']); if ($link->commit()) printf("[032] Commit should have failed\n"); else printf("[033] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; $stats = mysqlnd_ms_get_stats(); compare_stats(34, $stats, $expected); $link->autocommit(true); /* Note: we inject before the original query, thus we see the inection error */ mst_mysqli_query(36, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(38, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); $link->autocommit(false); mst_mysqli_query(40, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(42, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); print "done!"; ?> --CLEAN-- --EXPECTF-- [005] [1146] %s [013] Slave says 'slave' [017] Master says '' [021] Master says again '' [025] [1146] %s Slave says '1' Master says '2' [033] [1146] %s [036] [1193] %s [038] [1193] %s [040] [1193] %s [042] [1193] %s done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_report_errors_on.phpt0000664000175000017500000001667212161007456024172 0ustar andreyandrey--TEST-- GTID and report errors on --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (mysqli_connect_errno()) die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query($sql['drop'])) die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error)); $link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (mysqli_connect_errno()) die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error())); if (!$link->query($sql['drop'])) die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'report_error' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_report_errors_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_report_errors_on.ini mysqlnd_ms.collect_statistics=1 --FILE-- $value) { if (isset($expected[$name])) { if ($value != $expected[$name]) { printf("[%03d] Expecting %s = %d got %d\n", $offset, $name, $expected[$name], $value); } unset($expected[$name]); } } if (!empty($expected)) { printf("[%03d] Dumping list of missing stats\n", $offset); var_dump($expected); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $expected = array( "gtid_autocommit_injections_success" => 0, "gtid_autocommit_injections_failure" => 0, "gtid_commit_injections_success" => 0, "gtid_commit_injections_failure" => 0, ); $stats = mysqlnd_ms_get_stats(); compare_stats(4, $stats, $expected); /* auto commit on (default) */ mst_mysqli_query(5, $link, "SET @myrole='master'"); $expected['gtid_autocommit_injections_failure']++; mst_mysqli_query(7, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $stats = mysqlnd_ms_get_stats(); compare_stats(9, $stats, $expected); $link->autocommit(false); /* SET should have not been executed */ if (!$res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role")) printf("[012] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[013] Slave says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(14, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)) printf("[016] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[017] Master says '%s'\n", $row['_role']); if (!$res = mst_mysqli_query(18, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)) printf("[020] %d %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[021] Master says again '%s'\n", $row['_role']); mst_mysqli_query(22, $link, "SET @myrole='master'"); if (!$link->commit()) printf("[024] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; /* we continue to run in transaction mode! */ $res = mst_mysqli_query(26, $link, "SELECT 1 AS _one FROM DUAL"); $row = $res->fetch_assoc(); printf("Slave says '%d'\n", $row['_one']); if (!$link->commit()) printf("[029] [%d] %s\n", $link->errno, $link->error); $expected['gtid_commit_injections_failure']++; /* we continue to run in transaction mode! */ $res = mst_mysqli_query(30, $link, "SELECT 2 AS _two FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("Master says '%d'\n", $row['_two']); if (!$link->commit()) printf("[033] [%d] %s\n", $link->errno, $link->error); $stats = mysqlnd_ms_get_stats(); compare_stats(34, $stats, $expected); if (!$link->autocommit(true)) { printf("[035] [%d] %s\n", $link->errno, $link->error); /* NOTE: the user MUST do rollback to prevent deadlock */ $link->rollback(); } /* autocommit failed, still in transaction mode */ /* Note: we inject before the original query, thus we see the inection error */ if (!$link->query("SET MY LIFE ON FIRE")) { printf("[036] %d %s\n", $link->errno, $link->error); } var_dump(mst_mysqli_query(38, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH)); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[040] %s\n", $error); if (!$link->autocommit(true)) { printf("[041] [%d] %s\n", $link->errno, $link->error); /* NOTE: the user MUST do rollback to prevent deadlock */ $link->rollback(); } /* autocommit success */ mst_mysqli_query(42, $link, "SET MY LIFE ON FIRE"); $expected['gtid_autocommit_injections_success']++; mst_mysqli_query(44, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); $expected['gtid_autocommit_injections_success']++; $stats = mysqlnd_ms_get_stats(); compare_stats(45, $stats, $expected); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) printf("[046] %s\n", $error); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) printf("[047] %s\n", $error); $link->autocommit(false); mst_mysqli_query(48, $link, "SET MY LIFE ON FIRE"); mst_mysqli_query(50, $link, "SET MY LIFE ON FIRE", MYSQLND_MS_MASTER_SWITCH); print "done!"; ?> --CLEAN-- --EXPECTF-- [005] [1146] %s [013] Slave says 'slave' [017] Master says '' [021] Master says again '' [024] [1146] %s Slave says '1' Master says '2' [033] [1146] %s [035] [1146] %s [036] 1193 %s [038] [1193] %s bool(false) [042] [1193] %s [044] [1193] %s [048] [1193] %s [050] [1193] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_serverside_basics.phpt0000664000175000017500000000762012161007456024257 0ustar andreyandrey--TEST-- Server GTID --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $ret = mst_mysqli_server_supports_gtid($master_host_only, $user, $passwd, $db, $master_port, $master_socket); if (is_string($ret)) die(sprintf("SKIP Failed to check if server has built-in GTID support, %s\n", $ret)); if (true != $ret) die(sprintf("SKIP Server has no built-in GTID support")); $ret = mst_is_slave_of($slave_host_only, $slave_port, $slave_socket, $master_host_only, $master_port, $master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true != $ret) die("SKIP Configured master and slave seem not to be part of a replication cluster\n"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'global_transaction_id_injection' => array( 'select' => "SELECT @@GLOBAL.GTID_DONE", "fetch_last_gtid" => "SELECT @@GLOBAL.GTID_DONE AS trx_id FROM DUAL", "check_for_gtid" => "SELECT GTID_SUBSET('#GTID', @@GLOBAL.GTID_DONE) AS trx_id FROM DUAL", 'report_errors' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_serverside_basics.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_serverside_basics.ini --FILE-- errno, $link->error); } /* Either run on master or a slave which has replicated the INSERT */ $res = mst_mysqli_query(10, $link, "SELECT 1 AS id, @myrole AS _role FROM DUAL"); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- GTID from MySQL '%s' array(2) { ["id"]=> string(1) "1" ["_role"]=> string(5) "%s" } done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_serverside_stats.phpt0000664000175000017500000001035712161007456024152 0ustar andreyandrey--TEST-- Server GTID and emulation stats --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $ret = mst_mysqli_server_supports_gtid($master_host_only, $user, $passwd, $db, $master_port, $master_socket); if (is_string($ret)) die(sprintf("SKIP Failed to check if server has built-in GTID support, %s\n", $ret)); if (true != $ret) die(sprintf("SKIP Server has no built-in GTID support")); $ret = mst_is_slave_of($slave_host_only, $slave_port, $slave_socket, $master_host_only, $master_port, $master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true != $ret) die("SKIP Configured master and slave seem not to be part of a replication cluster\n"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'global_transaction_id_injection' => array( 'select' => "SELECT @@GLOBAL.GTID_DONE", "fetch_last_gtid" => "SELECT @@GLOBAL.GTID_DONE AS trx_id FROM DUAL", "check_for_gtid" => "SELECT GTID_SUBSET('#GTID', @@GLOBAL.GTID_DONE) AS trx_id FROM DUAL", 'report_errors' => true, ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_serverside_stats.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_serverside_stats.ini mysqlnd_ms.collect_statistics=1 --FILE-- errno, $link->error); } /* Either run on master or a slave which has replicated the INSERT */ $res = mst_mysqli_query(10, $link, "SELECT 1 AS id, @myrole AS _role FROM DUAL"); var_dump($res->fetch_assoc()); $stats_after = mysqlnd_ms_get_stats(); foreach ($stats_after as $k => $v) { if ((substr($k, 0, 4) == "gtid") && ($v != $stats_before[$k])) { printf("[011] GTID emulation stat '%s' has changed from '%s' to '%s'\n", $k, $stats_before[$k], $v); } } print "done!"; ?> --CLEAN-- --EXPECTF-- GTID from MySQL '%s' array(2) { ["id"]=> string(1) "1" ["_role"]=> string(5) "%s" } done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_gtid_tx_non_ms.phpt0000664000175000017500000000632512161007456022565 0ustar andreyandrey--TEST-- GTID - transactions in non MS connections --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], ), 'lazy_connections' => 1, 'trx_stickiness' => 'disabled', 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_gtid_tx_non_ms.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_gtid_tx_non_ms.ini --FILE-- fetch_assoc(); return $row['auto_commit']; } $link = mst_mysqli_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* make sure we run through the tx code with non ms connections */ if (!get_autocommit_setting(3, $link)) printf("[004] Autocommit should be on by default\n"); if (!$link->autocommit(false)) printf("[005] Failed to deactivate autocommit\n"); if (get_autocommit_setting(6, $link)) printf("[007] Autocommit should be off\n"); if (!$link->autocommit(true)) printf("[008] Failed to activate autocommit\n"); if (!get_autocommit_setting(9, $link)) printf("[010] Autocommit should be on\n"); if (!$link->autocommit(false)) printf("[011] Failed to disable autocommit\n"); if (get_autocommit_setting(12, $link)) printf("[013] Autocommit should be off\n"); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB") || !$link->query("INSERT INTO test(id) VALUES (1)") || !$link->commit()) printf("[014] [%d] %s\n", $link->errno, $link->error); $res = $link->query("SELECT * FROM test"); var_dump($res->num_rows); $link->query("INSERT INTO test(id) VALUES (2)"); $res = $link->query("SELECT * FROM test"); var_dump($res->num_rows); $link->rollback(); $res = $link->query("SELECT * FROM test"); var_dump($res->num_rows); print "done!"; ?> --CLEAN-- --EXPECTF-- int(1) int(2) int(1) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_host_info.phpt0000664000175000017500000000565012161007456021542 0ustar andreyandrey--TEST-- mysqli->host_info --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_host_info.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_host_info.ini --FILE-- 'Slave 1', 'info' => $link->host_info); /* slave 2 */ mst_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $threads[mst_mysqli_get_emulated_id(5, $link)] = array('role' => 'Slave 2', 'info' => $link->host_info); /* master */ mst_mysqli_query(6, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $threads[mst_mysqli_get_emulated_id(7, $link)] = array('role' => 'Master', 'info' => $link->host_info); foreach ($threads as $thread_id => $details) { printf("%s - %s: '%s'\n", $thread_id, $details['role'], $details['info']); if ('' == $details['info']) printf("Host info must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- slave[1,2]-%d - Slave 1: '%s' slave[1,2]-%d - Slave 2: '%s' master-%d - Master: '%s' done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_info.phpt0000664000175000017500000000742412161007456020506 0ustar andreyandrey--TEST-- Thread id --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_info.ini", $settings)) die(sprintf("SKIP %d\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_info.ini --FILE-- 'master', 'info' => mysqli_info($link)); $threads[mst_mysqli_get_emulated_id(5, $link)] = $tmp; mst_mysqli_query(6, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(7, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(8, $link, "CREATE TABLE test(id INT)", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(9, $link, "INSERT INTO test(id) VALUES (1), (2), (3)", MYSQLND_MS_LAST_USED_SWITCH); $tmp = array('role' => 'slave 1', 'info' => mysqli_info($link)); $threads[mst_mysqli_get_emulated_id(10, $link)] = $tmp; mst_mysqli_query(11, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(12, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(13, $link, "CREATE TABLE test(id INT)", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(14, $link, "INSERT INTO test(id) VALUES (1), (2), (3)", MYSQLND_MS_LAST_USED_SWITCH); $tmp = array('role' => 'slave 2', 'info' => mysqli_info($link)); $threads[mst_mysqli_get_emulated_id(15, $link)] = $tmp; mst_mysqli_query(16, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); foreach ($threads as $thread_id => $info) { printf("%s - %s - '%s'\n", $thread_id, $info['role'], $info['info']); if ('' == $info['info']) printf("info should not be empty. Check manually.\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- master-%d - master - '%s' slave[1,2]-%d - slave 1 - '%s' slave[1,2]-%d - slave 2 - '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_ini_settings.phpt0000664000175000017500000000310212161007456022237 0ustar andreyandrey--TEST-- PHP configuration settings --SKIPIF-- --FILE-- "mysqlnd_ms.enable", "mysqlnd_ms.force_config_usage" => "mysqlnd_ms.force_config_usage", "mysqlnd_ms.config_file" => "mysqlnd_ms.config_file", "mysqlnd_ms.collect_statistics" => "mysqlnd_ms.collect_statistics", "mysqlnd_ms.multi_master" => "mysqlnd_ms.multi_master", "mysqlnd_ms.disable_rw_split" => "mysqlnd_ms.disable_rw_split", ); $inigetall_list = ini_get_all("mysqlnd_ms", true); foreach ($expected as $ini_name) { if (!isset($inigetall_list[$ini_name])) { printf("[001] %s not found.\n", $ini_name); } else { $access = $inigetall_list[$ini_name]['access']; switch ($access) { case 1: $access = 'PHP_INI_USER'; break; case 4: $access = 'PHP_INI_SYSTEM'; break; case 2: case 6: $access = 'PHP_INI_PERDIR'; break; case 7: $access = 'PHP_INI_ALL'; break; default: break; } printf("%s [%s] '%s'\n", $ini_name, $access, $inigetall_list[$ini_name]['local_value']); unset($inigetall_list[$ini_name]); } } if (!empty($inigetall_list)) { printf("[002] Dumping list of unexpected ini settings\n"); var_dump($inigetall_list); } print "done!"; ?> --EXPECTF-- mysqlnd_ms.enable [PHP_INI_SYSTEM] '0' mysqlnd_ms.force_config_usage [PHP_INI_SYSTEM] '0' mysqlnd_ms.config_file [PHP_INI_SYSTEM] '' mysqlnd_ms.collect_statistics [PHP_INI_SYSTEM] '0' mysqlnd_ms.multi_master [PHP_INI_SYSTEM] '0' mysqlnd_ms.disable_rw_split [PHP_INI_SYSTEM] '0' done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_insert_affected_pdo.phpt0000664000175000017500000000516412161007456023541 0ustar andreyandrey--TEST-- insert id, affected rows (PDO) --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_insert_affected_pdo.ini", $settings)) die(sprintf("SKIP %d\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_insert_affected_pdo.ini --FILE-- exec($query); } function run_insert($offset, $pdo, $num_rows, $switch = NULL) { sleep(1); mst_mysqli_query($offset, $pdo, "DROP TABLE IF EXISTS test", $switch); mst_mysqli_query($offset + 1, $pdo, "CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, label CHAR(1))", MYSQLND_MS_LAST_USED_SWITCH); for ($i = 0; $i < $num_rows; $i++) { mst_mysqli_query($offset + 2, $pdo, "INSERT INTO test(label) VALUES ('a')", MYSQLND_MS_LAST_USED_SWITCH); } } try { $pdo = my_pdo_connect("myapp", $user, $passwd, $db, $port, $socket); } catch (Exception $e) { printf("[001] %s\n", $e->getMessage()); } /* master, automatically */ try { run_insert(10, $pdo, 1); if (1 != $pdo->lastInsertId()) printf("[11] Master insert id should be 1 got %d\n", $pdo->lastInsertId()); $affected = mst_mysqli_query(12, $pdo, "UPDATE test SET label = 'b'", MYSQLND_MS_LAST_USED_SWITCH); if (1 !== $affected) printf("[13] Master affected should be 1 got %d\n", $affected); } catch (Exception $e) { printf("[014] %s\n", $e->getMessage()); } /* slave 1 */ try { run_insert(20, $pdo, 5, MYSQLND_MS_SLAVE_SWITCH); if (5 != $pdo->lastInsertId()) printf("[21] Slave 1 insert id should be 5 got %d\n", $pdo->lastInsertId()); $affected = mst_mysqli_query(22, $pdo, "UPDATE test SET label = 'b'", MYSQLND_MS_LAST_USED_SWITCH); if (5 !== $affected) printf("[23] Slave 1 affected should be 5 got %d\n", $affected); } catch (Exception $e) { printf("[014] %s\n", $e->getMessage()); } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_insert_affected.phpt0000664000175000017500000000544312161007456022677 0ustar andreyandrey--TEST-- insert id, affected rows --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_insert_affected.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_insert_affected.ini --FILE-- insert_id) printf("[17] Master insert id should be 1 got %d\n", $link->insert_id); mst_mysqli_query(18, $link, "UPDATE test SET label = 'b'", MYSQLND_MS_LAST_USED_SWITCH); if (1 !== $link->affected_rows) printf("[19] Master affected should be 1 got %d\n", $link->affected_rows); /* slave 1 */ run_insert(20, $link, 5, MYSQLND_MS_SLAVE_SWITCH); if (5 !== $link->insert_id) printf("[27] Slave 1 insert id should be 5 got %d\n", $link->insert_id); mst_mysqli_query(28, $link, "UPDATE test SET label = 'b'", MYSQLND_MS_LAST_USED_SWITCH); if (5 !== $link->affected_rows) printf("[29] Slave 1 affected should be 5 got %d\n", $link->affected_rows); /* slave 2 */ run_insert(30, $link, 10, MYSQLND_MS_SLAVE_SWITCH); if (10 !== $link->insert_id) printf("[37] Slave 2 insert id should be 10 got %d\n", $link->insert_id); mst_mysqli_query(38, $link, "UPDATE test SET label = 'b'", MYSQLND_MS_LAST_USED_SWITCH); if (10 !== $link->affected_rows) printf("[39] Slave 2 affected should be 10 got %d\n", $link->affected_rows); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_last_used_random_once.phpt0000664000175000017500000000324312161007456024075 0ustar andreyandrey--TEST-- SQL hints LAST_USED called before any server has been selected, pick = random once --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('random' => array('sticky' => '1')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_last_used_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_last_used_random_once.ini --FILE-- query(sprintf("/*%s*/SELECT 1", MYSQLND_MS_LAST_USED_SWITCH))) printf("[002] [%d][%s] %s\n", $link->errno, $link->sqlstate, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Last used SQL hint cannot be used because last used connection has not been set yet. Statement will fail in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000][HY000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_last_used_random.phpt0000664000175000017500000000325312161007456023072 0ustar andreyandrey--TEST-- SQL hints LAST_USED called before any server has been selected, pick = random --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_last_used_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_last_used_random.ini --FILE-- query(sprintf("/*%s*/SELECT 1", MYSQLND_MS_LAST_USED_SWITCH))) printf("[002] [%d][%s] %s\n", $link->errno, $link->sqlstate, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Last used SQL hint cannot be used because last used connection has not been set yet. Statement will fail in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000][HY000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_last_used_rr.phpt0000664000175000017500000000314112161007456022231 0ustar andreyandrey--TEST-- SQL hints LAST_USED called before any server has been selected, pick = rr --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_last_used_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_last_used_rr.ini --FILE-- query(sprintf("/*%s*/SELECT 1", MYSQLND_MS_LAST_USED_SWITCH))) printf("[002] [%d][%s] %s\n", $link->errno, $link->sqlstate, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Last used SQL hint cannot be used because last used connection has not been set yet. Statement will fail in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000][HY000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_autocommit.phpt0000664000175000017500000000701212161007456022764 0ustar andreyandrey--TEST-- lazy connections and autocommit --SKIPIF-- 5.4.0, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_autocommit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_autocommit.ini --FILE-- fetch_assoc(); return $row['auto_commit']; } /* intentionally no MS connection - looking for default */ $link = mst_mysqli_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $master_default = get_autocommit_setting(2, $link); $link->close(); /* now MS */ $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* establish slave connection */ if ($res = mst_mysqli_query(2, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); if (!mysqli_autocommit($link, !$master_default)) printf("[003] Failed to change autocommit setting\n"); if ($master_default == ($tmp = get_autocommit_setting(4, $link))) printf("[005] Autocommit should be %d, got %d\n", !$master_default, $tmp); if ($master_default == ($tmp = get_autocommit_setting(6, $link, MYSQLND_MS_MASTER_SWITCH))) printf("[007] Autocommit should be %d, got %d\n", !$master_default, $tmp); $link->close(); $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* establish master connection */ if ($res = mst_mysqli_query(2, $link, "SELECT 1 FROM DUAL", MYSQLND_MS_MASTER_SWITCH)) var_dump($res->fetch_assoc()); if (!mysqli_autocommit($link, !$master_default)) printf("[003] Failed to change autocommit setting\n"); if ($master_default == ($tmp = get_autocommit_setting(4, $link))) printf("[005] Autocommit should be %d, got %d\n", !$master_default, $tmp); if ($master_default == ($tmp = get_autocommit_setting(6, $link, MYSQLND_MS_MASTER_SWITCH))) printf("[007] Autocommit should be %d, got %d\n", !$master_default, $tmp); $link->close(); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [1]=> string(1) "1" } array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_autocommit_switches.phpt0000664000175000017500000000465512161007456024707 0ustar andreyandrey--TEST-- lazy connections and autocommit (switching often) --SKIPIF-- 5.4.0, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_autocommit_switches.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_autocommit_switches.ini --FILE-- fetch_assoc(); return $row['auto_commit']; } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* establish slave connection */ if ($res = mst_mysqli_query(2, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); for ($i = 0; $i < 500; $i++) if (!mysqli_autocommit($link, ($setting = ($i % 2)))) printf("[003] Failed to change autocommit setting\n"); if ($setting != ($tmp = get_autocommit_setting(4, $link))) printf("[005] Autocommit should be %d, got %d\n", $setting, $tmp); if ($setting != ($tmp = get_autocommit_setting(6, $link, MYSQLND_MS_MASTER_SWITCH))) printf("[007] Autocommit should be %d, got %d\n", $setting, $tmp); $link->close(); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_change_user.phpt0000664000175000017500000001041712161007456023071 0ustar andreyandrey--TEST-- lazy + change_user() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_change_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); function test_mysql_access($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect to %s (port '%d', socket '%s') [%d] %s", $host, $port, $socket, mysqli_connect_errno(), mysqli_connect_error())); return $link->select_db("mysql"); } if (!test_mysql_access($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die("skip Master server account cannot access mysql database"); if (!test_mysql_access($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket)) die("skip Slave server account cannot access mysql database"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_change_user.ini --FILE-- thread_id; $link->change_user($user, $passwd, 'mysql'); mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $slave_thread = $link->thread_id; $res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_SLAVE_SWITCH); if (!$row = $res->fetch_assoc()) printf("[006] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[007] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != 'slave') printf("[008] Expecting role 'slave' got '%s'\n", $row['_role']); if ($link->thread_id != $slave_thread) printf("[009] Expecting slave connection thread id %d got %d\n", $slave_thread, $link->thread_id); $res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[011] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[012] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != '') printf("[013] Expecting role '' got '%s'\n", $row['_role']); if ($link->thread_id != $master_thread) printf("[014] Expecting master connection thread id %d got %d\n", $master_thread, $link->thread_id); $link->change_user($user, $passwd, $db); $res = mst_mysqli_query(15, $link, "SELECT @myrole AS _role, DATABASE() as _database"); if (!$row = $res->fetch_assoc()) printf("[016] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != $db) printf("[017] Expecting database '%s' got '%s'\n", $db, $row['_database']); if ($row['_role'] != '') printf("[018] Expecting role 'slave' got '%s'\n", $row['_role']); if ($link->thread_id != $slave_thread) printf("[019] Expecting slave connection thread id %d got %d\n", $slave_thread, $link->thread_id); $res = mst_mysqli_query(20, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[021] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != $db) printf("[022] Expecting database '%s' got '%s'\n", $db, $row['_database']); if ($row['_role'] != '') printf("[023] Expecting role '' got '%s'\n", $row['_role']); if ($link->thread_id != $master_thread) printf("[024] Expecting master connection thread id %d got %d\n", $master_thread, $link->thread_id); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_charsets.phpt0000664000175000017500000001174212161007456022424 0ustar andreyandrey--TEST-- Lazy connections and charsets --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_charsets.ini", $settings)) die(sprintf("SKIP %s\n", $error)); function test_for_charset($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) || !($tmp = mysqli_fetch_assoc($res))) { mysqli_close($link); die(sprintf("skip Cannot check server version, [%d] %s\n", mysqli_errno($link), mysqli_error($link))); } mysqli_free_result($res); $version = explode('.', $tmp['server_version']); if (empty($version)) { mysqli_close($link); die(sprintf("skip Cannot check server version, based on '%s'", $tmp['server_version'])); } if ($version[0] <= 4 && $version[1] < 1) { mysqli_close($link); die(sprintf("skip Requires MySQL Server 4.1+\n")); } if ((($res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'latin1'", MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) || (($res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'latin2'", MYSQLI_STORE_RESULT)) && (mysqli_num_rows($res) == 1)) ) { // ok, required latin1 or latin2 are available } else { die(sprintf("skip Requires character set latin1 or latin2\n")); } if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset')) die(sprintf("skip Cannot select current charset, [%d] %s\n", $link->errno, $link->error)); if (!$row = mysqli_fetch_assoc($res)) die(sprintf("skip Cannot detect current charset, [%d] %s\n", $link->errno, $link->error)); return $row['charset']; } $master_charset = test_for_charset($master_host_only, $user, $passwd, $db, $master_port, $master_socket); $slave_charset = test_for_charset($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if ($master_charset != $slave_charset) { die(sprintf("skip Master (%s) and slave (%s) must use the same default charset.", $master_charset, $slave_charset)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_charsets.ini --FILE-- errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[004] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; $new_charset = ('latin1' == $current_charset) ? 'latin2' : 'latin1'; /* shall be run on *all* configured machines - all masters, all slaves */ if (!$link->set_charset($new_charset)) printf("[005] [%d] %s\n", $link->errno, $link->error); /* slave 1 */ if (!$res = mst_mysqli_query(6, $link, "SELECT @@character_set_connection AS charset", MYSQLND_MS_LAST_USED_SWITCH)) printf("[007] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[008] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; if ($current_charset != $new_charset) printf("[009] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); /* master */ if (!$res = mst_mysqli_query(10, $link, "SELECT @@character_set_connection AS charset", MYSQLND_MS_MASTER_SWITCH)) printf("[011] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[012] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; if ($current_charset != $new_charset) printf("[013] Expecting charset '%s' got '%s'\n", $new_charset, $current_charset); if ($link->character_set_name() != $new_charset) printf("[014] Expecting charset '%s' got '%s'\n", $new_charset, $link->character_set_name()); /* slave 2 */ if (!$res = mst_mysqli_query(15, $link, "SELECT @@character_set_connection AS charset")) printf("[016] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[017] [%d] %s\n", $link->errno, $link->error); $current_charset = $row['charset']; printf("Slave 2 reports charset '%s', charset set was '%s'\n", $current_charset, $new_charset); print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 2 reports charset '%s', charset set was '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_commit.phpt0000664000175000017500000000400612161007456022073 0ustar andreyandrey--TEST-- lazy connections and commit --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_commit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_commit.ini --FILE-- commit())) printf("[003] [%d] %s\n", $link->errno, $link->error); $link->close(); /* Now MS */ $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[004] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } if (!($w_ms = $link->commit())) printf("[005] [%d] %s\n", $link->errno, $link->error); $link->close(); if ($wo_ms != $w_ms) printf("[006] Different behaviour with and without MS!\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_failure_failover_remember_master_only_random.phpt0000664000175000017500000000371712161007456031763 0ustar andreyandrey--TEST-- Lazy,loop,remember failed, master only, random --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', "remember_failed" => true, "max_retries" => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_failure_failover_remember_master_only_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.disable_rw_split=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_failure_failover_remember_master_only_random.ini --FILE-- fetch_assoc(); if (!isset($connections[$row['_id']])) { $connections[$row['_id']] = 1; } else { $connections[$row['_id']]++; } } foreach ($connections as $thread_id => $count) printf("%d: %d\n", $thread_id, $count); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %A %d: 10 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_failure_failover_remember_random_default_strategy.phpt0000664000175000017500000000414112161007456032765 0ustar andreyandrey--TEST-- Random, Remember failed, default strategy (= disabled) --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array("remember_failed" => true), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_lazy_failure_failover_remember_random_default_strategy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_lazy_failure_failover_remember_random_default_strategy.ini --FILE-- query("SELECT 1 FROM DUAL")) { /* failed slave ? */ $failed++; } else { if (!($res = $link->query(sprintf("/*%s*/SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)))) { printf("[002] Failed to check role [%d] %s\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($row['_role'] == 'master') { printf("[003] Master has been used.\n"); break; } } } if (0 == $failed) { printf("[004] No failed slaves, verify whether its a bug or a false positive\n"); } printf("Failed: %d\n", $failed); print "done!"; ?> --CLEAN-- --EXPECTF-- Failed: 100 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_failure_failover_remember_random_once.phpt0000664000175000017500000000533212161007456030346 0ustar andreyandrey--TEST-- Lazy,loop,remember failed, random_once --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', "remember_failed" => true, "max_retries" => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_failure_failover_remember_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_failure_failover_remember_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); mst_compare_stats(); /* let's hope we hit both slaves */ for ($i = 0; $i < 10; $i++) { mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true); $connections[$link->thread_id][] = 'slave (fallback to master)'; } mst_compare_stats(); mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true)); $connections[$link->thread_id][] = 'slave (fallback to master)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- Stats use_master: 11 Stats use_slave_sql_hint: 10 Stats lazy_connections_slave_failure: 2 This is 'slave %d' speaking Connection %d - ... master ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_failure_failover_remember_random.phpt0000664000175000017500000000523512161007456027344 0ustar andreyandrey--TEST-- Lazy,loop,remember failed, random --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', "remember_failed" => true, "max_retries" => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_failure_failover_remember_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_failure_failover_remember_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); mst_compare_stats(); /* let's hope we hit both slaves */ for ($i = 0; $i < 10; $i++) { mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true); $connections[$link->thread_id][] = 'slave (fallback to master)'; } mst_compare_stats(); mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); $connections[$link->thread_id][] = 'slave (fallback to master)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- Stats use_master: 11 Stats use_slave_sql_hint: 10 Stats lazy_connections_slave_failure: 2 %AThis is 'slave %d' speaking Connection %d - ... master ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_failure_failover_remember_rr_default_strategy.phpt0000664000175000017500000000432112161007456032130 0ustar andreyandrey--TEST-- RR, Remember failed, default strategy --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", $slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array("remember_failed" => true), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_lazy_failure_failover_remember_rr_default_strategy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_lazy_failure_failover_remember_rr_default_strategy.ini --FILE-- fetch_assoc()); /* slave 2 - no failure */ if ($res = mst_mysqli_query(3, $link, "SELECT 3 FROM DUAL")) var_dump($res->fetch_assoc()); /* slave 2 - no failure */ if ($res = mst_mysqli_query(4, $link, "SELECT 4 FROM DUAL")) var_dump($res->fetch_assoc()); /* slave 2 - no failure */ if ($res = mst_mysqli_query(5, $link, "SELECT 5 FROM DUAL")) var_dump($res->fetch_assoc()); /* master 1 - no failure */ mst_mysqli_query(7, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT @myrole AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [002] %s array(1) { [3]=> string(1) "3" } array(1) { [4]=> string(1) "4" } array(1) { [5]=> string(1) "5" } This is '' speaking done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_failure_failover_remember_rr.phpt0000664000175000017500000000737312161007456026514 0ustar andreyandrey--TEST-- Lazy,loop,remember failed, rr --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', "remember_failed" => true, "max_retries" => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_lazy_failure_failover_remember_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_lazy_failure_failover_remember_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- ")); $connections[$link->thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_query(3, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); $connections[$link->thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; /* will fall back to the master */ mst_mysqli_query(4, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; /* will again fall back to the master */ mst_mysqli_query(5, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- ---- Stats use_master: 1 Stats use_master_sql_hint: 1 Stats lazy_connections_master_success: 1 Stats lazy_connections_master_failure: 1 ---- ---- Stats use_master: 2 Stats use_master_sql_hint: 2 ---- ---- Stats use_master: 3 Stats use_slave_sql_hint: 1 Stats lazy_connections_slave_failure: 2 ---- ---- Stats use_master: 4 Stats use_slave_sql_hint: 2 ---- This is 'slave %d' speaking ---- Stats use_master: 5 Stats use_slave_guess: 1 ---- This is 'slave %d' speaking ---- Stats use_master: 6 Stats use_slave_guess: 2 ---- Connection %d - ... master ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_get_charset.phpt0000664000175000017500000000353012161007456023074 0ustar andreyandrey--TEST-- lazy connections and get charset before running a statement --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_get_charset.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_get_charset.ini --FILE-- get_charset())) printf("[003] [%d] %s\n", $link->errno, $link->error); else printf("[003] Charset is '%s'\n"); if ($res = mst_mysqli_query(4, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::get_charset(): The connection has no charset associated in %s on line %d [003] [%d] array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_failover_loop_max_retries_random_once.phpt0000664000175000017500000000572212161007456033501 0ustar andreyandrey--TEST-- Lazy,loop,random once,max_retries,master --SKIPIF-- array( 'master' => array("unreachable:7033", $emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_failover_loop_max_retries_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_failover_loop_max_retries_random_once.ini mysqlnd_ms.multi_master=1 mysqlnd_ms.collect_statistics=1 mysqlnd_ms.disable_rw_split=1 --FILE-- query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- master-%d 0,master-%d 1,master-%d 2,master-%d 3,master-%d 4,master-%d 5,master-%d 6,master-%d 7,master-%d 8,master-%d 9, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_failover_loop_max_retries_rr.phpt0000664000175000017500000001127312161007456031636 0ustar andreyandrey--TEST-- Lazy,loop,rr,max_retries,master --SKIPIF-- array( 'master' => array("unreachable:8033", "unreachable:9033", $emulated_master_host), 'slave' => array("unreachable:6033", "unreachable:7033", $emulated_slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_failover_loop_max_retries_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_failover_loop_max_retries_rr.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.disable_rw_split=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); /* one successful to one slave possible */ $exp_stats['lazy_connections_master_success'] = 1; for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { $exp_stats['lazy_connections_master_failure']+=2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array( "lazy_connections_master_failure", "lazy_connections_master_success", )); $exp_stats = $stats; for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("/*%s*/SELECT %d AS _run FROM DUAL", MYSQLND_MS_MASTER_SWITCH, $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { $exp_stats['lazy_connections_master_failure']+=2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(4, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(5, $stats, $exp_stats, array( "lazy_connections_master_failure", "lazy_connections_master_success", "lazy_connections_master_failure", "lazy_connections_master_success", )); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0,master-%d 1,no result 2,master-%d 3,no result 4,master-%d 5,no result 6,master-%d 7,no result 8,master-%d 9, no result 0,master-%d 1,no result 2,master-%d 3,no result 4,master-%d 5,no result 6,master-%d 7,no result 8,master-%d 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_no_slaves.phpt0000664000175000017500000000267612161007456025671 0ustar andreyandrey--TEST-- Lazy connect, master failure, no slaves --SKIPIF-- array( 'master' => array($master_host), 'slave' => array(), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_no_slaves.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_no_slaves.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); foreach ($connections as $thread_id => $details) { printf("Connection %s -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- [002] [1045] %s Connection %d - ... master done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure.phpt0000664000175000017500000000345412161007456023613 0ustar andreyandrey--TEST-- Lazy connect, master failure --SKIPIF-- array( 'master' => array($master_host), 'slave' => array( array( "host" => $slave_host_only, "port" => $slave_port, "socket" => $slave_socket, 'user' => $user, 'password' => $passwd, ), ), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_no_slaves.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_no_slaves.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); mst_mysqli_query(3, $link, "SELECT 1 FROM DUAL"); $connections[$link->thread_id] = array('slave'); foreach ($connections as $thread_id => $details) { printf("Connection %s -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- [002] [1045] %s Connection %d - ... master Connection %d - ... slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_random_once.phpt0000664000175000017500000000574412161007456026163 0ustar andreyandrey--TEST-- Lazy connect, master failure, random once --SKIPIF-- array( 'master' => array("unreachable:6033"), 'slave' => array($slave_host, $slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- ")); $connections[$link->thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $connections[$link->thread_id][] = 'slave'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); $connections[$link->thread_id][] = 'slave'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_MASTER_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'master'; echo "----\n"; mst_compare_stats(); echo "----\n"; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- Connect error, [002] [%d] %s ---- Stats use_master_sql_hint: 1 Stats lazy_connections_master_failure: 1 ---- ---- Stats use_slave: 1 Stats use_slave_sql_hint: 1 Stats lazy_connections_slave_success: 1 ---- This is 'slave %d' speaking ---- Stats use_slave: 2 Stats use_slave_guess: 1 ---- Connect error, [005] [%d] %s ---- Stats use_master_sql_hint: 2 Stats lazy_connections_master_failure: 2 ---- Connection 0 - ... master ... master Connection %d - ... slave ... slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_random.phpt0000664000175000017500000000420412161007456025145 0ustar andreyandrey--TEST-- Lazy connect, master failure, random --SKIPIF-- array( 'master' => array("unreachable:6033"), 'slave' => array($slave_host, $slave_host), 'pick' => array('random'), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- ")); $connections[$link->thread_id] = array('master'); mst_compare_stats(); mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_MASTER_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'master'; mst_compare_stats(); foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [002] [%d] %s Stats use_master_sql_hint: 1 Stats lazy_connections_master_failure: 1 Connect error, [004] [%d] %s Stats use_master_sql_hint: 2 Stats lazy_connections_master_failure: 2 Connection 0 - ... master ... master done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_rr.phpt0000664000175000017500000000752612161007456024322 0ustar andreyandrey--TEST-- Lazy connect, master failure, roundrobin --SKIPIF-- array( 'master' => array("unreachable:6033"), 'slave' => array($emulated_slave_host, $emulated_slave_host, $emulated_slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2,3]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- ")); $connections[$link->thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); echo "----\n"; mst_compare_stats(); $connections[mst_mysqli_get_emulated_id(4, $link)][] = 'slave'; echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); echo "----\n"; mst_compare_stats(); $connections[mst_mysqli_get_emulated_id(6, $link)][] = 'slave'; echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_MASTER_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'master'; echo "----\n"; mst_compare_stats(); echo "----\n"; foreach ($connections as $thread_id => $details) { printf("Connection %s -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- Connect error, [002] [%d] %s ---- Stats use_master_sql_hint: 1 Stats lazy_connections_master_failure: 1 ---- ---- Stats use_slave: 1 Stats use_slave_sql_hint: 1 Stats lazy_connections_slave_success: 1 ---- This is '' speaking ---- Stats use_slave: 2 Stats use_slave_guess: 1 Stats use_last_used_sql_hint: 1 Stats lazy_connections_slave_success: 2 ---- Connect error, [007] [%d] %s ---- Stats use_master_sql_hint: 2 Stats use_last_used_sql_hint: 2 Stats lazy_connections_master_failure: 2 ---- Connection 0 - ... master ... master Connection slave[1,2,3]-%d - ... slave Connection slave[1,2,3]-%d - ... slave done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_master_failure_user.phpt0000664000175000017500000001014312161007456024642 0ustar andreyandrey--TEST-- Lazy connect, master failure, user --SKIPIF-- array( 'master' => array("unreachable:6033"), 'slave' => array($slave_host), 'pick' => array('user' => array("callback" => "pick_server")), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_master_failure_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_master_failure_user.ini mysqlnd_ms.collect_statistics=1 --FILE-- %s\n", $connected_host, $query, $server); return $ret; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $connections = array(); echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH, true, false, true, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH); $connections[$link->thread_id][] = 'slave'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); $connections[$link->thread_id][] = 'slave'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_MASTER_SWITCH, true, false, true, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'master'; echo "----\n"; mst_compare_stats(); echo "----\n"; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- ---- Stats use_master_sql_hint: 1 Stats use_master_callback: 1 Stats lazy_connections_master_failure: 1 ---- pick_server('myapp', '/*ms=slave*//*3*/SET @myrole='slave'') => slave ---- Stats use_slave_sql_hint: 1 Stats use_slave_callback: 1 Stats lazy_connections_slave_success: 1 ---- pick_server('myapp', '/*4*/SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role') => slave This is 'slave %d' speaking ---- Stats use_slave_guess: 1 Stats use_slave_callback: 2 ---- ---- Stats use_master_sql_hint: 2 Stats use_master_callback: 2 Stats lazy_connections_master_failure: 2 ---- Connection 0 - ... master ... master Connection %d - ... slave ... slave done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_more_results.phpt0000664000175000017500000000362512161007456023334 0ustar andreyandrey--TEST-- lazy connections and more_results --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_more_results.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_more_results.ini --FILE-- dump_debug_info()) printf("[003] [%d] %s\n", $link->errno, $link->error); if (!$link->more_results()) printf("[004] [%d] '%s'\n", $link->errno, $link->error); else printf("[004] More results\n"); if (!$link->dump_debug_info()) printf("[005] [%d] %s\n", $link->errno, $link->error); if ($res = mst_mysqli_query(6, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- [004] [%d] '' array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_multi_master_failure_failover_loop_master_random_once.phpt0000664000175000017500000000541612161007456033664 0ustar andreyandrey--TEST-- MM, R/W splitting on but no slaves, RO --SKIPIF-- array( 'master' => array($master_host, "unreachable:7033", "unreachable:8033", "unreachable:9033"), 'slave' => array(), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_failure_failover_loop_master_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_failure_failover_loop_master_random_once.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.multi_master=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); @mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we must be connected to the master */ $exp_stats['lazy_connections_master_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", $row['_msg'], $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master 0,master 1,master 2,master 3,master 4,master 5,master 6,master 7,master 8,master 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_multi_master_failure_failover_loop_master_random.phpt0000664000175000017500000000533712161007456032662 0ustar andreyandrey--TEST-- MM, R/W splitting on but no slaves, R --SKIPIF-- array( 'master' => array($master_host, "unreachable:7033", "unreachable:8033", "unreachable:9033"), 'slave' => array(), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_failure_failover_loop_master_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_failure_failover_loop_master_random.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.multi_master=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); @mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we must be connected to the master */ $exp_stats['lazy_connections_master_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", $row['_msg'], $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master 0,master 1,master 2,master 3,master 4,master 5,master 6,master 7,master 8,master 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_multi_master_failure_failover_loop_master_rr.phpt0000664000175000017500000000530612161007456032021 0ustar andreyandrey--TEST-- MM, R/W splitting on but no slaves, RR --SKIPIF-- array( 'master' => array("unreachable:7033", $master_host), 'slave' => array(), 'pick' => array('roundrobin' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_failure_failover_loop_master_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_failure_failover_loop_master_rr.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.multi_master=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); @mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we must be connected to the master */ $exp_stats['lazy_connections_master_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", $row['_msg'], $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master 0,master 1,master 2,master 3,master 4,master 5,master 6,master 7,master 8,master 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_next_result.phpt0000664000175000017500000000361712161007456023166 0ustar andreyandrey--TEST-- lazy connections and next_result --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_next_result.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_next_result.ini --FILE-- dump_debug_info()) printf("[003] [%d] %s\n", $link->errno, $link->error); if (!$link->next_result()) printf("[004] [%d] '%s'\n", $link->errno, $link->error); else printf("[004] Next result\n"); if (!$link->dump_debug_info()) printf("[005] [%d] %s\n", $link->errno, $link->error); if ($res = mst_mysqli_query(6, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- %A004] [%d] '' array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_other_commands_old.phpt0000664000175000017500000001221712161007456024446 0ustar andreyandrey--TEST-- lazy connections and assorted commands called before connect (mysqlnd < 5.0.9) --SKIPIF-- = 50009) { die("SKIP Requires mysqlnd < 5.0.9, found $MYSQLND_VERSION"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_escape.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_escape.ini --FILE-- errno) { printf("[%03d] [%d/%s] %s\n", $offset, $link->errno, $link->sqlstate, $link->error); return; } if (!$silent) printf("[%03d] %s\n", $offset, var_export($ret, true)); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } check_codes(3, $link, $link->errno); check_codes(4, $link, $link->error); check_codes(5, $link, $link->sqlstate); check_codes(6, $link, $link->thread_id); check_codes(7, $link, $link->server_version); check_codes(8, $link, $link->server_info); check_codes(9, $link, $link->host_info); check_codes(10, $link, $link->protocol_version); check_codes(11, $link, $link->insert_id); check_codes(12, $link, $link->affected_rows); check_codes(13, $link, $link->warning_count); check_codes(14, $link, $link->field_count); check_codes(15, $link, $link->client_version); check_codes(16, $link, $link->client_info); check_codes(17, $link, $link->info); check_codes(18, $link, $link->autocommit(false)); check_codes(19, $link, $link->autocommit(true)); check_codes(20, $link, $link->dump_debug_info()); check_codes(21, $link, $link->ping()); check_codes(22, $link, $link->autocommit(false)); check_codes(23, $link, $link->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10)); check_codes(24, $link, $link->autocommit(false)); check_codes(25, $link, $link->dump_debug_info()); check_codes(26, $link, $link->stmt_init()); check_codes(27, $link, $link->dump_debug_info()); check_codes(28, $link, $link->stmt_init()); check_codes(29, $link, $link->kill(-1)); check_codes(30, $link, $link->select_db($db)); check_codes(31, $link, $link->ssl_set('blubb_server-key.pem','blubb_server-cert.pem', 'blubb_cacert.pem', NULL, NULL)); check_codes(32, $link, $link->dump_debug_info()); check_codes(33, $link, $link->change_user($user, $passwd, $db)); check_codes(35, $link, $link->close()); if (function_exists('mysqli_set_local_infile_handler')) { mysqli_set_local_infile_handler($link, "callme"); } if (function_exists('mysqli_set_local_infile_default')) { mysqli_set_local_infile_default($link); } if (function_exists('mysqli_get_client_stats')) { mysqli_get_client_stats(); } if (function_exists('mysqli_get_connection_stats')) { $link->get_connection_stats(); } print "done!"; ?> --CLEAN-- --EXPECTF-- [003] 0 [004] '' [005] '00000' [006] 0 [007] %d [008] %s [009] %s [010] %d [011] 0 [012] %d [013] 0 [014] 0 [015] %d [016] '%s' [017] NULL [018] true [019] true [020] true [021] true [022] true [023] true [024] true [025] true [026] mysqli_stmt::__set_state(array( 'affected_rows' => NULL, 'insert_id' => NULL, 'num_rows' => NULL, 'param_count' => NULL, 'field_count' => NULL, 'errno' => NULL, 'error' => NULL, 'sqlstate' => NULL, 'id' => NULL, )) [027] true [028] mysqli_stmt::__set_state(array( 'affected_rows' => NULL, 'insert_id' => NULL, 'num_rows' => NULL, 'param_count' => NULL, 'field_count' => NULL, 'errno' => NULL, 'error' => NULL, 'sqlstate' => NULL, 'id' => NULL, )) Warning: mysqli::kill(): processid should have positive value in %s on line %d [029] false [030] true [031] true [032] true [033] true Warning: check_codes(): Couldn't fetch mysqli in %s on line %d [035] true Warning: mysqli::get_connection_stats(): Couldn't fetch mysqli in %s on line %d done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_other_commands.phpt0000664000175000017500000001176412161007456023616 0ustar andreyandrey--TEST-- lazy connections and assorted commands called before connect (mysqlnd >= 5.0.9) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_escape.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_escape.ini --FILE-- errno) { printf("[%03d] [%d/%s] %s\n", $offset, $link->errno, $link->sqlstate, $link->error); return; } if (!$silent) printf("[%03d] %s\n", $offset, var_export($ret, true)); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } check_codes(3, $link, $link->errno); check_codes(4, $link, $link->error); check_codes(5, $link, $link->sqlstate); check_codes(6, $link, $link->thread_id); check_codes(7, $link, $link->server_version); check_codes(8, $link, $link->server_info); check_codes(9, $link, $link->host_info); check_codes(10, $link, $link->protocol_version); check_codes(11, $link, $link->insert_id); check_codes(12, $link, $link->affected_rows); check_codes(13, $link, $link->warning_count); check_codes(14, $link, $link->field_count); check_codes(15, $link, $link->client_version); check_codes(16, $link, $link->client_info); check_codes(17, $link, $link->info); check_codes(18, $link, $link->autocommit(false)); check_codes(19, $link, $link->autocommit(true)); check_codes(20, $link, $link->dump_debug_info()); check_codes(21, $link, $link->ping()); check_codes(22, $link, $link->autocommit(false)); check_codes(23, $link, $link->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10)); check_codes(24, $link, $link->autocommit(false)); check_codes(25, $link, $link->dump_debug_info()); check_codes(26, $link, $link->stmt_init(), 1); check_codes(29, $link, $link->kill(-1)); check_codes(30, $link, $link->select_db($db)); check_codes(31, $link, $link->ssl_set('blubb_server-key.pem','blubb_server-cert.pem', 'blubb_cacert.pem', NULL, NULL)); check_codes(32, $link, $link->dump_debug_info()); check_codes(33, $link, $link->change_user($user, $passwd, $db)); /* check_codes(71, $link, mysqli_get_server_version($link)); check_codes(81, $link, mysqli_get_server_info($link)); check_codes(91, $link, mysqli_get_host_info($link)); check_codes(101, $link, mysqli_get_proto_info($link)); check_codes(102, $link, mysqli_character_set_name($link)); check_codes(103, $link, mysqli_stat($link)); check_codes(104, $link, $link->dump_debug_info()); check_codes(105, $link, mysqli_dump_debug_info($link)); */ check_codes(45, $link, $link->close()); if (function_exists('mysqli_set_local_infile_handler')) { mysqli_set_local_infile_handler($link, "callme"); } if (function_exists('mysqli_set_local_infile_default')) { mysqli_set_local_infile_default($link); } if (function_exists('mysqli_get_client_stats')) { mysqli_get_client_stats(); } if (function_exists('mysqli_get_connection_stats')) { $link->get_connection_stats(); } print "done!"; ?> --CLEAN-- --EXPECTF-- [003] %d [004] '' [005] '00000' [006] 0 [007] %d [008] %s [009] %s [010] 10 [011] 0 [012] 0 [013] 0 [014] 0 [015] %d [016] '%s' [017] NULL [018] true [019] true [020] true [021] true [022] true [023] true [024] true [025] true Warning: mysqli::kill(): processid should have positive value in %s on line %d [029] false [030] true [031] true [032] true [033] true Warning: check_codes(): Couldn't fetch mysqli in %s on line %d [045] true Warning: mysqli::get_connection_stats(): Couldn't fetch mysqli in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_prepared_statements.phpt0000664000175000017500000000404112161007456024653 0ustar andreyandrey--TEST-- Prepared Statements + lazy --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_prepared_statements.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_prepared_statements.ini --FILE-- prepare("SELECT @myrole AS _role")) printf("[005] [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) printf("[006] [%d] %s\n", $stmt->errno, $stmt->error); $role = NULL; if (!$stmt->bind_result($role)) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); while ($stmt->fetch()) printf("Role = '%s'\n", $role); if (!$stmt = $link->prepare("/*".MYSQLND_MS_MASTER_SWITCH."*/ SELECT @myrole AS _role")) printf("[008] [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) printf("[009] [%d] %s\n", $stmt->errno, $stmt->error); $role = NULL; if (!$stmt->bind_result($role)) printf("[010] [%d] %s\n", $stmt->errno, $stmt->error); while ($stmt->fetch()) printf("Role = '%s'\n", $role); $stmt->close(); print "done!"; ?> --CLEAN-- --EXPECTF-- Role = 'slave' Role = 'master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_real_escape.phpt0000664000175000017500000000364312161007456023054 0ustar andreyandrey--TEST-- lazy + real escape + set_charset --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_real_escape.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_real_escape.ini --FILE-- real_escape_string($string); $ms = $link_ms->real_escape_string($string); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::real_escape_string(): (mysqlnd_ms) string escaping doesn't work without established connection. Possible solution is to add server_charset to your configuration in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_real_escape_set_charset.phpt0000664000175000017500000000604512161007456025437 0ustar andreyandrey--TEST-- lazy + real escape + set_charset --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_real_escape_set_charset.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_real_escape_set_charset.ini --FILE-- close(); /* From a user perspective MS and non MS-Connection are now in the same state: connected */ if (!($link_ms = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if (!($link = mst_mysqli_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket))) printf("[004] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); foreach ($charsets as $charset) { if (!@$link->set_charset($charset) || !@$link_ms->set_charset($charset)) continue; $string = ""; for ($i = 0; $i < 256; $i++) { $char = @iconv("UTF-8", $charset, chr($i)); if ($char) $string .= $char; else $string .= chr($i); } $no_ms = $link->real_escape_string($string); $ms = $link_ms->real_escape_string($string); if (($ms === "") && ($no_ms !== "")) { printf("[005] MS has returned an empty string!\n"); printf("[006] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); printf("[007] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); break; } if ($no_ms !== $ms) { printf("[008] Encoded strings differ for charset '%s', MS = '%s', no MS = '%s'\n", $charset, $ms, $no_ms); printf("[009] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); printf("[010] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); break; } } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_rollback.phpt0000664000175000017500000000401312161007456022372 0ustar andreyandrey--TEST-- lazy connections and rollback --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_rollback.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_rollback.ini --FILE-- dump_debug_info()) printf("[003] [%d] %s\n", $link->errno, $link->error); /* Rollback on unopened connection is a no-op */ if (!$link->rollback()) printf("[004] [%d] %s\n", $link->errno, $link->error); else printf("[004] Rollback\n"); if (!$link->dump_debug_info()) printf("[005] [%d] %s\n", $link->errno, $link->error); if ($res = mst_mysqli_query(6, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- [004] Rollback array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_select_db.phpt0000664000175000017500000000632612161007456022536 0ustar andreyandrey--TEST-- lazy connections and select_db --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_select_db.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_select_db.ini --FILE-- fetch_assoc(); if ($row['_db'] != "") printf("[004] No DB should be selected, connected to '%s'\n", $row['_db']); $res = mst_mysqli_query(5, $link, "SELECT DATABASE() AS _db", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); if ($row['_db'] != "") printf("[006] No DB should be selected, connected to '%s'\n", $row['_db']); mysqli_close($link); $link = mst_mysqli_connect("myapp", $user, $passwd, NULL, $port, $socket); if (mysqli_connect_errno()) printf("[007] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if (!mysqli_select_db($link, $db)) printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); $res = mst_mysqli_query(9, $link, "SELECT DATABASE() AS _db"); $row = $res->fetch_assoc(); if ($row['_db'] != $db) printf("[010] DB should be '%s', connected to '%s'\n", $db, $row['_db']); $res = mst_mysqli_query(11, $link, "SELECT DATABASE() AS _db", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); if ($row['_db'] != $db) printf("[012] DB should be '%s', connected to '%s'\n", $db, $row['_db']); mysqli_close($link); $link = mst_mysqli_connect("myapp", $user, $passwd, NULL, $port, $socket); if (mysqli_connect_errno()) printf("[013] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* free and alloc/copy of internal db field */ if (!mysqli_select_db($link, $db)) printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); if (!mysqli_select_db($link, $db)) printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); $res = mst_mysqli_query(16, $link, "SELECT DATABASE() AS _db"); $row = $res->fetch_assoc(); if ($row['_db'] != $db) printf("[017] DB should be '%s', connected to '%s'\n", $db, $row['_db']); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_set_charset.phpt0000664000175000017500000000366712161007456023123 0ustar andreyandrey--TEST-- lazy connections and set charset before running a statement (code flow) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_charset.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_charset.ini --FILE-- set_charset("latin1")) printf("[003] [%d] %s\n", $link->errno, $link->error); else printf("[003] Charset successfully set ?!\n"); if ($res = mst_mysqli_query(4, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); /* no further testing, its about code flow only */ print "done!"; ?> --CLEAN-- --EXPECTF-- [003] Charset successfully set ?! array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure2_random.phpt0000664000175000017500000000513712161007456025054 0ustar andreyandrey--TEST-- Lazy connect, slave failure and existing slave, random --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033", $slave_host, "unreachable3:6033"), 'pick' => array('random'), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_random.ini --FILE-- array(), 'slave' => array(), 'slave (no fallback)' => array(), ); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); $connections['master'][] = $link->thread_id; mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, false, true, version_compare(PHP_VERSION, '5.3.99', ">")); $connections['slave (no fallback)'][0] = $link->thread_id; $states = array("failure" => 0, "connect" => 0); do { $res = mst_mysqli_query(4, $link, "SELECT CONNECTION_ID() AS _role", NULL, true, false, true, version_compare(PHP_VERSION, '5.3.99', ">")); if ($res) { $row = $res->fetch_assoc(); $res->close(); if (0 == $states['connect']) { printf("This is '%s' speaking\n", $row['_role']); $connections['slave'][] = $link->thread_id; } $states['connect']++; } else { $states['failure']++; $connections['slave (no fallback)'][1] = $link->thread_id; } } while ((0 == $states['connect']) || (0 == $states['failure'])); foreach ($connections as $role => $details) { printf("Role %s -\n", $role); foreach ($details as $id) printf("... %d\n", $id); } print "done!"; ?> --CLEAN-- --EXPECTF-- This is %s speaking Role master - ... %d Role slave - ... %d Role slave (no fallback) - ... %d ... 0 done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure2_user.phpt0000664000175000017500000001245512161007456024553 0ustar andreyandrey--TEST-- Lazy connect, slave failure and existing slave, user --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host, "unreachable2:6033"), 'pick' => array('user' => array("callback" => "pick_server")), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure2_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure2_user.ini --FILE-- 2) $emulated_slave_idx = 0; $server = 'slave'; $ret = $emulated_slaves[$emulated_slave_idx++]; break; default: printf("Unknown return value from mysqlnd_ms_query_is_select, where = %s .\n", $where); $ret = $emulated_master[0]; $server = 'unknown'; break; } if (false === stristr($query, "util.inc")) printf("pick_server('%s', '%s') => %s\n", $connected_host, $query, $server); return $ret; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $connections = array(); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); $connections[mst_mysqli_get_emulated_id(3, $link)] = array('master'); mst_mysqli_query(4, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, false, true, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); $connections[mst_mysqli_get_emulated_id(6, $link)] = array('slave'); mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", true, false, true, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", true, false, true, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; foreach ($connections as $thread_id => $details) { printf("Connection %s -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SET @myrole='master'') => master pick_server('myapp', '/*5*/SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role') => slave This is '' speaking pick_server('myapp', '/*1*//*7*/SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role') => slave %AE_WARNING] mysqli::query(): (mysqlnd_ms) Callback chose tcp://unreachable2:6033 but connection failed in %s on line %A pick_server('myapp', '/*1*//*8*/SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role') => slave %AE_WARNING] mysqli::query(): (mysqlnd_ms) Callback chose tcp://unreachable:6033 but connection failed in %s on line %A Connection master-%d - ... master Connection 0 - ... slave (no fallback) ... slave (no fallback) ... slave (no fallback) Connection slave[2]-%d - ... slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_master_random_once.phpt0000664000175000017500000000530412161007456032265 0ustar andreyandrey--TEST-- Lazy,loop,random once --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_master_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_master_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we must be connected to the master */ $exp_stats['lazy_connections_master_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", $row['_msg'], $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master 0,master 1,master 2,master 3,master 4,master 5,master 6,master 7,master 8,master 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_master_random.phpt0000664000175000017500000000522112161007456031257 0ustar andreyandrey--TEST-- Lazy,loop,random --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_master_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_master_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we must be connected to the master */ $exp_stats['lazy_connections_master_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", $row['_msg'], $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master 0,master 1,master 2,master 3,master 4,master 5,master 6,master 7,master 8,master 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_master_rr.phpt0000664000175000017500000000520112161007456030420 0ustar andreyandrey--TEST-- Lazy,loop,rr --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_master_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_master_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we must be connected to the master */ $exp_stats['lazy_connections_master_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", $row['_msg'], $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master 0,master 1,master 2,master 3,master 4,master 5,master 6,master 7,master 8,master 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_random_once.phpt0000664000175000017500000000563712161007456033325 0ustar andreyandrey--TEST-- Lazy,loop,random once,max_retries --SKIPIF-- array( 'master' => array("unreachable:7033", $emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_random_once.ini mysqlnd_ms.multi_master=1 mysqlnd_ms.collect_statistics=1 --FILE-- query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- slave-%d 0,slave-%d 1,slave-%d 2,slave-%d 3,slave-%d 4,slave-%d 5,slave-%d 6,slave-%d 7,slave-%d 8,slave-%d 9, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_random.phpt0000664000175000017500000000725212161007456032314 0ustar andreyandrey--TEST-- Lazy,loop,random,max_retries --SKIPIF-- array( 'master' => array("unreachable:8033", $emulated_master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); $exp_stats['lazy_connections_master_success'] = 1; for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { $exp_stats['lazy_connections_slave_failure']+=2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure", "lazy_connections_master_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- master-%d 0,master-%d 1,master-%d 2,master-%d 3,master-%d 4,master-%d 5,master-%d 6,master-%d 7,master-%d 8,master-%d 9, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_range.phpt0000664000175000017500000000322512161007456032124 0ustar andreyandrey--TEST-- Lazy,loop,random once,max_retries=-1 --SKIPIF-- array( 'master' => array("unreachable:7033"), 'slave' => array("unreachable:6033", $emulated_slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => (-1 * PHP_INT_MAX) - 1.1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_range.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_range.ini --FILE-- --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Invalid value '%s' for max_retries. Stopping in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_rr.phpt0000664000175000017500000001127212161007456031454 0ustar andreyandrey--TEST-- Lazy,loop,rr,max_retries --SKIPIF-- array( 'master' => array("unreachable:8033", "unreachable:9033", $emulated_master_host), 'slave' => array("unreachable:6033", "unreachable:7033", $emulated_slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_max_retries_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); /* one successful to one slave possible */ $exp_stats['lazy_connections_slave_success'] = 1; for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { $exp_stats['lazy_connections_slave_failure']+=2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array( "lazy_connections_slave_failure", "lazy_connections_slave_success", )); $exp_stats = $stats; $exp_stats['lazy_connections_master_success'] = 1; for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("/*%s*/SELECT %d AS _run FROM DUAL", MYSQLND_MS_MASTER_SWITCH, $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { $exp_stats['lazy_connections_master_failure']+=2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(4, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(5, $stats, $exp_stats, array( "lazy_connections_slave_failure", "lazy_connections_slave_success", "lazy_connections_master_failure", "lazy_connections_master_success", )); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0,slave-%d 1,master-%d 2,slave-%d 3,no result 4,slave-%d 5,master-%d 6,slave-%d 7,no result 8,slave-%d 9, master-%d 0,no result 1,master-%d 2,no result 3,master-%d 4,no result 5,master-%d 6,no result 7,master-%d 8,no result 9, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_random_once.phpt0000664000175000017500000000536212161007456033503 0ustar andreyandrey--TEST-- Lazy,loop,ro,multi master --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_random_once.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.multi_master=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%d - '%s',", $row['_run'], $link->error); } else { /* we should never get here */ printf("no result %d - %s\n", $i, $link->error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- 0 - '',1 - '',2 - '',3 - '',4 - '',5 - '',6 - '',7 - '',8 - '',9 - '', done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_random.phpt0000664000175000017500000000530512161007456032474 0ustar andreyandrey--TEST-- Lazy,loop,random,no master --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_random.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.multi_master=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%d - '%s',", $row['_run'], $link->error); } else { /* we should never get here */ printf("no result %d - %s\n", $i, $link->error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- 0 - '',1 - '',2 - '',3 - '',4 - '',5 - '',6 - '',7 - '',8 - '',9 - '', done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_rr.phpt0000664000175000017500000000527112161007456031641 0ustar andreyandrey--TEST-- Lazy,loop,rr,multi master --SKIPIF-- array( 'master' => array("unreachable:8033", $master_host), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_multi_master_rr.ini mysqlnd_ms.collect_statistics=1 mysqlnd_ms.multi_master=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%d - '%s'\n", $row['_run'], $link->error); } else { /* we should never get here */ printf("no result %d - %s\n", $i, $link->error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- 0 - '' 1 - '' 2 - '' 3 - '' 4 - '' 5 - '' 6 - '' 7 - '' 8 - '' 9 - '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_no_master2_random_once.phpt0000664000175000017500000000632412161007456033046 0ustar andreyandrey--TEST-- Lazy,loop,ro,no master --SKIPIF-- array( 'master' => array(), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { $error = ""; ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $error = $link->error; $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d\n", $row['_msg'], $row['_run']); } else { /* note the error message! */ printf("no result %d - %s\n", $i, $error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_failure", "lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0 - php_network_getaddresses: getaddrinfo failed: %s no result 1 - php_network_getaddresses: getaddrinfo failed: %s no result 2 - php_network_getaddresses: getaddrinfo failed: %s no result 3 - php_network_getaddresses: getaddrinfo failed: %s no result 4 - php_network_getaddresses: getaddrinfo failed: %s no result 5 - php_network_getaddresses: getaddrinfo failed: %s no result 6 - php_network_getaddresses: getaddrinfo failed: %s no result 7 - php_network_getaddresses: getaddrinfo failed: %s no result 8 - php_network_getaddresses: getaddrinfo failed: %s no result 9 - php_network_getaddresses: getaddrinfo failed: %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_no_master2_random.phpt0000664000175000017500000000625612161007456032046 0ustar andreyandrey--TEST-- Lazy,loop,random,no master --SKIPIF-- array( 'master' => array(), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master2_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master2_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { $error = ""; ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $error = $link->error; $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d\n", $row['_msg'], $row['_run']); } else { /* note the error message! */ printf("no result %d - %s\n", $i, $error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_failure", "lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0 - php_network_getaddresses: getaddrinfo failed: %s no result 1 - php_network_getaddresses: getaddrinfo failed: %s no result 2 - php_network_getaddresses: getaddrinfo failed: %s no result 3 - php_network_getaddresses: getaddrinfo failed: %s no result 4 - php_network_getaddresses: getaddrinfo failed: %s no result 5 - php_network_getaddresses: getaddrinfo failed: %s no result 6 - php_network_getaddresses: getaddrinfo failed: %s no result 7 - php_network_getaddresses: getaddrinfo failed: %s no result 8 - php_network_getaddresses: getaddrinfo failed: %s no result 9 - php_network_getaddresses: getaddrinfo failed: %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_no_master2_rr.phpt0000664000175000017500000000623312161007456031204 0ustar andreyandrey--TEST-- Lazy,loop,rr,no master --SKIPIF-- array( 'master' => array(), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { $error = ""; ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $error = $link->error; $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d\n", $row['_msg'], $row['_run']); } else { /* note the error message! */ printf("no result %d - %s\n", $i, $error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_failure", "lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0 - php_network_getaddresses: getaddrinfo failed: %s no result 1 - php_network_getaddresses: getaddrinfo failed: %s no result 2 - php_network_getaddresses: getaddrinfo failed: %s no result 3 - php_network_getaddresses: getaddrinfo failed: %s no result 4 - php_network_getaddresses: getaddrinfo failed: %s no result 5 - php_network_getaddresses: getaddrinfo failed: %s no result 6 - php_network_getaddresses: getaddrinfo failed: %s no result 7 - php_network_getaddresses: getaddrinfo failed: %s no result 8 - php_network_getaddresses: getaddrinfo failed: %s no result 9 - php_network_getaddresses: getaddrinfo failed: %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random_once.phpt0000664000175000017500000000643212161007456032764 0ustar andreyandrey--TEST-- Lazy,loop,ro,no master --SKIPIF-- array( 'master' => array("unreachable:8033"), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { $error = ""; ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $error = $link->error; $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_master_failure']++; $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d\n", $row['_msg'], $row['_run']); } else { /* note the error message! */ printf("no result %d - %s\n", $i, $error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_failure", "lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0 - php_network_getaddresses: getaddrinfo failed: %s no result 1 - php_network_getaddresses: getaddrinfo failed: %s no result 2 - php_network_getaddresses: getaddrinfo failed: %s no result 3 - php_network_getaddresses: getaddrinfo failed: %s no result 4 - php_network_getaddresses: getaddrinfo failed: %s no result 5 - php_network_getaddresses: getaddrinfo failed: %s no result 6 - php_network_getaddresses: getaddrinfo failed: %s no result 7 - php_network_getaddresses: getaddrinfo failed: %s no result 8 - php_network_getaddresses: getaddrinfo failed: %s no result 9 - php_network_getaddresses: getaddrinfo failed: %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random.phpt0000664000175000017500000000636012161007456031760 0ustar andreyandrey--TEST-- Lazy,loop,random,no master --SKIPIF-- array( 'master' => array("unreachable:8033"), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { $error = ""; ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $error = $link->error; $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_master_failure']++; $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d\n", $row['_msg'], $row['_run']); } else { /* note the error message! */ printf("no result %d - %s\n", $i, $error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_failure", "lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0 - php_network_getaddresses: getaddrinfo failed: %s no result 1 - php_network_getaddresses: getaddrinfo failed: %s no result 2 - php_network_getaddresses: getaddrinfo failed: %s no result 3 - php_network_getaddresses: getaddrinfo failed: %s no result 4 - php_network_getaddresses: getaddrinfo failed: %s no result 5 - php_network_getaddresses: getaddrinfo failed: %s no result 6 - php_network_getaddresses: getaddrinfo failed: %s no result 7 - php_network_getaddresses: getaddrinfo failed: %s no result 8 - php_network_getaddresses: getaddrinfo failed: %s no result 9 - php_network_getaddresses: getaddrinfo failed: %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_rr.phpt0000664000175000017500000000634112161007456031122 0ustar andreyandrey--TEST-- Lazy,loop,rr,no master --SKIPIF-- array( 'master' => array("unreachable:8033"), 'slave' => array("unreachable:6033", "unreachable:7033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_no_master_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { $error = ""; ob_start(); $res = $link->query(sprintf("SELECT @myrole AS _msg, %d AS _run FROM DUAL", $i)); $error = $link->error; $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (!stristr($tmp, "warning")) { /* ... we should never get here */ printf("no warning %d\n", $i); } else { $exp_stats['lazy_connections_master_failure']++; $exp_stats['lazy_connections_slave_failure']+= 2; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d\n", $row['_msg'], $row['_run']); } else { /* note the error message! */ printf("no result %d - %s\n", $i, $error); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_master_failure", "lazy_connections_slave_failure")); print "done!"; ?> --CLEAN-- --EXPECTF-- no result 0 - php_network_getaddresses: getaddrinfo failed: %s no result 1 - php_network_getaddresses: getaddrinfo failed: %s no result 2 - php_network_getaddresses: getaddrinfo failed: %s no result 3 - php_network_getaddresses: getaddrinfo failed: %s no result 4 - php_network_getaddresses: getaddrinfo failed: %s no result 5 - php_network_getaddresses: getaddrinfo failed: %s no result 6 - php_network_getaddresses: getaddrinfo failed: %s no result 7 - php_network_getaddresses: getaddrinfo failed: %s no result 8 - php_network_getaddresses: getaddrinfo failed: %s no result 9 - php_network_getaddresses: getaddrinfo failed: %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_random_once.phpt0000664000175000017500000000756712161007456030727 0ustar andreyandrey--TEST-- Lazy,loop,random once --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { /* plugin tried host unreachable:6033... */ $exp_stats['lazy_connections_slave_failure']++; /* ... and immediately thereafter $emulated_host, thus ...*/ $exp_stats['lazy_connections_slave_success'] = 1; } else { /* ... once we are connected, the stat won't increase as there is only one valid slave */ $exp_stats['lazy_connections_slave_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure", "lazy_connections_slave_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- slave-%d 0,slave-%d 1,slave-%d 2,slave-%d 3,slave-%d 4,slave-%d 5,slave-%d 6,slave-%d 7,slave-%d 8,slave-%d 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_random.phpt0000664000175000017500000000750412161007456027712 0ustar andreyandrey--TEST-- Lazy,loop,random --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { /* plugin tried host unreachable:6033... */ $exp_stats['lazy_connections_slave_failure']++; /* ... and immediately thereafter $emulated_host, thus ...*/ $exp_stats['lazy_connections_slave_success'] = 1; } else { /* ... once we are connected, the stat won't increase as there is only one valid slave */ $exp_stats['lazy_connections_slave_success'] = 1; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure", "lazy_connections_slave_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- slave-%d 0,slave-%d 1,slave-%d 2,slave-%d 3,slave-%d 4,slave-%d 5,slave-%d 6,slave-%d 7,slave-%d 8,slave-%d 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_loop_rr.phpt0000664000175000017500000000712112161007456027050 0ustar andreyandrey--TEST-- Lazy,loop,rr --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array("unreachable:6033", $emulated_slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_loop_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_loop_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- $field) { if (!isset($stats[$field])) { printf("[%03d] No such stat '%s'\n", $offset, $field); } else if ($stats[$field] != $exp_stats[$field]) { printf("[%03d] Expecting stat '%s' = %d, got %d\n", $offset, $field, $exp_stats[$field], $stats[$field]); } } } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* let's hope we hit both slaves */ $stats = $exp_stats = mysqlnd_ms_get_stats(); /* one successful to one slave possible */ $exp_stats['lazy_connections_slave_success'] = 1; for ($i = 0; $i < 10; $i++) { ob_start(); $res = $link->query(sprintf("SELECT %d AS _run FROM DUAL", $i)); $tmp = ob_get_contents(); ob_end_clean(); /* NOTE: it is ok to get a warning from the underlying API if connection fails */ if (stristr($tmp, "warning")) { $exp_stats['lazy_connections_slave_failure']++; } if ($res) { $row = $res->fetch_assoc(); printf("%s %d,", mst_mysqli_get_emulated_id(2, $link), $row['_run']); } else { printf("no result %d,", $i); } } printf("\n"); $stats = mysqlnd_ms_get_stats(); compare_stats(3, $stats, $exp_stats, array("lazy_connections_slave_failure", "lazy_connections_slave_success")); print "done!"; ?> --CLEAN-- --EXPECTF-- slave-%d 0,slave-%d 1,slave-%d 2,slave-%d 3,slave-%d 4,slave-%d 5,slave-%d 6,slave-%d 7,slave-%d 8,slave-%d 9, done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_random_once.phpt0000664000175000017500000000547712161007456027674 0ustar andreyandrey--TEST-- Lazy connect, failover = master, pick = random_once --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1, 'failover' => array('strategy' => 'master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; /* falls back to the master */ mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; /* falls back to the master */ mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- ---- Stats use_master: 1 Stats use_master_sql_hint: 1 Stats lazy_connections_master_success: 1 ---- ---- Stats use_master: 2 Stats use_slave_sql_hint: 1 Stats lazy_connections_slave_failure: 1 ---- This is 'slave %d' speaking ---- Stats use_master: 3 Stats use_slave_guess: 1 Stats lazy_connections_slave_failure: 2 ---- Connection %d - ... master ... slave (fallback to master) ... slave (fallback to master) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_random.phpt0000664000175000017500000000505012161007456026653 0ustar andreyandrey--TEST-- Lazy connect, failover = master, pick = random --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033"), 'pick' => array('random'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_failover_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_failover_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); /* let's hope we hit both slaves */ for ($i = 0; $i < 10; $i++) { mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (fallback to master)'; } mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (fallback to master)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- This is 'slave %d' speaking Connection %d - ... master ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_failover_rr.phpt0000664000175000017500000000720212161007456026017 0ustar andreyandrey--TEST-- Lazy connect, failover = master, pick = roundrobin --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1, 'failover' => array('strategy' => 'master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_lazy_slave_failure_failover_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_lazy_slave_failure_failover_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = array('master'); echo "----\n"; mst_compare_stats(); echo "----\n"; /* will fall back to the master */ mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; /* will again fall back to the master */ mst_mysqli_query(4, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (fallback to master)'; echo "----\n"; mst_compare_stats(); echo "----\n"; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- ---- Stats use_master: 1 Stats use_master_sql_hint: 1 Stats lazy_connections_master_success: 1 ---- ---- Stats use_master: 2 Stats use_slave_sql_hint: 1 Stats lazy_connections_slave_failure: 1 ---- ---- Stats use_master: 3 Stats use_slave_sql_hint: 2 Stats lazy_connections_slave_failure: 2 ---- This is 'slave %d' speaking ---- Stats use_master: 4 Stats use_slave_guess: 1 Stats lazy_connections_slave_failure: 3 ---- This is 'slave %d' speaking ---- Stats use_master: 5 Stats use_slave_guess: 2 Stats lazy_connections_slave_failure: 4 ---- Connection %d - ... master ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) ... slave (fallback to master) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_random_once.phpt0000664000175000017500000000433712161007456025777 0ustar andreyandrey--TEST-- Lazy connect, slave failure, random once --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033"), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_random_once.ini --FILE-- thread_id] = array('master'); mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [003] [%d] %s Connect error, [004] [%d] %s Connection %d - ... master Connection 0 - ... slave (no fallback) ... slave (no fallback) done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_random.phpt0000664000175000017500000000425412161007456024771 0ustar andreyandrey--TEST-- Lazy connect, slave failure, random --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033"), 'pick' => array('random'), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_random.ini --FILE-- thread_id] = array('master'); mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [003] [%d] %s Connect error, [004] [%d] %s Connection %d - ... master Connection 0 - ... slave (no fallback) ... slave (no fallback) done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_rr.phpt0000664000175000017500000000470612161007456024136 0ustar andreyandrey--TEST-- Lazy connect, slave failure, roundrobin --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033", "unreachable2:6033"), 'pick' => array('roundrobin'), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_rr.ini --FILE-- thread_id] = array('master'); mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, true, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- Connect error, [003] [%d] %s Connect error, [004] [%d] %s Connect error, [005] [%d] %s Connection %d - ... master Connection 0 - ... slave (no fallback) ... slave (no fallback) ... slave (no fallback) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_slave_failure_user.phpt0000664000175000017500000000702212161007456024463 0ustar andreyandrey--TEST-- Lazy connect, slave failure, user --SKIPIF-- array( 'master' => array($master_host), 'slave' => array("unreachable:6033"), 'pick' => array('user' => array("callback" => "pick_server")), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_slave_failure_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_slave_failure_user.ini --FILE-- %s\n", $connected_host, $query, $server); return $ret; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $connections = array(); mst_mysqli_query(2, $link, "SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH); $connections[$link->thread_id] = array('master'); mst_mysqli_query(3, $link, "SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH, true, false, false, version_compare(PHP_VERSION, '5.3.99', ">")); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, false, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", NULL, true, false, false, version_compare(PHP_VERSION, '5.3.99', ">"))); $connections[$link->thread_id][] = 'slave (no fallback)'; foreach ($connections as $thread_id => $details) { printf("Connection %d -\n", $thread_id); foreach ($details as $msg) printf("... %s\n", $msg); } print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SET @myrole='master'') => master Connect error, [003] [2002] %s Connect error, [004] [2002] %s Connect error, [005] [2002] %s Connection %d - ... master Connection 0 - ... slave (no fallback) ... slave (no fallback) ... slave (no fallback) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lazy_stmt_init.phpt0000664000175000017500000000545012161007456022621 0ustar andreyandrey--TEST-- lazy connections and stmt init --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lazy_stmt_init.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lazy_stmt_init.ini --FILE-- dump_debug_info()) printf("[003] [%d] %s\n", $link->errno, $link->error); if (!($stmt = $link->stmt_init())) printf("[004] [%d] %s\n", $link->errno, $link->error); if (!($stmt = $link->stmt_init())) printf("[005] [%d] %s\n", $link->errno, $link->error); /* line useable ?! */ if (!$link->dump_debug_info()) printf("[006] [%d] %s\n", $link->errno, $link->error); if (is_object($stmt)) { $one = NULL; if (!$stmt->prepare("SELECT 1 AS _one FROM DUAL") || !$stmt->execute() || !$stmt->bind_result($one) || !$stmt->fetch()) { printf("[007] [%d] '%s'\n", $stmt->errno, $stmt->error); } else { printf("[008] _one = %s\n", $one); if ($stmt->fetch()) { printf("[008] More data than expected"); } } } if (!($stmt = $link->stmt_init())) printf("[011] [%d] %s\n", $link->errno, $link->error); if (is_object($stmt)) { $one = "42"; if (!$stmt->prepare("SET @a=?") || !$stmt->bind_param("s", $one) || !$stmt->execute()) { printf("[012] [%d] '%s'\n", $stmt->errno, $stmt->error); } else { if ($res = mst_mysqli_query(13, $link, "SELECT @a", MYSQLND_MS_LAST_USED_SWITCH)) { var_dump($res->fetch_assoc()); } } } if ($res = mst_mysqli_query(14, $link, "SELECT 1 FROM DUAL")) var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- [008] _one = 1 array(1) { ["@a"]=> string(2) "42" } array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lb_filter_twice_ro_rr.phpt0000664000175000017500000000563412161007456024114 0ustar andreyandrey--TEST-- Stacking LB filter: r[andom] | rr - second ignored --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array("sticky" => 1), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lb_filter_twice_r_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lb_filter_twice_r_rr.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Error while creating filter 'roundrobin' . Non-multi filter 'random' already created. Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Error while creating filter 'roundrobin' . Non-multi filter 'random' already created. Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_lb_filter_twice_rr_ro.phpt0000664000175000017500000000556212161007456024114 0ustar andreyandrey--TEST-- Stacking LB filter: rr | random_once - second ignored --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "roundrobin" => array(), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_lb_filter_twice_rr_ro.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_lb_filter_twice_rr_ro.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Error while creating filter 'random' . Non-multi filter 'roundrobin' already created. Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Error while creating filter 'random' . Non-multi filter 'roundrobin' already created. Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_async_cont.phpt0000664000175000017500000000633112161007456023270 0ustar andreyandrey--TEST-- Limits: Asynchronous queries (continue after E_RECOVERABLE_ERROR) --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_async_cont.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_async_cont.ini --FILE-- query("SET @my_role='master'")) printf("[002] [%d] %s\n", $link1->errno, $link1->error); $threads['set'] = $link1->thread_id; if (!$link1->query("SELECT @my_role AS _msg", MYSQLI_ASYNC)) printf("[003] [%d] %s\n", $link1->errno, $link1->error); /* CAUTION: Asynchronous queries are not supported with the plugin. We don't promise any particular behaviour. Not even the one found in the EXPECTF section. Behaviour may change at any time without prior notice. Application developers MUST NOT rely on it. The only promise is: no crash. */ $threads['async select'] = $link1->thread_id; $all_links = array($link1); $processed = 0; $retry = 0; do { $links = $errors = $reject = array(); foreach ($all_links as $link) { $links[] = $errors[] = $reject[] = $link; } if (!mysqli_poll($links, $errors, $reject, 1)) { $retry++; if ($retry > 3) break; usleep(100); continue; } foreach ($links as $link) { if ($result = $link->reap_async_query()) { $processed++; $row = $result->fetch_assoc(); printf("fetch %d - thread %d - '%s'\n", $processed, $link->thread_id, $row['_msg']); mysqli_free_result($result); } } } while ($processed < count($all_links)); if (!($res = $link1->query("SELECT @my_role AS _msg"))) printf("[004] [%d] %s\n", $link1->errno, $link1->error); $threads["sync select"] = $link1->thread_id; foreach ($threads as $task => $id) printf("%s - %d\n", $task, $id); if ($threads["sync select"] != $threads["async select"]) printf("[005] Asynchronous SELECT and SELECT have been send over different connections\n"); if (!$link1->query("DROP TABLE IF EXISTS test")) printf("[006] [%d] %s\n", $link1->errno, $link1->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) Asynchronous queries are not supported in %s on line %d [003] [2000] (mysqlnd_ms) Asynchronous queries are not supported set - %d async select - %d sync select - %d [005] Asynchronous SELECT and SELECT have been send over different connections done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_async.phpt0000664000175000017500000000473112161007456022247 0ustar andreyandrey--TEST-- Limits: Asynchronous queries --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_async.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_async.ini --FILE-- query("SET @my_role='master'")) printf("[002] [%d] %s\n", $link1->errno, $link1->error); $threads['set'] = $link1->thread_id; if (!$link1->query("SELECT @my_role AS _msg", MYSQLI_ASYNC)) printf("[003] [%d] %s\n", $link1->errno, $link1->error); $threads['async select'] = $link1->thread_id; $all_links = array($link1); $processed = 0; do { $links = $errors = $reject = array(); foreach ($all_links as $link) { $links[] = $errors[] = $reject[] = $link; } if (!mysqli_poll($links, $errors, $reject, 1)) { usleep(100); continue; } foreach ($links as $link) { if ($result = $link->reap_async_query()) { $processed++; $row = $result->fetch_assoc(); printf("fetch %d - thread %d - '%s'\n", $processed, $link->thread_id, $row['_msg']); mysqli_free_result($result); } } } while ($processed < count($all_links)); if (!($res = $link1->query("SELECT @my_role AS _msg"))) printf("[004] [%d] %s\n", $link1->errno, $link1->error); $threads["sync select"] = $link1->thread_id; foreach ($threads as $task => $id) printf("%s - %d\n", $task, $id); if ($threads["sync select"] != $threads["async select"]) printf("[005] Asynchronous SELECT and SELECT have been send over different connections\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli::query(): (mysqlnd_ms) Asynchronous queries are not supported in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_autocommit.phpt0000664000175000017500000000626212161007456023314 0ustar andreyandrey--TEST-- Limits: autocommit - NOT handled by plugin before PHP 5.3.99 --SKIPIF-- 5.4.0, using " . PHP_VERSION)); $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_autocommit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_autocommit.ini --FILE-- autocommit is not handled by the plugin! Don't rely on it! */ if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if (!mysqli_autocommit($link, false)) printf("[002] Failed to change autocommit setting\n"); mst_mysqli_query(3, $link, "SET autocommit=0", MYSQLND_MS_MASTER_SWITCH); mst_mysqli_query(4, $link, "SET autocommit=0", MYSQLND_MS_SLAVE_SWITCH); /* applied to master connection because master is the first one contacted by plugin and autocommit is not dispatched */ if (!mysqli_autocommit($link, true)) printf("[005] Failed to change autocommit setting\n"); /* slave because SELECT */ $res = mst_mysqli_query(6, $link, "SELECT @@autocommit AS auto_commit"); $row = $res->fetch_assoc(); if (1 != $row['auto_commit']) printf("[007] Autocommit should be on, got '%s'\n", $row['auto_commit']); /* master because of hint */ $res = mst_mysqli_query(8, $link, "SELECT @@autocommit AS auto_commit", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); if (1 != $row['auto_commit']) printf("[009] Autocommit should be on, got '%s'\n", $row['auto_commit']); $link->close(); /* no plugin magic */ if (!($link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket))) printf("[010] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if (!mysqli_autocommit($link, false)) printf("[011] Failed to change autocommit setting\n"); mst_mysqli_query(12, $link, "SET autocommit=0"); if (!mysqli_autocommit($link, false)) printf("[013] Failed to change autocommit setting\n"); $res = mst_mysqli_query(14, $link, "SELECT @@autocommit AS auto_commit"); $row = $res->fetch_assoc(); if (0 != $row['auto_commit']) printf("[015] Autocommit should be off, got '%s'\n", $row['auto_commit']); if (!mysqli_autocommit($link, true)) printf("[016] Failed to change autocommit setting\n"); $res = mst_mysqli_query(17, $link, "SELECT @@autocommit AS auto_commit"); $row = $res->fetch_assoc(); if (1 != $row['auto_commit']) printf("[018] Autocommit should be on, got '%s'\n", $row['auto_commit']); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_connection_options.phpt0000664000175000017500000000411712161007456025042 0ustar andreyandrey--TEST-- Limits: connection options not handled --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_connection_options.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_connection_options.ini --FILE-- options(MYSQLI_INIT_COMMAND, "SET @myinitcommand = 'something'")) printf("[001] Cannot set init command, [%d] %s\n", $link->errno, $link->error); if (!mst_mysqli_real_connect($link, "myapp", $user, $passwd, $db, $port, $socket)) printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* master may have it because MS prototype used to connect to the master first */ if (!($res = mst_mysqli_query(3, $link, "SELECT @myinitcommand AS _myinit", MYSQLND_MS_MASTER_SWITCH))) printf("[004] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[005] [%d] %s\n", $link->errno, $link->error); if ('something' != $row['_myinit']) printf("[006] Expecting 'something' got '%s'\n", $row['_myinit']); if (!($res = mst_mysqli_query(7, $link, "SELECT @myinitcommand AS _myinit", MYSQLND_MS_SLAVE_SWITCH))) printf("[008] [%d] %s\n", $link->errno, $link->error); if (!$row = $res->fetch_assoc()) printf("[009] [%d] %s\n", $link->errno, $link->error); if ('something' != $row['_myinit']) printf("[010] Expecting 'something' got '%s'\n", $row['_myinit']); print "done!"; ?> --CLEAN-- --EXPECTF-- [010] Expecting 'something' got '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_multi_query_lazy.phpt0000664000175000017500000000422212161007456024543 0ustar andreyandrey--TEST-- multi query and lazy connections: doesn't work because set_server_option calls are not buffered and lost --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_multi_query_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_multi_query_lazy.ini --FILE-- multi_query($query))) printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); return $ret; } if (!($link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); mst_mysqli_query(2, $link, "SET @myrole='Slave 1'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(4, $link, "SET @myrole='Master 1'"); /* slave 1 */ mst_mysqli_query(5, $link, "SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL"); do { if ($res = $link->store_result()) { $row = $res->fetch_assoc(); printf("%s\n", $row['_msg']); $res->free(); } } while ($link->more_results() && $link->next_result()); echo "\n"; print "done!"; ?> --CLEAN-- --EXPECTF-- [002] /*ms=slave*/SET @myrole='Slave 1' [004] SET @myrole='Master 1' [005] SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL [005] [0]%s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_poll.phpt0000664000175000017500000000462612161007456022103 0ustar andreyandrey--TEST-- Limits: mysqli_poll() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_poll.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_poll.ini --FILE-- query("SET @my_role='master'")) printf("[002] [%d] %s\n", $link1->errno, $link1->error); $threads['set'] = $link1->thread_id; $threads['async select'] = $link1->thread_id; $all_links = array($link1); $processed = 0; $tries = 0; do { $links = $errors = $reject = array(); foreach ($all_links as $link) { $links[] = $errors[] = $reject[] = $link; } if (!@mysqli_poll($links, $errors, $reject, 1)) { usleep(1000); if ($tries++ > 2) break; continue; } foreach ($links as $link) { if ($result = $link->reap_async_query()) { $processed++; $row = $result->fetch_assoc(); printf("fetch %d - thread %d - '%s'\n", $processed, $link->thread_id, $row['_msg']); mysqli_free_result($result); } } } while ($processed < count($all_links)); if (!($res = $link1->query("SELECT @my_role AS _msg"))) printf("[004] [%d] %s\n", $link1->errno, $link1->error); $threads["sync select"] = $link1->thread_id; foreach ($threads as $task => $id) printf("%s - %d\n", $task, $id); if ($threads["sync select"] != $threads["async select"]) printf("[005] Asynchronous SELECT and SELECT have been send over different connections\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- set - %d async select - %d sync select - %d [005] Asynchronous SELECT and SELECT have been send over different connections done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_sql_calc_found_rows.phpt0000664000175000017500000000467112161007456025163 0ustar andreyandrey--TEST-- SQL_CALC_FOUND_ROWS and RR --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_sql_calc_found_rows.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_sql_calc_found_rows.ini --FILE-- num_rows; /* round robin: slave 2 - found_rows() not set by previous query - found_rows() = 1 */ $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role, FOUND_ROWS() AS _found"); $row = $res->fetch_assoc(); printf("Num rows %d, found rows %d, role %s\n", $rows, $row['_found'], $row['_role']); /* slave 1 */ $res = mst_mysqli_query(5, $link, "SELECT SQL_CALC_FOUND_ROWS id FROM test WHERE id < 3 LIMIT 1"); $rows = $res->num_rows; /* round robin: slave 1 (SQL hint used) - found_rows() set by previous query - found_rows() = 2 */ $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role, FOUND_ROWS() AS _found", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); printf("Num rows %d, found rows %d, role %s\n", $rows, $row['_found'], $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- Num rows 1, found rows 0, role slave2 Num rows 1, found rows 2, role slave1 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_sql_prepare.phpt0000664000175000017500000001022312161007456023440 0ustar andreyandrey--TEST-- Limits: SQL prepare --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_sql_prepare.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_sql_prepare.ini --FILE-- query($sql)) { printf("[002] [%d] %s\n", $link->errno, $link->error); } /* first slave */ $sql = sprintf("/*%s*/SET @myrole='slave_a'", MYSQLND_MS_SLAVE_SWITCH); if (!$link->query($sql)) { printf("[003] [%d] %s\n", $link->errno, $link->error); } /* At this point we are connected to the slave. We do a SQL PREPARE ... SELECT. A PREPARE is not a SELECT. It will be redirected to the master. If you want to run it on the slave to which you are currently connected, for example to avoid overloading the master, you must use the SQL hint MYSQLND_MS_LAST_USED_SWITCH. */ if (!$link->query("PREPARE mystmt FROM 'SELECT @myrole AS _role'")) printf("[004] [%d] %s\n", $link->errno, $link->error); if (!($res = $link->query("EXECUTE mystmt"))) printf("[005] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('master' != $row['_role']) { printf("[006] Expecting 'master' got '%s'\n", $row['_role']); } $res->close(); /* second slave - round robin ! Also note: two slaves with the same URI */ if (!($res = $link->query("SELECT @myrole AS _role"))) printf("[007] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('' != $row['_role']) printf("[008] Expecting '' got '%s'\n", $row['_role']); /* should go to the master */ if (!($res = $link->query("EXECUTE mystmt"))) printf("[009] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('master' != $row['_role']) { printf("[010] Expecting 'master' got '%s'\n", $row['_role']); } $res->close(); /* A more tricky scenatio for which there is no solution but to use a user-defined server selection (pick_server() handler). PREPARE ... - slave A, forced with MS_SLAVE hint EXECUTE ... - slave A, forced with MS_LAST_USED hint EXECUTE - master. no hint EXECUTE - ... no way to get to slave A, MS_SLAVE hint will use slave B because of RR */ $query = sprintf("/*%s*/PREPARE mystmt FROM 'SELECT @myrole AS _role'", MYSQLND_MS_SLAVE_SWITCH); if (!$link->query($query)) printf("[011] [%d] %s\n", $link->errno, $link->error); /* if we don't use a hint this goes to the master because it is no select */ $query = sprintf("/*%s*/EXECUTE mystmt", MYSQLND_MS_LAST_USED_SWITCH); if (!($res = $link->query($query))) printf("[012] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('slave_a' != $row['_role']) { printf("[013] Expecting 'slave_a' got '%s'\n", $row['_role']); } $res->close(); if (!($res = $link->query("EXECUTE mystmt"))) printf("[014] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ('master' != $row['_role']) { printf("[015] Expecting 'master' got '%s'\n", $row['_role']); } $res->close(); /* round robin will give us the second slave */ $query = sprintf("/*%s*/EXECUTE mystmt", MYSQLND_MS_SLAVE_SWITCH); if (!($res = $link->query($query))) printf("[016] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [016] [%d] %s done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_sql_transactions.phpt0000664000175000017500000001115312161007456024515 0ustar andreyandrey--TEST-- Limits: SQL transactions --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_sql_transactions.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_sql_transactions.ini --FILE-- autocommit = false; /* slave */ mst_mysqli_query(100, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(4, $link, "CREATE TABLE test(id VARCHAR(20)) ENGINE=InnoDB", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(5, $link, "START TRANSACTION", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(6, $link, "INSERT INTO test(id) VALUES ('slave')", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(7, $link, "COMMIT", MYSQLND_MS_LAST_USED_SWITCH); /* master */ mst_mysqli_query(101, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_MASTER_SWITCH); mst_mysqli_query(8, $link, "CREATE TABLE test(id VARCHAR(20)) ENGINE=InnoDB", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(9, $link, "START TRANSACTION", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(10, $link, "INSERT INTO test(id) VALUES ('master')", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(11, $link, "COMMIT", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(12, $link, "START TRANSACTION", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(13, $link, "INSERT INTO test(id) VALUES ('master')", MYSQLND_MS_LAST_USED_SWITCH); /* leaving master with open transaction */ mst_mysqli_query(14, $link, "START TRANSACTION", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(15, $link, "INSERT INTO test(id) VALUES ('slave')", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(16, $link, "COMMIT", MYSQLND_MS_LAST_USED_SWITCH); /* back to the master for a rollback */ mst_mysqli_query(17, $link, "ROLLBACK", MYSQLND_MS_MASTER_SWITCH); $res = mst_mysqli_query(18, $link, "SELECT id FROM test", MYSQLND_MS_LAST_USED_SWITCH); while ($row = $res->fetch_assoc()) printf("Master, id = '%s'\n", $row['id']); /* back to the slave for a select */ $res = mst_mysqli_query(19, $link, "SELECT id FROM test"); while ($row = $res->fetch_assoc()) printf("Slave, id = '%s'\n", $row['id']); /* No hint. Goes to the master. Open transaction, no autocommit. Slave will not see it. For test running we do not require $emulated_master_host and $emulated_slave_host to identify an actual master and slave in a MySQL replication setup. However, you get the point when looking at the test... */ $res = mst_mysqli_query(20, $link, "INSERT INTO test(id) VALUES ('master')"); /* back to the slave for a select */ $res = mst_mysqli_query(21, $link, "SELECT id FROM test"); while ($row = $res->fetch_assoc()) printf("Slave, id = '%s'\n", $row['id']); print "done!"; ?> --CLEAN-- --EXPECTF-- Master, id = 'master' Slave, id = 'slave' Slave, id = 'slave' Slave, id = 'slave' Slave, id = 'slave' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_limits_use_db.phpt0000664000175000017500000000541012161007456022366 0ustar andreyandrey--TEST-- Limits: SQL USE database/schema --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_use_db.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); function test_mysql_access($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); return $link->select_db("mysql"); } if (!test_mysql_access($master_host_only, $user, $passwd, $db, $port, $socket)) die("skip Master server account cannot access mysql database"); if (!test_mysql_access($slave_host_only, $user, $passwd, $db, $port, $socket)) die("skip Slave server account cannot access mysql database"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_use_db.ini --FILE-- fetch_assoc()) printf("[006] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[007] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != 'slave') printf("[008] Expecting role 'slave' got '%s'\n", $row['_role']); /* master and other slaves do not see the change */ $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[010] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != $db) printf("[011] Expecting database '%s' got '%s'\n", $db, $row['_database']); if ($row['_role'] != 'master') printf("[012] Expecting role 'master' got '%s'\n", $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_manual_failover_killed.phpt0000664000175000017500000001016212161007456024234 0ustar andreyandrey--TEST-- Manual failover, unknown slave host --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), 'failover' => array('strategy' => 'master'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_failover_killed.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2,3]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_failover_killed.ini --FILE-- query($query))) { printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); return 0; } if (!is_object($res)) { return $link->thread_id; } if (!($row = @$res->fetch_assoc())) { printf("[%03d + 03] [%d] %s\n", $offset, $link->errno, $link->error); return 0; } return @mst_mysqli_get_emulated_id($offset, $link); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (0 !== mysqli_connect_errno()) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $threads = array( 'master' => array(), 'slave 1' => array(), 'slave 2' => array(), 'slave 3' => array(), ); $threads['master'][my_mysqli_query(10, $link, "DROP TABLE IF EXISTS test")] = 1; $threads['slave 1'][my_mysqli_query(20, $link, "SELECT 'Slave 1' AS msg")] = 1; $threads['slave 2'][my_mysqli_query(30, $link, "SELECT 'Slave 2' AS msg")] = 1; $thread_id = $link->thread_id; $threads['slave 3'][my_mysqli_query(40, $link, "SELECT 'Slave 3' AS msg")] = 1; $link->kill($thread_id); $threads['slave 1'][my_mysqli_query(50, $link, "SELECT 'Slave 1' AS msg")]++; $threads['slave 2'][my_mysqli_query(60, $link, "SELECT 'Slave 2' AS msg")] = 1; $threads['slave 3'][my_mysqli_query(70, $link, "SELECT 'Slave 3' AS msg")]++; $threads['slave 1'][my_mysqli_query(80, $link, "SELECT 'Slave 1' AS msg")]++; $threads['slave 2'][my_mysqli_query(90, $link, "SELECT 'Slave 2' AS msg")]++; $threads['slave 3'][my_mysqli_query(100, $link, "SELECT 'Slave 3' AS msg")]++; foreach ($threads['slave 2'] as $thread_id => $num_queries) { printf("Slave 2, %d\n", $thread_id); if (isset($threads['slave 1'][$thread_id])) { printf("[201] Slave 2 is Slave 1 ?!\n"); var_dump($threads); } if (isset($threads['slave 3'][$thread_id])) { printf("[202] Slave 2 is Slave 3 ?!\n"); var_dump($threads); } if (isset($threads['master'][$thread_id])) { printf("[203] Slave 2 is the Master ?!\n"); var_dump($threads); } } print "done!"; ?> --CLEAN-- --EXPECTF-- [060 + 01] [2006] MySQL server has gone away [090 + 01] [2006] MySQL server has gone away Slave 2, %d Slave 2, 0 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_manual_failover_unknown.phpt0000664000175000017500000000770112161007456024474 0ustar andreyandrey--TEST-- Manual failover, unknown slave host --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, "unknown", $emulated_slave_host), 'pick' => array("roundrobin"), 'failover' => array('strategy' => 'disabled'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_failover_unknown.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2,3]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_failover_unknown.ini --FILE-- query($query))) { if (isset($mst_connect_errno_codes[$link->errno])) printf("[%03d + 01] Expected connect error, [%d] %s\n", $offset, $link->errno, $link->error); else printf("[%03d + 02] Unexpected error, [%d] %s\n", $offset, $link->errno, $link->error); return 0; } if (!is_object($res)) { printf("[%03d + 04] Thread %d, %s\n", $offset, $link->thread_id, $query); return mst_mysqli_get_emulated_id($offset, $link); } if (!($row = $res->fetch_assoc())) { printf("[%03d + 04] [%d] %s\n", $offset, $link->errno, $link->error); return 0; } printf("[%03d + 05] Thread %d, %s\n", $offset, $link->thread_id, $row['msg']); return mst_mysqli_get_emulated_id($offset, $link); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (0 !== mysqli_connect_errno()) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $threads = array(); $threads[my_mysqli_query(10, $link, "DROP TABLE IF EXISTS test")] = 'master'; $threads[my_mysqli_query(20, $link, "SELECT 'Slave 1' AS msg")] = 'slave 1'; $threads[my_mysqli_query(30, $link, "SELECT 'Slave 2' AS msg")] = 'slave 2'; $threads[my_mysqli_query(40, $link, "SELECT 'Slave 3' AS msg")] = 'slave 3'; $threads[my_mysqli_query(50, $link, "SELECT 'Slave 1' AS msg")] = 'slave 1'; $threads[my_mysqli_query(60, $link, "SELECT 'Slave 2' AS msg")] = 'slave 2'; $threads[my_mysqli_query(70, $link, "SELECT 'Slave 3' AS msg")] = 'slave 3'; foreach ($threads as $thread_id => $role) printf("Thread ID %s, role %s\n", $thread_id, $role); print "done!"; ?> --CLEAN-- --EXPECTF-- [010 + 04] Thread %s, DROP TABLE IF EXISTS test [020 + 05] Thread %s, Slave 1 [030 + 01] Expected connect error, [%d] %s [040 + 05] Thread %s, Slave 3 [050 + 05] Thread %s, Slave 1 [060 + 01] Expected connect error, [%d] %s [070 + 05] Thread %s, Slave 3 Thread ID %s, role master Thread ID %s, role slave 1 Thread ID 0, role slave 2 Thread ID %s, role slave 3 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_on_write.phpt0000664000175000017500000000747012161007456022755 0ustar andreyandrey--TEST-- Use master on write (pick = random_once) --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'master_on_write' => 1, 'pick' => array("random" => array("sticky" => "1")), ), ); if ($error = mst_create_config("test_mysqlnd_ms_master_on_write.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_master_on_write.ini mysqlnd_ms.collect_statistics=1 --FILE-- fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); echo "----\n"; mst_compare_stats(); echo "----\n"; /* not a select -> master query */ mst_mysqli_query(4, $link, "SET @myrole='Master 1'"); echo "----\n"; mst_compare_stats(); echo "----\n"; /* master on write is active, master should reply */ $res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); echo "----\n"; mst_compare_stats(); echo "----\n"; /* SQL hint wins */ $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); echo "----\n"; mst_compare_stats(); echo "----\n"; /* master on write is active, master should reply */ $res = mst_mysqli_query(7, $link, "SELECT @myrole AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write... */ $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write... */ $res = mst_mysqli_query(10, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- ---- Stats use_slave: 1 Stats use_slave_sql_hint: 1 Stats lazy_connections_slave_success: 1 ---- This is 'Slave 1' speaking ---- Stats use_slave: 2 Stats use_slave_guess: 1 ---- ---- Stats use_master: 1 Stats use_master_guess: 1 Stats lazy_connections_master_success: 1 ---- This is 'Master 1' speaking ---- Stats use_master: 2 Stats use_slave_guess: 2 ---- This is 'Slave 1' speaking ---- Stats use_slave: 3 Stats use_slave_sql_hint: 2 ---- This is 'Master 1' speaking This is 'Slave 1' speaking This is 'Slave 1' speaking This is 'Master 1' speaking This is 'Master 1' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_on_write_random.phpt0000664000175000017500000000775512161007456024323 0ustar andreyandrey--TEST-- Use master on write (pick = random) --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host, $slave_host, $slave_host), 'master_on_write' => 1, 'pick' => array('random'), 'lazy_connection' => 0 ), ); if ($error = mst_create_config("test_mysqlnd_ms_master_on_write_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_master_on_write_random.ini --FILE-- thread_id] = true; } while (count($slaves) < 4); $res = mst_mysqli_query(3, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* not a select -> master query */ mst_mysqli_query(4, $link, "SET @myrole='Master'"); /* master on write is active, master should reply */ $res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write is active, master should reply */ $res = mst_mysqli_query(7, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(8, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(9, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write is active, master should reply */ $res = mst_mysqli_query(10, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(11, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write... */ $res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write... */ $res = mst_mysqli_query(13, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- This is 'Slave %d' speaking This is 'Master %d' speaking This is 'Slave %d' speaking This is 'Master %d' speaking This is 'Slave %d' speaking This is 'Slave %d' speaking This is 'Master %d' speaking This is 'Slave %d' speaking This is 'Master' speaking This is 'Master' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_on_write_round_robin.phpt0000664000175000017500000001054412161007456025351 0ustar andreyandrey--TEST-- Use master on write (pick = random) --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'master_on_write' => 1, 'pick' => array('roundrobin'), 'lazy_connection' => 0 ), ); if ($error = mst_create_config("test_mysqlnd_ms_master_on_write_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_master_on_write_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- thread_id] = true; } while (count($slaves) < 2); $res = mst_mysqli_query(3, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* not a select -> master query */ mst_mysqli_query(4, $link, "SET @myrole='Master'"); /* master on write is active, master should reply */ $res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); echo "----\n"; mst_compare_stats(); echo "----\n"; /* SQL hint wins */ $res = mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write is active, master should reply */ $res = mst_mysqli_query(7, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(8, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(9, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write is active, master should reply */ $res = mst_mysqli_query(10, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* SQL hint wins */ $res = mst_mysqli_query(11, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write... */ $res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); /* master on write... */ $res = mst_mysqli_query(13, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- This is 'Slave 1 %d' speaking This is 'Master %d' speaking ---- Stats use_slave: 3 Stats use_master: 2 Stats use_slave_guess: 2 Stats use_master_guess: 1 Stats use_slave_sql_hint: 2 Stats lazy_connections_slave_success: 2 Stats lazy_connections_master_success: 1 ---- This is 'Slave 2 %d' speaking This is 'Master %d' speaking This is 'Slave 1 %d' speaking This is 'Slave 1 %d' speaking This is 'Master %d' speaking This is 'Slave 2 %d' speaking This is 'Master' speaking This is 'Master' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_unreachable_random_once.phpt0000664000175000017500000000420112161007456025731 0ustar andreyandrey--TEST-- Unreachable master, pick = random once, lazy = 0 --SKIPIF-- array( 'master' => array("unknown_i_really_hope"), 'slave' => array($slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_master_unreachable_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_master_unreachable_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- close(); print "done!"; ?> --CLEAN-- --EXPECTF-- Stats non_lazy_connections_master_failure: 1 [003] Plugin reports connect error, [200%d] '%s' mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_unreachable_random.phpt0000664000175000017500000000411612161007456024732 0ustar andreyandrey--TEST-- Unreachable master, pick = random, lazy = 0 --SKIPIF-- array( 'master' => array("unknown_i_really_hope"), 'slave' => array($slave_host), 'pick' => array("random"), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_master_unreachable_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_master_unreachable_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- close(); print "done!"; ?> --CLEAN-- --EXPECTF-- Stats non_lazy_connections_master_failure: 1 [003] Plugin reports connect error, [200%d] '%s' mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_unreachable_rr.phpt0000664000175000017500000000410712161007456024075 0ustar andreyandrey--TEST-- Unreachable master, pick = round robin, lazy = 0 --SKIPIF-- array( 'master' => array("unknown_i_really_hope"), 'slave' => array($slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_master_unreachable_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_master_unreachable_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- close(); print "done!"; ?> --CLEAN-- --EXPECTF-- Stats non_lazy_connections_master_failure: 1 [003] Plugin reports connect error, [200%d] '%s' mysqlnd_ms-1.5.2/tests/mysqlnd_ms_master_unreachable_user.phpt0000664000175000017500000000570612161007456024436 0ustar andreyandrey--TEST-- Unreachable master, pick = user, lazy = 0 --SKIPIF-- array( 'master' => array("unknown_i_really_hope"), 'slave' => array($slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("est_mysqlnd_ms_master_unreachable_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=est_mysqlnd_ms_master_unreachable_user.ini mysqlnd_ms.collect_statistics=1 --FILE-- close(); print "done!"; ?> --CLEAN-- --EXPECTF-- Stats non_lazy_connections_master_failure: 1 [003] Plugin reports connect error, [200%d] '%s' mysqlnd_ms-1.5.2/tests/mysqlnd_ms_match_wild.phpt0000664000175000017500000000322612161007456021662 0ustar andreyandrey--TEST-- mysqlnd_ms_match_wild(string table_name, string wildcard) --SKIPIF-- --INI-- mysqlnd_ms.enable=1 --FILE-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_master_no_slaves_ro.phpt0000664000175000017500000000604112161007456025023 0ustar andreyandrey--TEST-- Multi master, no slaves, random once --SKIPIF-- array( /* NOTE: second master will be ignored! */ 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array(), 'failover' => array('strategy' => 'master'), 'pick' => array('random' => array("sticky" => 1)), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_no_slaves_ro.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_no_slaves_ro.ini mysqlnd_ms.multi_master=1 --FILE-- 1) break; } if (100 <= $i) { printf("[004] Random once has choosen the same master for 100 subsequent writes\n"); } /* slaves - reads */ $servers = array(); for ($i = 0; $i <= 100; $i++) { /* ignore warning */ if ((!($res = $link->query("SELECT 1 FROM DUAL"))) && (2000 != $link->errno)) { printf("[005] Wrong connection error, [%d] %s\n", $link->errno, $link->error); /* breaking to keep trace short */ break; } $server_id = mst_mysqli_get_emulated_id(6, $link); if (isset($servers[$server_id])) $servers[$server_id] = $servers[$server_id] + 1; else $servers[$server_id] = 1; if (count($servers) > 1) break; } if (100 <= $i) { printf("[007] Random once has choosen the same server for 100 subsequent reads\n"); } else { printf("[007] Random once has changed server after %d reads\n", $i); } if (!$link->query("SELECT 1 FROM DUAL")) printf("[008] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [004] Random once has choosen the same master for 100 subsequent writes [007] Random once has choosen the same server for 100 subsequent reads done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_master_no_slaves_r.phpt0000664000175000017500000000623012161007456024644 0ustar andreyandrey--TEST-- Multi master, no slaves, random --SKIPIF-- array( /* NOTE: second master will be ignored! */ 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array(), 'pick' => array('random'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_no_slaves_r.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_no_slaves_r.ini mysqlnd_ms.multi_master=1 --FILE-- 1) break; } if (100 <= $i) { printf("[004] Random has choosen the same master for 100 subsequent writes\n"); } /* slaves - reads */ $servers = array(); for ($i = 0; $i <= 100; $i++) { /* ignore warning */ if ((!($res = @$link->query("SELECT 1 FROM DUAL"))) && (2000 != $link->errno)) { printf("[005] Wrong connection error. User should always get same error for same issue, [%d] %s\n", $link->errno, $link->error); /* breaking to keep trace short */ break; } $server_id = mst_mysqli_get_emulated_id(6, $link); if (isset($servers[$server_id])) $servers[$server_id] = $servers[$server_id] + 1; else $servers[$server_id] = 1; if (count($servers) > 1) break; } if (100 <= $i) { printf("[007] Random has choosen the same slave for 100 subsequent reads\n"); } if (!$link->query("SELECT 1 FROM DUAL")) printf("[008] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [007] Random has choosen the same slave for 100 subsequent reads Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [008] [2000] (mysqlnd_ms) No connection selected by the last filter done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_master_no_slaves_rr_nf.phpt0000664000175000017500000000655412161007456025522 0ustar andreyandrey--TEST-- Multi master, no slaves, RR, no failover --SKIPIF-- array( /* NOTE: second master will be ignored! */ 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array(), 'pick' => array('roundrobin'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_no_slaves_rr_nf.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_no_slaves_rr_nf.ini mysqlnd_ms.multi_master=1 --FILE-- $num_queries) { printf("%s has run %d queries\n", $server_id, $num_queries); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [006] [2000] (mysqlnd_ms) No connection selected by the last filter Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [008] [2000] (mysqlnd_ms) No connection selected by the last filter master[1,2]-%d has run 3 queries master[1,2]-%d has run 1 queries done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_master_no_slaves_rr.phpt0000664000175000017500000000541212161007456025027 0ustar andreyandrey--TEST-- Multi master, no slaves, RR --SKIPIF-- array( /* NOTE: second master will be ignored! */ 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array(), 'failover' => array('strategy' => 'master'), 'pick' => array('roundrobin'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_no_slaves_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_no_slaves_rr.ini mysqlnd_ms.multi_master=1 --FILE-- $num_queries) { printf("%s has run %d queries\n", $server_id, $num_queries); } print "done!"; ?> --CLEAN-- --EXPECTF-- master[1,2]-%d has run 2 queries master[1,2]-%d has run 2 queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_master_on.phpt0000664000175000017500000001077112161007456022753 0ustar andreyandrey--TEST-- Multi master enabled --SKIPIF-- array( /* NOTE: second master will be ignored! */ 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($emulated_slave_host), 'pick' => array('roundrobin'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master_on.ini mysqlnd_ms.multi_master=1 --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $servers = array(); /* master 1 */ mst_mysqli_query(3, $link, "SET @myrole='master1'", MYSQLND_MS_MASTER_SWITCH); /* master 2 */ mst_mysqli_query(4, $link, "SET @myrole='master2'", MYSQLND_MS_MASTER_SWITCH); /* master 1 */ $role = fetch_role(6, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 2 */ $role = fetch_role(8, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(9, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* slave 1 */ $role = fetch_role(10, $link); $server_id = mst_mysqli_get_emulated_id(11, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 1 */ $role = fetch_role(12, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(13, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 1 */ $role = fetch_role(14, $link, MYSQLND_MS_LAST_USED_SWITCH); $server_id = mst_mysqli_get_emulated_id(15, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* master 2 */ $role = fetch_role(16, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(17, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); foreach ($servers as $server_id => $roles) { foreach ($roles as $role => $num_queries) { printf("%s (%s) has run %d queries\n", $role, $server_id, $num_queries); } } print "done!"; ?> --CLEAN-- --EXPECTF-- master1 (master[1,2]-%d) has run 3 queries master2 (master[1,2]-%d) has run 2 queries %s(slave-%d) has run 1 queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_master.phpt0000664000175000017500000000572612161007456022263 0ustar andreyandrey--TEST-- Many masters; syntax exists but unsupported! --SKIPIF-- array( /* NOTE: second master will be ignored! */ 'master' => array($master_host, "unreachable"), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_master.ini mysqlnd_ms.multi_master=0 --FILE-- errno, $link->error); $row = $res->fetch_assoc(); if ($link->thread_id != $row['_conn_id']) printf("[007] Expecting thread_id = %d got %d\n", $link->thread_id, $row['_conn_id']); $master[$row['_conn_id']] = (isset($master[$row['_conn_id']])) ? ++$master[$row['_conn_id']] : 1; mst_mysqli_query(8, $link, "DROP TABLE IF EXISTS test"); mst_mysqli_query(9, $link, "CREATE TABLE test(id INT)", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(10, $link, "INSERT INTO test(id) VALUES(1)", MYSQLND_MS_LAST_USED_SWITCH); $res = mst_mysqli_query(11, $link, "SELECT CONNECTION_ID() AS _conn_id", MYSQLND_MS_LAST_USED_SWITCH); if (!$res) printf("[012] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ($link->thread_id != $row['_conn_id']) printf("[013] Expecting thread_id = %d got %d\n", $link->thread_id, $row['_conn_id']); $master[$row['_conn_id']] = (isset($master[$row['_conn_id']])) ? ++$master[$row['_conn_id']] : 1; $res = mst_mysqli_query(14, $link, "SELECT CONNECTION_ID() AS _conn_id", MYSQLND_MS_MASTER_SWITCH); if (!$res) printf("[015] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ($link->thread_id != $row['_conn_id']) printf("[016] Expecting thread_id = %d got %d\n", $link->thread_id, $row['_conn_id']); $master[$row['_conn_id']] = (isset($master[$row['_conn_id']])) ? ++$master[$row['_conn_id']] : 1; foreach ($master as $id => $num_queries) { printf("Master %d has run %d queries\n", $id, $num_queries); } print "done!"; ?> --CLEAN-- --EXPECTF-- Master %d has run %d queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_query_no_ms.phpt0000664000175000017500000000412312161007456023316 0ustar andreyandrey--TEST-- multi query (set server option) wo ms --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_query_no_ms.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_query_no_ms.ini --FILE-- multi_query($query))) printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); return $ret; } if (!($link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* Hints will be ignored */ mst_mysqli_query(2, $link, "SET @myrole='Slave 1'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(4, $link, "SET @myrole='Master 1'"); mst_mysqli_query(5, $link, "SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL"); do { if ($res = $link->store_result()) { $row = $res->fetch_assoc(); printf("%s", $row['_msg']); $res->free(); } } while ($link->more_results() && $link->next_result()); echo "\n"; print "done!"; ?> --CLEAN-- --EXPECTF-- [002] /*ms=slave*/SET @myrole='Slave 1' [004] SET @myrole='Master 1' [005] SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL This is Master 1 speaking! done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_multi_query.phpt0000664000175000017500000000522612161007456022130 0ustar andreyandrey--TEST-- multi query --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_multi_query.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_multi_query.ini --FILE-- multi_query($query))) printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); return $ret; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); mst_mysqli_query(2, $link, "SET @myrole='Slave 1'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(3, $link, "SET @myrole='Slave 2'", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(4, $link, "SET @myrole='Master 1'"); /* slave 1 */ mst_mysqli_query(5, $link, "SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL"); do { if ($res = $link->store_result()) { $row = $res->fetch_assoc(); printf("%s", $row['_msg']); $res->free(); } } while ($link->more_results() && $link->next_result()); echo "\n"; /* slave 2 */ mst_mysqli_query(6, $link, "SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL"); do { if ($res = $link->store_result()) { $row = $res->fetch_assoc(); printf("%s", $row['_msg']); $res->free(); } } while ($link->more_results() && $link->next_result()); echo "\n"; /* master */ mst_mysqli_query(7, $link, "SELECT 'This is ' AS _msg FROM DUAL; SELECT @myrole AS _msg; SELECT ' speaking!' AS _msg FROM DUAL", MYSQLND_MS_MASTER_SWITCH); do { if ($res = $link->store_result()) { $row = $res->fetch_assoc(); printf("%s", $row['_msg']); $res->free(); } } while ($link->more_results() && $link->next_result()); echo "\n"; print "done!"; ?> --CLEAN-- --EXPECTF-- This is Slave 1 speaking! This is Slave 2 speaking! This is Master 1 speaking! done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_no_master.phpt0000664000175000017500000000230412161007456021532 0ustar andreyandrey--TEST-- No master configured --SKIPIF-- array( 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_no_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_no_master.ini --FILE-- query("DROP TABLE IF EXISTS test")) { printf("[002] [%d] %s\n", $link->errno, $link->error); } } print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Section [master] doesn't exist for host [name_of_a_config_section] in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_no_slaves.phpt0000664000175000017500000000250612161007456021540 0ustar andreyandrey--TEST-- No slaves given in config -> connect error --SKIPIF-- array( 'master' => array($master_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_no_slaves.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_no_slaves.ini --FILE-- query("SELECT 'Who runs this?'"))) { printf("[002] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_row(); printf("[003] %s\n", $row[0]); } } print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Section [slave] doesn't exist for host [name_of_a_config_section] in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_pdo_autocommit.phpt0000664000175000017500000000606612161007456022577 0ustar andreyandrey--TEST-- PDO::ATTR_AUTOCOMMIT --SKIPIF-- array( 'master' => array( "master_0" => array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'master', 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pdo_attr_autocommit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pdo_attr_autocommit.ini --FILE-- exec(sprintf("SET @myrole='master'")); $pdo->exec(sprintf("/*%s*/SET @myrole='slave1'", MYSQLND_MS_SLAVE_SWITCH)); $pdo->exec(sprintf("/*%s*/SET @myrole='slave2'", MYSQLND_MS_SLAVE_SWITCH)); /* slave 1 */ $stmt = $pdo->prepare("SELECT @myrole AS _role"); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result[0]['_role']); $stmt = $pdo->prepare("SELECT @myrole AS _role"); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result[0]['_role']); /* master */ $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, false); $stmt = $pdo->prepare("SELECT @myrole AS _role"); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result[0]['_role']); /* slave1 */ $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, true); $stmt = $pdo->prepare("SELECT @myrole AS _role"); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result[0]['_role']); } catch (Exception $e) { printf("[001] %s\n", $e->__toString()); } } /* $options = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => true); */ $options = array(PDO::ATTR_EMULATE_PREPARES => false, ); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); $options = array(PDO::ATTR_EMULATE_PREPARES => false); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); print "done!"; ?> --CLEAN-- --EXPECTF-- string(6) "slave1" string(6) "slave2" string(6) "master" string(6) "slave1" string(6) "slave1" string(6) "slave2" string(6) "master" string(6) "slave1" done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pdo_basics.phpt0000664000175000017500000000753512161007456021664 0ustar andreyandrey--TEST-- PDO Basics --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pdo_basics.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pdo_basics.ini --FILE-- query("SELECT 1 AS _one"); $result_slave = $stmt->fetchAll(PDO::FETCH_ASSOC); var_dump($result_slave); $stmt = $pdo->query(sprintf("/*%s*/SELECT 1 AS _one", MYSQLND_MS_MASTER_SWITCH)); $result_master = $stmt->fetchAll(PDO::FETCH_ASSOC); if ($result_master != $result_slave) { printf("[001] Master and slave data differ, dumping\n"); var_dump($result_master); var_dump($result_slave); } /* PDO::exec() */ $pdo = $pdo = my_pdo_connect($host, $user, $passwd, $db, $port, $socket, $options); $pdo->exec(sprintf("/*%s*/SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH)); $pdo->exec(sprintf("/*%s*/SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH)); /* PDO::prepare() */ $stmt = $pdo->prepare("SELECT @myrole AS _role, ?"); $stmt->execute(array("poor guy")); $result = $stmt->fetch(PDO::FETCH_ASSOC); var_dump($result); $stmt = $pdo->prepare(sprintf("/*%s*/SELECT @myrole AS _role, ?", MYSQLND_MS_MASTER_SWITCH)); $stmt->execute(array("not so poor guy")); $result = $stmt->fetch(PDO::FETCH_ASSOC); var_dump($result); $stmt = $pdo->prepare(sprintf("/*%s*/SELECT @myrole AS _role, ?", MYSQLND_MS_LAST_USED_SWITCH)); $stmt->execute(array("rich guy")); $result = $stmt->fetch(PDO::FETCH_ASSOC); var_dump($result); $pdo->exec(sprintf("DROP TABLE IF EXISTS test")); $pdo->exec(sprintf("CREATE TABLE test(id INT)")); var_dump($pdo->exec(sprintf("INSERT INTO test(id) VALUES (1)"))); var_dump($pdo->query(sprintf("/*%s*/SELECT * FROM test", MYSQLND_MS_MASTER_SWITCH))->fetch(PDO::FETCH_ASSOC)); var_dump($pdo->exec(sprintf("DROP TABLE IF EXISTS test"))); } catch (Exception $e) { printf("[001] %s\n", $e->__toString()); } } /* $options = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => true); */ $options = array(PDO::ATTR_EMULATE_PREPARES => true); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); $options = array(PDO::ATTR_EMULATE_PREPARES => false); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { ["_one"]=> string(1) "1" } } array(2) { ["_role"]=> string(5) "slave" ["poor guy"]=> string(8) "poor guy" } array(2) { ["_role"]=> string(6) "master" ["not so poor guy"]=> string(15) "not so poor guy" } array(2) { ["_role"]=> string(6) "master" ["rich guy"]=> string(8) "rich guy" } int(1) array(1) { ["id"]=> string(1) "1" } int(0) array(1) { [0]=> array(1) { ["_one"]=> %s1%s } } array(2) { ["_role"]=> string(5) "slave" ["?"]=> string(8) "poor guy" } array(2) { ["_role"]=> string(6) "master" ["?"]=> string(15) "not so poor guy" } array(2) { ["_role"]=> string(6) "master" ["?"]=> string(8) "rich guy" } int(1) array(1) { ["id"]=> int(1) } int(0) done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pdo_begin_trx.phpt0000664000175000017500000000416112161007456022371 0ustar andreyandrey--TEST-- PDO::beginTransaction --SKIPIF-- array( 'master' => array( "master_0" => array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password' => $passwd, ), "master_1" => array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'slave' => array(), 'failover' => array('strategy' => 'master'), ), ); if ($error = mst_create_config("test_pdo_begin_trx.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_pdo_begin_trx.ini mysqlnd_ms.multi_master=1 mysqlnd_ms.disable_rw_split=1 --FILE-- beginTransaction(); $ret = $pdo->query("SELECT @@hostname AS _hostname"); $row = $ret->fetch(PDO::FETCH_ASSOC); var_dump($row['_hostname']); $pdo->commit(); } catch (Exception $e) { printf("[001] %s\n", $e->__toString()); } } $options = array(PDO::ATTR_EMULATE_PREPARES => true); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); $options = array(PDO::ATTR_EMULATE_PREPARES => false); test_pdo("myapp", $user, $passwd, $db, $port, $socket, $options); print "done!"; ?> --CLEAN-- --EXPECTF-- string(%d) "%s" string(%d) "%s" done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_phpinfo.phpt0000664000175000017500000000075512161007456021216 0ustar andreyandrey--TEST-- phpinfo() section --SKIPIF-- --INI-- mysqlnd_ms.enable=1 --FILE-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_once2.phpt0000664000175000017500000000546412161007456023131 0ustar andreyandrey--TEST-- Load Balancing: random_once (slaves) --SKIPIF-- array( 'pick' => array('random' => array('sticky' => true)), 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_once2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_once2.ini --FILE-- sprintf("Slave %d", count($emulated_slaves) + 1), 'queries' => 0); } else { $emulated_slaves[$id]['queries']++; } } foreach ($emulated_slaves as $thread => $details) { printf("%s (%s) has run %d queries.\n", $details['role'], $thread, $details['queries']); } print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1 (%s) has run 100 queries. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_once.phpt0000664000175000017500000000600412161007456023036 0ustar andreyandrey--TEST-- Load Balancing: random_once (slaves) --SKIPIF-- array( 'pick' => array('random' => array('sticky' => '1')), 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host, $emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2,3]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_once.ini --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* first master */ mst_mysqli_query(2, $link, "SET @myrole = 'Master 1'", MYSQLND_MS_MASTER_SWITCH); $emulated_master = mst_mysqli_get_emulated_id(3, $link); $emulated_slaves = array(); $num_queries = 100; for ($i = 0; $i <= $num_queries; $i++) { mst_mysqli_query(4, $link, "SELECT 1"); $id = mst_mysqli_get_emulated_id(5, $link); if (!isset($emulated_slaves[$id])) { $emulated_slaves[$id] = array('role' => sprintf("Slave %d", count($emulated_slaves) + 1), 'queries' => 0); } else { $emulated_slaves[$id]['queries']++; } if ($id == $emulated_master) printf("[006] Master and slave use the same connection!\n"); if (mt_rand(0, 10) > 9) { /* switch to master to check if next read goes to same slave */ mst_mysqli_query(7, $link, "DROP TABLE IF EXISTS test"); } } foreach ($emulated_slaves as $thread => $details) { printf("%s (%s) has run %d queries.\n", $details['role'], $thread, $details['queries']); } print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1 (%s) has run 100 queries. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random.phpt0000664000175000017500000001053612161007456022037 0ustar andreyandrey--TEST-- Load Balancing: random (slaves) --SKIPIF-- array( 'pick' => array('random'), 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host, $emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2,3]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random.ini --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* first master */ mst_mysqli_query(2, $link, "SET @myrole = 'Master 1'", MYSQLND_MS_MASTER_SWITCH); $emulated_slaves = array(); do { mst_mysqli_query(3, $link, "SELECT 1"); $server_id = mst_mysqli_get_emulated_id(4, $link); if (!isset($emulated_slaves[$server_id])) { $emulated_slaves[$server_id] = array('role' => sprintf("Slave %d", count($emulated_slaves) + 1), 'queries' => 0); } } while (count($emulated_slaves) < 3); $sequences = array(); $num_queries = 1000; for ($i = 0; $i < $num_queries; $i+=3) { mst_mysqli_query(5, $link, "SELECT 1"); $server_id = mst_mysqli_get_emulated_id(6, $link); $emulated_slaves[$server_id]['queries']++; $sequence_id = $server_id; mst_mysqli_query(7, $link, "SELECT 1"); $server_id = mst_mysqli_get_emulated_id(8, $link); $emulated_slaves[$server_id]['queries']++; $sequence_id .= $server_id; mst_mysqli_query(9, $link, "SELECT 1"); $server_id = mst_mysqli_get_emulated_id(10, $link); $emulated_slaves[$server_id]['queries']++; $sequence_id .= $server_id; if (!isset($sequences[$sequence_id])) $sequences[$sequence_id] = 1; else $sequences[$sequence_id]++; } if (count($sequences) == 1) printf("[011] Slaves are always called in the same order, does not look like random\n"); $min = ($num_queries / 3) * 0.5; $max = ($num_queries / 3) * 2; foreach ($emulated_slaves as $thread => $details) { printf("%s (%s) has run %d queries.\n", $details['role'], $thread, $details['queries']); if ($details['queries'] < $min) { printf("[008] %s (%s) has run less queries (%d) than expected (> %d), check manually.\n", $details['role'], $thread, $details['queries'], $min); } if ($details['queries'] > $max) { printf("[009] %s (%s) has run more queries (%d) than expected (< %d), check manually.\n", $details['role'], $thread, $details['queries'], $max); } } print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1 (%s) has run %d queries. Slave 2 (%s) has run %d queries. Slave 3 (%s) has run %d queries. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_user_multi_no_master_non_lazy.phpt0000664000175000017500000000427612161007456030273 0ustar andreyandrey--TEST-- Random, user multi, no master, non lazy --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_user_multi_no_master_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_user_multi_no_master_non_lazy.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. 0 masters to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_user_multi_no_master.phpt0000664000175000017500000000422012161007456026347 0ustar andreyandrey--TEST-- Random, user multi, no master --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_user_multi_no_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_user_multi_no_master.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. 0 masters to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_user_multi_no_slave_non_lazy.phpt0000664000175000017500000000420312161007456030100 0ustar andreyandrey--TEST-- Random, user multi, no master, non lazy --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connection' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_user_multi_no_slave_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_user_multi_no_slave_non_lazy.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_user_multi_no_slave.phpt0000664000175000017500000000412512161007456026172 0ustar andreyandrey--TEST-- Random, user multi, no master --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connection' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_user_multi_no_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_user_multi_no_slave.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_user_multi_slave_err.phpt0000664000175000017500000000427412161007456026353 0ustar andreyandrey--TEST-- Random, user multi, slave list error --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_user_multi_no_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_user_multi_no_slave.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has returned an invalid list of servers to use. The callback must return an array in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line %d mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_weight_list_length_error2.phpt0000664000175000017500000000427612161007456027301 0ustar andreyandrey--TEST-- Round robin, weights, less weights than servers --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), ), 'pick' => array('random' => array("weights" => array("slave1" => 8, "master1" => 3))), 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_weight_list_length_error2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_weight_list_length_error2.ini --FILE-- --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) You must specify the load balancing weight for none or all configured servers. There is no default weight yet. Stopping in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_weight_list_length_error.phpt0000664000175000017500000000424312161007456027211 0ustar andreyandrey--TEST-- Round robin, weights, more weights than servers --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), ), 'pick' => array('random' => array("weights" => array("slave1" => 8, "slave2" => 4, "slave3" => 1, "master1" => 3))), 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_weight_list_length_error.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_weight_list_length_error.ini --FILE-- --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Unknown server 'slave3' in 'random' filter configuration. Stopping in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_weight_master_fail_loop.phpt0000664000175000017500000000545312161007456027007 0ustar andreyandrey--TEST-- Round robin, weights, master w failure --SKIPIF-- array( 'slave' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'master' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave3" => array( 'host' => "lalala", 'port' => 0, 'socket' => "/kein/anschluss/unter/dieser.nummer" ), ), 'pick' => array('random' => array("weights" => array("slave1" => 8, "slave2" => 4, "slave3" => 1, "master1" => 3))), 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_weight_master_fail_loop.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_weight_master_fail_loop.ini mysqlnd_ms.multi_master=1 mysqlnd_ms.disable_rw_split=1 --FILE-- fetch_assoc(); if (!isset($servers[$row['_id']])) { $servers[$row['_id']] = 1; } else { $servers[$row['_id']]++; } } arsort($servers); $last_used = 0; foreach ($servers as $conn_id => $used) { printf("%04d - %d\n", $conn_id, $used); if ($last_used && (($used * 1.2) > $last_used)) { printf("[002] Validate manually, could be falst positive as its random - last_used %d used %d\n", $last_used, $used); } $last_used = $used; } print "done!"; ?> --CLEAN-- --EXPECTF-- %d - %d %d - %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_weight.phpt0000664000175000017500000000513212161007456023402 0ustar andreyandrey--TEST-- Round robin, weights --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave3" => array( 'host' => "lalala", 'port' => 0, 'socket' => "/kein/anschluss/unter/dieser.nummer" ), ), 'pick' => array('random' => array("weights" => array("slave1" => 8, "slave2" => 4, "slave3" => 1, "master1" => 3))), 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_weight.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_weight.ini --FILE-- query("SELECT CONNECTION_ID() AS _id FROM DUAL")->fetch_assoc(); if (!isset($servers[$row['_id']])) { $servers[$row['_id']] = 1; } else { $servers[$row['_id']]++; } } arsort($servers); $last_used = 0; foreach ($servers as $conn_id => $used) { printf("%04d - %d\n", $conn_id, $used); if ($last_used && (($used * 1.2) > $last_used)) { printf("[002] Validate manually, could be false positive as it is random - last_used %d used %d\n", $last_used, $used); } $last_used = $used; } print "done!"; ?> --CLEAN-- --EXPECTF-- %d - %d %d - %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_random_weight_range.phpt0000664000175000017500000000460712161007456024564 0ustar andreyandrey--TEST-- Round robin, weights, more weights than servers --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), ), 'pick' => array('random' => array("weights" => array("slave1" => -1, "slave2" => 65536, "master1" => 0))), 'failover' => array('strategy' => 'loop_before_master', 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_random_weight_range.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_random_weight_range.ini --FILE-- --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Invalid value '-1' for weight. Stopping in %s on line %d [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Invalid value '65536' for weight. Stopping in %s on line %d [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) You must specify the load balancing weight for none or all configured servers. There is no default weight yet. Stopping in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_round_robin.phpt0000664000175000017500000001042012161007456023067 0ustar andreyandrey--TEST-- Round robin load balancing --SKIPIF-- array( 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array('roundrobin'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_round_robin.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_round_robin.ini --FILE-- errno, $link->error); return NULL; } $row = $res->fetch_assoc(); return $row['_role']; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); /* first master */ mst_mysqli_query(2, $link, "SET @myrole = 'Master 1'", MYSQLND_MS_MASTER_SWITCH); /* second master */ mst_mysqli_query(3, $link, "SET @myrole = 'Master 2'", MYSQLND_MS_MASTER_SWITCH); /* pick first in row */ mst_mysqli_query(4, $link, "SET @myrole = 'Slave 1'", MYSQLND_MS_SLAVE_SWITCH); /* move to second in row */ mst_mysqli_query(5, $link, "SET @myrole = 'Slave 2'", MYSQLND_MS_SLAVE_SWITCH); $servers = array(); /* wrap around to first slave */ $role = fetch_role(6, $link); $server_id = mst_mysqli_get_emulated_id(7, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* move forward to second slave */ $role = fetch_role(8, $link); $server_id = mst_mysqli_get_emulated_id(9, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* wrap around to first master */ $role = fetch_role(10, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(11, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); /* move forward to the second master */ $role = fetch_role(12, $link, MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(13, $link); if (isset($servers[$server_id][$role])) $servers[$server_id][$role] = $servers[$server_id][$role] + 1; else $servers[$server_id] = array($role => 1); foreach ($servers as $server_id => $roles) { foreach ($roles as $role => $num_queries) { printf("%s (%s) has run %d queries\n", $role, $server_id, $num_queries); } } print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1 (%s) has run 1 queries Slave 2 (%s) has run 1 queries Master 2 (%s) has run 2 queries done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_round_robin_weight_loop.phpt0000664000175000017500000001034212161007456025472 0ustar andreyandrey--TEST-- Round robin, weights, loop before master --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave3" => array( 'host' => 'kielerwoche', 'port' => '123', 'socket'=> 'free_concerts_but_no_free_beer', ), ), 'pick' => array('roundrobin' => array("weights" => array("slave1" => 1, "slave2" => 2, "slave3" => 1, "master1" => 3))), 'failover' => array('strategy' => 'loop_before_master', "remember_failed" => true, 'max_retries' => 0), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_round_robin_weight_loop.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_round_robin_weight_loop.ini --FILE-- query($sql)->fetch_assoc(); if (is_null($last_id)) { $last_id = $row['_id']; } if (!isset($usage[$row['_id']])) { $usage[$row['_id']] = 1; } else { $usage[$row['_id']]++; } printf("Call %d - %d - %d - ", ++$calls, $row['_id'], $usage[$row['_id']]); if ($row['_id'] == $last_id) { print " no change\n"; } else { print " change\n"; } $last_id = $row['_id']; return $last_id; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); print "done!"; ?> --CLEAN-- --EXPECTF-- Call 1 - %d - 1 - no change Call 2 - %d - 1 - change Call 3 - %d - 2 - change Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %A Call 4 - %d - 3 - no change Call 5 - %d - 4 - no change Call 6 - %d - 2 - change Call 7 - %d - 5 - change Call 8 - %d - 6 - no change Call 9 - %d - 7 - no change Call 10 - %d - 3 - change Call 11 - %d - 8 - change done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_round_robin_weight_master.phpt0000664000175000017500000001211412161007456026013 0ustar andreyandrey--TEST-- Round robin, weights (master list) --SKIPIF-- array( 'slave' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'master' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), ), 'pick' => array('roundrobin' => array("weights" => array("slave1" => 1, "slave2" => 4, "master1" => 3))), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_round_robin_weight_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_round_robin_weight_master.ini mysqlnd_ms.disable_rw_split=1 mysqlnd_ms.multi_master=1 --FILE-- query($sql)->fetch_assoc(); if (is_null($last_id)) { $last_id = $row['_id']; } if (!isset($usage[$row['_id']])) { $usage[$row['_id']] = 1; } else { $usage[$row['_id']]++; } printf("Call %d - %d - %d - ", ++$calls, $row['_id'], $usage[$row['_id']]); if ($row['_id'] == $last_id) { print " no change\n"; } else { print " change\n"; } $last_id = $row['_id']; return $last_id; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); /* testing slave access is not possible - would go to master */ monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); printf("%s\n", str_repeat("-", 60)); /* restart the game */ if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); monitor_connection_id($link); monitor_connection_id($link); $last_id = monitor_connection_id($link); /* which node will be used? */ mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); $node_id = monitor_connection_id($link, MYSQLND_MS_LAST_USED_SWITCH); if ($last_id != $node_id) { printf("[005] Servers switched from %d to %d\n", $last_id, $node_id); } monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); print "done!"; ?> --CLEAN-- --EXPECTF-- Call 1 - %d - 1 - no change Call 2 - %d - 2 - no change Call 3 - %d - 3 - no change Call 4 - %d - 1 - change Call 5 - %d - 4 - change Call 6 - %d - 2 - change Call 7 - %d - 5 - change Call 8 - %d - 6 - no change Call 9 - %d - 7 - no change Call 10 - %d - 3 - change Call 11 - %d - 8 - change ------------------------------------------------------------ Call 12 - %d - 1 - change Call 13 - %d - 2 - no change Call 14 - %d - 3 - no change Call 15 - %d - 4 - no change Call 16 - %d - 1 - change Call 17 - %d - 5 - change Call 18 - %d - 2 - change Call 19 - %d - 6 - change Call 20 - %d - 7 - no change done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_round_robin_weight.phpt0000664000175000017500000001201112161007456024434 0ustar andreyandrey--TEST-- Round robin, weights --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket ), ), 'pick' => array('roundrobin' => array("weights" => array("slave1" => 1, "slave2" => 4, "master1" => 3))), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_round_robin_weight.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1,2]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_round_robin_weight.ini --FILE-- query($sql)->fetch_assoc(); if (is_null($last_id)) { $last_id = $row['_id']; } if (!isset($usage[$row['_id']])) { $usage[$row['_id']] = 1; } else { $usage[$row['_id']]++; } printf("Call %d - %d - %d - ", ++$calls, $row['_id'], $usage[$row['_id']]); if ($row['_id'] == $last_id) { print " no change\n"; } else { print " change\n"; } $last_id = $row['_id']; return $last_id; } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); /* can a master access fool us? */ mst_mysqli_query(2, $link, "DROP TABLE IF EXISTS test"); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); printf("%s\n", str_repeat("-", 60)); /* restart the game */ if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); monitor_connection_id($link); monitor_connection_id($link); $last_id = monitor_connection_id($link); /* which node will be used? */ mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); $node_id = monitor_connection_id($link, MYSQLND_MS_LAST_USED_SWITCH); if ($last_id != $node_id) { printf("[005] Servers switched from %d to %d\n", $last_id, $node_id); } monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); monitor_connection_id($link); print "done!"; ?> --CLEAN-- --EXPECTF-- Call 1 - %d - 1 - no change Call 2 - %d - 2 - no change Call 3 - %d - 3 - no change Call 4 - %d - 1 - change Call 5 - %d - 4 - change Call 6 - %d - 2 - change Call 7 - %d - 5 - change Call 8 - %d - 6 - no change Call 9 - %d - 7 - no change Call 10 - %d - 3 - change Call 11 - %d - 8 - change ------------------------------------------------------------ Call 12 - %d - 1 - change Call 13 - %d - 2 - no change Call 14 - %d - 3 - no change Call 15 - %d - 4 - no change Call 16 - %d - 1 - change Call 17 - %d - 5 - change Call 18 - %d - 2 - change Call 19 - %d - 6 - change Call 20 - %d - 7 - no change done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_ro_user_multi_no_master_non_lazy.phpt0000664000175000017500000000446112161007456027427 0ustar andreyandrey--TEST-- RO, user multi, no master, non lazy --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array('sticky' => '1'), ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), 'lazy_connections' => 0 ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_ro_user_multi_no_master_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_ro_user_multi_no_master_non_lazy.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has returned an invalid list of servers to use. The callback must return an array in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_ro_user_multi_no_master.phpt0000664000175000017500000000421412161007456025512 0ustar andreyandrey--TEST-- RO, user multi, no master --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array('sticky' => '1'), ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_ro_user_multi_no_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_ro_user_multi_no_master.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. 0 masters to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_ro_user_multi_no_slave_non_lazy.phpt0000664000175000017500000000417312161007456027246 0ustar andreyandrey--TEST-- RO, user multi, no slave, non lazy --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array("sticky" => 1) ), 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connection' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_ro_user_multi_no_slave_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_ro_user_multi_no_slave_non_lazy.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_ro_user_multi_no_slave.phpt0000664000175000017500000000411512161007456025331 0ustar andreyandrey--TEST-- RO, user multi, no slave --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array("sticky" => 1) ), 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connection' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_ro_user_multi_no_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_ro_user_multi_no_slave.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_ro_user_multi_slave_killed.phpt0000664000175000017500000000650612161007456026167 0ustar andreyandrey--TEST-- RO, user multi, slave killed --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array('sticky' => '1'), ), 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_ro_user_multi_slave_removed.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_ro_user_multi_slave_removed.ini --FILE-- call %d\n", ++$calls); $last_used = $last_used_connection; $servers = array(array(), array()); foreach ($masters as $k => $master) $servers[0][] = $k; foreach ($slaves as $k => $slave) $servers[1][] = $k; foreach ($connections as $server_id => $thread_id) { if (!$link->kill($thread_id)) { printf("[002] [%d] %s\n", $link->errno, $link->error); } } printf("<- %d master, %d slaves\n", count($servers[0]), count($servers[1])); return $servers; } $connections = array(); if (!$link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket)) printf("[001][%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if ($res = mst_mysqli_query(3, $link, "SELECT 3 FROM DUAL")) var_dump($res->fetch_assoc()); $server_id = mst_mysqli_get_emulated_id(4, $link); $connections[$server_id] = $link->thread_id; if ($res = mst_mysqli_query(5, $link, "SELECT 5 FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH)) var_dump($res->fetch_assoc()); $connections = array(); $server_id = mst_mysqli_get_emulated_id(6, $link); $connections[$server_id] = $link->thread_id; print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*3*/SELECT 3 FROM DUAL, '', 1, 2) -> call 1 <- 1 master, 2 slaves array(1) { [3]=> string(1) "3" } pick_server('myapp', '/*ms=last_used*//*4*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s', 1, 2) -> call 2 <- 1 master, 2 slaves pick_server('myapp', '/*ms=last_used*//*5*/SELECT 5 FROM DUAL, '%s', 1, 2) -> call 3 <- 1 master, 2 slaves [005] [2006] %s pick_server('myapp', '/*ms=last_used*//*6*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s', 1, 2) -> call 4 <- 1 master, 2 slaves [006] [2006] %s done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_ro_user_multi_slave_removed.phpt0000664000175000017500000001227012161007456026357 0ustar andreyandrey--TEST-- RO, user multi, slave removed --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array('sticky' => '1'), ), 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_ro_user_multi_slave_removed.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_ro_user_multi_slave_removed.ini --FILE-- call %d\n", ++$calls); if ($last_used && $last_used_connection && ($last_used == $last_used_connection)) printf("[002] Last used connection has not changed\n"); $last_used = $last_used_connection; $servers = array(array(), array()); foreach ($masters as $k => $master) $servers[0][] = $k; foreach ($slaves as $k => $slave) if ($slave != $last_used_connection) $servers[1][] = $k; printf("<- %d master, %d slaves\n", count($servers[0]), count($servers[1])); return $servers; } if (!$link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket)) printf("[001][%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); if ($res = mst_mysqli_query(3, $link, "SELECT 3 FROM DUAL")) var_dump($res->fetch_assoc()); if ($res = mst_mysqli_query(4, $link, "SELECT 4 FROM DUAL")) var_dump($res->fetch_assoc()); if ($res = mst_mysqli_query(5, $link, "SELECT 5 FROM DUAL")) var_dump($res->fetch_assoc()); if ($res = mst_mysqli_query(6, $link, "SELECT 6 FROM DUAL")) var_dump($res->fetch_assoc()); $last_used = mst_mysqli_get_emulated_id(7, $link); if ($res = mst_mysqli_query(8, $link, "SELECT 8 FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH)) var_dump($res->fetch_assoc()); $server_id = mst_mysqli_get_emulated_id(9, $link); if ($server_id != $last_used) printf("[010] Server changed from %s to %s\n"); $last_used = $server_id; if ($res = mst_mysqli_query(11, $link, "SELECT 8 FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH)) var_dump($res->fetch_assoc()); $server_id = mst_mysqli_get_emulated_id(12, $link); if ($server_id != $last_used) printf("[013] Server changed from %s to %s\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*3*/SELECT 3 FROM DUAL, '', 1, 2) -> call 1 <- 1 master, 2 slaves array(1) { [3]=> string(1) "3" } pick_server('myapp', '/*4*/SELECT 4 FROM DUAL, '%s', 1, 2) -> call 2 <- 1 master, 1 slaves array(1) { [4]=> string(1) "4" } pick_server('myapp', '/*5*/SELECT 5 FROM DUAL, '%s', 1, 2) -> call 3 <- 1 master, 1 slaves array(1) { [5]=> string(1) "5" } pick_server('myapp', '/*6*/SELECT 6 FROM DUAL, '%s', 1, 2) -> call 4 <- 1 master, 1 slaves array(1) { [6]=> string(1) "6" } pick_server('myapp', '/*ms=last_used*//*7*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s', 1, 2) -> call 5 <- 1 master, 1 slaves pick_server('myapp', '/*ms=last_used*//*8*/SELECT 8 FROM DUAL, '%s', 1, 2) -> call 6 [002] Last used connection has not changed <- 1 master, 1 slaves array(1) { [8]=> string(1) "8" } pick_server('myapp', '/*ms=last_used*//*9*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s', 1, 2) -> call 7 [002] Last used connection has not changed <- 1 master, 1 slaves pick_server('myapp', '/*ms=last_used*//*11*/SELECT 8 FROM DUAL, '%s', 1, 2) -> call 8 [002] Last used connection has not changed <- 1 master, 1 slaves array(1) { [8]=> string(1) "8" } pick_server('myapp', '/*ms=last_used*//*12*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s', 1, 2) -> call 9 [002] Last used connection has not changed <- 1 master, 1 slaves done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_rr_user_multi_no_master_non_lazy.phpt0000664000175000017500000000444612161007456027435 0ustar andreyandrey--TEST-- RR, user multi, no master, non-lazy --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "roundrobin" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_rr_user_multi_no_master_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_rr_user_multi_no_master_non_lazy.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has returned an invalid list of servers to use. The callback must return an array in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_rr_user_multi_no_master.phpt0000664000175000017500000000420212161007456025512 0ustar andreyandrey--TEST-- RR, user multi, no master --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "roundrobin" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_rr_user_multi_no_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_rr_user_multi_no_master.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. 0 masters to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_rr_user_multi_no_slave_non_lazy.phpt0000664000175000017500000000416412161007456027251 0ustar andreyandrey--TEST-- RR, user multi, no master, non slave --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "roundrobin" => array() ), 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connection' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_rr_user_multi_no_slave_non_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_rr_user_multi_no_slave_non_lazy.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_rr_user_multi_no_slave.phpt0000664000175000017500000000410412161007456025332 0ustar andreyandrey--TEST-- RR, user multi, no slave --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "roundrobin" => array() ), 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connection' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_rr_user_multi_no_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_rr_user_multi_no_slave.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line 16mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_unknown_policy.phpt0000664000175000017500000000246212161007456023634 0ustar andreyandrey--TEST-- Unknwon filter --SKIPIF-- array( 'pick' => array('unknown'), 'master' => array($master_host), 'slave' => array($slave_host, $slave_host, $slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_unknown_policy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_unknown_policy.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'unknown' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter 'unknown' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_complex.phpt0000664000175000017500000002233312161007456023262 0ustar andreyandrey--TEST-- Config settings: pick = user --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $settings = array( "myapp" => array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_complex.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_complex.ini --FILE-- %s\n", $query, $server); $pick_server_last_used = $ret; return $ret; } function my_mysqli_query($offset, $link, $query, $expected) { global $queries; $queries[$query] = $query; if (!$res = $link->query($query)) { printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); return false; } if ($expected) { $row = $res->fetch_assoc(); $res->close(); if (empty($row)) { printf("[%03d + 02] [%d] %s, empty result\n", $offset, $link->errno, $link->error); return false; } if ($row != $expected) { printf("[%03d + 03] Unexpected results, dumping data\n", $offset); var_dump($row); var_dump($expected); return false; } } return true; } function check_master_slave_threads($offset, $threads) { if (isset($threads["slave"]) && isset($threads["master"])) { foreach ($threads["slave"] as $server_id => $num_queries) { if (isset($threads["master"][$server_id])) { printf("[%03d + 01] Slave connection thread=%s is also a master connection!\n", $offset, $server_id); unset($threads["slave"][$server_id]); } } foreach ($threads["master"] as $server_id => $num_queries) { if (isset($threads["slave"][$server_id])) { printf("[%03d + 02] Master connection thread=%s is also a slave connection!\n", $offset, $server_id); } } } } $threads = array(); if (!$link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket)) printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket); $autocommit = true; $link->autocommit($autocommit); /* Should go to the first slave */ $query = "SELECT 'Master Andrey has send this query to a slave.' AS _message FROM DUAL"; $expected = array('_message' => 'Master Andrey has send this query to a slave.'); my_mysqli_query(20, $link, $query, $expected); $server_id = mst_mysqli_get_emulated_id(21, $link); if (!isset($threads["slave"][$server_id])) { $threads["slave"][$server_id] = 1; } else { $threads["slave"][$server_id]++; } check_master_slave_threads(30, $threads); /* Should go to the first master */ $query = sprintf("/*%s*/SELECT 'master' AS _message FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $expected = array('_message' => 'master'); my_mysqli_query(40, $link, $query, $expected); $server_id = mst_mysqli_get_emulated_id(41, $link); if (!isset($threads["master"][$server_id])) { $threads["master"][$server_id] = 1; } else { $threads["master"][$server_id]++; } check_master_slave_threads(50, $threads); /* Should go to the first master */ $query = sprintf("/*%s*/SELECT 'master' AS _message FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $expected = array('_message' => 'master'); my_mysqli_query(60, $link, $query, $expected); $server_id = mst_mysqli_get_emulated_id(61, $link); if (!isset($threads["master"][$server_id])) { $threads["master"][$server_id] = 1; } else { $threads["master"][$server_id]++; } check_master_slave_threads(70, $threads); if ($threads["master"][$server_id] != 2) { printf("[071] Master should have run 2 queries, records report %d\n", $threads["master"][$serverid]); } /* Should go to the first slave */ $query = sprintf("/*%s*/SELECT 'slave' AS _message FROM DUAL", MYSQLND_MS_SLAVE_SWITCH); $expected = array('_message' => 'slave'); my_mysqli_query(80, $link, $query, $expected); $server_id = mst_mysqli_get_emulated_id(81, $link); if (!isset($threads["slave"][$server_id])) { $threads["slave"][$server_id] = 1; } else { $threads["slave"][$server_id]++; } check_master_slave_threads(90, $threads); if ($threads["slave"][$server_id] != 2) { printf("[091] Slave should have run 2 queries, records report %d\n", $threads["slave"][$server_id]); } $autocommit = false; $link->autocommit($autocommit); /* Should go to the first slave with in_transaction = true */ $query = sprintf("/*%s*/SELECT 'slave' AS _message FROM DUAL", MYSQLND_MS_SLAVE_SWITCH); $expected = array('_message' => 'slave'); my_mysqli_query(100, $link, $query, $expected); $server_id = mst_mysqli_get_emulated_id(101, $link); if (!isset($threads["slave"][$server_id])) { $threads["slave"][$server_id] = 1; } else { $threads["slave"][$server_id]++; } check_master_slave_threads(110, $threads); if ($threads["slave"][$server_id] != 3) { printf("[111] Slave should have run 3 queries, records report %d\n", $threads["slave"][$server_id]); } print "done!"; ?> --CLEAN-- --EXPECTF-- 'SELECT 'Master Andrey has send this query to a slave.' AS _message FROM DUAL' => slave '/*ms=master*/SELECT 'master' AS _message FROM DUAL' => master '/*ms=master*/SELECT 'master' AS _message FROM DUAL' => master '/*ms=slave*/SELECT 'slave' AS _message FROM DUAL' => slave '/*ms=slave*/SELECT 'slave' AS _message FROM DUAL' => slave done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_error.phpt0000664000175000017500000000550312161007456022744 0ustar andreyandrey--TEST-- Config settings: pick server = user, handling of user error --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_error.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_error.ini --FILE-- query($query)) printf("[002] [%d] %s\n", $link->errno, $link->error); /* The connection is still useable. Just rerun the statement and pick a connection from the pool */ $fail = false; $query = sprintf("/*%s*/SELECT CONNECTION_ID() as _master FROM DUAL", MYSQLND_MS_MASTER_SWITCH); /* random follow-up error message, e.g. 2014 Commands out of sync */ if (!$res = $link->query($query)) printf("[003] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); $res->close(); printf("Master has thread id %d\n", $row['_master']); print "done!"; ?> --CLEAN-- --EXPECTF-- /*ms=master*/SELECT CONNECTION_ID() as _master FROM DUAL [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User filter callback has not returned string with server to use. The callback must return a string in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter /*ms=master*/SELECT CONNECTION_ID() as _master FROM DUAL Master has thread id %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_function.phpt0000664000175000017500000000355512161007456023445 0ustar andreyandrey--TEST-- pick = user, callback = function --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_function.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_function.ini --FILE-- query($query); printf("[%03d + 01] [%d] '%s'\n", $offset, $link->errno, $link->error); return $ret; } if (!$link = mst_mysqli_connect("myapp", $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); mst_mysqli_query(2, $link, "SELECT 1 FROM DUAL"); mst_mysqli_query(3, $link, "SET @my_role='master'"); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', 'SELECT 1 FROM DUAL') [002 + 01] [0] '' pick_server('myapp', 'SET @my_role='master'') [003 + 01] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_multi_master.phpt0000664000175000017500000000363712161007456025540 0ustar andreyandrey--TEST-- User multi, return bogus list --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array( 'master1' => $master_host, 'master2' => $master_host, ), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_multi_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_multi_master.ini mysqlnd_ms.multi_master=1 --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*ms=master*//*2*/SELECT 1 FROM DUAL, '', 2, 1) array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_multi_slaves.phpt0000664000175000017500000000351512161007456025535 0ustar andreyandrey--TEST-- User multi, return bogus list --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array( 'master1' => $master_host, ), 'slave' => array($slave_host, $slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_multi_slaves.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_multi_slaves.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '', 1, 2) array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi.phpt0000664000175000017500000000322612161007456022745 0ustar andreyandrey--TEST-- User mutli filter --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_return_big_id.phpt0000664000175000017500000000367012161007456025644 0ustar andreyandrey--TEST-- User multi, return bogus list offset --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_return_bid_id.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_return_bid_id.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has returned an invalid list of servers to use. Server id is too big in %s on line %d array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_return_bogus_list.phpt0000664000175000017500000000417612161007456026603 0ustar andreyandrey--TEST-- User multi, return bogus list --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_return_bogus_list.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_return_bogus_list.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has returned an invalid list of servers to use. The callback must return an array in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_return_negative_id.phpt0000664000175000017500000000436612161007456026710 0ustar andreyandrey--TEST-- User multi, return negative id --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_return_negative_id.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_return_negative_id.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has returned an invalid list of servers to use. Server id is either negative or not a number in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_return_slave_twice.phpt0000664000175000017500000001105212161007456026725 0ustar andreyandrey--TEST-- User multi, RR, return slave twice --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "roundrobin" => array() ), 'master' => array('mymaster' => $emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_return_slave_twice.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_return_slave_twice.ini --FILE-- --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 2 FROM DUAL, '') pick_server('myapp', '/*ms=last_used*//*3*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s') string(%d) "slave[1]-%d" pick_server('myapp', '/*4*/SELECT 4 FROM DUAL, '%s') pick_server('myapp', '/*ms=last_used*//*5*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s') string(%d) "slave[1]-%d" [006] Server changed: no pick_server('myapp', '/*7*/SELECT 7 FROM DUAL, '%s') pick_server('myapp', '/*ms=last_used*//*8*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s') string(%d) "master-%d" [009] Server changed: yes pick_server('myapp', '/*10*/SELECT 10 FROM DUAL, '%s') pick_server('myapp', '/*ms=last_used*//*11*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s') string(%d) "slave[1]-%d" [012] Server changed: yes pick_server('myapp', '/*13*/DROP TABLE IF EXISTS test, '%s') pick_server('myapp', '/*ms=last_used*//*14*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, '%s') string(%d) "master-%d" done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_return_void.phpt0000664000175000017500000000407312161007456025366 0ustar andreyandrey--TEST-- User multi, return void --SKIPIF-- array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "random" => array() ), 'master' => array('mymaster' => $master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_return_void.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_return_void.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 1 FROM DUAL, '') [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User multi filter callback has not returned a list of servers to use. The callback must return an array in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_multi_trx_stickiness.phpt0000664000175000017500000001102712161007456026077 0ustar andreyandrey--TEST-- User multi, RR, trx_stickiness --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Check config.inc notes! Configured emulated master and emulated slave could be part of a replication cluster\n"); $settings = array( "myapp" => array( 'filters' => array( 'user_multi' => array('callback' => 'pick_servers'), "roundrobin" => array() ), 'master' => array('mymaster' => $emulated_master_host), 'slave' => array($emulated_slave_host), 'lazy_connections' => 1, 'trx_stickiness' => 'master', ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_multi_trx_stickiness.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_multi_trx_stickiness.ini --FILE-- autocommit(false)) { printf("[003] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(4, $link, "SELECT 4 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(5, $link)); } if (!$link->commit()) { printf("[006] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(7, $link, "SELECT 7 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(5, $link)); } if (!$link->autocommit(true)) { printf("[008] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(9, $link, "SELECT 9 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(10, $link)); } if (!$link->rollback()) { printf("[011] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(12, $link, "SELECT 9 FROM DUAL")) { printf("Server: %s\n", mst_mysqli_get_emulated_id(13, $link)); } print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server('myapp', '/*2*/SELECT 2 FROM DUAL, 0) pick_server('myapp', '/*ms=last_used*//*3*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, 0) Server: slave[1]-%d pick_server('myapp', '/*4*/SELECT 4 FROM DUAL, 1) pick_server('myapp', '/*ms=last_used*//*5*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, 1) Server: master-%d pick_server('myapp', '/*7*/SELECT 7 FROM DUAL, 1) pick_server('myapp', '/*ms=last_used*//*5*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, 1) Server: master-%d pick_server('myapp', '/*9*/SELECT 9 FROM DUAL, 0) pick_server('myapp', '/*ms=last_used*//*10*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, 0) Server: slave[1]-%d pick_server('myapp', '/*12*/SELECT 9 FROM DUAL, 0) pick_server('myapp', '/*ms=last_used*//*13*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles, 0) Server: slave[1]-%d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_no_callback.phpt0000664000175000017500000000303412161007456024040 0ustar andreyandrey--TEST-- pick = user, callback = not given --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('user' => array('andrey' => 'ulf')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_no_callback.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_no_callback.ini --FILE-- fetch_assoc()); mst_mysqli_query(3, $link, "SET @my_role='master'"); print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Error by creating filter 'user', can't find section 'callback' . Stopping. in %s on line %d mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_return_void.phpt0000664000175000017500000000534212161007456024154 0ustar andreyandrey--TEST-- Config settings: pick server = user, unknown server --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_return_void.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_return_void.ini --FILE-- query($query)) printf("[002] [%d] %s\n", $link->errno, $link->error); /* The connection is still useable. Just rerun the statement and pick a connection from the pool */ $fail = false; $query = sprintf("/*%s*/SELECT CONNECTION_ID() as _master FROM DUAL", MYSQLND_MS_MASTER_SWITCH); /* random follow-up error message, e.g. 2014 Commands out of sync */ if (!$res = $link->query($query)) printf("[003] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); $res->close(); printf("Master has thread id %d\n", $row['_master']); print "done!"; ?> --CLEAN-- --EXPECTF-- /*ms=master*/SELECT CONNECTION_ID() as _master FROM DUAL [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User filter callback has not returned string with server to use. The callback must return a string in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter /*ms=master*/SELECT CONNECTION_ID() as _master FROM DUAL Master has thread id %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_unknown_function.phpt0000664000175000017500000000344012161007456025215 0ustar andreyandrey--TEST-- pick = user, callback = non existant --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('user' => array('callback' => 'unknown function')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_unknown_function.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_unknown_function.ini --FILE-- query($query); printf("[%03d + 01] [%d] '%s'\n", $offset, $link->errno, $link->error); return $ret; } if (!$link = mst_mysqli_connect("myapp", $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); mst_mysqli_query(2, $link, "SELECT 1 FROM DUAL"); print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) Specified callback (unknown function) is not a valid callback in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002 + 01] [2000] '(mysqlnd_ms) No connection selected by the last filter' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_pick_user_unknown_server.phpt0000664000175000017500000000554412161007456024705 0ustar andreyandrey--TEST-- Config settings: pick server = user, unknown server --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_pick_user_unknown_server.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_pick_user_unknown_server.ini --FILE-- query($query)) printf("[002] [%d] %s\n", $link->errno, $link->error); /* The connection is still useable. Just rerun the statement and pick a connection from the pool */ $fail = false; $query = sprintf("/*%s*/SELECT CONNECTION_ID() as _master FROM DUAL", MYSQLND_MS_MASTER_SWITCH); /* random follow-up error message, e.g. 2014 Commands out of sync */ if (!$res = $link->query($query)) printf("[003] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); $res->close(); printf("Master has thread id %d\n", $row['_master']); print "done!"; ?> --CLEAN-- --EXPECTF-- /*ms=master*/SELECT CONNECTION_ID() as _master FROM DUAL [E_RECOVERABLE_ERROR] mysqli::query(): (mysqlnd_ms) User filter callback has returned an unknown server. The server 'server that is not in master or slave list' can neither be found in the master list nor in the slave list in %s on line %d [E_WARNING] mysqli::query(): (mysqlnd_ms) No connection selected by the last filter in %s on line %d [002] [2000] (mysqlnd_ms) No connection selected by the last filter /*ms=master*/SELECT CONNECTION_ID() as _master FROM DUAL Master has thread id %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_ping.phpt0000664000175000017500000000607112161007456020505 0ustar andreyandrey--TEST-- ping --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_ping.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_ping.ini --FILE-- ping()) printf("[005] [%d] %s\n", $link->errno, $link-error); /* although we kill the master connection, the slaves are still reachable */ if (!$link->kill($link->thread_id)) printf("[006] [%d] %s\n", $link->errno, $link->error); usleep(2000); if ($link->ping()) printf("[007] Master connection is still alive\n"); else printf("[007] [%d] %s\n", $link->errno, $link->error); if (mst_mysqli_query(8, $link, "SET @myrole='Master 1'")) printf("[008] Master connection can still run queries\n"); $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role"); if (!$res || !($row = $res->fetch_assoc())) printf("[010] Slave connections should be still usable, [%d] %s\n", $link->errno, $link->error); if ($row['_role'] != "Slave 1") printf("[011] Expecting 'Slave 1' got '%s'\n", $row['_role']); if (!$link->ping()) printf("[012] [%d] %s\n", $link->errno, $link->error); if (!$link->kill($link->thread_id)) printf("[013] [%d] %s\n", $link->errno, $link->error); usleep(2000); if ($link->ping()) printf("[014] Slave connection is still alive\n"); else printf("[014] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(15, $link, "SELECT @myrole AS _role"); if (!$res || !($row = $res->fetch_assoc())) printf("[016] Slave connections should be still usable, [%d] %s\n", $link->errno, $link->error); if ($row['_role'] != "Slave 2") printf("[017] Expecting 'Slave 2' got '%s'\n", $row['_role']); if (!$link->ping()) printf("[018] [%d] %s\n", $link->errno, $link->error); if (!$link->kill($link->thread_id)) printf("[019] [%d] %s\n", $link->errno, $link->error); usleep(2000); if ($link->ping()) printf("[020] Slave connection is still alive\n"); else printf("[020] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [007] [%d] %s [008] [%d] %s [014] [%d] %s [020] [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_prepared_statements.phpt0000664000175000017500000000403212161007456023614 0ustar andreyandrey--TEST-- Prepared Statements --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_prepared_statements.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_prepared_statements.ini --FILE-- prepare("SELECT @myrole AS _role")) printf("[005] [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) printf("[006] [%d] %s\n", $stmt->errno, $stmt->error); $role = NULL; if (!$stmt->bind_result($role)) printf("[007] [%d] %s\n", $stmt->errno, $stmt->error); while ($stmt->fetch()) printf("Role = '%s'\n", $role); if (!$stmt = $link->prepare("/*".MYSQLND_MS_MASTER_SWITCH."*/ SELECT @myrole AS _role")) printf("[008] [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) printf("[009] [%d] %s\n", $stmt->errno, $stmt->error); $role = NULL; if (!$stmt->bind_result($role)) printf("[010] [%d] %s\n", $stmt->errno, $stmt->error); while ($stmt->fetch()) printf("Role = '%s'\n", $role); $stmt->close(); print "done!"; ?> --CLEAN-- --EXPECTF-- Role = 'slave' Role = 'master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_prepare_switch.phpt0000664000175000017500000000527612161007456022575 0ustar andreyandrey--TEST-- Prepare and switch --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), 'filters' => array( "roundrobin" => array(), ), 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_prepare_switch.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_prepare_switch.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (!($stmt_master = $link->prepare(sprintf("/*%s*/SELECT id as _one FROM test", MYSQLND_MS_MASTER_SWITCH)))) { printf("[003] [%d] %s\n", $link->errno, $link->error); } if (!($stmt_slave = $link->prepare("SELECT 2 AS _two FROM DUAL"))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } if (!$stmt_master->execute()) printf("[005] [%d] %s\n", $stmt_master->errno, $stmt_master->error); if (!$stmt_slave->execute()) printf("[006] [%d] %s\n", $stmt_slave->errno, $stmt_slave->error); if (!($res_master = $stmt_master->get_result())) printf("[007] [%d] %s\n", $stmt_master->errno, $stmt_master->error); if (!($res_slave = $stmt_slave->get_result())) printf("[008] [%d] %s\n", $stmt_slave->errno, $stmt_slave->error); var_dump($res_slave->fetch_all()); var_dump($res_master->fetch_all()); /* resource reusage without close etc */ if (!($stmt_master = $link->prepare(sprintf("/*%s*/SELECT id as _one FROM test", MYSQLND_MS_MASTER_SWITCH)))) { printf("[009] [%d] %s\n", $link->errno, $link->error); } if (!($stmt_slave = $link->prepare("SELECT 1 AS _one FROM DUAL"))) { printf("[010] [%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> int(2) } } array(1) { [0]=> array(1) { [0]=> int(1) } } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_proto_info.phpt0000664000175000017500000000610712161007456021726 0ustar andreyandrey--TEST-- mysqli->protocol_version / mysqli_get_proto_info() --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_proto_info.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_proto_info.ini --FILE-- 'Slave 1', 'version' => $link->protocol_version); /* slave 2 */ mst_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Slave 2', 'version' => mysqli_get_proto_info($link)); /* master */ mst_mysqli_query(6, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = array('role' => 'Master', 'version' => $link->protocol_version); foreach ($threads as $server_id => $details) { printf("%s - %s: %d\n", $server_id, $details['role'], $details['version']); if (!is_int($details['version'])) printf("Protocol version is not a number.\n"); if ($details['version'] < 1) printf("Protocol version must not be < 1.\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %s - Slave 1: %d %s - Slave 2: %d %s - Master: %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_ps_commit.phpt0000664000175000017500000001062512161007456021542 0ustar andreyandrey--TEST-- PS and commit --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); if (($master_host == $slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host), 'filters' => array( "roundrobin" => array(), ), 'trx_stickiness' => 'disabled', 'lazy_connections' => 1 ), ); if ($error = mst_create_config("test_mysqlnd_ms_ps_commit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_ps_commit.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT) ENGINE=InnoDB")) printf("[002] [%d] %s\n", $link->errno, $link->error); /* statement created in autocommit mode on master connection */ if (!($stmt = $link->prepare("INSERT INTO test(id) VALUES (1)"))) printf("[003] [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) printf("[004] [%d] %s\n", $stmt->errno, $stmt->error); if (!($res = $link->query(sprintf("/*%s*//*%d*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH, 5)))) printf("[006] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); /* switch to slave connection */ if (!($res = $link->query("SELECT 'Ahoy' AS _msg FROM DUAL"))) printf("[007] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Slave says: %s\n", $row['_msg']); /* must dispatch autocommit to master and stmt */ if (!$link->autocommit(false)) printf("[008] Can't change autocommit mode, [%d] %s\n", $link->errno, $link->error); if (!$stmt->execute()) printf("[009] [%d] %s\n", $stmt->errno, $stmt->error); /* master */ if (!($res = $link->query(sprintf("/*%s*//*%d*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH, 10)))) printf("[011] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); /* 'trx_stickiness' => 'disabled' -> slave */ if (!($res = $link->query("SELECT 'Ahoy' AS _msg FROM DUAL"))) printf("[012] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Slave says: %s\n", $row['_msg']); /* no effect because comitted on slave */ if (!$link->commit()) printf("[013] Failed to commit, [%d] %s\n", $link->errno, $link->error); /* master */ if (!$stmt->execute()) printf("[014] [%d] %s\n", $stmt->errno, $stmt->error); /* master */ if (!($res = $link->query(sprintf("/*%s*//*%d*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH, 15)))) printf("[016] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); /* rollback on master */ if (!$link->rollback()) printf("[017] Cannot roll back, [%d] %s\n", $link->errno, $link->error); /* master */ if (!($res = $link->query(sprintf("/*%s*//*%d*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH, 19)))) printf("[020] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); if (!$stmt->execute()) printf("[021] [%d] %s\n", $stmt->errno, $stmt->error); /* comitted on master */ if (!$link->commit()) printf("[022] Failed to commit, [%d] %s\n", $link->errno, $link->error); /* master */ if (!($res = $link->query(sprintf("/*%s*//*%d*/SELECT COUNT(*) AS _num_rows FROM test", MYSQLND_MS_MASTER_SWITCH, 23)))) printf("[024] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); printf("Rows %d\n", $row['_num_rows']); print "done!"; ?> --CLEAN-- --EXPECTF-- Rows 1 Slave says: Ahoy Rows 2 Slave says: Ahoy Rows 3 Rows 1 Rows 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_qc_failed_master.phpt0000664000175000017500000000601612161007456023031 0ustar andreyandrey--TEST-- MS + QC - failed master --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_check_extensions(array("mysqlnd_qc")); if (!defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { die("SKIP Cache support not compiled in"); } $settings = array( "myapp" => array( 'master' => array("unreachable:6003"), 'slave' => array("unreachable:7003"), 'filters' => array( "quality_of_service" => array( "eventual_consistency" => array( 'cache' => 123 ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_qc_failed_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_qc_failed_master.ini apc.use_request_time=0 mysqlnd_qc.use_request_time=0 mysqlnd_qc.collect_statistics=1 mysqlnd_qc.ttl=99 --FILE-- fetch_assoc()); } $res = mst_mysqli_query(3, $link, "SELECT 1 FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH); if ($res) { var_dump($res->fetch_assoc()); } mst_mysqli_query(4, $link, "SELECT 1 FROM DUAL", MYSQLND_MS_MASTER_SWITCH); if ($res) { var_dump($res->fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d Connect error, [002] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d Warning: mysqli::query(): (mysqlnd_qc) Plugin data is empty. If you are trying to use PECL/mysqlnd_ms together with PECL/mysqlnd_qc make sure to compile PECL/mysqlnd_ms appropriately respectively load the PECL/mysqlnd_qc extension into PHP before loading the PECL/mysqlnd_ms extension into PHP to avoid issues with the plugin initialization order in %s on line %d Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d Connect error, [004] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_qc_failed_slave_failover.phpt0000664000175000017500000000420112161007456024531 0ustar andreyandrey--TEST-- MS + QC - failed slave, failover --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_check_extensions(array("mysqlnd_qc")); if (!defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { die("SKIP Cache support not compiled in"); } _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array("unreachable:7003"), 'filters' => array( "quality_of_service" => array( "eventual_consistency" => array( 'cache' => 123 ), ), "roundrobin" => array(), ), 'failover' => array("strategy" => "master", "remember_failed" => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_qc_failed_slave_failover.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_qc_failed_slave_failover.ini apc.use_request_time=0 mysqlnd_qc.use_request_time=0 mysqlnd_qc.collect_statistics=1 mysqlnd_qc.ttl=99 --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): %A array(1) { [1]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_qc_failed_slave.phpt0000664000175000017500000000523512161007456022652 0ustar andreyandrey--TEST-- MS + QC - failed slave --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); _skipif_check_extensions(array("mysqli")); _skipif_check_extensions(array("mysqlnd_qc")); if (!defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { die("SKIP Cache support not compiled in"); } $settings = array( "myapp" => array( 'master' => array("unreachable:6003"), 'slave' => array("unreachable:7003"), 'filters' => array( "quality_of_service" => array( "eventual_consistency" => array( 'cache' => 123 ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_qc_failed_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_qc_failed_slave.ini apc.use_request_time=0 mysqlnd_qc.use_request_time=0 mysqlnd_qc.collect_statistics=1 mysqlnd_qc.ttl=99 --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d Connect error, [002] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %d Warning: mysqli::query(): (mysqlnd_qc) Plugin data is empty. If you are trying to use PECL/mysqlnd_ms together with PECL/mysqlnd_qc make sure to compile PECL/mysqlnd_ms appropriately respectively load the PECL/mysqlnd_qc extension into PHP before loading the PECL/mysqlnd_ms extension into PHP to avoid issues with the plugin initialization order in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_query_is_select.phpt0000664000175000017500000000625112161007456022747 0ustar andreyandrey--TEST-- int mysqlnd_ms_query_is_select(string query) --SKIPIF-- --INI-- mysqlnd_ms.enable=1 --FILE-- '%s'\n", $query, $server); } } $queries = array( "\0" => MYSQLND_MS_QUERY_USE_MASTER, "" => MYSQLND_MS_QUERY_USE_MASTER, "SELECT 1 FROM DUAL" => MYSQLND_MS_QUERY_USE_SLAVE, "sElEct 1 from DUAL" => MYSQLND_MS_QUERY_USE_SLAVE, "sElEct '1' AS _one from dual" => MYSQLND_MS_QUERY_USE_SLAVE, "sElEct/* insert */ '1'a _two from dual" => MYSQLND_MS_QUERY_USE_SLAVE, "INSERT INTO test(id) VALUES (1)" => MYSQLND_MS_QUERY_USE_MASTER, "/*SELECT*/DELETE FROM test" => MYSQLND_MS_QUERY_USE_MASTER, "CREATE TABLE test(id INT)" => MYSQLND_MS_QUERY_USE_MASTER, "/*INSERT*/SELECT 2 FROM DUAL" => MYSQLND_MS_QUERY_USE_SLAVE, "/*" . MYSQLND_MS_LAST_USED_SWITCH . "*/INSERT INTO test(id) VALUES(2)" => MYSQLND_MS_QUERY_USE_LAST_USED, "/*" . MYSQLND_MS_MASTER_SWITCH . "*/SELECT 3 FROM DUAL" => MYSQLND_MS_QUERY_USE_MASTER, "/*" . MYSQLND_MS_SLAVE_SWITCH . "*/DELETE FROM test" => MYSQLND_MS_QUERY_USE_SLAVE, "CALL p()/*" . MYSQLND_MS_MASTER_SWITCH . "*/" => MYSQLND_MS_QUERY_USE_MASTER, /* Note: tokenizer is stupid - only switches at the very beginning are recognized */ "SELECT 1 FROM DUAL/*" . MYSQLND_MS_MASTER_SWITCH . "*/" => MYSQLND_MS_QUERY_USE_SLAVE, "INSERT INTO test(id) VALUES (1); SELECT 1 FROM DUAL/*" . MYSQLND_MS_SLAVE_SWITCH . "*/" => MYSQLND_MS_QUERY_USE_MASTER, ); if (!is_null(($tmp = @mysqlnd_ms_query_is_select()))) printf("[001] Expecting NULL got %s/%s\n", gettype($tmp), var_export($tmp, true)); foreach ($queries as $query => $expected) { is_select($query, $expected); } is_select(NULL, MYSQLND_MS_QUERY_USE_MASTER); is_select("\0a", MYSQLND_MS_QUERY_USE_MASTER); print "done!"; ?> --EXPECTF-- %s => 'master' %s => 'master' 'SELECT 1 FROM DUAL' => 'slave' 'sElEct 1 from DUAL' => 'slave' 'sElEct '1' AS _one from dual' => 'slave' 'sElEct/* insert */ '1'a _two from dual' => 'slave' 'INSERT INTO test(id) VALUES (1)' => 'master' '/*SELECT*/DELETE FROM test' => 'master' 'CREATE TABLE test(id INT)' => 'master' '/*INSERT*/SELECT 2 FROM DUAL' => 'slave' '/*ms=last_used*/INSERT INTO test(id) VALUES(2)' => 'last used' '/*ms=master*/SELECT 3 FROM DUAL' => 'master' '/*ms=slave*/DELETE FROM test' => 'slave' 'CALL p()/*ms=master*/' => 'master' 'SELECT 1 FROM DUAL/*ms=master*/' => 'slave' 'INSERT INTO test(id) VALUES (1); SELECT 1 FROM DUAL/*ms=slave*/' => 'master' '' => 'master' %sa%s => 'master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_query_is_select_rw_disabled.phpt0000664000175000017500000000634512161007456025312 0ustar andreyandrey--TEST-- int mysqlnd_ms_query_is_select(string query) - disable RW split --SKIPIF-- --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.disable_rw_split=1 --FILE-- '%s'\n", $query, $server); } } $queries = array( "\0" => MYSQLND_MS_QUERY_USE_MASTER, "" => MYSQLND_MS_QUERY_USE_MASTER, "SELECT 1 FROM DUAL" => MYSQLND_MS_QUERY_USE_MASTER, "sElEct 1 from DUAL" => MYSQLND_MS_QUERY_USE_MASTER, "sElEct '1' AS _one from dual" => MYSQLND_MS_QUERY_USE_MASTER, "sElEct/* insert */ '1'a _two from dual" => MYSQLND_MS_QUERY_USE_MASTER, "INSERT INTO test(id) VALUES (1)" => MYSQLND_MS_QUERY_USE_MASTER, "/*SELECT*/DELETE FROM test" => MYSQLND_MS_QUERY_USE_MASTER, "CREATE TABLE test(id INT)" => MYSQLND_MS_QUERY_USE_MASTER, "/*INSERT*/SELECT 2 FROM DUAL" => MYSQLND_MS_QUERY_USE_MASTER, "/*" . MYSQLND_MS_LAST_USED_SWITCH . "*/INSERT INTO test(id) VALUES(2)" => MYSQLND_MS_QUERY_USE_LAST_USED, "/*" . MYSQLND_MS_MASTER_SWITCH . "*/SELECT 3 FROM DUAL" => MYSQLND_MS_QUERY_USE_MASTER, "/*" . MYSQLND_MS_SLAVE_SWITCH . "*/DELETE FROM test" => MYSQLND_MS_QUERY_USE_MASTER, "CALL p()/*" . MYSQLND_MS_MASTER_SWITCH . "*/" => MYSQLND_MS_QUERY_USE_MASTER, /* Note: tokenizer is stupid - only switches at the very beginning are recognized */ "SELECT 1 FROM DUAL/*" . MYSQLND_MS_MASTER_SWITCH . "*/" => MYSQLND_MS_QUERY_USE_MASTER, "INSERT INTO test(id) VALUES (1); SELECT 1 FROM DUAL/*" . MYSQLND_MS_SLAVE_SWITCH . "*/" => MYSQLND_MS_QUERY_USE_MASTER, ); if (!is_null(($tmp = @mysqlnd_ms_query_is_select()))) printf("[001] Expecting NULL got %s/%s\n", gettype($tmp), var_export($tmp, true)); foreach ($queries as $query => $expected) { is_select($query, $expected); } is_select(NULL, MYSQLND_MS_QUERY_USE_MASTER); is_select("\0a", MYSQLND_MS_QUERY_USE_MASTER); print "done!"; ?> --EXPECTF-- %s => 'master' %s => 'master' 'SELECT 1 FROM DUAL' => 'master' 'sElEct 1 from DUAL' => 'master' 'sElEct '1' AS _one from dual' => 'master' 'sElEct/* insert */ '1'a _two from dual' => 'master' 'INSERT INTO test(id) VALUES (1)' => 'master' '/*SELECT*/DELETE FROM test' => 'master' 'CREATE TABLE test(id INT)' => 'master' '/*INSERT*/SELECT 2 FROM DUAL' => 'master' '/*ms=last_used*/INSERT INTO test(id) VALUES(2)' => 'last used' '/*ms=master*/SELECT 3 FROM DUAL' => 'master' '/*ms=slave*/DELETE FROM test' => 'master' 'CALL p()/*ms=master*/' => 'master' 'SELECT 1 FROM DUAL/*ms=master*/' => 'master' 'INSERT INTO test(id) VALUES (1); SELECT 1 FROM DUAL/*ms=slave*/' => 'master' %s => 'master' %s => 'master' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_random_once_unknown_parameter.phpt0000664000175000017500000000616312161007456025655 0ustar andreyandrey--TEST-- LB random once: unknown parameter --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array( "please" => "warn me", "sticky" => 1, "" => "please", "\n" => "SOS" ), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_random_once_unknown_parameter.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_random_once_unknown_parameter.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_random_unknown_parameter.phpt0000664000175000017500000000341112161007456024642 0ustar andreyandrey--TEST-- LB random: unknown parameter --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array("please" => "warn me", "" => "please", "\n" => "SOS"), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_random_unknown_parameter.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_random_unknown_parameter.ini --FILE-- thread_id == 0) printf("[003] Which server has run this?"); for ($i = 0; $i < 10; $i++) mst_mysqli_query(5, $link, "SELECT 1 FROM DUAL"); if ($link->thread_id == 0) printf("[006] Which server has run this?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_real_escape.phpt0000664000175000017500000000432712161007456022015 0ustar andreyandrey--TEST-- real escape --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_real_escape.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_real_escape.ini --FILE-- set_charset($charset) || !@$link_ms->set_charset($charset)) continue; $string = ""; for ($i = 0; $i < 256; $i++) { $char = @iconv("UTF-8", $charset, chr($i)); if ($char) $string .= $char; else $string .= chr($i); } $no_ms = $link->real_escape_string($string); $ms = $link_ms->real_escape_string($string); if ($no_ms !== $ms) { printf("[004] Encoded strings differ for charset '%s', MS = '%s', no MS = '%s'\n", $charset, $ms, $no_ms); } } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_real_query.phpt0000664000175000017500000000511612161007456021717 0ustar andreyandrey--TEST-- Limits - real_query is NOT handled by the prototype --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_limits_real_query.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_limits_real_query.ini --FILE-- errno, $link->error); } while ($row = $res->fetch_assoc()) if ($row['_role'] != 'slave1') printf("[007] Expecting 'slave1' got '%s'\n", $row['_role']); $res->close(); mst_mysqli_query(8, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(9, $link, "CREATE TABLE test(id INT, label varchar(20))", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(10, $link, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c')", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_real_query(11, $link, "SELECT @myrole AS _role, id, label FROM test ORDER BY id ASC", MYSQLND_MS_LAST_USED_SWITCH); if (!$res = mysqli_use_result($link)) { printf("[012] [%d] %s\n", $link->errno, $link->error); } while ($row = $res->fetch_assoc()) printf("Slave 1, field_count = %d, role = %s, id = %d, label = '%s'\n", $res->field_count, $row['_role'], $row['id'], $row['label']); print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1, field_count = 3, role = slave1, id = 1, label = 'a' Slave 1, field_count = 3, role = slave1, id = 2, label = 'b' Slave 1, field_count = 3, role = slave1, id = 3, label = 'c' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_reflection_extension.phpt0000664000175000017500000000356412161007456024002 0ustar andreyandrey--TEST-- ReflectionExtension basics to check API --SKIPIF-- --FILE-- name); printf("Version: %s\n", $r->getVersion()); if ($r->getVersion() != MYSQLND_MS_VERSION) { printf("[001] Expecting version '%s' got '%s'\n", MYSQLND_MS_VERSION, $r->getVersion()); } $classes = $r->getClasses(); if (!empty($classes)) { printf("[002] Expecting no class\n"); asort($classes); var_dump($classes); } $expected = array( 'json' => true, 'standard' => true, 'mysqlnd' => true, 'mysqlnd_qc'=> true, ); $dependencies = $r->getDependencies(); asort($dependencies); printf("Dependencies:\n"); foreach ($dependencies as $what => $how) { printf(" %s - %s, ", $what, $how); if (isset($expected[$what])) { unset($expected[$what]); } else { printf("Unexpected extension dependency with %s - %s\n", $what, $how); } } if (!empty($expected)) { printf("Dumping list of missing extension dependencies\n"); var_dump($expected); } printf("\n"); $ignore = array(); if (version_compare(PHP_VERSION, '5.3.99', ">")) { $ignore['mysqlnd_ms_set_qos'] = true; $ignore['mysqlnd_ms_get_last_gtid'] = true; } $functions = $r->getFunctions(); asort($functions); printf("Functions:\n"); foreach ($functions as $func) { if (isset($ignore[$func->name])) { unset($ignore[$func->name]); } else { printf(" %s\n", $func->name); } } if (!empty($ignore)) { printf("Dumping version dependent and missing functions\n"); var_dump($ignore); } print "done!"; ?> --EXPECTF-- Name: mysqlnd_ms Version: 1.5.2 Dependencies: %s Functions: mysqlnd_ms_get_last_used_connection mysqlnd_ms_get_stats mysqlnd_ms_match_wild mysqlnd_ms_query_is_select done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_reflection_functions.phpt0000664000175000017500000000306112161007456023766 0ustar andreyandrey--TEST-- ReflectionFunction to check API --SKIPIF-- --FILE-- ")) { $ignore['mysqlnd_ms_set_qos'] = true; $ignore['mysqlnd_ms_get_last_gtid'] = true; } $functions = $r->getFunctions(); asort($functions); printf("Functions:\n"); foreach ($functions as $func) { if (isset($ignore[$func->name])) continue; printf(" %s\n", $func->name); $rf = new ReflectionFunction($func->name); printf(" Deprecated: %s\n", $rf->isDeprecated() ? "yes" : "no"); printf(" Accepted parameters: %d\n", $rf->getNumberOfParameters()); printf(" Required parameters: %d\n", $rf->getNumberOfRequiredParameters()); foreach( $rf->getParameters() as $param ) { printf(" %s\n", $param); } } print "done!"; ?> --EXPECTF-- Functions: mysqlnd_ms_get_last_used_connection Deprecated: no Accepted parameters: 1 Required parameters: 1 Parameter #0 [ $object ] mysqlnd_ms_get_stats Deprecated: no Accepted parameters: 0 Required parameters: 0 mysqlnd_ms_match_wild Deprecated: no Accepted parameters: 2 Required parameters: 2 Parameter #0 [ $haystack ] Parameter #1 [ $wild ] mysqlnd_ms_query_is_select Deprecated: no Accepted parameters: 1 Required parameters: 1 Parameter #0 [ $query ] done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_rr_unknown_parameter.phpt0000664000175000017500000000630612161007456024013 0ustar andreyandrey--TEST-- LB round robin: unknown parameter --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "roundrobin" => array( "please" => "warn me", "sticky" => 1, "" => "please", "\n" => "SOS" ), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_rr_unknown_parameter.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_rr_unknown_parameter.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_select_db_fail.phpt0000664000175000017500000000512212161007456022463 0ustar andreyandrey--TEST-- select_db() and kill() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_select_db_fail.ini", $settings)) die(sprintf("SKIP %s\n", $error)); $db = 'pleasenot'; function test_pleasenot_access($host, $user, $passwd, $db, $port, $socket) { if ($link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("SKIP Can connect to 'pleasenot', [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); return; } test_pleasenot_access($master_host_only, $user, $passwd, $db, $port, $socket); test_pleasenot_access($slave_host_only, $user, $passwd, $db, $port, $socket); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_select_db_fail.ini --FILE-- select_db("pleasenot")) printf("[005] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(6, $link, "SELECT SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_SLAVE_SWITCH); if (!$link->select_db($db)) printf("[007] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); $row = $res->fetch_assoc(); printf("%s - %s\n", $row['_role'], ($row['_database'] == $db) ? 'OK' : sprintf("Wrong DB - %s!", $row['_database'])); $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role, DATABASE() as _database"); $row = $res->fetch_assoc(); printf("%s - %s\n", $row['_role'], ($row['_database'] == $db) ? 'OK' : sprintf("Wrong DB - %s!", $row['_database'])); print "done!"; ?> --CLEAN-- --EXPECTF-- [005] [%d] %spleasenot%s [006] [%d] %s master - OK slave - OK done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_select_db_kill.phpt0000664000175000017500000000643612161007456022514 0ustar andreyandrey--TEST-- select_db() and kill() --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_select_db_kill.ini", $settings)) die(sprintf("SKIP %s\n", $error)); function test_mysql_access($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("SKIP Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); return $link->select_db("mysql"); } if (!test_mysql_access($master_host_only, $user, $passwd, $db, $port, $socket)) die("SKIP Master server account cannot access mysql database"); if (!test_mysql_access($slave_host_only, $user, $passwd, $db, $port, $socket)) die("SKIP Slave server account cannot access mysql database"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_select_db_kill.ini --FILE-- thread_id; if (!$link->kill($link->thread_id)) printf("[004] [%d] %s\n", $link->errno, $link->error); /* will change schema of all connections */ if (!$link->select_db("mysql")) printf("[005] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(6, $link, "SELECT @myrole AS _role, DATABASE() as _database"); if ($res) { printf("[007] Who has run this? Slave thread id is '%d', thread id '%d'\n", $slave_thread_id, $link->thread_id); var_dump($res->fetch_assoc()); } $res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[009] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[010] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != 'master') printf("[011] Expecting role 'master' got '%s'\n", $row['_role']); if (!$link->select_db($db)) printf("[012] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(13, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[014] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != $db) printf("[015] Expecting database '%s' got '%s'\n", $db, $row['_database']); if ($row['_role'] != 'master') printf("[016] Expecting role 'master' got '%s'\n", $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- [006] [2006] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_select_db.phpt0000664000175000017500000000546412161007456021501 0ustar andreyandrey--TEST-- select_db() - covered by plugin prototype --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_select_db.ini", $settings)) die(sprintf("SKIP %s\n", $error)); function test_mysql_access($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); return $link->select_db("mysql"); } if (!test_mysql_access($master_host_only, $user, $passwd, $db, $port, $socket)) die("skip Master server account cannot access mysql database"); if (!test_mysql_access($slave_host_only, $user, $passwd, $db, $port, $socket)) die("skip Slave server account cannot access mysql database"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_select_db.ini --FILE-- select_db("mysql")) printf("[004] [%d] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_SLAVE_SWITCH); if (!$row = $res->fetch_assoc()) printf("[006] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[007] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != 'slave') printf("[008] Expecting role 'slave' got '%s'\n", $row['_role']); $res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role, DATABASE() as _database", MYSQLND_MS_MASTER_SWITCH); if (!$row = $res->fetch_assoc()) printf("[010] [%d] %s\n", $link->errno, $link->error); if ($row['_database'] != 'mysql') printf("[011] Expecting database 'mysql' got '%s'\n", $row['_database']); if ($row['_role'] != 'master') printf("[012] Expecting role 'master' got '%s'\n", $row['_role']); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_server_charset_real_escape_change_back.phpt0000664000175000017500000000733512161007456027403 0ustar andreyandrey--TEST-- server_charset + set_charset --SKIPIF-- query("SELECT @@character_set_connection AS charset")) || !($row = $res->fetch_assoc())) { die(sprintf("SKIP Can't check for slave charset, [%d] %s\n", $link->errno, $link->error)); } if (!($res = $link->query('SHOW CHARACTER SET LIKE "utf8"')) || (0 == $res->num_rows)) { die(sprintf("SKIP We need a slave that supports utf8, [%d] %s\n", $link->errno, $link->error)); } if (!($res = $link->query('SHOW CHARACTER SET LIKE "latin1"')) || (0 == $res->num_rows)) { die(sprintf("SKIP We need a slave that supports latin1, [%d] %s\n", $link->errno, $link->error)); } $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'server_charset' => $row['charset'], 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_server_charset_real_escape_change_back.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_server_charset_real_escape_change_back.ini --FILE-- fetch_assoc(); if ('latin1' == $row['charset']) { $other_charset = 'utf8'; } else { $other_charset = 'latin1'; } /* From a user perspective MS and non MS-Connection are now in the same state: connected */ if (!($link_ms = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); printf("set_charset()\n"); if (!$link_ms->set_charset($other_charset)) { printf("[003] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } $string = "андрей\0'\"улф\"\'\13\10\7йоханес\0майескюел мастер слейв"; $no_ms = $link->real_escape_string($string); $ms = $link_ms->real_escape_string($string); if ($no_ms !== $ms) { printf("[004] Encoded strings differ for charset '%s', MS = '%s', no MS = '%s'\n", $row['charset'], $ms, $no_ms); printf("[005] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); printf("[006] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } printf("set_charset()\n"); if (!$link_ms->set_charset($row['charset'])) { printf("[007] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } printf("query()\n"); $res = mst_mysqli_query(8, $link_ms, "SELECT @@character_set_connection AS charset"); $row_ms = $res->fetch_assoc(); if ($row_ms['charset'] != $row['charset']) printf("[009] %s - %s\n", $row_ms['charset'], $row['charset']); print "done!"; ?> --CLEAN-- --EXPECTF-- set_charset() set_charset() query() done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_server_charset_real_escape_change_later.phpt0000664000175000017500000001072512161007456027607 0ustar andreyandrey--TEST-- server_charset + set_charset --SKIPIF-- query("SELECT @@character_set_connection AS charset")) || !($row = $res->fetch_assoc())) { die(sprintf("SKIP Can't check for slave charset, [%d] %s\n", $link->errno, $link->error)); } if (!($res = $link->query('SHOW CHARACTER SET LIKE "utf8"')) || (0 == $res->num_rows)) { die(sprintf("SKIP We need a slave that supports utf8, [%d] %s\n", $link->errno, $link->error)); } if (!($res = $link->query('SHOW CHARACTER SET LIKE "latin1"')) || (0 == $res->num_rows)) { die(sprintf("SKIP We need a slave that supports latin1, [%d] %s\n", $link->errno, $link->error)); } $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host), 'pick' => array("roundrobin"), 'server_charset' => $row['charset'], 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_server_charset_real_escape_change_later.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_server_charset_real_escape_change_later.ini --FILE-- fetch_assoc(); if ('latin1' == $row['charset']) { $other_charset = 'utf8'; } else { $other_charset = 'latin1'; } /* From a user perspective MS and non MS-Connection are now in the same state: connected */ if (!($link_ms = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $string = "андрей\0'\"улф\"\'\13\10\7йоханес\0майескюел мастер слейв"; $no_ms = $link->real_escape_string($string); $ms = $link_ms->real_escape_string($string); if ($no_ms !== $ms) { printf("[003] Encoded strings differ for charset '%s', MS = '%s', no MS = '%s'\n", $row['charset'], $ms, $no_ms); printf("[004] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); printf("[005] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } printf("query()\n"); /* Connection gets opened, CS tricks shall be tested for */ $res = mst_mysqli_query(6, $link_ms, "SELECT @@character_set_connection AS charset"); $row_ms = $res->fetch_assoc(); if ($row['charset'] != $row_ms['charset']) { printf("[007] Expecting charset '%s' but '%s' is reported", $row['charset'], $row_ms['charset']); } printf("set_charset()\n"); if (!$link_ms->set_charset($other_charset)) { printf("[008] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } /* Connection is established, what about CS - limit? */ printf("query()\n"); $res = mst_mysqli_query(9, $link_ms, "SELECT @@character_set_connection AS charset"); $row_ms = $res->fetch_assoc(); if ($other_charset != $row_ms['charset']) { printf("[010] Expecting charset '%s' but '%s' is reported", $other_charset, $row_ms['charset']); } printf("set_charset()\n"); if (!$link_ms->set_charset( $row['charset'])) { printf("[011] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } printf("query()\n"); $res = mst_mysqli_query(12, $link_ms, "SELECT @@character_set_connection AS charset"); $row_ms = $res->fetch_assoc(); if ($row['charset'] != $row_ms['charset']) { printf("[013] Expecting charset '%s' but '%s' is reported", $row['charset'], $row_ms['charset']); } print "done!"; ?> --CLEAN-- --EXPECTF-- query() set_charset() query() set_charset() query() done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_server_charset_real_escape_change.phpt0000664000175000017500000000710712161007456026420 0ustar andreyandrey--TEST-- server_charset + set_charset --SKIPIF-- query("SELECT @@character_set_connection AS charset")) || !($row = $res->fetch_assoc())) { die(sprintf("SKIP Can't check for slave charset, [%d] %s\n", $link->errno, $link->error)); } if (!($res = $link->query('SHOW CHARACTER SET LIKE "utf8"')) || (0 == $res->num_rows)) { die(sprintf("SKIP We need a slave that supports utf8, [%d] %s\n", $link->errno, $link->error)); } if (!($res = $link->query('SHOW CHARACTER SET LIKE "latin1"')) || (0 == $res->num_rows)) { die(sprintf("SKIP We need a slave that supports latin1, [%d] %s\n", $link->errno, $link->error)); } $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), 'server_charset' => $row['charset'], 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_server_charset_real_escape_change.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_server_charset_real_escape_change.ini --FILE-- fetch_assoc(); if ('latin1' == $row['charset']) { $other_charset = 'utf8'; } else { $other_charset = 'latin1'; } /* From a user perspective MS and non MS-Connection are now in the same state: connected */ if (!($link_ms = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); printf("set_charset()\n"); if (!$link_ms->set_charset($other_charset)) { printf("[003] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } $string = "андрей\0'\"улф\"\'\13\10\7йоханес\0майескюел мастер слейв"; $no_ms = $link->real_escape_string($string); $ms = $link_ms->real_escape_string($string); if ($no_ms !== $ms) { printf("[004] Encoded strings differ for charset '%s', MS = '%s', no MS = '%s'\n", $row['charset'], $ms, $no_ms); printf("[005] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); printf("[006] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } printf("query()\n"); /* charset should have been changed */ $res = mst_mysqli_query(7, $link_ms, "SELECT @@character_set_connection AS charset"); $row_ms = $res->fetch_assoc(); if ($row_ms['charset'] != $other_charset) printf("[008] %s - %s\n", $row_ms['charset'], $row['charset']); print "done!"; ?> --CLEAN-- --EXPECTF-- set_charset() query() done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_server_charset_real_escape.phpt0000664000175000017500000000560212161007456025111 0ustar andreyandrey--TEST-- server_charset --SKIPIF-- query("SELECT @@character_set_connection AS charset")) || !($row = $res->fetch_assoc())) { die(sprintf("SKIP Can't check for slave charset, [%d] %s\n", $link->errno, $link->error)); } $settings = array( "myapp" => array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), 'server_charset' => $row['charset'], 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_server_charset_real_escape.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_server_charset_real_escape.ini --FILE-- fetch_assoc(); /* From a user perspective MS and non MS-Connection are now in the same state: connected */ if (!($link_ms = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $string = "андрей\0'\"улф\"\'\13\10\7йоханес\0майескюел мастер слейв"; $no_ms = $link->real_escape_string($string); $ms = $link_ms->real_escape_string($string); if ($no_ms !== $ms) { printf("[007] Encoded strings differ for charset '%s', MS = '%s', no MS = '%s'\n", $row['charset'], $ms, $no_ms); printf("[008] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); printf("[009] [%d/%s] '%s'\n", $link_ms->errno, $link_ms->sqlstate, $link_ms->error); } $res = mst_mysqli_query(10, $link_ms, "SELECT @@character_set_connection AS charset"); $row_ms = $res->fetch_assoc(); if ($row_ms['charset'] != $row['charset']) { printf("[011] MS connection should use charset '%s' but reports '%s'\n", $row['charset'], $row_ms['charset']); } $link_ms->close(); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_server_info.phpt0000664000175000017500000000567112161007456022076 0ustar andreyandrey--TEST-- mysqli->server_info --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_server_info.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_server_info.ini --FILE-- 'Slave 1', 'info' => $link->server_info); /* slave 2 */ mst_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Slave 2', 'info' => $link->server_info); /* master */ mst_mysqli_query(6, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = array('role' => 'Master', 'info' => $link->server_info); foreach ($threads as $server_id => $details) { printf("%s - %s: '%s'\n", $server_id, $details['role'], $details['info']); if ('' == $details['info']) printf("Server info must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %s - Slave 1: '%s' %s - Slave 2: '%s' %s - Master: '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_server_version.phpt0000664000175000017500000000576512161007456022634 0ustar andreyandrey--TEST-- mysqli->server_version --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_server_version.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_server_version.ini --FILE-- 'Slave 1', 'version' => $link->server_version); /* slave 2 */ mst_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Slave 2', 'version' => $link->server_version); /* master */ mst_mysqli_query(6, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = array('role' => 'Master', 'version' => $link->server_version); foreach ($threads as $server_id => $details) { printf("%s - %s: %d\n", $server_id, $details['role'], $details['version']); if ('' == $details['version']) printf("Server version must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %s - Slave 1: %d %s - Slave 2: %d %s - Master: %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_age_killed.phpt0000664000175000017500000000737612161007456023376 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), age, killed slave --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($master_host == $slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($slave_host_only, $slave_port, $slave_socket, $master_host_only, $master_port, $master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (false == $ret) die("SKIP Configured master and slave might not be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_age_killed.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_age_killed.ini --FILE-- query("SELECT 1 FROM DUAL")) printf("[002] [%d] %s\n", $link->errno, $link->error); $slave_thread = $link->thread_id; /* kill slave connection */ $link->kill($link->thread_id); if (!$link->query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[004] [%d] %s\n", $link->errno, $link->error); $master_thread = $link->thread_id; if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_AGE, 4))) { printf("[005] [%d] %s\n", $link->errno, $link->error); } /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); printf("Reply comes from %d, slave is %d, %d\n", $link->thread_id, $slave_thread, ($master_thread == $slave_thread) ? 1 : ($link->thread_id == $master_thread)); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' Reply comes from %d, slave is %d, 1 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_age_no_value.phpt0000664000175000017500000000357512161007456023737 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), max age/lag, no value --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_age_no_value.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_age_no_value.ini --FILE-- errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqlnd_ms_set_qos(): Option value required in %s on line %d [002] [0%s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_age.phpt0000664000175000017500000000646712161007456022052 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), max age/lag --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($master_host == $slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($slave_host_only, $slave_port, $slave_socket, $master_host_only, $master_port, $master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (false == $ret) die("SKIP Configured master and slave might not be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_age.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_age.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); /* GTID */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_AGE, 4))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } /* Ignore repl errors such as slave not running. Result must be the same whatever server is used */ if ($res = @mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_cache.phpt0000664000175000017500000001201212161007456022340 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), max age/lag w. TTL cache --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($master_host == $slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_check_extensions(array("mysqlnd_qc")); if (!defined("MYSQLND_MS_HAVE_CACHE_SUPPORT")) { die("SKIP Cache support not compiled in"); } _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($slave_host_only, $slave_port, $slave_socket, $master_host_only, $master_port, $master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (false == $ret) die("SKIP Configured master and slave might not be part of a replication cluster\n"); $lag = mst_mysqli_get_slave_lag($slave_host_only, $user, $passwd, $db, (int)$slave_port, $slave_socket); if (is_string($lag)) { die(sprintf("SKIP %s\n", $lag)); } $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_cache.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_cache.ini apc.use_request_time=0 mysqlnd_qc.use_request_time=0 mysqlnd_qc.collect_statistics=1 mysqlnd_qc.ignore_sql_comments=1 --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); /* Test relies on replication, try to reduce false-positives */ do { $lag = mst_mysqli_get_slave_lag($slave_host_only, $user, $passwd, $db, (int)$slave_port, $slave_socket); if (is_string($lag)) { printf("[003] Caution, false positive - %s\n", $lag); $lag = 0; } } while ($lag > 0); /* slave may still be outdated, still possible to get false-positive */ $attempts = 0; while ($attempts < 10) { if ($res = mst_mysqli_query(4, $link, "SELECT id FROM test")) { if ($res->num_rows == 0) { continue; } break; } $attempts++; sleep(1); } var_dump($res->fetch_all()); if (!$res || ($res->num_rows == 0)) printf("[005] Caution, false positive possible, slave may not be up to date\n"); if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_CACHE, 4))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } dump_put_hit(); /* Should be served from cache */ if ($res = mst_mysqli_query(7, $link, "SELECT id FROM test")) { var_dump($res->fetch_all()); } dump_put_hit(); /* Note: Its not save to rely on the DELETE being executed by the slave before we do the next read. We must rely on the stats. This is just an extra little thingie on top which may cause a fail if stats are wrong. */ mst_mysqli_query(8, $link, "DELETE FROM test"); usleep(100000); /* Should be served from cache */ if ($res = mst_mysqli_query(9, $link, "SELECT id FROM test")) { var_dump($res->fetch_all()); } dump_put_hit(); printf("[010] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- array(1) { [0]=> array(1) { [0]=> string(1) "1" } } cache_put 0 cache_hit 0 array(1) { [0]=> array(1) { [0]=> string(1) "1" } } cache_put 1 cache_hit 0 array(1) { [0]=> array(1) { [0]=> string(1) "1" } } cache_put 1 cache_hit 1 [010] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_gtid_lost_connection.phpt0000664000175000017500000001076712161007456025523 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), GTID lost connection --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured master and slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to setup GTID on slave, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'filter' => array( 'roundrobin' => array(), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_gtid_lost_connection.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_gtid_lost_connection.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[003] [%d] %s\n", $link->errno, $link->error); /* kill master connection */ $link->kill($link->thread_id); /* kill first slave connection */ $res = $link->query("SELECT 1 FROM DUAL"); $link->kill($link->thread_id); /* kill second slave connection */ $res = $link->query("SELECT 1 FROM DUAL"); $link->kill($link->thread_id); /* GTID */ /* Insert QOS filter */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } /* Whatever server the filter wants to use, its connection is closed */ if ($res = mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [006] [%d] %s [007] [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_gtid_sql_error2.phpt0000664000175000017500000001020112161007456024374 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), GTID SQL error --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => "Be my #GTID", 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_gtid_sql_error2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_gtid_sql_error2.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[003] [%d] %s\n", $link->errno, $link->error); /* GTID */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1064/'%s' at line 1' in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1064/'%s' at line 1' in %s on line %d array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_gtid_sql_error.phpt0000664000175000017500000000661512161007456024330 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), GTID SQL error --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($master_host == $slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => "Looking for more interesting tasks!", 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_gtid_sql_error.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_gtid_sql_error.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[003] [%d] %s\n", $link->errno, $link->error); /* GTID */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Failed parse SQL for checking GTID. Cannot find #GTID placeholder in %s on line %d array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_gtid_sql_parsing2.phpt0000664000175000017500000000676712161007456024734 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), GTID SQL parsing --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($master_host == $slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($master_host_only, $user, $passwd, $db, $master_port, $master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); include_once("util.inc"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($master_host_only, $user, $passwd, $db, $master_port, $master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => "\n'#GTID'" . $sql['check_for_gtid'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_gtid_sql_parsing2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_gtid_sql_parsing2.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[003] [%d] %s\n", $link->errno, $link->error); /* GTID */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1064/'%s' in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1064/'%s' in %s on line %d array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_gtid_sql_parsing.phpt0000664000175000017500000001146112161007456024635 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), GTID SQL parsing --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); if ($error = mst_mysqli_setup_gtid_table($emulated_slave_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_slave_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'] . "\n'#GTID'", 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_gtid_sql_parsing.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_gtid_sql_parsing.ini --FILE-- query("DROP TABLE IF EXISTS test") || !$link->query("CREATE TABLE test(id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)")) printf("[002] [%d] %s\n", $link->errno, $link->error); if (false === ($gtid = mysqlnd_ms_get_last_gtid($link))) printf("[003] [%d] %s\n", $link->errno, $link->error); /* GTID */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, $gtid))) { printf("[004] [%d] %s\n", $link->errno, $link->error); } if ($res = mst_mysqli_query(6, $link, "SELECT id FROM test")) var_dump($res->fetch_all()); printf("[007] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1064/'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''#GTID'' at line 2' in %s on line %d Warning: mysqli::query(): (mysqlnd_ms) SQL error while checking slave for GTID: 1064/'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''#GTID'' at line 2' in %s on line %d array(1) { [0]=> array(1) { [0]=> string(1) "1" } } [007] [0] '' done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_params.phpt0000664000175000017500000001675712161007456022604 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), params --SKIPIF-- = 5.3.99, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); include_once("util.inc"); $ret = mst_is_slave_of($emulated_slave_host_only, $emulated_slave_port, $emulated_slave_socket, $emulated_master_host_only, $emulated_master_port, $emulated_master_socket, $user, $passwd, $db); if (is_string($ret)) die(sprintf("SKIP Failed to check relation of configured master and slave, %s\n", $ret)); if (true == $ret) die("SKIP Configured emulated master and emulated slave could be part of a replication cluster\n"); $sql = mst_get_gtid_sql($db); if ($error = mst_mysqli_setup_gtid_table($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("SKIP Failed to setup GTID on master, %s\n", $error)); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'global_transaction_id_injection' => array( 'on_commit' => $sql['update'], 'fetch_last_gtid' => $sql['fetch_last_gtid'], 'check_for_gtid' => $sql['check_for_gtid'], 'report_error' => true, ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_params.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave1"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master1"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_params.ini --FILE-- true, MYSQLND_MS_QOS_CONSISTENCY_SESSION => true, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL => true, ); do { $invalid_service_level = mt_rand(10, 100); } while (isset($valid_service_levels[$invalid_service_level])); if (false !== ($ret = mysqlnd_ms_set_qos($link, $invalid_service_level))) printf("[007] Expecting false got %s\n", var_export($ret, true)); $valid_options = array( MYSQLND_MS_QOS_OPTION_GTID => MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_AGE => MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, ); do { $invalid_option = mt_rand(10, 100); } while (isset($valid_options[$invalid_option])); foreach ($valid_options as $option => $service_level) { if (is_null($service_level)) continue; ob_start(); $ret = mysqlnd_ms_set_qos($link, $service_level, $invalid_option); $tmp = ob_get_contents(); ob_end_clean(); if (!stristr($tmp, "Warning")) { printf("[008] Can't find warning about invalid option %d for service level %d\n", $invalid_option, $service_level); } if (false !== $ret) printf("[009] Expecting false got %s with invalid option %d for service level %d\n", var_export($ret, true), $invalid_option, $service_level); } foreach ($valid_options as $option => $service_level) { $invalid_service_levels = array(); foreach ($valid_service_levels as $level => $v) { if ($service_level != $level) $invalid_service_levels[$level] = $level; } foreach ($invalid_service_levels as $service_level) { ob_start(); $ret = mysqlnd_ms_set_qos($link, $service_level, $option, 1); $tmp = ob_get_contents(); ob_end_clean(); if (!stristr($tmp, "Warning")) { printf("[010] Can't find warning about invalid option %d for service level %d\n", $invalid_option, $service_level); } if (false !== $ret) printf("[011] Expecting false got %s with invalid option %d for service level %d\n", var_export($ret, true), $invalid_option, $service_level); } } /* GTID */ if (false !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID))) { printf("[012] Expecting false got %s\n", var_export($ret, true)); } /* casted to 0 */ if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, array()))) { printf("[013] Expecting true got %s\n", var_export($ret, true)); } if (true !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, (-1 * PHP_INT_MAX) + 1))) { printf("[014] Expecting true got %s\n", var_export($ret, true)); } if (false !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_SESSION, MYSQLND_MS_QOS_OPTION_GTID, ""))) { printf("[015] Expecting false got %s\n", var_export($ret, true)); } /* Age */ if (false !== ($ret = mysqlnd_ms_set_qos($link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_AGE, -1))) { printf("[016] Expecting false got %s\n", var_export($ret, true)); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No mysqlnd_ms connection in %s on line %d Warning: mysqlnd_ms_set_qos(): Invalid service level in %s on line %d Warning: mysqlnd_ms_set_qos(): Option value required in %s on line %d Warning: mysqlnd_ms_set_qos(): GTID must be a number or a string in %s on line %d Notice: Array to string conversion in %s on line %d Warning: mysqlnd_ms_set_qos(): GTID is empty in %s on line %d Warning: mysqlnd_ms_set_qos(): Maximum age must have a positive value in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_trx_stickiness_master.phpt0000664000175000017500000001556412161007456025743 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), trx stickiness=master --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); include_once("util.inc"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'trx_stickiness' => 'master', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_trx_stickiness_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_trx_stickiness_master.ini --FILE-- query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] BEFORE [%d] '%s'\n", $offset, $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("[%03d] BEFORE id = %d\n", $offset, $row['_id']); } if (false == mysqlnd_ms_set_qos($link, $qos)) { printf("[%03d] [%d] '%s'\n", $offset, $link->errno, $link->error); } if (!($res = $link->query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] [%d] '%s'\n", $offset, $link->errno, $link->error); } else { printf("[%03d] AFTER [%d] '%s'\n", $offset, $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[%03d] AFTER id = %d\n", $offset, $row['_id']); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* autocommit, qos changes allowed at any time */ $link->autocommit(true); fetch_change_fetch(2, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); /* autocommit off, in transaction, qos changes shall not be allowed */ $link->autocommit(false); fetch_change_fetch(3, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); fetch_change_fetch(4, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); fetch_change_fetch(5, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* in transaction, forbid changes... */ $link->begin_transaction(); fetch_change_fetch(6, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); fetch_change_fetch(7, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); fetch_change_fetch(8, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow... */ fetch_change_fetch(9, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* disallow... */ $link->autocommit(false); $link->begin_transaction(); fetch_change_fetch(10, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); fetch_change_fetch(11, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* allow.. */ $link->autocommit(true); fetch_change_fetch(12, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* forbid... */ $link->begin_transaction(); fetch_change_fetch(13, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->rollback(); /* trx has ended - allow... */ fetch_change_fetch(14, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); $link->autocommit(false); $link->commit(); fetch_change_fetch(15, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); printf("[016] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [002] BEFORE id = 2 [002] AFTER [0] '' [002] AFTER id = 2 [003] BEFORE id = 3 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [003] [0] '' [003] AFTER [0] '' [003] AFTER id = 3 [004] BEFORE id = 4 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [004] [0] '' [004] AFTER [0] '' [004] AFTER id = 4 [005] BEFORE id = 5 [005] AFTER [0] '' [005] AFTER id = 5 [006] BEFORE id = 6 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [006] [0] '' [006] AFTER [0] '' [006] AFTER id = 6 [007] BEFORE id = 7 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [007] [0] '' [007] AFTER [0] '' [007] AFTER id = 7 [008] BEFORE id = 8 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [008] [0] '' [008] AFTER [0] '' [008] AFTER id = 8 [009] BEFORE id = 9 [009] AFTER [0] '' [009] AFTER id = 9 [010] BEFORE id = 10 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [010] [0] '' [010] AFTER [0] '' [010] AFTER id = 10 [011] BEFORE id = 11 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [011] [0] '' [011] AFTER [0] '' [011] AFTER id = 11 [012] BEFORE id = 12 [012] AFTER [0] '' [012] AFTER id = 12 [013] BEFORE id = 13 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [013] [0] '' [013] AFTER [0] '' [013] AFTER id = 13 [014] BEFORE id = 14 [014] AFTER [0] '' [014] AFTER id = 14 [015] BEFORE id = 15 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [015] [0] '' [015] AFTER [0] '' [015] AFTER id = 15 [016] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_trx_stickiness_off.phpt0000664000175000017500000001335012161007456025211 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), trx stickiness off --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); include_once("util.inc"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_trx_stickiness_off.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_trx_stickiness_off.ini --FILE-- query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] BEFORE [%d] '%s'\n", $offset, $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("[%03d] BEFORE id = %d\n", $offset, $row['_id']); } if (false == mysqlnd_ms_set_qos($link, $qos)) { printf("[%03d] [%d] '%s'\n", $offset, $link->errno, $link->error); } if (!($res = $link->query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] [%d] '%s'\n", $offset, $link->errno, $link->error); } else { printf("[%03d] AFTER [%d] '%s'\n", $offset, $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[%03d] AFTER id = %d\n", $offset, $row['_id']); } } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* autocommit, qos changes allowed at any time */ $link->autocommit(true); fetch_change_fetch(2, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); /* autocommit off, in transaction, qos changes shall not be allowed */ $link->autocommit(false); fetch_change_fetch(3, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); fetch_change_fetch(4, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); fetch_change_fetch(5, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* in transaction, forbid changes... */ $link->begin_transaction(); fetch_change_fetch(6, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); fetch_change_fetch(7, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); fetch_change_fetch(8, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow... */ fetch_change_fetch(9, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* disallow... */ $link->autocommit(false); $link->begin_transaction(); fetch_change_fetch(10, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); fetch_change_fetch(11, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* allow.. */ $link->autocommit(true); fetch_change_fetch(12, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* forbid... */ $link->begin_transaction(); fetch_change_fetch(13, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->rollback(); /* trx has ended - allow... */ fetch_change_fetch(14, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); $link->autocommit(false); $link->commit(); fetch_change_fetch(15, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); printf("[016] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [002] BEFORE id = 2 [002] AFTER [0] '' [002] AFTER id = 2 [003] BEFORE id = 3 [003] AFTER [0] '' [003] AFTER id = 3 [004] BEFORE id = 4 [004] AFTER [0] '' [004] AFTER id = 4 [005] BEFORE id = 5 [005] AFTER [0] '' [005] AFTER id = 5 [006] BEFORE id = 6 [006] AFTER [0] '' [006] AFTER id = 6 [007] BEFORE id = 7 [007] AFTER [0] '' [007] AFTER id = 7 [008] BEFORE id = 8 [008] AFTER [0] '' [008] AFTER id = 8 [009] BEFORE id = 9 [009] AFTER [0] '' [009] AFTER id = 9 [010] BEFORE id = 10 [010] AFTER [0] '' [010] AFTER id = 10 [011] BEFORE id = 11 [011] AFTER [0] '' [011] AFTER id = 11 [012] BEFORE id = 12 [012] AFTER [0] '' [012] AFTER id = 12 [013] BEFORE id = 13 [013] AFTER [0] '' [013] AFTER id = 13 [014] BEFORE id = 14 [014] AFTER [0] '' [014] AFTER id = 14 [015] BEFORE id = 15 [015] AFTER [0] '' [015] AFTER id = 15 [016] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_trx_stickiness_on.phpt0000664000175000017500000002034012161007456025050 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), trx stickiness --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); include_once("util.inc"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'trx_stickiness' => 'on', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_trx_stickiness_on.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_trx_stickiness_on.ini --FILE-- errno, $link->error); } if (!($res = $link->query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] [%d] '%s'\n", $offset, $link->errno, $link->error); } else { printf("[%03d] AFTER [%d] '%s'\n", $offset, $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[%03d] AFTER id = %d\n", $offset, $row['_id']); } } function fetch_change_fetch($offset, $link, $qos) { if (!($res = $link->query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] BEFORE [%d] '%s'\n", $offset, $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("[%03d] BEFORE id = %d\n", $offset, $row['_id']); } change_fetch($offset, $link, $qos); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* autocommit, qos changes allowed at any time */ $link->autocommit(true); fetch_change_fetch(2, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); /* fool around with state, allowed... */ $link->autocommit(false); $link->autocommit(true); change_fetch(3, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); /* autocommit off, in transaction, qos changes shall not be allowed */ $link->autocommit(false); fetch_change_fetch(4, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); fetch_change_fetch(5, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); $link->autocommit(false); /* autocommit off but no query run before change, allowed (could forbid as well, makes no difference) */ change_fetch(6, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); $link->autocommit(false); /* query has been run, server has been picked, not allowed */ fetch_change_fetch(7, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); /* autocommit, allow */ fetch_change_fetch(8, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* in transaction, forbid changes... */ $link->begin_transaction(); fetch_change_fetch(9, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); fetch_change_fetch(10, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); /* in trx, forbid */ fetch_change_fetch(11, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow, autocommit is on. */ fetch_change_fetch(12, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* disallow... */ $link->autocommit(false); $link->begin_transaction(); fetch_change_fetch(13, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); fetch_change_fetch(14, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow because no query has been run yet, we are in between transactions */ change_fetch(15, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* allow.. */ $link->autocommit(true); fetch_change_fetch(16, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* forbid... */ $link->begin_transaction(); fetch_change_fetch(17, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->rollback(); /* trx has ended - allow... */ fetch_change_fetch(18, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); $link->autocommit(false); $link->commit(); /* forbid, autocommit is off */ fetch_change_fetch(19, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow because no query has been run, we are in between transactions */ change_fetch(20, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); printf("[021] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [002] BEFORE id = 2 [002] AFTER [0] '' [002] AFTER id = 2 [003] AFTER [0] '' [003] AFTER id = 3 [004] BEFORE id = 4 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [004] [0] '' [004] AFTER [0] '' [004] AFTER id = 4 [005] BEFORE id = 5 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [005] [0] '' [005] AFTER [0] '' [005] AFTER id = 5 [006] AFTER [0] '' [006] AFTER id = 6 [007] BEFORE id = 7 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [007] [0] '' [007] AFTER [0] '' [007] AFTER id = 7 [008] BEFORE id = 8 [008] AFTER [0] '' [008] AFTER id = 8 [009] BEFORE id = 9 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [009] [0] '' [009] AFTER [0] '' [009] AFTER id = 9 [010] BEFORE id = 10 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [010] [0] '' [010] AFTER [0] '' [010] AFTER id = 10 [011] BEFORE id = 11 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [011] [0] '' [011] AFTER [0] '' [011] AFTER id = 11 [012] BEFORE id = 12 [012] AFTER [0] '' [012] AFTER id = 12 [013] BEFORE id = 13 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [013] [0] '' [013] AFTER [0] '' [013] AFTER id = 13 [014] BEFORE id = 14 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [014] [0] '' [014] AFTER [0] '' [014] AFTER id = 14 [015] AFTER [0] '' [015] AFTER id = 15 [016] BEFORE id = 16 [016] AFTER [0] '' [016] AFTER id = 16 [017] BEFORE id = 17 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [017] [0] '' [017] AFTER [0] '' [017] AFTER id = 17 [018] BEFORE id = 18 [018] AFTER [0] '' [018] AFTER id = 18 [019] BEFORE id = 19 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [019] [0] '' [019] AFTER [0] '' [019] AFTER id = 19 [020] AFTER [0] '' [020] AFTER id = 20 [021] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_set_qos_trx_stickiness_on_rr.phpt0000664000175000017500000002117112161007456025556 0ustar andreyandrey--TEST-- mysqlnd_ms_set_qos(), trx stickiness, RR --SKIPIF-- = 5.5.0, using " . PHP_VERSION)); require_once('skipif.inc'); require_once("connect.inc"); if (($emulated_master_host == $emulated_slave_host)) { die("SKIP master and slave seem to the the same, see tests/README"); } _skipif_check_extensions(array("mysqli")); include_once("util.inc"); $settings = array( "myapp" => array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'trx_stickiness' => 'on', 'lazy_connections' => 1, 'filters' => array( "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_set_qos_trx_stickiness_on_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_set_qos_trx_stickiness_on_rr.ini mysqlnd_ms.multi_master=1 --FILE-- errno, $link->error); } if (!($res = $link->query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] [%d] '%s'\n", $offset, $link->errno, $link->error); } else { printf("[%03d] AFTER [%d] '%s'\n", $offset, $link->errno, $link->error); $row = $res->fetch_assoc(); printf("[%03d] AFTER id = %d\n", $offset, $row['_id']); } } function fetch_change_fetch($offset, $link, $qos) { if (!($res = $link->query(sprintf("SELECT %d AS _id", $offset)))) { printf("[%03d] BEFORE [%d] '%s'\n", $offset, $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("[%03d] BEFORE id = %d\n", $offset, $row['_id']); } change_fetch($offset, $link, $qos); } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* autocommit, qos changes allowed at any time */ $link->autocommit(true); fetch_change_fetch(2, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); /* fool around with state, allowed... */ $link->autocommit(false); $link->autocommit(true); change_fetch(3, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); /* autocommit off, in transaction, qos changes shall not be allowed */ $link->autocommit(false); fetch_change_fetch(4, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); fetch_change_fetch(5, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); $link->autocommit(false); /* autocommit off but no query run before change, allowed (could forbid as well, makes no difference) */ change_fetch(6, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); $link->autocommit(false); /* query has been run, server has been picked, not allowed */ fetch_change_fetch(7, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); $link->autocommit(true); /* autocommit, allow */ fetch_change_fetch(8, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* in transaction, forbid changes... */ $link->begin_transaction(); fetch_change_fetch(9, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); fetch_change_fetch(10, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); /* in trx, forbid */ fetch_change_fetch(11, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow, autocommit is on. */ fetch_change_fetch(12, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* disallow... */ $link->autocommit(false); $link->begin_transaction(); fetch_change_fetch(13, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); fetch_change_fetch(14, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow because no query has been run yet, we are in between transactions */ change_fetch(15, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* allow.. */ $link->autocommit(true); fetch_change_fetch(16, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); /* forbid... */ $link->begin_transaction(); fetch_change_fetch(17, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->rollback(); /* trx has ended - allow... */ fetch_change_fetch(18, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->begin_transaction(); $link->autocommit(false); $link->commit(); /* forbid, autocommit is off */ fetch_change_fetch(19, $link, MYSQLND_MS_QOS_CONSISTENCY_SESSION); $link->commit(); /* allow because no query has been run, we are in between transactions */ change_fetch(20, $link, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL); printf("[021] [%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [002] BEFORE id = 2 [002] AFTER [0] '' [002] AFTER id = 2 [003] AFTER [0] '' [003] AFTER id = 3 [004] BEFORE id = 4 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [004] [0] '' [004] AFTER [0] '' [004] AFTER id = 4 [005] BEFORE id = 5 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [005] [0] '' [005] AFTER [0] '' [005] AFTER id = 5 [006] AFTER [0] '' [006] AFTER id = 6 [007] BEFORE id = 7 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [007] [0] '' [007] AFTER [0] '' [007] AFTER id = 7 [008] BEFORE id = 8 [008] AFTER [0] '' [008] AFTER id = 8 [009] BEFORE id = 9 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [009] [0] '' [009] AFTER [0] '' [009] AFTER id = 9 [010] BEFORE id = 10 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [010] [0] '' [010] AFTER [0] '' [010] AFTER id = 10 [011] BEFORE id = 11 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [011] [0] '' [011] AFTER [0] '' [011] AFTER id = 11 [012] BEFORE id = 12 [012] AFTER [0] '' [012] AFTER id = 12 [013] BEFORE id = 13 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [013] [0] '' [013] AFTER [0] '' [013] AFTER id = 13 [014] BEFORE id = 14 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [014] [0] '' [014] AFTER [0] '' [014] AFTER id = 14 [015] AFTER [0] '' [015] AFTER id = 15 [016] BEFORE id = 16 [016] AFTER [0] '' [016] AFTER id = 16 [017] BEFORE id = 17 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [017] [0] '' [017] AFTER [0] '' [017] AFTER id = 17 [018] BEFORE id = 18 [018] AFTER [0] '' [018] AFTER id = 18 [019] BEFORE id = 19 Warning: mysqlnd_ms_set_qos(): (mysqlnd_ms) No change allowed in the middle of a transaction in %s on line %d [019] [0] '' [019] AFTER [0] '' [019] AFTER id = 19 [020] AFTER [0] '' [020] AFTER id = 20 [021] [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_connect_flags_invalid.phpt0000664000175000017500000000337712161007456026011 0ustar andreyandrey--TEST-- Invalid connect flag (negative number and array) --SKIPIF-- array( 'master' => array( array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, 'db' => (string)$db, 'user' => $user, 'password' => $passwd, 'connect_flags' => -1, ), ), 'slave' => array( array( 'host' => $slave_host_only, 'port' => (double)$slave_port, 'socket' => $slave_socket, 'db' => $db, 'user' => $user, 'password' => $passwd, 'connect_flags' => array(-1), ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_connect_flags_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_connect_flags_invalid.ini --FILE-- --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) Invalid value for connect_flags '-1' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_connect_flags.phpt0000664000175000017500000000762512161007456024303 0ustar andreyandrey--TEST-- Connection flags --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, 'db' => (string)$db, 'user' => $user, 'password' => $passwd, 'connect_flags' => 0, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => (double)$emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, 'connect_flags' => 0, ), array( 'host' => $emulated_slave_host_only, 'port' => (double)$emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, 'connect_flags' => MYSQLI_CLIENT_FOUND_ROWS ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_connect_flags.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_connect_flags.ini --FILE-- affected_rows); $server_id = mst_mysqli_get_emulated_id(3, $link); $threads[$server_id] = "Slave 1 . I"; mst_mysqli_query(4, $link, "UPDATE test SET id = 1 WHERE id = 1", MYSQLND_MS_SLAVE_SWITCH); printf("Slave 2 - affected rows: %d\n", $link->affected_rows); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = "Slave 2"; mst_mysqli_query(6, $link, "DROP TABLE IF EXISTS test"); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = "Master"; mst_mysqli_query(8, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); $server_id = mst_mysqli_get_emulated_id(9, $link); $threads[$server_id] = "Slave 1 - II"; foreach ($threads as $id => $role) printf("%s - %s\n", $role, $id); print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1 - affected rows: 0 Slave 2 - affected rows: 1 Slave 1 - II - %s Slave 2 - %s Master - %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_db_invalid.phpt0000664000175000017500000000346312161007456023565 0ustar andreyandrey--TEST-- Invalid database (number and object) --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, 'db' => -1, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => new stdClass(), 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_db_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_db_invalid.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- %A Warning: mysqli_connect(): (%s/1049): %s '-1' %s %Amysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_default_lazy.phpt0000664000175000017500000000347612161007456024161 0ustar andreyandrey--TEST-- Config settings: many slaves --SKIPIF-- array( 'master' => array($host), 'slave' => array($host), ), ); /* in the hope that few Mysql test server are configures to handle 5000 connections */ for ($i = 0; $i < 1; $i++) $settings['do_not_overload_mysql']['slave'][] = $host; if ($error = mst_create_config("test_mysqlnd_ms_settings_force_many_slaves.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_force_many_slaves.ini --FILE-- query("SELECT 1 AS _one FROM DUAL")) printf("[002] [%d] %s\n", $link->errno, $link->error); $row = $res->fetch_assoc(); if ($row['_one'] != 1) { printf("[003] [%d] %s - Wrong results, dumping results.\n", $link->errno, $link->error); var_dump($rows); } $res->close(); if (!$res = $link->query("DROP TABLE IF EXISTS test")) printf("[004] [%d] %s\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_force_config.phpt0000664000175000017500000001253312161007456024113 0ustar andreyandrey--TEST-- INI setting: mysqlnd_ms.force_config_usage --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), 'lazy_connections' => 0, ), "192.168.14.17" => array( 'master' => array('forced_master_hostname_ip'), 'slave' => array('forced_slave_hostname_ip'), 'lazy_connections' => 0, ), "my_orginal_mysql_server_host" => array( 'master' => array('forced_master_hostname_orgname'), 'slave' => array('forced_slave_hostname_orgname'), 'lazy_connections' => 0, ), "lazy_default_and_no_error" => array( 'master' => array('forced_master_hostname_orgname'), 'slave' => array('forced_slave_hostname_orgname'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_ini_force_config.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage=1 mysqlnd_ms.config_file=test_mysqlnd_ms_ini_force_config.ini --FILE-- true, 2003 => true, 2005 => true, ); /* shall use host = forced_master_hostname_abstract_name from the ini file */ $link = @mst_mysqli_connect("name_of_a_config_section", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[001] Is this a valid code? [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $link = @mst_mysqli_connect("192.168.14.17", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[002] Is this a valid code? [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $link = @mst_mysqli_connect("my_orginal_mysql_server_host", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[003] Is this a valid code? [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (0 == mysqli_connect_errno()) { /* 0 means no error. This is documented behaviour! */ $res = $link->query("SELECT 'This connection should have been forbidden!'"); $row = $res->fetch_row(); printf("[004] %s\n", $row[0]); } else if (2000 == mysqli_connect_errno()) { /* Error: 2000 (CR_UNKNOWN_ERROR), HYOOO */ printf("[005] Connection failed. The plugin can't set a specific error code as none exists, we go for unspecific code 2000 (CR_UNKNOWN_ERROR), [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[006] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $link = @mst_mysqli_connect("lazy_default_and_no_error", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[007] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[008] No error because no connection yet [%d] '%s'\n", mysqli_connect_errno(), mysqli_connect_error()); } /* error is delayed due to lazy */ @$link->query("DROP TABLE IF EXISTS test"); if (isset($mst_connect_errno_codes[mysqli_errno($link)])) { printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } else { printf("[010] Unexpected error [%d] '%s'\n", mysqli_errno($link), mysqli_error($link)); } /* error */ $link = @mst_mysqli_connect("i_hope_there_is_no_such_host", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[011] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[011] Is this a valid code? [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [001] [%d] %s [002] [%d] %s [003] [%d] %s Warning: mysqli_real_connect(): (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section (%s) in %s on line %d Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section in %s on line %d [005] Connection failed. The plugin can't set a specific error code as none exists, we go for unspecific code 2000 (CR_UNKNOWN_ERROR), [2000] (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section [008] No error because no connection yet [%d] '' [009] [%d] %s [011] Is this a valid code? [2000] (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_host_credentials_inherit.phpt0000664000175000017500000001005112161007456026535 0ustar andreyandrey--TEST-- Per host credentials --SKIPIF-- array( 'master' => array( 'master1' => array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_host_credentials_inherit.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_host_credentials_inherit.ini --FILE-- query($query))) printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); return $ret; } /* note that user etc are to be taken from the config! */ if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, NULL, NULL))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $threads = array(); /* slave 1 */ my_mysqli_query(2, $link, "SELECT 1 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(3, $link); $threads[$server_id] = array('role' => 'Slave 1', 'stat' => $link->stat()); /* master */ my_mysqli_query(4, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Master', 'stat' => $link->stat()); /* slave 2 */ my_mysqli_query(6, $link, "SELECT 2 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = array('role' => 'Slave 2', 'stat' => $link->stat()); $res = my_mysqli_query(8, $link, "SELECT DATABASE() AS _db FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($db != $row['_db']) printf("[009] Expecting database '%s' got '%s'\n", $ddb, $row['_db']); foreach ($threads as $server_id => $details) { printf("%s - %s: '%s'\n", $server_id, $details['role'], $details['stat']); if ('' == $details['stat']) printf("Server stat must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %s - Slave 1: '%s' %s - Master: '%s' %s - Slave 2: '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_host_credentials_invalid.phpt0000664000175000017500000000732012161007456026526 0ustar andreyandrey--TEST-- Per host credentials, invalid --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host, 'port' => PHP_INT_MAX, 'socket' => false, 'db' => array("db"), 'user' => NULL, 'password' => -1, 'connect_flags' => -1, ), ), 'slave' => array( array( 'host' => $emulated_slave_host, 'port' => -1, 'socket' => array(), 'db' => NULL, 'user' => array(), 'password'=> array(), 'connect_flags' => array(), ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_host_credentials_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_host_credentials_invalid.ini --FILE-- real_query($query)) printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); if (!($res = $link->use_result())) printf("[%03d + 02] [%d] %s\n", $offset, $link->errno, $link->error); while ($row = $res->fetch_assoc()) printf("[%03d + 03] '%s'\n", $offset, $row['_one']); } /* note that user etc are to be taken from the config! */ if (!($link = mst_mysqli_connect("myapp", NULL, NULL, NULL, NULL, NULL))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $threads = array(); /* slave 1 */ my_mysqli_query(2, $link, "SELECT 1 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(3, $link); $threads[$server_id] = array('role' => 'Slave 1', 'stat' => $link->stat()); /* master */ my_mysqli_query(4, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Master', 'stat' => $link->stat()); foreach ($threads as $server_id => $details) { printf("%s - %s: '%s'\n", $server_id, $details['role'], $details['stat']); if ('' == $details['stat']) printf("Server stat must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) Invalid value for connect_flags '-1' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_host_credentials_types.phpt0000664000175000017500000000327112161007456026245 0ustar andreyandrey--TEST-- Per host credentials --SKIPIF-- array( 'master' => array( array( 'host' => $master_host_only, 'port' => 123, 'socket' => PHP_INT_MAX * 2, 'db' => 1.124, 'user' => array($user), 'password' => $obj, ), ), 'slave' => array( array( 'host' => $slave_host_only, 'port' => 456.78, 'socket' => "an", 'db' => false, 'user' => NULL, 'password'=> 123, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_host_credentials_types.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_host_credentials_types.ini --FILE-- --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) Invalid value for user. Cannot be a list/hash' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_bool_false_aus.phpt0000664000175000017500000000211112161007456025273 0ustar andreyandrey--TEST-- INI parser: string "aus" = bool false --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_ini_bool_false_aus.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage=aus mysqlnd_ms.config_file=test_mysqlnd_ms_ini_bool_false_aus.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_bool_false_false.phpt0000664000175000017500000000213112161007456025577 0ustar andreyandrey--TEST-- INI parser: string "false" = bool false --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_ini_bool_false_false.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage="false" mysqlnd_ms.config_file=test_mysqlnd_ms_ini_bool_false_false.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_bool_false_off.phpt0000664000175000017500000000254712161007456025272 0ustar andreyandrey--TEST-- INI parser: string "off" = bool false --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_ini_bool_false_off.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2,3]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage=off mysqlnd_ms.config_file=test_mysqlnd_ms_ini_bool_false_off.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_bool_false_zero.phpt0000664000175000017500000000210412161007456025464 0ustar andreyandrey--TEST-- INI parser: int 0 = bool false --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), ), ); if ($error = mst_create_config("test_mysqlnd_ms_ini_bool_false_zero.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage=0 mysqlnd_ms.config_file=test_mysqlnd_ms_ini_bool_false_zero.ini --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_bool_true.phpt0000664000175000017500000000337012161007456024320 0ustar andreyandrey--TEST-- INI parser: anything that is not false is true --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_ini_bool_true.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage="gurkensalat" mysqlnd_ms.config_file=test_mysqlnd_ms_ini_bool_true.ini --FILE-- true, 2003 => true, 2005 => true, ); /* shall use host = forced_master_hostname_abstract_name from the ini file */ $link = @mst_mysqli_connect("name_of_a_config_section", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[001] Looks like the config has not been interpreted correctly [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [001] [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_file_faulty.phpt0000664000175000017500000000242212161007456024626 0ustar andreyandrey--TEST-- mysqlnd_ms: Faulty ini file --SKIPIF-- --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_ini_file_faulty.ini --FILE-- query("SELECT 1 FROM DUAL"))) printf("[002] [%d] %s\n", $link->errno, $link->error); var_dump($res->fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- %A [001] [%d] %s Fatal error: Call to a member function query() on a non-object in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_file_invalid.phpt0000664000175000017500000000062212161007456024750 0ustar andreyandrey--TEST-- mysqlnd_ms: Invalid ini file --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=a_file_by_this_name_better_not_exists.ini --FILE-- --EXPECTF-- Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0 Warning: Unknown: (mysqlnd_ms) Failed to open server list config file [a_file_by_this_name_better_not_exists.ini] in Unknown on line 0 DONEmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_file_json_empty.phpt0000664000175000017500000000271512161007456025516 0ustar andreyandrey--TEST-- Empty config file --SKIPIF-- --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_ini_file_json_empty.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (mysqlnd_ms) (mysqlnd_ms) Config file [test_mysqlnd_ms_settings_ini_file_json_empty.ini] is empty. If this is not by mistake, please add some minimal JSON to it to prevent this warning. For example, use '{}' in %s on line %d Warning: mysqli_real_connect(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d Warning: mysqli_real_connect(): (HY000/2002): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [001] Cannot connect to the server using %A done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_ini_file_json_stub.phpt0000664000175000017500000000205412161007456025331 0ustar andreyandrey--TEST-- Config file with nothing but {} --SKIPIF-- --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_ini_file_json_stub.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): %A [001] Cannot connect to the server using host=%s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_no_host.phpt0000664000175000017500000000360612161007456023142 0ustar andreyandrey--TEST-- No hostname --SKIPIF-- array( 'master' => array( array( 'port' => (int)$master_port, 'socket' => $master_socket, 'db' => (string)$db, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'port' => (double)$slave_port, 'socket' => $slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_no_host.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_no_host.ini --FILE-- --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) Cannot find [host] in [master] section in config in %s on line %d [E_WARNING] mysqli_real_connect(): (mysqlnd_ms) Error while connecting to the master(s) in %s on line %d [E_WARNING] mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Cannot find [host] in section in config in %s on line %d [001] [2000] (mysqlnd_ms) Cannot find [host] in section in config done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_no_json.phpt0000664000175000017500000000410012161007456023124 0ustar andreyandrey--TEST-- Invalid config format --SKIPIF-- --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_no_json.ini mysqlnd_ms.in_regression_tests=1 --FILE-- --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) (mysqlnd_ms) Failed to parse config file [test_mysqlnd_ms_settings_no_json.ini]. Please, verify the JSON in %s on line %d [E_WARNING] mysqli_real_connect(): (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section (myapp) in %s on line %d [E_WARNING] mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section in %s on line %d [001] [2000] (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_password_invalid.phpt0000664000175000017500000000364312161007456025042 0ustar andreyandrey--TEST-- Invalid password (number and array) --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password' => array(-1), ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> array(1, 2, 3), ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_password_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_password_invalid.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_connect(): (mysqlnd_ms) Invalid value for password. Cannot be a list/hash' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_plugin_conf_false_aus.phpt0000664000175000017500000000400612161007456026011 0ustar andreyandrey--TEST-- JSON aus == false --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'pick' => array("random" => array('sticky' => 'aus')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_plugin_conf_false_aus.ini", $settings)) die(sprintf("SKIP %s\n", $error)); require_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_plugin_conf_false_aus.ini --FILE-- = 100) printf("[002] Server has never changed, sticky on?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_plugin_conf_false_false.phpt0000664000175000017500000000402412161007456026313 0ustar andreyandrey--TEST-- JSON 'false' == false --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'pick' => array("random" => array('sticky' => 'false')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_plugin_conf_false_false.ini", $settings)) die(sprintf("SKIP %s\n", $error)); require_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_plugin_conf_false_false.ini --FILE-- = 100) printf("[002] Server has never changed, sticky on?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_plugin_conf_false_off.phpt0000664000175000017500000000400612161007456025773 0ustar andreyandrey--TEST-- JSON off == false --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'pick' => array("random" => array('sticky' => 'off')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_plugin_conf_false_off.ini", $settings)) die(sprintf("SKIP %s\n", $error)); require_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_plugin_conf_false_off.ini --FILE-- = 100) printf("[002] Server has never changed, sticky on?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_plugin_conf_false_zero.phpt0000664000175000017500000000401012161007456026173 0ustar andreyandrey--TEST-- JSON '0' == false --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'pick' => array("random" => array('sticky' => '0')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_plugin_conf_false_zero.ini", $settings)) die(sprintf("SKIP %s\n", $error)); require_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_plugin_conf_false_zero.ini --FILE-- = 100) printf("[002] Server has never changed, sticky on?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_plugin_conf_true_empty.phpt0000664000175000017500000000406612161007456026252 0ustar andreyandrey--TEST-- JSON '' == true --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_master_host), 'pick' => array("random" => array('sticky' => '')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_plugin_conf_false_empty.ini", $settings)) die(sprintf("SKIP %s\n", $error)); require_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_plugin_conf_false_empty.ini --FILE-- = 100) printf("[002] Server has never changed, sticky on?\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- [002] Server has never changed, sticky on? done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_port_invalid2.phpt0000664000175000017500000000362712161007456024250 0ustar andreyandrey--TEST-- Invalid port (out of range: too big) --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => 65536, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => 65536, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_port_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_port_invalid.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_connect(): (mysqlnd_ms) Invalid value for port '%s' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_port_invalid.phpt0000664000175000017500000000364012161007456024161 0ustar andreyandrey--TEST-- Invalid port (out of range: negative) --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => -1 * PHP_INT_MAX, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => -1, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_port_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_port_invalid.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_connect(): (mysqlnd_ms) Invalid value for port '%s' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_port_wrong_master.phpt0000664000175000017500000000413412161007456025241 0ustar andreyandrey--TEST-- Wrong port (9999), master --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => 9999, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_port_wrong_master.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_port_wrong_master.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli_connect(): (mysqlnd_ms) Cannot connect to %s in %s on line %d Warning: mysqli_connect(): (mysqlnd_ms) Error while connecting to the master(s) in %s on line %d %Amysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_port_wrong_slave.phpt0000664000175000017500000000407112161007456025060 0ustar andreyandrey--TEST-- Wrong port (9999), slave --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => 9999, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_port_wrong_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_port_wrong_slave.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- %Aarning: mysqli_connect(): (mysqlnd_ms) Cannot connect to %s in %s on line %d Warning: mysqli_connect(): (mysqlnd_ms) Error while connecting to the slaves in %s on line %d %Amysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_server_charset_invalid.phpt0000664000175000017500000000336012161007456026213 0ustar andreyandrey--TEST-- Invalid server_charset --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "random" => array('sticky' => '1'), ), 'server_charset' => "\0please_let_me_be_invalid", ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_offline_charset_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_offline_charset_invalid.ini --FILE-- real_escape_string($text))) { printf("[002] [%d/%s] '%s'\n", $link->errno, $link->sqlstate, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli_real_connect(): (mysqlnd_ms) Erroneous server_charset [] in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_socket_invalid.phpt0000664000175000017500000000366312161007456024472 0ustar andreyandrey--TEST-- Invalid socket (array and number) --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => array(1), 'db' => $db, 'user' => $user, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => -1, 'db' => $db, 'user' => $user, 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_socket_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_socket_invalid.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_connect(): (mysqlnd_ms) Invalid value for socket. Cannot be a list/hash' . Stopping in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_unknown_section_force_config.phpt0000664000175000017500000000364012161007456027415 0ustar andreyandrey--TEST-- Connect using unkonwn config section, force use of config --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_unknown_section_force_config.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_unknown_section_force_config.ini mysqlnd_ms.force_config_usage=1 --FILE-- true, 2003 => true, 2005 => true, ); /* shall use host = forced_master_hostname_abstract_name from the ini file */ $link = @mst_mysqli_connect("please_let_this_host_be_unknown", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[001] Is this a valid code? [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [001] [2000] (mysqlnd_ms) Exclusive usage of configuration enforced but did not find the correct INI file section done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_unknown_section.phpt0000664000175000017500000000332312161007456024710 0ustar andreyandrey--TEST-- Connect using unkonwn config section --SKIPIF-- array( 'master' => array('forced_master_hostname_abstract_name'), 'slave' => array('forced_slave_hostname_abstract_name'), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_unknown_section.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_unknown_section.ini --FILE-- true, 2003 => true, 2005 => true, ); /* shall use host = forced_master_hostname_abstract_name from the ini file */ $link = @mst_mysqli_connect("please_let_this_host_be_unknown", $user, $passwd, $db, $port, $socket); if (isset($mst_connect_errno_codes[mysqli_connect_errno()])) { printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } else { printf("[001] Is this a valid code? [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [001] [%d] %s done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_settings_user_invalid.phpt0000664000175000017500000000432612161007456024155 0ustar andreyandrey--TEST-- Invalid user (number and object) --SKIPIF-- array( 'master' => array( array( 'host' => $emulated_master_host_only, 'port' => $emulated_master_port, 'socket' => $emulated_master_socket, 'db' => $db, 'user' => -1, 'password' => $passwd, ), ), 'slave' => array( array( 'host' => $emulated_slave_host_only, 'port' => $emulated_slave_port, 'socket' => $emulated_slave_socket, 'db' => $db, 'user' => new stdClass(), 'password'=> $passwd, ), ), 'pick' => 'roundrobin', 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_settings_user_invalid.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_settings_user_invalid.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- %A Warning: mysqli_connect(): (mysqlnd_ms) Error while connecting to the master(s) in %s on line %d %A Fatal error: Call to a member function query() on a non-object in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_simple.phpt0000664000175000017500000000321012161007456021031 0ustar andreyandrey--TEST-- Simple --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.force_config_usage=0 mysqlnd_ms.config_file=test_mysqlnd_ms_simple.ini --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_simple.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --FILE-- query("/*ms=slave*/SELECT user from mysql.user")); var_dump($res2=$link->query("/*ms=master*/SELECT user from mysql.user")); var_dump($res3=$link->query("/*ms=master*/SELECT user from mysql.user")); print "done!"; ?> --CLEAN-- --EXPECTF-- object(mysqli_result)#%d (5) { ["current_field"]=> int(0) ["field_count"]=> int(1) ["lengths"]=> NULL ["num_rows"]=> int(%d) ["type"]=> int(0) } object(mysqli_result)#%d (5) { ["current_field"]=> int(0) ["field_count"]=> int(1) ["lengths"]=> NULL ["num_rows"]=> int(%d) ["type"]=> int(0) } object(mysqli_result)#%d (5) { ["current_field"]=> int(0) ["field_count"]=> int(1) ["lengths"]=> NULL ["num_rows"]=> int(%d) ["type"]=> int(0) } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_slave_unreachable_random_once.phpt0000664000175000017500000000467012161007456025562 0ustar andreyandrey--TEST-- Unreachable slave, pick = random once, lazy = 0 --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, "unknown_i_really_hope", $slave_host), 'pick' => array('random' => array('sticky' => '1')), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_slave_unreachable_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_slave_unreachable_random_once.ini mysqlnd_ms.collect_statistics=1 --FILE-- --CLEAN-- --EXPECTF-- Stats non_lazy_connections_slave_success: 2 Stats non_lazy_connections_slave_failure: 1 Stats non_lazy_connections_master_success: 1 [003] OK, plugin reports connect error, [%d] %s mysqlnd_ms-1.5.2/tests/mysqlnd_ms_slave_unreachable_random.phpt0000664000175000017500000000460512161007456024554 0ustar andreyandrey--TEST-- Unreachable slave, pick = random, lazy = 0 --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, "unknown_i_really_hope", $slave_host), 'pick' => array("ramdom"), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_slave_unreachable_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_slave_unreachable_random.ini mysqlnd_ms.collect_statistics=1 --FILE-- --CLEAN-- --EXPECTF-- Stats non_lazy_connections_slave_success: 2 Stats non_lazy_connections_slave_failure: 1 Stats non_lazy_connections_master_success: 1 [003] OK, plugin reports connect error, [%d] %s mysqlnd_ms-1.5.2/tests/mysqlnd_ms_slave_unreachable_rr.phpt0000664000175000017500000000456512161007456023724 0ustar andreyandrey--TEST-- Unreachable slave, pick = rr, lazy = 0 --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, "unknown_i_really_hope", $slave_host), 'pick' => array('roundrobin'), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_slave_unreachable_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_slave_unreachable_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- --CLEAN-- --EXPECTF-- Stats non_lazy_connections_slave_success: 2 Stats non_lazy_connections_slave_failure: 1 Stats non_lazy_connections_master_success: 1 [003] OK, plugin reports connect error, [%d] %s mysqlnd_ms-1.5.2/tests/mysqlnd_ms_slave_unreachable_user.phpt0000664000175000017500000000637212161007456024255 0ustar andreyandrey--TEST-- Unreachable slave, pick = user, lazy = 0 --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, "unknown_i_really_hope", $slave_host), 'pick' => array('user' => array('callback' => 'pick_server')), 'lazy_connections' => 0, ), ); if ($error = mst_create_config("test_mysqlnd_ms_slave_unreachable_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- error_reporting=E_ALL mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_slave_unreachable_rr.ini mysqlnd_ms.collect_statistics=1 --FILE-- --CLEAN-- --EXPECTF-- Stats non_lazy_connections_slave_success: 2 Stats non_lazy_connections_slave_failure: 1 Stats non_lazy_connections_master_success: 1 [003] OK, plugin reports connect error, [%d] %s mysqlnd_ms-1.5.2/tests/mysqlnd_ms_sql_hints.phpt0000664000175000017500000001452712161007456021561 0ustar andreyandrey--TEST-- SQL hints to control query redirection --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_sql_hints.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_sql_hints.ini --FILE-- query($query)) { printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); return false; } if ($expected) { $row = $res->fetch_assoc(); $res->close(); if (empty($row)) { printf("[%03d + 02] [%d] %s, empty result\n", $offset, $link->errno, $link->error); return false; } if ($row != $expected) { printf("[%03d + 03] Unexpected results, dumping data\n", $offset); var_dump($row); var_dump($expected); return false; } } return true; } if (!$link = mst_mysqli_connect("myapp", $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); $expected = array(); my_mysqli_query(10, $link, sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_MASTER_SWITCH), $expected); $emulated_master_thread_id = $link->thread_id; $emulated_master = mst_mysqli_get_emulated_id(11, $link); my_mysqli_query(20, $link, sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH), $expected); $emulated_slave_thread_id = $link->thread_id; $emulated_slave = mst_mysqli_get_emulated_id(21, $link); my_mysqli_query(30, $link, sprintf("/*%s*/CREATE TABLE test(id INT)", MYSQLND_MS_MASTER_SWITCH), $expected); my_mysqli_query(40, $link, sprintf("/*%s*/CREATE TABLE test(id INT)", MYSQLND_MS_SLAVE_SWITCH), $expected); my_mysqli_query(50, $link, sprintf("/*%s*/INSERT INTO test(id) VALUES (CONNECTION_ID())", MYSQLND_MS_SLAVE_SWITCH), $expected); my_mysqli_query(60, $link, sprintf("/*%s*/INSERT INTO test(id) VALUES (CONNECTION_ID())", MYSQLND_MS_MASTER_SWITCH), $expected); my_mysqli_query(70, $link, sprintf("/*%s*/SET @myrole='master'", MYSQLND_MS_MASTER_SWITCH), $expected); my_mysqli_query(80, $link, sprintf("/*%s*/SET @myrole='slave'", MYSQLND_MS_SLAVE_SWITCH), $expected); /* slave, no hint */ $expected = array('_role' => 'slave'); my_mysqli_query(90, $link, "SELECT @myrole AS _role", $expected); $server_id = mst_mysqli_get_emulated_id(91, $link); if ($server_id != $emulated_slave) printf("[092] Query should have been run on the slave\n"); /* master, no hint */ $expected = array(); my_mysqli_query(100, $link, "INSERT INTO test(id) VALUES (-2)", $expected); $server_id = mst_mysqli_get_emulated_id(101, $link); if ($server_id != $emulated_master) printf("[102] Query should have been run on the master\n"); /* ... boring: slave */ $expected = array("id" => $emulated_slave_thread_id); my_mysqli_query(110, $link, sprintf("/*%s*/SELECT id FROM test", MYSQLND_MS_SLAVE_SWITCH), $expected); $server_id = mst_mysqli_get_emulated_id(111, $link); if ($server_id != $emulated_slave) printf("[112] Query should have been run on the slave\n"); /* master, no hint */ $expected = array(); my_mysqli_query(120, $link, "DELETE FROM test WHERE id = -2", $expected); $server_id = mst_mysqli_get_emulated_id(121, $link); if ($server_id != $emulated_master) printf("[122] Query should have been run on the master\n"); /* master, forced */ $expected = array("id" => $emulated_master_thread_id); my_mysqli_query(130, $link, sprintf("/*%s*/SELECT id FROM test", MYSQLND_MS_MASTER_SWITCH), $expected); $server_id = mst_mysqli_get_emulated_id(131, $link); if ($server_id != $emulated_master) printf("[132] Query should have been run on the master\n"); /* master, forced */ $expected = array("_role" => 'master'); my_mysqli_query(140, $link, sprintf("/*%s*/SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH), $expected); $server_id = mst_mysqli_get_emulated_id(141, $link); if ($server_id != $emulated_master) printf("[142] Query should have been run on the master\n"); /* slave, forced */ $expected = array(); my_mysqli_query(150, $link, sprintf("/*%s*/INSERT INTO test(id) VALUES (0)", MYSQLND_MS_SLAVE_SWITCH), $expected); $server_id = mst_mysqli_get_emulated_id(151, $link); if ($server_id != $emulated_slave) printf("[152] Query should have been run on the slave\n"); $expected = array('_role' => 'slave'); my_mysqli_query(160, $link, sprintf("/*%s*/SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH), $expected); $server_id = mst_mysqli_get_emulated_id(161, $link); if ($server_id != $emulated_slave) printf("[162] Query should have been run on the slave\n"); $expected = array(); my_mysqli_query(170, $link, sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_MASTER_SWITCH), $expected); my_mysqli_query(180, $link, sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH), $expected); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_sql_hints_space.phpt0000664000175000017500000001013212161007456022720 0ustar andreyandrey--TEST-- SQL hints padded with whitespace --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_sql_hints_space.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_sql_hints_space.ini --FILE-- query($query)) { printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); return false; } if ($expected) { $row = $res->fetch_assoc(); $res->close(); if (empty($row)) { printf("[%03d + 02] [%d] %s, empty result\n", $offset, $link->errno, $link->error); return false; } if ($row != $expected) { printf("[%03d + 03] Unexpected results, dumping data\n", $offset); var_dump($row); var_dump($expected); return false; } } return true; } if (!$link = mst_mysqli_connect("myapp", $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); $expected = array(); /* for simplicty lets assume those work, there's a dedicated test to check they do */ my_mysqli_query(10, $link, sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_MASTER_SWITCH), $expected); $emulated_master_thread_id = $link->thread_id; $emulated_master = mst_mysqli_get_emulated_id(11, $link); my_mysqli_query(20, $link, sprintf("/*%s*/DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH), $expected); $emulated_slave_thread_id = $link->thread_id; $emulated_slave = mst_mysqli_get_emulated_id(21, $link); my_mysqli_query(30, $link, sprintf("/* %s */CREATE TABLE test(id INT)", MYSQLND_MS_MASTER_SWITCH), $expected); if ($emulated_master != ($tmp = mst_mysqli_get_emulated_id(31, $link))) { printf("[032] Expecting master got %s\n", $tmp); } my_mysqli_query(40, $link, sprintf("/* %s*/CREATE TABLE test(id INT)", MYSQLND_MS_SLAVE_SWITCH), $expected); if ($emulated_slave != ($tmp = mst_mysqli_get_emulated_id(41, $link))) { printf("[042] Expecting slave got %s\n", $tmp); } my_mysqli_query(50, $link, sprintf("/*%s */INSERT INTO test(id) VALUES (CONNECTION_ID())", MYSQLND_MS_SLAVE_SWITCH), $expected); if ($emulated_slave != ($tmp = mst_mysqli_get_emulated_id(51, $link))) { printf("[052] Expecting slave got %s\n", $tmp); } my_mysqli_query(60, $link, sprintf("/**/INSERT INTO test(id) VALUES (CONNECTION_ID())"), $expected); if ($emulated_master != ($tmp = mst_mysqli_get_emulated_id(61, $link))) { printf("[062] Expecting master got %s\n", $tmp); } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_stat.phpt0000664000175000017500000000560712161007456020527 0ustar andreyandrey--TEST-- mysqli->stat --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_stat.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_stat.ini --FILE-- 'Slave 1', 'stat' => $link->stat()); /* slave 2 */ mst_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Slave 2', 'stat' => $link->stat()); /* master */ mst_mysqli_query(6, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = array('role' => 'Master', 'stat' => $link->stat()); foreach ($threads as $server_id => $details) { printf("%s - %s: '%s'\n", $server_id, $details['role'], $details['stat']); if ('' == $details['stat']) printf("Server stat must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %s - Slave 1: '%s' %s - Slave 2: '%s' %s - Master: '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_assorted_slave.phpt0000664000175000017500000000637512161007456023744 0ustar andreyandrey--TEST-- table filter basics: leak --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (double)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".test1%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_assorted_slave.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_assorted_slave.ini --FILE-- fetch_assoc()); } $server_id = mst_mysqli_get_emulated_id(6, $link); if ($server_id == $emulated_master) printf("[007] Master has replied to slave query\n"); if (!is_null($server_id)) printf("[008] Connected to some server, but which one?\n"); printf("[009] [%s/%d] %s\n", $link->sqlstate, $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- [009] [HY000/2002] Some meaningful message from mysqlnd_ms, e.g. some connect error done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_basics.phpt0000664000175000017500000000451612161007456022165 0ustar andreyandrey--TEST-- table filter basics --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test%" => array( "master" => array("master2"), "slave" => array("slave1"), ), "%" => array( "master" => array("master1"), "slave" => array("master1"), ) ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_basics.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_basics.ini --FILE-- master 1 */ mst_mysqli_verbose_query(3, $link, "DROP TABLE IF EXISTS ulf"); /* db.test1 -> master 2 -> no such host */ mst_mysqli_verbose_query(4, $link, "DROP TABLE IF EXISTS test1"); print "done!"; ?> --CLEAN-- --EXPECTF-- [003 + 01] Query 'DROP TABLE IF EXISTS ulf' [003 + 02] Thread '%d' [004 + 01] Query 'DROP TABLE IF EXISTS test1' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [004] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004 + 02] Thread '%d' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_db_detection.phpt0000664000175000017500000000553312161007456023344 0ustar andreyandrey--TEST-- table filter: db name detection --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( "host" => "unknown_master_i_hope", ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( "host" => "unknown_slave_i_hope", ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master"=> array("master2"), "slave" => array("slave2"), ), ), ), "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_db_detection.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_db_detection.ini mysqlnd_ms.multi_master=1 --FILE-- db.% rule -> master2 */ mst_mysqli_query(3, $link, "DROP TABLE IF EXISTS test"); $threads[$link->thread_id] = array("master2"); /* db.test -> db.% rule -> slave2 */ mst_mysqli_query(4, $link, "SELECT * FROM test"); $threads[$link->thread_id][] = "slave2"; /* db.test -> db.% rule -> slave2 */ mst_mysqli_query(5, $link, sprintf("SELECT * FROM %s.test", $db)); $threads[$link->thread_id][] = "slave2"; if ($link->select_db("i_hope_this_db_does_not_exist")) printf("[006] Database 'i_hope_this_db_does_not_exist' exists, test will fail\n"); /* current db unchanged, db.test -> db.% rule -> slave2 */ mst_mysqli_query(7, $link, "SELECT * FROM test"); $threads[$link->thread_id][] = "slave2"; foreach ($threads as $thread_id => $roles) { printf("%d: ", $thread_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %Aonnect error, [003] [%d] %s %Aonnect error, [004] [%d] %s %Aonnect error, [005] [%d] %s %Aonnect error, [007] [%d] %s 0: master2,slave2,slave2,slave2, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_dual.phpt0000664000175000017500000000701512161007456021643 0ustar andreyandrey--TEST-- table filter: SELECT * FROM DUAL (no db) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( "host" => "unknown_master_i_hope", ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( "host" => "unknown_slave_i_hope", ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master"=> array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_dual.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_dual.ini --FILE-- $roles) { printf("%s: ", $server_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %s: slave1, slave1, %s: master1, master1, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_evaluation_order.phpt0000664000175000017500000000753512161007456024267 0ustar andreyandrey--TEST-- table filter: rule evaluation order --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( "host" => "unknown_master_i_hope", ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( "host" => "unknown_slave_i_hope", ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( "%" => array( "master"=> array("master2"), "slave" => array("slave1"), ), $db . ".test%" => array( "master"=> array("master1"), "slave" => array("slave2"), ), ), ), "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_evaluation_order.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_evaluation_order.ini mysqlnd_ms.multi_master=1 --FILE-- master 2 -> error */ $threads = array(); if (!@mysqli_query($link, "DROP TABLE IF EXISTS best")) { if (isset($mst_connect_errno_codes[$link->errno])) { printf("Connect error, "); } printf("[%d] %s\n", $link->errno, $link->error); } $threads[$link->thread_id] = array("master2"); /* db.test but match all rule at the beginning -> slave 1 -> no error */ mst_mysqli_create_test_table($emulated_slave_host_only, $user, $passwd, $db, $port, $socket); if ($res = mst_mysqli_query(4, $link, "SELECT 1 FROM test")) var_dump($res->fetch_assoc()); $threads[mst_mysqli_get_emulated_id(5, $link)] = array('slave1'); foreach ($threads as $server_id => $roles) { printf("%s: ", $server_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %Aonnect error, [%d] %s array(1) { [1]=> string(1) "1" } 0: master2, %s: slave1, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_evaluation_order_qualified_first.phpt0000664000175000017500000000730112161007456027510 0ustar andreyandrey--TEST-- table filter: rule evaluation order --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), "master2" => array( "host" => "unknown_master_i_hope", ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), "slave2" => array( "host" => "unknown_slave_i_hope", ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test" => array( "master"=> array("master1"), "slave" => array("slave2"), ), "%" => array( "master"=> array("master2"), "slave" => array("slave1"), ), ), ), "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_evaluation_order_qualified_first.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master[1]"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_evaluation_order_qualified_first.ini mysqlnd_ms.multi_master=1 --FILE-- db.test rule -> master 1 */ mst_mysqli_query(3, $link, "DROP TABLE IF EXISTS test"); $threads[mst_mysqli_get_emulated_id(4, $link)] = array("master1"); /* db.test2 -> % rule -> master 2 */ mst_mysqli_query(5, $link, "DROP TABLE IF EXISTS test2"); $threads[$link->thread_id] = array("master2"); /* db.test -> db.test rule -> slave 2 */ if ($res = mst_mysqli_query(5, $link, "SELECT 1 FROM test")) var_dump($res->fetch_assoc()); $threads[$link->thread_id][] = 'slave2'; foreach ($threads as $server_id => $roles) { printf("%s: ", $server_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- %Aonnect error, [004] [%d] %s %Aonnect error, [005] [%d] %s %s: master1, 0: master2,slave2, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_master_no_match_random_once.phpt0000664000175000017500000000437512161007456026433 0ustar andreyandrey--TEST-- table filter: no master for DROP, pick = random once --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . "%" => array( "master" => array("master2"), "slave" => array("slave1"), ), ), ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_master_no_match_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_master_no_match_random_once.ini --FILE-- no matching master -> no such host */ if (!$link->query("DROP TABLE IF EXISTS test")) { printf("[003] Warn user about misconfiguration, [%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] Warn user about misconfiguration, [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_master_no_match_random.phpt0000664000175000017500000000432712161007456025424 0ustar andreyandrey--TEST-- table filter: no master for DROP, pick = random --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . "%" => array( "master" => array("master2"), "slave" => array("slave1"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_master_no_match_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_master_no_match_random.ini --FILE-- no matching master -> no such host */ if (!$link->query("DROP TABLE IF EXISTS test")) { printf("[003] Warn user about misconfiguration, [%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] Warn user about misconfiguration, [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_master_no_match_rr.phpt0000664000175000017500000000430712161007456024565 0ustar andreyandrey--TEST-- table filter: no master for DROP, pick = rr --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . "%" => array( "master" => array("master2"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_master_no_match_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_master_no_match_rr.ini --FILE-- no matching master -> no such host */ if (!$link->query("DROP TABLE IF EXISTS test")) { printf("[003] Warn user about misconfiguration, [%d] %s\n", $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] Warn user about misconfiguration, [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_master_ref_slave_rr.phpt0000664000175000017500000000617512161007456024750 0ustar andreyandrey--TEST-- table filter: master referencing slave (rr) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("slave1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_master_ref_slave_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_master_ref_slave_rr.ini --FILE-- fetch_assoc()); } print "done!"; ?> --CLEAN-- --EXPECTF-- [002 + 01] Query 'DROP TABLE IF EXISTS test' [002 + 02] Thread '%d' [003 + 01] Query 'DROP TABLE IF EXISTS test' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [003 + 02] Thread '%d' [004 + 01] Query 'CREATE TABLE test(id INT)' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [004] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004 + 02] Thread '%d' [005 + 01] Query 'SELECT * FROM test' [005 + 02] Thread '%d' [006 + 01] Query 'INSERT INTO test(id) VALUES (1)' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [006 + 02] Thread '%d' [007 + 01] Query 'SELECT * FROM test' [007 + 02] Thread '%d' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser10.phpt0000664000175000017500000000725712161007456022363 0ustar andreyandrey--TEST-- parser: SELECT SQL_SMALL_RESULT --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser10.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser10.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT SQL_SMALL_RESULT id AS _id FROM test GROUP BY id ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser11.phpt0000664000175000017500000000725112161007456022356 0ustar andreyandrey--TEST-- parser: SELECT SQL_BIG_RESULT --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser11.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser11.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT SQL_BIG_RESULT id AS _id FROM test GROUP BY id ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser12.phpt0000664000175000017500000000726512161007456022364 0ustar andreyandrey--TEST-- parser: SELECT SQL_BUFFER_RESULT --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser12.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser12.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT SQL_BUFFER_RESULT id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser13.phpt0000664000175000017500000000720312161007456022355 0ustar andreyandrey--TEST-- parser: SELECT SQL_CACHE --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser13.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser13.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT SQL_CACHE id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser14.phpt0000664000175000017500000000721412161007456022360 0ustar andreyandrey--TEST-- parser: SELECT SQL_NO_CACHE --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser14.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser14.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT SQL_NO_CACHE id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser15.phpt0000664000175000017500000000721012161007456022355 0ustar andreyandrey--TEST-- parser: SELECT DISTINCTROW --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser15.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser15.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT DISTINCTROW id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser16.phpt0000664000175000017500000000724012161007456022361 0ustar andreyandrey--TEST-- parser: SELECT SQL_CALC_FOUND_ROWS --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser16.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser16.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT SQL_CALC_FOUND_ROWS id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser17.phpt0000664000175000017500000000714112161007456022362 0ustar andreyandrey--TEST-- parser: SELECT 'a' ' ' 'string' --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser17.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser17.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT 'a' ' ' 'string' AS _id' [006] _id = 'a string' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser18.phpt0000664000175000017500000001002212161007456022353 0ustar andreyandrey--TEST-- parser: SELECT _latin1'string' --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser18.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser18.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT _latin1'string' AS _id' [006] _id = 'string' [009] Testing server support of 'SELECT _latin1'string' COLLATE latin1_danish_ci AS _id' [012] _id = 'string' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser19.phpt0000664000175000017500000000770412161007456022371 0ustar andreyandrey--TEST-- parser: SELECT N'some text'; --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser19.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser19.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT N'some text' AS _id' [006] _id = 'some text' [009] Testing server support of 'SELECT n'some text' AS _id' [012] _id = 'some text' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser1.phpt0000664000175000017500000000445112161007456022274 0ustar andreyandrey--TEST-- parser: SELECT 'a' AS _id FROM test --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); $settings['myapp']['filters']['roundrobin'] = array( ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser1.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser1.ini --FILE-- --CLEAN-- --EXPECTF-- [005] _id = 'a' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser20.phpt0000664000175000017500000000772512161007456022364 0ustar andreyandrey--TEST-- parser: SELECT 'h\'ello' --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser20.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser20.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT 'h\'ello' AS _id FROM DUAL' [006] _id = 'h'ello' [009] Testing server support of 'SELECT '''hello''' AS _id FROM DUAL' [012] _id = ''hello'' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser21.phpt0000664000175000017500000000644512161007456022363 0ustar andreyandrey--TEST-- parser: SELECT -32032.6809e+10 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser21.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser21.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT -32032.6809e+10 AS _id FROM DUAL' [006] _id = '-320326809000000' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser22.phpt0000664000175000017500000000641212161007456022356 0ustar andreyandrey--TEST-- parser: SELECT X'4D7953514C' --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser22.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser22.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT X'4D7953514C' AS _id FROM DUAL' [006] _id = 'MySQL' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser23.phpt0000664000175000017500000000745412161007456022366 0ustar andreyandrey--TEST-- parser: SELECT true --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser23.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser23.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT true AS _id FROM DUAL' [006] _id = '1' [009] Testing server support of 'SELECT FALSE AS _id FROM DUAL' [012] _id = '0' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser24.phpt0000664000175000017500000000636512161007456022367 0ustar andreyandrey--TEST-- parser: SELECT b'1' + 0 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser24.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser24.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT b'1' + 0 AS _id FROM DUAL' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser25.phpt0000664000175000017500000000634112161007456022362 0ustar andreyandrey--TEST-- parser: SELECT \N --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser25.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser25.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT \N AS _id FROM DUAL' [006] _id = '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser26.phpt0000664000175000017500000000535712161007456022371 0ustar andreyandrey--TEST-- parser: CREATE TABLE `a``b` --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".a`b" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser26.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser26.ini --FILE-- --CLEAN-- --EXPECTF-- [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser27.phpt0000664000175000017500000000407712161007456022370 0ustar andreyandrey--TEST-- parser: SELECT * FROM `select` --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".select" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); $settings['myapp']['filters']['roundrobin'] = array(); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser26.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser26.ini --FILE-- --CLEAN-- --EXPECTF-- [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser28.phpt0000664000175000017500000000635612161007456022373 0ustar andreyandrey--TEST-- parser: SELECT @._$ _id FROM DUAL --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser28.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser28.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT @._$ _id FROM DUAL' [006] _id = '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser29.phpt0000664000175000017500000000640512161007456022367 0ustar andreyandrey--TEST-- parser: SELECT @._$ _id FROM DUAL --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser29.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser29.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT id OR id AS _id FROM test AS d' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser2.phpt0000664000175000017500000000471412161007456022277 0ustar andreyandrey--TEST-- parser: SELECT --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser2.ini --FILE-- --CLEAN-- --EXPECTF-- [004] [1064] %s [005] No result done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser3.phpt0000664000175000017500000000463712161007456022304 0ustar andreyandrey--TEST-- parser: Andrey, ... --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser3.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser3.ini --FILE-- --CLEAN-- --EXPECTF-- [004] [1064] %s [005] No result done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser4.phpt0000664000175000017500000000550612161007456022301 0ustar andreyandrey--TEST-- parser: SELECT NULL, 1 AS _id FROM test --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); $settings['myapp']['filters']['roundrobin'] = array(); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser4.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser4.ini --FILE-- --CLEAN-- --EXPECTF-- [005] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser5.phpt0000664000175000017500000000542412161007456022301 0ustar andreyandrey--TEST-- parser: SELECT PASSWORD('foo') AS _id --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser5.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser5.ini --FILE-- --CLEAN-- --EXPECTF-- [005] _id = '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser6.phpt0000664000175000017500000000613712161007456022304 0ustar andreyandrey--TEST-- parser: SELECT HIGH_PRIORITY --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser6.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser6.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT HIGH_PRIORITY id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser7.phpt0000664000175000017500000000610212161007456022275 0ustar andreyandrey--TEST-- parser: SELECT ALL --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser7.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser7.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT ALL id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser8.phpt0000664000175000017500000000612112161007456022277 0ustar andreyandrey--TEST-- parser: SELECT DISTINCT --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser8.ini", $settings)) die(sprintf("SKIP %s\n", $error)); include_once("util.inc"); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser8.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT DISTINCT id AS _id FROM test ORDER BY id ASC' [006] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser9.phpt0000664000175000017500000000721512161007456022305 0ustar andreyandrey--TEST-- parser: SELECT STRAIGHT_JOIN --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $emulated_master_host_only, 'port' => (int)$emulated_master_port, 'socket' => $emulated_master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $emulated_slave_host_only, 'port' => (int)$emulated_slave_port, 'socket' => $emulated_slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser9.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser9.ini --FILE-- --CLEAN-- --EXPECTF-- [001] Testing server support of 'SELECT STRAIGHT_JOIN id AS _id FROM test ORDER BY id ASC' [006] _id = '%d' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_parser.phpt0000664000175000017500000000743512161007456022220 0ustar andreyandrey--TEST-- parser --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( ), ), ); if (_skipif_have_feature("table_filter")) { $settings['myapp']['filters']['table'] = array( "rules" => array( $db . ".test" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ); } if ($error = mst_create_config("test_mysqlnd_ms_table_parser.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_parser.ini --FILE-- --CLEAN-- --EXPECTF-- [004 + 01] Query 'SELECT CONNECTION_ID() AS _id FROM test' [004 + 02] Thread '%d' [005] _id = '%d' [006 + 01] Query 'SELECT id AS _id FROM test ORDER BY id ASC' [006 + 02] Thread '%d' [007] _id = '1' [008 + 01] Query 'SELECT id, id AS _id FROM test ORDER BY id ASC' [008 + 02] Thread '%d' [009] _id = '1' [012 + 01] Query 'SELECT 1 AS _id FROM test ORDER BY id ASC' [012 + 02] Thread '%d' [013] _id = '1' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_pattern_cont_ro.phpt0000664000175000017500000000642612161007456026370 0ustar andreyandrey--TEST-- table filter: rule with empty pattern (random once) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => 'Master_Thursday_1540_pm_really', ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "master2" => array( 'host' => 'Slave_Thursday_1540_pm_really', ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( "" => array( "master" => array("master2"), "slave" => array("slave2"), ), "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "random" => array("sticky" => true), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_pattern_cont_ro.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_pattern_cont_ro.ini mysqlnd_ms.multi_master=1 --FILE-- thread_id) printf("[003] Not connected to any server.\n"); mst_mysqli_verbose_query(4, $link, "SELECT 1"); if (0 == $link->thread_id) printf("[005] Not connected to any server.\n"); $stats = mysqlnd_ms_get_stats(); foreach ($stats as $k => $v) if (0 != $v) printf("[006] Stat '%s' = %d\n", $k, $v); print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) A table filter must be given a name. You must not use an empty string in %s on line %d [001] [2000] (mysqlnd_ms) A table filter must be given a name. You must not use an empty string [002 + 01] Query 'DROP TABLE IF EXISTS test' [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [002 + 02] Thread '0' [003] Not connected to any server. [004 + 01] Query 'SELECT 1' [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [004] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004 + 02] Thread '0' [005] Not connected to any server. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_pattern_cont_r.phpt0000664000175000017500000000637512161007456026214 0ustar andreyandrey--TEST-- table filter: rule with empty pattern (random) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => 'Master_Thursday_1540_pm_really', ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "master2" => array( 'host' => 'Slave_Thursday_1540_pm_really', ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( "" => array( "master" => array("master2"), "slave" => array("slave2"), ), "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_pattern_cont_r.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_pattern_cont_r.ini mysqlnd_ms.multi_master=1 --FILE-- thread_id) printf("[003] Not connected to any server.\n"); mst_mysqli_verbose_query(4, $link, "SELECT 1"); if (0 == $link->thread_id) printf("[005] Not connected to any server.\n"); $stats = mysqlnd_ms_get_stats(); foreach ($stats as $k => $v) if (0 != $v) printf("[006] Stat '%s' = %d\n", $k, $v); print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) A table filter must be given a name. You must not use an empty string in %s on line %d [001] [2000] (mysqlnd_ms) A table filter must be given a name. You must not use an empty string [002 + 01] Query 'DROP TABLE IF EXISTS test' [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [002 + 02] Thread '0' [003] Not connected to any server. [004 + 01] Query 'SELECT 1' [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [004] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004 + 02] Thread '0' [005] Not connected to any server. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_pattern_cont_rr.phpt0000664000175000017500000000640512161007456026370 0ustar andreyandrey--TEST-- table filter: rule with empty pattern (random) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => 'Master_Thursday_1540_pm_really', ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "master2" => array( 'host' => 'Slave_Thursday_1540_pm_really', ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( "" => array( "master" => array("master2"), "slave" => array("slave2"), ), "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_pattern_cont_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_pattern_cont_rr.ini mysqlnd_ms.multi_master=1 --FILE-- thread_id) printf("[003] Not connected to any server.\n"); mst_mysqli_verbose_query(4, $link, "SELECT 1"); if (0 == $link->thread_id) printf("[005] Not connected to any server.\n"); $stats = mysqlnd_ms_get_stats(); foreach ($stats as $k => $v) if (0 != $v) printf("[006] Stat '%s' = %d\n", $k, $v); print "done!"; ?> --CLEAN-- --EXPECTF-- [E_RECOVERABLE_ERROR] mysqli_real_connect(): (mysqlnd_ms) A table filter must be given a name. You must not use an empty string in %s on line %d [001] [2000] (mysqlnd_ms) A table filter must be given a name. You must not use an empty string [002 + 01] Query 'DROP TABLE IF EXISTS test' [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [002 + 02] Thread '0' [003] Not connected to any server. [004 + 01] Query 'SELECT 1' [E_WARNING] mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [004] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004 + 02] Thread '0' [005] Not connected to any server. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_pattern.phpt0000664000175000017500000000434312161007456024641 0ustar andreyandrey--TEST-- table filter: rule with empty pattern --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => 'Master_Thursday_1540_pm_really', ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "master2" => array( 'host' => 'Slave_Thursday_1540_pm_really', ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( "" => array( "master" => array("master2"), "slave" => array("slave2"), ), "%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "random" => array("sticky" => true), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_pattern.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_pattern.ini mysqlnd_ms.multi_master=1 --FILE-- thread_id) printf("[003] Not connected to any server."); print "done!"; ?> --CLEAN-- --EXPECTF-- Catchable fatal error: mysqli_real_connect(): (mysqlnd_ms) A table filter must be given a name. You must not use an empty string in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_random_once.phpt0000664000175000017500000000427312161007456025452 0ustar andreyandrey--TEST-- table filter: empty rule (random once) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array(), ), ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_random.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_random.phpt0000664000175000017500000000425112161007456024442 0ustar andreyandrey--TEST-- table filter: empty rule (random) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array(), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_random.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_empty_rr.phpt0000664000175000017500000000423112161007456023603 0ustar andreyandrey--TEST-- table filter: empty rule (rr) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array(), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_empty_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_empty_rr.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [003] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_master_empty_random_once.phpt0000664000175000017500000000464212161007456027025 0ustar andreyandrey--TEST-- table filter: no master rule (random once) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "slave" => array("slave1"), ), ), ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_master_empty_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_master_empty_random_once.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- [002 + 01] Query 'DROP TABLE IF EXISTS test' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [002 + 02] Thread '%d' [003 + 01] Query 'SELECT id FROM test ORDER BY id ASC' [003 + 02] Thread '%d' array(1) { ["id"]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_master_empty_random.phpt0000664000175000017500000000457512161007456026026 0ustar andreyandrey--TEST-- table filter: no master rule (random) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "slave" => array("slave1"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_master_empty_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_master_empty_random.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- [002 + 01] Query 'DROP TABLE IF EXISTS test' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [002 + 02] Thread '%d' [003 + 01] Query 'SELECT id FROM test ORDER BY id ASC' [003 + 02] Thread '%d' array(1) { ["id"]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_master_empty_rr.phpt0000664000175000017500000000455512161007456025167 0ustar andreyandrey--TEST-- table filter: no master rule (rr) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_master_empty_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_master_empty_rr.ini --FILE-- fetch_assoc()); print "done!"; ?> --CLEAN-- --EXPECTF-- [002 + 01] Query 'DROP TABLE IF EXISTS test' Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [002 + 02] Thread '%d' [003 + 01] Query 'SELECT id FROM test ORDER BY id ASC' [003 + 02] Thread '%d' array(1) { ["id"]=> string(1) "1" } done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_numeric.phpt0000664000175000017500000000415412161007456023410 0ustar andreyandrey--TEST-- table filter: "numeric" pattern/key --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => 'Master_Thursday_1546_pm_really', ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "master2" => array( 'host' => 'Slave_Thursday_1546_pm_really', ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( -1.01 => array( "master" => array("master2"), "slave" => array("slave2"), ), ), ), "random" => array("sticky" => true), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_numeric.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_numeric.ini --FILE-- thread_id) printf("[003] Not connected to any server."); print "done!"; ?> --CLEAN-- --EXPECTF-- [002 + 01] Query 'DROP TABLE IF EXISTS test' Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_slave_empty_random_once.phpt0000664000175000017500000000413612161007456026642 0ustar andreyandrey--TEST-- table filter: no slave rule (random once) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master1"), ), ), ), "random" => array("sticky" => 1), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_slave_empty_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_slave_empty_random_once.ini --FILE-- --CLEAN-- --EXPECTF-- [003] Expecting Fatal error... Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_slave_empty_random.phpt0000664000175000017500000000407112161007456025634 0ustar andreyandrey--TEST-- table filter: no slave rule (random) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master1"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_slave_empty_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_slave_empty_random.ini --FILE-- --CLEAN-- --EXPECTF-- [003] Expecting Fatal error... Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_slave_empty_rr.phpt0000664000175000017500000000405112161007456024775 0ustar andreyandrey--TEST-- table filter: no slave rule (rr) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_slave_empty_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_slave_empty_rr.ini --FILE-- --CLEAN-- --EXPECTF-- [003] Expecting Fatal error... Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_twice2.phpt0000664000175000017500000000366212161007456023146 0ustar andreyandrey--TEST-- table filter: rule defined twice, invalid hosts first --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => "I_really_hope_this_does_and_so_forth", ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( 'host' => "I_really_hope_this_does_and_so_forth", ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master2"), "slave" => array("slave2"), ), $db . ".%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_twice2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_twice2.ini mysqlnd_ms.multi_master=1 --FILE-- --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_twice.phpt0000664000175000017500000000420712161007456023060 0ustar andreyandrey--TEST-- table filter: rule defined twice --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => "I_really_hope_this_master_does_and_so_forth", ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( 'host' => "I_really_hope_this_slave_does_and_so_forth", ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master1"), "slave" => array("slave1"), ), $db . ".%" => array( "master" => array("master2"), "slave" => array("slave2"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_twice.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_twice.ini mysqlnd_ms.multi_master=1 --FILE-- thread_id) printf("[003] Not connected to any server.\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- %Aonnect error, [002] [%d] %s [003] Not connected to any server. done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_rule_unknown_parameter.phpt0000664000175000017500000000410712161007456025503 0ustar andreyandrey--TEST-- table filter: unknown parameter in valid rule --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "slave" => array("slave1"), "master" => array("master1"), "unknown" => "rule", ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_rule_unknown_parameter.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_rule_unknown_parameter.ini --FILE-- thread_id) printf("[003] Statement has not been executed?\n"); mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); if (0 == $link->thread_id) printf("[005] Statement has not been executed?\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_slave_no_match_random_once.phpt0000664000175000017500000000600412161007456026241 0ustar andreyandrey--TEST-- table filter: no slave for SELECT, use master - pick = random once --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test" => array( "slave" => array("slave1"), "master" => array("master1"), ), ), ), "random" => array('sticky' => '1'), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_slave_no_match_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_slave_no_match_random_once.ini --FILE-- thread_id] = array("master"); mst_mysqli_query(4, $link, "CREATE TABLE test(id INT)"); $threads[$link->thread_id][] = 'master'; mst_mysqli_query(5, $link, "INSERT INTO test(id) VALUES (1)"); $threads[$link->thread_id][] = 'master'; /* db.test -> slave 1 */ mst_mysqli_create_test_table($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); $res = mst_mysqli_verbose_query(6, $link, "SELECT id FROM test"); $threads[$link->thread_id] = array("slave"); /* db.DUAL -> master, slave 1 has db.test only! */ $res = mst_mysqli_verbose_query(7, $link, "SELECT 1 FROM DUAL"); var_dump($res->fetch_assoc()); $threads[$link->thread_id][] = 'master'; foreach ($threads as $thread_id => $roles) { printf("%d: ", $thread_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [006 + 01] Query 'SELECT id FROM test' [006 + 02] Thread '%d' [007 + 01] Query 'SELECT 1 FROM DUAL' Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_slave_no_match_random.phpt0000664000175000017500000000573412161007456025246 0ustar andreyandrey--TEST-- table filter: no slave for SELECT, use master - pick = random --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test" => array( "slave" => array("slave1"), "master" => array("master1"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_slave_no_match_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_slave_no_match_random.ini --FILE-- thread_id] = array("master"); mst_mysqli_query(4, $link, "CREATE TABLE test(id INT)"); $threads[$link->thread_id][] = 'master'; mst_mysqli_query(5, $link, "INSERT INTO test(id) VALUES (1)"); $threads[$link->thread_id][] = 'master'; /* db.test -> slave 1 */ mst_mysqli_create_test_table($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); $res = mst_mysqli_verbose_query(6, $link, "SELECT id FROM test"); $threads[$link->thread_id] = array("slave"); /* db.DUAL -> master, slave 1 has db.test only! */ $res = mst_mysqli_verbose_query(7, $link, "SELECT 1 FROM DUAL"); var_dump($res->fetch_assoc()); $threads[$link->thread_id][] = 'master'; foreach ($threads as $thread_id => $roles) { printf("%d: ", $thread_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [006 + 01] Query 'SELECT id FROM test' [006 + 02] Thread '%d' [007 + 01] Query 'SELECT 1 FROM DUAL' Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_slave_no_match_rr.phpt0000664000175000017500000000575412161007456024413 0ustar andreyandrey--TEST-- table filter: no slave for SELECT, use master - pick = roundrobin --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test" => array( "slave" => array("slave1"), "master" => array("master1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_slave_no_match_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_slave_no_match_rr.ini --FILE-- thread_id] = array("master"); mst_mysqli_query(4, $link, "CREATE TABLE test(id INT)"); $threads[$link->thread_id][] = 'master'; mst_mysqli_query(5, $link, "INSERT INTO test(id) VALUES (1)"); $threads[$link->thread_id][] = 'master'; /* db.test -> slave 1 */ mst_mysqli_create_test_table($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); $res = mst_mysqli_verbose_query(6, $link, "SELECT id FROM test"); $threads[$link->thread_id] = array("slave"); /* db.DUAL -> master, slave 1 has db.test only! */ $res = mst_mysqli_verbose_query(7, $link, "SELECT 1 FROM DUAL"); var_dump($res->fetch_assoc()); $threads[$link->thread_id][] = 'master'; foreach ($threads as $thread_id => $roles) { printf("%d: ", $thread_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [006 + 01] Query 'SELECT id FROM test' [006 + 02] Thread '%d' [007 + 01] Query 'SELECT 1 FROM DUAL' Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_slave_ref_master_random.phpt0000664000175000017500000000427712161007456025606 0ustar andreyandrey--TEST-- table filter: slave referencing master --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master1"), "slave" => array("master1"), ), ), ), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_slave_ref_master_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_slave_ref_master_random.ini --FILE-- --CLEAN-- --EXPECTF-- [002 + 01] Query 'DROP TABLE IF EXISTS test' [002 + 02] Thread '%d' [003 + 01] Query 'CREATE TABLE test(id INT)' [003 + 02] Thread '%d' [004 + 01] Query 'SELECT * FROM test' Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_slave_rr.phpt0000664000175000017500000000646012161007456022536 0ustar andreyandrey--TEST-- table filter: slave rule --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( "host" => "unknown_i_hope", ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( "host" => "unknown_i_hope", ), "slave3" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test%" => array( "master" => array("master2"), "slave" => array("slave2"), ), "%" => array( "master" => array("master1"), "slave" => array("slave1", "slave3"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_slave_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_slave_rr.ini mysqlnd_ms.multi_master=1 --FILE-- master 1 */ mst_mysqli_query(3, $link, "DROP TABLE IF EXISTS ulf"); $threads[$link->thread_id] = array('master1'); /* db.dual -> rr, slave 1 */ mst_mysqli_query(4, $link, "SELECT 1 FROM DUAL"); $threads[$link->thread_id] = array('slave1'); /* db.test -> slave 2 -> no such host */ if (!@$link->query("SELECT * FROM test")) { if (isset($mst_connect_errno_codes[$link->errno])) printf("[005] Connect error, [%d] %s\n", $link->errno, $link->error); else printf("[005] Unexpected error, [%d] %s\n", $link->errno, $link->error); } $threads[$link->thread_id] = array('slave2'); /* db.dual -> rr, slave 3 */ mst_mysqli_query(6, $link, "SELECT 1 FROM DUAL"); $threads[$link->thread_id] = array('slave3'); /* db.dual -> rr, slave 1 */ mst_mysqli_query(7, $link, "SELECT 1 FROM DUAL"); $threads[$link->thread_id][] = 'slave1'; /* db.dual -> rr, slave 3 */ mst_mysqli_query(6, $link, "SELECT 1 FROM DUAL"); $threads[$link->thread_id][] = 'slave3'; foreach ($threads as $thread_id => $roles) { printf("%d: ", $thread_id); foreach ($roles as $k => $role) printf("%s,", $role); printf("\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [005] Connect error, [%d] %s %d: master1, %d: slave1,slave1, 0: slave2, %d: slave3,slave3, done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_sql_hint.phpt0000664000175000017500000000625212161007456022541 0ustar andreyandrey--TEST-- table filter basics: SQL hint --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".test1%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_sql_hint.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_sql_hint.ini --FILE-- thread_id; mst_mysqli_query(3, $link, "CREATE TABLE test1(id BIGINT)", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(4, $link, "INSERT INTO test1(id) VALUES (CONNECTION_ID())", MYSQLND_MS_LAST_USED_SWITCH); $res = mst_mysqli_query(5, $link, "SELECT id FROM test1", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($master != $row['id']) printf("[006] Master thread id differs from INSERT CONNECTION_ID(), expecting %d got %d\n", $master, $row['id']); if ($master != $link->thread_id) printf("[007] Master thread id differs from SELECT CONNECTION_ID(), expecting %d got %d\n", $master, $link->thread_id); mst_mysqli_query(8, $link, "DROP TABLE IF EXISTS test1", MYSQLND_MS_SLAVE_SWITCH); $slave = $link->thread_id; mst_mysqli_query(9, $link, "CREATE TABLE test1(id BIGINT)", MYSQLND_MS_SLAVE_SWITCH); mst_mysqli_query(10, $link, "INSERT INTO test1(id) VALUES (CONNECTION_ID())", MYSQLND_MS_LAST_USED_SWITCH); $res = mst_mysqli_query(11, $link, "SELECT id FROM test1", MYSQLND_MS_LAST_USED_SWITCH); $row = $res->fetch_assoc(); if ($slave != $row['id']) printf("[012] Slave thread id differs from INSERT CONNECTION_ID(), expecting %d got %d\n", $slave, $row['id']); if ($slave != $link->thread_id) printf("[013] Master thread id differs from SELECT CONNECTION_ID(), expecting %d got %d\n", $slave, $link->thread_id); if ($slave == $master) printf("[014] Master and slave are using the same connection\n"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_undefined_master_in_rule_lazy.phpt0000664000175000017500000000451412161007456027007 0ustar andreyandrey--TEST-- table filter basics: undefined master, lazy --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (double)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test1%" => array( "master" => array("master2"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_undefined_master_in_rule_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_undefined_master_in_rule_lazy.ini --FILE-- thread_id != 0) printf("[003] Connected to some server, but which one?\n"); printf("[004] [%s/%d] %s\n", $link->sqlstate, $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004] [HY000/2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done! mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_undefined_master_in_rule.phpt0000664000175000017500000000451712161007456025753 0ustar andreyandrey--TEST-- table filter basics: undefined master, non lazy --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (double)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".test1%" => array( "master" => array("master2"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_undefined_master_in_rule.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_undefined_master_in_rule.ini --FILE-- thread_id != 0) printf("[003] Connected to some server (%d), but which one?\n", $link->thread_id); printf("[004] [%s/%d] %s\n", $link->sqlstate, $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong in %s on line %d [002] [2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong [004] [HY000/2000] (mysqlnd_ms) Couldn't find the appropriate master connection. Something is wrong done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_undefined_slave_in_rule_lazy.phpt0000664000175000017500000000467312161007456026634 0ustar andreyandrey--TEST-- table filter basics: undefined slave, lazy --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (double)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "rules" => array( $db . ".test1%" => array( "master" => array("master1"), "slave" => array("slave2"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_undefined_slave_in_rule_lazy.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_undefined_slave_in_rule_lazy.ini --FILE-- thread_id; /* there is no slave to run this query... */ if ($res = mst_mysqli_query(4, $link, "SELECT 'one' AS _id FROM test1")) { var_dump($res->fetch_assoc()); } if ($link->thread_id == $master) printf("[005] Master has replied to slave query\n"); if ($link->thread_id != 0) printf("[006] Connected to some server, but which one?\n"); printf("[007] [%s/%d] %s\n", $link->sqlstate, $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %dmysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_undefined_slave_in_rule.phpt0000664000175000017500000000453512161007456025572 0ustar andreyandrey--TEST-- table filter basics: undefined slave, non lazy --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (double)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".test1%" => array( "master" => array("master1"), "slave" => array("slave2"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_undefined_slave_in_rule.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_undefined_slave_in_rule.ini --FILE-- thread_id; /* there is no slave to run this query... */ if ($res = mst_mysqli_query(4, $link, "SELECT 'one' AS _id FROM test1")) { var_dump($res->fetch_assoc()); } if ($link->thread_id == $master) printf("[005] Master has replied to slave query\n"); if ($link->thread_id != 0) printf("[006] Connected to some server, but which one?\n"); printf("[007] [%s/%d] %s\n", $link->sqlstate, $link->errno, $link->error); } print "done!"; ?> --CLEAN-- --EXPECTF-- Fatal error: mysqli::query(): (mysqlnd_ms) Couldn't find the appropriate slave connection. 0 slaves to choose from. Something is wrong in %s on line %d mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_unknown_parameter2.phpt0000664000175000017500000000427012161007456024537 0ustar andreyandrey--TEST-- table filter: unknown parameter, empty name --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( "host" => "running_out_of_silly_names"), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( "host" => "running_out_of_silly_names"), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "" => array( "best.%" => array( "master" => array("master2"), "slave" => array("slave2"), ), ), "rules" => array( $db . ".%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_unknown_parameter2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_unknown_parameter2.ini --FILE-- thread_id == 0) printf("[003] Which server has run this?"); mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); if ($link->thread_id == 0) printf("[005] Which server has run this?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_unknown_parameter3.phpt0000664000175000017500000000426712161007456024546 0ustar andreyandrey--TEST-- table filter: unknown parameter, name \0 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( "host" => "running_out_of_silly_names"), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( "host" => "running_out_of_silly_names"), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "\0" => array( "best.%" => array( "master" => array("master2"), "slave" => array("slave2"), ), ), "rules" => array( $db . ".%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_unknown_parameter3.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_unknown_parameter3.ini --FILE-- thread_id == 0) printf("[003] Which server has run this?"); mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); if ($link->thread_id == 0) printf("[005] Which server has run this?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_unknown_parameter.phpt0000664000175000017500000000426212161007456024456 0ustar andreyandrey--TEST-- table filter: unknown parameter --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( "host" => "running_out_of_silly_names"), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), "slave2" => array( "host" => "running_out_of_silly_names"), ), 'lazy_connections' => 1, 'filters' => array( "table" => array( "more_rules" => array( "best.%" => array( "master" => array("master2"), "slave" => array("slave2"), ), ), "rules" => array( $db . ".%" => array( "master" => array("master1"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_unknown_parameter.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_unknown_parameter.ini --FILE-- thread_id == 0) printf("[003] Which server has run this?"); mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_SLAVE_SWITCH); if ($link->thread_id == 0) printf("[005] Which server has run this?"); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_table_write_non_unique.phpt0000664000175000017500000000523412161007456024311 0ustar andreyandrey--TEST-- table filter: multiple master --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), "master2" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "table" => array( "rules" => array( $db . ".%" => array( "master" => array("master1", "master2"), "slave" => array("slave1"), ), ), ), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_table_write_non_unique.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_table_write_non_unique.ini mysqlnd_ms.multi_master=1 --FILE-- thread_id; /* master 2 */ mst_mysqli_query(3, $link, "DROP TABLE IF EXISTS test"); $masters[] = $link->thread_id; /* master 1 */ mst_mysqli_query(4, $link, "DROP TABLE IF EXISTS test"); $masters[] = $link->thread_id; /* master 2 */ mst_mysqli_query(5, $link, "DROP TABLE IF EXISTS test"); $masters[] = $link->thread_id; $last = NULL; foreach ($masters as $k => $thread_id) { printf("%d -> %d\n", $k, $thread_id); if (!is_null($last)) { if ($last != $thread_id) printf("Server switch\n"); else printf("No server switch\n"); } $last = $thread_id; } print "done!"; ?> --XFAIL-- Discuss if allowed. --CLEAN-- --EXPECTF-- 0 -> %d 1 -> %d Server switch 2 -> %d Server switch 3 -> %d Server switch done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_thread_id.phpt0000664000175000017500000000377712161007456021505 0ustar andreyandrey--TEST-- Thread id --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_thread_id.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_thread_id.ini --FILE-- query($query)) { printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); return false; } if (!$res = $link->query(sprintf("/*%s*/SELECT CONNECTION_ID() AS _thread", MYSQLND_MS_LAST_USED_SWITCH))) { printf("[%03d + 02] [%d] %s\n", $offset, $link->errno, $link->error); return false; } $row = $res->fetch_assoc(); if ($link->thread_id != $row['_thread']) { printf("[%03d + 03] Expecting thread id %d got %d\n", $offset, $link->thread_id, $row['_thread']); } return $link->thread_id; } $link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket); if (0 !== mysqli_connect_errno()) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $threads = array(); $threads[check_thread_id(10, $link, "DROP TABLE IF EXISTS test")]= "master"; $threads[check_thread_id(20, $link, "SELECT 'Slave1'")] = "slave 1"; $threads[check_thread_id(30, $link, "SELECT 'Slave2'")] = "slave 2"; foreach ($threads as $thread_id => $role) printf("%d %s\n", $thread_id, $role); print "done!"; ?> --CLEAN-- --EXPECTF-- %d master %d slave 1 %d slave 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_tmp_double_error.phpt0000664000175000017500000000242412161007456023111 0ustar andreyandrey--TEST-- Temporary --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host), ), ); if ($error = mst_create_config("test_mysqlnd_ms_tmp_double_error.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_tmp_double_error.ini --FILE-- query("role=master I_HOPE_THIS_IS_INVALID_SQL"); printf("[%d] '%s'\n", $link->errno, $link->error); $link->query(sprintf("/*%s*/SELECT 1", MYSQLND_MS_LAST_USED_SWITCH)); printf("[%d] '%s'\n", $link->errno, $link->error); print "done!"; ?> --CLEAN-- --EXPECTF-- [1064] '%s' [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_master_failover_random.phpt0000664000175000017500000000600012161007456027416 0ustar andreyandrey--TEST-- trx_stickiness=master, failover, random --SKIPIF-- array( 'master' => array($master_host, "unknown:6033"), 'slave' => array($slave_host), 'trx_stickiness' => 'master', 'pick' => array("random"), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_master_failover_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_master_failover_random.ini --FILE-- autocommit(FALSE); /* This is the first query in the transaction, failover may be done to find an initial connection. Once we have a connection, it must not change, ever! */ $res = $link->query("SELECT CONNECTION_ID() AS _master_role"); if (0 != $link->errno) { printf("[003] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); $last = $row['_master_role']; $res = $link->query("SELECT CONNECTION_ID() AS _master_role"); if (0 != $link->errno) { printf("[004] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($last != $row['_master_role']) { printf("[005] Server switched in the middle of a transaction!\n"); break; } $link->autocommit(TRUE); } while ((++$i < 50) && ($res) && (0 == $link->errno)); printf("[006] %d - [%d] '%s'\n", $i, $link->errno, $link->error); /* this is a MUST to break out of "in_trx = 1 => use last_used" */ $link->autocommit(TRUE); $link->autocommit(FALSE); /* in_trx = 1, remember_failed skips failed master */ for ($i = 0; $i < 10; $i++) { $res = $link->query("SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); if (!$res) { printf("[075] [%d] '%s'\n", $link->errno, $link->error); break; } } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [006] 50 - [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_master_failover_rr.phpt0000664000175000017500000000577012161007456026576 0ustar andreyandrey--TEST-- trx_stickiness=master, failover, roundrobin --SKIPIF-- array( 'master' => array($master_host, "unknown:6033"), 'slave' => array($slave_host), 'trx_stickiness' => 'master', 'pick' => array("roundrobin"), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_master_failover_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_master_failover_rr.ini --FILE-- autocommit(FALSE); /* This is the first query in the transaction, failover may be done to find an initial connection. Once we have a connection, it must not change, ever! */ $res = $link->query("SELECT CONNECTION_ID() AS _master_role"); if (0 != $link->errno) { printf("[003] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); $last = $row['_master_role']; $res = $link->query("SELECT CONNECTION_ID() AS _master_role"); if (0 != $link->errno) { printf("[004] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($last != $row['_master_role']) { printf("[005] Server switched in the middle of a transaction!\n"); break; } $link->autocommit(TRUE); } while ((++$i < 50) && ($res) && (0 == $link->errno)); printf("[006] %d - [%d] '%s'\n", $i, $link->errno, $link->error); /* this is a MUST to break out of "in_trx = 1 => use last_used" */ $link->autocommit(TRUE); $link->autocommit(FALSE); /* in_trx = 1, remember_failed skips failed master */ for ($i = 0; $i < 10; $i++) { $res = $link->query("SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"); if (!$res) { printf("[075] [%d] '%s'\n", $link->errno, $link->error); break; } } print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [006] 50 - [0] '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_master_random_once.phpt0000664000175000017500000001707312161007456026547 0ustar andreyandrey--TEST-- trx_stickiness=master --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'trx_stickiness' => 'master', ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_master_random_once.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_master_random_once.ini --FILE-- fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[012] Expecting id = 1 got id = '%s'\n", $row['id']); /* explicitly setting autocommit via API */ $link->autocommit(TRUE); $res = mst_mysqli_query(13, $link, "SELECT 1 AS id FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(14, $link); if ($server_id != $emulated_slave_thread) { printf("[015] SELECT in autocommit mode should have been run on the slave\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[016] Expecting id = 1 got id = '%s'\n", $row['id']); /* explicitly disabling autocommit via API */ $link->autocommit(FALSE); /* this can be the start of a transaction, thus it shall be run on the master */ $res = mst_mysqli_query(17, $link, "SELECT 1 AS id FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(18, $link); if ($server_id != $emulated_master_thread) { printf("[019] SELECT not run in autocommit mode should have been run on the master\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[020] Expecting id = 1 got id = '%s'\n", $row['id']); if (!$link->commit()) printf("[021] [%d] %s\n", $link->errno, $link->error); /* autocommit is still off, thus it shall be run on the master */ $res = mst_mysqli_query(22, $link, "SELECT id FROM test WHERE id = 1"); $server_id = mst_mysqli_get_emulated_id(23, $link); if ($server_id != $emulated_master_thread) { printf("[024] SELECT not run in autocommit mode should have been run on the master\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[025] Expecting id = 1 got id = '%s'\n", $row['id']); /* back to the slave for the next SELECT because autocommit is on */ $link->autocommit(TRUE); $res = mst_mysqli_query(26, $link, "SELECT 1 AS id FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(27, $link); if ($server_id != $emulated_slave_thread) { printf("[028] SELECT in autocommit mode should have been run on the slave\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[029] Expecting id = 1 got id = '%s'\n", $row['id']); /* master because update... */ mst_mysqli_query(30, $link, "UPDATE test SET id = 100 WHERE id = 1"); /* back to the master because autocommit is off */ $link->autocommit(FALSE); $res = mst_mysqli_query(31, $link, "SELECT id FROM test WHERE id = 100"); $server_id = mst_mysqli_get_emulated_id(32, $link); if ($server_id != $emulated_master_thread) { printf("[033] SELECT not run in autocommit mode should have been run on the master\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 100) printf("[034] Expecting id = 100 got id = '%s'\n", $row['id']); mst_mysqli_query(35, $link, "DELETE FROM test WHERE id = 100"); if (!$link->rollback()) printf("[036] [%s] %s\n", $link->errno, $link->error); $res = mst_mysqli_query(37, $link, "SELECT id FROM test WHERE id = 100"); $server_id = mst_mysqli_get_emulated_id(38, $link); if ($server_id != $emulated_master_thread) { printf("[039] SELECT not run in autocommit mode should have been run on the master\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 100) printf("[040] Expecting id = 100 got id = '%s'\n", $row['id']); /* SQL hint must not win: use master albeit SQL hint used */ $res = mst_mysqli_query(41, $link, "SELECT 1 AS id FROM DUAL", MYSQLND_MS_SLAVE_SWITCH); $server_id = mst_mysqli_get_emulated_id(42, $link); if ($server_id == $emulated_slave_thread) { printf("[043] Forced SELECT in autocommit mode should have been run on the mast\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[044] Expecting id = 1 got id = '%s'\n", $row['id']); $res = mst_mysqli_query(45, $link, "SELECT 1 AS id FROM DUAL", MYSQLND_MS_LAST_USED_SWITCH); $server_id = mst_mysqli_get_emulated_id(46, $link); if ($server_id == $emulated_slave_thread) { printf("[047] Forced SELECT in autocommit mode should have been run on the slave\n"); } $row = $res->fetch_assoc(); $res->close(); if ($row['id'] != 1) printf("[048] Expecting id = 1 got id = '%s'\n", $row['id']); print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_master_random.phpt0000664000175000017500000000610612161007456025536 0ustar andreyandrey--TEST-- trx_stickiness=master (PHP 5.3.99+), pick = random --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'master', 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_master_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_master_random.ini --FILE-- thread_id] = true; } while (count($slaves) < 2); /* explicitly disabling autocommit via API */ $link->autocommit(FALSE); /* this can be the start of a transaction, thus it shall be run on the master */ mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); /* back to the slave for the next SELECT because autocommit is on */ $link->autocommit(TRUE); mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); /* explicitly disabling autocommit via API */ $link->autocommit(FALSE); /* SQL hint does NOT win! */ mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_SLAVE_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_LAST_USED_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role", MYSQLND_MS_MASTER_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(11, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- This is 'master %d' speaking This is 'slave %d' speaking This is 'slave %d' speaking This is 'slave %d' speaking This is 'master %d' speaking This is 'master %d' speaking This is 'master %d' speaking This is 'master %d' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_master_rr.phpt0000664000175000017500000000657612161007456024714 0ustar andreyandrey--TEST-- trx_stickiness=master (PHP 5.3.99+), pick = roundrobin --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'master', 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_master_round_robin.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_master_round_robin.ini mysqlnd_ms.collect_statistics=1 --FILE-- autocommit(FALSE); echo "----\n"; mst_compare_stats(); echo "----\n"; /* this can be the start of a transaction, thus it shall be run on the master */ mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT @myrole AS _role")); echo "----\n"; mst_compare_stats(); echo "----\n"; /* back to the slave for the next SELECT because autocommit is on */ $link->autocommit(TRUE); mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT @myrole AS _role")); /* explicitly disabling autocommit via API */ $link->autocommit(FALSE); /* SQL hint wins */ mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(11, $link, "SELECT @myrole AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- ---- Stats use_slave: 2 Stats use_master: 1 Stats use_slave_sql_hint: 2 Stats use_master_sql_hint: 1 Stats lazy_connections_slave_success: 2 Stats lazy_connections_master_success: 1 ---- ---- Stats trx_autocommit_off: 1 ---- This is 'master' speaking ---- Stats use_master: 2 Stats use_slave_guess: 1 Stats trx_master_forced: 1 ---- This is 'slave 1' speaking This is 'slave 2' speaking This is 'slave 1' speaking This is 'master' speaking This is 'master' speaking This is 'master' speaking This is 'master' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_master_user.phpt0000664000175000017500000001137212161007456025235 0ustar andreyandrey--TEST-- trx_stickiness=master (PHP 5.3.99+), pick = user (rr) --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host), 'trx_stickiness' => 'master', 'pick' => array('user' => array('callback' => 'pick_server')), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_master_user.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_master_user.ini mysqlnd_ms.collect_statistics=1 --FILE-- autocommit(FALSE); mst_compare_stats(); /* this can be the start of a transaction, thus it shall be run on the master */ mst_mysqli_fech_role(mst_mysqli_query(4, $link, "SELECT @myrole AS _role")); mst_compare_stats(); /* back to the slave for the next SELECT because autocommit is on */ $link->autocommit(TRUE); mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT @myrole AS _role")); mst_compare_stats(); /* explicitly disabling autocommit via API */ $link->autocommit(FALSE); /* SQL hint wins */ mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)); mst_compare_stats(); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role")); mst_compare_stats(); print "done!"; ?> --CLEAN-- --EXPECTF-- pick_server(/*ms=master*//*2*/SET @myrole='master') pick_server(/*ms=slave*//*3*/SET @myrole='slave 1') Stats use_slave_sql_hint: 1 Stats use_master_sql_hint: 1 Stats use_slave_callback: 1 Stats use_master_callback: 1 Stats lazy_connections_slave_success: 1 Stats lazy_connections_master_success: 1 Stats trx_autocommit_off: 1 pick_server(/*4*/SELECT @myrole AS _role) This is 'master' speaking Stats use_master_callback: 2 pick_server(/*5*/SELECT @myrole AS _role) This is 'slave 1' speaking pick_server(/*6*/SELECT @myrole AS _role) This is 'slave 1' speaking Stats use_slave_guess: 2 Stats use_slave_callback: 3 Stats trx_autocommit_on: 1 pick_server(/*ms=slave*//*7*/SELECT @myrole AS _role) This is 'master' speaking pick_server(/*ms=last_used*//*8*/SELECT @myrole AS _role) This is 'master' speaking pick_server(/*ms=master*//*9*/SELECT @myrole AS _role) This is 'master' speaking Stats use_master_callback: 5 Stats trx_autocommit_off: 2 pick_server(/*10*/SELECT @myrole AS _role) This is 'master' speaking Stats use_master_callback: 6 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_no_slave_failover_random.phpt0000664000175000017500000000610612161007456027740 0ustar andreyandrey--TEST-- trx_stickiness=on, failover, random --SKIPIF-- array( 'master' => array($emulated_master_host, "unknown:6033", $emulated_master_host), 'slave' => array(), 'trx_stickiness' => 'on', 'pick' => array("random"), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_no_slave_failover_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_no_slave_failover_random.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* This is the first query in the transaction, failover may be done to find an initial connection. Once we have a connection, it must not change, ever! */ $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[003] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); $last = $row['_slave_role']; $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[004] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($last != $row['_slave_role']) { printf("[005] Server switched in the middle of a transaction!\n"); break; } $link->commit(TRUE); $servers[$last] = true; } while ((++$i < 50) && ($res) && (0 == $link->errno)); printf("[006] %d - [%d] '%s'\n", $i, $link->errno, $link->error); printf("Number of servers contacted: %d\n", count($servers)); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [006] 50 - [0] '' Number of servers contacted: 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_no_slave_failover_rr.phpt0000664000175000017500000000633512161007456027107 0ustar andreyandrey--TEST-- trx_stickiness=on, failover, RR --SKIPIF-- array( 'master' => array($emulated_master_host, "unknown:6033", $emulated_master_host), 'slave' => array(), 'trx_stickiness' => 'on', 'pick' => array("roundrobin"), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_no_slave_failover_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_no_slave_failover_rr.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* This is the first query in the transaction, failover may be done to find an initial connection. Once we have a connection, it must not change, ever! */ $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[003] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if (!is_null($last)) { if ($last == $row['_slave_role']) { printf("[007] No switch between transactions or false positive, run again and decide?\n"); } } $last = $row['_slave_role']; $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[004] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($last != $row['_slave_role']) { printf("[005] Server switched in the middle of a transaction!\n"); break; } $link->commit(TRUE); $servers[$last] = true; } while ((++$i < 5) && ($res) && (0 == $link->errno)); printf("[006] %d - [%d] '%s'\n", $i, $link->errno, $link->error); printf("Number of servers contacted: %d\n", count($servers)); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [006] 5 - [0] '' Number of servers contacted: 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_begin_name_random.phpt0000664000175000017500000001127612161007456027027 0ustar andreyandrey--TEST-- trx_stickiness=on, RW, begin(RW, name), pick = random --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'on', 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_begin_name_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ WRITE exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: needs MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_begin_name_random.ini --FILE-- thread_id] = true; $i++; } while (($i <= 10) && (count($slaves) < 2)); if (10 == $i) { die("[004] Two connections happen to have the same thread id, ignore and run again!"); } $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "foo"); $last = NULL; for ($i = 0; $i < 10; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); if (is_null($last)) { $last = $link->thread_id; printf("Loop 1: %s\n", $row['_role']); } else { if ($last != $link->thread_id) { printf("[007] Connection switch during transaction must not happen!\n"); break; } } /* master, please! */ if (!($res = mst_mysqli_query(8, $link, sprintf("SET @msg='_%d'", $i)))) { printf("[009] [%d] %s\n", $link->errno, $link->error); } if ($last != $link->thread_id) { printf("[010] Connection switch during transaction must not happen!\n"); break; } } $link->commit(); /* name gets longer */ $link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "foobar"); $last = NULL; for ($i = 0; $i < 10; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); if (is_null($last)) { $last = $link->thread_id; printf("Loop 2: %s\n", $row['_role']); } else { if ($last != $link->thread_id) { printf("[007] Connection switch during transaction must not happen!\n"); break; } } /* master, please! */ if (!($res = mst_mysqli_query(8, $link, sprintf("SET @msg='_%d'", $i)))) { printf("[009] [%d] %s\n", $link->errno, $link->error); } if ($last != $link->thread_id) { printf("[010] Connection switch during transaction must not happen!\n"); break; } } $link->rollback(); /* slave */ if (!($res = mst_mysqli_query(11, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_role']); } $last = $link->thread_id; /* no select... master, please! */ if (!($res = mst_mysqli_query(13, $link, sprintf("SET @msg='_%d'", ++$i)))) { printf("[014] [%d] %s\n", $link->errno, $link->error); } if ($last == $link->thread_id) { printf("[015] Switching not back in place?\n"); } /* slave - msg should not be set) */ if (!($res = mst_mysqli_query(16, $link, "SELECT @msg AS _msg"))) { printf("[017] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("'%s'\n", $row['_msg']); } print "done!"; ?> --CLEAN-- --EXPECTF-- Loop 1: master %d Loop 2: master %d slave %d '' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_random.phpt0000664000175000017500000000435112161007456024657 0ustar andreyandrey--TEST-- trx_stickiness=on, pick = random --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'on', 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_random.ini --FILE-- thread_id] = true; $i++; } while (($i <= 100) && (count($slaves) < 2)); if (100 == $i) { die("[004] Two connections happen to have the same thread id, ignore and run again!"); } $link->autocommit(FALSE); /* this can be the start of a transaction, thus it shall be run on the master */ $last = NULL; for ($i = 0; $i < 100; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); if (is_null($last)) { $last = $row['_role']; } else { if ($last != $row['_role']) { printf("[007] Connection switch during transaction must not happen!\n"); break; } } } print "done!"; ?> --CLEAN-- --EXPECTF-- done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_ro_mor_random.phpt0000664000175000017500000000743312161007456026240 0ustar andreyandrey--TEST-- trx_stickiness=on, RO trx, master on write, pick = random --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'on', 'master_on_write' => 1, 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_ro_mor_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_ro_mor_random.ini --FILE-- thread_id] = true; $i++; } while (($i <= 10) && (count($slaves) < 2)); if (10 == $i) { die("[004] Two connections happen to have the same thread id, ignore and run again!"); } $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* ro trx but master on write set, must use master! */ $last = NULL; for ($i = 0; $i < 10; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); if (is_null($last)) { $last = $link->thread_id; } else { if ($last != $link->thread_id) { printf("[007] Connection switch during transaction must not happen!\n"); break; } } /* must always use master! */ if (!($res = mst_mysqli_query(8, $link, sprintf("SET @msg='_%d'", $i)))) { printf("[009] [%d] %s\n", $link->errno, $link->error); } if ($last != $link->thread_id) { printf("[010] Connection switch during transaction must not happen!\n"); break; } } $link->commit(); /* must use master */ if (!($res = mst_mysqli_query(11, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_role']); } $last = $link->thread_id; /* no select... master, please! */ if (!($res = mst_mysqli_query(13, $link, sprintf("SET @msg='_%d'", ++$i)))) { printf("[014] [%d] %s\n", $link->errno, $link->error); } if ($last != $link->thread_id) { printf("[015] Switching must not happen!\n"); } if (!($res = mst_mysqli_query(16, $link, "SELECT @msg AS _msg"))) { printf("[017] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_msg']); } print "done!"; ?> --CLEAN-- --EXPECTF-- master %d _11 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_ro_mor_rr.phpt0000664000175000017500000000647712161007456025412 0ustar andreyandrey--TEST-- trx_stickiness=on, RO trx, master on write pick = RR --SKIPIF-- array( 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'on', 'master_on_write' => 1, 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_ro_mor_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($slave_host_only, $user, $passwd, $db, $slave_port, $slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.multi_master=1 mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_ro_mor_rr.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* ro trx but master on write set, must use master! */ $last = NULL; for ($i = 0; $i < 3; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); if (is_null($last)) { $last = $row['_role']; } else { if ($last != $row['_role']) { printf("[007] Connection switch during transaction must not happen!\n"); break; } } } $link->commit(); /* must use master 1 */ if (!($res = mst_mysqli_query(8, $link, "SELECT @myrole AS _role"))) { printf("[009] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_role']); } /* no select, no trx... master 0, please! */ if (!($res = mst_mysqli_query(10, $link, "DROP TABLE IF EXISTS test"))) { printf("[011] [%d] %s\n", $link->errno, $link->error); } if (!($res = mst_mysqli_query(12, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH))) { printf("[013] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_role']); } print "done!"; ?> --CLEAN-- --EXPECTF-- master1 master0 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_ro_random.phpt0000664000175000017500000001036712161007456025363 0ustar andreyandrey--TEST-- trx_stickiness=on, RO trx, pick = random --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("random"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_ro_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_ro_random.ini --FILE-- thread_id] = true; $i++; } while (($i <= 10) && (count($slaves) < 2)); if (10 == $i) { die("[004] Two connections happen to have the same thread id, ignore and run again!"); } $link->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* ro transaction can be run on slave */ $last = NULL; for ($i = 0; $i < 10; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); if (is_null($last)) { $last = $link->thread_id; } else { if ($last != $link->thread_id) { printf("[007] Connection switch during transaction must not happen!\n"); break; } } /* no select... but no master, please! */ if (!($res = mst_mysqli_query(8, $link, sprintf("SET @msg='_%d'", $i)))) { printf("[009] [%d] %s\n", $link->errno, $link->error); } if ($last != $link->thread_id) { printf("[010] Connection switch during transaction must not happen!\n"); break; } } $link->commit(); /* slave */ if (!($res = mst_mysqli_query(11, $link, "SELECT CONCAT(@myrole, ' ', CONNECTION_ID()) AS _role"))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_role']); } $last = $link->thread_id; /* no select... master, please! */ if (!($res = mst_mysqli_query(13, $link, sprintf("SET @msg='_%d'", ++$i)))) { printf("[014] [%d] %s\n", $link->errno, $link->error); } if ($last == $link->thread_id) { printf("[015] Switching not back in place?\n"); } /* slave... could either be the slave used in the loop (=_msg set) or the other one (_msg not set) */ if (!($res = mst_mysqli_query(16, $link, "SELECT @msg AS _msg"))) { printf("[017] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_msg']); } print "done!"; ?> --CLEAN-- --EXPECTF-- slave %d %A done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_ro_rr.phpt0000664000175000017500000000744012161007456024524 0ustar andreyandrey--TEST-- trx_stickiness=on, RO trx, pick = random --SKIPIF-- array( 'master' => array($emulated_master_host, $emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_ro_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_ro_rr.ini mysqlnd_ms.multi_master=1 --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* ro transaction can be run on slave */ for ($i = 0; $i < 5; $i++) { if (!($res = mst_mysqli_query(5, $link, "SELECT @myrole AS _role"))) { printf("[006] [%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); printf("Run on %s\n", $row['_role']); /* no select... but no master, please! */ if (!($res = mst_mysqli_query(7, $link, sprintf("SET @msg='_%d'", $i)))) { printf("[008] [%d] %s\n", $link->errno, $link->error); } } $link->commit(); /* slave */ if (!($res = mst_mysqli_query(9, $link, "SELECT @myrole AS _role"))) { printf("[010] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_role']); } /* no select... master, please! */ if (!($res = mst_mysqli_query(11, $link, sprintf("SET @msg='_%d'", ++$i)))) { printf("[012] [%d] %s\n", $link->errno, $link->error); } mst_mysqli_fech_role(mst_mysqli_query(12, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)); if (!($res = mst_mysqli_query(13, $link, "SELECT @msg AS _msg"))) { printf("[014] [%d] %s\n", $link->errno, $link->error); } else { $row = $res->fetch_assoc(); printf("%s\n", $row['_msg']); } print "done!"; ?> --CLEAN-- --EXPECTF-- Run on slave0 Run on slave0 Run on slave0 Run on slave0 Run on slave0 slave1 This is 'master0' speaking _4 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_on_rr.phpt0000664000175000017500000000655612161007456024033 0ustar andreyandrey--TEST-- trx_stickiness=master (PHP 5.3.99+), pick = roundrobin --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'trx_stickiness' => 'master', 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_on_round_robin.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_on_round_robin.ini mysqlnd_ms.collect_statistics=1 --FILE-- autocommit(FALSE); echo "----\n"; mst_compare_stats(); echo "----\n"; /* this can be the start of a transaction, thus it shall be run on the master */ mst_mysqli_fech_role(mst_mysqli_query(5, $link, "SELECT @myrole AS _role")); echo "----\n"; mst_compare_stats(); echo "----\n"; /* back to the slave for the next SELECT because autocommit is on */ $link->autocommit(TRUE); mst_mysqli_fech_role(mst_mysqli_query(6, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(7, $link, "SELECT @myrole AS _role")); mst_mysqli_fech_role(mst_mysqli_query(8, $link, "SELECT @myrole AS _role")); /* explicitly disabling autocommit via API */ $link->autocommit(FALSE); /* SQL hint wins */ mst_mysqli_fech_role(mst_mysqli_query(9, $link, "SELECT @myrole AS _role", MYSQLND_MS_SLAVE_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role", MYSQLND_MS_LAST_USED_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(10, $link, "SELECT @myrole AS _role", MYSQLND_MS_MASTER_SWITCH)); mst_mysqli_fech_role(mst_mysqli_query(11, $link, "SELECT @myrole AS _role")); print "done!"; ?> --CLEAN-- --EXPECTF-- ---- ---- ---- Stats use_slave: 2 Stats use_master: 1 Stats use_slave_sql_hint: 2 Stats use_master_sql_hint: 1 Stats lazy_connections_slave_success: 2 Stats lazy_connections_master_success: 1 ---- ---- Stats trx_autocommit_off: 1 ---- This is 'master' speaking ---- Stats use_master: 2 Stats use_slave_guess: 1 Stats trx_master_forced: 1 ---- This is 'slave 1' speaking This is 'slave 2' speaking This is 'slave 1' speaking This is 'master' speaking This is 'master' speaking This is 'master' speaking This is 'master' speaking done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_slave_failover_random.phpt0000664000175000017500000000710512161007456027244 0ustar andreyandrey--TEST-- trx_stickiness=on, failover, random --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, "unknown:7033", $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("random"), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_slave_failover_random.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_slave_failover_random.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* This is the first query in the transaction, failover may be done to find an initial connection. Once we have a connection, it must not change, ever! */ $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[003] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); $last = $row['_slave_role']; $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[004] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($last != $row['_slave_role']) { printf("[005] Server switched in the middle of a transaction!\n"); break; } $link->commit(TRUE); $servers[$last] = true; } while ((++$i < 50) && ($res) && (0 == $link->errno)); printf("[006] %d - [%d] '%s'\n", $i, $link->errno, $link->error); printf("Number of server contacted %d\n", count($servers)); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [006] 50 - [0] '' Number of server contacted 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_trx_stickiness_slave_failover_rr.phpt0000664000175000017500000000706312161007456026412 0ustar andreyandrey--TEST-- trx_stickiness=on, failover, RR --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, "unknown:7033", $emulated_slave_host), 'trx_stickiness' => 'on', 'pick' => array("roundrobin"), 'lazy_connections' => 1, 'failover' => array('strategy' => 'loop_before_master', 'remember_failed' => 1), ), ); if ($error = mst_create_config("test_mysqlnd_ms_trx_stickiness_slave_failover_rr.ini", $settings)) die(sprintf("SKIP %s\n", $error)); _skipif_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket); _skipif_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket); if (!$link = mst_mysqli_connect($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated master: need MySQL 5.6.5+, got %s", $link->server_version)); } if (!$link = mst_mysqli_connect($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket)) die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); /* BEGIN READ ONLY exists since MySQL 5.6.5 */ if ($link->server_version < 50605) { die(sprintf("skip Emulated slave: need MySQL 5.6.5+, got %s", $link->server_version)); } ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.multi_master=1 mysqlnd_ms.config_file=test_mysqlnd_ms_trx_stickiness_slave_failover_rr.ini --FILE-- begin_transaction(MYSQLI_TRANS_START_READ_ONLY); /* This is the first query in the transaction, failover may be done to find an initial connection. Once we have a connection, it must not change, ever! */ $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[003] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); $last = $row['_slave_role']; $res = $link->query("SELECT CONNECTION_ID() AS _slave_role"); if (0 != $link->errno) { printf("[004] [%d] '%s'\n", $link->errno, $link->error); break; } $row = $res->fetch_assoc(); if ($last != $row['_slave_role']) { printf("[005] Server switched in the middle of a transaction!\n"); break; } $link->commit(TRUE); $servers[$last] = true; } while ((++$i < 5) && ($res) && (0 == $link->errno)); printf("[006] %d - [%d] '%s'\n", $i, $link->errno, $link->error); printf("Number of server contacted %d\n", count($servers)); print "done!"; ?> --CLEAN-- --EXPECTF-- Warning: mysqli::query(): php_network_getaddresses: getaddrinfo failed: %s in %s on line %d [006] 5 - [0] '' Number of server contacted 2 done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter2.phpt0000664000175000017500000000324212161007456022673 0ustar andreyandrey--TEST-- Unknown filter, filtername \0 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "a\0b" => array( "is" => "not", "fair" => "!"), "random" => array("sticky" => true), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter2.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'a' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter 'a' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter3.phpt0000664000175000017500000000332412161007456022675 0ustar andreyandrey--TEST-- Unknown filter, filtername empty string --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array("sticky" => true), "" => array( "is" => "not", "fair" => "!"), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter3.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter3.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Error loading filters. Filter with empty name found in %s on line %d [001] [2000] (mysqlnd_ms) Error loading filters. Filter with empty name found done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter4.phpt0000664000175000017500000000324012161007456022673 0ustar andreyandrey--TEST-- Unknown filter, filtername int 1 --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array("sticky" => true), 1 => array( "is" => "not", "fair" => "!"), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter4.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter4.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter '1' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter '1' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter5.phpt0000664000175000017500000000320412161007456022674 0ustar andreyandrey--TEST-- Unknown filter - no array --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array("sticky" => true), 1 => "huhu!", ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter5.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter5.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'huhu!' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter 'huhu!' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter6.phpt0000664000175000017500000000316012161007456022676 0ustar andreyandrey--TEST-- Unknown filter - no value --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "random" => array("sticky" => true), 6 ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter6.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter6.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter '6' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter '6' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter_cont_ro.phpt0000664000175000017500000000335212161007456024336 0ustar andreyandrey--TEST-- Unknown filter continue (random once) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "ulf" => array( "is" => "bored"), "random" => array("sticky" => true), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter_cont_ro.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter_cont_ro.ini --FILE-- --CLEAN-- --EXPECTF-- [E_WARNING] mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'ulf' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter 'ulf' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter_cont_r.phpt0000664000175000017500000000305012161007456024152 0ustar andreyandrey--TEST-- Unknown filter continue (random) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "ulf" => array( "is" => "amazed"), "random" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter_cont_r.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter_cont_r.ini --FILE-- --CLEAN-- --EXPECTF-- [E_WARNING] mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'ulf' . Stopping in %s on line %d done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter_cont_rr.phpt0000664000175000017500000000333212161007456024337 0ustar andreyandrey--TEST-- Unknown filter continue (round robin) --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "ulf" => array( "is" => "amazed"), "roundrobin" => array(), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter_cont_r.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter_cont_r.ini --FILE-- --CLEAN-- --EXPECTF-- [E_WARNING] mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'ulf' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter 'ulf' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_unknown_filter.phpt0000664000175000017500000000320512161007456022610 0ustar andreyandrey--TEST-- Unknown filter --SKIPIF-- array( 'master' => array( "master1" => array( 'host' => $master_host_only, 'port' => (int)$master_port, 'socket' => $master_socket, ), ), 'slave' => array( "slave1" => array( 'host' => $slave_host_only, 'port' => (int)$slave_port, 'socket' => $slave_socket, ), ), 'lazy_connections' => 0, 'filters' => array( "ulf" => array( "is" => "bored"), "random" => array("sticky" => true), ), ), ); if ($error = mst_create_config("test_mysqlnd_ms_unknown_filter.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_unknown_filter.ini --FILE-- --CLEAN-- --EXPECTF-- Warning: mysqli_real_connect(): (HY000/2000): (mysqlnd_ms) Unknown filter 'ulf' . Stopping in %s on line %d [001] [2000] (mysqlnd_ms) Unknown filter 'ulf' . Stopping done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_use_result2.phpt0000664000175000017500000000524712161007456022030 0ustar andreyandrey--TEST-- mysqli_query + MYSQLI_USE_RESULT --SKIPIF-- array( 'master' => array($master_host), 'slave' => array($slave_host, $slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_use_result2.ini", $settings)) die(sprintf("SKIP %s\n", $error)); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_use_result2.ini --FILE-- errno, $link->error); } while ($row = $res->fetch_assoc()) if ($row['_role'] != 'slave1') printf("[007] Expecting 'slave1' got '%s'\n", $row['_role']); $res->close(); mst_mysqli_query(8, $link, "DROP TABLE IF EXISTS test", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(9, $link, "CREATE TABLE test(id INT, label varchar(20))", MYSQLND_MS_LAST_USED_SWITCH); mst_mysqli_query(10, $link, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c')", MYSQLND_MS_LAST_USED_SWITCH); $ret = mst_mysqli_real_query(11, $link, "SELECT @myrole AS _role, id, label FROM test ORDER BY id ASC", MYSQLND_MS_LAST_USED_SWITCH); if (!$ret) { printf("[012] [%d] %s\n", $link->errno, $link->error); } if (!$res = mysqli_use_result($link)) printf("[013] [%d] %s\n", $link->errno, $link->error); while ($row = $res->fetch_assoc()) printf("Slave 1, field_count = %d, role = %s, id = %d, label = '%s'\n", $res->field_count, $row['_role'], $row['id'], $row['label']); print "done!"; ?> --CLEAN-- --EXPECTF-- Slave 1, field_count = 3, role = slave1, id = 1, label = 'a' Slave 1, field_count = 3, role = slave1, id = 2, label = 'b' Slave 1, field_count = 3, role = slave1, id = 3, label = 'c' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_use_result.phpt0000664000175000017500000000663612161007456021751 0ustar andreyandrey--TEST-- Unbuffered query / use_result --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => 'roundrobin', 'lazy_connections' => 1, ), ); if ($error = mst_create_config("test_mysqlnd_ms_use_result.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_use_result.ini --FILE-- real_query($query)) printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error); if (!($res = $link->use_result())) printf("[%03d + 02] [%d] %s\n", $offset, $link->errno, $link->error); while ($row = $res->fetch_assoc()) printf("[%03d + 03] '%s'\n", $offset, $row['_one']); } if (!($link = mst_mysqli_connect("myapp", $user, $passwd, $db, $port, $socket))) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); $threads = array(); /* slave 1 */ my_mysqli_query(2, $link, "SELECT 1 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(3, $link); $threads[$server_id] = array('role' => 'Slave 1', 'stat' => $link->stat()); /* slave 2 */ my_mysqli_query(4, $link, "SELECT 12 AS _one FROM DUAL"); $server_id = mst_mysqli_get_emulated_id(5, $link); $threads[$server_id] = array('role' => 'Slave 2', 'stat' => $link->stat()); /* master */ my_mysqli_query(6, $link, "SELECT 123 AS _one FROM DUAL", MYSQLND_MS_MASTER_SWITCH); $server_id = mst_mysqli_get_emulated_id(7, $link); $threads[$server_id] = array('role' => 'Master', 'stat' => $link->stat()); foreach ($threads as $server_id => $details) { printf("%s - %s: '%s'\n", $server_id, $details['role'], $details['stat']); if ('' == $details['stat']) printf("Server stat must not be empty!\n"); } print "done!"; ?> --CLEAN-- --EXPECTF-- [002 + 03] '1' [004 + 03] '12' [006 + 03] '123' %s - Slave 1: '%s' %s - Slave 2: '%s' %s - Master: '%s' done!mysqlnd_ms-1.5.2/tests/mysqlnd_ms_warning_count.phpt0000664000175000017500000001017212161007456022422 0ustar andreyandrey--TEST-- Thread id --SKIPIF-- array( 'master' => array($emulated_master_host), 'slave' => array($emulated_slave_host, $emulated_slave_host), 'pick' => array("roundrobin"), ), ); if ($error = mst_create_config("test_mysqlnd_ms_warning_count.ini", $settings)) die(sprintf("SKIP %s\n", $error)); msg_mysqli_init_emulated_id_skip($emulated_slave_host_only, $user, $passwd, $db, $emulated_slave_port, $emulated_slave_socket, "slave[1,2]"); msg_mysqli_init_emulated_id_skip($emulated_master_host_only, $user, $passwd, $db, $emulated_master_port, $emulated_master_socket, "master"); ?> --INI-- mysqlnd_ms.enable=1 mysqlnd_ms.config_file=test_mysqlnd_ms_warning_count.ini --FILE-- $label) printf("%d - %s\n", $server_id, $label); print "done!"; ?> --CLEAN-- --EXPECTF-- %s - master (2) %s - slave 1 (2) %s - slave 2 (2) done!mysqlnd_ms-1.5.2/tests/README0000664000175000017500000000224012161007456015257 0ustar andreyandreyEdit config.inc prior to running the tests. Four MySQL servers are required for running *all* tests: 1) replication master 2) replication slave Master and slave must be configured as a replication cluster. Replication must be up and running. 3) emulated replication master 4) emulated replication slave The emulated master and slave must not be setup as a replication cluster. Those servers are used whenever asynchronous replication could give false positives or errors are simulated which would break the replication stream. Most tests use the emulated server pair. Only few need the replication server pair. Some tests can be run with only one physical server as both emulated master and emulated slave, Some tests don't need MySQL at all. All configured hosts must use the same user, password settings. Using host[:port|socket] you can set the port respectively socket of the master and slave server. If not give, MYSQL_TEST_SOCKET and MYSQL_TEST_PORT are used. MYSQL_TEST_MASTER_HOST="localhost" MYSQL_TEST_SLAVE_HOST="localhost" Example using host[:port|socket] syntax: MYSQL_TEST_MASTER_HOST="127.0.0.1:3307" MYSQL_TEST_SLAVE_HOST="localhost:/tmp/mysql2.sock"mysqlnd_ms-1.5.2/tests/skipif.inc0000664000175000017500000000304612161007456016364 0ustar andreyandrey $extension) { if (!extension_loaded($extension)) die(sprintf("SKIP ext/%s not available", $extension)); } } function _skipif_connect($host, $user, $passwd, $db, $port, $socket) { if (!$link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("SKIP (h=%s,u=%s,p=%s,db=%s,P=%s,S=%s), [%d] %s\n", $host, $user, ($passwd) ? "***" : '', $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error())); } function _skipif_can_connect($host, $user, $passwd, $db, $port, $socket, $hint = NULL) { if ($link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die(sprintf("SKIP Can connect(hint: %s, h=%s,u=%s,p=%s,db=%s,P=%s,S=%s), [%d] %s\n", $hint, $host, $user, ($passwd) ? "***" : '', $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error())); } function _skipif_have_feature($feature) { $ret = false; switch ($feature) { case "table_filter": $ret = defined("MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION"); break; case "parser": $ret = true; break; default: $ret = false; break; } return $ret; } function _skipif_check_feature($features) { if (!is_array($features)) $features = array($features); foreach ($features as $k => $feature) { if (!_skipif_have_feature($feature)) die(sprintf("SKIP Feature '%s' not available", $feature)); } } _skipif_check_extensions("mysqlnd_ms"); ?>mysqlnd_ms-1.5.2/tests/util.inc0000775000175000017500000003351612161007456016064 0ustar andreyandrey true, 2003 => true, 2005 => true, ); function mst_is_slave_of($slave_host, $slave_port, $slave_socket, $master_host, $master_port, $master_socket, $user, $passwd, $db) { /* Used for skipping tests if master and slave are part of a replication setup and replication could cause false-positives */ $slave_link = mst_mysqli_connect($slave_host, $user, $passwd, $db, $slave_port, $slave_socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s", mysqli_connect_errno(), mysqli_connect_error()); } if (!($res = $slave_link->query("SHOW SLAVE STATUS"))) { return sprintf("[%d] %s", $slave_link->errno, $slave_link->error); } if (0 == $res->num_rows) { return false; } if (!($row = $res->fetch_assoc())) { return sprintf("[%d] %s", $slave_link->errno, $slave_link->error); } if ("localhost" == $master_host || '' == $master_host) { /* not sure what port master runs on, better assume servers are related */ if ($row['Master_Host'] == '127.0.0.1') return true; } if (('127.0.0.1' != $master_host) && ($master_host == $slave_host)) { /* Remote connection to two servers running on the same box. If so, the slave likely replicates from 127.0.0.1 but not from the hosts remote address, e.g. 192.168.2.21. We can't be 100% sure they are not real master/slave, thus we better assume they are. */ if (($row['Master_Host'] == '127.0.0.1') && ($row['Master_Port'] == $master_port)) return true; } if (($row['Master_Host'] == 'localhost') && ($master_host == '127.0.0.1')) $master_host = 'localhost'; return (($row['Master_Host'] == $master_host) && ($row['Master_Port'] == $master_port)); } function mst_mysqli_verbose_query($offset, $link, $query, $switch = NULL, $quiet = false, $expect_connect_warning = false, $ignore_error = false) { printf("[%03d + 01] Query '%s'\n", $offset, $query); $ret = mst_mysqli_query($offset, $link, $query, $switch = NULL, $quiet = false, $expect_connect_warning = false, $ignore_error = false); printf("[%03d + 02] Thread '%d'\n", $offset, $link->thread_id); return $ret; } function mst_mysqli_query($offset, $link, $query, $switch = NULL, $quiet = false, $expect_connect_warning = false, $ignore_error = false, $weak_connect_warning = false) { global $mst_connect_errno_codes; $query = "/*$offset*/$query"; if ($switch) $query = sprintf("/*%s*/%s", $switch, $query); if ($quiet) { /* Stupid PHP streams sometimes shout without caller being able to suppress */ ob_start(); $ret = $link->query($query); $haystack = ob_get_contents(); ob_end_clean(); if ($expect_connect_warning) { $found = false; foreach ($mst_connect_errno_codes as $code => $v) { $needle = "Warning: mysqli::query(): [" . $code . "]"; if (false !== ($found = strpos($haystack, $needle))) { break; } } if (!$found && $weak_connect_warning) { /* In 5.4-beta a warning disappeared due to network code re-factoring. It was the second of two warnings about the same mistake. After 5.4-beta there is only one warning left. */ $found = strpos($haystack, "php_network_getaddresses: getaddrinfo failed"); } if (!$found) { printf("[%03d] Cannot find the expected connect warning, got '%s'\n", $offset, $haystack); } } } else { $ret = $link->query($query); } if (!$ret && !$ignore_error && $link->errno) { if (isset($mst_connect_errno_codes[$link->errno])) printf("Connect error, "); printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); } return $ret; } function mst_mysqli_real_query($offset, $link, $query, $switch = NULL, $quiet = false, $expect_connect_warning = false, $ignore_error = false) { global $mst_connect_errno_codes; $query = "/*$offset*/$query"; if ($switch) $query = sprintf("/*%s*/%s", $switch, $query); if ($quiet) { /* Stupid PHP streams sometimes shouts without caller being able to suppress */ ob_start(); $ret = $link->real_query($query); $haystack = ob_get_contents(); ob_end_clean(); if ($expect_connect_warning) { $found = false; foreach ($mst_connect_errno_codes as $code => $v) { $needle = "Warning: mysqli::query(): [" . $code . "]"; if (false !== ($found = strpos($haystack, $needle))) { break; } } if (!$found) { printf("[%03d] Cannot find expect connect warning, got '%s'\n", $offset, $haystack); } } } else { $ret = $link->real_query($query); } if (!$ret && !$ignore_error && $link->errno) { if (isset($mst_connect_errno_codes[$link->errno])) printf("Connect error, "); printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); } return $ret; } function mst_mysqli_fech_role($res) { if (!is_object($res)) return false; $row = $res->fetch_assoc(); $res->close(); printf("This is '%s' speaking\n", $row['_role']); return true; } function mst_compare_stats() { static $last_stats = NULL; if (is_null($last_stats)) { $last_stats = mysqlnd_ms_get_stats(); return; } $stats = mysqlnd_ms_get_stats(); foreach ($stats as $k => $v) { if ($last_stats[$k] != $v) { printf("Stats %s: %d\n", $k, $v); } } $last_stats = $stats; } function mst_mysqli_create_test_table($host, $user, $passwd, $db, $port, $socket, $tablename = "test") { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } if (!$link->query(sprintf("DROP TABLE IF EXISTS %s", $link->real_escape_string($tablename))) || !$link->query(sprintf("CREATE TABLE %s(id INT) ENGINE=InnoDB", $link->real_escape_string($tablename))) || !$link->query(sprintf("INSERT INTO %s(id) VALUES (1), (2), (3), (4), (5)", $link->real_escape_string($tablename)))) return sprintf("[%d] %s\n", $link->errno, $link->error); return ''; } function mst_mysqli_drop_test_table($host, $user, $passwd, $db, $port, $socket, $tablename = "test") { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } if (!$link->query(sprintf("DROP TABLE IF EXISTS %s", $link->real_escape_string($tablename)))) return sprintf("[%d] %s\n", $link->errno, $link->error); return ''; } function mst_mysqli_fetch_id($offset, $res) { if (!$res) { printf("[%03d] No result\n", $offset); return; } $row = $res->fetch_assoc(); printf("[%03d] _id = '%s'\n", $offset, $row['_id']); } function mst_mysqli_server_supports_query($offset, $sql, $host, $user, $passwd, $db, $port, $socket) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { printf("[%03d] [%d] %s\n", $offset, mysqli_connect_errno(), mysqli_connect_error()); } printf("[%03d] Testing server support of '%s'\n", $offset, $sql); return $link->query($sql); } function msg_mysqli_init_emulated_id_skip($host, $user, $passwd, $db, $port, $socket, $role) { if (true !== ($msg = _mst_mysqli_init_emulated_id(1, $host, $user, $passwd, $db, $port, $socket, $role))) die(sprintf("SKIP Cannot setup emulated server id, %s", $msg)); } function mst_mysqli_init_emulated_id($offset, $host, $user, $passwd, $db, $port, $socket, $role) { if (true !== ($msg = _mst_mysqli_init_emulated_id($offset, $host, $user, $passwd, $db, $port, $socket, $role))) echo $msg; return true; } function _mst_mysqli_init_emulated_id($offset, $host, $user, $passwd, $db, $port, $socket, $role) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%03d] [%d] %s\n", $offset, mysqli_connect_errno(), mysqli_connect_error()); } if (!$link->query("DROP TABLE IF EXISTS _mysqlnd_ms_roles") || !$link->query("CREATE TABLE _mysqlnd_ms_roles(role VARCHAR(255) NOT NULL)") || !$link->query(sprintf("INSERT INTO _mysqlnd_ms_roles(role) values ('%s')", $link->real_escape_string($role)))) { return sprintf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); } return true; } function mst_mysqli_drop_emulated_id($host, $user, $passwd, $db, $port, $socket) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%03d] [%d] %s\n", $offset, mysqli_connect_errno(), mysqli_connect_error()); } if (!$link->query("DROP TABLE IF EXISTS _mysqlnd_ms_roles")) { return sprintf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); } return true; } function mst_mysqli_get_emulated_id($offset, $link) { $thread_id = $link->thread_id; if (0 == $thread_id) return NULL; $query = sprintf("/*%s*//*%d*//*util.inc*/SELECT role FROM _mysqlnd_ms_roles", MYSQLND_MS_LAST_USED_SWITCH, $offset); if (!($res = $link->query($query))) { printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); return NULL; } if ($res->num_rows > 1) { printf("[%03d] _mysqlnd_ms_roles holds more than one row\n", $offset); return NULL; } if ($thread_id != $link->thread_id) { printf("[%03] Unexpected connection switch\n"); return NULL; } $row = $res->fetch_assoc(); return sprintf("%s-%d", $row['role'], $link->thread_id); } function mst_get_gtid_sql($mst_gtid_db) { return array( 'drop' => 'DROP TABLE IF EXISTS ' . $mst_gtid_db . '.trx', 'create' => 'CREATE TABLE ' . $mst_gtid_db . '.trx(trx_id INT, last_update TIMESTAMP) ENGINE=InnoDB', 'insert' => 'INSERT INTO ' . $mst_gtid_db . '.trx(trx_id) VALUES (0)', 'update' => 'UPDATE ' . $mst_gtid_db . '.trx SET trx_id = trx_id + 1', 'select' => 'SELECT trx_id FROM ' . $mst_gtid_db . '.trx', 'fetch_last_gtid' => 'SELECT MAX(trx_id) FROM ' . $mst_gtid_db . '.trx', 'check_for_gtid' => 'SELECT trx_id FROM ' . $mst_gtid_db . '.trx WHERE trx_id >= #GTID', /* tests only - not needed for ms configuration */ 'set' => 'INSERT INTO ' . $mst_gtid_db . '.trx(trx_id) VALUES (#GTID)', /* SLEEP() cannot be used here */ 'check_for_gtid_wait' => 'SELECT trx_id FROM ' . $mst_gtid_db . '.trx WHERE trx_id >= #GTID', 'wait_for_seconds' => 2, 'wait_for_gtid_fail' => 1, 'wait_for_gtid_succeed' => 3, ); } function mst_mysqli_drop_gtid_table($host, $user, $passwd, $db, $port, $socket, $drop = NULL) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } $sql = mst_get_gtid_sql($db); if (!$link->query(($drop) ? $drop : $sql['drop'])) return sprintf("[%d] %s\n", $link->errno, $link->error); return NULL; } function mst_mysqli_setup_gtid_table($host, $user, $passwd, $db, $port, $socket, $drop = NULL, $create = NULL, $insert = NULL) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } if ($err = mst_mysqli_drop_gtid_table($host, $user, $passwd, $db, $port, $socket, $drop)) return $err; $sql = mst_get_gtid_sql($db); if (!$link->query(($create) ? $create : $sql['create'])) return sprintf("[%d] %s\n", $link->errno, $link->error); if (!$link->query(($insert) ? $insert : $sql['insert'])) return sprintf("[%d] %s\n", $link->errno, $link->error); } function mst_mysqli_fetch_gtid($offset, $link, $db) { $sql = mst_get_gtid_sql($db); $query = sprintf("/*%d*/%s", $offset, $sql['select']); if (!($res = $link->query($query))) { printf("[%03d] [%d] %s\n", $offset, $link->errno, $link->error); return NULL; } $row = $res->fetch_row(); return $row[0]; } function mst_mysqli_server_supports_gtid($host, $user, $passwd, $db, $port, $socket) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } if (!($res = $link->query("SHOW GLOBAL VARIABLES LIKE 'GTID_MODE'"))) { return false; } $row = $res->fetch_assoc(); if (!$row) return false; return ('ON' == $row['Value']) ? true : false; } function mst_mysqli_get_slave_lag($host, $user, $passwd, $db, $port, $socket) { $link = mst_mysqli_connect($host, $user, $passwd, $db, $port, $socket); if (mysqli_connect_errno()) { return sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } /* NOTE: logic should always match mysqlnd_ms_flter_qos.c logic */ if (!($res = $link->query("SHOW SLAVE STATUS"))) { return sprintf("[%d] %s\n", $link->errno, $link->error); } $row = $res->fetch_assoc(); $res->free(); if (!isset($row['Slave_IO_Running'])) return "Failed to extract Slave_IO_Running"; if ("Yes" != $row['Slave_IO_Running']) return "Slave_IO_Running is not 'Yes'"; if (!isset($row['Slave_SQL_Running'])) return 'Failed to extract Slave_SQL_Running'; if ("Yes" != $row['Slave_SQL_Running']) return "Slave_SQL_Running is not 'Yes'"; if (!isset($row['Seconds_Behind_Master'])) return 'Failed to extract Seconds_Behind_Master'; return (int)$row['Seconds_Behind_Master']; } ?>mysqlnd_ms-1.5.2/tests/config.inc0000664000175000017500000000327712161007456016352 0ustar andreyandreymysqlnd_ms-1.5.2/tests/connect.inc0000664000175000017500000003745212161007456016540 0ustar andreyandreyreal_connect($host, $user, $passwd, $db, $port, $socket, $flags); } else { parent::__construct($host, $user, $passwd, $db, $port, $socket); } } } function mst_mysqli_get_charsets($link) { /* Those tree are set by SET NAMES */ $charsets = array( 'client' => NULL, 'results' => NULL, 'connection' => NULL, ); if (!($res = mysqli_query($link, "SHOW VARIABLES LIKE '%character%'"))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } $names = array(); while ($row = mysqli_fetch_assoc($res)) { $names[$row['Variable_name']] = $row['Value']; } mysqli_free_result($res); if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $names['character_set_client']))) || !($details = mysqli_fetch_assoc($res))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } mysqli_free_result($res); $charsets['client'] = array( 'charset' => $details['Charset'], 'desc' => $details['Description'], 'collation' => $details['Default collation'], 'maxlen' => $details['Maxlen'], 'nr' => NULL, ); if (!($res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $details['Default collation']))) || !($collation = mysqli_fetch_assoc($res))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } mysqli_free_result($res); $charsets['client']['nr'] = $collation['Id']; if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $names['character_set_results']))) || !($details = mysqli_fetch_assoc($res))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } mysqli_free_result($res); $charsets['results'] = array( 'charset' => $details['Charset'], 'desc' => $details['Description'], 'collation' => $details['Default collation'], 'maxlen' => $details['Maxlen'], 'nr' => NULL, ); if (!($res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $details['Default collation']))) || !($collation = mysqli_fetch_assoc($res))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } mysqli_free_result($res); $charsets['results']['nr'] = $collation['Id']; if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $names['character_set_connection']))) || !($details = mysqli_fetch_assoc($res))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } mysqli_free_result($res); $charsets['connection'] = array( 'charset' => $details['Charset'], 'desc' => $details['Description'], 'collation' => $details['Default collation'], 'maxlen' => $details['Maxlen'], 'nr' => NULL, ); if (!($res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $details['Default collation']))) || !($collation = mysqli_fetch_assoc($res))) { printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link)); return $charsets; } mysqli_free_result($res); $charsets['connection']['nr'] = $collation['Id']; return $charsets; } if (extension_loaded("pdo_mysql")) { function my_pdo_connect($host, $user, $passwd, $db, $port, $socket, $options = NULL) { if (is_null($options)) $options = array( PDO::ATTR_EMULATE_PREPARES => true, PDO::MYSQL_ATTR_DIRECT_QUERY => true, ); if ($port) { $dsn = sprintf("mysql:host=%s;port=%d;dbname=%s", $host, $port, $db); } else { $dsn = sprintf("mysql:host=%s;unix_socket=%s;dbname=%s", $host, $socket, $db); } return new PDO($dsn, $user, $passwd, $options); } } } else { printf("skip Eeeek/BUG/FIXME - connect.inc included twice! skipif bug?\n"); } if (!function_exists("mst_create_config")) { function mst_create_config($file, $settings, $replace_file = true, $format = 'json') { switch ($format) { case 'json': return mst_create_config_json($file, $settings, $replace_file); break; case 'ini': default: return mst_create_config_ini($file, $settings, $replace_file); break; } } function mst_create_config_json($file, $settings, $replace_file) { if ($replace_file && file_exists($file) && !@unlink($file)) return sprintf("Cannot unlink existing file '%s'.", $file); if (!$fp = @fopen($file, "w")) return sprintf("Cannot open file '%s' for writing.", $file); $json = array(); foreach ($settings as $application => $config) { $json[$application] = array(); if (isset($config['master'])) { if (!is_array($config['master'])) return sprintf("The master must be set using a hash"); $json[$application]['master'] = array(); foreach ($config['master'] as $idx => $host) { if (is_array($host)) { /* 1.1. syntax */ if (is_string($idx)) { $json[$application]['master'][$idx] = $host; } else { $json[$application]['master']['master_' . $idx] = $host; } } else { $host_config = array(); if (false !== stristr($host, ':')) { /* 1.0 legacy */ list($real_host, $port) = explode(':', $host); $host_config['host'] = $real_host; if ($port) { if (!is_numeric($port)) { $host_config['socket'] = $port; } else { $host_config['port'] = $port; } } } else { $host_config['host'] = $host; } $json[$application]['master']['master_' . $idx] = $host_config; } } } if (isset($config['slave'])) { $json[$application]['slave'] = array(); foreach ($config['slave'] as $idx => $host) { if (is_array($host)) { if (is_string($idx)) { $json[$application]['slave'][$idx] = $host; } else { $json[$application]['slave']['slave_' . $idx] = $host; } } else { $host_config = array(); /* 1.0 legacy */ if (false !== stristr($host, ':')) { list($real_host, $port) = explode(':', $host); $host_config['host'] = $real_host; if ($port) { if (!is_numeric($port)) { $host_config['socket'] = $port; } else { $host_config['port'] = $port; } } } else { $host_config['host'] = $host; } $json[$application]['slave']['slave_' . $idx] = $host_config; } } } if (isset($config['filters'])) { $json[$application]['filters'] = $config['filters']; } else if (isset($config['pick'])) { if (!is_array($config['pick'])) $config['pick'] = array($config['pick']); /* 1. array('random') -- is_int()==true, take $method_values 2. array('random' => array('once' => '1')) -- is_int()==false, take $method for name */ foreach ($config['pick'] as $method => $method_values) { $json[$application]['filters'][is_int($method)? (string)$method_values:(string)$method] = is_int($method)? array() : (is_array($method_values)? $method_values : array($method_values)); } } if (isset($config['lazy_connections'])) { $json[$application]['lazy_connections'] = (string)$config['lazy_connections']; } if (isset($config['server_charset'])) { $json[$application]['server_charset'] = (string)$config['server_charset']; } if (isset($config['failover'])) { $json[$application]['failover'] = $config['failover']; } if (isset($config['master_on_write'])) { $json[$application]['master_on_write'] = (string)$config['master_on_write']; } if (isset($config['trx_stickiness'])) { $json[$application]['trx_stickiness'] = (string)$config['trx_stickiness']; } if (isset($config['global_transaction_id_injection'])) { $json[$application]['global_transaction_id_injection'] = $config['global_transaction_id_injection']; } } fwrite($fp, json_encode($json)); fclose($fp); return ''; } } function mst_error_handler($errno, $error, $file, $line) { /* KLUDGE */ global $mst_ignore_errors; static $errcodes = array(); if (empty($errcodes)) { $constants = get_defined_constants(); foreach ($constants as $name => $value) { if (substr($name, 0, 2) == "E_") $errcodes[$value] = $name; } } $msg = sprintf("[%s] %s in %s on line %s\n", (isset($errcodes[$errno])) ? $errcodes[$errno] : $errno, $error, $file, $line); if (isset($mst_ignore_errors) && is_array($mst_ignore_errors)) { foreach ($mst_ignore_errors as $pattern) { if (stristr($msg, $pattern)) return true; } } echo $msg; return true; } ?> mysqlnd_ms-1.5.2/CHANGES0000664000175000017500000002722412161007456014241 0ustar andreyandrey1.4.2 stable Release date: 06/2013 Fixed problems with versions 1.4.1 stable Release date: 06/2013 Release as stable 1.5.0 alpha Motto/theme: Sharding support, improved transaction support Release date: 03/2013 * BC break and bug fix: SQL hints enforcing the use of a specific server are ignored for the duration of a transaction, given a transaction has been properly detected. Please note, other than intended SQL hints did not overrule all other rules in prior versions in all cases (bug). For example, the QoS filter did ignore the SQL hints MYSQLND_MS_USE_SLAVE, MYSQLND_MS_USE_MASTER, MYSQLND_MS_USE_LAST_USED already in prior versions whereas transaction stickiness could be overruled using the SQL hints if, and only if, transaction stickiness was not used with a QoS filter. The new behaviour differs from the previous but its consistent: neither transaction stickiness nor QoS can be overruled by SQL hints. It is no longer possible to send a query to a slave using MYSQLND_MS_USE_SLAVE hint when in a transaction that is to be executed on the master. This is most likely what you expect anyway. * BC break and bug fix: Calls to mysqlnd_ms_set_qos() are blocked in the middle of a transaction if transaction stickiness is set and transaction boundaries are detected properly. Switching servers is forbidden in the middle of a transaction, thus changes to quality of service resulting in different servers being used are blocked. However, if autocommit is disabled one can still change QoS in between transactions like so: autocommit(false); mysqlnd_ms_set_qos(); begin(); ... ; commit(); mysqlnd_ms_set_qos(); begin(); This is no longer allowed: autocommit(false); query()|begin(): mysqlnd_ms_set_qos(); * Fixed #60605 PHP segmentation fault when mysqlnd_ms is enabled The bug was caused by using an uninitialized handle. Implicit connect as part of lazy connections have been extended to cover (hopefully) all situations in which the status of a connection is read before a connection has been established, for example, situations in which get_server_version() is called prior to connecting to any server. The implicit connect added will establish a connection to the first configured master. The extended implicit connect also means less warnings, for example, when calling more_results() on a connection handle on which no query has been run so far. * New filter: node_groups The filter lets you organize servers (master and slaves) in groups. Queries can be directed to a certain group of servers by prefixing the query statement with a SQL hint/comment, e.g.: /*group_name*/SELECT ... /*group_name*/INSERT ... Directing a query to a fixed and predefined subset of cluster nodes may be desired for cache locality optimizations (keep certain server caches hot with certain queries) or to build shard/partitioning groups. In the latter case the group_name can be considered a shard key. Note, however, this is only the client part, which is the easiest. Do not confuse the feature with the table filter (experimental) which supports schema based partitioning (do-replicate-* server config). * examples/ contents clearned up * Extended warnings during RINIT about faulty configuration file PHP warnings are thrown is the configuration file cannot be read, is empty or contains no valid JSON. Distributions that aim to provide a pre-configured setup including a configuration file stub are asked to put {} into the configuration file to prevent any warnings about an invalid configuration. * Fixed: Setting transaction stickiness disables all load balancing, including automatic failover, for the duration of a transaction. So far connection switches could have happened in the middle of a transaction in multi-master configurations and during automatic failover although transaction monitoring had detected transaction boundaries properly. * Added transaction monitoring based on mysqlnd tx_begin() (user space call: mysqli_begin(), mysqli_rollback(), ...) NOTE: PDO_MySQL has not yet been modified to use the appropriate mysqlnd library calls. Improved trx monitoring works with mysqli only. * Added new transaction stickiness setting trx_stickiness=on which allows the use of slaves for read only transactions. * Removed experimental feature notes for remember_failed failover setting from documentation. remember_failed is very useful together with the improved trx_stickiness=on setting. * Marked query cache support as beta for mysqli in config.m4. It should work fine for primary copy based clusters. NOTE: PDO is a different story, still experimental. 1.4.2 stable Release date: 08/2012 1.4.1 beta Release date: 08/2012 * Fixed compatibility with PHP 5.5 1.4.0 alpha Motto/theme: Tweaking based on user feedback Release date: 07/2012 * BC break: renamed ini setting "ini_file" to "config_file". Earlier versions have been configured through an ini style file and its name was set with the ini setting "ini_file". The ini style soon got replaced with JSON. We are now updating the file name to config_file to leave the past behing and avoid confusion with the PHP configuration file * New config setting: "server_charset". Allows setting of charset to be used for string encoding before connections have been opened. Most useful with lazy connections. * Improved error messages if opening and/or parsing of plugin configuration file fails. * Added "wait_for_gtid_timeout" for throttling of read-your-write SELECTs * Weighted load balancing. Servers can have a weight. Before picking a server, the load balancing logic sorts the server list by weight and picks the one with the highest weight. Then, the weight counter is decremented and the same logic is applied for the next request. * New failover strategy "loop_before_master". If connecting to a slave fails the plugin can either return an error to the caller (strategy "disabled", default), fall back to the master (stategy "master") or try to connect to any of the other slaves before connecting to the master (stategy "loop_before_master"). * New "max_retries" setting to be used with fail over strategy "loop_before_master". If "max_retries" is set to 0 (default), all alternatives will be tested and the search is unlimited. Set max_retries to n to limit slave connection attempts to n attempts before falling back to master. If, multiple master are configured and max_retries = n != 0, then n masters are tested. No matter whether there was a slave loop before or not. This means that there can be update 2 * n connection attempts before the plugin gives up. Experimental: stable but syntax may change and QoS may not support it. * New "remember_failed" setting to remember hosts that have failed and skip them for the rest of the the web request instead of attempting to connect again. Experimental: stable with roundrobin and random but not supported with QoS - syntax is likely to change due to refactoring. 1.3.2 stable Release date: 04/2012 * Fixed problem with multi-master where although in a transaction the queries to the master weren't sticky and were spread all over the masters (RR). Still not sticky for Random. Random_once is not affected. 1.3.1 beta Release date: 04/2012 * Fixed problem with building together with QC. 1.3.0 alpha Motto/theme: Query caching through quality-of-service concept Release date: 04/2012 * Added support for MySQL 5.6.5-m8+ global transaction ID feature - GTID is string if using server-side feature - GTID continues to be a long if using client-side emulation * Added query cache support to quality-of-service filter - new compile option --enable-mysqlnd-ms-cache-support - new constant MYSQLND_MS_QOS_OPTION_CACHE to be used with mysqlnd_ms_set_qos() - new constant MYSQLND_MS_HAVE_CACHE_SUPPORT set if cache support is compiled in 1.2.1 beta Motto/theme: Global Transaction ID injection and quality-of-service concept Release date: 01/2012 * No major changes 1.2.0 alpha Motto/theme: Global Transaction ID injection and quality-of-service concept Release date: 12/2011 * Introduced quality-of-service (QoS) filter * Added mysqlnd_ms_set_qos() function to set required connection quality at runtime * New constants related to mysqlnd_ms_set_qos() - MYSQLND_MS_QOS_CONSISTENCY_STRONG - MYSQLND_MS_QOS_CONSISTENCY_SESSION - MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL - MYSQLND_MS_QOS_OPTION_GTID - MYSQLND_MS_QOS_OPTION_AGE * Service levels provided by QoS filter * eventual consistency, optional option slave lag * session consistency, optional option GTID * strong consistency * Added global transaction ID injection (GTID) * Added mysqlnd_ms_get_last_gtid() to fetch last transaction id * Enabled support for multi master with or without slaves * New statistics related to GTID: - gtid_autocommit_injections_success - gtid_autocommit_injections_failure - gtid_commit_injections_success - gtid_commit_injections_failure - gtid_implicit_commit_injections_success - gtid_implicit_commit_injections_failure 1.1.2 stable / production ready Motto/theme : Cover replication basics with production quality Release date: 11/2011 * Introduced mysqlnd_ms.disable_rw_split ini setting * Fixed Bug #60119 - host="localhost" lost in mysqlnd_ms_get_last_used_connection() 1.1.1 beta Motto/theme : Cover replication basics with production quality Release date: 10/2011 * NOTE: 1.1.0 alpha (PECL version) has reported itself as "1.1.0-beta" * Fixed PECL #59982 - Unusable extension with --enable-mysqlnd-ms-table-filter Use of the option is NOT supported. You must not used it. Added note to m4. 1.1.0 alpha Motto/theme : Cover replication basics with production quality Release date: 09/2011 * Code base refactored to prepare for future releases * Introduction of (chainable) filter concept * New powerful JSON based configuration syntax * Lazy connections improved: security relevant, state changing commands covered * Support for (native) prepared statements * Added new function - mysqlnd_ms_get_last_used_connection($obj_or_res) * Replaced mysqlnd_ms_set_user_pick_server() with "user" filter * New statistics: use_slave_guess, use_master_guess * Change of semantics of statistics: use_slave, use_master * List of broadcasted messages extended: ssl_set * Commands monitored to remember settings for lazy connections: change_user, select_db, set_charset, set_autocommit. * The plugin configuration file must contain a slave list. Failing to provide will cause an E_ERROR level error (fatal). The slave list may be empty. * MySQL replication filter (client-side partitioning) support prepared * Multi-master configuration support prepared (ini setting: mysqlnd_ms.multi_master) * Almost 5x more tests, code coverage through tests 75-90% for core files * Fixed PECL #22724 - Server switching (mysqlnd_ms_query_is_select case sensitive) * Fixed PECL #22784 - Using mysql_connect and mysql_select_db() won't work 1.0 alpha Release date: 04/2011 Motto/theme : Cover replication basics to test user feeedback * Basic automatic read-write split (read: slave, write: master) * SQL hints to overrule automatic R/W split * Load balancing of slave requests 1.0 pre-alpha Release date: 09/2010 Motto/theme : Proof-of-concept * Initial check-in * Hardly more than a demo of the mysqlnd * Hardly of any practial use. mysqlnd_ms-1.5.2/config.m40000664000175000017500000000347412161007456014756 0ustar andreyandreyPHP_ARG_ENABLE(mysqlnd_ms, whether to enable mysqlnd_ms support, [ --enable-mysqlnd-ms Enable mysqlnd_ms support]) PHP_ARG_ENABLE(mysqlnd_ms_table_filter, whether to enable table filter in mysqlnd_ms, [ --enable-mysqlnd-ms-table-filter Enable support for table filter in mysqlnd_ms (EXPERIMENTAL - do not use!)], no, no) PHP_ARG_ENABLE(mysqlnd_ms_cache_support, whether to query caching through mysqlnd_qc in mysqlnd_ms, [ --enable-mysqlnd-ms-cache-support Enable query caching through mysqlnd_qc (BETA for mysqli - try!, EXPERIMENTAL for all other - do not use!)], no, no) if test "$PHP_MYSQLND_MS" && test "$PHP_MYSQLND_MS" != "no"; then PHP_SUBST(MYSQLND_MS_SHARED_LIBADD) mysqlnd_ms_sources="php_mysqlnd_ms.c mysqlnd_ms.c mysqlnd_ms_switch.c mysqlnd_ms_config_json.c \ mf_wcomp.c mysqlnd_query_lexer.c \ mysqlnd_ms_filter_random.c mysqlnd_ms_filter_round_robin.c \ mysqlnd_ms_filter_user.c mysqlnd_ms_filter_qos.c \ mysqlnd_ms_lb_weights.c mysqlnd_ms_filter_groups.c" if test "$PHP_MYSQLND_MS_TABLE_FILTER" && test "$PHP_MYSQLND_MS_TABLE_FILTER" != "no"; then AC_DEFINE([MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION], 1, [Enable table partition support]) mysqlnd_ms_sources="$mysqlnd_ms_sources mysqlnd_query_parser.c mysqlnd_ms_filter_table_partition.c" fi if test "$PHP_MYSQLND_MS_CACHE_SUPPORT" && test "$PHP_MYSQLND_MS_CACHE_SUPPORT" != "no"; then AC_MSG_CHECKING([for mysqlnd_qc header location]); PHP_ADD_EXTENSION_DEP(mysqlnd_ms, mysqlnd_qc) AC_DEFINE([MYSQLND_MS_HAVE_MYSQLND_QC], 1, [Whether mysqlnd_qc is enabled]) fi PHP_ADD_EXTENSION_DEP(mysqlnd_ms, mysqlnd) PHP_ADD_EXTENSION_DEP(mysqlnd_ms, json) PHP_NEW_EXTENSION(mysqlnd_ms, $mysqlnd_ms_sources, $ext_shared) PHP_INSTALL_HEADERS([ext/mysqlnd_ms/]) fi mysqlnd_ms-1.5.2/config.w320000664000175000017500000000103012161007456015033 0ustar andreyandrey// $Id$ // vim:ft=javascript ARG_ENABLE("mysqlnd-ms", "enable mysqlnd_ms support", "no"); if (PHP_MYSQLND_MS != "no") { ADD_EXTENSION_DEP('mysqlnd_ms', 'mysqlnd'); EXTENSION("mysqlnd_ms", "php_mysqlnd_ms.c mysqlnd_ms.c mysqlnd_ms_switch.c " + "mysqlnd_ms_config_json.c mf_wcomp.c mysqlnd_query_lexer.c " + "mysqlnd_ms_filter_random.c " + "mysqlnd_ms_filter_round_robin.c mysqlnd_ms_filter_user.c " + "mysqlnd_ms_filter_qos.c" + "mysqlnd_ms_lb_weights.c" + "mysqlnd_ms_filter_groups.c"); } mysqlnd_ms-1.5.2/CREDITS0000664000175000017500000000010712161007456014255 0ustar andreyandreymysqlnd_ms Andrey Hristov, Ulf Wendel, Johannes Schlueter, Oracle Corp.mysqlnd_ms-1.5.2/LICENSE0000664000175000017500000000622212161007456014246 0ustar andreyandrey-------------------------------------------------------------------- The PHP License, version 3.01 Copyright (c) 1999 - 2010 The PHP Group. All rights reserved. -------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, is permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name "PHP" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact group@php.net. 4. Products derived from this software may not be called "PHP", nor may "PHP" appear in their name, without prior written permission from group@php.net. You may indicate that your software works in conjunction with PHP by saying "Foo for PHP" instead of calling it "PHP Foo" or "phpfoo" 5. The PHP Group may publish revised and/or new versions of the license from time to time. Each version will be given a distinguishing version number. Once covered code has been published under a particular version of the license, you may always continue to use it under the terms of that version. You may also choose to use such covered code under the terms of any subsequent version of the license published by the PHP Group. No one other than the PHP Group has the right to modify the terms applicable to covered code created under this License. 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes PHP software, freely available from ". THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- This software consists of voluntary contributions made by many individuals on behalf of the PHP Group. The PHP Group can be contacted via Email at group@php.net. For more information on the PHP Group and the PHP project, please see . PHP includes the Zend Engine, freely available at . mysqlnd_ms-1.5.2/mf_wcomp.c0000664000175000017500000000473412161007456015222 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ #include "php.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_priv.h" #include "ext/mysqlnd/mysqlnd_debug.h" /* $Id: mysqlnd_ms_config_json.c 311386 2011-05-24 12:10:21Z andrey $ */ /* {{{ mysqlnd_ms_match_wild */ PHPAPI zend_bool mysqlnd_ms_match_wild(const char * const str, const char * const wildstr TSRMLS_DC) { static char many = '%'; static char single = '_'; static char escape = '\\'; const char * s = str; const char * w = wildstr; DBG_ENTER("mysqlnd_ms_match_wild"); /* check for */ if (!s || !w) { DBG_RETURN(FALSE); } do { while (*w != many && *w != single) { if (*w == escape && !*++w) { DBG_RETURN(FALSE); } if (*s != *w) { DBG_RETURN(FALSE); } else if (!*s) { /* the same chars, and both are \0 terminators */ DBG_RETURN(TRUE); } /* still not the end */ ++s; ++w; } /* one or many */ if (*w == many) { /* even if *s is \0 this is ok */ DBG_RETURN(TRUE); } else if (*w == single) { if (!*s) { /* single is not zero */ DBG_RETURN(FALSE); } ++s; ++w; } } while (1); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms.c0000664000175000017500000025721012161007456015600 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 329522 2013-02-20 17:10:01Z uw $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/info.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #include "ext/mysqlnd/mysqlnd_charset.h" #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #ifndef mnd_sprintf #define mnd_sprintf spprintf #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_config_json.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_switch.h" #if PHP_VERSION_ID < 50400 #define mnd_vsprintf vspprintf #define mnd_sprintf_free efree #endif #if PHP_VERSION_ID < 50400 #define CONN_GET_OPTION(conn, option) (conn)->options.option #else #define CONN_GET_OPTION(conn, option) (conn)->options->option #endif #if MYSQLND_VERSION_ID >= 50010 #define MS_LOAD_AND_COPY_CONN_HANDLE_METHODS(orig_methods, ms_methods) \ (orig_methods) = mysqlnd_conn_get_methods(); \ memcpy(&(ms_methods), (orig_methods), sizeof(struct st_mysqlnd_conn_methods)); #define MS_SET_CONN_HANDLE_METHODS(ms_methods) mysqlnd_conn_set_methods((ms_methods)); #define MS_LOAD_AND_COPY_CONN_DATA_METHODS(orig_methods, ms_methods) \ (orig_methods) = mysqlnd_conn_data_get_methods(); \ memcpy(&(ms_methods), (orig_methods), sizeof(struct st_mysqlnd_conn_data_methods)); #define MS_SET_CONN_DATA_METHODS(ms_methods) mysqlnd_conn_data_set_methods((ms_methods)); #define MS_GET_CONN_DATA_FROM_CONN(conn) (conn)->data struct st_mysqlnd_conn_data_methods * ms_orig_mysqlnd_conn_methods; static struct st_mysqlnd_conn_methods my_mysqlnd_conn_handle_methods; struct st_mysqlnd_conn_methods * ms_orig_mysqlnd_conn_handle_methods; static struct st_mysqlnd_conn_data_methods my_mysqlnd_conn_methods; #else #define MS_LOAD_AND_COPY_CONN_HANDLE_METHODS(orig_methods, ms_methods) #define MS_SET_CONN_HANDLE_METHODS(ms_methods) #define MS_LOAD_AND_COPY_CONN_DATA_METHODS(orig_methods, ms_methods) \ (orig_methods) = mysqlnd_conn_get_methods(); \ memcpy(&(ms_methods), (orig_methods), sizeof(struct st_mysqlnd_conn_methods)); #define MS_SET_CONN_DATA_METHODS(ms_methods) mysqlnd_conn_set_methods((ms_methods)); #define MS_GET_CONN_DATA_FROM_CONN(conn) (conn) struct st_mysqlnd_conn_methods * ms_orig_mysqlnd_conn_methods; static struct st_mysqlnd_conn_methods my_mysqlnd_conn_methods; #endif struct st_mysqlnd_stmt_methods * ms_orig_mysqlnd_stmt_methods; static struct st_mysqlnd_stmt_methods my_mysqlnd_stmt_methods; static void mysqlnd_ms_conn_free_plugin_data(MYSQLND_CONN_DATA * conn TSRMLS_DC); MYSQLND_STATS * mysqlnd_ms_stats = NULL; #define CONN_DATA_NOT_SET(conn_data) (!(conn_data) || !*(conn_data) || !(*(conn_data))->initialized || (*(conn_data))->skip_ms_calls) #define CONN_DATA_TRX_SET(conn_data) ((conn_data) && (*(conn_data)) && (!(*(conn_data))->skip_ms_calls)) #define CONN_DATA_TRY_TRX_INJECTION(conn_data, conn) ((CONN_GET_STATE(conn) > CONN_ALLOCED) && ((FALSE == (*(conn_data))->skip_ms_calls)) && ((*(conn_data))->global_trx.on_commit) && (TRUE == (*(conn_data))->global_trx.is_master)) #define MS_TRX_INJECT(ret, connection, conn_data) \ if (PASS == (ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(send_query)((connection), ((*(conn_data))->global_trx.on_commit), ((*(conn_data))->global_trx.on_commit_len) TSRMLS_CC))) \ (ret) = MS_CALL_ORIGINAL_CONN_DATA_METHOD(reap_query)((connection) TSRMLS_CC); /* {{{ mysqlnd_ms_client_n_php_error */ void mysqlnd_ms_client_n_php_error(MYSQLND_ERROR_INFO * error_info, unsigned int client_error_code, const char * const client_error_state, unsigned int php_error_level TSRMLS_DC, const char * const format, ...) { char * error_buf; va_list args; DBG_ENTER("mysqlnd_ms_client_n_php_error"); va_start(args, format); mnd_vsprintf(&error_buf, 0, format, args); va_end(args); if (error_info) { SET_CLIENT_ERROR((*error_info), client_error_code, client_error_state, error_buf); } if (php_error_level) { php_error_docref(NULL TSRMLS_CC, php_error_level, "%s", error_buf); } DBG_ERR_FMT("%s", error_buf); mnd_sprintf_free(error_buf); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_get_scheme_from_list_data */ static int mysqlnd_ms_get_scheme_from_list_data(MYSQLND_MS_LIST_DATA * el, char ** scheme, zend_bool persistent TSRMLS_DC) { char * tmp = NULL; int scheme_len; *scheme = NULL; #ifndef PHP_WIN32 if (el->host && !strcasecmp("localhost", el->host)) { scheme_len = mnd_sprintf(&tmp, 0, "unix://%s", el->socket? el->socket : "/tmp/mysql.sock"); #else if (el->host && !strcmp(".", el->host)) { scheme_len = mnd_sprintf(&tmp, 0, "pipe://%s", el->socket? el->socket : "\\\\.\\pipe\\MySQL"); #endif } else { if (!el->port) { el->port = 3306; } scheme_len = mnd_sprintf(&tmp, 0, "tcp://%s:%u", el->host? el->host:"localhost", el->port); } if (tmp) { *scheme = mnd_pestrndup(tmp, scheme_len, persistent); efree(tmp); /* allocated by spprintf */ } return scheme_len; } /* }}} */ /* {{{ mysqlnd_ms_conn_list_dtor */ void mysqlnd_ms_conn_list_dtor(void * pDest) { MYSQLND_MS_LIST_DATA * element = pDest? *(MYSQLND_MS_LIST_DATA **) pDest : NULL; TSRMLS_FETCH(); DBG_ENTER("mysqlnd_ms_conn_list_dtor"); DBG_INF_FMT("conn=%p", element->conn); if (!element) { DBG_VOID_RETURN; } if (element->name_from_config) { mnd_pefree(element->name_from_config, element->persistent); element->name_from_config = NULL; } if (element->conn) { element->conn->m->free_reference(element->conn TSRMLS_CC); element->conn = NULL; } if (element->host) { mnd_pefree(element->host, element->persistent); element->host = NULL; } if (element->user) { mnd_pefree(element->user, element->persistent); element->user = NULL; } if (element->passwd) { mnd_pefree(element->passwd, element->persistent); element->passwd = NULL; } if (element->db) { mnd_pefree(element->db, element->persistent); element->db = NULL; } if (element->socket) { mnd_pefree(element->socket, element->persistent); element->socket = NULL; } if (element->emulated_scheme) { mnd_pefree(element->emulated_scheme, element->persistent); element->emulated_scheme = NULL; } mnd_pefree(element, element->persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_lazy_connect */ enum_func_status mysqlnd_ms_lazy_connect(MYSQLND_MS_LIST_DATA * element, zend_bool master TSRMLS_DC) { enum_func_status ret = FAIL; MYSQLND_CONN_DATA * connection = element->conn; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, connection); MS_DECLARE_AND_LOAD_CONN_DATA(proxy_conn_data, (*conn_data)->proxy_conn); DBG_ENTER("mysqlnd_ms_lazy_connect"); /* We may get called by the load balancing filters (random, roundrobin) while they setup a new connection to be used for running a transaction. If transaction stickiness is enabled, the filters will have set all flags to block connection switches and try to use the last used connection (the one which we are to open yet) when setting up the connection in execute_init_commands(). To prevent this recursion we have to skip MS for the connect itself. */ (*conn_data)->skip_ms_calls = TRUE; if ((*proxy_conn_data)->server_charset && !CONN_GET_OPTION(connection, charset_name) && FAIL == (ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_client_option)(connection, MYSQL_SET_CHARSET_NAME, (*proxy_conn_data)->server_charset->name TSRMLS_CC))) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(connection), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't force charset to '%s'", (*proxy_conn_data)->server_charset->name); } else { ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(connect)(connection, element->host, element->user, element->passwd, element->passwd_len, element->db, element->db_len, element->port, element->socket, element->connect_flags TSRMLS_CC); } (*conn_data)->skip_ms_calls = FALSE; if (PASS == ret) { DBG_INF("Connected"); MYSQLND_MS_INC_STATISTIC(master? MS_STAT_LAZY_CONN_MASTER_SUCCESS:MS_STAT_LAZY_CONN_SLAVE_SUCCESS); #ifndef MYSQLND_HAS_INJECTION_FEATURE /* TODO: without this the global trx id injection logic will fail on recently opened lazy connections */ if (conn_data && *conn_data) { (*conn_data)->initialized = TRUE; } #endif } else { MYSQLND_MS_INC_STATISTIC(master? MS_STAT_LAZY_CONN_MASTER_FAILURE:MS_STAT_LAZY_CONN_SLAVE_FAILURE); } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_connect_init_global_trx */ static void mysqlnd_ms_init_connection_global_trx(struct st_mysqlnd_ms_global_trx_injection * new_global_trx, struct st_mysqlnd_ms_global_trx_injection * orig_global_trx, zend_bool is_master, zend_bool persistent TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_init_connection_global_trx"); if (new_global_trx == orig_global_trx) { orig_global_trx->is_master = is_master; DBG_VOID_RETURN; } if (TRUE == is_master) { new_global_trx->on_commit_len = orig_global_trx->on_commit_len; new_global_trx->on_commit = (orig_global_trx->on_commit) ? mnd_pestrndup(orig_global_trx->on_commit, orig_global_trx->on_commit_len, persistent) : NULL; } else { new_global_trx->on_commit_len = 0; new_global_trx->on_commit = NULL; } new_global_trx->fetch_last_gtid_len = orig_global_trx->fetch_last_gtid_len; new_global_trx->fetch_last_gtid = (orig_global_trx->fetch_last_gtid) ? mnd_pestrndup(orig_global_trx->fetch_last_gtid, orig_global_trx->fetch_last_gtid_len, persistent) : NULL; new_global_trx->check_for_gtid_len = orig_global_trx->check_for_gtid_len; new_global_trx->check_for_gtid = (orig_global_trx->check_for_gtid) ? mnd_pestrndup(orig_global_trx->check_for_gtid, orig_global_trx->check_for_gtid_len, persistent) : NULL; new_global_trx->is_master = is_master; new_global_trx->report_error = orig_global_trx->report_error; new_global_trx->wait_for_gtid_timeout = orig_global_trx->wait_for_gtid_timeout; DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_connect_to_host_aux */ static enum_func_status mysqlnd_ms_connect_to_host_aux(MYSQLND_CONN_DATA * proxy_conn, MYSQLND_CONN_DATA * conn, const char * name_from_config, zend_bool is_master, const char * host, zend_llist * conn_list, struct st_mysqlnd_ms_conn_credentials * cred, struct st_mysqlnd_ms_global_trx_injection * global_trx, zend_bool lazy_connections, zend_bool persistent TSRMLS_DC) { enum_func_status ret = FAIL; MS_DECLARE_AND_LOAD_CONN_DATA(proxy_conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms_connect_to_host_aux"); DBG_INF_FMT("conn:%p host:%s port:%d socket:%s", conn, host, cred->port, cred->socket); if (lazy_connections) { DBG_INF("Lazy connection"); ret = PASS; } else { if ((*proxy_conn_data)->server_charset && FAIL == (ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_client_option)(conn, MYSQL_SET_CHARSET_NAME, (*proxy_conn_data)->server_charset->name TSRMLS_CC))) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't force charset to '%s'", (*proxy_conn_data)->server_charset->name); } else { ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(connect)(conn, host, cred->user, cred->passwd, cred->passwd_len, cred->db, cred->db_len, cred->port, cred->socket, cred->mysql_flags TSRMLS_CC); } if (PASS == ret) { DBG_INF_FMT("Connection "MYSQLND_LLU_SPEC" established", conn->thread_id); } } if (ret == PASS) { MYSQLND_MS_LIST_DATA * new_element = mnd_pecalloc(1, sizeof(MYSQLND_MS_LIST_DATA), persistent); new_element->name_from_config = mnd_pestrdup(name_from_config? name_from_config:"", conn->persistent); #if MYSQLND_VERSION_ID >= 50010 new_element->conn = conn->m->get_reference(conn TSRMLS_CC); #else new_element->conn = conn; #endif new_element->host = host? mnd_pestrdup(host, persistent) : NULL; new_element->persistent = persistent; new_element->port = cred->port; new_element->user = cred->user? mnd_pestrdup(cred->user, conn->persistent) : NULL; new_element->passwd_len = cred->passwd_len; new_element->passwd = cred->passwd? mnd_pestrndup(cred->passwd, cred->passwd_len, conn->persistent) : NULL; new_element->db_len = cred->db_len; new_element->db = cred->db? mnd_pestrndup(cred->db, cred->db_len, conn->persistent) : NULL; new_element->connect_flags = cred->mysql_flags; new_element->socket = cred->socket? mnd_pestrdup(cred->socket, conn->persistent) : NULL; new_element->emulated_scheme_len = mysqlnd_ms_get_scheme_from_list_data(new_element, &new_element->emulated_scheme, persistent TSRMLS_CC); zend_llist_add_element(conn_list, &new_element); { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); /* initialize for every connection, even for slaves and secondary masters */ if (proxy_conn != conn) { /* otherwise we will overwrite ourselves */ *conn_data = mnd_pecalloc(1, sizeof(MYSQLND_MS_CONN_DATA), conn->persistent); } (*conn_data)->skip_ms_calls = FALSE; (*conn_data)->proxy_conn = proxy_conn; #ifndef MYSQLND_HAS_INJECTION_FEATURE mysqlnd_ms_init_connection_global_trx(&(*conn_data)->global_trx, global_trx, is_master, conn->persistent TSRMLS_CC); #endif } } DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL"); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_connect_to_host */ static enum_func_status mysqlnd_ms_connect_to_host(MYSQLND_CONN_DATA * proxy_conn, MYSQLND_CONN_DATA * conn, zend_llist * conn_list, zend_bool is_master, struct st_mysqlnd_ms_conn_credentials * master_credentials, struct st_mysqlnd_ms_global_trx_injection * master_global_trx, struct st_mysqlnd_ms_config_json_entry * main_section, const char * const subsection_name, size_t subsection_name_len, zend_bool lazy_connections, zend_bool persistent, zend_bool process_all_list_values, unsigned int success_stat, unsigned int fail_stat, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { zend_bool value_exists = FALSE, is_list_value = FALSE; struct st_mysqlnd_ms_config_json_entry * subsection = NULL, * parent_subsection = NULL; zend_bool recursive = FALSE; unsigned int i = 0; unsigned int failures = 0; DBG_ENTER("mysqlnd_ms_connect_to_host"); DBG_INF_FMT("conn:%p", conn); if (TRUE == mysqlnd_ms_config_json_sub_section_exists(main_section, subsection_name, subsection_name_len, 0 TSRMLS_CC)) { subsection = parent_subsection = mysqlnd_ms_config_json_sub_section(main_section, subsection_name, subsection_name_len, &value_exists TSRMLS_CC); recursive = (TRUE == mysqlnd_ms_config_json_section_is_list(subsection TSRMLS_CC) && TRUE == mysqlnd_ms_config_json_section_is_object_list(subsection TSRMLS_CC)); } else { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Cannot find %s section in config", subsection_name); } do { struct st_mysqlnd_ms_conn_credentials cred = *master_credentials; char * socket_to_use = NULL; char * user_to_use = NULL; char * pass_to_use = NULL; char * db_to_use = NULL; char * host = NULL; int64_t port, flags; char * current_subsection_name = NULL; size_t current_subsection_name_len = 0; if (recursive) { subsection = mysqlnd_ms_config_json_next_sub_section(parent_subsection, ¤t_subsection_name, ¤t_subsection_name_len, NULL TSRMLS_CC); } if (!subsection) { break; } flags = mysqlnd_ms_config_json_int_from_section(subsection, SECT_CONNECT_FLAGS_NAME, sizeof(SECT_CONNECT_FLAGS_NAME)-1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_CONNECT_FLAGS_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (value_exists) { if (flags < 0) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_CONNECT_FLAGS_NAME" '%i' . Stopping", flags); failures++; } else { cred.mysql_flags = flags; } } port = mysqlnd_ms_config_json_int_from_section(subsection, SECT_PORT_NAME, sizeof(SECT_PORT_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_PORT_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (value_exists) { if (port < 0 || port > 65535) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_PORT_NAME" '%i' . Stopping", port); failures++; } else { cred.port = port; } } socket_to_use = mysqlnd_ms_config_json_string_from_section(subsection, SECT_SOCKET_NAME, sizeof(SECT_SOCKET_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_SOCKET_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (value_exists) { cred.socket = socket_to_use; } user_to_use = mysqlnd_ms_config_json_string_from_section(subsection, SECT_USER_NAME, sizeof(SECT_USER_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_USER_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (value_exists) { cred.user = user_to_use; } pass_to_use = mysqlnd_ms_config_json_string_from_section(subsection, SECT_PASS_NAME, sizeof(SECT_PASS_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_PASS_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (value_exists) { cred.passwd = pass_to_use; cred.passwd_len = strlen(cred.passwd); } db_to_use = mysqlnd_ms_config_json_string_from_section(subsection, SECT_DB_NAME, sizeof(SECT_DB_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_DB_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (value_exists) { cred.db = db_to_use; cred.db_len = strlen(cred.db); } host = mysqlnd_ms_config_json_string_from_section(subsection, SECT_HOST_NAME, sizeof(SECT_HOST_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (is_list_value) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value for "SECT_HOST_NAME". Cannot be a list/hash' . Stopping"); failures++; } else if (FALSE == value_exists) { DBG_ERR_FMT("Cannot find ["SECT_HOST_NAME"] in [%s] section in config", subsection_name); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, MYSQLND_MS_ERROR_PREFIX " Cannot find ["SECT_HOST_NAME"] in [%s] section in config", subsection_name); SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, MYSQLND_MS_ERROR_PREFIX " Cannot find ["SECT_HOST_NAME"] in section in config"); failures++; } else { #if MYSQLND_VERSION_ID >= 50010 MYSQLND * tmp_conn_handle = NULL; MYSQLND_CONN_DATA * tmp_conn = NULL; if (conn && i==0) { tmp_conn = conn; } else { tmp_conn_handle = mysqlnd_init(persistent); if (tmp_conn_handle) { tmp_conn = MS_GET_CONN_DATA_FROM_CONN(tmp_conn_handle); } } #else MYSQLND * tmp_conn = (conn && i==0)? conn->m->get_reference(conn TSRMLS_CC) : mysqlnd_init(persistent); #endif if (tmp_conn) { enum_func_status status = mysqlnd_ms_connect_to_host_aux(proxy_conn, tmp_conn, current_subsection_name, is_master, host, conn_list, &cred, master_global_trx, lazy_connections, persistent TSRMLS_CC); if (status != PASS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Cannot connect to %s", host); (*error_info) = MYSQLND_MS_ERROR_INFO(tmp_conn); failures++; /* let's free the handle, if there is one. The underlying object will stay alive */ MYSQLND_MS_INC_STATISTIC(fail_stat); #if MYSQLND_VERSION_ID < 50010 if (tmp_conn != conn) { tmp_conn->m->dtor(tmp_conn TSRMLS_CC); } else { conn->m->free_reference(conn TSRMLS_CC); } #endif } else { if (!lazy_connections) { MYSQLND_MS_INC_STATISTIC(success_stat); } } #if MYSQLND_VERSION_ID >= 50010 if (tmp_conn_handle) { tmp_conn_handle->m->dtor(tmp_conn_handle TSRMLS_CC); } #endif } else { failures++; /* Handle OOM!! */ MYSQLND_MS_INC_STATISTIC(fail_stat); } } i++; /* to pass only the first conn handle */ if (socket_to_use) { mnd_efree(socket_to_use); } if (user_to_use) { mnd_efree(user_to_use); } if (pass_to_use) { mnd_efree(pass_to_use); } if (db_to_use) { mnd_efree(db_to_use); } if (host) { mnd_efree(host); host = NULL; } } while (TRUE == process_all_list_values && TRUE == recursive /* && failures == 0 */ ); DBG_RETURN(failures==0 ? PASS:FAIL); } /* }}} */ /* {{{ mysqlnd_ms_init_trx_to_null */ static void mysqlnd_ms_init_trx_to_null(struct st_mysqlnd_ms_global_trx_injection * trx TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_init_trx_to_null"); trx->on_commit = NULL; trx->on_commit_len = (size_t)0; trx->fetch_last_gtid = NULL; trx->fetch_last_gtid_len = (size_t)0; trx->check_for_gtid = NULL; trx->check_for_gtid_len = (size_t)0; trx->wait_for_gtid_timeout = 0; trx->is_master = FALSE; trx->report_error = TRUE; DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_load_trx_config */ static void mysqlnd_ms_load_trx_config(struct st_mysqlnd_ms_config_json_entry * main_section, struct st_mysqlnd_ms_global_trx_injection * trx, MYSQLND_CONN_DATA *conn, zend_bool persistent TSRMLS_DC) { zend_bool entry_exists; zend_bool entry_is_list; struct st_mysqlnd_ms_config_json_entry * g_trx_section; DBG_ENTER("mysqlnd_ms_load_trx_config"); g_trx_section = mysqlnd_ms_config_json_sub_section(main_section, SECT_G_TRX_NAME, sizeof(SECT_G_TRX_NAME) - 1, &entry_exists TSRMLS_CC); if (entry_exists && g_trx_section) { char * json_value = NULL; size_t json_value_len; int64_t json_int; json_value = mysqlnd_ms_config_json_string_from_section(g_trx_section, SECT_G_TRX_ON_COMMIT, sizeof(SECT_G_TRX_ON_COMMIT) - 1, 0, &entry_exists, &entry_is_list TSRMLS_CC); if (entry_exists && json_value) { if (entry_is_list) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " '%s' from '%s' must be a string", SECT_G_TRX_ON_COMMIT, SECT_G_TRX_NAME); } else { json_value_len = strlen(json_value); trx->on_commit = mnd_pestrndup(json_value, json_value_len, persistent); trx->on_commit_len = strlen(json_value); } mnd_efree(json_value); } json_value = mysqlnd_ms_config_json_string_from_section(g_trx_section, SECT_G_TRX_FETCH_LAST_GTID, sizeof(SECT_G_TRX_FETCH_LAST_GTID) - 1, 0, &entry_exists, &entry_is_list TSRMLS_CC); if (entry_exists && json_value) { if (entry_is_list) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " '%s' from '%s' must be a string", SECT_G_TRX_FETCH_LAST_GTID, SECT_G_TRX_NAME); } else { json_value_len = strlen(json_value); trx->fetch_last_gtid = mnd_pestrndup(json_value, json_value_len, persistent); trx->fetch_last_gtid_len = strlen(json_value); } mnd_efree(json_value); } json_value = mysqlnd_ms_config_json_string_from_section(g_trx_section, SECT_G_TRX_CHECK_FOR_GTID, sizeof(SECT_G_TRX_CHECK_FOR_GTID) - 1, 0, &entry_exists, &entry_is_list TSRMLS_CC); if (entry_exists && json_value) { if (entry_is_list) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " '%s' from '%s' must be a string", SECT_G_TRX_CHECK_FOR_GTID, SECT_G_TRX_NAME); } else { json_value_len = strlen(json_value); trx->check_for_gtid = mnd_pestrndup(json_value, json_value_len, persistent); trx->check_for_gtid_len = strlen(json_value); } mnd_efree(json_value); } json_value = mysqlnd_ms_config_json_string_from_section(g_trx_section, SECT_G_TRX_REPORT_ERROR, sizeof(SECT_G_TRX_REPORT_ERROR) - 1, 0, &entry_exists, &entry_is_list TSRMLS_CC); if (entry_exists && json_value) { trx->report_error = !mysqlnd_ms_config_json_string_is_bool_false(json_value); mnd_efree(json_value); } json_int = mysqlnd_ms_config_json_int_from_section(g_trx_section, SECT_G_TRX_WAIT_FOR_GTID_TIMEOUT, sizeof(SECT_G_TRX_WAIT_FOR_GTID_TIMEOUT) - 1, 0, &entry_exists, &entry_is_list TSRMLS_CC); if (entry_exists) { if (json_int < 0) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " '%s' from '%s' must be greater or equal than zero", SECT_G_TRX_WAIT_FOR_GTID_TIMEOUT, SECT_G_TRX_NAME); } else if (json_int > 65535) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " '%s' from '%s' must be less than 65536", SECT_G_TRX_WAIT_FOR_GTID_TIMEOUT, SECT_G_TRX_NAME); } else { trx->wait_for_gtid_timeout = (unsigned int)json_int; } } } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_connect_load_charset_aux */ static enum_func_status mysqlnd_ms_connect_load_charset_aux(struct st_mysqlnd_ms_config_json_entry * the_section, const char * const setting_name, const size_t setting_name_len, const MYSQLND_CHARSET ** out_storage, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { enum_func_status ret = PASS; char * charset_name; zend_bool value_exists = FALSE; const MYSQLND_CHARSET * config_charset = NULL; DBG_ENTER("mysqlnd_ms_connect_load_charset_aux"); charset_name = mysqlnd_ms_config_json_string_from_section(the_section, setting_name, setting_name_len, 0, &value_exists, NULL TSRMLS_CC); if (charset_name) { DBG_INF_FMT("%s=%s", setting_name, charset_name); config_charset = mysqlnd_find_charset_name(charset_name); if (!config_charset) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Erroneous %s [%s]", setting_name, charset_name); ret = FAIL; } mnd_efree(charset_name); charset_name = NULL; } *out_storage = config_charset; DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_connect_load_charset */ static enum_func_status mysqlnd_ms_connect_load_charset(MYSQLND_MS_CONN_DATA ** conn_data, struct st_mysqlnd_ms_config_json_entry * the_section, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_ms_connect_load_charset"); ret = mysqlnd_ms_connect_load_charset_aux(the_section, SECT_SERVER_CHARSET_NAME, sizeof(SECT_SERVER_CHARSET_NAME) - 1, &(*conn_data)->server_charset, error_info TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::connect */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, connect)(MYSQLND_CONN_DATA * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket, unsigned int mysql_flags TSRMLS_DC) { enum_func_status ret = FAIL; MYSQLND_MS_CONN_DATA ** conn_data; size_t host_len = host? strlen(host) : 0; zend_bool section_found; zend_bool hotloading = MYSLQND_MS_HOTLOADING; DBG_ENTER("mysqlnd_ms::connect"); if (hotloading) { MYSQLND_MS_CONFIG_JSON_LOCK(mysqlnd_ms_json_config); } section_found = mysqlnd_ms_config_json_section_exists(mysqlnd_ms_json_config, host, host_len, 0, hotloading? FALSE:TRUE TSRMLS_CC); if (MYSQLND_MS_G(force_config_usage)) { if (MYSQLND_MS_G(config_startup_error)) { /* TODO: May bark before a hot loading (disabled) attempt is made. Same should be true about force config usage */ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, MYSQLND_MS_ERROR_PREFIX " %s", MYSQLND_MS_G(config_startup_error)); } if (FALSE == section_found) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Exclusive usage of configuration enforced but did not find the correct INI file section (%s)", host); if (hotloading) { MYSQLND_MS_CONFIG_JSON_UNLOCK(mysqlnd_ms_json_config); } SET_CLIENT_ERROR(MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, MYSQLND_MS_ERROR_PREFIX " Exclusive usage of configuration enforced but did not find the correct INI file section"); DBG_RETURN(FAIL); } } else { if (MYSQLND_MS_G(config_startup_error)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " %s", MYSQLND_MS_G(config_startup_error)); } } mysqlnd_ms_conn_free_plugin_data(conn TSRMLS_CC); if (FALSE == section_found) { DBG_INF("section not found"); ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(connect)(conn, host, user, passwd, passwd_len, db, db_len, port, socket, mysql_flags TSRMLS_CC); } else { struct st_mysqlnd_ms_config_json_entry * the_section; MS_LOAD_CONN_DATA(conn_data, conn); *conn_data = mnd_pecalloc(1, sizeof(MYSQLND_MS_CONN_DATA), conn->persistent); zend_llist_init(&(*conn_data)->master_connections, sizeof(MYSQLND_MS_LIST_DATA *), (llist_dtor_func_t) mysqlnd_ms_conn_list_dtor, conn->persistent); zend_llist_init(&(*conn_data)->slave_connections, sizeof(MYSQLND_MS_LIST_DATA *), (llist_dtor_func_t) mysqlnd_ms_conn_list_dtor, conn->persistent); (*conn_data)->cred.user = user? mnd_pestrdup(user, conn->persistent) : NULL; (*conn_data)->cred.passwd_len = passwd_len; (*conn_data)->cred.passwd = passwd? mnd_pestrndup(passwd, passwd_len, conn->persistent) : NULL; (*conn_data)->cred.db_len = db_len; (*conn_data)->cred.db = db? mnd_pestrndup(db, db_len, conn->persistent) : NULL; (*conn_data)->cred.port = port; (*conn_data)->cred.socket = socket? mnd_pestrdup(socket, conn->persistent) : NULL; (*conn_data)->cred.mysql_flags = mysql_flags; #ifndef MYSQLND_HAS_INJECTION_FEATURE mysqlnd_ms_init_trx_to_null(&(*conn_data)->global_trx TSRMLS_CC); #endif (*conn_data)->initialized = TRUE; if (!hotloading) { MYSQLND_MS_CONFIG_JSON_LOCK(mysqlnd_ms_json_config); } do { zend_bool value_exists = FALSE, use_lazy_connections = TRUE; /* create master connection */ the_section = mysqlnd_ms_config_json_section(mysqlnd_ms_json_config, host, host_len, &value_exists TSRMLS_CC); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(conn)); #ifndef MYSQLND_HAS_INJECTION_FEATURE mysqlnd_ms_load_trx_config(the_section, &(*conn_data)->global_trx, conn, conn->persistent TSRMLS_CC); #endif { char * lazy_connections = mysqlnd_ms_config_json_string_from_section(the_section, LAZY_NAME, sizeof(LAZY_NAME) - 1, 0, &use_lazy_connections, NULL TSRMLS_CC); /* ignore if lazy_connections ini entry exists or not */ use_lazy_connections = TRUE; if (lazy_connections) { /* lazy_connections ini entry exists, disabled? */ use_lazy_connections = !mysqlnd_ms_config_json_string_is_bool_false(lazy_connections); mnd_efree(lazy_connections); lazy_connections = NULL; } } if (FAIL == (ret = mysqlnd_ms_connect_load_charset(conn_data, the_section, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC))) { break; } { const char * const sects_to_check[] = {MASTER_NAME, SLAVE_NAME}; unsigned int i = 0; for (; i < sizeof(sects_to_check) / sizeof(sects_to_check[0]); ++i) { size_t sect_len = strlen(sects_to_check[i]); if (FALSE == mysqlnd_ms_config_json_sub_section_exists(the_section, sects_to_check[i], sect_len, 0 TSRMLS_CC)) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Section [%s] doesn't exist for host [%s]", sects_to_check[i], host); } } } DBG_INF("-------------------- MASTER CONNECTIONS ------------------"); ret = mysqlnd_ms_connect_to_host(conn, conn, &(*conn_data)->master_connections, TRUE, &(*conn_data)->cred, &(*conn_data)->global_trx, the_section, MASTER_NAME, sizeof(MASTER_NAME) - 1, use_lazy_connections, conn->persistent, MYSQLND_MS_G(multi_master) /* multimaster*/, MS_STAT_NON_LAZY_CONN_MASTER_SUCCESS, MS_STAT_NON_LAZY_CONN_MASTER_FAILURE, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); if (FAIL == ret || (MYSQLND_MS_ERROR_INFO(conn).error_no)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Error while connecting to the master(s)"); break; } SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(conn)); DBG_INF("-------------------- SLAVE CONNECTIONS ------------------"); ret = mysqlnd_ms_connect_to_host(conn, NULL, &(*conn_data)->slave_connections, FALSE, &(*conn_data)->cred, &(*conn_data)->global_trx, the_section, SLAVE_NAME, sizeof(SLAVE_NAME) - 1, use_lazy_connections, conn->persistent, TRUE /* multi*/, MS_STAT_NON_LAZY_CONN_SLAVE_SUCCESS, MS_STAT_NON_LAZY_CONN_SLAVE_FAILURE, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); if (FAIL == ret || (MYSQLND_MS_ERROR_INFO(conn).error_no)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Error while connecting to the slaves"); break; } DBG_INF_FMT("master_list=%p count=%d", &(*conn_data)->master_connections, zend_llist_count(&(*conn_data)->master_connections)); DBG_INF_FMT("slave_list=%p count=%d", &(*conn_data)->slave_connections, zend_llist_count(&(*conn_data)->slave_connections)); (*conn_data)->stgy.filters = mysqlnd_ms_load_section_filters(the_section, &MYSQLND_MS_ERROR_INFO(conn), &(*conn_data)->master_connections, &(*conn_data)->slave_connections, TRUE /* load all config persistently */ TSRMLS_CC); if (!(*conn_data)->stgy.filters) { ret = FAIL; break; } mysqlnd_ms_lb_strategy_setup(&(*conn_data)->stgy, the_section, &MYSQLND_MS_ERROR_INFO(conn), conn->persistent TSRMLS_CC); } while (0); mysqlnd_ms_config_json_reset_section(the_section, TRUE TSRMLS_CC); if (!hotloading) { MYSQLND_MS_CONFIG_JSON_UNLOCK(mysqlnd_ms_json_config); } if (ret == PASS) { (*conn_data)->connect_host = host? mnd_pestrdup(host, conn->persistent) : NULL; } } if (hotloading) { MYSQLND_MS_CONFIG_JSON_UNLOCK(mysqlnd_ms_json_config); } DBG_INF_FMT("conn=%llu old_refcount=%u", conn->thread_id, conn->refcount); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_do_send_query(MYSQLND_CONN_DATA * conn, const char * query, size_t query_len, zend_bool pick_server TSRMLS_DC) */ static enum_func_status mysqlnd_ms_do_send_query(MYSQLND_CONN_DATA * conn, const char * query, size_t query_len, zend_bool pick_server TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); enum_func_status ret = PASS; DBG_ENTER("mysqlnd_ms::do_send_query"); if (CONN_DATA_NOT_SET(conn_data)) { } else if (pick_server) { DBG_INF("Must be async query, blocking and failing"); if (conn) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Asynchronous queries are not supported"); DBG_RETURN(FAIL); } } ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(send_query)(conn, query, query_len TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ MYSQLND_METHOD(mysqlnd_ms, send_query) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, send_query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC) { return mysqlnd_ms_do_send_query(conn, query, query_len, TRUE TSRMLS_CC); } /* }}} */ /* {{{ MYSQLND_METHOD(mysqlnd_ms, query) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int q_len TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); MYSQLND_CONN_DATA * connection; enum_func_status ret = FAIL; zend_bool free_query = FALSE; size_t query_len = q_len; #ifdef ALL_SERVER_DISPATCH zend_bool use_all = 0; #endif DBG_ENTER("mysqlnd_ms::query"); DBG_INF_FMT("query=%s", query); if (CONN_DATA_NOT_SET(conn_data)) { ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(query)(conn, query, q_len TSRMLS_CC); DBG_RETURN(ret); } if ((*conn_data)->skip_ms_calls) { ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(query)(conn, query, q_len TSRMLS_CC); DBG_RETURN(ret); } connection = mysqlnd_ms_pick_server_ex(conn, (char**)&query, &query_len, &free_query TSRMLS_CC); DBG_INF_FMT("Connection %p error_no=%d", connection, connection? (MYSQLND_MS_ERROR_INFO(connection).error_no) : -1); /* Beware : error_no is set to 0 in original->query. This, this might be a problem, as we dump a connection from usage till the end of the script. Lazy connections can generate connection failures, thus we need to check for them. If we skip these checks we will get 2014 from original->query. */ if (!connection || (MYSQLND_MS_ERROR_INFO(connection).error_no)) { if (TRUE == free_query) { efree((void *)query); } DBG_RETURN(ret); } #ifdef ALL_SERVER_DISPATCH if (use_all) { MYSQLND_MS_CONN_DATA ** conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(conn, mysqlnd_ms_plugin_id); zend_llist * master_connections = (conn_data && *conn_data)? &(*conn_data)->master_connections : NULL; zend_llist * slave_connections = (conn_data && *conn_data)? &(*conn_data)->slave_connections : NULL; mysqlnd_ms_query_all(conn, query, query_len, master_connections, slave_connections TSRMLS_CC); } #endif DBG_INF_FMT("conn="MYSQLND_LLU_SPEC" query=%s", connection->thread_id, query); /* TODO: This is wrong - we should do injection *after* successful query. Doing it here - for now - to avoid trouble with result sets. How expensive is the load? */ MS_LOAD_CONN_DATA(conn_data, connection); #ifndef MYSQLND_HAS_INJECTION_FEATURE if (CONN_DATA_TRX_SET(conn_data) && CONN_DATA_TRY_TRX_INJECTION(conn_data, connection)) { if (FALSE == (*conn_data)->stgy.in_transaction) { /* autocommit mode */ MS_TRX_INJECT(ret, connection, conn_data); MYSQLND_MS_INC_STATISTIC((PASS == ret) ? MS_STAT_GTID_AUTOCOMMIT_SUCCESS : MS_STAT_GTID_AUTOCOMMIT_FAILURE); if (FAIL == ret) { if (TRUE == (*conn_data)->global_trx.report_error) { if (TRUE == free_query) { efree((void *)query); } DBG_RETURN(ret); } SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(connection)); } } } #endif if ((PASS == (ret = mysqlnd_ms_do_send_query(connection, query, query_len, FALSE TSRMLS_CC))) && (PASS == (ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(reap_query)(connection TSRMLS_CC)))) { if (connection->last_query_type == QUERY_UPSERT && (MYSQLND_MS_UPSERT_STATUS(connection).affected_rows)) { MYSQLND_INC_CONN_STATISTIC_W_VALUE(connection->stats, STAT_ROWS_AFFECTED_NORMAL, MYSQLND_MS_UPSERT_STATUS(connection).affected_rows); } } if (TRUE == free_query) { efree((void *)query); } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::use_result */ static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_ms, use_result)(MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MYSQLND_RES * result; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::use_result"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); result = MS_CALL_ORIGINAL_CONN_DATA_METHOD(use_result)(conn TSRMLS_CC); DBG_RETURN(result); } /* }}} */ /* {{{ mysqlnd_ms::store_result */ static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_ms, store_result)(MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MYSQLND_RES * result; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::store_result"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); result = MS_CALL_ORIGINAL_CONN_DATA_METHOD(store_result)(conn TSRMLS_CC); DBG_RETURN(result); } /* }}} */ /* {{{ mysqlnd_ms_conn_free_plugin_data */ static void mysqlnd_ms_conn_free_plugin_data(MYSQLND_CONN_DATA * conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(data_pp, conn); DBG_ENTER("mysqlnd_ms_conn_free_plugin_data"); DBG_INF_FMT("data_pp=%p", data_pp); if (data_pp && *data_pp) { if ((*data_pp)->connect_host) { mnd_pefree((*data_pp)->connect_host, conn->persistent); (*data_pp)->connect_host = NULL; } if ((*data_pp)->cred.user) { mnd_pefree((*data_pp)->cred.user, conn->persistent); (*data_pp)->cred.user = NULL; } if ((*data_pp)->cred.passwd) { mnd_pefree((*data_pp)->cred.passwd, conn->persistent); (*data_pp)->cred.passwd = NULL; } (*data_pp)->cred.passwd_len = 0; if ((*data_pp)->cred.db) { mnd_pefree((*data_pp)->cred.db, conn->persistent); (*data_pp)->cred.db = NULL; } (*data_pp)->cred.db_len = 0; if ((*data_pp)->cred.socket) { mnd_pefree((*data_pp)->cred.socket, conn->persistent); (*data_pp)->cred.socket = NULL; } (*data_pp)->cred.port = 0; (*data_pp)->cred.mysql_flags = 0; #ifndef MYSQLND_HAS_INJECTION_FEATURE if ((*data_pp)->global_trx.on_commit) { mnd_pefree((*data_pp)->global_trx.on_commit, conn->persistent); (*data_pp)->global_trx.on_commit = NULL; (*data_pp)->global_trx.on_commit_len = 0; } if ((*data_pp)->global_trx.fetch_last_gtid) { mnd_pefree((*data_pp)->global_trx.fetch_last_gtid, conn->persistent); (*data_pp)->global_trx.fetch_last_gtid = NULL; (*data_pp)->global_trx.fetch_last_gtid_len = (size_t)0; } if ((*data_pp)->global_trx.check_for_gtid) { mnd_pefree((*data_pp)->global_trx.check_for_gtid, conn->persistent); (*data_pp)->global_trx.check_for_gtid = NULL; (*data_pp)->global_trx.check_for_gtid_len = (size_t)0; } #endif DBG_INF_FMT("cleaning the llists"); zend_llist_clean(&(*data_pp)->master_connections); zend_llist_clean(&(*data_pp)->slave_connections); DBG_INF_FMT("cleaning the section filters"); if ((*data_pp)->stgy.filters) { DBG_INF_FMT("%d loaded filters", zend_llist_count((*data_pp)->stgy.filters)); zend_llist_clean((*data_pp)->stgy.filters); mnd_pefree((*data_pp)->stgy.filters, TRUE /* all filters were loaded persistently */); (*data_pp)->stgy.filters = NULL; } if ((*data_pp)->stgy.failover_remember_failed) { zend_hash_destroy(&((*data_pp)->stgy.failed_hosts)); } if ((*data_pp)->stgy.trx_begin_name) { mnd_pefree((*data_pp)->stgy.trx_begin_name, conn->persistent); (*data_pp)->stgy.trx_begin_name = NULL; } mnd_pefree(*data_pp, conn->persistent); *data_pp = NULL; } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms::dtor */ static void MYSQLND_METHOD_PRIVATE(mysqlnd_ms, dtor)(MYSQLND_CONN_DATA * conn TSRMLS_DC) { DBG_ENTER("mysqlnd_ms::dtor"); mysqlnd_ms_conn_free_plugin_data(conn TSRMLS_CC); MS_CALL_ORIGINAL_CONN_DATA_METHOD(dtor)(conn TSRMLS_CC); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms::escape_string */ static ulong MYSQLND_METHOD(mysqlnd_ms, escape_string)(MYSQLND_CONN_DATA * const proxy_conn, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; ulong ret = 0; DBG_ENTER("mysqlnd_ms::escape_string"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); if (CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) != CONN_QUIT_SENT) { if (conn_data && *conn_data) { (*conn_data)->skip_ms_calls = TRUE; } ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(escape_string)(conn, newstr, escapestr, escapestr_len TSRMLS_CC); if (conn_data && *conn_data) { (*conn_data)->skip_ms_calls = FALSE; } } else if (CONN_GET_STATE(conn) == CONN_ALLOCED && ((*conn_data)->server_charset || CONN_GET_OPTION(conn, charset_name))) { const MYSQLND_CHARSET * orig_charset = conn->charset; conn->charset = (*conn_data)->server_charset; /* must not happen but put sentinels */ if (!(*conn_data)->server_charset && CONN_GET_OPTION(conn, charset_name)) { conn->charset = mysqlnd_find_charset_name(CONN_GET_OPTION(conn, charset_name)); } if (conn_data && *conn_data) { (*conn_data)->skip_ms_calls = TRUE; } ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(escape_string)(conn, newstr, escapestr, escapestr_len TSRMLS_CC); if (conn_data && *conn_data) { (*conn_data)->skip_ms_calls = FALSE; } conn->charset = orig_charset; } else { /* broken connection or no "server_charset" setting */ newstr[0] = '\0'; mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " string escaping doesn't work without established connection. Possible solution is to add " SECT_SERVER_CHARSET_NAME" to your configuration"); } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::change_user */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, change_user)(MYSQLND_CONN_DATA * const proxy_conn, const char *user, const char *passwd, const char *db, zend_bool silent #if PHP_VERSION_ID >= 50399 ,size_t passwd_len #endif TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::change_user"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, proxy_conn->thread_id); if (CONN_DATA_NOT_SET(conn_data)) { #if PHP_VERSION_ID >= 50399 DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(change_user)(proxy_conn, user, passwd, db, silent, passwd_len TSRMLS_CC)); #else DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(change_user)(proxy_conn, user, passwd, db, silent TSRMLS_CC)); #endif } else { MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { MS_DECLARE_AND_LOAD_CONN_DATA(el_conn_data, el->conn); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy connection */ if (el->user) { mnd_pefree(el->user, el->persistent); } el->user = user? mnd_pestrdup(user, el->persistent) : NULL; if (el->passwd) { mnd_pefree(el->passwd, el->persistent); } #if PHP_VERSION_ID >= 50399 el->passwd_len = passwd_len; #else el->passwd_len = strlen(passwd); #endif el->passwd = passwd? mnd_pestrndup(passwd, el->passwd_len, el->persistent) : NULL; if (el->db) { mnd_pefree(el->db, el->persistent); } el->db_len = strlen(db); el->db = db? mnd_pestrndup(db, el->db_len, el->persistent) : NULL; } else { if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(change_user)(el->conn, user, passwd, db, silent #if PHP_VERSION_ID >= 50399 ,passwd_len #endif TSRMLS_CC)) { ret = FAIL; } } if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::ping */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, ping)(MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { enum_func_status ret; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::ping"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(ping)(conn TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::kill */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, kill)(MYSQLND_CONN_DATA * proxy_conn, unsigned int pid TSRMLS_DC) { enum_func_status ret; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::kill"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(kill_connection)(conn, pid TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ #if 0 /* {{{ mysqlnd_ms::get_errors */ static zval * MYSQLND_METHOD(mysqlnd_ms, get_errors)(MYSQLND_CONN_DATA * const proxy_conn, const char * const db, unsigned int db_len TSRMLS_DC) { zval * ret = NULL; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::get_errors"); if (conn_data && *conn_data) { MYSQLND_MS_LIST_DATA * el; array_init(ret); BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { MS_DECLARE_AND_LOAD_CONN_DATA(el_conn_data, el->conn); zval * row = NULL; char * scheme; size_t scheme_len; if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { scheme = el->emulated_scheme; scheme_len = el->emulated_scheme_len; } else { scheme = el->conn->scheme; scheme_len = el->conn->scheme_len; } array_init(row); add_assoc_long_ex(row, "errno", sizeof("errno") - 1, MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_error_no)(el->conn TSRMLS_CC)); { const char * err = MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_error_str)(el->conn TSRMLS_CC); add_assoc_stringl_ex(row, "error", sizeof("error") - 1, (char*) err, strlen(err), 1 /*dup*/); } { const char * sqlstate = MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_sqlstate)(el->conn TSRMLS_CC); add_assoc_stringl_ex(row, "sqlstate", sizeof("sqlstate") - 1, (char*) sqlstate, strlen(sqlstate), 1 /*dup*/); } add_assoc_zval_ex(ret, scheme, scheme_len, row); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ #endif /* {{{ mysqlnd_ms::select_db */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, select_db)(MYSQLND_CONN_DATA * const proxy_conn, const char * const db, unsigned int db_len TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::select_db"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, proxy_conn->thread_id); if (CONN_DATA_NOT_SET(conn_data)) { DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(select_db)(proxy_conn, db, db_len TSRMLS_CC)); } else { MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { if (CONN_GET_STATE(el->conn) > CONN_ALLOCED && CONN_GET_STATE(el->conn) != CONN_QUIT_SENT) { MS_DECLARE_AND_LOAD_CONN_DATA(el_conn_data, el->conn); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(select_db)(el->conn, db, db_len TSRMLS_CC)) { ret = FAIL; } if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } else if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy connection */ if (el->db) { mnd_pefree(el->db, el->persistent); } el->db_len = db_len; el->db = db? mnd_pestrndup(db, db_len, el->persistent) : NULL; } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::set_charset */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, set_charset)(MYSQLND_CONN_DATA * const proxy_conn, const char * const csname TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::set_charset"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, proxy_conn->thread_id); if (CONN_DATA_NOT_SET(conn_data)) { DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_charset)(proxy_conn, csname TSRMLS_CC)); } else { const MYSQLND_CHARSET * new_charset = mysqlnd_find_charset_name(csname); MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { enum_mysqlnd_connection_state state = CONN_GET_STATE(el->conn); if (state != CONN_QUIT_SENT) { MS_DECLARE_AND_LOAD_CONN_DATA(el_conn_data, el->conn); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (state == CONN_ALLOCED) { ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_client_option)(el->conn, MYSQL_SET_CHARSET_NAME, csname TSRMLS_CC); if (PASS == ret) { (*el_conn_data)->server_charset = mysqlnd_find_charset_name(CONN_GET_OPTION(el->conn, charset_name)); if (!(*el_conn_data)->server_charset) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(el->conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " unknown to the connector charset '%s'. Please report to the developers", CONN_GET_OPTION(el->conn, charset_name)); } } } else if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_charset)(el->conn, csname TSRMLS_CC)) { ret = FAIL; } if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::set_server_option */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, set_server_option)(MYSQLND_CONN_DATA * const proxy_conn, enum_mysqlnd_server_option option TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::set_server_option"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, proxy_conn->thread_id); if (CONN_DATA_NOT_SET(conn_data)) { DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_server_option)(proxy_conn, option TSRMLS_CC)); } else { MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { if (CONN_GET_STATE(el->conn) > CONN_ALLOCED && CONN_GET_STATE(el->conn) != CONN_QUIT_SENT) { MS_DECLARE_AND_LOAD_CONN_DATA(el_conn_data, el->conn); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_server_option)(el->conn, option TSRMLS_CC)) { ret = FAIL; } if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::set_client_option */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, set_client_option)(MYSQLND_CONN_DATA * const proxy_conn, enum_mysqlnd_option option, const char * const value TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::set_server_option"); if (CONN_DATA_NOT_SET(conn_data)) { DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_client_option)(proxy_conn, option, value TSRMLS_CC)); } else { MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { MS_DECLARE_AND_LOAD_CONN_DATA(el_conn_data, el->conn); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_client_option)(el->conn, option, value TSRMLS_CC)) { ret = FAIL; } if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::next_result */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, next_result)(MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { enum_func_status ret; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::next_result"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(next_result)(conn TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::more_results */ static zend_bool MYSQLND_METHOD(mysqlnd_ms, more_results)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { zend_bool ret; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::more_results"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, conn->thread_id); ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(more_results)(conn TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::errno */ static unsigned int MYSQLND_METHOD(mysqlnd_ms, error_no)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return MYSQLND_MS_ERROR_INFO(conn).error_no; } /* }}} */ /* {{{ mysqlnd_ms::error */ static const char * MYSQLND_METHOD(mysqlnd_ms, error)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return MYSQLND_MS_ERROR_INFO(conn).error; } /* }}} */ /* {{{ mysqlnd_conn::sqlstate */ static const char * MYSQLND_METHOD(mysqlnd_ms, sqlstate)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return (MYSQLND_MS_ERROR_INFO(conn).sqlstate[0]) ? (MYSQLND_MS_ERROR_INFO(conn).sqlstate): MYSQLND_SQLSTATE_NULL; } /* }}} */ /* {{{ mysqlnd_ms::field_count */ static unsigned int MYSQLND_METHOD(mysqlnd_ms, field_count)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return conn->field_count; } /* }}} */ /* {{{ mysqlnd_conn::thread_id */ static uint64_t MYSQLND_METHOD(mysqlnd_ms, thread_id)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return conn->thread_id; } /* }}} */ /* {{{ mysqlnd_ms::insert_id */ static uint64_t MYSQLND_METHOD(mysqlnd_ms, insert_id)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return MYSQLND_MS_UPSERT_STATUS(conn).last_insert_id; } /* }}} */ /* {{{ mysqlnd_ms::affected_rows */ static uint64_t MYSQLND_METHOD(mysqlnd_ms, affected_rows)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return MYSQLND_MS_UPSERT_STATUS(conn).affected_rows; } /* }}} */ /* {{{ mysqlnd_ms::warning_count */ static unsigned int MYSQLND_METHOD(mysqlnd_ms, warning_count)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return MYSQLND_MS_UPSERT_STATUS(conn).warning_count; } /* }}} */ /* {{{ mysqlnd_ms::info */ static const char * MYSQLND_METHOD(mysqlnd_ms, info)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; return conn->last_message; } /* }}} */ #if MYSQLND_VERSION_ID >= 50009 /* {{{ MYSQLND_METHOD(mysqlnd_ms, set_autocommit) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, set_autocommit)(MYSQLND_CONN_DATA * proxy_conn, unsigned int mode TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::set_autocommit"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, proxy_conn->thread_id); if (CONN_DATA_NOT_SET(conn_data)) { DBG_INF("Using original"); ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_autocommit)(proxy_conn, mode TSRMLS_CC); DBG_RETURN(ret); } else { MYSQLND_MS_LIST_DATA * el; #ifndef MYSQLND_HAS_INJECTION_FEATURE if (((TRUE == (*conn_data)->stgy.in_transaction) && mode) && CONN_DATA_TRY_TRX_INJECTION(conn_data, proxy_conn)) { /* Implicit commit when autocommit(false) ..query().. autocommit(true). Must inject before second=current autocommit() call. */ MS_TRX_INJECT(ret, proxy_conn, conn_data); MYSQLND_MS_INC_STATISTIC((PASS == ret) ? MS_STAT_GTID_IMPLICIT_COMMIT_SUCCESS : MS_STAT_GTID_IMPLICIT_COMMIT_FAILURE); if (FAIL == ret) { if (TRUE == (*conn_data)->global_trx.report_error) { DBG_RETURN(ret); } ret = PASS; SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(proxy_conn)); } } #endif BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { if (CONN_GET_STATE(el->conn) != CONN_QUIT_SENT) { MYSQLND_MS_CONN_DATA ** el_conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(el->conn, mysqlnd_ms_plugin_id); if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = TRUE; } if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_client_option)(el->conn, MYSQL_INIT_COMMAND, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0" TSRMLS_CC); } else if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(set_autocommit)(el->conn, mode TSRMLS_CC)) { ret = FAIL; } if (el_conn_data && *el_conn_data) { (*el_conn_data)->skip_ms_calls = FALSE; } } } END_ITERATE_OVER_SERVER_LISTS; if (PASS == ret) { /* If toggling autocommit fails for any line, we do not touch the plugins transaction detection status. The user is supposed to handle the failed autocommit mode switching function call. */ BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { if (CONN_GET_STATE(el->conn) != CONN_QUIT_SENT) { MYSQLND_MS_CONN_DATA ** el_conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(el->conn, mysqlnd_ms_plugin_id); if (el_conn_data && *el_conn_data) { if (mode) { (*el_conn_data)->stgy.in_transaction = FALSE; (*el_conn_data)->stgy.trx_stop_switching = FALSE; (*el_conn_data)->stgy.trx_read_only = FALSE; (*el_conn_data)->stgy.trx_autocommit_off = FALSE; } else { (*el_conn_data)->stgy.in_transaction = TRUE; (*el_conn_data)->stgy.trx_autocommit_off = TRUE; } } } } END_ITERATE_OVER_SERVER_LISTS; } } MYSQLND_MS_INC_STATISTIC(mode? MS_STAT_TRX_AUTOCOMMIT_ON:MS_STAT_TRX_AUTOCOMMIT_OFF); DBG_INF_FMT("in_transaction = %d", (*conn_data)->stgy.in_transaction); DBG_INF_FMT("trx_stop_switching = %d", (*conn_data)->stgy.trx_stop_switching); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_tx_commit_or_rollback */ #if MYSQLND_VERSION_ID >= 50011 static enum_func_status mysqlnd_ms_tx_commit_or_rollback(MYSQLND_CONN_DATA * proxy_conn, zend_bool commit, const unsigned int flags, const char * const name TSRMLS_DC) #else static enum_func_status mysqlnd_ms_tx_commit_or_rollback(MYSQLND_CONN_DATA * proxy_conn, zend_bool commit TSRMLS_DC) #endif { MYSQLND_CONN_DATA * conn; MYSQLND_MS_CONN_DATA ** conn_data; MS_DECLARE_AND_LOAD_CONN_DATA(proxy_conn_data, proxy_conn); enum_func_status ret = PASS; DBG_ENTER("mysqlnd_ms_tx_commit_or_rollback"); if (proxy_conn_data && *proxy_conn_data && (*proxy_conn_data)->stgy.last_used_conn) { conn = (*proxy_conn_data)->stgy.last_used_conn; MS_LOAD_CONN_DATA(conn_data, conn); } else { conn = proxy_conn; conn_data = proxy_conn_data; } DBG_INF_FMT("conn="MYSQLND_LLU_SPEC, conn->thread_id); if (CONN_GET_STATE(conn) == CONN_ALLOCED && !CONN_DATA_NOT_SET(conn_data)) { /* TODO: what is this good for ? */ DBG_RETURN(PASS); } /* Must add query before committing ... */ #ifndef MYSQLND_HAS_INJECTION_FEATURE if ((conn_data && *conn_data && TRUE == commit) && ((TRUE == (*conn_data)->stgy.in_transaction)) && CONN_DATA_TRY_TRX_INJECTION(conn_data, conn)) { MS_TRX_INJECT(ret, conn, conn_data); MYSQLND_MS_INC_STATISTIC((PASS == ret) ? MS_STAT_GTID_COMMIT_SUCCESS : MS_STAT_GTID_COMMIT_FAILURE); if (FAIL == ret) { if (TRUE == (*conn_data)->global_trx.report_error) { DBG_RETURN(ret); } SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(conn)); } } #endif if (conn_data && *conn_data) { (*conn_data)->skip_ms_calls = TRUE; } /* TODO: the recursive rattle tail is terrible, we should optimize and call query() directly */ #if MYSQLND_VERSION_ID >= 50011 ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_commit_or_rollback)(conn, commit, flags, name TSRMLS_CC); #else ret = commit? MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_commit)(conn TSRMLS_CC) : MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_rollback)(conn TSRMLS_CC); #endif if (conn_data && *conn_data) { (*conn_data)->skip_ms_calls = FALSE; if (PASS == ret) { if (FALSE == (*conn_data)->stgy.trx_autocommit_off) { /* autocommit(true) -> in_trx = 0; begin() -> in_trx = 1; commit() or rollback() -> in_trx = 0; */ /* proxy conn stgy controls the filter */ (*proxy_conn_data)->stgy.in_transaction = FALSE; (*proxy_conn_data)->stgy.trx_stop_switching = FALSE; (*proxy_conn_data)->stgy.trx_read_only = FALSE; /* clean up actual line as well to be on the safe side */ (*conn_data)->stgy.in_transaction = FALSE; (*conn_data)->stgy.trx_stop_switching = FALSE; (*conn_data)->stgy.trx_read_only = FALSE; } else if ((*conn_data)->stgy.trx_autocommit_off && (*proxy_conn_data)->stgy.in_transaction) { /* autocommit(false); query()|begin() -> pick server; query() -> keep server; commit()|rollback/() -> keep server; query()|begin() --> pick new server */ (*proxy_conn_data)->stgy.trx_stop_switching = FALSE; (*conn_data)->stgy.trx_stop_switching = FALSE; } } } DBG_RETURN(ret); } /* }}} */ #if MYSQLND_VERSION_ID >= 50011 /* {{{ MYSQLND_METHOD(mysqlnd_ms, tx_commit_or_rollback) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, tx_commit_or_rollback)(MYSQLND_CONN_DATA * conn, const zend_bool commit, const unsigned int flags, const char * const name TSRMLS_DC) { enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_ms::tx_commit_or_rollback"); ret = mysqlnd_ms_tx_commit_or_rollback(conn, commit, flags, name TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ MYSQLND_METHOD(mysqlnd_ms, tx_begin) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, tx_begin)(MYSQLND_CONN_DATA * conn, const unsigned int mode, const char * const name TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_ms::tx_begin"); /* HACK KLUDGE The way MS has been designed an tx_begin(read_only_trx) don't go together. If a user starts a transaction using tx_begin() it is yet unknown where this transaction will be executed. This is even true if the sticky flag has been used because at best the sticky flag reduces the list of servers down to two for a typical setup: one master, one slave. tx_begin() hints us whether there will be a ready only transaction or not. Ideally, we keep a read only transaction on a MySQL Replication slave. It is likely the slave has been marked read only and performance is better on a slave. Also, its always great to use slaves whenever possible. Now, if read only and if there are slaves and if those slaves qualify for the execution of the transaction (e.g. their lag is within limits set), then we may end up on a slave. Otherwise we may end up on a master. We simply do not know at this point which connection will be choosen. Load balancing/filter chain is yet to come. Thus, we do not know yet on which server BEGIN shall be executed. As a solution for now, BEGIN is delayed until a connection has been picked. Once picked, we stay on the same server until the end of the transaction is recognized. Note that we set the request for BEGIN, the message to the LB filter, on the proxy connection. We also set in_transaction on the proxy connection. Whereas the actual BEGIN has to be send on another connection. The proxy connection stgy object is passed to the filters. When intercepting a COMMIT/ROLLBACK we have to send the command on the last used connection but reset in_transaction on the proxy connection. */ if (FALSE == CONN_DATA_NOT_SET(conn_data)) { #ifndef MYSQLND_HAS_INJECTION_FEATURE if ((TRUE == (*conn_data)->stgy.in_transaction) && (CONN_DATA_TRY_TRX_INJECTION(conn_data, conn))) { /* Implicit commit when begin() ..query().. begin(). Must inject before second=current begin() call. */ MS_TRX_INJECT(ret, conn, conn_data); MYSQLND_MS_INC_STATISTIC((PASS == ret) ? MS_STAT_GTID_IMPLICIT_COMMIT_SUCCESS : MS_STAT_GTID_IMPLICIT_COMMIT_FAILURE); if (FAIL == ret) { if (TRUE == (*conn_data)->global_trx.report_error) { DBG_RETURN(ret); } ret = PASS; SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(conn)); } } #endif if ((*conn_data)->stgy.trx_stickiness_strategy != TRX_STICKINESS_STRATEGY_DISABLED) { /* the true answer is delayed... unfortunately :-/ */ ret = PASS; /* reundant if autocommit(false) -> in_trx = 1 but does not harm */ (*conn_data)->stgy.in_transaction = TRUE; /* filter will set this after choosing an initial connection */ (*conn_data)->stgy.trx_stop_switching = FALSE; /* message to filter: call tx_begin */ (*conn_data)->stgy.trx_begin_required = TRUE; (*conn_data)->stgy.trx_begin_mode = mode; if ((*conn_data)->stgy.trx_begin_name) { mnd_pefree((*conn_data)->stgy.trx_begin_name, conn->persistent); } (*conn_data)->stgy.trx_begin_name = (name) ? mnd_pestrdup(name, conn->persistent) : NULL; if (mode & TRANS_START_READ_ONLY) { (*conn_data)->stgy.trx_read_only = TRUE; DBG_INF("In read only transaction, stop switching."); } else { (*conn_data)->stgy.trx_read_only = FALSE; DBG_INF("In transaction, stop switching."); } } else { /* Note: we are dealing with the proxy connection */ ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_begin)(conn, mode, name TSRMLS_CC); if (PASS == ret) (*conn_data)->stgy.in_transaction = TRUE; DBG_INF_FMT("in_transaction=%d", (*conn_data)->stgy.in_transaction); } } else { /* Note: we are dealing with the proxy connection */ ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_begin)(conn, mode, name TSRMLS_CC); } DBG_RETURN(ret); } /* }}} */ #endif /* {{{ MYSQLND_METHOD(mysqlnd_ms, tx_commit) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC) { enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_ms::tx_commit"); #if MYSQLND_VERSION_ID >= 50011 ret = mysqlnd_ms_tx_commit_or_rollback(conn, TRUE, TRANS_COR_NO_OPT, NULL TSRMLS_CC); #else ret = mysqlnd_ms_tx_commit_or_rollback(conn, TRUE TSRMLS_CC); #endif DBG_RETURN(ret); } /* }}} */ /* {{{ MYSQLND_METHOD(mysqlnd_ms, tx_rollback) */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_DC) { enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_ms::tx_rollback"); #if MYSQLND_VERSION_ID >= 50011 ret = mysqlnd_ms_tx_commit_or_rollback(conn, FALSE, TRANS_COR_NO_OPT, NULL TSRMLS_CC); #else ret = mysqlnd_ms_tx_commit_or_rollback(conn, FALSE TSRMLS_CC); #endif DBG_RETURN(ret); } /* }}} */ #endif /* {{{ mysqlnd_ms::statistic */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, get_server_statistics)(MYSQLND_CONN_DATA * proxy_conn, char **message, unsigned int * message_len TSRMLS_DC) { enum_func_status ret = FAIL; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::statistic"); DBG_INF_FMT("conn="MYSQLND_LLU_SPEC, conn->thread_id); if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); if (!conn || (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY)) { DBG_INF("No connection"); DBG_RETURN(ret); } } ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_server_statistics)(conn, message, message_len TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::get_server_version */ static unsigned long MYSQLND_METHOD(mysqlnd_ms, get_server_version)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); } return MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_server_version)(conn TSRMLS_CC); } /* }}} */ /* {{{ mysqlnd_ms::get_server_info */ static const char * MYSQLND_METHOD(mysqlnd_ms, get_server_info)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); } return MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_server_information)(conn TSRMLS_CC); } /* }}} */ /* {{{ mysqlnd_ms::get_host_info */ static const char * MYSQLND_METHOD(mysqlnd_ms, get_host_info)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); } return MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_host_information)(conn TSRMLS_CC); } /* }}} */ /* {{{ mysqlnd_ms::get_proto_info */ static unsigned int MYSQLND_METHOD(mysqlnd_ms, get_proto_info)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); } return MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_protocol_information)(conn TSRMLS_CC); } /* }}} */ /* {{{ mysqlnd_ms::charset_name */ static const char * MYSQLND_METHOD(mysqlnd_ms, charset_name)(const MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); } return MS_CALL_ORIGINAL_CONN_DATA_METHOD(charset_name)(conn TSRMLS_CC); } /* }}} */ /* {{{ mysqlnd_ms::get_connection_stats */ static void MYSQLND_METHOD(mysqlnd_ms, get_connection_stats)(const MYSQLND_CONN_DATA * const proxy_conn, zval * return_value TSRMLS_DC ZEND_FILE_LINE_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); const MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; MS_CALL_ORIGINAL_CONN_DATA_METHOD(get_statistics)(conn, return_value TSRMLS_CC ZEND_FILE_LINE_CC); } /* }}} */ /* {{{ mysqlnd_ms::dump_debug_info */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, dump_debug_info)(MYSQLND_CONN_DATA * const proxy_conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); MYSQLND_CONN_DATA * conn = ((*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn; DBG_ENTER("mysqlnd_ms::dump_debug_info"); if (CONN_GET_STATE((MYSQLND_CONN_DATA *) conn) < CONN_READY) { conn = mysqlnd_ms_pick_first_master_or_slave(proxy_conn TSRMLS_CC); } DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(server_dump_debug_information)(conn TSRMLS_CC)); } /* }}} */ /* {{{ mysqlnd_ms_stmt::prepare */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms_stmt, prepare)(MYSQLND_STMT * const s, const char * const query, unsigned int query_len TSRMLS_DC) { MYSQLND_MS_CONN_DATA ** conn_data = NULL; MYSQLND_CONN_DATA * connection = NULL; enum_func_status ret = FAIL; zend_bool free_query = FALSE; DBG_ENTER("mysqlnd_ms_stmt::prepare"); DBG_INF_FMT("query=%s", query); if (!s || !s->data || !s->data->conn || !(MS_LOAD_CONN_DATA(conn_data, s->data->conn)) || !*conn_data || (*conn_data)->skip_ms_calls) { DBG_INF("skip MS"); DBG_RETURN(ms_orig_mysqlnd_stmt_methods->prepare(s, query, query_len TSRMLS_CC)); } /* this can possibly reroute us to another server */ connection = mysqlnd_ms_pick_server_ex((*conn_data)->proxy_conn, (char **)&query, (size_t *)&query_len, &free_query TSRMLS_CC); DBG_INF_FMT("Connection %p, query=%s", connection, query); if (connection != s->data->conn) { /* free what we have */ s->m->net_close(s, TRUE TSRMLS_CC); mnd_pefree(s->data, s->data->persistent); /* new handle */ { MYSQLND_STMT * new_handle = MS_CALL_ORIGINAL_CONN_DATA_METHOD(stmt_init)(connection TSRMLS_CC); if (!new_handle || !new_handle->data) { DBG_ERR("new_handle is null"); if (TRUE == free_query) { efree((void *)query); } DBG_RETURN(FAIL); } s->data = new_handle->data; mnd_pefree(new_handle, new_handle->data->persistent); } } ret = ms_orig_mysqlnd_stmt_methods->prepare(s, query, query_len TSRMLS_CC); if (TRUE == free_query) { efree((void *)query); } DBG_RETURN(ret); } /* }}} */ #ifndef MYSQLND_HAS_INJECTION_FEATURE /* {{{ mysqlnd_ms_stmt::execute */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC) { enum_func_status ret = PASS; MYSQLND_MS_CONN_DATA ** conn_data = NULL; MYSQLND_CONN_DATA * connection = NULL; MYSQLND_STMT_DATA * stmt = s? s->data:NULL; DBG_ENTER("mysqlnd_ms_stmt::execute"); if (!stmt || !s || !s->data || !s->data->conn || !(MS_LOAD_CONN_DATA(conn_data, s->data->conn)) || !conn_data || !*conn_data || (*conn_data)->skip_ms_calls) { DBG_INF("skip MS"); ret = ms_orig_mysqlnd_stmt_methods->execute(s TSRMLS_CC); DBG_RETURN(ret); } connection = s->data->conn; DBG_INF_FMT("conn="MYSQLND_LLU_SPEC, connection->thread_id); if (CONN_DATA_TRY_TRX_INJECTION(conn_data, connection) && (FALSE == (*conn_data)->stgy.in_transaction)) { /* autocommit mode */ MS_TRX_INJECT(ret, connection, conn_data); MYSQLND_MS_INC_STATISTIC((PASS == ret) ? MS_STAT_GTID_AUTOCOMMIT_SUCCESS : MS_STAT_GTID_AUTOCOMMIT_FAILURE); if (FAIL == ret) { if (TRUE == (*conn_data)->global_trx.report_error) { /* user stmt returns false and shall have error set */ SET_STMT_ERROR(stmt, (MYSQLND_MS_ERROR_INFO(connection)).error_no, (MYSQLND_MS_ERROR_INFO(connection)).sqlstate, (MYSQLND_MS_ERROR_INFO(connection)).error); DBG_RETURN(ret); } SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(connection)); } } ret = ms_orig_mysqlnd_stmt_methods->execute(s TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ #endif /* {{{ mysqlnd_conn::ssl_set */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, ssl_set)(MYSQLND_CONN_DATA * const proxy_conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC) { enum_func_status ret = PASS; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); DBG_ENTER("mysqlnd_ms::ssl_set"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, proxy_conn->thread_id); if (CONN_DATA_NOT_SET(conn_data)) { DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(ssl_set)(proxy_conn, key, cert, ca, capath, cipher TSRMLS_CC)); } else { MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LISTS(el, &(*conn_data)->master_connections, &(*conn_data)->slave_connections); { if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(ssl_set)(el->conn, key, cert, ca, capath, cipher TSRMLS_CC)) { ret = FAIL; } } END_ITERATE_OVER_SERVER_LISTS; } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms::close */ static enum_func_status MYSQLND_METHOD(mysqlnd_ms, close)(MYSQLND * conn, enum_connection_close_type close_type TSRMLS_DC) { enum_func_status ret; DBG_ENTER("mysqlnd_ms::close"); DBG_INF_FMT("Using thread "MYSQLND_LLU_SPEC, MS_GET_CONN_DATA_FROM_CONN(conn)->thread_id); /* Force cleaning of the master and slave lists. In the master list this connection is present and free_reference will be called, and later in the original `close` the data of this connection will be destructed as refcount will become 0. */ mysqlnd_ms_conn_free_plugin_data(MS_GET_CONN_DATA_FROM_CONN(conn) TSRMLS_CC); ret = MS_CALL_ORIGINAL_CONN_HANDLE_METHOD(close)(conn, close_type TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_register_hooks*/ void mysqlnd_ms_register_hooks() { MS_LOAD_AND_COPY_CONN_DATA_METHODS(ms_orig_mysqlnd_conn_methods, my_mysqlnd_conn_methods); my_mysqlnd_conn_methods.connect = MYSQLND_METHOD(mysqlnd_ms, connect); my_mysqlnd_conn_methods.query = MYSQLND_METHOD(mysqlnd_ms, query); my_mysqlnd_conn_methods.send_query = MYSQLND_METHOD(mysqlnd_ms, send_query); my_mysqlnd_conn_methods.use_result = MYSQLND_METHOD(mysqlnd_ms, use_result); my_mysqlnd_conn_methods.store_result = MYSQLND_METHOD(mysqlnd_ms, store_result); my_mysqlnd_conn_methods.dtor = MYSQLND_METHOD_PRIVATE(mysqlnd_ms, dtor); my_mysqlnd_conn_methods.escape_string = MYSQLND_METHOD(mysqlnd_ms, escape_string); my_mysqlnd_conn_methods.change_user = MYSQLND_METHOD(mysqlnd_ms, change_user); my_mysqlnd_conn_methods.ping = MYSQLND_METHOD(mysqlnd_ms, ping); my_mysqlnd_conn_methods.kill_connection = MYSQLND_METHOD(mysqlnd_ms, kill); my_mysqlnd_conn_methods.get_thread_id = MYSQLND_METHOD(mysqlnd_ms, thread_id); my_mysqlnd_conn_methods.select_db = MYSQLND_METHOD(mysqlnd_ms, select_db); my_mysqlnd_conn_methods.set_charset = MYSQLND_METHOD(mysqlnd_ms, set_charset); my_mysqlnd_conn_methods.set_server_option = MYSQLND_METHOD(mysqlnd_ms, set_server_option); my_mysqlnd_conn_methods.set_client_option = MYSQLND_METHOD(mysqlnd_ms, set_client_option); my_mysqlnd_conn_methods.next_result = MYSQLND_METHOD(mysqlnd_ms, next_result); my_mysqlnd_conn_methods.more_results = MYSQLND_METHOD(mysqlnd_ms, more_results); my_mysqlnd_conn_methods.get_error_no = MYSQLND_METHOD(mysqlnd_ms, error_no); my_mysqlnd_conn_methods.get_error_str = MYSQLND_METHOD(mysqlnd_ms, error); my_mysqlnd_conn_methods.get_sqlstate = MYSQLND_METHOD(mysqlnd_ms, sqlstate); my_mysqlnd_conn_methods.ssl_set = MYSQLND_METHOD(mysqlnd_ms, ssl_set); my_mysqlnd_conn_methods.get_field_count = MYSQLND_METHOD(mysqlnd_ms, field_count); my_mysqlnd_conn_methods.get_last_insert_id = MYSQLND_METHOD(mysqlnd_ms, insert_id); my_mysqlnd_conn_methods.get_affected_rows = MYSQLND_METHOD(mysqlnd_ms, affected_rows); my_mysqlnd_conn_methods.get_warning_count = MYSQLND_METHOD(mysqlnd_ms, warning_count); my_mysqlnd_conn_methods.get_last_message = MYSQLND_METHOD(mysqlnd_ms, info); #if MYSQLND_VERSION_ID >= 50009 my_mysqlnd_conn_methods.set_autocommit = MYSQLND_METHOD(mysqlnd_ms, set_autocommit); my_mysqlnd_conn_methods.tx_commit = MYSQLND_METHOD(mysqlnd_ms, tx_commit); my_mysqlnd_conn_methods.tx_rollback = MYSQLND_METHOD(mysqlnd_ms, tx_rollback); #endif #if MYSQLND_VERSION_ID >= 50011 my_mysqlnd_conn_methods.tx_commit_or_rollback = MYSQLND_METHOD(mysqlnd_ms, tx_commit_or_rollback); my_mysqlnd_conn_methods.tx_begin = MYSQLND_METHOD(mysqlnd_ms, tx_begin); #endif my_mysqlnd_conn_methods.get_server_statistics = MYSQLND_METHOD(mysqlnd_ms, get_server_statistics); my_mysqlnd_conn_methods.get_server_version = MYSQLND_METHOD(mysqlnd_ms, get_server_version); my_mysqlnd_conn_methods.get_server_information = MYSQLND_METHOD(mysqlnd_ms, get_server_info); my_mysqlnd_conn_methods.get_host_information = MYSQLND_METHOD(mysqlnd_ms, get_host_info); my_mysqlnd_conn_methods.get_protocol_information= MYSQLND_METHOD(mysqlnd_ms, get_proto_info); my_mysqlnd_conn_methods.charset_name = MYSQLND_METHOD(mysqlnd_ms, charset_name); my_mysqlnd_conn_methods.get_statistics = MYSQLND_METHOD(mysqlnd_ms, get_connection_stats); my_mysqlnd_conn_methods.server_dump_debug_information = MYSQLND_METHOD(mysqlnd_ms, dump_debug_info); MS_SET_CONN_DATA_METHODS(&my_mysqlnd_conn_methods); #if PHP_VERSION_ID < 50399 my_mysqlnd_conn_methods.close = MYSQLND_METHOD(mysqlnd_ms, close); #else MS_LOAD_AND_COPY_CONN_HANDLE_METHODS(ms_orig_mysqlnd_conn_handle_methods, my_mysqlnd_conn_handle_methods); my_mysqlnd_conn_handle_methods.close = MYSQLND_METHOD(mysqlnd_ms, close); MS_SET_CONN_HANDLE_METHODS(&my_mysqlnd_conn_handle_methods); #endif ms_orig_mysqlnd_stmt_methods = mysqlnd_stmt_get_methods(); memcpy(&my_mysqlnd_stmt_methods, ms_orig_mysqlnd_stmt_methods, sizeof(struct st_mysqlnd_stmt_methods)); my_mysqlnd_stmt_methods.prepare = MYSQLND_METHOD(mysqlnd_ms_stmt, prepare); #ifndef MYSQLND_HAS_INJECTION_FEATURE my_mysqlnd_stmt_methods.execute = MYSQLND_METHOD(mysqlnd_ms_stmt, execute); #endif mysqlnd_stmt_set_methods(&my_mysqlnd_stmt_methods); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_config_json.c0000664000175000017500000007571012161007456020161 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms_config_json.c 329770 2013-03-13 15:28:49Z uw $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #include "mysqlnd_ms.h" #include "mysqlnd_ms_config_json.h" #include "ext/json/php_json.h" #ifndef mnd_sprintf #define mnd_sprintf spprintf #define mnd_sprintf_free efree #endif struct st_mysqlnd_ms_config_json_entry { union { struct { char * c; size_t len; } str; HashTable * ht; double dval; long long lval; } value; zend_uchar type; }; struct st_mysqlnd_ms_json_config { struct st_mysqlnd_ms_config_json_entry * main_section; #ifdef ZTS MUTEX_T LOCK_access; #endif }; /* {{{ mysqlnd_ms_config_json_init */ PHPAPI struct st_mysqlnd_ms_json_config * mysqlnd_ms_config_json_init(TSRMLS_D) { struct st_mysqlnd_ms_json_config * ret; DBG_ENTER("mysqlnd_ms_config_json_init"); ret = mnd_calloc(1, sizeof(struct st_mysqlnd_ms_json_config)); #ifdef ZTS ret->LOCK_access = tsrm_mutex_alloc(); #endif DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_section_dtor */ static void mysqlnd_ms_config_json_section_dtor(void * data) { struct st_mysqlnd_ms_config_json_entry * entry = * (struct st_mysqlnd_ms_config_json_entry **) data; TSRMLS_FETCH(); if (entry) { switch (entry->type) { case IS_DOUBLE: case IS_LONG: case IS_NULL: break; case IS_STRING: mnd_free(entry->value.str.c); break; case IS_ARRAY: zend_hash_destroy(entry->value.ht); mnd_free(entry->value.ht); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Unknown entry type %d in mysqlnd_ms_config_json_section_dtor", entry->type); } mnd_free(entry); } } /* }}} */ /* {{{ mysqlnd_ms_config_json_free */ PHPAPI void mysqlnd_ms_config_json_free(struct st_mysqlnd_ms_json_config * cfg TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_config_json_free"); if (cfg) { mysqlnd_ms_config_json_section_dtor(&cfg->main_section); #ifdef ZTS tsrm_mutex_free(cfg->LOCK_access); #endif mnd_free(cfg); } DBG_VOID_RETURN; } /* }}} */ static struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_zval_data_to_hashtable(zval * json_data TSRMLS_DC); /* {{{ mysqlnd_ms_add_zval_to_hash */ static void mysqlnd_ms_add_zval_to_hash(zval * zv, HashTable * ht, const char * skey, size_t skey_len, ulong nkey, int key_type TSRMLS_DC) { struct st_mysqlnd_ms_config_json_entry * new_entry = NULL; DBG_ENTER("mysqlnd_ms_add_zval_to_hash"); switch (Z_TYPE_P(zv)) { case IS_ARRAY: new_entry = mysqlnd_ms_zval_data_to_hashtable(zv TSRMLS_CC); break; case IS_STRING: new_entry = mnd_calloc(1, sizeof(struct st_mysqlnd_ms_config_json_entry)); new_entry->type = IS_STRING; new_entry->value.str.c = mnd_pestrndup(Z_STRVAL_P(zv), Z_STRLEN_P(zv), 1); new_entry->value.str.len = Z_STRLEN_P(zv); DBG_INF_FMT("str=%s", new_entry->value.str.c); break; case IS_DOUBLE: new_entry = mnd_calloc(1, sizeof(struct st_mysqlnd_ms_config_json_entry)); new_entry->type = IS_DOUBLE; new_entry->value.dval = Z_DVAL_P(zv); DBG_INF_FMT("dval=%f", new_entry->value.dval); break; case IS_BOOL: DBG_INF("boolean"); case IS_LONG: new_entry = mnd_calloc(1, sizeof(struct st_mysqlnd_ms_config_json_entry)); new_entry->type = IS_LONG; new_entry->value.lval = Z_LVAL_P(zv); DBG_INF_FMT("lval="MYSQLND_LL_SPEC, (long long) new_entry->value.lval); break; case IS_NULL: new_entry = mnd_calloc(1, sizeof(struct st_mysqlnd_ms_config_json_entry)); new_entry->type = IS_NULL; DBG_INF("null value"); break; default: DBG_INF("unknown type"); break; } if (new_entry) { switch (key_type) { case HASH_KEY_IS_STRING: zend_hash_add(ht, skey, skey_len, &new_entry, sizeof(struct st_mysqlnd_ms_config_json_entry *), NULL); DBG_INF_FMT("New HASH_KEY_IS_STRING entry [%s]", skey); break; default: zend_hash_index_update(ht, nkey, &new_entry, sizeof(struct st_mysqlnd_ms_config_json_entry *), NULL); DBG_INF_FMT("New HASH_KEY_IS_LONG entry [%u]", nkey); break; } } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_zval_data_to_hashtable */ static struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_zval_data_to_hashtable(zval * json_data TSRMLS_DC) { struct st_mysqlnd_ms_config_json_entry * ret = NULL; DBG_ENTER("mysqlnd_ms_zval_data_to_hashtable"); if (json_data && (ret = mnd_calloc(1, sizeof(struct st_mysqlnd_ms_config_json_entry)))) { HashPosition pos; zval ** entry_zval; ret->type = IS_ARRAY; ret->value.ht = mnd_calloc(1, sizeof(HashTable)); zend_hash_init(ret->value.ht, Z_TYPE_P(json_data) == IS_ARRAY? zend_hash_num_elements(Z_ARRVAL_P(json_data)) : 1, NULL /* hash_func */, mysqlnd_ms_config_json_section_dtor /*dtor*/, 1 /* persistent */); if (Z_TYPE_P(json_data) == IS_ARRAY) { zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(json_data), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(json_data), (void **)&entry_zval, &pos) == SUCCESS) { char * skey = NULL; uint skey_len = 0; ulong nkey = 0; int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(json_data), &skey, &skey_len, &nkey, 0/*dup*/, &pos); mysqlnd_ms_add_zval_to_hash(*entry_zval, ret->value.ht, skey, skey_len, nkey, key_type TSRMLS_CC); zend_hash_move_forward_ex(Z_ARRVAL_P(json_data), &pos); } /* while */ } else { } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_load_configuration */ PHPAPI enum_func_status mysqlnd_ms_config_json_load_configuration(struct st_mysqlnd_ms_json_config * cfg TSRMLS_DC) { enum_func_status ret = FAIL; char * json_file_name = INI_STR("mysqlnd_ms.config_file"); DBG_ENTER("mysqlnd_ms_config_json_load_configuration"); DBG_INF_FMT("json_file=%s", json_file_name? json_file_name:"n/a"); if (MYSQLND_MS_G(config_startup_error)) { mnd_sprintf_free(MYSQLND_MS_G(config_startup_error)); MYSQLND_MS_G(config_startup_error) = NULL; } if (!json_file_name) { ret = PASS; } else if (json_file_name && cfg) { do { php_stream * stream; int str_data_len; char * str_data; zval json_data; stream = php_stream_open_wrapper_ex(json_file_name, "rb", REPORT_ERRORS, NULL, NULL); if (!stream) { mnd_sprintf(&(MYSQLND_MS_G(config_startup_error)), 0, MYSQLND_MS_ERROR_PREFIX " Failed to open server list config file [%s]", json_file_name); /* The only one to bark in RINIT as otherwise no specific warning/error appears */ php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_G(config_startup_error)); break; } str_data_len = php_stream_copy_to_mem(stream, &str_data, PHP_STREAM_COPY_ALL, 0); php_stream_close(stream); if (str_data_len <= 0) { mnd_sprintf(&(MYSQLND_MS_G(config_startup_error)), 0, MYSQLND_MS_ERROR_PREFIX " Config file [%s] is empty. If this is not by mistake, please add some minimal JSON to it to prevent this warning. For example, use '{}' ", json_file_name); break; } #if PHP_VERSION_ID >= 50399 php_json_decode_ex(&json_data, str_data, str_data_len, PHP_JSON_OBJECT_AS_ARRAY, 512 /* default depth */ TSRMLS_CC); #else php_json_decode(&json_data, str_data, str_data_len, 1 /* assoc */, 512 /* default depth */ TSRMLS_CC); #endif efree(str_data); if (Z_TYPE(json_data) == IS_NULL) { mnd_sprintf(&(MYSQLND_MS_G(config_startup_error)), 0, MYSQLND_MS_ERROR_PREFIX " Failed to parse config file [%s]. Please, verify the JSON", json_file_name); zval_dtor(&json_data); break; } cfg->main_section = mysqlnd_ms_zval_data_to_hashtable(&json_data TSRMLS_CC); zval_dtor(&json_data); if (!cfg->main_section) { mnd_sprintf(&(MYSQLND_MS_G(config_startup_error)), 0, MYSQLND_MS_ERROR_PREFIX " Failed to find a main section in the config file [%s]. Please, verify the JSON", json_file_name); break; } ret = PASS; } while (0); } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_section_exists */ PHPAPI zend_bool mysqlnd_ms_config_json_section_exists(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, ulong nkey, zend_bool use_lock TSRMLS_DC) { zend_bool ret = FALSE; DBG_ENTER("mysqlnd_ms_config_json_section_exists"); DBG_INF_FMT("section=[%s] len=[%d]", section? section:"n/a", section_len); if (cfg) { if (use_lock) { MYSQLND_MS_CONFIG_JSON_LOCK(cfg); } ret = mysqlnd_ms_config_json_sub_section_exists(cfg->main_section, section, section_len, nkey TSRMLS_CC); if (use_lock) { MYSQLND_MS_CONFIG_JSON_UNLOCK(cfg); } } DBG_INF_FMT("ret=%d", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_sub_section_exists */ PHPAPI zend_bool mysqlnd_ms_config_json_sub_section_exists(struct st_mysqlnd_ms_config_json_entry * main_section, const char * section, size_t section_len, ulong nkey TSRMLS_DC) { zend_bool ret = FALSE; DBG_ENTER("mysqlnd_ms_config_json_sub_section_exists"); DBG_INF_FMT("section=[%s] len=[%d]", section? section:"n/a", section_len); if (main_section && main_section->type == IS_ARRAY && main_section->value.ht){ void ** ini_entry; if (section && section_len) { ret = (SUCCESS == zend_hash_find(main_section->value.ht, section, section_len + 1, (void **) &ini_entry))? TRUE:FALSE; } else { ret = (SUCCESS == zend_hash_index_find(main_section->value.ht, nkey, (void **) &ini_entry))? TRUE:FALSE; } } DBG_INF_FMT("ret=%d", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_section */ PHPAPI struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_config_json_section(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, zend_bool * exists TSRMLS_DC) { struct st_mysqlnd_ms_config_json_entry * ret = NULL; DBG_ENTER("mysqlnd_ms_config_json_section"); if (cfg) { ret = mysqlnd_ms_config_json_sub_section(cfg->main_section, section, section_len, exists TSRMLS_CC); } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_section */ PHPAPI struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_config_json_sub_section(struct st_mysqlnd_ms_config_json_entry * main_section, const char * section, size_t section_len, zend_bool * exists TSRMLS_DC) { zend_bool tmp_bool; struct st_mysqlnd_ms_config_json_entry * ret = NULL; DBG_ENTER("mysqlnd_ms_config_json_sub_section"); DBG_INF_FMT("section=%s", section); if (exists) { *exists = 0; } else { exists = &tmp_bool; } if (main_section && main_section->type == IS_ARRAY && main_section->value.ht) { struct st_mysqlnd_ms_config_json_entry ** ini_section; if (zend_hash_find(main_section->value.ht, section, section_len + 1, (void **) &ini_section) == SUCCESS) { if (ini_section && IS_ARRAY == (*ini_section)->type) { *exists = 1; ret = *ini_section; } } } DBG_INF_FMT("ret=%p", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_section_is_list */ PHPAPI zend_bool mysqlnd_ms_config_json_section_is_list(struct st_mysqlnd_ms_config_json_entry * section TSRMLS_DC) { zend_bool ret; DBG_ENTER("mysqlnd_ms_config_json_section_is_list"); ret = (section && section->type == IS_ARRAY && section->value.ht)? TRUE:FALSE; DBG_INF_FMT("ret=%d", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_section_is_object_list */ PHPAPI zend_bool mysqlnd_ms_config_json_section_is_object_list(struct st_mysqlnd_ms_config_json_entry * section TSRMLS_DC) { zend_bool ret = TRUE; DBG_ENTER("mysqlnd_ms_config_json_section_is_object_list"); if (section && section->type == IS_ARRAY && section->value.ht) { HashPosition pos; struct st_mysqlnd_ms_config_json_entry ** entry; zend_hash_internal_pointer_reset_ex(section->value.ht, &pos); while (SUCCESS == zend_hash_get_current_data_ex(section->value.ht, (void **)&entry, &pos)) { if (!((*entry) && (*entry)->type == IS_ARRAY && (*entry)->value.ht)) { ret = FALSE; break; } zend_hash_move_forward_ex(section->value.ht, &pos); } } else { ret = FALSE; } DBG_INF_FMT("ret=%d", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_next_sub_section */ PHPAPI struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_config_json_next_sub_section(struct st_mysqlnd_ms_config_json_entry * main_section, char ** section_name, size_t * section_name_len, ulong * nkey TSRMLS_DC) { struct st_mysqlnd_ms_config_json_entry * ret = NULL; struct st_mysqlnd_ms_config_json_entry ** entry; DBG_ENTER("mysqlnd_ms_config_json_next_sub_section"); if (SUCCESS == zend_hash_get_current_data(main_section->value.ht, (void **)&entry)) { char * tmp_skey = NULL; uint tmp_skey_len = 0; ulong tmp_nkey = 0; int key_type; if (!section_name) { section_name = &tmp_skey; } if (!nkey) { nkey = &tmp_nkey; } key_type = zend_hash_get_current_key_ex(main_section->value.ht, section_name, &tmp_skey_len, nkey, 0/*dup*/,NULL/*pos*/); if (HASH_KEY_IS_STRING == key_type) { if (section_name_len) { *section_name_len = --tmp_skey_len; DBG_INF_FMT("section(len)=%s(%d)", *section_name, *section_name_len); } } ret = *entry; zend_hash_move_forward(main_section->value.ht); } DBG_INF_FMT("ret=%p", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_string_aux_inner */ static char * mysqlnd_ms_config_json_string_aux_inner(struct st_mysqlnd_ms_config_json_entry * ini_section_entry, zend_bool * exists, zend_bool * is_list_value TSRMLS_DC) { char * ret = NULL; DBG_ENTER("mysqlnd_ms_config_json_string_aux_inner"); if (ini_section_entry) { switch (ini_section_entry->type) { case IS_LONG: DBG_INF_FMT("long2string:%lld", ini_section_entry->value.lval); { char * tmp_buf; int tmp_buf_len = spprintf(&tmp_buf, 0, "%lld", ini_section_entry->value.lval); ret = mnd_pestrndup(tmp_buf, tmp_buf_len, 0); DBG_INF_FMT("result=%s", tmp_buf); efree(tmp_buf); } *exists = 1; break; case IS_DOUBLE: DBG_INF_FMT("double2string:%f", ini_section_entry->value.dval); { char * tmp_buf; int tmp_buf_len = spprintf(&tmp_buf, 0, "%f", ini_section_entry->value.dval); ret = mnd_pestrndup(tmp_buf, tmp_buf_len, 0); DBG_INF_FMT("result=%s", tmp_buf); efree(tmp_buf); } *exists = 1; break; case IS_STRING: DBG_INF("IS_STRING"); ret = mnd_pestrndup(ini_section_entry->value.str.c, ini_section_entry->value.str.len, 0); *exists = 1; break; case IS_NULL: DBG_INF("IS_NULL"); *exists = 1; break; case IS_ARRAY: { struct st_mysqlnd_ms_config_json_entry ** value; DBG_INF("IS_ARRAY"); *is_list_value = 1; DBG_INF_FMT("the list has %d entries", zend_hash_num_elements(ini_section_entry->value.ht)); if (SUCCESS == zend_hash_get_current_data(ini_section_entry->value.ht, (void **)&value)) { switch ((*value)->type) { case IS_STRING: ret = mnd_pestrndup((*value)->value.str.c, (*value)->value.str.len, 0); *exists = 1; break; case IS_LONG: { char * tmp_buf; int tmp_buf_len = spprintf(&tmp_buf, 0, "%lld", (*value)->value.lval); ret = mnd_pestrndup(tmp_buf, tmp_buf_len, 0); DBG_INF_FMT("result=%s", tmp_buf); efree(tmp_buf); } *exists = 1; break; case IS_DOUBLE: { char * tmp_buf; int tmp_buf_len = spprintf(&tmp_buf, 0, "%f", (*value)->value.dval); ret = mnd_pestrndup(tmp_buf, tmp_buf_len, 0); DBG_INF_FMT("result=%s", tmp_buf); efree(tmp_buf); } *exists = 1; break; case IS_ARRAY: DBG_ERR("still unsupported type"); /* to do */ break; } zend_hash_move_forward(ini_section_entry->value.ht); } break; } default: DBG_ERR("Unknown type"); php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Unknown entry type %d in mysqlnd_ms_config_json_string", ini_section_entry->type); break; } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_string_from_section */ PHPAPI char * mysqlnd_ms_config_json_string_from_section(struct st_mysqlnd_ms_config_json_entry * section, const char * name, size_t name_len, ulong nkey, zend_bool * exists, zend_bool * is_list_value TSRMLS_DC) { zend_bool tmp_bool; char * ret = NULL; DBG_ENTER("mysqlnd_ms_config_json_string_from_section"); DBG_INF_FMT("name=%s", name); if (exists) { *exists = 0; } else { exists = &tmp_bool; } if (is_list_value) { *is_list_value = 0; } else { is_list_value = &tmp_bool; } if (section && section->type == IS_ARRAY && section->value.ht) { struct st_mysqlnd_ms_config_json_entry ** ini_section_entry; if (name) { if (zend_hash_find(section->value.ht, name, name_len + 1, (void **) &ini_section_entry) == SUCCESS) { ret = mysqlnd_ms_config_json_string_aux_inner(*ini_section_entry, exists, is_list_value TSRMLS_CC); } } else { if (zend_hash_index_find(section->value.ht, nkey, (void **) &ini_section_entry) == SUCCESS) { ret = mysqlnd_ms_config_json_string_aux_inner(*ini_section_entry, exists, is_list_value TSRMLS_CC); } } } DBG_INF_FMT("ret=%s", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_int_aux_inner */ static int64_t mysqlnd_ms_config_json_int_aux_inner(struct st_mysqlnd_ms_config_json_entry * ini_section_entry, zend_bool * exists, zend_bool * is_list_value TSRMLS_DC) { int64_t ret = 0; DBG_ENTER("mysqlnd_ms_config_json_string_aux_inner"); if (ini_section_entry) { switch (ini_section_entry->type) { case IS_LONG: DBG_INF_FMT("long2string:%lld", ini_section_entry->value.lval); ret = ini_section_entry->value.lval; *exists = 1; break; case IS_DOUBLE: DBG_INF_FMT("double2string:%f", ini_section_entry->value.dval); ret = (int64_t) ini_section_entry->value.dval; *exists = 1; break; case IS_STRING: DBG_INF("IS_STRING"); ret = atoll(ini_section_entry->value.str.c); *exists = 1; break; case IS_NULL: DBG_INF("IS_NULL"); ret = 0; *exists = 1; break; case IS_ARRAY: { struct st_mysqlnd_ms_config_json_entry ** value; DBG_INF("IS_ARRAY"); *is_list_value = 1; DBG_INF_FMT("the list has %d entries", zend_hash_num_elements(ini_section_entry->value.ht)); if (SUCCESS == zend_hash_get_current_data(ini_section_entry->value.ht, (void **)&value)) { switch ((*value)->type) { case IS_STRING: ret = atoll((*value)->value.str.c); *exists = 1; break; case IS_LONG: ret = (*value)->value.lval; *exists = 1; break; case IS_DOUBLE: ret = (int64_t) (*value)->value.dval; *exists = 1; break; case IS_ARRAY: DBG_ERR("still unsupported type"); /* to do */ break; } zend_hash_move_forward(ini_section_entry->value.ht); } break; } default: DBG_ERR("Unknown type"); php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Unknown entry type %d in mysqlnd_ms_config_json_string", ini_section_entry->type); break; } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_config_json_int_from_section */ PHPAPI int64_t mysqlnd_ms_config_json_int_from_section(struct st_mysqlnd_ms_config_json_entry * section, const char * name, size_t name_len, ulong nkey, zend_bool * exists, zend_bool * is_list_value TSRMLS_DC) { zend_bool tmp_bool; int64_t ret = 0; DBG_ENTER("mysqlnd_ms_config_json_int_from_section"); DBG_INF_FMT("name=%s", name); if (exists) { *exists = 0; } else { exists = &tmp_bool; } if (is_list_value) { *is_list_value = 0; } else { is_list_value = &tmp_bool; } if (section && section->type == IS_ARRAY && section->value.ht) { struct st_mysqlnd_ms_config_json_entry ** ini_section_entry; if (name) { if (zend_hash_find(section->value.ht, name, name_len + 1, (void **) &ini_section_entry) == SUCCESS) { ret = mysqlnd_ms_config_json_int_aux_inner(*ini_section_entry, exists, is_list_value TSRMLS_CC); } } else { if (zend_hash_index_find(section->value.ht, nkey, (void **) &ini_section_entry) == SUCCESS) { ret = mysqlnd_ms_config_json_int_aux_inner(*ini_section_entry, exists, is_list_value TSRMLS_CC); } } } DBG_INF_FMT("ret="MYSQLND_LL_SPEC, ret); DBG_RETURN(ret); } /* }}} */ #ifdef U0 /* TODO: never called */ /* {{{ mysqlnd_ms_config_json_string */ PHPAPI char * mysqlnd_ms_config_json_string(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, const char * name, size_t name_len, zend_bool * exists, zend_bool * is_list_value, zend_bool use_lock TSRMLS_DC) { char * ret = NULL; DBG_ENTER("mysqlnd_ms_config_json_string"); DBG_INF_FMT("name=%s", name); if (!cfg) { DBG_RETURN(ret); } if (use_lock) { MYSQLND_MS_CONFIG_JSON_LOCK(cfg); } ret = mysqlnd_ms_config_json_string_aux(cfg->main_section->value.ht, section, section_len, name, name_len, exists, is_list_value TSRMLS_CC); if (use_lock) { MYSQLND_MS_CONFIG_JSON_UNLOCK(cfg); } DBG_INF_FMT("ret=%s", ret? ret:"n/a"); DBG_RETURN(ret); } /* }}} */ #endif #ifdef U0 /* TODO: never called */ /* {{{ mysqlnd_ms_str_to_long_long */ static long long mysqlnd_ms_str_to_long_long(const char * const s, zend_bool * valid) { long long ret; char * end_ptr; errno = 0; ret = strtoll(s, &end_ptr, 10); if ( ( (errno == ERANGE && (ret == LLONG_MAX || ret == LLONG_MIN)) || (errno != 0 && ret == 0) ) || end_ptr == s ) { *valid = 0; return 0; } *valid = 1; return ret; } /* }}} */ /* {{{ mysqlnd_ms_config_json_int */ PHPAPI long long mysqlnd_ms_config_json_int(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, const char * name, size_t name_len, zend_bool * exists, zend_bool * is_list_value, zend_bool use_lock TSRMLS_DC) { zend_bool tmp_bool; long long ret = 0; DBG_ENTER("mysqlnd_ms_config_json_int"); DBG_INF_FMT("name=%s", name); if (exists) { *exists = 0; } else { exists = &tmp_bool; } if (is_list_value) { *is_list_value = 0; } else { is_list_value = &tmp_bool; } if (!cfg) { DBG_RETURN(ret); } if (use_lock) { MYSQLND_MS_CONFIG_JSON_LOCK(cfg); } if (cfg->main_section) { struct st_mysqlnd_ms_config_json_entry ** ini_section; if (zend_hash_find(cfg->main_section->value.ht, section, section_len + 1, (void **) &ini_section) == SUCCESS) { struct st_mysqlnd_ms_config_json_entry * ini_section_entry = NULL; switch ((*ini_section)->type) { case IS_LONG: case IS_DOUBLE: case IS_STRING: ini_section_entry = *ini_section; break; case IS_ARRAY: { struct st_mysqlnd_ms_config_json_entry ** ini_section_entry_pp; if (zend_hash_find((*ini_section)->value.ht, name, name_len + 1, (void **) &ini_section_entry_pp) == SUCCESS) { ini_section_entry = *ini_section_entry_pp; } break; } } if (ini_section_entry) { switch (ini_section_entry->type) { case IS_LONG: ret = ini_section_entry->value.lval; *exists = 1; break; case IS_DOUBLE: ret = (long long) ini_section_entry->value.dval; *exists = 1; break; case IS_STRING: ret = mysqlnd_ms_str_to_long_long(ini_section_entry->value.str.c, exists); break; case IS_ARRAY: { struct st_mysqlnd_ms_config_json_entry ** value; *is_list_value = 1; DBG_INF_FMT("the list has %d entries", zend_hash_num_elements(ini_section_entry->value.ht)); if (SUCCESS == zend_hash_get_current_data(ini_section_entry->value.ht, (void **)&value)) { switch ((*value)->type) { case IS_STRING: ret = mysqlnd_ms_str_to_long_long((*value)->value.str.c, exists); break; case IS_LONG: ret = (*value)->value.lval; break; case IS_DOUBLE: ret = (long long) (*value)->value.dval; *exists = 1; break; case IS_ARRAY: DBG_ERR("still unsupported type"); break; /* to do */ } zend_hash_move_forward(ini_section_entry->value.ht); } break; } default: php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Unknown entry type %d in mysqlnd_ms_config_json_int", ini_section_entry->type); break; } } } /* if (zend_hash... */ } /* if (cfg->config) */ if (use_lock) { MYSQLND_MS_CONFIG_JSON_UNLOCK(cfg); } DBG_INF_FMT("ret="MYSQLND_LL_SPEC, (long long) ret); DBG_RETURN(ret); } /* }}} */ #endif #ifdef U0 /* TODO: never used */ /* {{{ mysqlnd_ms_str_to_double */ static double mysqlnd_ms_str_to_double(const char * const s, zend_bool * valid) { double ret; char * end_ptr; errno = 0; ret = strtod(s, &end_ptr); if ( ( (errno == ERANGE && (ret == HUGE_VALF || ret == HUGE_VALL)) || (errno != 0 && ret == 0) ) || end_ptr == s ) { *valid = 0; return 0; } *valid = 1; return ret; } /* }}} */ /* {{{ mysqlnd_ms_config_json_double */ PHPAPI double mysqlnd_ms_config_json_double(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, const char * name, size_t name_len, zend_bool * exists, zend_bool * is_list_value, zend_bool use_lock TSRMLS_DC) { zend_bool tmp_bool; double ret = 0; DBG_ENTER("mysqlnd_ms_config_json_double"); DBG_INF_FMT("name=%s", name); if (!cfg) { DBG_RETURN(ret); } if (exists) { *exists = 0; } else { exists = &tmp_bool; } if (is_list_value) { *is_list_value = 0; } else { is_list_value = &tmp_bool; } if (use_lock) { MYSQLND_MS_CONFIG_JSON_LOCK(cfg); } if (cfg->main_section) { struct st_mysqlnd_ms_config_json_entry ** ini_section; if (zend_hash_find(cfg->main_section->value.ht, section, section_len + 1, (void **) &ini_section) == SUCCESS) { struct st_mysqlnd_ms_config_json_entry * ini_section_entry = NULL; switch ((*ini_section)->type) { case IS_LONG: case IS_DOUBLE: case IS_STRING: ini_section_entry = *ini_section; break; case IS_ARRAY: { struct st_mysqlnd_ms_config_json_entry ** ini_section_entry_pp; if (zend_hash_find((*ini_section)->value.ht, name, name_len + 1, (void **) &ini_section_entry_pp) == SUCCESS) { ini_section_entry = *ini_section_entry_pp; } break; } } if (ini_section_entry) { switch (ini_section_entry->type) { case IS_LONG: ret = (double) ini_section_entry->value.lval; *exists = 1; break; case IS_DOUBLE: ret = ini_section_entry->value.dval; *exists = 1; break; case IS_STRING: ret = mysqlnd_ms_str_to_double(ini_section_entry->value.str.c, exists); break; case IS_ARRAY: { struct st_mysqlnd_ms_config_json_entry ** value; *is_list_value = 1; DBG_INF_FMT("the list has %d entries", zend_hash_num_elements(ini_section_entry->value.ht)); if (SUCCESS == zend_hash_get_current_data(ini_section_entry->value.ht, (void **)&value)) { switch ((*value)->type) { case IS_STRING: ret = mysqlnd_ms_str_to_double((*value)->value.str.c, exists); break; case IS_LONG: ret = (double) (*value)->value.lval; *exists = 1; break; case IS_DOUBLE: ret = (*value)->value.dval; *exists = 1; break; case IS_ARRAY: DBG_ERR("still unsupported type"); break; /* to do */ } zend_hash_move_forward(ini_section_entry->value.ht); } break; } default: php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " Unknown entry type %d in mysqlnd_ms_config_json_double", ini_section_entry->type); break; } } } /* if (zend_hash... */ } /* if (cfg->config) */ if (use_lock) { MYSQLND_MS_CONFIG_JSON_UNLOCK(cfg); } DBG_INF_FMT("ret=%d", ret); DBG_RETURN(ret); } /* }}} */ #endif /* {{{ mysqlnd_ms_config_json_reset_section */ PHPAPI void mysqlnd_ms_config_json_reset_section(struct st_mysqlnd_ms_config_json_entry * section, zend_bool recursive TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_config_json_reset_section"); DBG_INF_FMT("section=%p", section); if (section && section->type == IS_ARRAY && section->value.ht) { struct st_mysqlnd_ms_config_json_entry ** ini_section_entry; HashPosition pos; zend_hash_internal_pointer_reset_ex(section->value.ht, &pos); while (zend_hash_get_current_data_ex(section->value.ht, (void **) &ini_section_entry, &pos) == SUCCESS) { if (IS_ARRAY == (*ini_section_entry)->type && recursive) { mysqlnd_ms_config_json_reset_section((*ini_section_entry), recursive TSRMLS_CC); } zend_hash_move_forward_ex(section->value.ht, &pos); } zend_hash_internal_pointer_reset(section->value.ht); } DBG_VOID_RETURN; } /* }}} */ #ifdef ZTS /* {{{ mysqlnd_ms_config_json_lock */ PHPAPI void mysqlnd_ms_config_json_lock(struct st_mysqlnd_ms_json_config * cfg, const char * const file, unsigned int line TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_config_json_lock"); DBG_INF_FMT("mutex=%p file=%s line=%u", cfg->LOCK_access, file, line); tsrm_mutex_lock(cfg->LOCK_access); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_config_json_unlock */ PHPAPI void mysqlnd_ms_config_json_unlock(struct st_mysqlnd_ms_json_config * cfg, const char * const file, unsigned int line TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_config_json_unlock"); DBG_INF_FMT("mutex=%p file=%s line=%u", cfg->LOCK_access, file, line); tsrm_mutex_unlock(cfg->LOCK_access); DBG_VOID_RETURN; } /* }}} */ #endif /* {{{ mysqlnd_ms_config_json_string_is_bool_true */ zend_bool mysqlnd_ms_config_json_string_is_bool_false(const char * value) { if (!value) { return TRUE; } if (!strncmp("0", value, sizeof("0") - 1)) { return TRUE; } if (!strncasecmp("false", value, sizeof("false") - 1)) { return TRUE; } if (!strncasecmp("off", value, sizeof("off") - 1)) { return TRUE; } if (!strncasecmp("aus", value, sizeof("aus") - 1)) { return TRUE; } return FALSE; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_config_json.h0000664000175000017500000001224612161007456020161 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms_config_json.h 325340 2012-04-19 19:47:44Z andrey $ */ #ifndef MYSQLND_MS_CONFIG_JSON_H #define MYSQLND_MS_CONFIG_JSON_H struct st_mysqlnd_ms_json_config; struct st_mysqlnd_ms_config_json_entry; struct knv { char * key; union { union { char * s; size_t len; } str; long long lval; double dval; } value; }; PHPAPI struct st_mysqlnd_ms_json_config * mysqlnd_ms_config_json_init(TSRMLS_D); PHPAPI void mysqlnd_ms_config_json_free(struct st_mysqlnd_ms_json_config * cfg TSRMLS_DC); PHPAPI enum_func_status mysqlnd_ms_config_json_load_configuration(struct st_mysqlnd_ms_json_config * cfg TSRMLS_DC); PHPAPI zend_bool mysqlnd_ms_config_json_section_exists(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, ulong nkey, zend_bool use_lock TSRMLS_DC); PHPAPI zend_bool mysqlnd_ms_config_json_sub_section_exists(struct st_mysqlnd_ms_config_json_entry * main_section, const char * section, size_t section_len, ulong nkey TSRMLS_DC); #ifdef U0 /* TODO: never called */ PHPAPI char * mysqlnd_ms_config_json_string(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, const char * name, size_t name_len, zend_bool * exists, zend_bool * is_list_value, zend_bool use_lock TSRMLS_DC); #endif PHPAPI long long mysqlnd_ms_config_json_int(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, const char * name, size_t name_len, zend_bool * exists, zend_bool * is_list_value, zend_bool use_lock TSRMLS_DC); PHPAPI double mysqlnd_ms_config_json_double(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, const char * name, size_t name_len, zend_bool * exists, zend_bool * is_list_value, zend_bool use_lock TSRMLS_DC); PHPAPI void mysqlnd_ms_config_json_reset_section(struct st_mysqlnd_ms_config_json_entry * section, zend_bool recursive TSRMLS_DC); PHPAPI struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_config_json_section(struct st_mysqlnd_ms_json_config * cfg, const char * section, size_t section_len, zend_bool * exists TSRMLS_DC); PHPAPI struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_config_json_sub_section(struct st_mysqlnd_ms_config_json_entry *, const char * section, size_t section_len, zend_bool * exists TSRMLS_DC); PHPAPI zend_bool mysqlnd_ms_config_json_section_is_list(struct st_mysqlnd_ms_config_json_entry * TSRMLS_DC); PHPAPI zend_bool mysqlnd_ms_config_json_section_is_object_list(struct st_mysqlnd_ms_config_json_entry * section TSRMLS_DC); PHPAPI struct st_mysqlnd_ms_config_json_entry * mysqlnd_ms_config_json_next_sub_section(struct st_mysqlnd_ms_config_json_entry * main_section, char ** section_name, size_t * section_name_len, ulong * nkey TSRMLS_DC); PHPAPI char * mysqlnd_ms_config_json_string_from_section(struct st_mysqlnd_ms_config_json_entry * section, const char * name, size_t name_len, ulong nkey, zend_bool * exists, zend_bool * is_list_value TSRMLS_DC); PHPAPI int64_t mysqlnd_ms_config_json_int_from_section(struct st_mysqlnd_ms_config_json_entry * section, const char * name, size_t name_len, ulong nkey, zend_bool * exists, zend_bool * is_list_value TSRMLS_DC); zend_bool mysqlnd_ms_config_json_string_is_bool_false(const char * value); #ifdef ZTS PHPAPI void mysqlnd_ms_config_json_lock(struct st_mysqlnd_ms_json_config * cfg, const char * const file, unsigned int line TSRMLS_DC); PHPAPI void mysqlnd_ms_config_json_unlock(struct st_mysqlnd_ms_json_config * cfg, const char * const file, unsigned int line TSRMLS_DC); #define MYSQLND_MS_CONFIG_JSON_LOCK(cfg) mysqlnd_ms_config_json_lock((cfg), __FILE__, __LINE__ TSRMLS_CC) #define MYSQLND_MS_CONFIG_JSON_UNLOCK(cfg) mysqlnd_ms_config_json_unlock((cfg), __FILE__, __LINE__ TSRMLS_CC) #else #define MYSQLND_MS_CONFIG_JSON_LOCK(cfg) #define MYSQLND_MS_CONFIG_JSON_UNLOCK(cfg) #endif #endif /* MYSQLND_MS_CONFIG_JSON_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_enum_n_def.h0000664000175000017500000004273212161007456017765 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 311091 2011-05-16 15:42:48Z andrey $ */ #ifndef MYSQLND_MS_ENUM_N_DEF_H #define MYSQLND_MS_ENUM_N_DEF_H #if MYSQLND_VERSION_ID < 50010 && !defined(MYSQLND_CONN_DATA_DEFINED) typedef MYSQLND MYSQLND_CONN_DATA; #endif #if MYSQLND_VERSION_ID >= 50010 #define MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, connection) \ MYSQLND_MS_CONN_DATA ** conn_data = \ (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data((connection), mysqlnd_ms_plugin_id) #define MS_LOAD_CONN_DATA(conn_data, connection) \ (conn_data) = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data((connection), mysqlnd_ms_plugin_id) #define MS_CALL_ORIGINAL_CONN_HANDLE_METHOD(method) ms_orig_mysqlnd_conn_handle_methods->method #define MS_CALL_ORIGINAL_CONN_DATA_METHOD(method) ms_orig_mysqlnd_conn_methods->method extern struct st_mysqlnd_conn_data_methods * ms_orig_mysqlnd_conn_methods; extern struct st_mysqlnd_conn_methods * ms_orig_mysqlnd_conn_handle_methods; #else #define MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, connection) \ MYSQLND_MS_CONN_DATA ** conn_data = \ (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data((connection), mysqlnd_ms_plugin_id) #define MS_LOAD_CONN_DATA(conn_data, connection) \ (conn_data) = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data((connection), mysqlnd_ms_plugin_id) #define MS_CALL_ORIGINAL_CONN_HANDLE_METHOD(method) ms_orig_mysqlnd_conn_methods->method #define MS_CALL_ORIGINAL_CONN_DATA_METHOD(method) ms_orig_mysqlnd_conn_methods->method extern struct st_mysqlnd_conn_methods * ms_orig_mysqlnd_conn_methods; #endif #ifndef MYSQLND_HAS_INJECTION_FEATURE #define MS_LOAD_STMT_DATA(stmt_data, statement) \ (stmt_data) = (MYSQLND_MS_STMT_DATA **) mysqlnd_plugin_get_plugin_stmt_data((statement), mysqlnd_ms_plugin_id); #endif #if MYSQLND_VERSION_ID < 50010 #define MYSQLND_MS_ERROR_INFO(conn_object) ((conn_object)->error_info) #else #define MYSQLND_MS_ERROR_INFO(conn_object) (*((conn_object)->error_info)) #endif #if MYSQLND_VERSION_ID < 50010 #define MYSQLND_MS_UPSERT_STATUS(conn_object) ((conn_object)->upsert_status) #else #define MYSQLND_MS_UPSERT_STATUS(conn_object) (*((conn_object)->upsert_status)) #endif #define BEGIN_ITERATE_OVER_SERVER_LISTS(el, masters, slaves) \ { \ /* need to cast, as masters of slaves could be const. We use external llist_position, so this is safe */ \ DBG_INF_FMT("master(%p) has %d, slave(%p) has %d", \ (masters), zend_llist_count((zend_llist *) (masters)), (slaves), zend_llist_count((zend_llist *) (slaves))); \ { \ MYSQLND_MS_LIST_DATA ** el_pp;\ zend_llist * lists[] = {NULL, (masters), (zend_llist *) (slaves), NULL}; \ zend_llist ** list = lists; \ while (*++list) { \ zend_llist_position pos; \ /* search the list of easy handles hanging off the multi-handle */ \ for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(*list, &pos); \ el_pp && ((el) = *el_pp) && (el)->conn; \ el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(*list, &pos)) \ { \ #define END_ITERATE_OVER_SERVER_LISTS \ } \ } \ } \ } #define BEGIN_ITERATE_OVER_SERVER_LISTS_NEW(el, masters, slaves) \ { \ /* need to cast, as masters of slaves could be const. We use external llist_position, so this is safe */ \ DBG_INF_FMT("master(%p) has %d, slave(%p) has %d", \ (masters), zend_llist_count((zend_llist *) (masters)), (slaves), zend_llist_count((zend_llist *) (slaves))); \ { \ MYSQLND_MS_LIST_DATA ** el_pp; \ zend_llist * internal_master_list = (masters); \ zend_llist * internal_slave_list = (slaves); \ zend_llist * internal_list = internal_master_list; \ zend_llist_position pos; \ /* search the list of easy handles hanging off the multi-handle */ \ for ((el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(internal_list, &pos)) \ || ((internal_list = internal_slave_list) \ && \ (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(internal_list, &pos))) ; \ el_pp && ((el) = *el_pp) && (el)->conn; \ (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(internal_list, &pos)) \ || \ ( \ (internal_list == internal_master_list) \ && \ /* yes, we need an assignment */ \ (internal_list = internal_slave_list) \ && \ (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(internal_slave_list, &pos)) \ ) \ ) \ { \ #define END_ITERATE_OVER_SERVER_LISTS_NEW \ } \ } \ } #define BEGIN_ITERATE_OVER_SERVER_LIST(el, list) \ { \ /* need to cast, as this list could be const. We use external llist_position, so this is safe */ \ DBG_INF_FMT("list(%p) has %d", (list), zend_llist_count((zend_llist *) (list))); \ { \ MYSQLND_MS_LIST_DATA ** MACRO_el_pp;\ zend_llist_position MACRO_pos; \ /* search the list of easy handles hanging off the multi-handle */ \ for (((el) = NULL), MACRO_el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex((zend_llist *)(list), &MACRO_pos); \ MACRO_el_pp && ((el) = *MACRO_el_pp) && (el)->conn; \ ((el) = NULL), MACRO_el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex((zend_llist *)(list), &MACRO_pos)) \ { \ #define END_ITERATE_OVER_SERVER_LIST \ } \ } \ } #define MS_TIMEVAL_TO_UINT64(tp) (uint64_t)(tp.tv_sec*1000000 + tp.tv_usec) #define MS_TIME_SET(time_now) \ { \ struct timeval __tp = {0}; \ struct timezone __tz = {0}; \ gettimeofday(&__tp, &__tz); \ (time_now) = MS_TIMEVAL_TO_UINT64(__tp); \ } \ #define MS_TIME_DIFF(run_time) \ { \ uint64_t __now; \ MS_TIME_SET(__now); \ (run_time) = __now - (run_time); \ } \ #define MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, retval) \ if ((TRUE == (stgy)->in_transaction) && (TRUE == (stgy)->trx_stop_switching)) { \ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, \ MYSQLND_MS_ERROR_PREFIX " Automatic failover is not permitted in the middle of a transaction"); \ DBG_INF("In transaction, no switch allowed"); \ DBG_RETURN((retval)); \ } \ #define MASTER_SWITCH "ms=master" #define SLAVE_SWITCH "ms=slave" #define LAST_USED_SWITCH "ms=last_used" #define ALL_SERVER_SWITCH "ms=all" #define MASTER_NAME "master" #define SLAVE_NAME "slave" #define PICK_RANDOM "random" #define PICK_ONCE "sticky" #define PICK_RROBIN "roundrobin" #define PICK_USER "user" #define PICK_USER_MULTI "user_multi" #define PICK_TABLE "table" #define PICK_QOS "quality_of_service" #define PICK_GROUPS "node_groups" #define LAZY_NAME "lazy_connections" #define FAILOVER_NAME "failover" #define FAILOVER_STRATEGY_NAME "strategy" #define FAILOVER_STRATEGY_DISABLED "disabled" #define FAILOVER_STRATEGY_MASTER "master" #define FAILOVER_STRATEGY_LOOP "loop_before_master" #define FAILOVER_MAX_RETRIES "max_retries" #define FAILOVER_REMEMBER_FAILED "remember_failed" #define MASTER_ON_WRITE_NAME "master_on_write" #define TRX_STICKINESS_NAME "trx_stickiness" #define TRX_STICKINESS_MASTER "master" #define TRX_STICKINESS_ON "on" #define TABLE_RULES "rules" #define SECT_SERVER_CHARSET_NAME "server_charset" #define SECT_HOST_NAME "host" #define SECT_PORT_NAME "port" #define SECT_SOCKET_NAME "socket" #define SECT_USER_NAME "user" #define SECT_PASS_NAME "password" #define SECT_DB_NAME "db" #define SECT_CONNECT_FLAGS_NAME "connect_flags" #define SECT_FILTER_PRIORITY_NAME "priority" #define SECT_FILTER_NAME "filters" #define SECT_USER_CALLBACK "callback" #define SECT_QOS_STRONG "strong_consistency" #define SECT_QOS_SESSION "session_consistency" #define SECT_QOS_EVENTUAL "eventual_consistency" #define SECT_QOS_AGE "age" #define SECT_QOS_CACHE "cache" #define SECT_G_TRX_NAME "global_transaction_id_injection" #define SECT_G_TRX_ON_COMMIT "on_commit" #define SECT_G_TRX_REPORT_ERROR "report_error" #define SECT_G_TRX_FETCH_LAST_GTID "fetch_last_gtid" #define SECT_G_TRX_CHECK_FOR_GTID "check_for_gtid" #define SECT_G_TRX_WAIT_FOR_GTID_TIMEOUT "wait_for_gtid_timeout" #define SECT_LB_WEIGHTS "weights" typedef enum { STATEMENT_SELECT, STATEMENT_INSERT, STATEMENT_UPDATE, STATEMENT_DELETE, STATEMENT_TRUNCATE, STATEMENT_REPLACE, STATEMENT_RENAME, STATEMENT_ALTER, STATEMENT_DROP, STATEMENT_CREATE } enum_mysql_statement_type; enum enum_which_server { USE_MASTER, USE_SLAVE, USE_LAST_USED, USE_ALL }; enum mysqlnd_ms_server_pick_strategy { SERVER_PICK_RROBIN, SERVER_PICK_RANDOM, SERVER_PICK_USER, SERVER_PICK_USER_MULTI, SERVER_PICK_TABLE, SERVER_PICK_QOS, SERVER_PICK_GROUPS, SERVER_PICK_LAST_ENUM_ENTRY }; /* it should work also without any params, json config to the ctor will be NULL */ #define DEFAULT_PICK_STRATEGY SERVER_PICK_RANDOM enum mysqlnd_ms_server_failover_strategy { SERVER_FAILOVER_DISABLED, SERVER_FAILOVER_MASTER, SERVER_FAILOVER_LOOP }; #define DEFAULT_FAILOVER_STRATEGY SERVER_FAILOVER_DISABLED #define DEFAULT_FAILOVER_MAX_RETRIES 1 #define DEFAULT_FAILOVER_REMEMBER_FAILED 0 enum mysqlnd_ms_trx_stickiness_strategy { TRX_STICKINESS_STRATEGY_DISABLED, TRX_STICKINESS_STRATEGY_MASTER, TRX_STICKINESS_STRATEGY_ON }; #define DEFAULT_TRX_STICKINESS_STRATEGY TRX_STICKINESS_STRATEGY_DISABLED typedef enum mysqlnd_ms_collected_stats { MS_STAT_USE_SLAVE, MS_STAT_USE_MASTER, MS_STAT_USE_SLAVE_GUESS, MS_STAT_USE_MASTER_GUESS, MS_STAT_USE_SLAVE_FORCED, MS_STAT_USE_MASTER_FORCED, MS_STAT_USE_LAST_USED_FORCED, MS_STAT_USE_SLAVE_CALLBACK, MS_STAT_USE_MASTER_CALLBACK, MS_STAT_NON_LAZY_CONN_SLAVE_SUCCESS, MS_STAT_NON_LAZY_CONN_SLAVE_FAILURE, MS_STAT_NON_LAZY_CONN_MASTER_SUCCESS, MS_STAT_NON_LAZY_CONN_MASTER_FAILURE, MS_STAT_LAZY_CONN_SLAVE_SUCCESS, MS_STAT_LAZY_CONN_SLAVE_FAILURE, MS_STAT_LAZY_CONN_MASTER_SUCCESS, MS_STAT_LAZY_CONN_MASTER_FAILURE, MS_STAT_TRX_AUTOCOMMIT_ON, MS_STAT_TRX_AUTOCOMMIT_OFF, MS_STAT_TRX_MASTER_FORCED, #ifndef MYSQLND_HAS_INJECTION_FEATURE MS_STAT_GTID_AUTOCOMMIT_SUCCESS, MS_STAT_GTID_AUTOCOMMIT_FAILURE, MS_STAT_GTID_COMMIT_SUCCESS, MS_STAT_GTID_COMMIT_FAILURE, MS_STAT_GTID_IMPLICIT_COMMIT_SUCCESS, MS_STAT_GTID_IMPLICIT_COMMIT_FAILURE, #endif MS_STAT_LAST /* Should be always the last */ } enum_mysqlnd_ms_collected_stats; #define MYSQLND_MS_INC_STATISTIC(stat) MYSQLND_INC_STATISTIC(MYSQLND_MS_G(collect_statistics), mysqlnd_ms_stats, (stat)) #define MYSQLND_MS_INC_STATISTIC_W_VALUE(stat, value) MYSQLND_INC_STATISTIC_W_VALUE(MYSQLND_MS_G(collect_statistics), mysqlnd_ms_stats, (stat), (value)) typedef struct st_mysqlnd_ms_list_data { char * name_from_config; MYSQLND_CONN_DATA * conn; char * host; char * user; char * passwd; size_t passwd_len; unsigned int port; char * socket; char * db; size_t db_len; unsigned long connect_flags; char * emulated_scheme; size_t emulated_scheme_len; zend_bool persistent; } MYSQLND_MS_LIST_DATA; typedef struct st_mysqlnd_ms_filter_data { void (*filter_dtor)(struct st_mysqlnd_ms_filter_data * TSRMLS_DC); char * name; size_t name_len; enum mysqlnd_ms_server_pick_strategy pick_type; zend_bool multi_filter; zend_bool persistent; } MYSQLND_MS_FILTER_DATA; typedef struct st_mysqlnd_ms_filter_user_data { MYSQLND_MS_FILTER_DATA parent; zval * user_callback; zend_bool callback_valid; } MYSQLND_MS_FILTER_USER_DATA; typedef struct st_mysqlnd_ms_filter_table_data { MYSQLND_MS_FILTER_DATA parent; HashTable master_rules; HashTable slave_rules; } MYSQLND_MS_FILTER_TABLE_DATA; typedef struct st_mysqlnd_ms_filter_rr_data { MYSQLND_MS_FILTER_DATA parent; HashTable master_context; HashTable slave_context; HashTable lb_weight; } MYSQLND_MS_FILTER_RR_DATA; typedef struct st_mysqlnd_ms_filter_rr_context { unsigned int pos; zend_llist weight_list; } MYSQLND_MS_FILTER_RR_CONTEXT; typedef struct st_mysqlnd_ms_filter_lb_weight { unsigned int weight; unsigned int current_weight; zend_bool persistent; } MYSQLND_MS_FILTER_LB_WEIGHT; typedef struct st_mysqlnd_ms_filter_lb_weight_in_context { MYSQLND_MS_FILTER_LB_WEIGHT * lb_weight; MYSQLND_MS_LIST_DATA * element; } MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT; typedef struct st_mysqlnd_ms_filter_random_lb_context { zend_llist sort_list; unsigned int total_weight; } MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT; typedef struct st_mysqlnd_ms_filter_random_data { MYSQLND_MS_FILTER_DATA parent; struct { HashTable master_context; HashTable slave_context; zend_bool once; } sticky; HashTable lb_weight; struct { HashTable master_context; HashTable slave_context; } weight_context; } MYSQLND_MS_FILTER_RANDOM_DATA; enum mysqlnd_ms_filter_qos_consistency { CONSISTENCY_STRONG, CONSISTENCY_SESSION, CONSISTENCY_EVENTUAL, CONSISTENCY_LAST_ENUM_ENTRY }; enum mysqlnd_ms_filter_qos_option { QOS_OPTION_NONE, QOS_OPTION_GTID, QOS_OPTION_AGE, QOS_OPTION_CACHE, QOS_OPTION_LAST_ENUM_ENTRY }; /* using struct because we will likely add cache ttl later */ typedef struct st_mysqlnd_ms_filter_qos_option_data { char * gtid; size_t gtid_len; long age; uint ttl; } MYSQLND_MS_FILTER_QOS_OPTION_DATA; typedef struct st_mysqlnd_ms_filter_qos_data { MYSQLND_MS_FILTER_DATA parent; enum mysqlnd_ms_filter_qos_consistency consistency; enum mysqlnd_ms_filter_qos_option option; MYSQLND_MS_FILTER_QOS_OPTION_DATA option_data; } MYSQLND_MS_FILTER_QOS_DATA; typedef struct st_mysqlnd_ms_filter_groups_data { MYSQLND_MS_FILTER_DATA parent; HashTable groups; } MYSQLND_MS_FILTER_GROUPS_DATA; typedef struct st_mysqlnd_ms_filter_groups_data_group { HashTable master_context; HashTable slave_context; } MYSQLND_MS_FILTER_GROUPS_DATA_GROUP; /* NOTE: Some elements are available with every connection, some are set for the global/proxy connection only. The global/proxy connection is the handle provided by the user. The other connections are the "hidden" ones that MS openes to the cluster nodes. */ typedef struct st_mysqlnd_ms_conn_data { zend_bool initialized; zend_bool skip_ms_calls; MYSQLND_CONN_DATA * proxy_conn; char * connect_host; zend_llist master_connections; zend_llist slave_connections; const MYSQLND_CHARSET * server_charset; /* Global LB strategy set on proxy conn */ struct mysqlnd_ms_lb_strategies { HashTable table_filters; enum mysqlnd_ms_server_failover_strategy failover_strategy; uint failover_max_retries; zend_bool failover_remember_failed; HashTable failed_hosts; zend_bool mysqlnd_ms_flag_master_on_write; zend_bool master_used; /* note: some flags may not be used, however saves us a ton of ifdef to declare them anyway */ enum mysqlnd_ms_trx_stickiness_strategy trx_stickiness_strategy; zend_bool trx_stop_switching; zend_bool trx_read_only; zend_bool trx_autocommit_off; /* buffered tx_begin call */ zend_bool trx_begin_required; unsigned int trx_begin_mode; char * trx_begin_name; zend_bool in_transaction; MYSQLND_CONN_DATA * last_used_conn; MYSQLND_CONN_DATA * random_once_slave; zend_llist * filters; } stgy; struct st_mysqlnd_ms_conn_credentials { char * user; char * passwd; size_t passwd_len; char * db; size_t db_len; unsigned int port; char * socket; unsigned long mysql_flags; } cred; #ifndef MYSQLND_HAS_INJECTION_FEATURE /* per connection trx context set on proxy conn and all others */ struct st_mysqlnd_ms_global_trx_injection { char * on_commit; size_t on_commit_len; char * fetch_last_gtid; size_t fetch_last_gtid_len; char * check_for_gtid; size_t check_for_gtid_len; unsigned int wait_for_gtid_timeout; /* TODO: This seems to be the only per-connection value. We may want to split up the structure into a global and local part. is_master needs to be local/per-connection. The rest could probably be global, like with stgy and LB weigth. */ zend_bool is_master; zend_bool report_error; } global_trx; #endif } MYSQLND_MS_CONN_DATA; typedef struct st_mysqlnd_ms_table_filter { char * host_id; size_t host_id_len; char * wild; size_t wild_len; #ifdef WE_NEED_NEXT struct st_mysqlnd_ms_table_filter * next; #endif unsigned int priority; zend_bool persistent; } MYSQLND_MS_TABLE_FILTER; typedef struct st_mysqlnd_ms_command { enum php_mysqlnd_server_command command; zend_uchar * payload; size_t payload_len; enum mysqlnd_packet_type ok_packet; zend_bool silent; zend_bool ignore_upsert_status; zend_bool persistent; } MYSQLND_MS_COMMAND; #endif /* MYSQLND_MS_ENUM_N_DEF_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_groups.c0000664000175000017500000003420212161007456020536 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Ulf Wendel | | Andrey Hristov | +----------------------------------------------------------------------+ */ /* $Id: $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/info.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_config_json.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_switch.h" #include "mysqlnd_query_parser.h" #include "mysqlnd_qp.h" /* {{{ groups_filter_dtor */ static void groups_filter_dtor(struct st_mysqlnd_ms_filter_data * pDest TSRMLS_DC) { MYSQLND_MS_FILTER_GROUPS_DATA * filter = (MYSQLND_MS_FILTER_GROUPS_DATA *) pDest; DBG_ENTER("groups_filter_dtor"); if (&filter->groups) { zend_hash_destroy(&filter->groups); } mnd_pefree(filter, filter->parent.persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_filter_groups_ht_dtor */ void mysqlnd_ms_filter_groups_ht_dtor(void * pDest) { MYSQLND_MS_FILTER_GROUPS_DATA_GROUP * element = pDest? *(MYSQLND_MS_FILTER_GROUPS_DATA_GROUP **) pDest : NULL; TSRMLS_FETCH(); DBG_ENTER("mysqlnd_ms_filter_groups_ht_dtor"); zend_hash_destroy(&element->master_context); zend_hash_destroy(&element->slave_context); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_groups_filter_ctor */ MYSQLND_MS_FILTER_DATA * mysqlnd_ms_groups_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { MYSQLND_MS_FILTER_GROUPS_DATA * ret = NULL; MYSQLND_MS_LIST_DATA * entry, **entry_pp; zend_llist_position pos; DBG_ENTER("mysqlnd_ms_groups_filter_ctor"); DBG_INF_FMT("section=%p", section); if (section) { ret = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_GROUPS_DATA), persistent); if (ret) { ret->parent.filter_dtor = groups_filter_dtor; zend_hash_init(&ret->groups, 4, NULL/*hash*/, mysqlnd_ms_filter_groups_ht_dtor, persistent); if ((TRUE == mysqlnd_ms_config_json_section_is_list(section TSRMLS_CC) && TRUE == mysqlnd_ms_config_json_section_is_object_list(section TSRMLS_CC))) { /* node_groups => array(GROUP_NAME_A => ...) */ struct st_mysqlnd_ms_config_json_entry * subsection = NULL; HashTable server_names; /* 1) build list of all server names from config - note that names must be globally unique */ zend_hash_init(&server_names, 4, NULL/*hash*/, NULL/*dtor*/, FALSE); for (entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(master_connections, &pos); entry_pp && (entry = *entry_pp) && (entry->name_from_config) && (entry->conn); entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(master_connections, &pos)) { if (SUCCESS != zend_hash_add(&server_names, entry->name_from_config, strlen(entry->name_from_config) + 1, entry_pp, sizeof(void *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to setup master server list for '%s' filter. Stopping", PICK_GROUPS); } } for (entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(slave_connections, &pos); entry_pp && (entry = *entry_pp) && (entry->name_from_config) && (entry->conn); entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(slave_connections, &pos)) { if (SUCCESS != zend_hash_add(&server_names, entry->name_from_config, strlen(entry->name_from_config) + 1, entry_pp, sizeof(void *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to setup slave server list for '%s' filter. Stopping", PICK_GROUPS); } } DBG_INF_FMT("server name list has %d entries", zend_hash_num_elements(&server_names)); /* 2. iterate over node_group names */ do { char * current_group_name = NULL; size_t current_group_name_len = 0; char * server_name = NULL; size_t server_name_len = 0; struct st_mysqlnd_ms_config_json_entry * serversection = NULL; zend_bool section_exists; zend_bool is_list; MYSQLND_MS_FILTER_GROUPS_DATA_GROUP * node_group = NULL; subsection = mysqlnd_ms_config_json_next_sub_section(section, ¤t_group_name, ¤t_group_name_len, NULL TSRMLS_CC); if (!subsection) { break; } DBG_INF_FMT("checking node group '%s'", current_group_name); /* 3. for each node_group parse out master and slave servers */ node_group = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_GROUPS_DATA_GROUP), persistent); if (!node_group) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to allocate memory to create node group '%s' for '%s' filter. Stopping", current_group_name, PICK_GROUPS); mnd_pefree(node_group, persistent); break; } /* TODO: dtor needed? Seems not to be the case */ zend_hash_init(&node_group->master_context, 4, NULL/*hash*/, NULL/*dtor*/, persistent); zend_hash_init(&node_group->slave_context, 4, NULL/*hash*/, NULL/*dtor*/, persistent); if (SUCCESS != zend_hash_add(&ret->groups, current_group_name, current_group_name_len, &node_group, sizeof(MYSQLND_MS_FILTER_GROUPS_DATA_GROUP *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to create node group '%s' for '%s' filter. Stopping", current_group_name, PICK_GROUPS); mnd_pefree(node_group, persistent); break; } /* 3.1 masters */ serversection = mysqlnd_ms_config_json_sub_section(subsection, MASTER_NAME, sizeof(MASTER_NAME) - 1, §ion_exists TSRMLS_CC); if (section_exists && serversection) { ulong nkey = 0; server_name = NULL; do { server_name = mysqlnd_ms_config_json_string_from_section(serversection, NULL, 0, nkey, §ion_exists, &is_list TSRMLS_CC); if (section_exists && server_name) { server_name_len = strlen(server_name) + 1; if (SUCCESS != zend_hash_find(&server_names, server_name, server_name_len, (void **)&entry_pp)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Unknown master '%s' (section '%s') in '%s' filter configuration. Stopping", server_name, current_group_name, PICK_GROUPS); mnd_efree(server_name); continue; } if (SUCCESS != zend_hash_add(&node_group->master_context, server_name, server_name_len, &server_name, sizeof(char *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to add master '%s' to node group '%s' for '%s' filter. Stopping", server_name, current_group_name, PICK_GROUPS); mnd_efree(server_name); continue; } mnd_efree(server_name); } } while (section_exists && ++nkey); DBG_INF_FMT("added '%d' masters", zend_hash_num_elements(&node_group->master_context)); } if ((zend_llist_count(master_connections) > 0) && (0 == zend_hash_num_elements(&node_group->master_context))) { /* A user may not configure any slaves if using multi-master setup. Unfortunately we don't know whether multi-master is on or not. Thus, no check and warning in the slave section below. However, configuring masters but not naming any in a group section stinks. */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " No masters configured in node group '%s' for '%s' filter. Please, verify the setup", current_group_name, PICK_GROUPS); } /* 3.1 slaves */ serversection = mysqlnd_ms_config_json_sub_section(subsection, SLAVE_NAME, sizeof(SLAVE_NAME) - 1, §ion_exists TSRMLS_CC); if (section_exists && serversection) { ulong nkey = 0; server_name = NULL; do { server_name = mysqlnd_ms_config_json_string_from_section(serversection, NULL, 0, nkey, §ion_exists, &is_list TSRMLS_CC); if (section_exists && server_name) { server_name_len = strlen(server_name) + 1; if (SUCCESS != zend_hash_find(&server_names, server_name, server_name_len, (void **)&entry_pp)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Unknown slave '%s' (section '%s') in '%s' filter configuration. Stopping", server_name, current_group_name, PICK_GROUPS); mnd_efree(server_name); continue; } if (SUCCESS != zend_hash_add(&node_group->slave_context, server_name, server_name_len, &server_name, sizeof(char *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to add slave '%s' to node group '%s' for '%s' filter. Stopping", server_name, current_group_name, PICK_GROUPS); mnd_efree(server_name); continue; } mnd_efree(server_name); } } while (section_exists && ++nkey); DBG_INF_FMT("added '%d' slaves", zend_hash_num_elements(&node_group->slave_context)); } } while (1); zend_hash_destroy(&server_names); } } } DBG_RETURN((MYSQLND_MS_FILTER_DATA *) ret); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_groups */ enum_func_status mysqlnd_ms_choose_connection_groups(MYSQLND_CONN_DATA * conn, void * f_data, const char * connect_host, char ** query, size_t * query_len, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { enum_func_status ret = PASS; MYSQLND_MS_FILTER_GROUPS_DATA * filter_data = (MYSQLND_MS_FILTER_GROUPS_DATA *) f_data; MYSQLND_MS_LIST_DATA * element; DBG_ENTER("mysqlnd_ms_choose_connection_groups"); if (filter_data && (&filter_data->groups) && (query_len > 0)) { MYSQLND_MS_FILTER_GROUPS_DATA_GROUP *node_group, **node_group_pp; struct st_ms_token_and_value token = {0}; struct st_mysqlnd_query_scanner * scanner; zend_bool found = FALSE; char ** server_name_pp; scanner = mysqlnd_qp_create_scanner(TSRMLS_C); mysqlnd_qp_set_string(scanner, *query, *query_len TSRMLS_CC); token = mysqlnd_qp_get_token(scanner TSRMLS_CC); DBG_INF_FMT("token=COMMENT? = %d", token.token == QC_TOKEN_COMMENT); while (token.token == QC_TOKEN_COMMENT) { if (SUCCESS == zend_hash_find(&filter_data->groups, Z_STRVAL(token.value), Z_STRLEN(token.value) - 1, (void **)&node_group_pp)) { DBG_INF_FMT("node_group=%s", Z_STRVAL(token.value)); found = TRUE; break; } zval_dtor(&token.value); token = mysqlnd_qp_get_token(scanner TSRMLS_CC); } zval_dtor(&token.value); mysqlnd_qp_free_scanner(scanner TSRMLS_CC); if (FALSE == found) { goto use_all; } /* TODO: check if HTs exist? */ node_group = *node_group_pp; DBG_INF_FMT("%d masters, %d slaves in group", zend_hash_num_elements(&node_group->master_context), zend_hash_num_elements(&node_group->slave_context)); /* Note: the way we write the loop probably determines the rr selection order. We shall use input sort order. No re-ordering! */ BEGIN_ITERATE_OVER_SERVER_LIST(element, master_list) if (element && element->name_from_config) { if ((SUCCESS == zend_hash_find(&node_group->master_context, element->name_from_config, strlen(element->name_from_config) + 1, (void **)&server_name_pp))) { zend_llist_add_element(selected_masters, &element); } } END_ITERATE_OVER_SERVER_LIST; BEGIN_ITERATE_OVER_SERVER_LIST(element, slave_list) if (element && element->name_from_config) { if ((SUCCESS == zend_hash_find(&node_group->slave_context, element->name_from_config, strlen(element->name_from_config) + 1, (void **)&server_name_pp))) { zend_llist_add_element(selected_slaves, &element); } } END_ITERATE_OVER_SERVER_LIST; DBG_RETURN(ret); } use_all: DBG_INF("Using all servers"); BEGIN_ITERATE_OVER_SERVER_LIST(element, master_list) zend_llist_add_element(selected_masters, &element); END_ITERATE_OVER_SERVER_LIST; BEGIN_ITERATE_OVER_SERVER_LIST(element, slave_list) zend_llist_add_element(selected_slaves, &element); END_ITERATE_OVER_SERVER_LIST; DBG_RETURN(ret); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_groups.h0000664000175000017500000000411612161007456020544 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: $ */ #ifndef MYSQLND_MS_FILTER_GROUPS_H #define MYSQLND_MS_FILTER_GROUPS_H struct mysqlnd_ms_lb_strategies; enum_func_status mysqlnd_ms_choose_connection_groups(MYSQLND_CONN_DATA * conn, void * f_data, const char * connect_host, char ** query, size_t * query_len, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC); MYSQLND_MS_FILTER_DATA * mysqlnd_ms_groups_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); #endif /* MYSQLND_MS_FILTER_GROUPS_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_qos.c0000664000175000017500000006411012161007456020022 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Ulf Wendel | | Andrey Hristov | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 311179 2011-05-18 11:26:22Z andrey $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/info.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #ifdef MYSQLND_MS_HAVE_MYSQLND_QC #include "ext/mysqlnd_qc/mysqlnd_qc.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_config_json.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_switch.h" /* {{{ qos_filter_dtor */ static void qos_filter_dtor(struct st_mysqlnd_ms_filter_data * pDest TSRMLS_DC) { MYSQLND_MS_FILTER_QOS_DATA * filter = (MYSQLND_MS_FILTER_QOS_DATA *) pDest; DBG_ENTER("qos_filter_dtor"); if (filter->option_data.gtid_len) efree(filter->option_data.gtid); mnd_pefree(filter, filter->parent.persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_qos_filter_ctor */ MYSQLND_MS_FILTER_DATA * mysqlnd_ms_qos_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { MYSQLND_MS_FILTER_QOS_DATA * ret; DBG_ENTER("mysqlnd_ms_qos_filter_ctor"); DBG_INF_FMT("section=%p", section); if (section) { ret = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_QOS_DATA), persistent); if (ret) { zend_bool value_exists = FALSE, is_list_value = FALSE; char * service; ret->parent.filter_dtor = qos_filter_dtor; ret->consistency = CONSISTENCY_LAST_ENUM_ENTRY; service = mysqlnd_ms_config_json_string_from_section(section, SECT_QOS_STRONG, sizeof(SECT_QOS_STRONG) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { DBG_INF("strong consistency"); mnd_efree(service); ret->consistency = CONSISTENCY_STRONG; } service = mysqlnd_ms_config_json_string_from_section(section, SECT_QOS_SESSION, sizeof(SECT_QOS_SESSION) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { DBG_INF("session consistency"); mnd_efree(service); if (ret->consistency != CONSISTENCY_LAST_ENUM_ENTRY) { mnd_pefree(ret, persistent); php_error_docref(NULL TSRMLS_CC, E_ERROR, MYSQLND_MS_ERROR_PREFIX " Error by creating filter '%s', '%s' clashes with previous setting. Stopping", PICK_QOS, SECT_QOS_SESSION); } else { ret->consistency = CONSISTENCY_SESSION; } } service = mysqlnd_ms_config_json_string_from_section(section, SECT_QOS_EVENTUAL, sizeof(SECT_QOS_EVENTUAL) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { DBG_INF("eventual consistency"); mnd_efree(service); if (ret->consistency != CONSISTENCY_LAST_ENUM_ENTRY) { mnd_pefree(ret, persistent); php_error_docref(NULL TSRMLS_CC, E_ERROR, MYSQLND_MS_ERROR_PREFIX " Error by creating filter '%s', '%s' clashes with previous setting. Stopping", PICK_QOS, SECT_QOS_EVENTUAL); } else { ret->consistency = CONSISTENCY_EVENTUAL; if (TRUE == is_list_value) { zend_bool section_exists; struct st_mysqlnd_ms_config_json_entry * eventual_section = mysqlnd_ms_config_json_sub_section(section, SECT_QOS_EVENTUAL, sizeof(SECT_QOS_EVENTUAL) - 1, §ion_exists TSRMLS_CC); if (section_exists && eventual_section) { char * json_value; json_value = mysqlnd_ms_config_json_string_from_section(eventual_section, SECT_QOS_AGE, sizeof(SECT_QOS_AGE) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists && json_value) { ret->option = QOS_OPTION_AGE; ret->option_data.age = atol(json_value); mnd_efree(json_value); } json_value = mysqlnd_ms_config_json_string_from_section(eventual_section, SECT_QOS_CACHE, sizeof(SECT_QOS_CACHE) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists && json_value) { if (QOS_OPTION_AGE == ret->option) { mnd_pefree(ret, persistent); mnd_efree(json_value); php_error_docref(NULL TSRMLS_CC, E_ERROR, MYSQLND_MS_ERROR_PREFIX " Error by creating filter '%s', '%s' has conflicting entries for cache and age. Stopping", PICK_QOS, SECT_QOS_EVENTUAL); } else { ret->option = QOS_OPTION_CACHE; /* TODO - Andrey, do we need range checks? */ ret->option_data.ttl = (uint)atol(json_value); mnd_efree(json_value); } } } } } } switch (ret->consistency) { case CONSISTENCY_STRONG: case CONSISTENCY_SESSION: case CONSISTENCY_EVENTUAL: break; default: mnd_pefree(ret, persistent); ret = NULL; php_error_docref(NULL TSRMLS_CC, E_ERROR, MYSQLND_MS_ERROR_PREFIX " Error by creating filter '%s', can't find section '%s', '%s' or '%s' . Stopping", PICK_QOS, SECT_QOS_STRONG, SECT_QOS_SESSION, SECT_QOS_EVENTUAL); } } } DBG_RETURN((MYSQLND_MS_FILTER_DATA *) ret); } /* }}} */ /* {{{ mysqlnd_ms_qos_server_has_gtid */ static enum_func_status mysqlnd_ms_qos_server_has_gtid(MYSQLND_CONN_DATA * conn, MYSQLND_MS_CONN_DATA ** conn_data, char *sql, size_t sql_len, unsigned int wait_time, MYSQLND_ERROR_INFO * tmp_error_info TSRMLS_DC) { MYSQLND_RES * res = NULL; enum_func_status ret = FAIL; uint64_t total_time = 0, run_time = 0, my_wait_time = wait_time * 1000000; #if MYSQLND_VERSION_ID >= 50010 MYSQLND_ERROR_INFO * org_error_info; #else MYSQLND_ERROR_INFO org_error_info; #endif DBG_ENTER("mysqlnd_ms_qos_server_has_gtid"); DBG_INF_FMT("wait_time=%d", wait_time); /* hide errors from user */ org_error_info = conn->error_info; #if MYSQLND_VERSION_ID >= 50010 conn->error_info = tmp_error_info; #else SET_EMPTY_ERROR(conn->error_info); #endif (*conn_data)->skip_ms_calls = TRUE; if (wait_time) { MS_TIME_SET(run_time); } do { if ((PASS == MS_CALL_ORIGINAL_CONN_DATA_METHOD(send_query)(conn, sql, sql_len TSRMLS_CC)) && (PASS == MS_CALL_ORIGINAL_CONN_DATA_METHOD(reap_query)(conn TSRMLS_CC)) && (res = MS_CALL_ORIGINAL_CONN_DATA_METHOD(store_result)(conn TSRMLS_CC))) { ret = (MYSQLND_MS_UPSERT_STATUS(conn).affected_rows) ? PASS : FAIL; DBG_INF_FMT("sql = %s - ret = %d - affected_rows = %d", sql, ret, (MYSQLND_MS_UPSERT_STATUS(conn).affected_rows)); } if (wait_time && (FAIL == ret)) { MS_TIME_DIFF(run_time); total_time += run_time; if (my_wait_time > total_time) { /* Server has not caught up yet but we are told to wait (throttle ourselves) and there is wait time left. NOTE: If the user is using any kind of SQL-level waits we will not notice and loop until the external */ DBG_INF_FMT("sleep and retry, time left=" MYSQLND_LLU_SPEC, (my_wait_time - total_time)); MS_TIME_SET(run_time); sleep(1); if (res) { res->m.free_result(res, FALSE TSRMLS_CC); } continue; } } break; } while (1); (*conn_data)->skip_ms_calls = FALSE; #if MYSQLND_VERSION_ID < 50010 *tmp_error_info = conn->error_info; #endif conn->error_info = org_error_info; if (res) { res->m.free_result(res, FALSE TSRMLS_CC); } DBG_RETURN(ret); } /* }}} */ #define SHOW_SS_QUERY "SHOW SLAVE STATUS" /* {{{ mysqlnd_ms_qos_server_get_lag_stage1 */ enum_func_status mysqlnd_ms_qos_server_get_lag_stage1(MYSQLND_CONN_DATA * conn, MYSQLND_MS_CONN_DATA ** conn_data, MYSQLND_ERROR_INFO * tmp_error_info TSRMLS_DC) { enum_func_status ret; #if MYSQLND_VERSION_ID >= 50010 MYSQLND_ERROR_INFO * org_error_info; #else MYSQLND_ERROR_INFO org_error_info; #endif DBG_ENTER("mysqlnd_ms_qos_server_get_lag_stage1"); /* hide errors from user */ org_error_info = conn->error_info; #if MYSQLND_VERSION_ID >= 50010 conn->error_info = tmp_error_info; #else SET_EMPTY_ERROR(conn->error_info); #endif (*conn_data)->skip_ms_calls = TRUE; ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(send_query)(conn, SHOW_SS_QUERY , sizeof(SHOW_SS_QUERY) - 1 TSRMLS_CC); (*conn_data)->skip_ms_calls = FALSE; #if MYSQLND_VERSION_ID < 50010 *tmp_error_info = conn->error_info; #endif conn->error_info = org_error_info; DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_qos_get_lag_stage2 */ static long mysqlnd_ms_qos_server_get_lag_stage2(MYSQLND_CONN_DATA * conn, MYSQLND_MS_CONN_DATA ** conn_data, MYSQLND_ERROR_INFO * tmp_error_info TSRMLS_DC) { MYSQLND_RES * res = NULL; long lag = -1L; #if MYSQLND_VERSION_ID >= 50010 MYSQLND_ERROR_INFO * org_error_info; #else MYSQLND_ERROR_INFO org_error_info; #endif DBG_ENTER("mysqlnd_ms_qos_server_get_lag_stage2"); /* hide errors from user */ org_error_info = conn->error_info; #if MYSQLND_VERSION_ID >= 50010 conn->error_info = tmp_error_info; #else SET_EMPTY_ERROR(conn->error_info); #endif (*conn_data)->skip_ms_calls = TRUE; if ((PASS == MS_CALL_ORIGINAL_CONN_DATA_METHOD(reap_query)(conn TSRMLS_CC)) && (res = MS_CALL_ORIGINAL_CONN_DATA_METHOD(store_result)(conn TSRMLS_CC))) { zval * row; zval ** seconds_behind_master; zval ** io_running; zval ** sql_running; MAKE_STD_ZVAL(row); mysqlnd_fetch_into(res, MYSQLND_FETCH_ASSOC, row, MYSQLND_MYSQL); if (Z_TYPE_P(row) == IS_ARRAY) { /* TODO: make test incasesensitive */ if (FAILURE == zend_hash_find(Z_ARRVAL_P(row), "Slave_IO_Running", sizeof("Slave_IO_Running"), (void**)&io_running)) { SET_CLIENT_ERROR((*tmp_error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Failed to extract Slave_IO_Running"); goto getlagsqlerror; } if ((Z_TYPE_PP(io_running) != IS_STRING) || (0 != strncasecmp(Z_STRVAL_PP(io_running), "Yes", Z_STRLEN_PP(io_running)))) { SET_CLIENT_ERROR((*tmp_error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Slave_IO_Running is not 'Yes'"); goto getlagsqlerror; } if (FAILURE == zend_hash_find(Z_ARRVAL_P(row), "Slave_SQL_Running", sizeof("Slave_SQL_Running"), (void**)&sql_running)) { SET_CLIENT_ERROR((*tmp_error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Failed to extract Slave_SQL_Running"); goto getlagsqlerror; } if ((Z_TYPE_PP(io_running) != IS_STRING) || (0 != strncasecmp(Z_STRVAL_PP(sql_running), "Yes", Z_STRLEN_PP(sql_running)))) { SET_CLIENT_ERROR((*tmp_error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Slave_SQL_Running is not 'Yes'"); goto getlagsqlerror; } if (FAILURE == zend_hash_find(Z_ARRVAL_P(row), "Seconds_Behind_Master", sizeof("Seconds_Behind_Master"), (void**)&seconds_behind_master)) { SET_CLIENT_ERROR((*tmp_error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Failed to extract Seconds_Behind_Master"); goto getlagsqlerror; } lag = Z_LVAL_PP(seconds_behind_master); } getlagsqlerror: zval_ptr_dtor(&row); } (*conn_data)->skip_ms_calls = FALSE; #if MYSQLND_VERSION_ID < 50010 *tmp_error_info = conn->error_info; #endif conn->error_info = org_error_info; if (res) { res->m.free_result(res, FALSE TSRMLS_CC); } DBG_RETURN(lag); } /* }}} */ /* {{{ mysqlnd_ms_qos_which_server */ static enum enum_which_server mysqlnd_ms_qos_which_server(const char * query, size_t query_len, struct mysqlnd_ms_lb_strategies * stgy TSRMLS_DC) { zend_bool forced; enum enum_which_server which_server = mysqlnd_ms_query_is_select(query, query_len, &forced TSRMLS_CC); DBG_ENTER("mysqlnd_ms_qos_which_server"); if ((stgy->trx_stickiness_strategy == TRX_STICKINESS_STRATEGY_MASTER) && stgy->in_transaction && !forced) { DBG_INF("Enforcing use of master while in transaction"); which_server = USE_MASTER; } else if (stgy->mysqlnd_ms_flag_master_on_write) { if (which_server != USE_MASTER) { if (stgy->master_used && !forced) { switch (which_server) { case USE_MASTER: case USE_LAST_USED: break; case USE_SLAVE: default: DBG_INF("Enforcing use of master after write"); which_server = USE_MASTER; break; } } } else { DBG_INF("Use of master detected"); stgy->master_used = TRUE; } } switch (which_server) { case USE_SLAVE: case USE_MASTER: break; case USE_LAST_USED: DBG_INF("Using last used connection"); if (stgy->last_used_conn) { /* TODO: move is_master flag from global trx struct to CONN_DATA */ } else { /* TODO: handle error at this level? */ } break; case USE_ALL: default: break; } DBG_RETURN(which_server); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_qos */ enum_func_status mysqlnd_ms_choose_connection_qos(MYSQLND_CONN_DATA * conn, void * f_data, const char * connect_host, char ** query, size_t * query_len, zend_bool * free_query, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { enum_func_status ret = PASS; MYSQLND_MS_FILTER_QOS_DATA * filter_data = (MYSQLND_MS_FILTER_QOS_DATA *) f_data; MYSQLND_MS_LIST_DATA * element; DBG_ENTER("mysqlnd_ms_choose_connection_qos"); DBG_INF_FMT("query(50bytes)=%*s", MIN(50, *query_len), *query); switch (filter_data->consistency) { case CONSISTENCY_SESSION: /* For now... We may be able to use selected slaves which have replicated the last write on the line, e.g. using global transaction ID. We may be able to use slaves which have replicated certain, "tagged" writes. For example, the user could have a relaxed definition of session consistency and require only consistent reads from one table. In that case, we may use master and all slaves which have replicated the latest updates on the table in question. */ if ((QOS_OPTION_GTID == filter_data->option) && (USE_MASTER != mysqlnd_ms_qos_which_server(*query, *query_len, stgy TSRMLS_CC))) { smart_str sql = {0, 0, 0}; zend_bool exit_loop = FALSE; BEGIN_ITERATE_OVER_SERVER_LIST(element, slave_list) MYSQLND_CONN_DATA * connection = element->conn; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, connection); if (!conn_data || !*conn_data) { continue; } if ((*conn_data)->global_trx.check_for_gtid && (CONN_GET_STATE(connection) != CONN_QUIT_SENT) && ( (CONN_GET_STATE(connection) > CONN_ALLOCED) || (PASS == mysqlnd_ms_lazy_connect(element, TRUE TSRMLS_CC) ))) { DBG_INF_FMT("Checking slave connection "MYSQLND_LLU_SPEC"", connection->thread_id); if (!sql.c) { char * pos = strstr((*conn_data)->global_trx.check_for_gtid, "#GTID"); if (pos) { smart_str_appendl(&sql, (*conn_data)->global_trx.check_for_gtid, pos - ((*conn_data)->global_trx.check_for_gtid)); smart_str_appends(&sql, filter_data->option_data.gtid); smart_str_appends(&sql, (*conn_data)->global_trx.check_for_gtid + (pos - ((*conn_data)->global_trx.check_for_gtid)) + sizeof("#GTID") - 1); smart_str_appendc(&sql, '\0'); } else { mysqlnd_ms_client_n_php_error(NULL, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed parse SQL for checking GTID. Cannot find #GTID placeholder"); exit_loop = TRUE; } } if (sql.c) { MYSQLND_ERROR_INFO tmp_error_info; memset(&tmp_error_info, 0, sizeof(MYSQLND_ERROR_INFO)); if (PASS == mysqlnd_ms_qos_server_has_gtid(connection, conn_data, sql.c, sql.len - 1, (*conn_data)->global_trx.wait_for_gtid_timeout, &tmp_error_info TSRMLS_CC)) { zend_llist_add_element(selected_slaves, &element); } else if (tmp_error_info.error_no) { mysqlnd_ms_client_n_php_error(NULL, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " SQL error while checking slave for GTID: %d/'%s'", tmp_error_info.error_no, tmp_error_info.error); } } } if (exit_loop) { break; } END_ITERATE_OVER_SERVER_LIST; smart_str_free(&sql); BEGIN_ITERATE_OVER_SERVER_LIST(element, master_list) zend_llist_add_element(selected_masters, &element); END_ITERATE_OVER_SERVER_LIST; break; } DBG_INF("fall-through from session consistency"); case CONSISTENCY_STRONG: /* For now and forever... ... use masters, no slaves. This is our master_on_write replacement. All the other filters don't need to take care in the future. */ DBG_INF("using masters only for strong consistency"); BEGIN_ITERATE_OVER_SERVER_LIST(element, master_list) zend_llist_add_element(selected_masters, &element); END_ITERATE_OVER_SERVER_LIST; break; case CONSISTENCY_EVENTUAL: /* For now... Either all masters and slaves or slaves filtered by SHOW SLAVE STATUS replication lag or slaves plus caching */ { #ifdef MYSQLND_MS_HAVE_MYSQLND_QC zend_bool search_slaves = FALSE; uint ttl = 0; if ((QOS_OPTION_CACHE == filter_data->option) && (USE_MASTER != mysqlnd_ms_qos_which_server((const char *)*query, *query_len, stgy TSRMLS_CC))) { char * server_id = NULL; int server_id_len; /* TODO: If QC tokenizer would be better we should not use conn->host but conn->host_info */ server_id_len = spprintf(&server_id, 0, "%s|%d|%d|%s|%s", conn->host, conn->port, (conn->charset) ? conn->charset->nr : 0, conn->user, conn->connect_or_select_db? conn->connect_or_select_db:""); ttl = filter_data->option_data.ttl; if (FALSE == mysqlnd_qc_query_is_cached(conn, (const char *)*query, *query_len, server_id, server_id_len TSRMLS_CC)) { DBG_INF("Query is not cached"); search_slaves = TRUE; } else { DBG_INF("Query is in the cache"); search_slaves = FALSE; } efree(server_id); } if ((search_slaves || (QOS_OPTION_AGE == filter_data->option)) && (USE_MASTER != mysqlnd_ms_qos_which_server((const char *)*query, *query_len, stgy TSRMLS_CC))) #else if ((QOS_OPTION_AGE == filter_data->option) && (USE_MASTER != mysqlnd_ms_qos_which_server((const char *)*query, *query_len, stgy TSRMLS_CC))) #endif { zend_llist stage1_slaves; zend_llist_init(&stage1_slaves, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, 0); /* Stage 1 - just fire the queries and forget them for a moment */ BEGIN_ITERATE_OVER_SERVER_LIST(element, slave_list) MYSQLND_CONN_DATA * connection = element->conn; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, connection); if (!conn_data || !*conn_data) { continue; } if ((CONN_GET_STATE(connection) != CONN_QUIT_SENT) && ( (CONN_GET_STATE(connection) > CONN_ALLOCED) || (PASS == mysqlnd_ms_lazy_connect(element, TRUE TSRMLS_CC)) )) { MYSQLND_ERROR_INFO tmp_error_info = {{'\0'}, {'\0'}, 0}; DBG_INF_FMT("Checking slave connection "MYSQLND_LLU_SPEC"", connection->thread_id); tmp_error_info.error_no = 0; if (PASS == mysqlnd_ms_qos_server_get_lag_stage1(connection, conn_data, &tmp_error_info TSRMLS_CC)) { zend_llist_add_element(&stage1_slaves, &element); } else if (tmp_error_info.error_no) { mysqlnd_ms_client_n_php_error(NULL, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " SQL error while checking slave for lag: %d/'%s'", tmp_error_info.error_no, tmp_error_info.error); } } END_ITERATE_OVER_SERVER_LIST; /* Stage 2 - Now, after all servers have something to do, try to fetch the result, in the same order */ BEGIN_ITERATE_OVER_SERVER_LIST(element, &stage1_slaves) long lag; MYSQLND_ERROR_INFO tmp_error_info; MYSQLND_CONN_DATA * connection = element->conn; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, connection); memset(&tmp_error_info, 0, sizeof(MYSQLND_ERROR_INFO)); lag = mysqlnd_ms_qos_server_get_lag_stage2(connection, conn_data, &tmp_error_info TSRMLS_CC); if (tmp_error_info.error_no) { mysqlnd_ms_client_n_php_error(NULL, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " SQL error while checking slave for lag (%d): %d/'%s'", lag, tmp_error_info.error_no, tmp_error_info.error); continue; } #ifdef MYSQLND_MS_HAVE_MYSQLND_QC if (QOS_OPTION_CACHE == filter_data->option) { if ((lag > 0) && (lag < filter_data->option_data.ttl)) { if ((filter_data->option_data.ttl - lag) < ttl) { ttl = (filter_data->option_data.ttl - lag); } zend_llist_add_element(selected_slaves, &element); } continue; } #endif /* Must be QOS_OPTION_AGE */ if ((lag > 0) && (lag <= filter_data->option_data.age)) { zend_llist_add_element(selected_slaves, &element); } END_ITERATE_OVER_SERVER_LIST; zend_llist_clean(&stage1_slaves); } else { BEGIN_ITERATE_OVER_SERVER_LIST(element, slave_list) zend_llist_add_element(selected_slaves, &element); END_ITERATE_OVER_SERVER_LIST; } BEGIN_ITERATE_OVER_SERVER_LIST(element, master_list) zend_llist_add_element(selected_masters, &element); END_ITERATE_OVER_SERVER_LIST; #ifdef MYSQLND_MS_HAVE_MYSQLND_QC if (ttl > 0) { char * new_query = NULL; *query_len = spprintf(&new_query, 0, "/*" ENABLE_SWITCH "*//*" ENABLE_SWITCH_TTL"%u*//*" SERVER_ID_SWITCH "%s|%d|%d|%s|%s*/%s", ttl, conn->host, conn->port, (conn->charset) ? conn->charset->nr : 0, conn->user, conn->connect_or_select_db? conn->connect_or_select_db:"", *query); *query = new_query; *free_query = TRUE; DBG_INF_FMT("Cache option ttl %lu, slave list ttl %lu, %s", filter_data->option_data.ttl, ttl, *query); } #endif } break; default: DBG_ERR("Invalid filter data, we should never get here"); ret = FAIL; break; } DBG_RETURN(ret); } /* }}} */ #if PHP_VERSION_ID > 50399 /* {{{ mysqlnd_ms_remove_qos_filter */ static int mysqlnd_ms_remove_qos_filter(void * element, void * data) { MYSQLND_MS_FILTER_DATA * filter = *(MYSQLND_MS_FILTER_DATA **)element; return (filter->pick_type == SERVER_PICK_QOS) ? 1 : 0; } /* }}} */ /* {{{ mysqlnd_ms_section_filters_prepend_qos */ enum_func_status mysqlnd_ms_section_filters_prepend_qos(MYSQLND * proxy_conn, enum mysqlnd_ms_filter_qos_consistency consistency, enum mysqlnd_ms_filter_qos_option option, MYSQLND_MS_FILTER_QOS_OPTION_DATA * option_data TSRMLS_DC) { MYSQLND_MS_CONN_DATA ** conn_data; enum_func_status ret = FAIL; /* not sure... */ zend_bool persistent = proxy_conn->persistent; DBG_ENTER("mysqlnd_ms_section_filters_prepend_qos"); conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(proxy_conn->data, mysqlnd_ms_plugin_id); DBG_INF_FMT("conn_data=%p *conn_data=%p", conn_data, conn_data? *conn_data : NULL); if (conn_data && *conn_data) { struct mysqlnd_ms_lb_strategies * stgy = &(*conn_data)->stgy; zend_llist * filters = stgy->filters; MYSQLND_MS_FILTER_DATA * new_filter_entry = NULL; MYSQLND_MS_FILTER_QOS_DATA * new_qos_filter = NULL, * old_qos_filter = NULL; MYSQLND_MS_FILTER_DATA * filter, ** filter_pp; zend_llist_position pos; /* search for old filter - assumptions: there no more than one QOS filter at any time */ for (filter_pp = (MYSQLND_MS_FILTER_DATA **) zend_llist_get_first_ex(filters, &pos); filter_pp && (filter = *filter_pp) && (!old_qos_filter); (filter_pp = (MYSQLND_MS_FILTER_DATA **) zend_llist_get_next_ex(filters, &pos))) { if (filter->pick_type == SERVER_PICK_QOS) { old_qos_filter = (MYSQLND_MS_FILTER_QOS_DATA *) filter; } } /* new QOS filter */ new_qos_filter = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_QOS_DATA), persistent); new_qos_filter->parent.filter_dtor = qos_filter_dtor; new_qos_filter->consistency = consistency; new_qos_filter->option = option; /* preserve settings from current filter */ if (old_qos_filter) new_qos_filter->option_data = old_qos_filter->option_data; if (QOS_OPTION_AGE == option && CONSISTENCY_EVENTUAL == consistency) { new_qos_filter->option_data.age = option_data->age; } if (QOS_OPTION_CACHE == option && CONSISTENCY_EVENTUAL == consistency) { new_qos_filter->option_data.ttl = option_data->ttl; } if (QOS_OPTION_GTID == option && CONSISTENCY_SESSION == consistency) { new_qos_filter->option_data.gtid_len = option_data->gtid_len; new_qos_filter->option_data.gtid = estrndup(option_data->gtid, option_data->gtid_len); efree(option_data->gtid); } new_filter_entry = (MYSQLND_MS_FILTER_DATA *)new_qos_filter; new_filter_entry->persistent = persistent; new_filter_entry->name = mnd_pestrndup(PICK_QOS, sizeof(PICK_QOS) -1, persistent); new_filter_entry->name_len = sizeof(PICK_QOS) -1; new_filter_entry->pick_type = (enum mysqlnd_ms_server_pick_strategy)SERVER_PICK_QOS; new_filter_entry->multi_filter = TRUE; /* remove all existing QOS filters */ zend_llist_del_element(filters, NULL, mysqlnd_ms_remove_qos_filter); /* prepend with new filter */ zend_llist_prepend_element(filters, &new_filter_entry); } ret = PASS; DBG_RETURN(ret); } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_qos.h0000664000175000017500000000462712161007456020036 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 311510 2011-05-27 19:36:39Z andrey $ */ #ifndef MYSQLND_MS_FILTER_QOS_H #define MYSQLND_MS_FILTER_QOS_H struct mysqlnd_ms_lb_strategies; enum_func_status mysqlnd_ms_choose_connection_qos(MYSQLND_CONN_DATA * conn, void * f_data, const char * connect_host, char ** query, size_t * query_len, zend_bool * free_query, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC); MYSQLND_MS_FILTER_DATA * mysqlnd_ms_qos_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); #if PHP_VERSION_ID > 50399 enum_func_status mysqlnd_ms_section_filters_prepend_qos(MYSQLND * proxy_conn, enum mysqlnd_ms_filter_qos_consistency consistency, enum mysqlnd_ms_filter_qos_option option, MYSQLND_MS_FILTER_QOS_OPTION_DATA * option_data TSRMLS_DC); #endif #endif /* MYSQLND_MS_FILTER_QOS_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_random.c0000664000175000017500000010420312161007456020476 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 311179 2011-05-18 11:26:22Z andrey $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #include "mysqlnd_ms.h" #include "ext/standard/php_rand.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_switch.h" #include "mysqlnd_ms_config_json.h" #include "mysqlnd_ms_lb_weights.h" /* {{{ random_filter_dtor */ static void random_filter_dtor(struct st_mysqlnd_ms_filter_data * pDest TSRMLS_DC) { MYSQLND_MS_FILTER_RANDOM_DATA * filter = (MYSQLND_MS_FILTER_RANDOM_DATA *) pDest; DBG_ENTER("random_filter_dtor"); zend_hash_destroy(&filter->sticky.master_context); zend_hash_destroy(&filter->sticky.slave_context); mnd_pefree(filter, filter->parent.persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_random_filter_ctor */ MYSQLND_MS_FILTER_DATA * mysqlnd_ms_random_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { MYSQLND_MS_FILTER_RANDOM_DATA * ret; DBG_ENTER("mysqlnd_ms_random_filter_ctor"); DBG_INF_FMT("section=%p", section); ret = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_RANDOM_DATA), persistent); if (ret) { ret->parent.filter_dtor = random_filter_dtor; zend_hash_init(&ret->lb_weight, 4, NULL/*hash*/, mysqlnd_ms_filter_lb_weigth_dtor, persistent); /* section could be NULL! */ if (section) { /* random => array(sticky => true) */ zend_bool value_exists = FALSE, is_list_value = FALSE; char * once_value = mysqlnd_ms_config_json_string_from_section(section, PICK_ONCE, sizeof(PICK_ONCE) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists && once_value) { ret->sticky.once = !mysqlnd_ms_config_json_string_is_bool_false(once_value); mnd_efree(once_value); } if ((TRUE == mysqlnd_ms_config_json_section_is_list(section TSRMLS_CC) && TRUE == mysqlnd_ms_config_json_section_is_object_list(section TSRMLS_CC))) { struct st_mysqlnd_ms_config_json_entry * subsection = NULL; /* random => array(weights => ...) */ do { char * current_subsection_name = NULL; size_t current_subsection_name_len = 0; subsection = mysqlnd_ms_config_json_next_sub_section(section, ¤t_subsection_name, ¤t_subsection_name_len, NULL TSRMLS_CC); if (!subsection) { break; } if (!strcmp(current_subsection_name, SECT_LB_WEIGHTS)) { mysqlnd_ms_filter_ctor_load_weights_config(&ret->lb_weight, PICK_RANDOM, subsection, master_connections, slave_connections, error_info, persistent TSRMLS_CC); break; } } while (1); } } else { /* Stickiness by default when no filters section in the config Implies NULL passed to this ctor. */ ret->sticky.once = TRUE; } DBG_INF_FMT("sticky=%d", ret->sticky.once); /* XXX: this could be initialized only in case of ONCE */ zend_hash_init(&ret->sticky.master_context, 4, NULL/*hash*/, NULL/*dtor*/, persistent); zend_hash_init(&ret->sticky.slave_context, 4, NULL/*hash*/, NULL/*dtor*/, persistent); zend_hash_init(&ret->weight_context.master_context, 4, NULL/*hash*/, NULL/*dtor*/, persistent); zend_hash_init(&ret->weight_context.slave_context, 4, NULL/*hash*/, NULL/*dtor*/, persistent); } DBG_RETURN((MYSQLND_MS_FILTER_DATA *) ret); } /* }}} */ /* {{{ mysqlnd_ms_random_remove_conn */ static int mysqlnd_ms_random_remove_conn(void * element, void * data) { MYSQLND_MS_LIST_DATA * entry = NULL, ** entry_pp = NULL; entry_pp = (MYSQLND_MS_LIST_DATA **)element; if (entry_pp && (entry = *entry_pp) && (entry == data)) { return 1; } return 0; } /* }}} */ /* {{{ mysqlnd_ms_random_sort_list_remove_conn */ static int mysqlnd_ms_random_sort_list_remove_conn(void * element, void * data) { MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * entry = NULL, ** entry_pp = NULL; entry_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)element; if (entry_pp && (entry = *entry_pp) && (entry->element) && (entry->element == data)) { return 1; } return 0; } /* }}} */ /* {{{ mysqlnd_ms_random_sort_context_init */ static int mysqlnd_ms_random_sort_context_init(HashTable * context, const smart_str * const fprint, const zend_llist * const server_list, HashTable * lb_weight, zend_llist * sort_list, unsigned int * total_weight TSRMLS_DC) { MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT * lb_context; MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * lb_weight_context, ** lb_weight_context_pp; zend_llist_position pos; DBG_ENTER("mysqlnd_ms_init_sort_list"); { MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT local_lb_context; memset(&local_lb_context, 0, sizeof(MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT)); zend_llist_init(&local_lb_context.sort_list, sizeof(MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT *), NULL /* dtor */, 1); local_lb_context.total_weight = 0; if (SUCCESS != zend_hash_add(context, fprint->c, fprint->len /*\0 counted*/, &local_lb_context, sizeof(MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT), NULL)) { DBG_INF("Failed to add context"); DBG_RETURN(FAIL); } } /* fetch ptr to the data inside the HT */ if (SUCCESS != zend_hash_find(context, fprint->c, fprint->len /*\0 counted*/, (void**)&lb_context)) { DBG_INF_FMT("Failed to get ptr to context - fingerprint='%s' len=%d", fprint->c, fprint->len); DBG_RETURN(FAIL); } if (PASS != mysqlnd_ms_populate_weights_sort_list(lb_weight, &lb_context->sort_list, server_list TSRMLS_CC)) { DBG_INF("Failed to populate weights sort list"); DBG_RETURN(FAIL); } lb_context->total_weight = 0; mysqlnd_ms_weight_list_sort(&lb_context->sort_list TSRMLS_CC); /* TODO: Move total counter into MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT ? */ for (lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_first_ex(&lb_context->sort_list, &pos); (lb_weight_context_pp) && (lb_weight_context = *lb_weight_context_pp); lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_next_ex(&lb_context->sort_list, &pos)) { lb_context->total_weight += lb_weight_context->lb_weight->weight; } /* we must copy as we remove entries during retry */ mysqlnd_ms_weight_list_init(sort_list TSRMLS_CC); zend_llist_copy(sort_list, &lb_context->sort_list); *total_weight = lb_context->total_weight; DBG_RETURN(SUCCESS); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_random_populate_sort_list */ static enum_func_status mysqlnd_ms_choose_connection_random_populate_sort_list(zend_llist * sort_list, unsigned int * total_weight, HashTable * weight_context_m_o_s_ctx, zend_llist * the_list, MYSQLND_MS_FILTER_RANDOM_DATA * filter, const smart_str * const fprint, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT * lb_context = NULL; DBG_ENTER("mysqlnd_ms_choose_connection_random_populate_sort_list"); DBG_INF("Weighted load balancing"); if (FAILURE == zend_hash_find(weight_context_m_o_s_ctx, fprint->c, fprint->len /*\0 counted*/, (void **)&lb_context)) { /* build sort list for weighted load balancing */ if (SUCCESS != mysqlnd_ms_random_sort_context_init(weight_context_m_o_s_ctx, fprint, the_list, &filter->lb_weight, sort_list, total_weight TSRMLS_CC)) { DBG_RETURN(FAIL); } } else { zend_llist_copy(sort_list, &lb_context->sort_list); *total_weight = lb_context->total_weight; } DBG_INF_FMT("Sort list has %u elements, total_weight = %u", zend_llist_count(sort_list), *total_weight); if (0 == zend_llist_count(sort_list)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Something is very wrong for slave random/once. The sort list is empty."); DBG_RETURN(FAIL); } DBG_RETURN(PASS); } /* }}} */ /* Basic idea: summarize weights, compute random between 1... total_weight. Pick server that matches the rande of the random value. Example list, total_weight = 4, rnd_idx = 1..4 slave 1, weight 2 -> rnx_idx = 1..2 slave 2, weight 1 -> rnd_idx = 3 slave 3, weight 1 -> rnd_idx = 4 Without failover: Round 0 - rnd_idx = 3 slave 1, weight 2 -> rnx_idx = 1..2 slave 2, weight 1 -> rnd_idx = 3 --> try slave 2 slave 3, weight 1 -> rnd_idx = 4 With failover: Round 0 - total_weight = 4, rnd range 1..4, rnd = 3 slave 1, weight 2 -> rnx_idx = 1..2 slave 2, weight 1 -> rnd_idx = 3 --> try slave 2, fails slave 3, weight 1 -> rnd_idx = 4 Trim list - total_weight = 3: slave 1, weight 2 -> rnx_idx = 1..2 slave 3, weight 1 -> rnd_idx = 3 Round 1 - total_weight = 3, rnd range 1..3, rnd = 1 slave 1, weight 2 -> rnx_idx = 1..2 --> try slave 1, fails slave 3, weight 1 -> rnd_idx = 3 Trim list - total_weight = 1: slave 3, weight 1 -> rnd_idx = 1 Round 2 - total_weight = 1, rnd range 1..1, rnd = 1 slave 3, weight 1 -> rnd_idx = 1 -> try slave 3, fails Trim list (empty) Either consider masters or give up. */ /* {{{ mysqlnd_ms_choose_connection_random_use_slave_aux */ static MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_random_use_slave_aux(const zend_llist * const master_connections, zend_llist * slave_connections, MYSQLND_MS_FILTER_RANDOM_DATA * filter, const smart_str * const fprint, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { unsigned int retry_count = 0; zend_llist_position pos; zend_llist * l = slave_connections; MYSQLND_MS_LIST_DATA * element = NULL, ** element_pp = NULL; MYSQLND_CONN_DATA * connection = NULL; zend_bool use_lb_context = FALSE; zend_llist sort_list; unsigned int total_weight; DBG_ENTER("mysqlnd_ms_choose_connection_random_use_slave_aux"); if (zend_hash_num_elements(&filter->lb_weight)) { /* SEE COMMENT above the function */ mysqlnd_ms_choose_connection_random_populate_sort_list(&sort_list, &total_weight, &filter->weight_context.slave_context, l, filter, fprint, error_info TSRMLS_CC); use_lb_context = TRUE; } while (zend_llist_count(l) > 0) { MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * lb_weight_context = NULL; retry_count++; if (use_lb_context) { MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT ** lb_weight_context_pp = NULL; unsigned int i = 0; unsigned long rnd_idx; rnd_idx = php_rand(TSRMLS_C); RAND_RANGE(rnd_idx, 1, total_weight, PHP_RAND_MAX); DBG_INF_FMT("USE_SLAVE weighted, rnd_idx=%lu", rnd_idx); for ( lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_first_ex(&sort_list, &pos); (lb_weight_context_pp) && (lb_weight_context = *lb_weight_context_pp); (lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_next_ex(&sort_list, &pos)) ) { i += lb_weight_context->lb_weight->weight; if (i >= rnd_idx) { break; } } element = lb_weight_context? lb_weight_context->element:NULL; connection = element? element->conn:NULL; } else { unsigned int i = 0; unsigned long rnd_idx; rnd_idx = php_rand(TSRMLS_C); RAND_RANGE(rnd_idx, 0, zend_llist_count(l) - 1, PHP_RAND_MAX); DBG_INF_FMT("USE_SLAVE rnd_idx=%lu", rnd_idx); element_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(l, &pos); while (i++ < rnd_idx) { element_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(l, &pos); } connection = (element_pp && (element = *element_pp)) ? element->conn : NULL; } if (!connection) { /* Q: how can we get here? */ if (SERVER_FAILOVER_DISABLED == stgy->failover_strategy) { /* TODO: connection error would be better */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate slave connection. " "%d slaves to choose from. Something is wrong", zend_llist_count(l)); /* should be a very rare case to be here - connection shouldn't be NULL in first place */ DBG_RETURN(NULL); } MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { /* drop failed server from list, test remaining slaves before fall-through to master */ DBG_INF("Trying next slave, if any"); zend_llist_del_element(l, element, mysqlnd_ms_random_remove_conn); if (use_lb_context) { total_weight -= lb_weight_context->lb_weight->weight; zend_llist_del_element(&sort_list, element, mysqlnd_ms_random_sort_list_remove_conn); } continue; } /* must be SERVER_FAILOVER_MASTER */ break; } else { smart_str fprint_conn = {0}; if (stgy->failover_remember_failed) { zend_bool * failed; mysqlnd_ms_get_fingerprint_connection(&fprint_conn, &element TSRMLS_CC); if (SUCCESS == zend_hash_find(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, (void **) &failed)) { smart_str_free(&fprint_conn); zend_llist_del_element(l, element, mysqlnd_ms_random_remove_conn); if (use_lb_context) { total_weight -= lb_weight_context->lb_weight->weight; zend_llist_del_element(&sort_list, element, mysqlnd_ms_random_sort_list_remove_conn); } DBG_INF("Skipping previously failed connection"); continue; } } if (CONN_GET_STATE(connection) > CONN_ALLOCED || PASS == mysqlnd_ms_lazy_connect(element, FALSE TSRMLS_CC)) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(connection)); if (TRUE == filter->sticky.once) { zend_hash_update(&filter->sticky.slave_context, fprint->c, fprint->len /*\0 counted*/, &connection, sizeof(MYSQLND *), NULL); } if (fprint_conn.c) { smart_str_free(&fprint_conn); } DBG_RETURN(connection); } if (stgy->failover_remember_failed) { zend_bool failed = TRUE; if (SUCCESS != zend_hash_add(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, &failed, sizeof(zend_bool), NULL)) { DBG_INF("Failed to remember failing connection"); } } if (fprint_conn.c) { smart_str_free(&fprint_conn); } if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { /* drop failed server from list, test remaining slaves before fall-through to master */ DBG_INF("Trying next slave, if any"); zend_llist_del_element(l, element, mysqlnd_ms_random_remove_conn); if (use_lb_context) { total_weight -= lb_weight_context->lb_weight->weight; zend_llist_del_element(&sort_list, element, mysqlnd_ms_random_sort_list_remove_conn); } continue; } if (SERVER_FAILOVER_DISABLED == stgy->failover_strategy) { /* no failover */ DBG_INF("Failover disabled"); DBG_RETURN(connection); } MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); /* falling-through */ break; } } /* while */ if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && (0 == zend_llist_count((zend_llist *)master_connections))) { DBG_INF("No masters to continue search"); /* must not fall through as we'll loose the connection error */ DBG_RETURN(connection); } DBG_RETURN(NULL); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_random_use_slave */ static MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_random_use_slave(zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_MS_FILTER_RANDOM_DATA * filter, struct mysqlnd_ms_lb_strategies * stgy, enum enum_which_server * which_server, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { MYSQLND_CONN_DATA * conn = NULL; MYSQLND_CONN_DATA ** context_pos; smart_str fprint = {0}; DBG_ENTER("mysqlnd_ms_choose_connection_random_use_slave"); DBG_INF_FMT("%d slaves to choose from", zend_llist_count(slave_connections)); if (0 == zend_llist_count(slave_connections) && (SERVER_FAILOVER_DISABLED == stgy->failover_strategy)) { /* SERVER_FAILOVER_MASTER and SERVER_FAILOVER_LOOP will fall through to master */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate slave connection. " "%d slaves to choose from. Something is wrong", zend_llist_count(slave_connections)); DBG_RETURN(NULL); } mysqlnd_ms_get_fingerprint(&fprint, slave_connections TSRMLS_CC); if (SUCCESS == zend_hash_find(&filter->sticky.slave_context, fprint.c, fprint.len /*\0 counted*/, (void **) &context_pos)) { conn = context_pos? *context_pos : NULL; if (conn) { DBG_INF_FMT("Using already selected slave connection "MYSQLND_LLU_SPEC, conn->thread_id); MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(conn)); smart_str_free(&fprint); DBG_RETURN(conn); } mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Something is very wrong for slave random/once."); } { zend_llist slaves_copy; zend_llist_copy(&slaves_copy, slave_connections); conn = mysqlnd_ms_choose_connection_random_use_slave_aux(master_connections, &slaves_copy, filter, &fprint, stgy, error_info TSRMLS_CC); zend_llist_clean(&slaves_copy); } smart_str_free(&fprint); if (conn) { DBG_RETURN(conn); } if (SERVER_FAILOVER_DISABLED == stgy->failover_strategy) { /* We may get here with remember_failed but no failover strategy set. TODO: Is this a valid configuration at all? */ DBG_INF("Failover disabled"); DBG_RETURN(conn); } MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); *which_server = USE_MASTER; DBG_RETURN(NULL); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_random_use_master_aux */ static MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_random_use_master_aux(zend_llist * master_connections, MYSQLND_MS_FILTER_RANDOM_DATA * filter, const smart_str * const fprint, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { zend_llist_position pos; zend_bool use_lb_context = FALSE; MYSQLND_MS_LIST_DATA * element = NULL, ** element_pp = NULL; MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * lb_weight_context, ** lb_weight_context_pp; MYSQLND_MS_FILTER_RANDOM_LB_CONTEXT * lb_context = NULL; MYSQLND_CONN_DATA * connection = NULL; zend_llist sort_list; unsigned int total_weight; unsigned int retry_count = 0; zend_llist * l = master_connections; DBG_ENTER("mysqlnd_ms_choose_connection_random_use_master_aux"); if (zend_hash_num_elements(&filter->lb_weight)) { /* TODO: cleanup - master and slave code are identical,use function to avoid code duplication */ DBG_INF("Weighted load balancing"); use_lb_context = TRUE; if (FAILURE == zend_hash_find(&filter->weight_context.master_context, fprint->c, fprint->len /*\0 counted*/, (void **)&lb_context)) { /* build sort list for weighted load balancing */ if (SUCCESS != mysqlnd_ms_random_sort_context_init(&filter->weight_context.master_context, fprint, l, &filter->lb_weight, &sort_list, &total_weight TSRMLS_CC)) { DBG_RETURN(NULL); } } else { zend_llist_copy(&sort_list, &lb_context->sort_list); total_weight = lb_context->total_weight; } DBG_INF_FMT("Sort list has %d elements, total_weight = %d", zend_llist_count(&sort_list), total_weight); if (0 == zend_llist_count(&sort_list)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Something is very wrong for master random/once. The sort list is empty."); DBG_RETURN(NULL); } } while (zend_llist_count(l) > 0) { unsigned long rnd_idx = php_rand(TSRMLS_C); retry_count++; if (use_lb_context) { unsigned int i = 0; RAND_RANGE(rnd_idx, 1, total_weight, PHP_RAND_MAX); DBG_INF_FMT("USE_MASTER weighted, rnd_idx=%lu", rnd_idx); for (i = 0, lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_first_ex(&sort_list, &pos); (lb_weight_context_pp) && (lb_weight_context = *lb_weight_context_pp); (lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_next_ex(&sort_list, &pos))) { i += lb_weight_context->lb_weight->weight; if (i >= rnd_idx) { break; } } connection = (lb_weight_context && (element = lb_weight_context->element)) ? element->conn : NULL; } else { unsigned int i = 0; RAND_RANGE(rnd_idx, 0, zend_llist_count(l) - 1, PHP_RAND_MAX); DBG_INF_FMT("USE_MASTER rnd_idx=%lu", rnd_idx); element_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(l, &pos); while (i++ < rnd_idx) { element_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(l, &pos); } connection = (element_pp && (element = *element_pp)) ? element->conn : NULL; } if (connection) { smart_str fprint_conn = {0}; if (stgy->failover_remember_failed) { zend_bool * failed; mysqlnd_ms_get_fingerprint_connection(&fprint_conn, &element TSRMLS_CC); if (SUCCESS == zend_hash_find(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, (void **) &failed)) { smart_str_free(&fprint_conn); zend_llist_del_element(l, element, mysqlnd_ms_random_remove_conn); DBG_INF("Skipping previously failed connection"); if (use_lb_context) { total_weight -= lb_weight_context->lb_weight->weight; zend_llist_del_element(&sort_list, element, mysqlnd_ms_random_sort_list_remove_conn); } continue; } } if (CONN_GET_STATE(connection) > CONN_ALLOCED || PASS == mysqlnd_ms_lazy_connect(element, TRUE TSRMLS_CC)) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(connection)); if (TRUE == filter->sticky.once) { zend_hash_update(&filter->sticky.master_context, fprint->c, fprint->len /*\0 counted*/, &connection, sizeof(MYSQLND *), NULL); } if (fprint_conn.c) { smart_str_free(&fprint_conn); } DBG_RETURN(connection); } if (stgy->failover_remember_failed) { zend_bool failed = TRUE; if (SUCCESS != zend_hash_add(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, &failed, sizeof(zend_bool), NULL)) { DBG_INF("Failed to remember failing connection"); } } if (fprint_conn.c) { smart_str_free(&fprint_conn); } MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && (zend_llist_count(l) > 1) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { /* drop failed server from list, test remaining masters before giving up */ DBG_INF("Trying next master"); zend_llist_del_element(l, element, mysqlnd_ms_random_remove_conn); if (use_lb_context) { total_weight -= lb_weight_context->lb_weight->weight; zend_llist_del_element(&sort_list, element, mysqlnd_ms_random_sort_list_remove_conn); } continue; } DBG_INF("Failover disabled"); } else { MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && (zend_llist_count(l) > 1) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { /* drop failed server from list, test remaining slaves before fall-through to master */ DBG_INF("Trying next master"); zend_llist_del_element(l, element, mysqlnd_ms_random_remove_conn); if (use_lb_context) { total_weight -= lb_weight_context->lb_weight->weight; zend_llist_del_element(&sort_list, element, mysqlnd_ms_random_sort_list_remove_conn); } continue; } mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate master connection. " "%d masters to choose from. Something is wrong", zend_llist_count(l)); DBG_RETURN(NULL); } DBG_RETURN(connection); } DBG_RETURN(NULL); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_random_use_master */ static MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_random_use_master(zend_llist * master_connections, MYSQLND_MS_FILTER_RANDOM_DATA * filter, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { MYSQLND_CONN_DATA * conn = NULL; MYSQLND_CONN_DATA ** context_pos; smart_str fprint = {0}; DBG_ENTER("mysqlnd_ms_choose_connection_random_use_master"); DBG_INF_FMT("%d masters to choose from", zend_llist_count(master_connections)); if (0 == zend_llist_count(master_connections)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate master connection. " "%d masters to choose from. Something is wrong", zend_llist_count(master_connections)); DBG_RETURN(NULL); } mysqlnd_ms_get_fingerprint(&fprint, master_connections TSRMLS_CC); /* LOCK on context ??? */ if (SUCCESS == zend_hash_find(&filter->sticky.master_context, fprint.c, fprint.len /*\0 counted*/, (void **) &context_pos)) { conn = context_pos? *context_pos : NULL; if (!conn) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Something is very wrong for master random/once."); } else { DBG_INF_FMT("Using already selected master connection "MYSQLND_LLU_SPEC, conn->thread_id); MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(conn)); } } else { zend_llist masters_copy; zend_llist_copy(&masters_copy, master_connections); conn = mysqlnd_ms_choose_connection_random_use_master_aux(&masters_copy, filter, &fprint, stgy, error_info TSRMLS_CC); zend_llist_clean(&masters_copy); } smart_str_free(&fprint); DBG_RETURN(conn); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_random */ MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_random(void * f_data, const char * const query, const size_t query_len, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info, zend_llist * master_connections, zend_llist * slave_connections, enum enum_which_server * which_server, zend_bool allow_master_for_slave TSRMLS_DC) { MYSQLND_MS_FILTER_RANDOM_DATA * filter = (MYSQLND_MS_FILTER_RANDOM_DATA *) f_data; zend_bool forced; enum enum_which_server tmp_which; zend_bool forced_tx_master = FALSE; MYSQLND_CONN_DATA * conn = NULL; DBG_ENTER("mysqlnd_ms_choose_connection_random"); if (!which_server) { which_server = &tmp_which; } DBG_INF_FMT("trx_stickiness_strategy=%d in_transaction=%d trx_stop_switching=%d", stgy->trx_stickiness_strategy, stgy->in_transaction, stgy->trx_stop_switching); *which_server = mysqlnd_ms_query_is_select(query, query_len, &forced TSRMLS_CC); if (allow_master_for_slave && (USE_SLAVE == *which_server) && (0 == zend_llist_count(slave_connections))) { /* In versions prior to 1.5 the QoS filter could end the filter chain if it had sieved out all connections but one. This is no longer allowed to ensure QoS cannot overrule trx stickiness. trx stickiness is mostly handled by random/roundrobin filter invoked after QoS. Thus, random/roundrobin may be called with an empty slave list to pick a connection for a SELECT. If so, we implicitly switch to master list. */ *which_server = USE_MASTER; } if ((stgy->trx_stickiness_strategy == TRX_STICKINESS_STRATEGY_MASTER) && stgy->in_transaction) { DBG_INF("Enforcing use of master while in transaction"); if (stgy->trx_stop_switching) { /* in the middle of a transaction */ *which_server = USE_LAST_USED; } else { /* first statement run in transaction: disable switch and failover */ *which_server = USE_MASTER; } MYSQLND_MS_INC_STATISTIC(MS_STAT_TRX_MASTER_FORCED); } else if ((stgy->trx_stickiness_strategy == TRX_STICKINESS_STRATEGY_ON) && stgy->in_transaction) { if (stgy->trx_stop_switching) { DBG_INF("Use last in middle of transaction"); /* in the middle of a transaction */ *which_server = USE_LAST_USED; } else { /* first statement run in transaction: disable switch and failover */ if (FALSE == stgy->trx_read_only) { DBG_INF("Enforcing use of master while in transaction"); *which_server = USE_MASTER; } else { if (0 == zend_llist_count(slave_connections)) { DBG_INF("No slaves to run read only transaction, using master"); *which_server = USE_MASTER; } else { DBG_INF("Considering use of slave while in read only transaction"); *which_server = USE_SLAVE; } } } } /* Note: master on write shall be independent of trx settings */ if (stgy->mysqlnd_ms_flag_master_on_write) { if (*which_server != USE_MASTER) { if (stgy->master_used && !forced) { switch (*which_server) { case USE_MASTER: case USE_LAST_USED: /* Last used must not be modified, otherwise trx handling breaks */ break; case USE_SLAVE: default: DBG_INF("Enforcing use of master after write"); *which_server = USE_MASTER; break; } } } else { DBG_INF("Use of master detected"); stgy->master_used = TRUE; } } switch (*which_server) { case USE_SLAVE: { conn = mysqlnd_ms_choose_connection_random_use_slave(master_connections, slave_connections, filter, stgy, which_server, error_info TSRMLS_CC); if ((NULL != conn || USE_MASTER != *which_server) && !(NULL == conn && TRUE == allow_master_for_slave)) { /* conn == NULL && allow_master_for_slave is true if QoS filter has sieved out all available slaves. */ goto return_connection; } } if ((TRUE == stgy->in_transaction) && (TRUE == stgy->trx_stop_switching)) { /* If our list of slaves may is short and it contains of nothing but previously failed slaves, then we should allow failover when searching for an server to run a transaction. Thus, we set stgy->trx_stop_switching very late in this function. */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Automatic failover is not permitted in the middle of a transaction"); DBG_INF("In transaction, no switch allowed"); conn = NULL; goto return_connection; } DBG_INF("FAIL-OVER"); /* fall-through */ case USE_MASTER: conn = mysqlnd_ms_choose_connection_random_use_master(master_connections, filter, stgy, error_info TSRMLS_CC); break; case USE_LAST_USED: DBG_INF("Using last used connection"); if (!stgy->last_used_conn) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Last used SQL hint cannot be used because last " "used connection has not been set yet. Statement will fail"); } else { SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(stgy->last_used_conn)); } conn = stgy->last_used_conn; break; default: /* error */ break; } return_connection: if (stgy->in_transaction && (stgy->trx_stickiness_strategy != TRX_STICKINESS_STRATEGY_DISABLED)) { /* Initial server for running trx has been identified. No matter whether we found a valid connection or not, we stop switching servers until the transaction has ended. No kind of failover allowed when in a transaction. */ stgy->trx_stop_switching = TRUE; } #if MYSQLND_VERSION_ID >= 50011 if ((conn) && (stgy->trx_stickiness_strategy != TRX_STICKINESS_STRATEGY_DISABLED) && (TRUE == stgy->in_transaction) && (TRUE == stgy->trx_begin_required) && !forced) { /* See mysqlnd_ms.c tx_begin notes! */ enum_func_status ret = FAIL; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); if (conn_data && *conn_data) { /* Send BEGIN now that we have decided on a connection for the transaction */ DBG_INF_FMT("Delayed BEGIN mode=%d name='%s'", stgy->trx_begin_mode, stgy->trx_begin_name); (*conn_data)->skip_ms_calls = TRUE; /* TODO: flags */ ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_begin)(conn, stgy->trx_begin_mode, stgy->trx_begin_name TSRMLS_CC); (*conn_data)->skip_ms_calls = FALSE; stgy->trx_begin_required = FALSE; stgy->trx_begin_mode = 0; if (stgy->trx_begin_name) { mnd_pefree(stgy->trx_begin_name, conn->persistent); stgy->trx_begin_name = NULL; } if (FAIL == ret) { /* back to the beginning: reset everything */ stgy->in_transaction = FALSE; stgy->trx_stop_switching = FALSE; stgy->trx_read_only = FALSE; mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to start transaction after choosing a server"); } } } #endif DBG_RETURN(conn); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_random.h0000664000175000017500000000416612161007456020512 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 311510 2011-05-27 19:36:39Z andrey $ */ #ifndef MYSQLND_MS_FILTER_RANDOM_H #define MYSQLND_MS_FILTER_RANDOM_H MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_random(void * f_data, const char * const query, const size_t query_len, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info, zend_llist * master_connections, zend_llist * slave_connections, enum enum_which_server * which_server, zend_bool allow_master_for_slave TSRMLS_DC); MYSQLND_MS_FILTER_DATA * mysqlnd_ms_random_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); #endif /* MYSQLND_MS_FILTER_RANDOM_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_round_robin.c0000664000175000017500000006137612161007456021553 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 311179 2011-05-18 11:26:22Z andrey $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_switch.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_lb_weights.h" #include "mysqlnd_ms_config_json.h" /* {{{ mysqlnd_ms_filter_rr_context_dtor */ static void mysqlnd_ms_filter_rr_context_dtor(void * data) { MYSQLND_MS_FILTER_RR_CONTEXT * context = (MYSQLND_MS_FILTER_RR_CONTEXT *) data; zend_llist_clean(&context->weight_list); } /* }}} */ /* {{{ rr_filter_dtor */ static void rr_filter_dtor(struct st_mysqlnd_ms_filter_data * pDest TSRMLS_DC) { MYSQLND_MS_FILTER_RR_DATA * filter = (MYSQLND_MS_FILTER_RR_DATA *) pDest; DBG_ENTER("rr_filter_dtor"); zend_hash_destroy(&filter->master_context); zend_hash_destroy(&filter->slave_context); zend_hash_destroy(&filter->lb_weight); mnd_pefree(filter, filter->parent.persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_filter_rr_reset_current_weight */ static void mysqlnd_ms_filter_rr_reset_current_weight(void * data TSRMLS_DC) { MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * context = *(MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **) data; context->lb_weight->current_weight = context->lb_weight->weight; } /* }}} */ /* {{{ mysqlnd_ms_rr_filter_ctor */ MYSQLND_MS_FILTER_DATA * mysqlnd_ms_rr_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { MYSQLND_MS_FILTER_RR_DATA * ret; DBG_ENTER("mysqlnd_ms_rr_filter_ctor"); DBG_INF_FMT("section=%p", section); /* section could be NULL! */ ret = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_RR_DATA), persistent); if (ret) { ret->parent.filter_dtor = rr_filter_dtor; zend_hash_init(&ret->master_context, 4, NULL/*hash*/, mysqlnd_ms_filter_rr_context_dtor, persistent); zend_hash_init(&ret->slave_context, 4, NULL/*hash*/, mysqlnd_ms_filter_rr_context_dtor, persistent); zend_hash_init(&ret->lb_weight, 4, NULL/*hash*/, mysqlnd_ms_filter_lb_weigth_dtor, persistent); /* roundrobin => array(weights => array(name => w, ... )) */ if (section && (TRUE == mysqlnd_ms_config_json_section_is_list(section TSRMLS_CC) && TRUE == mysqlnd_ms_config_json_section_is_object_list(section TSRMLS_CC))) { struct st_mysqlnd_ms_config_json_entry * subsection = NULL; do { char * current_subsection_name = NULL; size_t current_subsection_name_len = 0; subsection = mysqlnd_ms_config_json_next_sub_section(section, ¤t_subsection_name, ¤t_subsection_name_len, NULL TSRMLS_CC); if (!subsection) { break; } if (!strcmp(current_subsection_name, SECT_LB_WEIGHTS)) { mysqlnd_ms_filter_ctor_load_weights_config(&ret->lb_weight, PICK_RROBIN, subsection, master_connections, slave_connections, error_info, persistent TSRMLS_CC); break; } } while (1); } } DBG_RETURN((MYSQLND_MS_FILTER_DATA *) ret); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_rr_fetch_context */ static MYSQLND_MS_FILTER_RR_CONTEXT * mysqlnd_ms_choose_connection_rr_fetch_context(HashTable * rr_contexts, zend_llist * connections, HashTable * lb_weights_list TSRMLS_DC) { MYSQLND_MS_FILTER_RR_CONTEXT * ret_context = NULL; smart_str fprint = {0}; DBG_ENTER("mysqlnd_ms_choose_connection_rr_fetch_context"); mysqlnd_ms_get_fingerprint(&fprint, connections TSRMLS_CC); if (SUCCESS != zend_hash_find(rr_contexts, fprint.c, fprint.len /*\0 counted*/, (void **) &ret_context)) { MYSQLND_MS_FILTER_RR_CONTEXT context; int retval; DBG_INF("Init the master context"); memset(&context, 0, sizeof(MYSQLND_MS_FILTER_RR_CONTEXT)); context.pos = 0; mysqlnd_ms_weight_list_init(&context.weight_list TSRMLS_CC); retval = zend_hash_add(rr_contexts, fprint.c, fprint.len /*\0 counted*/, &context, sizeof(MYSQLND_MS_FILTER_RR_CONTEXT), NULL); if (SUCCESS == retval) { /* fetch ptr to the data inside the HT */ retval = zend_hash_find(rr_contexts, fprint.c, fprint.len /*\0 counted*/, (void**)&ret_context); } smart_str_free(&fprint); if (SUCCESS != retval) { DBG_RETURN(NULL); } if (zend_hash_num_elements(lb_weights_list)) { /* sort list for weighted load balancing */ if (PASS != mysqlnd_ms_populate_weights_sort_list(lb_weights_list, &ret_context->weight_list, connections TSRMLS_CC)) { DBG_RETURN(NULL); } DBG_INF_FMT("Sort list has %d elements", zend_llist_count(&ret_context->weight_list)); } } else { smart_str_free(&fprint); } DBG_INF_FMT("context=%p", ret_context); DBG_RETURN(ret_context); } /* }}} */ /* Round 0, sort list slave 1, current_weight 3 --> pick, current_weight-- slave 2, current_weight 2 slave 3, current_weight 1 Round 1, sort list slave 1, current_weight 2 --> pick, current_weight-- slave 2, current_weight 2 slave 3, current_weight 1 Round 2, sort list slave 2, current_weight 2 --> pick, current_weight-- slave 1, current_weight 1 slave 3, current_weight 1 NOTE: slave 1, slave 3 ordering is undefined/implementation dependent! Round 3, sort list slave 2, current_weight 1 --> pick, current_weight--, reset slave 1, current_weight 1 slave 3, current_weight 1 Round 4, sort list slave 1, current_weight 1 --> pick, current_weight-- slave 3, current_weight 1 slave 2, current_weight 0 Round 5, sort list slave 3, current_weight 1 --> pick, current_weight-- slave 2, current_weight 0 slave 1, current_weight 0 Round 6, sort list slave 3, current_weight 0 --> RESET -> 1 --> sort again slave 2, current_weight 0 -> 2 slave 1, current_weight 0 -> 3 */ /* {{{ mysqlnd_ms_rr_weight_list_get_next */ static MYSQLND_MS_LIST_DATA * mysqlnd_ms_rr_weight_list_get_next(zend_llist * wl TSRMLS_DC) { MYSQLND_MS_LIST_DATA * element = NULL; DBG_ENTER("mysqlnd_ms_rr_weight_list_get_next"); DBG_INF("Sorting"); do { MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * lb_weight_context, ** lb_weight_context_pp; zend_llist_position tmp_pos; mysqlnd_ms_weight_list_sort(wl TSRMLS_CC); lb_weight_context_pp = (MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)zend_llist_get_first_ex(wl, &tmp_pos); if (lb_weight_context_pp && (lb_weight_context = *lb_weight_context_pp)) { element = lb_weight_context->element; DBG_INF_FMT("element %p current_weight %d", element, lb_weight_context->lb_weight->current_weight); if (0 == lb_weight_context->lb_weight->current_weight) { /* RESET */ zend_llist_apply(wl, mysqlnd_ms_filter_rr_reset_current_weight TSRMLS_CC); continue; } lb_weight_context->lb_weight->current_weight--; } else { DBG_INF("Sorting failed"); } } while (0); DBG_RETURN(element); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_rr_use_slave */ static MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_rr_use_slave(zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_MS_FILTER_RR_DATA * filter, struct mysqlnd_ms_lb_strategies * stgy, enum enum_which_server * which_server, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { unsigned int * pos; MYSQLND_CONN_DATA * connection = NULL; zend_llist * l = slave_connections; MYSQLND_MS_FILTER_RR_CONTEXT * context = NULL; unsigned int retry_count = 0; DBG_ENTER("mysqlnd_ms_choose_connection_rr_use_slave"); *which_server = USE_SLAVE; if (0 == zend_llist_count(l)) { DBG_INF("Slave list is empty"); MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); if ((SERVER_FAILOVER_MASTER == stgy->failover_strategy) || (SERVER_FAILOVER_LOOP == stgy->failover_strategy)) { *which_server = USE_MASTER; DBG_RETURN(connection); } /* failover must be disabled */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate slave connection. %d slaves to choose from. " "Something is wrong", zend_llist_count(l)); DBG_RETURN(connection); } context = mysqlnd_ms_choose_connection_rr_fetch_context(&filter->slave_context, l, &filter->lb_weight TSRMLS_CC); if (context) { pos = &(context->pos); } else { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't create or fetch context. Something is quite wrong"); DBG_RETURN(NULL); } DBG_INF_FMT("look under pos %u", *pos); do { MYSQLND_MS_LIST_DATA * element = NULL; retry_count++; if (zend_llist_count(&context->weight_list)) { element = mysqlnd_ms_rr_weight_list_get_next(&context->weight_list TSRMLS_CC); } else { unsigned int i = 0; BEGIN_ITERATE_OVER_SERVER_LIST(element, l); if (i++ == *pos) { break; } END_ITERATE_OVER_SERVER_LIST; DBG_INF_FMT("i=%u pos=%u", i, *pos); } if (!element) { /* there is no such safe guard in the random filter. Random tests for connection */ if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); /* time to increment the position */ *pos = ((*pos) + 1) % zend_llist_count(l); DBG_INF("Trying next slave, if any"); DBG_INF_FMT("pos is now %u", *pos); continue; } /* unlikely */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate slave connection. %d slaves to choose from. " "Something is wrong", zend_llist_count(l)); DBG_RETURN(NULL); } /* time to increment the position */ *pos = ((*pos) + 1) % zend_llist_count(l); DBG_INF_FMT("pos is now %u", *pos); if (element->conn) { connection = element->conn; } if (connection) { smart_str fprint_conn = {0}; DBG_INF_FMT("Using slave connection "MYSQLND_LLU_SPEC"", connection->thread_id); /* Check if this connection has already been marked failed */ if (stgy->failover_remember_failed) { zend_bool * failed; mysqlnd_ms_get_fingerprint_connection(&fprint_conn, &element TSRMLS_CC); if (SUCCESS == zend_hash_find(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, (void **) &failed)) { smart_str_free(&fprint_conn); DBG_INF("Skipping previously failed connection"); continue; } } if (CONN_GET_STATE(connection) > CONN_ALLOCED || PASS == mysqlnd_ms_lazy_connect(element, FALSE TSRMLS_CC)) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(connection)); if (fprint_conn.c) { smart_str_free(&fprint_conn); } /* Real Success !! */ DBG_RETURN(connection); } /* Not nice, bad connection, mark it if the user wants it */ if (stgy->failover_remember_failed) { zend_bool failed = TRUE; if (SUCCESS != zend_hash_add(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, &failed, sizeof(zend_bool), NULL)) { DBG_INF("Failed to remember failing connection"); } } if (fprint_conn.c) { smart_str_free(&fprint_conn); } } /* if we are here, we had some kind of a problem, either !connection or establishment failed */ MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { DBG_INF("Trying next slave, if any"); continue; } else if (SERVER_FAILOVER_DISABLED == stgy->failover_strategy) { DBG_INF("Failover disabled"); DBG_RETURN(connection); } DBG_INF("Falling back to the master"); break; } while (retry_count < zend_llist_count(l)); /* We should never get here if trx disallows switching. If no slaves, we have a test prior to the loop. If no connection, we have tests in the loop. */ MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && (0 == zend_llist_count(master_connections))) { /* must not fall through as we'll loose the connection error */ DBG_INF("No masters to continue search"); DBG_RETURN(connection); } if (SERVER_FAILOVER_DISABLED == stgy->failover_strategy) { /* We may get here with remember_failed but no failover strategy set. TODO: Is this a valid configuration at all? */ DBG_INF("Failover disabled"); DBG_RETURN(connection); } *which_server = USE_MASTER; DBG_RETURN(NULL); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_rr_use_master */ static MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_rr_use_master(zend_llist * master_connections, MYSQLND_MS_FILTER_RR_DATA * filter, struct mysqlnd_ms_lb_strategies * stgy, zend_bool forced_tx_master, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { zend_llist * l = master_connections; unsigned int * pos; MYSQLND_MS_LIST_DATA * element = NULL; MYSQLND_CONN_DATA * connection = NULL; MYSQLND_MS_FILTER_RR_CONTEXT * context; unsigned int retry_count = 0; DBG_ENTER("mysqlnd_ms_choose_connection_rr_use_master"); if (0 == zend_llist_count(l)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate master connection. %d masters to choose from. " "Something is wrong", zend_llist_count(l)); DBG_RETURN(NULL); } context = mysqlnd_ms_choose_connection_rr_fetch_context(&filter->master_context, l, &filter->lb_weight TSRMLS_CC); if (context) { pos = &(context->pos); } else { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't create or fetch context. Something is quite wrong"); DBG_RETURN(NULL); } while (retry_count++ < zend_llist_count(l)) { if (zend_llist_count(&context->weight_list)) { element = mysqlnd_ms_rr_weight_list_get_next(&context->weight_list TSRMLS_CC); } else { unsigned int i = 0; BEGIN_ITERATE_OVER_SERVER_LIST(element, l); if (i++ == *pos) { break; /* stop iterating */ } END_ITERATE_OVER_SERVER_LIST; DBG_INF_FMT("USE_MASTER pos=%lu", *pos); } if (!element) { if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); /* we must move to the next position and ignore forced_tx_master */ *pos = ((*pos) + 1) % zend_llist_count(l); DBG_INF("Trying next master, if any"); continue; } mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate master connection. %d masters to choose from. " "Something is wrong", zend_llist_count(l)); DBG_RETURN(NULL); } connection = NULL; if (element->conn) { connection = element->conn; } DBG_INF("Using master connection"); /* time to increment the position */ *pos = ((*pos) + 1) % zend_llist_count(l); if (connection) { smart_str fprint_conn = {0}; if (stgy->failover_remember_failed) { mysqlnd_ms_get_fingerprint_connection(&fprint_conn, &element TSRMLS_CC); if (zend_hash_exists(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/)) { smart_str_free(&fprint_conn); DBG_INF("Skipping previously failed connection"); continue; } } if ((CONN_GET_STATE(connection) > CONN_ALLOCED || PASS == mysqlnd_ms_lazy_connect(element, TRUE TSRMLS_CC))) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(connection)); if (fprint_conn.c) { smart_str_free(&fprint_conn); } DBG_RETURN(connection); } if (stgy->failover_remember_failed) { zend_bool failed = TRUE; if (SUCCESS != zend_hash_add(&stgy->failed_hosts, fprint_conn.c, fprint_conn.len /*\0 counted*/, &failed, sizeof(zend_bool), NULL)) { DBG_INF("Failed to remember failing connection"); } } if (fprint_conn.c) { smart_str_free(&fprint_conn); } } if ((SERVER_FAILOVER_LOOP == stgy->failover_strategy) && ((0 == stgy->failover_max_retries) || (retry_count <= stgy->failover_max_retries))) { MS_WARN_AND_RETURN_IF_TRX_FORBIDS_FAILOVER(stgy, NULL); DBG_INF("Trying next master, if any"); continue; } else if (SERVER_FAILOVER_DISABLED == stgy->failover_strategy) { DBG_INF("Failover disabled"); } break; } DBG_RETURN(connection); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_rr */ MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_rr(void * f_data, const char * const query, const size_t query_len, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info, zend_llist * master_connections, zend_llist * slave_connections, enum enum_which_server * which_server, zend_bool allow_master_for_slave TSRMLS_DC) { enum enum_which_server tmp_which; zend_bool forced; MYSQLND_MS_FILTER_RR_DATA * filter = (MYSQLND_MS_FILTER_RR_DATA *) f_data; zend_bool forced_tx_master = FALSE; MYSQLND_CONN_DATA * conn = NULL; DBG_ENTER("mysqlnd_ms_choose_connection_rr"); if (!which_server) { which_server = &tmp_which; } DBG_INF_FMT("trx_stickiness_strategy=%d in_transaction=%d trx_stop_switching=%d", stgy->trx_stickiness_strategy, stgy->in_transaction, stgy->trx_stop_switching); *which_server = mysqlnd_ms_query_is_select(query, query_len, &forced TSRMLS_CC); if (allow_master_for_slave && (USE_SLAVE == *which_server) && (0 == zend_llist_count(slave_connections))) { /* In versions prior to 1.5 the QoS filter could end the filter chain if it had sieved out all connections but one. This is no longer allowed to ensure QoS cannot overrule trx stickiness. trx stickiness is mostly handled by random/roundrobin filter invoked after QoS. Thus, random/roundrobin may be called with an empty slave list to pick a connection for a SELECT. If so, we implicitly switch to master list. */ *which_server = USE_MASTER; } if ((stgy->trx_stickiness_strategy == TRX_STICKINESS_STRATEGY_MASTER) && stgy->in_transaction) { DBG_INF("Enforcing use of master while in transaction"); if (stgy->trx_stop_switching) { /* in the middle of a transaction */ *which_server = USE_LAST_USED; } else { /* first statement run in transaction: disable switch and failover */ *which_server = USE_MASTER; } forced_tx_master = TRUE; MYSQLND_MS_INC_STATISTIC(MS_STAT_TRX_MASTER_FORCED); } else if ((stgy->trx_stickiness_strategy == TRX_STICKINESS_STRATEGY_ON) && stgy->in_transaction) { if (stgy->trx_stop_switching) { DBG_INF("Use last in middle of transaction"); /* in the middle of a transaction */ *which_server = USE_LAST_USED; } else { /* first statement run in transaction: disable switch and failover */ if (FALSE == stgy->trx_read_only) { DBG_INF("Enforcing use of master while in transaction"); forced_tx_master = TRUE; *which_server = USE_MASTER; } else { if (0 == zend_llist_count(slave_connections)) { DBG_INF("No slaves to run read only transaction, using master"); forced_tx_master = TRUE; *which_server = USE_MASTER; } else { DBG_INF("Considering use of slave while in read only transaction"); *which_server = USE_SLAVE; } } } } if (stgy->mysqlnd_ms_flag_master_on_write) { if (*which_server != USE_MASTER) { if (stgy->master_used && !forced) { switch (*which_server) { case USE_MASTER: case USE_LAST_USED: break; case USE_SLAVE: default: DBG_INF("Enforcing use of master after write"); *which_server = USE_MASTER; break; } } } else { DBG_INF("Use of master detected"); stgy->master_used = TRUE; } } switch (*which_server) { case USE_SLAVE: conn = mysqlnd_ms_choose_connection_rr_use_slave(master_connections, slave_connections, filter, stgy, which_server, error_info TSRMLS_CC); /* conn == NULL && allow_master_for_slave is true if QoS filter has sieved out all available slaves. */ if ((NULL != conn || USE_MASTER != *which_server) && !(NULL == conn && TRUE == allow_master_for_slave)) { goto return_connection; } if ((TRUE == stgy->in_transaction) && (TRUE == stgy->trx_stop_switching)) { /* If our list of slaves may is short and it contains of nothing but previously failed slaves, then we should allow failover when searching for an server to run a transaction. Thus, we set stgy->trx_stop_switching very late in this function. */ mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Automatic failover is not permitted in the middle of a transaction"); DBG_INF("In transaction, no switch allowed"); conn = NULL; goto return_connection; } DBG_INF("Fall-through to master"); /* fall-through */ case USE_MASTER: conn = mysqlnd_ms_choose_connection_rr_use_master(master_connections, filter, stgy, forced_tx_master, error_info TSRMLS_CC); break; case USE_LAST_USED: DBG_INF("Using last used connection"); if (!stgy->last_used_conn) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Last used SQL hint cannot be used because last used connection has not been set yet. " "Statement will fail"); } else { SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(stgy->last_used_conn)); } conn = stgy->last_used_conn; break; default: /* error */ conn = NULL; break; } return_connection: if (stgy->in_transaction && (stgy->trx_stickiness_strategy != TRX_STICKINESS_STRATEGY_DISABLED)) { /* Initial server for running trx has been identified. No matter whether we found a valid connection or not, we stop switching servers until the transaction has ended. No kind of failover allowed when in a transaction. */ stgy->trx_stop_switching = TRUE; } #if MYSQLND_VERSION_ID >= 50011 if ((conn) && (stgy->trx_stickiness_strategy != TRX_STICKINESS_STRATEGY_DISABLED) && (TRUE == stgy->in_transaction) && (TRUE == stgy->trx_begin_required) && !forced) { /* See mysqlnd_ms.c tx_begin notes! */ enum_func_status ret = FAIL; MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); if (conn_data && *conn_data) { /* Send BEGIN now that we have decided on a connection for the transaction */ DBG_INF_FMT("Delayed BEGIN mode=%d name='%s'", stgy->trx_begin_mode, stgy->trx_begin_name); (*conn_data)->skip_ms_calls = TRUE; /* TODO: flags */ ret = MS_CALL_ORIGINAL_CONN_DATA_METHOD(tx_begin)(conn, stgy->trx_begin_mode, stgy->trx_begin_name TSRMLS_CC); (*conn_data)->skip_ms_calls = FALSE; stgy->trx_begin_required = FALSE; stgy->trx_begin_mode = 0; if (stgy->trx_begin_name) { mnd_pefree(stgy->trx_begin_name, conn->persistent); stgy->trx_begin_name = NULL; } if (FAIL == ret) { /* back to the beginning: reset everything */ stgy->in_transaction = FALSE; stgy->trx_stop_switching = FALSE; stgy->trx_read_only = FALSE; mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to start transaction after choosing a server"); } } } #endif DBG_RETURN(conn); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_round_robin.h0000664000175000017500000000423712161007456021551 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 311510 2011-05-27 19:36:39Z andrey $ */ #ifndef MYSQLND_MS_FILTER_ROUND_ROBIN_H #define MYSQLND_MS_FILTER_ROUND_ROBIN_H struct st_mysqlnd_ms_config_json_entry; MYSQLND_CONN_DATA * mysqlnd_ms_choose_connection_rr(void * f_data, const char * const query, const size_t query_len, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info, zend_llist * master_connections, zend_llist * slave_connections, enum enum_which_server * which_server, zend_bool allow_master_for_slave TSRMLS_DC); MYSQLND_MS_FILTER_DATA * mysqlnd_ms_rr_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); #endif /* MYSQLND_MS_FILTER_ROUND_ROBIN_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_table_partition.c0000664000175000017500000004650212161007456022405 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 311179 2011-05-18 11:26:22Z andrey $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_switch.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_config_json.h" #include "mysqlnd_qp.h" static void mysqlnd_ms_filter_ht_dtor(void * data); static enum_func_status mysqlnd_ms_load_table_filters(HashTable * master_rules, HashTable * slave_rules, struct st_mysqlnd_ms_config_json_entry * section, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); /* {{{ table_filter_dtor */ static void table_filter_dtor(struct st_mysqlnd_ms_filter_data * pDest TSRMLS_DC) { MYSQLND_MS_FILTER_TABLE_DATA * filter = (MYSQLND_MS_FILTER_TABLE_DATA *) pDest; DBG_ENTER("table_specific_dtor"); zend_hash_destroy(&filter->master_rules); zend_hash_destroy(&filter->slave_rules); mnd_pefree(filter, filter->parent.persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_table_filter_ctor */ MYSQLND_MS_FILTER_DATA * mysqlnd_ms_table_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { MYSQLND_MS_FILTER_TABLE_DATA * ret; DBG_ENTER("mysqlnd_ms_table_filter_ctor"); DBG_INF_FMT("section=%p", section); ret = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_TABLE_DATA), persistent); if (ret) { do { ret->parent.filter_dtor = table_filter_dtor; zend_hash_init(&ret->master_rules, 4, NULL/*hash*/, mysqlnd_ms_filter_ht_dtor/*dtor*/, persistent); zend_hash_init(&ret->slave_rules, 4, NULL/*hash*/, mysqlnd_ms_filter_ht_dtor/*dtor*/, persistent); if (FAIL == mysqlnd_ms_load_table_filters(&ret->master_rules, &ret->slave_rules, section, error_info, persistent TSRMLS_CC)) { ret->parent.filter_dtor((MYSQLND_MS_FILTER_DATA *)ret TSRMLS_CC); ret = NULL; break; } } while (0); } DBG_RETURN((MYSQLND_MS_FILTER_DATA *) ret); } /* }}} */ /* {{{ mysqlnd_ms_filter_dtor */ static void mysqlnd_ms_filter_dtor(void * data) { MYSQLND_MS_TABLE_FILTER * entry = * (MYSQLND_MS_TABLE_FILTER **) data; TSRMLS_FETCH(); if (entry) { zend_bool pers = entry->persistent; if (entry->wild) { mnd_pefree(entry->wild, pers); entry->wild = NULL; } if (entry->host_id) { mnd_pefree(entry->host_id, pers); entry->host_id = NULL; } #ifdef WE_NEED_NEXT if (entry->next) { mysqlnd_ms_filter_dtor(&entry->next); } #endif mnd_pefree(entry, pers); * (MYSQLND_MS_TABLE_FILTER **) data = NULL; } } /* }}} */ #if 0 /* {{{ mysqlnd_ms_filter_compare (based on array_data_compare) */ static int mysqlnd_ms_filter_comparator(const MYSQLND_MS_TABLE_FILTER * a, const MYSQLND_MS_TABLE_FILTER * b) { if (a && b) { return a->priority > b->priority? -1:(a->priority == b->priority? 0: 1); } return 0; } /* }}} */ /* {{{ mysqlnd_ms_filter_compare (based on array_data_compare) */ static int mysqlnd_ms_filter_compare(const void * a, const void * b TSRMLS_DC) { Bucket * f = *((Bucket **) a); Bucket * s = *((Bucket **) b); MYSQLND_MS_TABLE_FILTER * first = *((MYSQLND_MS_TABLE_FILTER **) f->pData); MYSQLND_MS_TABLE_FILTER * second = *((MYSQLND_MS_TABLE_FILTER **) s->pData); return mysqlnd_ms_filter_comparator(first, second); } /* }}} */ #endif /* {{{ mysqlnd_ms_filter_ht_dtor */ static void mysqlnd_ms_filter_ht_dtor(void * data) { HashTable * entry = * (HashTable **) data; TSRMLS_FETCH(); if (entry) { zend_hash_destroy(entry); mnd_free(entry); } } /* }}} */ /* {{{ mysqlnd_ms_table_add_rule */ static enum_func_status mysqlnd_ms_table_add_rule(HashTable * rules_ht, const char * const section_name, const size_t section_name_len, const char * const filter_mask, const size_t filter_mask_len, struct st_mysqlnd_ms_config_json_entry * current_filter, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { enum_func_status ret = PASS; MYSQLND_MS_TABLE_FILTER * new_filter_entry = NULL; DBG_ENTER("mysqlnd_ms_table_add_rule"); DBG_INF_FMT("filter_mask=%s", filter_mask); do { zend_bool value_exists = FALSE; zend_bool section_exists; struct st_mysqlnd_ms_config_json_entry * sub_section = mysqlnd_ms_config_json_sub_section(current_filter, section_name, section_name_len, §ion_exists TSRMLS_CC); zend_bool subsection_is_list = section_exists? mysqlnd_ms_config_json_section_is_list(sub_section TSRMLS_CC) : FALSE; /* we don't need objects, we check for this */ zend_bool subsection_isnt_obj_list = subsection_is_list && !mysqlnd_ms_config_json_section_is_object_list(sub_section TSRMLS_CC)? TRUE:FALSE; DBG_INF_FMT("getting in? %d", sub_section && subsection_isnt_obj_list); if (sub_section && subsection_isnt_obj_list) { zend_bool server_list_is_list_value; do { size_t server_name_len; char * server_name = mysqlnd_ms_config_json_string_from_section(current_filter, section_name, section_name_len, 0, &value_exists, &server_list_is_list_value TSRMLS_CC); if (!value_exists) { break; } server_name_len = strlen(server_name); new_filter_entry = mnd_pecalloc(1, sizeof(MYSQLND_MS_TABLE_FILTER), persistent); if (!new_filter_entry) { ret = FAIL; break; } new_filter_entry->persistent = persistent; new_filter_entry->host_id_len = server_name_len; new_filter_entry->host_id = mnd_pestrndup(server_name? server_name:"", server_name?server_name_len:0, persistent); DBG_INF_FMT("server_name=%s", server_name); mnd_efree(server_name); server_name = NULL; /* now add */ { HashTable ** existing_filter; if (SUCCESS == zend_hash_find(rules_ht, filter_mask, filter_mask_len + 1, (void **) &existing_filter)) { DBG_INF("Filter HT already exists"); if (!existing_filter || SUCCESS != zend_hash_next_index_insert(*existing_filter, &new_filter_entry, sizeof(MYSQLND_MS_TABLE_FILTER *), NULL)) { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX "Couldn't add new filter and couldn't find the original %*s", (int) filter_mask_len, filter_mask); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_buf); DBG_ERR_FMT("%s", error_buf); mysqlnd_ms_filter_dtor(&new_filter_entry); ret = FAIL; } else { DBG_INF("Added to the existing HT"); DBG_INF("re-sorting"); /* Sort specified array. */ #ifdef PRIORITY_IS_OFF_FOR_NOW zend_hash_sort(*existing_filter, zend_qsort, mysqlnd_ms_filter_compare, 0 /* renumber */ TSRMLS_CC); #endif } } else { HashTable * ht_for_new_filter = mnd_malloc(sizeof(HashTable)); DBG_INF("Filter HT doesn't exist, need to create it"); if (ht_for_new_filter) { if (SUCCESS == zend_hash_init(ht_for_new_filter, 2, NULL, mysqlnd_ms_filter_dtor, 1/*pers*/)) { if (SUCCESS != zend_hash_add(rules_ht, filter_mask, filter_mask_len + 1, &ht_for_new_filter, sizeof(HashTable *), NULL)) { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX "The hashtable %*s did not exist in the slave_rules " "but couldn't add", (int) filter_mask_len, filter_mask); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_buf); DBG_ERR_FMT("%s", error_buf); zend_hash_destroy(ht_for_new_filter); mnd_free(ht_for_new_filter); ht_for_new_filter = NULL; mysqlnd_ms_filter_dtor(&new_filter_entry); new_filter_entry = NULL; } else if (SUCCESS != zend_hash_next_index_insert(ht_for_new_filter, &new_filter_entry, sizeof(MYSQLND_MS_TABLE_FILTER *), NULL)) { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX "Couldn't add new filter and couldn't find the original %*s", (int) filter_mask_len, filter_mask); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_buf); DBG_ERR_FMT("%s", error_buf); mysqlnd_ms_filter_dtor(&new_filter_entry); } else { DBG_INF("Created, added to global HT and filter added to local HT"); } } } } } } while (server_list_is_list_value == TRUE); } /* slaves_section && subsection_is_obj_list */ } while (0); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_load_table_filters */ static enum_func_status mysqlnd_ms_load_table_filters(HashTable * master_rules, HashTable * slave_rules, struct st_mysqlnd_ms_config_json_entry * section, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { enum_func_status ret = PASS; unsigned int filter_count = 0; DBG_ENTER("mysqlnd_ms_load_table_filters"); if (section && master_rules && slave_rules) { zend_bool section_exists; struct st_mysqlnd_ms_config_json_entry * filters_section = mysqlnd_ms_config_json_sub_section(section, TABLE_RULES, sizeof(TABLE_RULES) - 1, §ion_exists TSRMLS_CC); zend_bool subsection_is_list = section_exists? mysqlnd_ms_config_json_section_is_list(filters_section TSRMLS_CC) : FALSE; zend_bool subsection_is_obj_list = subsection_is_list && mysqlnd_ms_config_json_section_is_object_list(filters_section TSRMLS_CC)? TRUE:FALSE; if (filters_section && subsection_is_obj_list) { do { char * filter_mask = NULL; size_t filter_mask_len = 0; struct st_mysqlnd_ms_config_json_entry * current_filter = mysqlnd_ms_config_json_next_sub_section(filters_section, &filter_mask, &filter_mask_len, NULL TSRMLS_CC); if (!current_filter || !filter_mask || !filter_mask_len) { if (NULL != filter_mask) { char error_buf[128]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " A table filter must be given a name. You must not use an empty string"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } DBG_INF("no next sub-section"); break; } DBG_INF_FMT("---------- Loading MASTER rules for [%s] ----------------", filter_mask); if (PASS == mysqlnd_ms_table_add_rule(master_rules, MASTER_NAME, sizeof(MASTER_NAME) - 1, filter_mask, filter_mask_len, current_filter, error_info, persistent TSRMLS_CC)) { DBG_INF_FMT("---------- Loading SLAVE rules for [%s] ----------------", filter_mask); if (PASS == mysqlnd_ms_table_add_rule(slave_rules, SLAVE_NAME, sizeof(SLAVE_NAME) - 1, filter_mask, filter_mask_len, current_filter, error_info, persistent TSRMLS_CC)) { filter_count++; } } } while (1); } } DBG_INF_FMT("filter_count=%u", filter_count); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_table_filter_match */ static enum_func_status mysqlnd_ms_table_filter_match(const char * const db_table_buf, HashTable * rules, zend_llist * in_list, zend_llist * out_list TSRMLS_DC) { enum_func_status ret = PASS; zend_bool match = FALSE; HashPosition pos_rules; HashTable ** filter_ht; DBG_ENTER("mysqlnd_ms_table_filter_match"); zend_hash_internal_pointer_reset_ex(rules, &pos_rules); while ((FALSE == match) && (SUCCESS == zend_hash_get_current_data_ex(rules, (void **)&filter_ht, &pos_rules) && filter_ht)) { char * filter_mask; uint fm_len; ulong n_key; if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(rules, &filter_mask, &fm_len, &n_key, 0, &pos_rules)) { DBG_INF_FMT("Comparing [%s] with [%s]", db_table_buf, filter_mask); if (TRUE == (match = mysqlnd_ms_match_wild(db_table_buf, filter_mask TSRMLS_CC))) { MYSQLND_MS_TABLE_FILTER ** entry_filter_pp; HashPosition pos_servers; /* found a match*/ DBG_INF("Found a match"); zend_hash_internal_pointer_reset_ex(*filter_ht, &pos_servers); while (SUCCESS == zend_hash_get_current_data_ex(*filter_ht, (void **)&entry_filter_pp, &pos_servers) && entry_filter_pp) { MYSQLND_MS_TABLE_FILTER * entry_filter = *entry_filter_pp; /* compare entry_filter->host_id with MYSQLND_MS_LIST_DATA::name_from_config */ MYSQLND_MS_LIST_DATA * el; BEGIN_ITERATE_OVER_SERVER_LIST(el, in_list); if (!strncmp(entry_filter->host_id, el->name_from_config, entry_filter->host_id_len)) { DBG_INF_FMT("Matched [%s] with a server, adding to the list", entry_filter->host_id); if (el->conn) { DBG_INF_FMT("Matched conn_id: "MYSQLND_LLU_SPEC, el->conn->thread_id); } zend_llist_add_element(out_list, &el); goto skip1; /* we can't use continue as BEGIN_ITERATE uses a loop */ /* XXX: maybe we want directly to go to skip2 ??? */ } END_ITERATE_OVER_SERVER_LIST; skip1: zend_hash_move_forward_ex(*filter_ht, &pos_servers); } } } zend_hash_move_forward_ex(rules, &pos_rules); } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_choose_connection_table_filter */ enum_func_status mysqlnd_ms_choose_connection_table_filter(void * f_data, const char * query, size_t query_len, const char * const connect_or_select_db, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy_not_used, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { enum_func_status ret = FAIL; MYSQLND_MS_FILTER_TABLE_DATA * filter = (MYSQLND_MS_FILTER_TABLE_DATA *) f_data; struct st_mysqlnd_query_parser * parser; DBG_ENTER("mysqlnd_ms_choose_connection_table_filter"); if (filter) { int err; parser = mysqlnd_qp_create_parser(TSRMLS_C); if (parser && !(err = mysqlnd_qp_start_parser(parser, query, query_len TSRMLS_CC))) { zend_llist_position tinfo_list_pos; struct st_mysqlnd_ms_table_info * tinfo; zend_llist master_in_stack, * master_in = &master_in_stack; zend_llist master_out_stack, * master_out = &master_out_stack; zend_llist slave_in_stack, * slave_in = &slave_in_stack; zend_llist slave_out_stack, * slave_out = &slave_out_stack; zend_llist_init(master_in, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, FALSE); zend_llist_init(master_out, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, FALSE); zend_llist_init(slave_in, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, FALSE); zend_llist_init(slave_out, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, FALSE); mysqlnd_ms_select_servers_all(master_list, slave_list, master_in, slave_in TSRMLS_CC); for (tinfo = zend_llist_get_first_ex(&parser->parse_info.table_list, &tinfo_list_pos); tinfo; tinfo = zend_llist_get_next_ex(&parser->parse_info.table_list, &tinfo_list_pos)) { /* 80 char db + '.' + 80 char table + \0 : should be 64 but prepared for the future */ char db_table_buf[4*80 + 1 + 4*80 + 1]; DBG_INF_FMT("current db=%s table=%s org_table=%s statement_type=%d", tinfo->db? tinfo->db:"n/a", tinfo->table? tinfo->table:"n/a", tinfo->org_table? tinfo->org_table:"n/a", parser->parse_info.statement ); if (tinfo->db) { snprintf(db_table_buf, sizeof(db_table_buf), "%s.%s", tinfo->db, tinfo->table); DBG_INF_FMT("qualified table=%s", db_table_buf); } else if (tinfo->table && connect_or_select_db) { snprintf(db_table_buf, sizeof(db_table_buf), "%s.%s", connect_or_select_db, tinfo->table); DBG_INF_FMT("qualified table=%s (using connect_or_select_db=%s)", db_table_buf, connect_or_select_db); } else { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " Failed to parse table name"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_buf); break; } zend_llist_clean(master_out); zend_llist_clean(slave_out); ret = mysqlnd_ms_table_filter_match(db_table_buf, &filter->master_rules, master_in, master_out TSRMLS_CC); if (PASS == ret && parser->parse_info.statement == STATEMENT_SELECT) { /* non-SELECTs don't go the the slaves */ ret = mysqlnd_ms_table_filter_match(db_table_buf, &filter->slave_rules, slave_in, slave_out TSRMLS_CC); } if (ret != PASS || (!zend_llist_count(master_out) && !zend_llist_count(slave_out))) { break; } zend_llist_clean(master_in); zend_llist_clean(slave_in); mysqlnd_ms_select_servers_all(master_out, slave_out, master_in, slave_in TSRMLS_CC); DBG_INF_FMT("selected_masters=%d selected_slaves=%d", zend_llist_count(master_out), zend_llist_count(slave_out)); } mysqlnd_ms_select_servers_all(master_out, slave_out, selected_masters, selected_slaves TSRMLS_CC); zend_llist_clean(master_in); zend_llist_clean(slave_in); zend_llist_clean(master_out); zend_llist_clean(slave_out); } if (parser) { #if 0 if (err) { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " Please, check the SQL syntax. If correct, report a bug. Parser error %d. Failed to parse statement '%*s'", err, (int) query_len, query); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_buf); DBG_INF_FMT("parser start error %d", err); } #endif mysqlnd_qp_free_parser(parser TSRMLS_CC); ret = PASS; } } DBG_RETURN(ret); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */mysqlnd_ms-1.5.2/mysqlnd_ms_filter_table_partition.h0000664000175000017500000000476212161007456022414 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 311510 2011-05-27 19:36:39Z andrey $ */ #ifndef MYSQLND_MS_FILTER_TABLE_PARTITION_H #define MYSQLND_MS_FILTER_TABLE_PARTITION_H struct st_mysqlnd_ms_config_json_entry; enum_func_status mysqlnd_ms_load_table_filters(HashTable * master_rules, HashTable * slave_rules, struct st_mysqlnd_ms_config_json_entry * section, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); enum_func_status mysqlnd_ms_choose_connection_table_filter(void * f_data, const char * query, size_t query_len, const char * const connect_or_select_db, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy_not_used, MYSQLND_ERROR_INFO * error_info TSRMLS_DC); void mysqlnd_ms_filter_ht_dtor(void * data); MYSQLND_MS_FILTER_DATA * mysqlnd_ms_table_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); #endif /* MYSQLND_MS_FILTER_TABLE_PARTITION_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_user.c0000664000175000017500000005643512161007456020211 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 311179 2011-05-18 11:26:22Z andrey $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/info.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_config_json.h" #include "ext/standard/php_rand.h" #include "mysqlnd_query_parser.h" #include "mysqlnd_qp.h" #include "mysqlnd_ms_enum_n_def.h" #define MS_STRING(vl, a) \ { \ MAKE_STD_ZVAL((a)); \ ZVAL_STRING((a), (char *)(vl), 1); \ } #define MS_STRINGL(vl, ln, a) \ { \ MAKE_STD_ZVAL((a)); \ ZVAL_STRINGL((a), (char *)(vl), (ln), 1); \ } #define MS_ARRAY(a) \ { \ MAKE_STD_ZVAL((a)); \ array_init((a)); \ } /* {{{ user_filter_dtor */ static void user_filter_dtor(struct st_mysqlnd_ms_filter_data * pDest TSRMLS_DC) { MYSQLND_MS_FILTER_USER_DATA * filter = (MYSQLND_MS_FILTER_USER_DATA *) pDest; DBG_ENTER("user_filter_dtor"); if (filter->user_callback) { zval_ptr_dtor(&filter->user_callback); } mnd_pefree(filter, filter->parent.persistent); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_user_filter_ctor */ MYSQLND_MS_FILTER_DATA * mysqlnd_ms_user_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { MYSQLND_MS_FILTER_USER_DATA * ret; DBG_ENTER("mysqlnd_ms_user_filter_ctor"); DBG_INF_FMT("section=%p", section); if (section) { ret = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_USER_DATA), persistent); if (ret) { zend_bool value_exists = FALSE, is_list_value = FALSE; char * callback; ret->parent.filter_dtor = user_filter_dtor; callback = mysqlnd_ms_config_json_string_from_section(section, SECT_USER_CALLBACK, sizeof(SECT_USER_CALLBACK) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { zval * zv; char * c_name; MAKE_STD_ZVAL(zv); ZVAL_STRING(zv, callback, 1); mnd_efree(callback); ret->user_callback = zv; ret->callback_valid = zend_is_callable(zv, 0, &c_name TSRMLS_CC); DBG_INF_FMT("name=%s valid=%d", c_name, ret->callback_valid); efree(c_name); } else { mnd_pefree(ret, persistent); php_error_docref(NULL TSRMLS_CC, E_ERROR, MYSQLND_MS_ERROR_PREFIX " Error by creating filter 'user', can't find section '%s' . Stopping.", SECT_USER_CALLBACK); } } } DBG_RETURN((MYSQLND_MS_FILTER_DATA *) ret); } /* }}} */ /* {{{ mysqlnd_ms_call_handler */ static zval * mysqlnd_ms_call_handler(zval *func, int argc, zval **argv, zend_bool destroy_args, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { int i; zval * retval; DBG_ENTER("mysqlnd_ms_call_handler"); MAKE_STD_ZVAL(retval); if (call_user_function(EG(function_table), NULL, func, retval, argc, argv TSRMLS_CC) == FAILURE) { char error_buf[128]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " Failed to call '%s'", Z_STRVAL_P(func)); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); zval_ptr_dtor(&retval); retval = NULL; } if (destroy_args == TRUE) { for (i = 0; i < argc; i++) { zval_ptr_dtor(&argv[i]); } } DBG_RETURN(retval); } /* }}} */ /* {{{ mysqlnd_ms_user_pick_server */ MYSQLND_CONN_DATA * mysqlnd_ms_user_pick_server(void * f_data, const char * connect_host, const char * query, size_t query_len, zend_llist * master_list, zend_llist * slave_list, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { MYSQLND_MS_FILTER_USER_DATA * filter_data = (MYSQLND_MS_FILTER_USER_DATA *) f_data; zval * args[7]; zval * retval; MYSQLND_CONN_DATA * ret = NULL; DBG_ENTER("mysqlnd_ms_user_pick_server"); DBG_INF_FMT("query(50bytes)=%*s query_is_select=%p", MIN(50, query_len), query, filter_data? filter_data->user_callback:NULL); if (master_list && filter_data && filter_data->user_callback) { uint param = 0; #ifdef ALL_SERVER_DISPATCH uint use_all_pos = 0; #endif if (!filter_data->callback_valid) { char * cback_name; if (!zend_is_callable(filter_data->user_callback, 0, &cback_name TSRMLS_CC)) { char error_buf[128]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " Specified callback (%s) is not a valid callback", cback_name); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } else { filter_data->callback_valid = TRUE; } efree(cback_name); if (!filter_data->callback_valid) { DBG_RETURN(ret); } } /* connect host */ MS_STRING((char *) connect_host, args[param]); /* query */ param++; MS_STRINGL((char *) query, query_len, args[param]); { MYSQLND_MS_LIST_DATA * el, ** el_pp; zend_llist_position pos; /* master list */ param++; MS_ARRAY(args[param]); for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(master_list, &pos); el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(master_list, &pos)) { if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy */ add_next_index_stringl(args[param], el->emulated_scheme, el->emulated_scheme_len, 1); } else { add_next_index_stringl(args[param], el->conn->scheme, el->conn->scheme_len, 1); } } /* slave list*/ param++; MS_ARRAY(args[param]); if (slave_list) { for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(slave_list, &pos); el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(slave_list, &pos)) { if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy */ add_next_index_stringl(args[param], el->emulated_scheme, el->emulated_scheme_len, 1); } else { add_next_index_stringl(args[param], el->conn->scheme, el->conn->scheme_len, 1); } } } /* last used connection */ param++; MAKE_STD_ZVAL(args[param]); if (stgy->last_used_conn && stgy->last_used_conn->scheme) { ZVAL_STRING(args[param], stgy->last_used_conn->scheme, 1); } else { ZVAL_NULL(args[param]); } /* in transaction */ param++; MAKE_STD_ZVAL(args[param]); if (stgy->in_transaction) { ZVAL_TRUE(args[param]); } else { ZVAL_FALSE(args[param]); } #ifdef ALL_SERVER_DISPATCH /* use all */ use_all_pos = ++param; MAKE_STD_ZVAL(args[param]); Z_ADDREF_P(args[param]); ZVAL_FALSE(args[param]); #endif } retval = mysqlnd_ms_call_handler(filter_data->user_callback, param + 1, args, FALSE /*we destroy later*/, error_info TSRMLS_CC); if (retval) { if (Z_TYPE_P(retval) == IS_STRING) { do { MYSQLND_MS_LIST_DATA * el, ** el_pp; zend_llist_position pos; for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(master_list, &pos); !ret && el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(master_list, &pos)) { if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy */ if (!strcasecmp(el->emulated_scheme, Z_STRVAL_P(retval))) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER_CALLBACK); DBG_INF_FMT("Userfunc chose LAZY master host : [%*s]", el->conn->scheme_len, el->conn->scheme); if (PASS == mysqlnd_ms_lazy_connect(el, TRUE TSRMLS_CC)) { ret = el->conn; } else { DBG_ERR("Connect failed, forwarding error to the user"); ret = el->conn; /* no automatic action: leave it to the user to decide! */ } } } else { if (!strcasecmp(el->conn->scheme, Z_STRVAL_P(retval))) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER_CALLBACK); ret = el->conn; SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(ret)); DBG_INF_FMT("Userfunc chose master host : [%*s]", el->conn->scheme_len, el->conn->scheme); } } } if (slave_list) { for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(slave_list, &pos); !ret && el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(slave_list, &pos)) { if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy */ if (!strcasecmp(el->emulated_scheme, Z_STRVAL_P(retval))) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE_CALLBACK); DBG_INF_FMT("Userfunc chose LAZY slave host : [%*s]", el->emulated_scheme_len, el->emulated_scheme); if (PASS == mysqlnd_ms_lazy_connect(el, FALSE TSRMLS_CC)) { ret = el->conn; SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(ret)); } else { char error_buf[128]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " Callback chose %s but connection failed", el->emulated_scheme); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_buf); DBG_ERR_FMT("%s", error_buf); ret = el->conn; /* no automatic action: leave it to the user to decide! */ } } } else { if (!strcasecmp(el->conn->scheme, Z_STRVAL_P(retval))) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE_CALLBACK); ret = el->conn; SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(ret)); DBG_INF_FMT("Userfunc chose slave host : [%*s]", el->conn->scheme_len, el->conn->scheme); } } } } } while (0); if (!ret) { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User filter callback has returned an unknown server. The server '%s' can neither be found in the master list nor in the slave list", Z_STRVAL_P(retval)); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } } else { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User filter callback has not returned string with server to use. The callback must return a string"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } zval_ptr_dtor(&retval); } else { /* We should never get here */ char error_buf[128]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User filter callback did not return server to use"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } #ifdef ALL_SERVER_DISPATCH convert_to_boolean(args[use_all_pos]); Z_DELREF_P(args[use_all_pos]); #endif /* destroy the params */ { unsigned int i; for (i = 0; i <= param; i++) { zval_ptr_dtor(&args[i]); } } } DBG_RETURN(ret); } /* }}} */ /* {{{ my_long_compare */ static int my_long_compare(const void * a, const void * b TSRMLS_DC) { Bucket * f = *((Bucket **) a); Bucket * s = *((Bucket **) b); zval * first = *((zval **) f->pData); zval * second = *((zval **) s->pData); if (Z_LVAL_P(first) > Z_LVAL_P(second)) { return 1; } else if (Z_LVAL_P(first) == Z_LVAL_P(second)) { return 0; } return -1; } /* }}} */ /* {{{ mysqlnd_ms_user_pick_multiple_server */ enum_func_status mysqlnd_ms_user_pick_multiple_server(void * f_data, const char * connect_host, const char * query, size_t query_len, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { MYSQLND_MS_FILTER_USER_DATA * filter_data = (MYSQLND_MS_FILTER_USER_DATA *) f_data; zval * args[7]; zval * retval; enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_ms_user_pick_multiple_server"); DBG_INF_FMT("query(50bytes)=%*s query_is_select=%p", MIN(50, query_len), query, filter_data? filter_data->user_callback:NULL); if (master_list && filter_data && filter_data->user_callback) { uint param = 0; /* connect host */ MS_STRING((char *) connect_host, args[param]); /* query */ param++; MS_STRINGL((char *) query, query_len, args[param]); { MYSQLND_MS_LIST_DATA * el, ** el_pp; zend_llist_position pos; /* master list */ param++; MS_ARRAY(args[param]); for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(master_list, &pos); el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(master_list, &pos)) { if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy */ add_next_index_stringl(args[param], el->emulated_scheme, el->emulated_scheme_len, 1); } else { add_next_index_stringl(args[param], el->conn->scheme, el->conn->scheme_len, 1); } } /* slave list*/ param++; MS_ARRAY(args[param]); if (slave_list) { for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(slave_list, &pos); el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(slave_list, &pos)) { if (CONN_GET_STATE(el->conn) == CONN_ALLOCED) { /* lazy */ add_next_index_stringl(args[param], el->emulated_scheme, el->emulated_scheme_len, 1); } else { add_next_index_stringl(args[param], el->conn->scheme, el->conn->scheme_len, 1); } } } /* last used connection */ param++; MAKE_STD_ZVAL(args[param]); if (stgy->last_used_conn) { ZVAL_STRING(args[param], stgy->last_used_conn->scheme, 1); } else { ZVAL_NULL(args[param]); } /* in transaction */ param++; MAKE_STD_ZVAL(args[param]); if (stgy->in_transaction) { ZVAL_TRUE(args[param]); } else { ZVAL_FALSE(args[param]); } } retval = mysqlnd_ms_call_handler(filter_data->user_callback, param + 1, args, FALSE /*we destroy later*/, error_info TSRMLS_CC); if (retval) { if (Z_TYPE_P(retval) != IS_ARRAY) { char error_buf[256]; DBG_ERR("The user returned no array"); snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has not returned a list of servers to use. The callback must return an array"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } else { do { HashPosition hash_pos; zval ** users_masters, ** users_slaves; DBG_INF("Checking data validity"); /* Check data validity */ { zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(retval), &hash_pos); if (SUCCESS != zend_hash_get_current_data_ex(Z_ARRVAL_P(retval), (void **)&users_masters, &hash_pos) || Z_TYPE_PP(users_masters) != IS_ARRAY || SUCCESS != zend_hash_move_forward_ex(Z_ARRVAL_P(retval), &hash_pos) || SUCCESS != zend_hash_get_current_data_ex(Z_ARRVAL_P(retval), (void **)&users_slaves, &hash_pos) || Z_TYPE_PP(users_slaves) != IS_ARRAY || ( 0 == zend_hash_num_elements(Z_ARRVAL_PP(users_masters)) && 0 == zend_hash_num_elements(Z_ARRVAL_PP(users_slaves)) )) { char error_buf[256]; DBG_ERR("Error in validity"); snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has returned an invalid list of servers to use. The callback must return an array"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); break; } } /* convert to long and sort */ DBG_INF("Converting and sorting"); { zval ** selected_server; /* convert to longs and sort */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(users_masters), &hash_pos); while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(users_masters), (void **)&selected_server, &hash_pos)) { convert_to_long_ex(selected_server); zend_hash_move_forward_ex(Z_ARRVAL_PP(users_masters), &hash_pos); } if (FAILURE == zend_hash_sort(Z_ARRVAL_PP(users_masters), zend_qsort, my_long_compare, 1 TSRMLS_CC)) { char error_buf[256]; DBG_ERR("Error while sorting the master list"); snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has returned an invalid list of servers to use. Error while sorting the master list"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); break; } /* convert to longs and sort */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(users_slaves), &hash_pos); while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(users_slaves), (void **)&selected_server, &hash_pos)) { convert_to_long_ex(selected_server); zend_hash_move_forward_ex(Z_ARRVAL_PP(users_slaves), &hash_pos); } if (FAILURE == zend_hash_sort(Z_ARRVAL_PP(users_slaves), zend_qsort, my_long_compare, 1 TSRMLS_CC)) { char error_buf[256]; DBG_ERR("Error while sorting the slave list"); snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has returned an invalid list of servers to use. Error while sorting the slave list"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); break; } } DBG_INF("Extracting into the supplied lists"); /* extract into llists */ { unsigned int pass; zval ** selected_server; for (pass = 0; pass < 2; pass++) { long i = 0; zend_llist_position list_pos; zend_llist * in_list = (pass == 0)? master_list : slave_list; zend_llist * out_list = (pass == 0)? selected_masters : selected_slaves; MYSQLND_MS_LIST_DATA ** el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(in_list, &list_pos); MYSQLND_MS_LIST_DATA * el = el_pp? *el_pp : NULL; HashTable * conn_hash = (pass == 0)? Z_ARRVAL_PP(users_masters):Z_ARRVAL_PP(users_slaves); DBG_INF_FMT("pass=%u", pass); zend_hash_internal_pointer_reset_ex(conn_hash, &hash_pos); while (SUCCESS == zend_hash_get_current_data_ex(conn_hash, (void **)&selected_server, &hash_pos)) { if (Z_LVAL_PP(selected_server) >= 0) { long server_id = Z_LVAL_PP(selected_server); DBG_INF_FMT("i=%ld server_id=%ld llist_count=%d", i, server_id, zend_llist_count(in_list)); if (server_id >= zend_llist_count(in_list)) { char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has returned an invalid list of servers to use. Server id is too big"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR("server_id too big, skipping and breaking"); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); break; /* skip impossible indices */ } while (i < server_id) { el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(in_list, &list_pos); el = el_pp ? *el_pp : NULL; i++; } if (el && el->conn) { DBG_INF_FMT("gotcha. adding server_id=%ld", server_id); /* This will copy the whole structure, not the pointer. This is wanted!! */ zend_llist_add_element(out_list, &el); } } else { /* either negative offset from user or LVAL casting gets us here */ char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has returned an invalid list of servers to use. Server id is either negative or not a number"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR("server_id is negative, skipping and breaking"); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); break; } zend_hash_move_forward_ex(conn_hash, &hash_pos); } } DBG_INF_FMT("count(master_list)=%d", zend_llist_count(selected_masters)); DBG_INF_FMT("count(slave_list)=%d", zend_llist_count(selected_slaves)); ret = PASS; } } while (0); } zval_ptr_dtor(&retval); } else { /* We should never get here */ char error_buf[256]; snprintf(error_buf, sizeof(error_buf), MYSQLND_MS_ERROR_PREFIX " User multi filter callback has not returned a list of servers to use. The callback must return an array"); error_buf[sizeof(error_buf) - 1] = '\0'; SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, error_buf); DBG_ERR_FMT("%s", error_buf); php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "%s", error_buf); } /* destroy the params */ { unsigned int i; for (i = 0; i <= param; i++) { zval_ptr_dtor(&args[i]); } } } DBG_RETURN(ret); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_filter_user.h0000664000175000017500000000466112161007456020210 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 311510 2011-05-27 19:36:39Z andrey $ */ #ifndef MYSQLND_MS_FILTER_USER_H #define MYSQLND_MS_FILTER_USER_H struct st_mysqlnd_ms_config_json_entry; MYSQLND_CONN_DATA * mysqlnd_ms_user_pick_server(void * f_data, const char * connect_host, const char * query, size_t query_len, zend_llist * master_list, zend_llist * slave_list, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC); enum_func_status mysqlnd_ms_user_pick_multiple_server(void * f_data, const char * connect_host, const char * query, size_t query_len, zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves, struct mysqlnd_ms_lb_strategies * stgy, MYSQLND_ERROR_INFO * error_info TSRMLS_DC); MYSQLND_MS_FILTER_DATA * mysqlnd_ms_user_filter_ctor(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); #endif /* MYSQLND_MS_FILTER_USER_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms.h0000664000175000017500000001111512161007456015575 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.h 330598 2013-06-21 08:25:22Z andrey $ */ #ifndef MYSQLND_MS_H #define MYSQLND_MS_H #ifndef SMART_STR_START_SIZE #define SMART_STR_START_SIZE 1024 #endif #ifndef SMART_STR_PREALLOC #define SMART_STR_PREALLOC 256 #endif #include "ext/standard/php_smart_str.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_statistics.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #include "mysqlnd_ms_enum_n_def.h" #if MYSQLND_VERSION_ID > 50009 #include "ext/mysqlnd/mysqlnd_reverse_api.h" #endif #ifdef ZTS #include "TSRM.h" #endif #define MYSQLND_MS_CONFIG_FORMAT "json" ZEND_BEGIN_MODULE_GLOBALS(mysqlnd_ms) zend_bool enable; zend_bool force_config_usage; const char * config_file; zval * user_pick_server; zend_bool collect_statistics; zend_bool multi_master; zend_bool disable_rw_split; char * config_startup_error; ZEND_END_MODULE_GLOBALS(mysqlnd_ms) #ifdef ZTS #define MYSQLND_MS_G(v) TSRMG(mysqlnd_ms_globals_id, zend_mysqlnd_ms_globals *, v) #else #define MYSQLND_MS_G(v) (mysqlnd_ms_globals.v) #endif #define MYSQLND_MS_VERSION "1.5.2" #define MYSQLND_MS_VERSION_ID 10502 #define MYSQLND_MS_ERROR_PREFIX "(mysqlnd_ms)" extern MYSQLND_STATS * mysqlnd_ms_stats; /* ALREADY FIXED: Keep it false for now or we will have races in connect, where multiple instance can read the slave[] values and so move the pointer of each other. Need to find better implementation of hotloading. Maybe not use `hotloading? FALSE:TRUE` but an expclicit lock around the array extraction of master[] and slave[] and pass FALSE to mysqlnd_ms_json_config_string(), meaning it should not try to get a lock. */ #define MYSLQND_MS_HOTLOADING FALSE extern unsigned int mysqlnd_ms_plugin_id; extern struct st_mysqlnd_ms_json_config * mysqlnd_ms_json_config; ZEND_EXTERN_MODULE_GLOBALS(mysqlnd_ms) void mysqlnd_ms_register_hooks(); void mysqlnd_ms_conn_list_dtor(void * pDest); PHPAPI zend_bool mysqlnd_ms_match_wild(const char * const str, const char * const wildstr TSRMLS_DC); struct st_mysqlnd_ms_list_data; enum_func_status mysqlnd_ms_lazy_connect(struct st_mysqlnd_ms_list_data * element, zend_bool master TSRMLS_DC); void mysqlnd_ms_client_n_php_error(MYSQLND_ERROR_INFO * error_info, unsigned int client_error_code, const char * const client_error_state, unsigned int php_error_level TSRMLS_DC, const char * const format, ...); struct st_ms_token_and_value { unsigned int token; zval value; }; struct st_mysqlnd_query_scanner { void * scanner; zval * token_value; }; struct st_mysqlnd_ms_table_info { char * db; char * table; char * org_table; zend_bool persistent; }; struct st_mysqlnd_ms_field_info { char * db; char * table; char * name; char * org_name; void * custom_data; zend_bool free_custom_data; zend_bool persistent; }; struct st_mysqlnd_parse_info { zend_llist table_list; zend_llist select_field_list; zend_llist where_field_list; zend_llist * active_field_list; zend_bool parse_where; enum_mysql_statement_type statement; zend_bool persistent; }; struct st_mysqlnd_query_parser { struct st_mysqlnd_query_scanner * scanner; struct st_mysqlnd_parse_info parse_info; }; #endif /* MYSQLND_MS_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_lb_weights.c0000664000175000017500000002356612161007456020014 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2012 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Ulf Wendel | | Andrey Hristov | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_switch.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_config_json.h" /* {{{ mysqlnd_ms_filter_lb_weigth_dtor */ void mysqlnd_ms_filter_lb_weigth_dtor(void * pDest) { MYSQLND_MS_FILTER_LB_WEIGHT * element = pDest? *(MYSQLND_MS_FILTER_LB_WEIGHT **) pDest : NULL; TSRMLS_FETCH(); DBG_ENTER("mysqlnd_ms_filter_lb_weigth_dtor"); /* if (element) { mnd_pefree(element, element->persistent); } */ DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_filter_ctor_load_weights_config */ void mysqlnd_ms_filter_ctor_load_weights_config(HashTable * lb_weights_list, const char * filter_name, struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { zend_bool value_exists = FALSE, is_list_value = FALSE; struct st_mysqlnd_ms_config_json_entry * subsection = NULL; HashTable server_names; MYSQLND_MS_LIST_DATA * entry, **entry_pp; zend_llist_position pos; DBG_ENTER("mysqlnd_ms_filter_ctor_load_weights_config"); /* Build server hash table */ zend_hash_init(&server_names, 4, NULL/*hash*/, NULL/*dtor*/, FALSE); for (entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(master_connections, &pos); entry_pp && (entry = *entry_pp) && (entry->name_from_config) && (entry->conn); entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(master_connections, &pos)) { if (SUCCESS != zend_hash_add(&server_names, entry->name_from_config, strlen(entry->name_from_config), entry_pp, sizeof(void *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to setup master server list for '%s' filter. Stopping", filter_name); } } for (entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(slave_connections, &pos); entry_pp && (entry = *entry_pp) && (entry->name_from_config) && (entry->conn); entry_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(slave_connections, &pos)) { if (SUCCESS != zend_hash_add(&server_names, entry->name_from_config, strlen(entry->name_from_config), entry_pp, sizeof(void *), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to setup slave server list for '%s' filter. Stopping", filter_name); } } do { char * current_subsection_name = NULL; size_t current_subsection_name_len = 0; int weight; smart_str fprint_conn = {0}; subsection = mysqlnd_ms_config_json_next_sub_section(section, ¤t_subsection_name, ¤t_subsection_name_len, NULL TSRMLS_CC); if (!subsection) { break; } if (SUCCESS != zend_hash_find(&server_names, current_subsection_name, current_subsection_name_len, (void **)&entry_pp)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Unknown server '%s' in '%s' filter configuration. Stopping", current_subsection_name, filter_name); continue; } weight = mysqlnd_ms_config_json_int_from_section(section, current_subsection_name, current_subsection_name_len, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { if ((weight < 0) || (weight > 65535)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value '%i' for weight. Stopping", weight); } else if (NULL == entry_pp) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Fingerprint is empty. Did you ignore an error about an unknown server? Stopping"); } else { MYSQLND_MS_FILTER_LB_WEIGHT * weight_entry; /* Handle OOM */ weight_entry = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_LB_WEIGHT), persistent); weight_entry->weight = weight_entry->current_weight = weight; weight_entry->persistent = persistent; mysqlnd_ms_get_fingerprint_connection(&fprint_conn, entry_pp TSRMLS_CC); if (SUCCESS != zend_hash_add(lb_weights_list, fprint_conn.c, fprint_conn.len, weight_entry, sizeof(MYSQLND_MS_FILTER_LB_WEIGHT), NULL)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Failed to create internal weights lookup table for filter '%s'. Stopping", filter_name); } smart_str_free(&fprint_conn); } } } while (1); if (zend_hash_num_elements(lb_weights_list) && (zend_hash_num_elements(&server_names) != zend_hash_num_elements(lb_weights_list))) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " You must specify the load balancing weight for none or all configured servers. There is no default weight yet. Stopping"); } DBG_INF_FMT("weights %d", zend_hash_num_elements(lb_weights_list)); zend_hash_destroy(&server_names); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_populate_weights_sort_list */ enum_func_status mysqlnd_ms_populate_weights_sort_list(HashTable * lb_weights_list, zend_llist * lb_sort_list, const zend_llist * const server_list TSRMLS_DC) { int retval = FAILURE; MYSQLND_MS_FILTER_LB_WEIGHT * weight_entry; smart_str fprint_conn = {0}; MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * lb_weight_context; MYSQLND_MS_LIST_DATA * element = NULL; DBG_ENTER("mysqlnd_ms_populate_weights_sort_list"); DBG_INF("Building sort list"); BEGIN_ITERATE_OVER_SERVER_LIST(element, server_list); mysqlnd_ms_get_fingerprint_connection(&fprint_conn, &element TSRMLS_CC); retval = zend_hash_find(lb_weights_list, fprint_conn.c, fprint_conn.len /*\0 counted*/, (void**) &weight_entry); if (SUCCESS == retval) { /* persistent needed in weight entry - could take from element/conn */ lb_weight_context = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT), weight_entry->persistent); /* TODO: are we getting a pointer to the main list ? */ lb_weight_context->lb_weight = weight_entry; lb_weight_context->element = element; zend_llist_add_element(lb_sort_list, &lb_weight_context); } if (SUCCESS != retval) { DBG_INF_FMT("Failed to create sort list, fingerprint -%s- %d", fprint_conn.c, fprint_conn.len); smart_str_free(&fprint_conn); break; } smart_str_free(&fprint_conn); END_ITERATE_OVER_SERVER_LIST; DBG_RETURN(retval == SUCCESS? PASS:FAIL); } /* }}} */ /* {{{ mysqlnd_ms_weights_comparator */ static int mysqlnd_ms_weights_comparator(const zend_llist_element ** el1, const zend_llist_element ** el2 TSRMLS_DC) { MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * w1 = (el1 && *el1 && (*el1)->data) ? *(MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)((*el1)->data) : NULL; MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT * w2 = (el2 && *el2 && (*el2)->data) ? *(MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT **)((*el2)->data) : NULL; int ret = 0; DBG_ENTER("mysqlnd_ms_weights_comparator"); if ((w1) && (w1->lb_weight) && (w2) && (w2->lb_weight)) { if (((MYSQLND_MS_FILTER_LB_WEIGHT *)w1->lb_weight)->current_weight < ((MYSQLND_MS_FILTER_LB_WEIGHT *)w2->lb_weight)->current_weight) { ret = 1; } else if (((MYSQLND_MS_FILTER_LB_WEIGHT *)w1->lb_weight)->current_weight > ((MYSQLND_MS_FILTER_LB_WEIGHT *)w2->lb_weight)->current_weight) { ret = -1; } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_sort_weights_context_list */ void mysqlnd_ms_weight_list_init(zend_llist * wl TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_weight_list_init"); zend_llist_init(wl, sizeof(MYSQLND_MS_FILTER_LB_WEIGHT_IN_CONTEXT *), NULL, 1); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_weight_list_sort */ void mysqlnd_ms_weight_list_sort(zend_llist * wl TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_weight_list_init"); zend_llist_sort(wl, mysqlnd_ms_weights_comparator TSRMLS_CC); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_weight_list_deinit */ void mysqlnd_ms_weight_list_deinit(zend_llist * wl TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_weight_list_deinit"); zend_llist_clean(wl); DBG_VOID_RETURN; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_lb_weights.h0000664000175000017500000000437612161007456020017 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: $ */ #ifndef MYSQLND_MS_LB_WEIGHTS_H #define MYSQLND_MS_LB_WEIGHTS_H struct st_mysqlnd_ms_config_json_entry; void mysqlnd_ms_filter_lb_weigth_dtor(void * pDest); void mysqlnd_ms_filter_ctor_load_weights_config(HashTable * lb_weights_list, const char * filter_name, struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); enum_func_status mysqlnd_ms_populate_weights_sort_list(HashTable * lb_weights_list, zend_llist * lb_sort_list, const zend_llist * const server_list TSRMLS_DC); int mysqlnd_ms_sort_weights_context_list(const zend_llist_element ** el1, const zend_llist_element ** el2 TSRMLS_DC); void mysqlnd_ms_weight_list_init(zend_llist * wl TSRMLS_DC); void mysqlnd_ms_weight_list_sort(zend_llist * wl TSRMLS_DC); void mysqlnd_ms_weight_list_deinit(zend_llist * wl TSRMLS_DC); #endif /* MYSQLND_MS_LB_WEIGHTS_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_switch.c0000664000175000017500000007772612161007456017175 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms.c 311179 2011-05-18 11:26:22Z andrey $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/info.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #ifndef mnd_emalloc #include "ext/mysqlnd/mysqlnd_alloc.h" #endif #ifndef mnd_sprintf #define mnd_sprintf spprintf #endif #include "mysqlnd_ms.h" #include "ext/standard/php_rand.h" #include "mysqlnd_query_parser.h" #include "mysqlnd_qp.h" #include "mysqlnd_ms_enum_n_def.h" #include "mysqlnd_ms_config_json.h" #include "mysqlnd_ms_filter_user.h" #include "mysqlnd_ms_filter_random.h" #include "mysqlnd_ms_filter_round_robin.h" #include "mysqlnd_ms_filter_table_partition.h" #include "mysqlnd_ms_filter_qos.h" #include "mysqlnd_ms_filter_groups.h" #include "mysqlnd_ms_switch.h" typedef MYSQLND_MS_FILTER_DATA * (*func_filter_ctor)(struct st_mysqlnd_ms_config_json_entry * section, zend_llist * master_connections, zend_llist * slave_connections, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); struct st_specific_ctor_with_name { const char * name; size_t name_len; func_filter_ctor ctor; enum mysqlnd_ms_server_pick_strategy pick_type; zend_bool multi_filter; }; /* TODO: write copy ctors */ static const struct st_specific_ctor_with_name specific_ctors[] = { {PICK_RROBIN, sizeof(PICK_RROBIN) - 1, mysqlnd_ms_rr_filter_ctor, SERVER_PICK_RROBIN, FALSE}, {PICK_RANDOM, sizeof(PICK_RANDOM) - 1, mysqlnd_ms_random_filter_ctor, SERVER_PICK_RANDOM, FALSE}, {PICK_USER, sizeof(PICK_USER) - 1, mysqlnd_ms_user_filter_ctor, SERVER_PICK_USER, FALSE}, {PICK_USER_MULTI, sizeof(PICK_USER_MULTI) - 1, mysqlnd_ms_user_filter_ctor, SERVER_PICK_USER_MULTI, TRUE}, #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION {PICK_TABLE, sizeof(PICK_TABLE) - 1, mysqlnd_ms_table_filter_ctor, SERVER_PICK_TABLE, TRUE}, #endif {PICK_QOS, sizeof(PICK_QOS) - 1, mysqlnd_ms_qos_filter_ctor, SERVER_PICK_QOS, TRUE}, {PICK_GROUPS, sizeof(PICK_GROUPS) - 1, mysqlnd_ms_groups_filter_ctor, SERVER_PICK_GROUPS, TRUE}, {NULL, 0, NULL, SERVER_PICK_LAST_ENUM_ENTRY, FALSE} }; /* {{{ get_element_ptr */ static void mysqlnd_ms_get_element_ptr(void * d, void * arg TSRMLS_DC) { MYSQLND_MS_LIST_DATA * data = d? *(MYSQLND_MS_LIST_DATA **) d : NULL ; char ptr_buf[SIZEOF_SIZE_T + 1]; smart_str * context = (smart_str *) arg; DBG_ENTER("mysqlnd_ms_get_element_ptr"); DBG_INF_FMT("ptr=%p", data->conn); if (data) { #if SIZEOF_SIZE_T == 8 int8store(ptr_buf, (size_t) data->conn); #elif SIZEOF_SIZE_T == 4 int4store(ptr_buf, (size_t) data->conn); #else #error Unknown platform #endif ptr_buf[SIZEOF_SIZE_T] = '\0'; DBG_INF_FMT("data->conn=%p ptr_buf='%s'", data->conn, ptr_buf); smart_str_appendl(context, ptr_buf, SIZEOF_SIZE_T); } else { DBG_INF("No data!"); } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_get_fingerprint */ void mysqlnd_ms_get_fingerprint(smart_str * context, zend_llist * list TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_get_fingerprint"); zend_llist_apply_with_argument(list, mysqlnd_ms_get_element_ptr, context TSRMLS_CC); smart_str_appendc(context, '\0'); DBG_INF_FMT("len=%d", context->len); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_get_fingerprint_connection */ void mysqlnd_ms_get_fingerprint_connection(smart_str * context, MYSQLND_MS_LIST_DATA ** d TSRMLS_DC) { DBG_ENTER("mysqlnd_ms_get_fingerprint_connection"); mysqlnd_ms_get_element_ptr((void *) d, (void *)context TSRMLS_CC); smart_str_appendc(context, '\0'); DBG_INF_FMT("context=%s len=%d", context->c, context->len); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_filter_list_dtor */ static void mysqlnd_ms_filter_list_dtor(void * pDest) { MYSQLND_MS_FILTER_DATA * filter = *(MYSQLND_MS_FILTER_DATA **) pDest; TSRMLS_FETCH(); DBG_ENTER("mysqlnd_ms_filter_list_dtor"); DBG_INF_FMT("%p", filter); if (filter) { zend_bool pers = filter->persistent; DBG_INF_FMT("name=%s dtor=%p", filter->name? filter->name:"n/a", filter->filter_dtor); if (filter->name) { mnd_pefree(filter->name, pers); } if (filter->filter_dtor) { filter->filter_dtor(filter TSRMLS_CC); } else { mnd_pefree(filter, pers); } } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_lb_strategy_setup */ void mysqlnd_ms_lb_strategy_setup(struct mysqlnd_ms_lb_strategies * strategies, struct st_mysqlnd_ms_config_json_entry * the_section, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC) { zend_bool value_exists = FALSE, is_list_value = FALSE; DBG_ENTER("mysqlnd_ms_lb_strategy_setup"); { struct st_mysqlnd_ms_config_json_entry * failover_section = mysqlnd_ms_config_json_sub_section(the_section, FAILOVER_NAME, sizeof(FAILOVER_NAME) - 1, &value_exists TSRMLS_CC); strategies->failover_strategy = DEFAULT_FAILOVER_STRATEGY; strategies->failover_max_retries = DEFAULT_FAILOVER_MAX_RETRIES; strategies->failover_remember_failed = DEFAULT_FAILOVER_REMEMBER_FAILED; if (value_exists) { int64_t failover_max_retries; char * remember_failed; /* 1.4.0 syntax failover: { strategy: ...} */ char * failover_strategy = mysqlnd_ms_config_json_string_from_section(failover_section, FAILOVER_STRATEGY_NAME, sizeof(FAILOVER_STRATEGY_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (!value_exists) { /* pre 1.4.0 syntax failover : { disabled|... } */ failover_strategy = mysqlnd_ms_config_json_string_from_section(the_section, FAILOVER_NAME, sizeof(FAILOVER_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); } if (value_exists && failover_strategy) { /* 1.4.0 syntax failover: { strategy: ...} */ if (!strncasecmp(FAILOVER_STRATEGY_DISABLED, failover_strategy, sizeof(FAILOVER_STRATEGY_DISABLED) - 1)) { strategies->failover_strategy = SERVER_FAILOVER_DISABLED; } else if (!strncasecmp(FAILOVER_STRATEGY_MASTER, failover_strategy, sizeof(FAILOVER_STRATEGY_MASTER) - 1)) { strategies->failover_strategy = SERVER_FAILOVER_MASTER; } else if (!strncasecmp(FAILOVER_STRATEGY_LOOP, failover_strategy, sizeof(FAILOVER_STRATEGY_LOOP) - 1)) { strategies->failover_strategy = SERVER_FAILOVER_LOOP; } mnd_efree(failover_strategy); } failover_max_retries = mysqlnd_ms_config_json_int_from_section(failover_section, FAILOVER_MAX_RETRIES, sizeof(FAILOVER_MAX_RETRIES) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { if ((failover_max_retries < 0) || (failover_max_retries > 65535)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_RECOVERABLE_ERROR TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Invalid value '%i' for max_retries. Stopping", failover_max_retries); } else { strategies->failover_max_retries = (uint)failover_max_retries; } } remember_failed = mysqlnd_ms_config_json_string_from_section(failover_section, FAILOVER_REMEMBER_FAILED, sizeof(FAILOVER_REMEMBER_FAILED) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); if (value_exists) { strategies->failover_remember_failed = !mysqlnd_ms_config_json_string_is_bool_false(remember_failed); if (strategies->failover_remember_failed) { /* should we do a lazy init? */ zend_hash_init(&strategies->failed_hosts, 8, NULL/*hash*/, NULL/*dtor*/, persistent); } mnd_efree(remember_failed); } } } { char * master_on_write = mysqlnd_ms_config_json_string_from_section(the_section, MASTER_ON_WRITE_NAME, sizeof(MASTER_ON_WRITE_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); strategies->mysqlnd_ms_flag_master_on_write = FALSE; strategies->master_used = FALSE; if (value_exists && master_on_write) { DBG_INF("Master on write active"); strategies->mysqlnd_ms_flag_master_on_write = !mysqlnd_ms_config_json_string_is_bool_false(master_on_write); mnd_efree(master_on_write); } } { char * trx_strategy = mysqlnd_ms_config_json_string_from_section(the_section, TRX_STICKINESS_NAME, sizeof(TRX_STICKINESS_NAME) - 1, 0, &value_exists, &is_list_value TSRMLS_CC); strategies->trx_stickiness_strategy = DEFAULT_TRX_STICKINESS_STRATEGY; strategies->trx_stop_switching = FALSE; strategies->trx_read_only = FALSE; strategies->in_transaction = FALSE; if (value_exists && trx_strategy) { #if PHP_VERSION_ID >= 50399 if (!strncasecmp(TRX_STICKINESS_MASTER, trx_strategy, sizeof(TRX_STICKINESS_MASTER) - 1)) { DBG_INF("trx_stickiness = master"); strategies->trx_stickiness_strategy = TRX_STICKINESS_STRATEGY_MASTER; #if PHP_VERSION_ID >= 50499 } else if (!strncasecmp(TRX_STICKINESS_ON, trx_strategy, sizeof(TRX_STICKINESS_ON) - 1)) { DBG_INF("trx_stickiness = on"); strategies->trx_stickiness_strategy = TRX_STICKINESS_STRATEGY_ON; #endif } #else SET_CLIENT_ERROR((*error_info), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, MYSQLND_MS_ERROR_PREFIX " trx_stickiness strategy is not supported before PHP 5.4.0"); php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " trx_stickiness strategy is not supported before PHP 5.4.0"); #endif mnd_efree(trx_strategy); } } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_section_filters_add_filter */ static MYSQLND_MS_FILTER_DATA * mysqlnd_ms_section_filters_add_filter(zend_llist * filters, struct st_mysqlnd_ms_config_json_entry * filter_config, const char * const filter_name, const size_t filter_name_len, zend_llist * master_connections, zend_llist * slave_connections, const zend_bool persistent, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { MYSQLND_MS_FILTER_DATA * new_filter_entry = NULL; DBG_ENTER("mysqlnd_ms_section_filters_add_filter"); if (filter_name && filter_name_len) { unsigned int i = 0; /* find specific ctor, if available */ while (specific_ctors[i].name) { DBG_INF_FMT("current_ctor->name=%s", specific_ctors[i].name); if (!strcasecmp(specific_ctors[i].name, filter_name)) { if (zend_llist_count(filters)) { zend_llist_position llist_pos; MYSQLND_MS_FILTER_DATA * prev = *(MYSQLND_MS_FILTER_DATA **)zend_llist_get_last_ex(filters, &llist_pos); if (FALSE == prev->multi_filter) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, 0 TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Error while creating filter '%s' . " "Non-multi filter '%s' already created. Stopping", filter_name, prev->name); DBG_RETURN(NULL); } } if (specific_ctors[i].ctor) { new_filter_entry = specific_ctors[i].ctor(filter_config, master_connections, slave_connections, error_info, persistent TSRMLS_CC); if (!new_filter_entry) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, 0 TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Error while creating filter '%s' . Stopping", filter_name); DBG_RETURN(NULL); } } else { new_filter_entry = mnd_pecalloc(1, sizeof(MYSQLND_MS_FILTER_DATA), persistent); } new_filter_entry->persistent = persistent; new_filter_entry->name = mnd_pestrndup(filter_name, filter_name_len, persistent); new_filter_entry->name_len = filter_name_len; new_filter_entry->pick_type = specific_ctors[i].pick_type; new_filter_entry->multi_filter = specific_ctors[i].multi_filter; zend_llist_add_element(filters, &new_filter_entry); break; } ++i; } } if (!new_filter_entry) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, 0 TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX" Unknown filter '%s' . Stopping", filter_name); } DBG_RETURN(new_filter_entry); } /* }}} */ /* {{{ mysqlnd_ms_load_section_filters */ zend_llist * mysqlnd_ms_load_section_filters(struct st_mysqlnd_ms_config_json_entry * section, MYSQLND_ERROR_INFO * error_info, zend_llist * master_connections, zend_llist * slave_connections, zend_bool persistent TSRMLS_DC) { zend_llist * ret = NULL; DBG_ENTER("mysqlnd_ms_load_section_filters"); if (section) { ret = mnd_pemalloc(sizeof(zend_llist), persistent); } if (ret) { zend_bool section_exists; struct st_mysqlnd_ms_config_json_entry * filters_section = mysqlnd_ms_config_json_sub_section(section, SECT_FILTER_NAME, sizeof(SECT_FILTER_NAME) - 1, §ion_exists TSRMLS_CC); zend_llist_init(ret, sizeof(MYSQLND_MS_FILTER_DATA *), (llist_dtor_func_t) mysqlnd_ms_filter_list_dtor /*dtor*/, persistent); DBG_INF_FMT("normal filters section =%d", section_exists && filters_section); switch (section_exists && filters_section? 1:0) { case 1: do { char * filter_name = NULL; size_t filter_name_len = 0; ulong filter_int_name; struct st_mysqlnd_ms_config_json_entry * current_filter = mysqlnd_ms_config_json_next_sub_section(filters_section, &filter_name, &filter_name_len, &filter_int_name TSRMLS_CC); if (!current_filter || !filter_name || !filter_name_len) { if (current_filter) { char error_buf[128]; if (filter_name && !filter_name_len) { snprintf(error_buf, sizeof(error_buf), "Error loading filters. Filter with empty name found"); } else if (FALSE == mysqlnd_ms_config_json_section_is_list(current_filter TSRMLS_CC)) { /* filter_int_name */ filter_name = mysqlnd_ms_config_json_string_from_section(filters_section, NULL, 0, filter_int_name, NULL, NULL TSRMLS_CC); filter_name_len = strlen(filter_name); DBG_INF_FMT("%d was found as key, the value is %s", filter_int_name, filter_name); if (NULL == mysqlnd_ms_section_filters_add_filter(ret, current_filter, filter_name, filter_name_len, master_connections, slave_connections, persistent, error_info TSRMLS_CC)) { mnd_pefree(filter_name, 0); goto err; } mnd_pefree(filter_name, 0); continue; } else { snprintf(error_buf, sizeof(error_buf), "Unknown filter '%d' . Stopping", filter_int_name); } error_buf[sizeof(error_buf) - 1] = '\0'; mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, 0 TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " %s", error_buf); goto err; } DBG_INF("no next sub-section"); break; } if (NULL == mysqlnd_ms_section_filters_add_filter(ret, current_filter, filter_name, filter_name_len, master_connections, slave_connections, persistent, error_info TSRMLS_CC)) { goto err; } } while (1); if (zend_llist_count(ret)) { zend_llist_position llist_pos; MYSQLND_MS_FILTER_DATA * prev = *(MYSQLND_MS_FILTER_DATA **)zend_llist_get_last_ex(ret, &llist_pos); if (FALSE != prev->multi_filter) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Error in configuration. Last filter is multi filter. " "Needs to be non-multi one. Stopping"); goto err; } break; } /* fall-through */ case 0: { /* setup the default */ unsigned int i = 0; DBG_INF("No section, using defaults"); while (specific_ctors[i].name) { if (DEFAULT_PICK_STRATEGY == specific_ctors[i].pick_type) { DBG_INF_FMT("Found default pick strategy : %s", specific_ctors[i].name); if (NULL == mysqlnd_ms_section_filters_add_filter(ret, NULL, specific_ctors[i].name, specific_ctors[i].name_len, master_connections, slave_connections, persistent, error_info TSRMLS_CC)) { mysqlnd_ms_client_n_php_error(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Can't load default filter '%d' . Stopping", specific_ctors[i].name); goto err; } break; } ++i; } } } } DBG_RETURN(ret); err: zend_llist_clean(ret); mnd_pefree(ret, persistent); DBG_RETURN(NULL); } /* }}} */ /* {{{ mysqlnd_ms_query_is_select */ PHPAPI enum enum_which_server mysqlnd_ms_query_is_select(const char * query, size_t query_len, zend_bool * forced TSRMLS_DC) { enum enum_which_server ret = USE_MASTER; struct st_ms_token_and_value token = {0}; struct st_mysqlnd_query_scanner * scanner; DBG_ENTER("mysqlnd_ms_query_is_select"); *forced = FALSE; if (!query) { DBG_RETURN(USE_MASTER); } scanner = mysqlnd_qp_create_scanner(TSRMLS_C); mysqlnd_qp_set_string(scanner, query, query_len TSRMLS_CC); token = mysqlnd_qp_get_token(scanner TSRMLS_CC); DBG_INF_FMT("token=COMMENT? = %d", token.token == QC_TOKEN_COMMENT); while (token.token == QC_TOKEN_COMMENT) { size_t comment_len = Z_STRLEN(token.value); char * comment = Z_STRVAL(token.value); while (*comment && isspace(*comment)) { ++comment; --comment_len; } if ((comment_len >= sizeof(MASTER_SWITCH)) && (comment[sizeof(MASTER_SWITCH)] == '\0' || isspace(comment[sizeof(MASTER_SWITCH)])) && !strncasecmp(comment, MASTER_SWITCH, sizeof(MASTER_SWITCH) - 1)) { DBG_INF("forced master"); ret = USE_MASTER; *forced = TRUE; MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER_FORCED); } else if ((comment_len >= sizeof(SLAVE_SWITCH)) && (comment[sizeof(SLAVE_SWITCH)] == '\0' || isspace(comment[sizeof(SLAVE_SWITCH)])) && !strncasecmp(comment, SLAVE_SWITCH, sizeof(SLAVE_SWITCH) - 1)) { DBG_INF("forced slave"); if (MYSQLND_MS_G(disable_rw_split)) { ret = USE_MASTER; } else { ret = USE_SLAVE; MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE_FORCED); } *forced = TRUE; } else if ((comment_len >= sizeof(LAST_USED_SWITCH)) && (comment[sizeof(LAST_USED_SWITCH)] == '\0' || isspace(comment[sizeof(LAST_USED_SWITCH)])) && !strncasecmp(comment, LAST_USED_SWITCH, sizeof(LAST_USED_SWITCH) - 1)) { DBG_INF("forced last used"); ret = USE_LAST_USED; *forced = TRUE; MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_LAST_USED_FORCED); #ifdef ALL_SERVER_DISPATCH } else if ((comment_len >= sizeof(ALL_SERVER_SWITCH)) && (comment[sizeof(ALL_SERVER_SWITCH)] == '\0' || isspace(comment[sizeof(ALL_SERVER_SWITCH)])) && !strncasecmp(comment, ALL_SERVER_SWITCH, sizeof(ALL_SERVER_SWITCH) - 1)) { DBG_INF("forced all server"); ret = USE_ALL; *forced = TRUE; #endif } zval_dtor(&token.value); token = mysqlnd_qp_get_token(scanner TSRMLS_CC); } if (*forced == FALSE) { if (MYSQLND_MS_G(disable_rw_split)) { ret = USE_MASTER; } else if (token.token == QC_TOKEN_SELECT) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE_GUESS); ret = USE_SLAVE; #ifdef ALL_SERVER_DISPATCH } else if (token.token == QC_TOKEN_SET) { ret = USE_ALL; #endif } else { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER_GUESS); ret = USE_MASTER; } } zval_dtor(&token.value); mysqlnd_qp_free_scanner(scanner TSRMLS_CC); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_ms_pick_first_master_or_slave */ MYSQLND_CONN_DATA * mysqlnd_ms_pick_first_master_or_slave(const MYSQLND_CONN_DATA * const conn TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); zend_llist * master_list = &(*conn_data)->master_connections; zend_llist * slave_list = &(*conn_data)->slave_connections; struct mysqlnd_ms_lb_strategies * stgy = &(*conn_data)->stgy; MYSQLND_MS_LIST_DATA * el; DBG_ENTER("mysqlnd_ms_pick_first_master_or_slave"); BEGIN_ITERATE_OVER_SERVER_LIST(el, master_list); if (CONN_GET_STATE(el->conn) == CONN_ALLOCED && PASS == mysqlnd_ms_lazy_connect(el, FALSE TSRMLS_CC)) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_MASTER); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(el->conn)); /* Real Success !! */ DBG_RETURN(stgy->last_used_conn = el->conn); } END_ITERATE_OVER_SERVER_LIST; BEGIN_ITERATE_OVER_SERVER_LIST(el, slave_list); if (CONN_GET_STATE(el->conn) == CONN_ALLOCED && PASS == mysqlnd_ms_lazy_connect(el, FALSE TSRMLS_CC)) { MYSQLND_MS_INC_STATISTIC(MS_STAT_USE_SLAVE); SET_EMPTY_ERROR(MYSQLND_MS_ERROR_INFO(el->conn)); /* Real Success !! */ DBG_RETURN(stgy->last_used_conn = el->conn); } END_ITERATE_OVER_SERVER_LIST; DBG_RETURN(NULL); } /* }}} */ /* {{{ mysqlnd_ms_select_servers_all */ enum_func_status mysqlnd_ms_select_servers_all(zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves TSRMLS_DC) { const MYSQLND_MS_LIST_DATA * el; DBG_ENTER("mysqlnd_ms_select_servers_all"); BEGIN_ITERATE_OVER_SERVER_LIST(el, master_list); zend_llist_add_element(selected_masters, &el); END_ITERATE_OVER_SERVER_LIST; BEGIN_ITERATE_OVER_SERVER_LIST(el, slave_list); zend_llist_add_element(selected_slaves, &el); END_ITERATE_OVER_SERVER_LIST; DBG_RETURN(PASS); } /* }}} */ /* {{{ mysqlnd_ms_pick_server_ex */ MYSQLND_CONN_DATA * mysqlnd_ms_pick_server_ex(MYSQLND_CONN_DATA * conn, char ** query, size_t * query_len, zend_bool * free_query TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, conn); MYSQLND_CONN_DATA * connection = conn; DBG_ENTER("mysqlnd_ms_pick_server_ex"); DBG_INF_FMT("conn_data=%p *conn_data=%p", conn_data, conn_data? *conn_data : NULL); if (conn_data && *conn_data) { zend_bool allow_master_for_slave = FALSE; struct mysqlnd_ms_lb_strategies * stgy = &(*conn_data)->stgy; zend_llist * filters = stgy->filters; zend_llist * master_list = &(*conn_data)->master_connections; zend_llist * slave_list = &(*conn_data)->slave_connections; zend_llist * selected_masters = NULL, * selected_slaves = NULL; zend_llist * output_masters = NULL, * output_slaves = NULL; MYSQLND_MS_FILTER_DATA * filter, ** filter_pp; zend_llist_position pos; *free_query = FALSE; /* order of allocation and initialisation is important !*/ /* 1. */ selected_masters = mnd_pemalloc(sizeof(zend_llist), conn->persistent); if (!selected_masters) { goto end; } zend_llist_init(selected_masters, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, conn->persistent); /* 2. */ selected_slaves = mnd_pemalloc(sizeof(zend_llist), conn->persistent); if (!selected_slaves) { goto end; } zend_llist_init(selected_slaves, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, conn->persistent); /* 3. */ output_masters = mnd_pemalloc(sizeof(zend_llist), conn->persistent); if (!output_masters) { goto end; } zend_llist_init(output_masters, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, conn->persistent); /* 4. */ output_slaves = mnd_pemalloc(sizeof(zend_llist), conn->persistent); if (!output_slaves) { goto end; } zend_llist_init(output_slaves, sizeof(MYSQLND_MS_LIST_DATA *), NULL /*dtor*/, conn->persistent); mysqlnd_ms_select_servers_all(master_list, slave_list, selected_masters, selected_slaves TSRMLS_CC); connection = NULL; for (filter_pp = (MYSQLND_MS_FILTER_DATA **) zend_llist_get_first_ex(filters, &pos); filter_pp && (filter = *filter_pp); filter_pp = (MYSQLND_MS_FILTER_DATA **) zend_llist_get_next_ex(filters, &pos)) { zend_bool trx_continue_filtering = FALSE; zend_bool multi_filter = FALSE; zend_bool multi_filter_single_conn_continue_search = TRUE; if (zend_llist_count(output_masters) || zend_llist_count(output_slaves)) { /* swap and clean */ zend_llist * tmp_sel_masters = selected_masters; zend_llist * tmp_sel_slaves = selected_slaves; zend_llist_clean(selected_masters); zend_llist_clean(selected_slaves); selected_masters = output_masters; selected_slaves = output_slaves; output_masters = tmp_sel_masters; output_slaves = tmp_sel_slaves; } switch (filter->pick_type) { case SERVER_PICK_USER: connection = mysqlnd_ms_user_pick_server(filter, (*conn_data)->connect_host, (const char * const)*query, *query_len, selected_masters, selected_slaves, stgy, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); break; case SERVER_PICK_USER_MULTI: multi_filter = TRUE; /* TODO: Should we really stop filtering if a user multi filter returns only one server? User might have returned zero masters for upcoming SELECT. */ multi_filter_single_conn_continue_search = FALSE; mysqlnd_ms_user_pick_multiple_server(filter, (*conn_data)->connect_host, (const char * const)*query, *query_len, selected_masters, selected_slaves, output_masters, output_slaves, stgy, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); break; #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION case SERVER_PICK_TABLE: if (FALSE == stgy->trx_stop_switching) { multi_filter = TRUE; multi_filter_single_conn_continue_search = TRUE; mysqlnd_ms_choose_connection_table_filter(filter, (const char * const)*query, *query_len, CONN_GET_STATE(conn) > CONN_ALLOCED? conn->connect_or_select_db: (*conn_data)->cred.db, selected_masters, selected_slaves, output_masters, output_slaves, stgy, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); } else { trx_continue_filtering = TRUE; } break; #endif case SERVER_PICK_RANDOM: connection = mysqlnd_ms_choose_connection_random(filter, (const char * const)*query, *query_len, stgy, &MYSQLND_MS_ERROR_INFO(conn), selected_masters, selected_slaves, NULL, allow_master_for_slave TSRMLS_CC); break; case SERVER_PICK_RROBIN: connection = mysqlnd_ms_choose_connection_rr(filter, (const char * const)*query, *query_len, stgy, &MYSQLND_MS_ERROR_INFO(conn), selected_masters, selected_slaves, NULL, allow_master_for_slave TSRMLS_CC); break; case SERVER_PICK_QOS: /* TODO: MS must not bail if slave or master list is empty, mostly handled in 1.5 */ if (FALSE == stgy->trx_stop_switching) { multi_filter = TRUE; multi_filter_single_conn_continue_search = TRUE; allow_master_for_slave = TRUE; mysqlnd_ms_choose_connection_qos(conn, filter, (*conn_data)->connect_host, query, query_len, free_query, selected_masters, selected_slaves, output_masters, output_slaves, stgy, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); } else { trx_continue_filtering = TRUE; } break; case SERVER_PICK_GROUPS: /* TODO: MS must not bail if slave or master list is empty */ if (FALSE == stgy->trx_stop_switching) { multi_filter = TRUE; multi_filter_single_conn_continue_search = TRUE; mysqlnd_ms_choose_connection_groups(conn, filter, (*conn_data)->connect_host, query, query_len, selected_masters, selected_slaves, output_masters, output_slaves, stgy, &MYSQLND_MS_ERROR_INFO(conn) TSRMLS_CC); } break; default: mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Unknown pick type"); } DBG_INF_FMT("out_masters_count=%d out_slaves_count=%d", zend_llist_count(output_masters), zend_llist_count(output_slaves)); if (trx_continue_filtering) { continue; } /* if a multi-connection filter reduces the list to a single connection, then use this connection */ if (!connection && multi_filter == TRUE && (1 == zend_llist_count(output_masters) + zend_llist_count(output_slaves)) && (FALSE == multi_filter_single_conn_continue_search)) { MYSQLND_MS_LIST_DATA ** el_pp; if (zend_llist_count(output_masters)) { el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first(output_masters); } else { el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first(output_slaves); } if (el_pp && (*el_pp)->conn) { MYSQLND_MS_LIST_DATA * element = *el_pp; if (CONN_GET_STATE(element->conn) == CONN_ALLOCED) { DBG_INF("Lazy connection, trying to connect..."); /* lazy connection, connect now */ if (PASS != mysqlnd_ms_lazy_connect(element, zend_llist_count(output_masters)? TRUE:FALSE TSRMLS_CC)) { DBG_INF_FMT("Using master connection "MYSQLND_LLU_SPEC"", element->conn->thread_id); connection = element->conn; } } else { connection = element->conn; } } } if (!connection && (multi_filter == FALSE)) { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " No connection selected by the last filter"); stgy->last_used_conn = conn; goto end; } if (!connection && (0 == zend_llist_count(output_masters) && 0 == zend_llist_count(output_slaves))) { /* filtered everything out */ if ((SERVER_FAILOVER_MASTER == stgy->failover_strategy) || (SERVER_FAILOVER_LOOP == stgy->failover_strategy)) { DBG_INF("FAILOVER"); connection = conn; } else { mysqlnd_ms_client_n_php_error(&MYSQLND_MS_ERROR_INFO(conn), CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, E_WARNING TSRMLS_CC, MYSQLND_MS_ERROR_PREFIX " Couldn't find the appropriate master connection. Something is wrong"); stgy->last_used_conn = conn; goto end; } } if (connection) { /* filter till we get one, for now this is just a hack, not the ultimate solution */ break; } } stgy->last_used_conn = connection; end: if (selected_masters) { zend_llist_clean(selected_masters); mnd_pefree(selected_masters, conn->persistent); } if (selected_slaves) { zend_llist_clean(selected_slaves); mnd_pefree(selected_slaves, conn->persistent); } if (output_masters) { zend_llist_clean(output_masters); mnd_pefree(output_masters, conn->persistent); } if (output_slaves) { zend_llist_clean(output_slaves); mnd_pefree(output_slaves, conn->persistent); } #if 0 if (!connection) { connection = conn; } #endif } DBG_RETURN(connection); } /* }}} */ #ifdef ALL_SERVER_DISPATCH /* {{{ mysqlnd_ms_query_all */ static enum_func_status mysqlnd_ms_query_all(MYSQLND * const proxy_conn, const char * query, unsigned int query_len, zend_llist * master_connections, zend_llist * slave_connections TSRMLS_DC) { MS_DECLARE_AND_LOAD_CONN_DATA(conn_data, proxy_conn); enum_func_status ret = PASS; DBG_ENTER("mysqlnd_ms_query_all"); if (!conn_data || !*conn_data) { DBG_RETURN(MS_CALL_ORIGINAL_CONN_DATA_METHOD(query)(proxy_conn, query, query_len TSRMLS_CC)); } else { zend_llist * lists[] = {NULL, &(*conn_data)->master_connections, &(*conn_data)->slave_connections, NULL}; zend_llist ** list = lists; while (*++list) { zend_llist_position pos; MYSQLND_MS_LIST_DATA * el, ** el_pp; /* search the list of easy handles hanging off the multi-handle */ for (el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_first_ex(*list, &pos); el_pp && (el = *el_pp) && el->conn; el_pp = (MYSQLND_MS_LIST_DATA **) zend_llist_get_next_ex(*list, &pos)) { if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(query)(el->conn, query, query_len TSRMLS_CC)) { ret = FAIL; } } } } DBG_RETURN(ret); } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_ms_switch.h0000664000175000017500000000532712161007456017166 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_ms_enum_n_def.h 311091 2011-05-16 15:42:48Z andrey $ */ #ifndef MYSQLND_MS_SWITCH_H #define MYSQLND_MS_SWITCH_H struct mysqlnd_ms_lb_strategies; struct st_mysqlnd_ms_config_json_entry; PHPAPI enum enum_which_server mysqlnd_ms_query_is_select(const char * query, size_t query_len, zend_bool * forced TSRMLS_DC); zend_llist * mysqlnd_ms_load_section_filters(struct st_mysqlnd_ms_config_json_entry * section, MYSQLND_ERROR_INFO * error_info, zend_llist * master_connections, zend_llist * slave_connections, zend_bool persistent TSRMLS_DC); void mysqlnd_ms_lb_strategy_setup(struct mysqlnd_ms_lb_strategies * strategies, struct st_mysqlnd_ms_config_json_entry * the_section, MYSQLND_ERROR_INFO * error_info, zend_bool persistent TSRMLS_DC); MYSQLND_CONN_DATA * mysqlnd_ms_pick_server_ex(MYSQLND_CONN_DATA * conn, char ** query, size_t * query_len, zend_bool * free_query TSRMLS_DC); void mysqlnd_ms_get_fingerprint(smart_str * context, zend_llist * list TSRMLS_DC); void mysqlnd_ms_get_fingerprint_connection(smart_str * context, MYSQLND_MS_LIST_DATA ** d TSRMLS_DC); enum_func_status mysqlnd_ms_select_servers_all(zend_llist * master_list, zend_llist * slave_list, zend_llist * selected_masters, zend_llist * selected_slaves TSRMLS_DC); MYSQLND_CONN_DATA * mysqlnd_ms_pick_first_master_or_slave(const MYSQLND_CONN_DATA * const conn TSRMLS_DC); #endif /* MYSQLND_MS_SWITCH_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/mysqlnd_qp.h0000664000175000017500000000410512161007456015577 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* $Id: mysqlnd_qp.h 322877 2012-01-27 21:39:38Z uw $ */ #ifndef MYSQLND_MS_TOKENIZE_H #define MYSQLND_MS_TOKENIZE_H PHPAPI void mysqlnd_qp_free_scanner(struct st_mysqlnd_query_scanner * scanner TSRMLS_DC); PHPAPI struct st_mysqlnd_query_scanner * mysqlnd_qp_create_scanner(TSRMLS_D); PHPAPI struct st_ms_token_and_value mysqlnd_qp_get_token(struct st_mysqlnd_query_scanner * scanner TSRMLS_DC); PHPAPI void mysqlnd_qp_set_string(struct st_mysqlnd_query_scanner * scanner, const char * const s, size_t len TSRMLS_DC); #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION PHPAPI struct st_mysqlnd_query_parser * mysqlnd_qp_create_parser(TSRMLS_D); PHPAPI void mysqlnd_qp_free_parser(struct st_mysqlnd_query_parser * parser TSRMLS_DC); PHPAPI int mysqlnd_qp_start_parser(struct st_mysqlnd_query_parser * parser, const char * const query, const size_t query_len TSRMLS_DC); #endif #endif /* MYSQLND_MS_TOKENIZE_H */ mysqlnd_ms-1.5.2/mysqlnd_query_lexer.c0000664000175000017500000145743412161007456017540 0ustar andreyandrey#line 2 "mysqlnd_query_lexer.c" #line 4 "mysqlnd_query_lexer.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin yyg->yyin_r #define yyout yyg->yyout_r #define yyextra yyg->yyextra_r #define yyleng yyg->yyleng_r #define yytext yyg->yytext_r #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE mysqlnd_qp_restart(yyin ,yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = yyg->yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via mysqlnd_qp_restart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] void mysqlnd_qp_restart (FILE *input_file ,yyscan_t yyscanner ); void mysqlnd_qp__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__create_buffer (FILE *file,int size ,yyscan_t yyscanner ); void mysqlnd_qp__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); void mysqlnd_qp__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); void mysqlnd_qp_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); void mysqlnd_qp_pop_buffer_state (yyscan_t yyscanner ); static void mysqlnd_qp_ensure_buffer_stack (yyscan_t yyscanner ); static void mysqlnd_qp__load_buffer_state (yyscan_t yyscanner ); static void mysqlnd_qp__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); #define YY_FLUSH_BUFFER mysqlnd_qp__flush_buffer(YY_CURRENT_BUFFER ,yyscanner) YY_BUFFER_STATE mysqlnd_qp__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); void *mysqlnd_qp_alloc (yy_size_t ,yyscan_t yyscanner ); void *mysqlnd_qp_realloc (void *,yy_size_t ,yyscan_t yyscanner ); void mysqlnd_qp_free (void * ,yyscan_t yyscanner ); #define yy_new_buffer mysqlnd_qp__create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ mysqlnd_qp_ensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ mysqlnd_qp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ mysqlnd_qp_ensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ mysqlnd_qp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define mysqlnd_qp_wrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; typedef int yy_state_type; #define yytext_ptr yytext_r static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); static int yy_get_next_buffer (yyscan_t yyscanner ); static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; #define YY_NUM_RULES 625 #define YY_END_OF_BUFFER 626 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[2803] = { 0, 0, 0, 0, 0, 0, 0, 626, 624, 623, 623, 595, 624, 618, 616, 597, 603, 624, 591, 592, 593, 587, 589, 588, 594, 598, 573, 573, 624, 590, 611, 606, 609, 601, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 596, 624, 616, 616, 605, 599, 624, 624, 624, 622, 622, 616, 612, 0, 582, 580, 0, 618, 616, 0, 0, 0, 602, 0, 581, 579, 0, 0, 0, 573, 575, 620, 574, 0, 0, 0, 615, 613, 610, 608, 614, 600, 616, 616, 616, 616, 616, 616, 15, 19, 616, 616, 0, 616, 616, 616, 616, 616, 616, 39, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 128, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 201, 616, 616, 219, 220, 616, 222, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 323, 616, 616, 616, 616, 332, 616, 341, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 508, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 0, 616, 566, 616, 616, 616, 616, 0, 604, 616, 0, 0, 621, 616, 0, 0, 580, 0, 0, 0, 0, 0, 579, 0, 619, 0, 574, 0, 585, 0, 576, 584, 607, 616, 616, 3, 616, 616, 616, 616, 9, 616, 616, 13, 14, 16, 616, 616, 24, 0, 616, 616, 616, 616, 616, 616, 32, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 86, 616, 616, 616, 616, 616, 107, 616, 616, 616, 616, 616, 616, 616, 616, 126, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 139, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 170, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 217, 616, 221, 616, 616, 616, 616, 229, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 281, 616, 616, 616, 616, 616, 616, 298, 302, 616, 616, 616, 616, 616, 616, 616, 616, 316, 317, 616, 616, 616, 321, 322, 616, 616, 327, 616, 616, 616, 334, 616, 616, 616, 344, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 420, 616, 616, 616, 616, 616, 616, 616, 616, 616, 436, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 463, 465, 616, 471, 616, 616, 616, 482, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 539, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 0, 616, 567, 568, 616, 616, 617, 12, 0, 580, 0, 579, 619, 0, 578, 0, 577, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 586, 616, 616, 616, 616, 616, 616, 616, 33, 616, 36, 37, 616, 40, 616, 42, 616, 45, 46, 616, 616, 616, 52, 616, 616, 616, 616, 616, 616, 60, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 89, 616, 616, 616, 616, 98, 102, 616, 616, 616, 616, 616, 616, 616, 616, 117, 616, 616, 616, 616, 616, 124, 616, 616, 129, 130, 616, 616, 616, 134, 135, 616, 616, 140, 616, 143, 616, 616, 616, 616, 616, 616, 616, 153, 616, 616, 616, 616, 159, 616, 616, 162, 616, 616, 616, 616, 616, 616, 616, 616, 173, 174, 616, 616, 616, 616, 616, 616, 616, 187, 616, 189, 616, 616, 192, 197, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 216, 616, 616, 616, 616, 226, 227, 616, 230, 616, 232, 616, 616, 236, 237, 616, 616, 240, 616, 616, 245, 246, 616, 250, 616, 252, 256, 257, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 299, 616, 616, 616, 616, 616, 310, 616, 616, 616, 616, 318, 616, 320, 616, 326, 616, 616, 616, 616, 616, 335, 616, 616, 616, 616, 616, 616, 347, 616, 616, 616, 616, 616, 616, 616, 616, 360, 616, 616, 616, 616, 365, 616, 616, 616, 616, 616, 616, 616, 616, 616, 380, 382, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 418, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 440, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 472, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 498, 499, 500, 504, 616, 616, 616, 616, 513, 514, 616, 517, 616, 616, 616, 616, 525, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 537, 616, 616, 616, 616, 616, 616, 616, 616, 616, 552, 553, 616, 555, 556, 616, 616, 559, 562, 616, 616, 583, 565, 570, 616, 0, 0, 0, 0, 616, 616, 616, 5, 616, 616, 616, 10, 616, 17, 616, 616, 616, 616, 616, 616, 616, 27, 616, 616, 616, 616, 34, 616, 38, 41, 616, 616, 48, 616, 616, 54, 616, 616, 616, 58, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 85, 616, 88, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 144, 616, 616, 149, 150, 616, 616, 616, 616, 616, 158, 616, 161, 163, 164, 166, 167, 168, 616, 171, 616, 616, 616, 616, 616, 616, 181, 184, 616, 616, 616, 616, 193, 616, 198, 616, 616, 206, 616, 616, 209, 210, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 235, 238, 616, 241, 616, 243, 247, 616, 249, 616, 616, 616, 616, 616, 616, 276, 616, 616, 616, 616, 616, 616, 616, 616, 290, 616, 616, 616, 616, 616, 616, 303, 616, 307, 616, 309, 616, 616, 314, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 340, 342, 616, 345, 616, 616, 616, 616, 616, 355, 616, 358, 616, 616, 616, 616, 616, 616, 616, 616, 616, 373, 616, 375, 376, 377, 378, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 405, 616, 616, 616, 616, 616, 616, 616, 414, 616, 616, 616, 616, 421, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 437, 616, 616, 616, 616, 616, 445, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 468, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 483, 616, 485, 616, 616, 491, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 516, 616, 616, 616, 616, 616, 616, 616, 616, 616, 528, 616, 616, 616, 616, 533, 616, 616, 536, 616, 540, 616, 616, 545, 616, 616, 616, 616, 616, 616, 557, 558, 0, 616, 616, 564, 616, 616, 616, 2, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 25, 26, 616, 29, 30, 31, 616, 616, 616, 49, 616, 616, 55, 616, 57, 616, 616, 64, 616, 68, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 87, 616, 616, 92, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 116, 616, 616, 616, 616, 616, 616, 616, 127, 616, 616, 616, 136, 137, 616, 142, 145, 147, 148, 616, 152, 616, 616, 616, 616, 160, 616, 616, 616, 616, 616, 616, 616, 180, 182, 0, 616, 616, 616, 188, 616, 616, 616, 616, 616, 616, 202, 204, 616, 207, 616, 616, 212, 616, 616, 616, 616, 224, 616, 616, 616, 616, 234, 616, 242, 616, 616, 616, 616, 616, 616, 616, 273, 616, 616, 616, 616, 616, 616, 616, 288, 289, 616, 616, 616, 296, 616, 616, 301, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 330, 616, 616, 616, 338, 616, 616, 616, 349, 616, 616, 616, 357, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 389, 616, 616, 616, 395, 396, 397, 616, 399, 401, 616, 616, 616, 616, 616, 616, 616, 410, 412, 413, 616, 416, 616, 616, 616, 616, 616, 426, 616, 428, 616, 616, 432, 434, 616, 616, 616, 442, 443, 444, 616, 616, 448, 449, 450, 451, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 467, 469, 616, 616, 616, 475, 616, 616, 616, 616, 616, 616, 616, 616, 488, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 529, 616, 531, 616, 534, 616, 616, 616, 616, 544, 616, 616, 616, 616, 616, 616, 616, 0, 0, 616, 616, 616, 616, 616, 616, 4, 6, 616, 616, 11, 616, 20, 616, 616, 616, 28, 35, 43, 616, 50, 51, 616, 616, 616, 616, 61, 616, 63, 616, 66, 616, 69, 616, 616, 616, 616, 616, 616, 616, 616, 81, 616, 616, 84, 90, 616, 616, 94, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 110, 111, 112, 113, 114, 616, 616, 616, 616, 616, 122, 123, 616, 616, 616, 133, 616, 141, 146, 151, 616, 616, 616, 157, 616, 169, 616, 616, 616, 616, 616, 0, 616, 616, 186, 190, 616, 616, 616, 616, 616, 616, 205, 616, 616, 616, 214, 616, 218, 616, 225, 616, 616, 233, 616, 616, 248, 251, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 293, 616, 616, 616, 616, 616, 616, 616, 312, 616, 616, 616, 324, 616, 328, 616, 616, 616, 616, 616, 337, 343, 616, 616, 350, 616, 616, 356, 359, 616, 616, 363, 616, 366, 616, 616, 369, 371, 374, 616, 616, 383, 384, 616, 616, 616, 616, 616, 616, 616, 394, 616, 616, 402, 616, 404, 616, 616, 408, 616, 411, 616, 417, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 433, 616, 616, 616, 616, 616, 452, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 473, 616, 616, 477, 478, 616, 616, 484, 616, 487, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 506, 616, 616, 616, 512, 616, 616, 616, 616, 616, 616, 616, 616, 526, 616, 530, 616, 535, 538, 616, 616, 616, 547, 616, 616, 550, 616, 616, 0, 0, 616, 616, 563, 616, 616, 616, 616, 616, 616, 616, 22, 616, 44, 616, 53, 616, 616, 59, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 80, 82, 616, 616, 616, 95, 97, 99, 616, 616, 103, 616, 616, 616, 616, 616, 616, 118, 616, 616, 616, 125, 131, 616, 138, 616, 155, 616, 616, 616, 175, 176, 178, 616, 183, 183, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 215, 616, 616, 231, 616, 616, 253, 254, 255, 616, 616, 616, 616, 616, 616, 616, 616, 616, 279, 280, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 297, 300, 616, 616, 616, 616, 311, 616, 616, 616, 616, 329, 616, 333, 336, 616, 616, 616, 616, 354, 361, 616, 364, 616, 616, 616, 372, 616, 616, 385, 616, 616, 616, 390, 616, 616, 616, 616, 616, 406, 616, 409, 415, 616, 616, 423, 616, 616, 427, 616, 616, 616, 616, 616, 616, 441, 446, 447, 453, 616, 455, 616, 616, 616, 616, 616, 616, 616, 616, 466, 616, 616, 616, 616, 616, 486, 616, 616, 616, 616, 616, 616, 616, 616, 616, 505, 507, 509, 616, 511, 515, 616, 616, 616, 616, 616, 523, 616, 616, 532, 541, 543, 616, 616, 549, 551, 554, 0, 0, 616, 616, 616, 571, 616, 7, 8, 616, 616, 616, 616, 616, 616, 62, 616, 67, 616, 616, 616, 73, 616, 616, 616, 616, 616, 616, 96, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 121, 132, 154, 616, 165, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 223, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 284, 616, 286, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 319, 616, 616, 616, 346, 616, 353, 362, 616, 368, 616, 379, 616, 616, 387, 616, 616, 616, 616, 616, 616, 407, 616, 422, 616, 616, 429, 430, 616, 616, 616, 616, 616, 616, 616, 616, 459, 616, 616, 616, 616, 616, 0, 616, 616, 616, 481, 616, 616, 616, 616, 494, 495, 616, 616, 501, 616, 616, 616, 616, 521, 616, 616, 527, 616, 546, 548, 560, 0, 560, 616, 616, 1, 18, 616, 616, 616, 616, 616, 616, 70, 71, 72, 74, 75, 76, 616, 616, 616, 616, 616, 616, 105, 106, 108, 616, 616, 616, 616, 616, 616, 616, 179, 616, 616, 616, 616, 616, 199, 616, 616, 616, 616, 616, 616, 616, 244, 616, 616, 616, 616, 616, 616, 616, 616, 271, 616, 616, 616, 616, 616, 285, 287, 616, 616, 616, 616, 616, 305, 616, 616, 616, 315, 616, 616, 339, 616, 616, 352, 367, 616, 381, 616, 388, 616, 616, 398, 400, 616, 419, 616, 616, 616, 616, 438, 616, 616, 456, 616, 616, 616, 616, 616, 464, 616, 0, 616, 616, 616, 489, 616, 493, 616, 496, 616, 616, 616, 616, 616, 616, 616, 616, 616, 0, 616, 569, 616, 616, 616, 616, 572, 65, 616, 616, 616, 93, 616, 616, 616, 109, 616, 616, 616, 156, 172, 616, 616, 616, 616, 195, 196, 616, 616, 616, 211, 616, 616, 616, 616, 616, 616, 260, 616, 616, 264, 616, 616, 274, 616, 616, 616, 616, 616, 292, 616, 616, 616, 616, 308, 616, 616, 616, 616, 616, 370, 616, 616, 616, 616, 403, 424, 616, 616, 616, 439, 616, 616, 616, 616, 616, 616, 470, 0, 616, 616, 616, 616, 616, 497, 616, 616, 510, 518, 616, 520, 616, 616, 616, 561, 561, 616, 616, 47, 56, 616, 616, 616, 83, 91, 616, 616, 616, 616, 119, 616, 616, 185, 616, 616, 200, 616, 208, 616, 616, 239, 258, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 291, 616, 616, 616, 306, 313, 616, 331, 348, 351, 616, 616, 616, 393, 616, 431, 616, 454, 616, 616, 616, 461, 616, 0, 616, 616, 480, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 120, 616, 191, 616, 616, 213, 616, 616, 616, 616, 616, 616, 616, 267, 616, 616, 616, 616, 616, 616, 616, 616, 616, 295, 616, 616, 616, 616, 392, 616, 616, 616, 616, 616, 616, 474, 474, 616, 479, 616, 616, 502, 616, 519, 616, 616, 542, 616, 23, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 228, 616, 616, 616, 262, 616, 616, 616, 616, 616, 270, 616, 616, 616, 616, 616, 616, 616, 616, 616, 391, 616, 435, 457, 616, 616, 616, 616, 492, 616, 503, 616, 616, 21, 616, 78, 616, 616, 616, 104, 115, 616, 616, 616, 616, 616, 261, 263, 616, 616, 268, 616, 616, 616, 616, 616, 616, 616, 304, 616, 616, 616, 616, 616, 616, 476, 616, 616, 616, 616, 616, 616, 616, 616, 194, 616, 616, 616, 265, 616, 616, 616, 616, 616, 616, 616, 616, 616, 386, 616, 616, 616, 462, 616, 616, 524, 616, 79, 100, 101, 616, 203, 616, 616, 266, 269, 616, 616, 616, 616, 616, 616, 616, 616, 458, 616, 616, 616, 77, 177, 616, 616, 616, 616, 616, 616, 616, 294, 325, 425, 616, 490, 522, 616, 616, 616, 616, 616, 616, 616, 460, 259, 616, 616, 616, 278, 282, 283, 616, 616, 616, 616, 616, 616, 275, 616, 616, 616, 277, 616, 616, 616, 616, 272, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 21, 22, 21, 21, 21, 23, 24, 25, 26, 27, 28, 1, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 1, 56, 1, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 1, 86, 1, 87, 1, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 1, 1, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[93] = { 0, 1, 1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 3, 3, 3, 3, 3, 5, 1, 1, 1, 1, 1, 6, 3, 6, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 3, 6, 6, 3, 6, 3, 3, 3, 3, 3, 4, 1, 3, 4, 6, 3, 6, 3, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 3, 6, 6, 3, 6, 3, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3 } ; static yyconst flex_int16_t yy_base[2819] = { 0, 0, 0, 394, 349, 329, 327, 349,15652,15652,15652, 317, 90, 0, 6,15652, 330, 91,15652,15652,15652, 15652,15652, 83, 88, 320, 95, 102, 295,15652, 101, 15652, 103, 288, 117, 200, 263, 326, 389, 452, 110, 125, 504, 129, 191, 331, 567, 622, 680, 743, 114, 569, 829, 892, 944, 197, 1007, 276, 122, 205,15652, 0, 292, 367, 199,15652, 44, 191, 46,15652, 229, 199,15652, 135,15652, 223, 136, 0, 80, 54, 122, 73,15652, 221,15652, 135, 243, 135, 305, 362, 454, 15652, 488, 156, 431, 657,15652,15652, 92,15652,15652, 15652, 451, 464, 224, 468, 322, 674, 471, 160, 495, 532, 158, 518, 684, 749, 334, 619, 171, 579, 883, 752, 500, 739, 1057, 255, 427, 904, 652, 1120, 935, 649, 704, 958, 765, 735, 919, 1073, 888, 474, 826, 755, 1128, 1005, 626, 1131, 988, 1054, 1096, 1020, 1151, 1157, 1185, 1189, 1163, 1023, 1208, 1068, 481, 1051, 1160, 1268, 548, 1174, 1230, 1193, 1200, 974, 1253, 1262, 1320, 1324, 1387, 1330, 1393, 1400, 1409, 1384, 1247, 1314, 1084, 1396, 1415, 1460, 1453, 1297, 1424, 1285, 1238, 1468, 1463, 1478, 1488, 1535, 1474, 1430, 1543, 1554, 714, 1572, 1503, 1635, 1483, 1567, 1539, 1300, 1602, 1685, 1685, 1689, 1612, 1630, 1652, 1735, 1738, 1583, 1648, 1757, 1761, 1753, 1679, 1774, 1808, 1777, 1814, 710, 1833, 1354, 1805, 1768, 1894, 1846, 1854, 1704, 1900, 1782, 1911, 1869, 1914, 1829, 1560, 1951, 1993, 914, 852, 1939, 1785, 1957, 1863, 54,15652, 857, 134, 144,15652, 2002, 238, 253, 273, 316, 148, 178, 216, 428, 475, 578, 0, 2038, 1974, 2050, 292, 1947, 2017, 2068,15652, 1986, 2015, 2018, 2021, 2029, 2037, 2051, 1223, 2040, 2055, 1438, 1445, 2080, 1838, 2100, 2059, 322, 2093, 2090, 2085, 2070, 2097, 2138, 1513, 2162, 2115, 2129, 2135, 2144, 2165, 2169, 2184, 2181, 2239, 2205, 2178, 2201, 2230, 2210, 2242, 2246, 2264, 2236, 2325, 2272, 1659, 2257, 2261, 2331, 2334, 2341, 2288, 2299, 2328, 2370, 2380, 2377, 2373, 2393, 2426, 1825, 2412, 2401, 2388, 2407, 2436, 2421, 2452, 2456, 2463, 2459, 2294, 2468, 2473, 2478, 2487, 2492, 2519, 2509, 2524, 2527, 2557, 2545, 2152, 2515, 2535, 2560, 2550, 2574, 2583, 2591, 2597, 2587, 2600, 2604, 2613, 2623, 2626, 2302, 2632, 2629, 2617, 2637, 2643, 2663, 2666, 2443, 2669, 2683, 2690, 2695, 2698, 2702, 2705, 2709, 2729, 2715, 2733, 2768, 2778, 2754, 1884, 2743, 2759, 2763, 2775, 2783, 2786, 2790, 2813, 2838, 2823, 2816, 2845, 2746, 2852, 2849, 2856, 2842, 2860, 2915, 2918, 2888, 2881, 2805, 2878, 2899, 2902, 2927, 2923, 2938, 2910, 2934, 2956, 2962, 2993, 2972, 2986, 3002, 2997, 3005, 3018, 3010, 3013, 1908, 1954, 3032, 3026, 3048, 2048, 2067, 3039, 3065, 3073, 3068, 3084, 3056, 3061, 3077, 3103, 3108, 3143, 3120, 3126, 3139, 3172, 3135, 3166, 3149, 3146, 3169, 3100, 3184, 3222, 3226, 3234, 3219, 3201, 3242, 3239, 3254, 3294, 3258, 3262, 3297, 3231, 3303, 3332, 3307, 3310, 3313, 3377, 3329, 3396, 3362, 3336, 3324, 3367, 3382, 3407, 3399, 3402, 3413, 3434, 3437, 3431, 3420, 3462, 3454, 2122, 3459, 3472, 3190, 3468, 3475, 3283, 3480, 3391, 3493, 3499, 3526, 3530, 3508, 3542, 3561, 2233, 3565, 3545, 3583, 3608, 3632, 2357, 3595, 3621, 3627, 3591, 3598, 3613, 3646, 3636, 3660, 3624, 3682, 3695, 3557, 3692, 3698, 3728, 3712, 3687, 3718, 3722, 3761, 3783, 3750, 3756, 3786, 3790, 3776, 3802, 3771, 3813, 3796, 3741, 3805, 3868, 3820, 3842, 3855, 3849, 3871, 3879, 3864, 3883, 3890, 3893, 3967, 2498, 2363, 2484, 3902, 3922,15652, 2566, 346, 372, 342, 364, 0, 3984, 3996, 4001, 4006, 3960, 3965, 3980, 3983, 3988, 3977, 3999, 4006, 4009, 3994, 4016, 4021, 4024, 4040,15652, 4053, 4045, 4061, 4075, 4067, 4071, 4080, 2653, 4085, 4092, 2660, 4104, 2673, 4115, 2793, 4120, 2808, 2820, 4128, 4131, 4124, 4139, 4157, 4144, 4150, 4160, 4168, 4175, 2872, 4183, 4196, 4238, 4223, 4205, 4188, 4220, 4252, 4287, 4258, 4267, 4275, 4213, 3035, 4247, 4292, 4279, 4295, 4337, 4283, 4352, 4319, 4346, 4331, 4355, 4358, 4322, 4376, 4349, 4392, 4386, 4402, 4420, 4426, 3043, 4423, 4416, 3090, 3096, 4430, 4433, 4437, 3114, 4451, 4455, 4458, 3155, 4461, 3196, 4464, 4483, 4486, 4489, 4479, 4408, 4508, 3443, 4493, 4515, 4529, 4503, 3450, 4523, 4545, 3489, 4537, 4559, 4552, 4566, 4562, 4570, 4576, 3825, 3502, 4555, 4591, 4584, 4606, 4595, 4610, 4618, 4623, 3641, 4626, 3651, 4630, 4362, 4647, 4614, 4662, 4665, 4672, 4675, 4688, 4692, 4684, 4698, 4725, 4713, 4704, 3657, 4729, 4740, 4643, 4762, 3666, 3677, 4766, 3817, 4721, 3943, 4755, 4772, 3952, 3957, 4769, 4777, 4029, 4758, 4795, 4037, 4101, 4825, 4787, 4803, 4154, 4839, 4325, 4830, 4817, 4835, 4900, 4848, 4864, 4869, 4852, 4845, 4893, 4896, 4905, 4382, 4914, 4926, 4930, 4881, 4948, 4921, 4956, 4960, 4967, 4974, 4588, 4987, 4600, 4994, 4654, 4978, 4970, 4999, 5022, 5025, 4695, 5030, 5033, 5041, 5037, 5049, 4936, 4800, 5058, 5072, 5069, 5083, 5104, 5108, 5093, 5111, 4875, 5118, 5114, 5121, 5124, 4918, 5127, 5152, 5157, 5169, 5188, 5144, 5172, 5184, 5191, 5180, 4944, 5201, 5176, 5230, 5234, 5226, 5244, 5247, 5254, 5259, 5251, 5268, 5262, 5295, 5317, 5331, 5310, 5313, 5328, 5334, 5321, 5325, 5359, 5340, 5378, 5397, 5391, 4991, 5265, 5400, 5388, 5404, 5411, 5408, 5424, 5436, 5428, 5463, 5472, 5469, 5475, 5459, 5002, 5478, 5483, 5501, 5488, 5505, 5508, 5523, 5516, 5538, 5549, 5544, 5552, 5541, 5567, 5559, 5621, 5576, 5595, 5613, 5053, 5588, 5616, 5628, 5624, 5631, 5638, 5666, 5648, 5670, 5690, 5677, 5701, 5704, 5707, 5726, 5697, 5195, 5063, 5079, 5694, 5752, 5732, 5756, 5766, 5088, 5139, 5716, 5761, 5772, 5775, 5783, 5803, 5819, 5796, 5811, 5826, 5832, 5816, 5829, 5847, 5844, 5851, 5866, 5863, 5214, 5879, 5893, 5898, 5911, 5860, 5925, 5903, 5908, 5918, 5221, 5280, 5929, 5283, 5291, 5914, 5947, 6016, 5298, 5937, 5979,15652, 5348, 5439, 5991, 387, 399, 377, 436, 5975, 5982, 5996, 5351, 6006, 6011, 6021, 5370, 6024, 5381, 6052, 6045, 6040, 6057, 6060, 6065, 6090, 5442, 6094, 6080, 6084, 6097, 5493, 6109, 5512, 5531, 6120, 6116, 5598, 6127, 6130, 6145, 6148, 5882, 6113, 5653, 6154, 6164, 6124, 6136, 6180, 6198, 6213, 6216, 6184, 6202, 6220, 6205, 6210, 6230, 6226, 6241, 6247, 6252, 5659, 6285, 5736, 6274, 6281, 6278, 6288, 6296, 6313, 6321, 6337, 6308, 6346, 6327, 6318, 6333, 6343, 6355, 6367, 6396, 6387, 6384, 6405, 6390, 6393, 6399, 6416, 6421, 6409, 6430, 6470, 6465, 6474, 6480, 6456, 6485, 5745, 6462, 6494, 6489, 5940, 6510, 6515, 6520, 6541, 6537, 5943, 6525, 6027, 6172, 6175, 6255, 6244, 6358, 6547, 6375, 6544, 6554, 6557, 6572, 6550, 6582, 6578, 6647, 6596, 6623, 6611, 6607, 6425, 6648, 6642, 6659, 6627, 6678, 6682, 6664, 6433, 6439, 6687, 6692, 6637, 6706, 6702, 6709, 6712, 6726, 6719, 6731, 6742, 6747, 6451, 6762, 6575, 6765, 6770, 6593, 6776, 6653, 6773, 6787, 6779, 6802, 6782, 6799, 6672, 6807, 6830, 6838, 6845, 6856, 6865, 6860, 6849, 6794, 6852, 6871, 6874, 6881, 6894, 6920, 6815, 6934, 6886, 6901, 6890, 6924, 6930, 6911, 6937, 6942, 6945, 6962, 6970, 6981, 6990, 7010, 7007, 7017, 7002, 6904, 6951, 7024, 6959, 7036, 6998, 7040, 7061, 7067, 6967, 7070, 6976, 7074, 7081, 7055, 7077, 7097, 7103, 7114, 7144, 7129, 6987, 7122, 7044, 7047, 7091, 7106, 7157, 7137, 7168, 7165, 7179, 7182, 7189, 7171, 7196, 7204, 7235, 7241, 7244, 7247, 7229, 7250, 7253, 7260, 7269, 7134, 7257, 7276, 7281, 7286, 7321, 7313, 7328, 7151, 7333, 7324, 7336, 7343, 7174, 7347, 7350, 7371, 7389, 7364, 7316, 7380, 7406, 7402, 7397, 7409, 7199, 7306, 7416, 7424, 7412, 7448, 7211, 7453, 7468, 7462, 7483, 7471, 7486, 7495, 7491, 7502, 7506, 7480, 7541, 7535, 7525, 7538, 7547, 7574, 7556, 7568, 7577, 7584, 7587, 7581, 7591, 7622, 7608, 7614, 7219, 7619, 7222, 7626, 7640, 7649, 7643, 7664, 7652, 7660, 7674, 7655, 7685, 7695, 7699, 7718, 7715, 7732, 7290, 7729, 7740, 7726, 7735, 7722, 7761, 7743, 7782, 7779, 7298, 7802, 7394, 7797, 7805, 7357, 7812, 7816, 7377, 7791, 7432, 7820, 7809, 7827, 7841, 7830, 7855, 7866, 7883, 7880, 7438, 7441, 7918, 568, 7895, 7498, 7907, 7899, 7913, 7510, 7920, 7927, 7932, 7951, 7943, 7959, 7935, 7965, 7972, 7976, 7515, 7596, 7986, 7611, 7692, 7704, 7996, 7982, 8004, 8019, 8011, 7835, 7749, 8031, 7989, 8022, 8051, 8058, 8048, 8055, 8075, 8079, 8082, 8085, 8061, 8106, 8110, 8001, 8088, 8114, 8131, 8125, 8134, 7752, 8148, 8139, 8145, 8156, 8166, 8178, 8190, 8200, 8184, 8193, 8234, 8209, 8227, 8224, 8238, 8218, 8117, 8260, 8263, 7764, 8273, 8251, 8268, 8283, 8297, 8304, 8300, 7771, 8307, 8310, 8314, 7844, 8160, 8322, 8290, 8163, 8344, 8196, 8351, 8221, 8341, 8359, 8326, 8373, 8230, 8365, 8381, 8376, 8386, 8400, 8406, 8411, 8329, 8335, 8475, 8480, 8427, 8439, 8338, 8403, 8474, 8470, 8479, 8487, 8499, 8389, 8370, 8506, 8442, 8515, 8519, 8457, 8522, 8542, 8526, 8536, 8490, 8551, 8548, 8558, 8563, 8529, 8582, 8545, 8554, 8600, 8617, 8608, 8603, 8621, 8628, 8567, 8624, 8641, 8635, 8649, 8673, 8687, 8681, 8706, 8571, 8690, 8696, 8711, 8699, 8717, 8728, 8578, 8732, 8739, 8742, 8754, 8764, 8747, 8769, 8777, 8787, 8791, 8795, 8781, 8588, 8802, 8784, 8810, 8858, 8850, 8855, 8861, 8593, 8864, 8869, 8880, 8884, 8891, 8894, 8875, 8905, 8839, 8909, 8924, 8927, 8930, 8939, 8933, 8936, 8955, 8971, 8958, 8965, 8961, 8982, 8994, 8656, 9014, 9019, 8979, 8772, 8806, 8818, 9022, 8825, 9029, 9032, 9047, 9044, 9057, 9065, 9068, 9071, 8831, 9051, 8834, 9083, 8899, 9106, 9099, 9062, 9109, 9093, 9113, 9116, 8948, 9126, 9123, 9141, 9120, 9149, 9178, 9168, 8989, 9001, 9076, 9181, 9190, 9096, 9136, 9145, 9152, 9204, 9208, 9187, 9212, 9219, 9227, 9222, 9265, 9194, 9260, 9254, 9280, 9175, 9234, 9247, 9294, 9297, 9250, 9284, 9301, 9311, 9317, 9291, 9314, 9333, 9346, 9323, 9379, 9339, 9385, 9382, 9368, 9388, 9375, 9371, 9398, 9410, 9395, 9407, 9415, 9433, 9447, 9454, 9460, 9464, 9469, 9477, 9483, 9474, 9342, 9489, 9353, 9494, 9423, 9507, 9500, 9504, 9521, 9428, 9518, 9529, 9536, 9555, 9552, 9558, 9565, 9590, 110, 9591, 9585, 9588, 9592, 9598, 9571, 9439, 9513, 9602, 9635, 9524, 9647, 9605, 9639, 9642, 9628, 9608, 9615, 9654, 9650, 9619, 9622, 9679, 9675, 9688, 9694, 9657, 9699, 9664, 9714, 9669, 9728, 9684, 9725, 9720, 9738, 9733, 9745, 9762, 9759, 9753, 9742, 9774, 9789, 9750, 9756, 9797, 9813, 9767, 9826, 9829, 9833, 9837, 9840, 9821, 9845, 9858, 9852, 9855, 9849, 9782, 9785, 9792, 9861, 9899, 9920, 9876, 9912, 9909, 9867, 9870, 9915, 9931, 9934, 9879, 9945, 9882, 9885, 9889, 9953, 9965, 9939, 9924, 9959, 9928,10000, 9984, 9991, 9987, 9996, 186,10005,10010, 9956, 9975,10031,10062,10041,10047,10054,10050,10016,10022,10068, 10076,10019,10079,10035,10099,10065,10087,10117,10071,10123, 10126,10084,10092,10134,10131,10155,10159,10220,10163,10151, 10181,10198,10214,10187,10217,10225,10240,10229,10147,10237, 10095,10276,10244,10255,10271,10285,10292,10299,10109,10302, 10306,10315,10194,10309,10267,10325,10330,10339,10345,10333, 10320,10336,10349,10383,10354,10375,10399,10360,10363,10391, 10394,10366,10408,10369,10411,10416,10438,10432,10379,10446, 10450,10404,10421,10463,10469,10472,10482,10485,10475,10479, 10441,10488,10521,10493,10508,10498,10545,10557,10502,10548, 10511,10564,10515,10553,10577,10588,10580,10591,10574,10595, 10615,10605,10618,10518,10627,10635,10631,10645,10649,10527, 10652,10655,10665,10682,10673,10697,10701,10716,10719,10708, 10726,10730,10723,10539,10733,10749,10621,10662,10764,10760, 10685,10756,10693,10775,10782,10798,10795,10791,10804,10812, 10815,10788,10832,10752,10820,10835,10849,10852,10874,10865, 10841,10868,10882,10877,10885,10913,10844,10909,10862,10928, 10891,10894,10945,10953,10916,10898,10958,10961,10906,10949, 10964, 214, 393,10971,10975,10923,10984,10987,10993,10996, 11017,11020,11025,10990,11028,11000,11050,11004,11034,11056, 11013,11063,11040,11080,11070,11087,11090,11094,11084,11114, 11121,11098,11101,11117,11145,11108,11125,11128,11131,11139, 11152,11136,11158,11175,11190,11185,11195,11199,11149,11223, 11231,11216,11155,11165,11228,11169,11236,11181,11256,11253, 11259,11206,11220,11269,11244,15652,11247,11289,11296,11305, 11313,11309,11320,11324,11330,11341,11317,11338,11266,11333, 11373,11275,11383,11393,11283,11300,11347,11370,11396,11407, 11402,11447,11455,11424,11414,11444,11362,11367,11451,11377, 11461,11436,11469,11479,11475,11500,11511,11486,11465,11490, 11524,11520,11514,11517,11493,11540,11555,11550,11560,11530, 11544,11537,11547,11572,11575,11597,11581,11565,11568,11605, 11578,11615,11627,11642,11585,11630,11633,11602,11646,11636, 11649,11608,11665,11669,11680,11702,11706,11612,11697,11657, 11660,11723,11720,11672,11746,11739,11676,11752,11731,11749, 11757,11760,11767,11690,11727,11736,11763,11785,11770,11792, 11809,11829,11832,11788,11837,11840,11843,11778,11855,11918, 11814,11846,11877,11797,11882,11907,11867,11914,11897,11919, 11922,11926,11910,11800,11826,11870,11939,11900,11929,11948, 11967,11973,11982,11976,11936,11989,12000,11944,11952,12007, 11992,12022,11957,11970,11996, 460, 454,12041,12036,12029, 12003,12070,12011,12019,12081,12073,12084,12087,12093,12107, 12032,12096,12049,12123,12117,12102,12052,12127,12133,12141, 12147,12156,12163,12062,12168,12172,12178,12188,12194,12207, 12066,12111,12204,12197,12138,12159,12175,12218,12191,12201, 12232,12228,12268,12254,12258,12262,12274,12271,12277,12280, 12283,12304,12327,12222,12247,12347,12342,12352,12336,12356, 12332,12363,12367,12374,12383,12390,12377,12408,12415,12422, 12430,12291,12440,12297,12436,12444,12450,12455,12462,12447, 12469,12483,12490,12517,12509,12301,12513,12520,12529,12310, 12525,12550,12313,12545,12322,12554,12398,12562,12591,12412, 12579,12419,12595,12599,12604,12586,12476,12582,12479,12607, 12618,12486,12499,12627,12613,12635,12656,12662,12665,12668, 12659,12574,12672,12679,12675,12682,12696,12751,12771,12717, 12746,12630,12760,12765,12768,12686,12731,12751,12771,12774, 12781,12800,12805,12795,12811,12777,12820,12836,12789,12827, 12817,12823,15652, 539,12830,12843,12857,12839,12846,12867, 12873,12890,12901,12904,12907,12852,12860,12863,12876,12882, 12887,12913,12922,12942,12945,12957,12951,12917,12929,12932, 12968,12935,12960,12989,12982,13006,13012,12964,13015,13019, 13022,13027,13030,12974,13037,13034,13053,13082,13086,13089, 13092,12986,13106,13096,13112,13116,13041,13122,13126,13139, 13102,13144,13160,13163,13167,13175,12998,13050,13179,13193, 13186,13198,13189,13057,13217,13220,13230,13060,13242,13227, 13066,13259,13252,13071,13132,13247,13156,13268,13207,13296, 13275,13210,13237,13263,13256,13306,13315,13311,13325,13282, 13320,13334,13285,13331,13299,13339,13347,13357,13328,13382, 558,13388,13393,13397,13352,13405,13360,13401,13363,13420, 13468,13417,13446,13426,13471,13375,13453,13475, 561,13457, 13423,13478,13484,13487,13498,13462,13490,13551,13494,13510, 13501,13524,13546,13564,13514,13570,13575,13559,13520,13528, 13581,13584,13591,13594,13540,13554,13601,13614,13623,13598, 13633,13630,13645,13626,13662,13648,13609,13667,13659,13638, 13697,13715,13653,13708,13690,13702,13722,13718,13672,13712, 13728,13744,13768,13678,13779,13732,13783,13786,13789,13682, 13759,13793,13798,13804,13736,13748,13808,13822,13813,13774, 13819,13841,13846,13865,13882,13885,13816, 574,13879,13890, 13875,13849,13906,13834,13896,13916,13852,13860,13910,13871, 13902,13920,13937,15652,13913,13947,13940,13926,13930,13965, 13983,13991,13943,13950,13980,14002,14005,13986,13955,14018, 14024,13969,14014,14037,13972,14040,13994,14056,14048,14010, 14021,14059,14076,14052,14079,14082,14087,14124,14091,14111, 14115,14118,14142,14147,14104,14150,14158,14161,14121,14132, 14166,14153,14169,14172,14177,14194,14188,14180,14198,14183, 14204,14191,14246,14257,14249,14207,14252, 573,14260,14265, 14268,14273,14277,14291,14297,14319,14329,14322,14326,14337, 14340,14344,14334,14348,14356,14390,14398,14393,14214,14411, 14217,14401,14235,14220,14415,14407,14423,14429,14418,14447, 14386,14450,14457,14471,14468,14476,14483,14493,14501,14516, 14530,14228,14508,14533,14541,14538,14282,14548,14556,14562, 14565,14572,14569,15652,14288,14576,14307,14600,14606,14360, 14610,14363,14621,14627,14368,14624,14371,14639,14642,14645, 14657,14669,14661,14676,14679,14631,14635,14438,14453,14712, 14709,14441,14721,14706,14715,14697,14718,14486,14724,14742, 14746,14770,14759,14762,14782,14752,14773,14496,14794,14505, 14525,14777,14787,14799,14803,14592,14819,14595,14824,14827, 14673,14834,14687,14841,14862,14867,14690,14739,14870,14873, 14887,14851,14855,14876,14879,14911,14902,14892,14921,14940, 14898,14918,14928,14946,14943,14906,14950,14965,14970,14974, 14977,14994,14936,14984,14999,14989,15004,15028,15022,15031, 15043,14959,15049,15064,15013,15009,15069,15060,15054,15087, 15105,15116,15119,15100,15124,15019,15127,15133,15130,15034, 15150,15141,15039,15177,15057,15073,15094,15183,15111,15186, 15189,15146,15154,15169,15194,15208,15213,15218,15230,15235, 15239,15157,15242,15199,15257,15205,15221,15260,15254,15275, 15281,15288,15304,15296,15224,15250,15265,15311,15270,15284, 15316,15334,15329,15324,15345,15350,15356,15338,15341,15371, 15366,15386,15359,15374,15377,15400,15394,15408,15426,15437, 15422,15389,15446,15449,15415,15418,15462,15469,15457,15466, 15429,15652,15561,15567,15573,15577,15583,15589,15595,15601, 15607,15613,15619,15625,15631,15637,15643,15645 } ; static yyconst flex_int16_t yy_def[2819] = { 0, 2802, 1, 2803, 2803, 1, 1, 2802, 2802, 2802, 2802, 2802, 2804, 2805, 2806, 2802, 2802, 2807, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 37, 2806, 2806, 2806, 2806, 2806, 2806, 37, 2806, 2806, 2806, 2806, 2806, 2802, 51, 2806, 2806, 51, 2806, 2806, 2806, 2802, 2808, 35, 2806, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 34, 2802, 2804, 2802, 2802, 2809, 2810, 2806, 2802, 2802, 2802, 2802, 2811, 2802, 2802, 2812, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 129, 2806, 2806, 2806, 2806, 2806, 54, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2808, 2802, 2806, 2802, 2802, 2802, 2806, 2813, 2804, 2804, 2809, 2802, 2802, 2814, 2811, 2811, 2812, 2815, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2816, 2813, 2817, 2814, 2815, 2802, 2802, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2813, 2816, 2814, 2817, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 949, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 949, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 949, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2818, 2802, 949, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 949, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 949, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2802, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 0, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802 } ; static yyconst flex_int16_t yy_nxt[15745] = { 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 8, 60, 14, 61, 34, 62, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 63, 58, 59, 64, 65, 8, 8, 66, 67, 68, 74, 84, 75, 79, 80, 81, 87, 88, 85, 89, 89, 89, 89, 89, 90, 90, 90, 90, 90, 92, 577, 89, 89, 89, 89, 89, 92, 274, 89, 89, 89, 89, 89, 93, 97, 98, 94, 99, 100, 251, 251, 253, 253, 94, 266, 74, 74, 75, 258, 78, 78, 150, 262, 76, 86, 95, 102, 103, 151, 104, 105, 1903, 153, 247, 152, 106, 154, 107, 261, 261, 155, 199, 108, 109, 110, 111, 156, 79, 80, 81, 166, 150, 270, 270, 291, 291, 102, 103, 151, 104, 105, 1903, 153, 247, 152, 106, 154, 107, 76, 259, 155, 199, 108, 109, 110, 111, 156, 79, 80, 81, 166, 79, 80, 81, 79, 80, 81, 112, 260, 79, 80, 81, 79, 80, 81, 302, 79, 80, 81, 251, 251, 84, 167, 85, 234, 256, 168, 113, 85, 251, 251, 114, 235, 78, 78, 115, 248, 1966, 116, 255, 75, 117, 2116, 84, 254, 302, 118, 79, 80, 81, 264, 119, 167, 74, 234, 75, 168, 113, 79, 80, 81, 114, 235, 78, 78, 115, 248, 1966, 116, 581, 278, 117, 2116, 74, 86, 580, 118, 252, 79, 80, 81, 119, 250, 242, 79, 80, 81, 79, 80, 81, 120, 579, 79, 80, 81, 243, 265, 121, 122, 2802, 278, 123, 320, 244, 124, 125, 76, 126, 270, 270, 127, 79, 80, 81, 101, 245, 74, 246, 258, 96, 120, 90, 90, 90, 90, 90, 76, 121, 122, 602, 91, 123, 320, 244, 124, 125, 82, 126, 291, 291, 127, 72, 79, 80, 81, 245, 2802, 246, 580, 582, 79, 80, 81, 128, 71, 281, 71, 129, 169, 70, 282, 130, 170, 79, 80, 81, 171, 131, 283, 259, 132, 582, 172, 133, 580, 299, 92, 134, 89, 89, 89, 89, 89, 128, 85, 281, 243, 129, 169, 75, 282, 130, 170, 94, 244, 960, 171, 131, 283, 958, 132, 580, 172, 133, 70, 299, 245, 134, 246, 79, 80, 81, 2802, 79, 80, 81, 135, 581, 79, 80, 81, 79, 80, 81, 244, 579, 2802, 136, 84, 137, 581, 2117, 138, 139, 140, 85, 245, 141, 246, 142, 579, 2802, 271, 582, 271, 2802, 135, 272, 272, 272, 272, 272, 958, 2802, 79, 80, 81, 136, 321, 137, 2802, 2117, 138, 139, 140, 2802, 2802, 141, 322, 142, 90, 90, 90, 90, 90, 84, 79, 80, 81, 143, 275, 86, 582, 144, 2802, 267, 2802, 145, 321, 960, 146, 2273, 2274, 147, 277, 279, 148, 276, 322, 149, 287, 280, 288, 78, 268, 268, 268, 268, 268, 143, 275, 2802, 2802, 144, 79, 80, 81, 145, 350, 269, 146, 2273, 2274, 147, 277, 279, 148, 276, 86, 149, 287, 280, 288, 78, 157, 2802, 158, 159, 79, 80, 81, 289, 310, 160, 161, 162, 163, 292, 350, 164, 165, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 157, 290, 158, 159, 79, 80, 81, 289, 310, 160, 161, 162, 163, 292, 84, 164, 165, 2802, 79, 80, 81, 264, 2399, 79, 80, 81, 2802, 79, 80, 81, 173, 290, 200, 1627, 174, 2478, 201, 2802, 175, 2494, 202, 79, 80, 81, 176, 2558, 203, 78, 1628, 2614, 177, 204, 2399, 2802, 178, 79, 80, 81, 2802, 2802, 173, 303, 200, 1627, 174, 2478, 201, 265, 175, 2494, 202, 79, 80, 81, 176, 2558, 203, 78, 1628, 2614, 177, 204, 2802, 2802, 178, 179, 2802, 180, 181, 182, 2802, 303, 79, 80, 81, 2802, 300, 2802, 2802, 183, 2802, 301, 79, 80, 81, 184, 185, 2802, 360, 273, 273, 273, 273, 273, 2802, 179, 2802, 180, 181, 182, 273, 273, 273, 273, 273, 273, 300, 2802, 2802, 183, 2802, 301, 336, 2802, 325, 184, 185, 284, 360, 326, 285, 2802, 79, 80, 81, 79, 80, 81, 186, 79, 80, 81, 293, 294, 187, 2802, 188, 2802, 189, 2802, 190, 286, 336, 191, 325, 192, 295, 284, 2802, 326, 285, 2802, 79, 80, 81, 79, 80, 81, 186, 2802, 2802, 337, 293, 294, 187, 2802, 188, 2802, 189, 2802, 190, 286, 2802, 191, 471, 192, 295, 79, 80, 81, 342, 2802, 311, 79, 80, 81, 193, 79, 80, 81, 312, 337, 2802, 194, 2802, 308, 313, 195, 296, 309, 196, 2802, 352, 197, 471, 297, 198, 79, 80, 81, 342, 298, 311, 79, 80, 81, 193, 79, 80, 81, 312, 341, 2802, 194, 2802, 308, 313, 195, 296, 309, 196, 2802, 352, 197, 2802, 297, 198, 2802, 79, 80, 81, 298, 79, 80, 81, 2802, 79, 80, 81, 78, 2802, 341, 79, 80, 81, 79, 80, 81, 79, 80, 81, 78, 78, 78, 78, 78, 2802, 2802, 79, 80, 81, 351, 205, 78, 206, 78, 207, 78, 78, 208, 209, 78, 78, 210, 211, 212, 213, 214, 215, 78, 216, 217, 218, 78, 219, 78, 220, 78, 2802, 2802, 78, 351, 205, 78, 206, 78, 207, 78, 78, 208, 209, 78, 78, 210, 211, 212, 213, 214, 215, 78, 216, 217, 218, 78, 219, 78, 220, 78, 304, 79, 80, 81, 79, 80, 81, 221, 2802, 305, 2802, 222, 2802, 2802, 223, 224, 306, 307, 572, 2802, 323, 225, 2802, 349, 226, 2802, 78, 79, 80, 81, 304, 227, 79, 80, 81, 2802, 324, 221, 2802, 305, 2802, 222, 2802, 2802, 223, 224, 306, 307, 2802, 2802, 323, 225, 343, 349, 226, 2802, 78, 2802, 79, 80, 81, 227, 228, 79, 80, 81, 324, 333, 334, 2802, 229, 335, 230, 338, 231, 2802, 2802, 232, 233, 79, 80, 81, 343, 2802, 2802, 339, 2802, 2802, 340, 79, 80, 81, 228, 2802, 79, 80, 81, 333, 334, 2802, 229, 335, 230, 338, 231, 2802, 2802, 232, 233, 2802, 79, 80, 81, 401, 2802, 339, 2802, 364, 340, 79, 80, 81, 236, 365, 2802, 2802, 237, 2802, 2802, 238, 239, 357, 2802, 79, 80, 81, 240, 2802, 358, 241, 359, 78, 2802, 401, 382, 2802, 370, 364, 371, 79, 80, 81, 236, 365, 2802, 2802, 237, 2802, 2802, 238, 239, 357, 2802, 79, 80, 81, 240, 2802, 358, 241, 359, 78, 314, 2802, 382, 315, 370, 2802, 371, 386, 79, 80, 81, 316, 317, 318, 366, 385, 344, 367, 345, 346, 319, 2802, 347, 79, 80, 81, 79, 80, 81, 2802, 314, 2802, 2802, 315, 437, 2802, 348, 386, 2802, 368, 2802, 316, 317, 318, 366, 385, 344, 367, 345, 346, 319, 2802, 347, 369, 79, 80, 81, 79, 80, 81, 79, 80, 81, 327, 437, 328, 348, 2802, 329, 368, 2802, 79, 80, 81, 330, 353, 79, 80, 81, 354, 2802, 331, 332, 369, 2802, 361, 355, 79, 80, 81, 356, 362, 2802, 327, 2802, 328, 2802, 363, 329, 79, 80, 81, 2802, 2802, 330, 353, 2802, 2802, 372, 354, 2802, 331, 332, 373, 374, 361, 355, 380, 387, 396, 356, 362, 2802, 79, 80, 81, 2802, 363, 375, 381, 2802, 79, 80, 81, 79, 80, 81, 2802, 372, 2802, 399, 2802, 376, 373, 374, 377, 2802, 380, 387, 396, 378, 400, 2802, 379, 79, 80, 81, 2802, 375, 381, 79, 80, 81, 79, 80, 81, 79, 80, 81, 383, 399, 384, 376, 2802, 2802, 377, 2802, 79, 80, 81, 378, 400, 2802, 379, 2802, 452, 2802, 397, 79, 80, 81, 398, 79, 80, 81, 2802, 79, 80, 81, 383, 2802, 384, 2802, 79, 80, 81, 2802, 402, 434, 2802, 2802, 79, 80, 81, 388, 452, 389, 397, 403, 390, 2802, 398, 2802, 404, 391, 392, 79, 80, 81, 393, 394, 451, 395, 79, 80, 81, 2802, 402, 434, 2802, 449, 79, 80, 81, 388, 2802, 389, 2802, 403, 390, 79, 80, 81, 404, 391, 392, 79, 80, 81, 393, 394, 451, 395, 405, 496, 79, 80, 81, 406, 435, 449, 79, 80, 81, 2802, 2802, 436, 410, 2802, 411, 412, 407, 2802, 2802, 408, 413, 409, 2802, 79, 80, 81, 420, 421, 405, 496, 2802, 422, 2802, 406, 435, 79, 80, 81, 79, 80, 81, 436, 410, 2802, 411, 412, 407, 543, 2802, 408, 413, 409, 79, 80, 81, 2802, 420, 421, 79, 80, 81, 422, 79, 80, 81, 414, 2802, 415, 79, 80, 81, 416, 2802, 432, 423, 438, 2802, 543, 417, 418, 427, 433, 2802, 424, 428, 2802, 2802, 419, 425, 426, 430, 429, 79, 80, 81, 414, 2802, 415, 2802, 439, 431, 416, 2802, 432, 423, 438, 2802, 450, 417, 418, 427, 433, 2802, 424, 428, 440, 441, 419, 425, 426, 430, 429, 79, 80, 81, 79, 80, 81, 463, 439, 431, 79, 80, 81, 79, 80, 81, 450, 79, 80, 81, 442, 447, 448, 455, 440, 441, 79, 80, 81, 453, 443, 462, 79, 80, 81, 2802, 444, 463, 2802, 445, 2802, 79, 80, 81, 454, 446, 491, 79, 80, 81, 442, 447, 448, 455, 456, 79, 80, 81, 457, 453, 443, 462, 79, 80, 81, 2802, 444, 2802, 2802, 445, 79, 80, 81, 475, 454, 2802, 491, 79, 80, 81, 79, 80, 81, 2802, 456, 79, 80, 81, 457, 2802, 2802, 79, 80, 81, 458, 79, 80, 81, 459, 2802, 79, 80, 81, 475, 2802, 79, 80, 81, 464, 460, 461, 465, 2802, 495, 2802, 468, 2802, 466, 467, 469, 79, 80, 81, 2802, 458, 470, 2802, 2802, 459, 472, 79, 80, 81, 473, 568, 492, 2802, 474, 464, 460, 461, 465, 2802, 495, 493, 468, 494, 466, 467, 469, 2802, 519, 79, 80, 81, 470, 79, 80, 81, 472, 79, 80, 81, 473, 568, 492, 497, 474, 2802, 511, 2802, 79, 80, 81, 493, 2802, 494, 79, 80, 81, 2802, 519, 2802, 2802, 79, 80, 81, 512, 2802, 79, 80, 81, 476, 477, 478, 479, 497, 480, 481, 511, 79, 80, 81, 482, 483, 484, 485, 486, 487, 513, 488, 489, 2802, 490, 2802, 2802, 520, 512, 2802, 79, 80, 81, 476, 477, 478, 479, 2802, 480, 481, 79, 80, 81, 2802, 482, 483, 484, 485, 486, 487, 513, 488, 489, 505, 490, 498, 78, 520, 79, 80, 81, 506, 2802, 509, 499, 531, 500, 507, 501, 510, 502, 503, 504, 508, 558, 2802, 79, 80, 81, 2802, 79, 80, 81, 505, 2802, 498, 78, 79, 80, 81, 2802, 506, 2802, 509, 499, 531, 500, 507, 501, 510, 502, 503, 504, 508, 558, 514, 517, 79, 80, 81, 518, 2802, 2802, 79, 80, 81, 515, 79, 80, 81, 2802, 529, 2802, 516, 2802, 521, 2802, 2802, 522, 530, 525, 2802, 79, 80, 81, 514, 517, 2802, 2802, 523, 518, 526, 524, 532, 527, 536, 515, 528, 2802, 537, 545, 529, 2802, 516, 561, 521, 2802, 2802, 522, 530, 525, 2802, 2802, 79, 80, 81, 79, 80, 81, 523, 574, 526, 524, 532, 527, 536, 2802, 528, 544, 537, 545, 79, 80, 81, 561, 79, 80, 81, 533, 79, 80, 81, 2802, 534, 538, 539, 79, 80, 81, 535, 574, 540, 79, 80, 81, 79, 80, 81, 544, 541, 79, 80, 81, 79, 80, 81, 567, 553, 533, 598, 554, 542, 555, 534, 538, 539, 556, 2802, 2802, 535, 557, 540, 2802, 79, 80, 81, 79, 80, 81, 541, 2802, 564, 79, 80, 81, 2802, 567, 553, 576, 598, 554, 542, 555, 79, 80, 81, 556, 79, 80, 81, 557, 79, 80, 81, 546, 547, 79, 80, 81, 2802, 548, 564, 549, 550, 79, 80, 81, 2802, 576, 559, 551, 552, 79, 80, 81, 560, 565, 562, 2802, 2802, 566, 79, 80, 81, 546, 547, 563, 79, 80, 81, 548, 2802, 549, 550, 272, 272, 272, 272, 272, 559, 551, 552, 79, 80, 81, 560, 565, 562, 573, 569, 566, 2802, 79, 80, 81, 575, 563, 570, 79, 80, 81, 268, 268, 268, 268, 268, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 269, 2802, 573, 569, 571, 571, 571, 571, 571, 575, 2802, 570, 588, 2802, 2802, 571, 571, 571, 571, 571, 571, 79, 80, 81, 284, 2802, 2802, 578, 272, 272, 272, 272, 272, 79, 80, 81, 79, 80, 81, 79, 80, 81, 588, 590, 584, 589, 584, 591, 286, 585, 585, 585, 585, 585, 284, 2802, 586, 285, 586, 592, 2802, 587, 587, 587, 587, 587, 595, 2802, 79, 80, 81, 2802, 2802, 590, 2802, 589, 593, 591, 286, 273, 273, 273, 273, 273, 79, 80, 81, 594, 596, 592, 273, 273, 273, 273, 273, 273, 595, 79, 80, 81, 79, 80, 81, 79, 80, 81, 593, 2802, 2802, 601, 597, 79, 80, 81, 606, 605, 2802, 594, 596, 79, 80, 81, 79, 80, 81, 603, 604, 607, 2802, 599, 79, 80, 81, 79, 80, 81, 600, 79, 80, 81, 597, 79, 80, 81, 606, 605, 2802, 2802, 612, 79, 80, 81, 79, 80, 81, 603, 604, 607, 613, 599, 608, 614, 79, 80, 81, 2802, 600, 79, 80, 81, 615, 609, 79, 80, 81, 79, 80, 81, 612, 79, 80, 81, 79, 80, 81, 610, 611, 2802, 613, 2802, 608, 614, 2802, 693, 616, 2802, 2802, 79, 80, 81, 615, 609, 617, 621, 79, 80, 81, 626, 618, 2802, 619, 79, 80, 81, 2802, 610, 611, 79, 80, 81, 79, 80, 81, 693, 616, 620, 79, 80, 81, 625, 2802, 2802, 617, 621, 79, 80, 81, 626, 618, 2802, 619, 627, 2802, 2802, 79, 80, 81, 79, 80, 81, 629, 79, 80, 81, 2802, 620, 628, 2802, 2802, 625, 79, 80, 81, 79, 80, 81, 79, 80, 81, 622, 634, 627, 631, 635, 623, 630, 2802, 2802, 624, 643, 629, 2802, 2802, 79, 80, 81, 628, 79, 80, 81, 2802, 2802, 79, 80, 81, 2802, 2802, 632, 2802, 622, 634, 644, 631, 635, 623, 630, 633, 642, 624, 643, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 632, 79, 80, 81, 644, 653, 2802, 678, 2802, 633, 642, 652, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 636, 637, 2802, 709, 2802, 79, 80, 81, 645, 654, 646, 638, 655, 653, 650, 678, 639, 640, 651, 641, 2802, 79, 80, 81, 647, 648, 649, 79, 80, 81, 636, 637, 79, 80, 81, 79, 80, 81, 645, 654, 646, 638, 655, 656, 650, 2802, 639, 640, 651, 641, 662, 657, 660, 658, 647, 648, 649, 659, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 663, 2802, 670, 656, 79, 80, 81, 2802, 661, 2802, 662, 657, 660, 658, 2802, 2802, 668, 659, 2802, 669, 79, 80, 81, 2802, 673, 671, 79, 80, 81, 664, 663, 665, 670, 79, 80, 81, 79, 80, 81, 666, 79, 80, 81, 79, 80, 81, 668, 2802, 667, 669, 672, 79, 80, 81, 673, 671, 79, 80, 81, 664, 2802, 665, 674, 675, 79, 80, 81, 676, 2802, 666, 79, 80, 81, 677, 717, 79, 80, 81, 667, 679, 672, 681, 2802, 2802, 79, 80, 81, 2802, 680, 79, 80, 81, 674, 675, 954, 683, 2802, 676, 2802, 79, 80, 81, 2802, 677, 682, 2802, 79, 80, 81, 679, 2802, 681, 2802, 2802, 686, 79, 80, 81, 680, 79, 80, 81, 79, 80, 81, 683, 79, 80, 81, 694, 689, 79, 80, 81, 682, 684, 79, 80, 81, 685, 695, 79, 80, 81, 686, 687, 688, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 2802, 694, 689, 79, 80, 81, 690, 684, 692, 696, 2802, 685, 695, 697, 79, 80, 81, 687, 688, 691, 79, 80, 81, 698, 79, 80, 81, 2802, 699, 79, 80, 81, 79, 80, 81, 2802, 690, 2802, 692, 696, 79, 80, 81, 697, 701, 703, 702, 704, 2802, 691, 79, 80, 81, 698, 700, 79, 80, 81, 699, 2802, 2802, 705, 79, 80, 81, 79, 80, 81, 2802, 706, 707, 79, 80, 81, 701, 703, 702, 704, 710, 79, 80, 81, 712, 708, 700, 713, 2802, 711, 79, 80, 81, 705, 79, 80, 81, 714, 79, 80, 81, 706, 707, 2802, 79, 80, 81, 79, 80, 81, 710, 79, 80, 81, 712, 708, 2802, 713, 715, 711, 79, 80, 81, 718, 79, 80, 81, 714, 716, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 2802, 715, 719, 79, 80, 81, 718, 720, 721, 724, 2802, 716, 722, 79, 80, 81, 723, 725, 2802, 727, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 719, 79, 80, 81, 2802, 720, 721, 724, 2802, 2802, 722, 79, 80, 81, 723, 725, 726, 727, 79, 80, 81, 728, 734, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 733, 79, 80, 81, 729, 2802, 748, 79, 80, 81, 726, 735, 736, 2802, 731, 728, 734, 2802, 2802, 730, 737, 79, 80, 81, 732, 79, 80, 81, 741, 740, 733, 2802, 2802, 738, 729, 79, 80, 81, 79, 80, 81, 735, 736, 739, 731, 2802, 79, 80, 81, 730, 737, 79, 80, 81, 732, 79, 80, 81, 741, 740, 79, 80, 81, 738, 742, 760, 746, 79, 80, 81, 79, 80, 81, 743, 745, 79, 80, 81, 79, 80, 81, 747, 79, 80, 81, 79, 80, 81, 749, 750, 2802, 744, 751, 752, 742, 753, 746, 79, 80, 81, 79, 80, 81, 743, 745, 79, 80, 81, 79, 80, 81, 747, 79, 80, 81, 79, 80, 81, 749, 750, 2802, 744, 751, 752, 2802, 753, 758, 2802, 759, 761, 79, 80, 81, 762, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 754, 79, 80, 81, 2802, 79, 80, 81, 756, 758, 755, 759, 761, 767, 2802, 763, 762, 79, 80, 81, 764, 757, 765, 79, 80, 81, 79, 80, 81, 766, 754, 2802, 2802, 79, 80, 81, 768, 2802, 756, 2802, 755, 2802, 2802, 767, 79, 80, 81, 79, 80, 81, 764, 757, 765, 2802, 2802, 79, 80, 81, 769, 766, 79, 80, 81, 79, 80, 81, 768, 770, 79, 80, 81, 2802, 79, 80, 81, 771, 774, 2802, 2802, 79, 80, 81, 772, 79, 80, 81, 773, 2802, 769, 2802, 775, 776, 2802, 2802, 778, 781, 2802, 770, 777, 2802, 782, 79, 80, 81, 2802, 2802, 774, 79, 80, 81, 2802, 779, 772, 2802, 2802, 784, 773, 79, 80, 81, 775, 776, 2802, 780, 778, 781, 2802, 2802, 777, 2802, 782, 79, 80, 81, 2802, 2802, 783, 785, 79, 80, 81, 779, 79, 80, 81, 784, 786, 79, 80, 81, 79, 80, 81, 780, 2802, 79, 80, 81, 79, 80, 81, 787, 788, 79, 80, 81, 783, 785, 2802, 791, 789, 79, 80, 81, 792, 793, 786, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 790, 79, 80, 81, 787, 788, 79, 80, 81, 794, 795, 2802, 2802, 789, 79, 80, 81, 809, 793, 79, 80, 81, 798, 79, 80, 81, 79, 80, 81, 2802, 790, 79, 80, 81, 799, 79, 80, 81, 2802, 794, 795, 800, 79, 80, 81, 796, 797, 809, 79, 80, 81, 804, 798, 806, 79, 80, 81, 807, 79, 80, 81, 79, 80, 81, 799, 2802, 79, 80, 81, 2802, 801, 800, 79, 80, 81, 796, 797, 2802, 79, 80, 81, 804, 805, 806, 79, 80, 81, 807, 802, 803, 810, 808, 2802, 79, 80, 81, 2802, 79, 80, 81, 801, 79, 80, 81, 79, 80, 81, 79, 80, 81, 867, 2802, 805, 79, 80, 81, 820, 2802, 802, 803, 810, 808, 811, 819, 79, 80, 81, 79, 80, 81, 79, 80, 81, 830, 817, 812, 815, 818, 813, 822, 867, 814, 79, 80, 81, 816, 820, 2802, 79, 80, 81, 2802, 811, 819, 79, 80, 81, 821, 823, 79, 80, 81, 2802, 830, 817, 812, 815, 818, 813, 822, 2802, 814, 2802, 2802, 827, 816, 826, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 821, 823, 79, 80, 81, 79, 80, 81, 824, 870, 79, 80, 81, 79, 80, 81, 825, 827, 831, 826, 2802, 836, 828, 2802, 2802, 79, 80, 81, 829, 79, 80, 81, 835, 79, 80, 81, 2802, 2802, 824, 870, 2802, 837, 849, 832, 2802, 2802, 825, 833, 831, 2802, 2802, 836, 828, 2802, 79, 80, 81, 834, 829, 2802, 841, 848, 835, 2802, 2802, 79, 80, 81, 79, 80, 81, 837, 849, 832, 79, 80, 81, 833, 79, 80, 81, 79, 80, 81, 79, 80, 81, 834, 838, 850, 841, 848, 839, 847, 2802, 79, 80, 81, 2802, 840, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2802, 842, 851, 872, 854, 843, 2802, 855, 838, 850, 2802, 844, 839, 847, 2802, 2802, 845, 846, 856, 840, 2802, 861, 2802, 79, 80, 81, 852, 2802, 79, 80, 81, 842, 851, 872, 854, 843, 853, 855, 79, 80, 81, 844, 859, 79, 80, 81, 845, 846, 856, 857, 860, 861, 79, 80, 81, 858, 852, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 862, 859, 864, 79, 80, 81, 865, 866, 857, 860, 79, 80, 81, 863, 858, 2802, 2802, 868, 869, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 862, 871, 864, 79, 80, 81, 865, 866, 873, 874, 79, 80, 81, 863, 79, 80, 81, 868, 869, 79, 80, 81, 79, 80, 81, 2802, 875, 878, 79, 80, 81, 871, 79, 80, 81, 79, 80, 81, 873, 874, 79, 80, 81, 876, 879, 2802, 2802, 877, 886, 79, 80, 81, 2802, 79, 80, 81, 875, 878, 2802, 79, 80, 81, 79, 80, 81, 880, 2802, 2802, 79, 80, 81, 2802, 2802, 876, 879, 2802, 2802, 877, 886, 881, 2802, 908, 884, 882, 885, 2802, 79, 80, 81, 883, 79, 80, 81, 2802, 2802, 880, 2802, 2802, 887, 896, 888, 900, 79, 80, 81, 79, 80, 81, 889, 881, 899, 908, 884, 882, 885, 2802, 890, 79, 80, 81, 2802, 79, 80, 81, 901, 79, 80, 81, 887, 896, 888, 900, 2802, 2802, 891, 892, 897, 905, 889, 2802, 899, 893, 898, 79, 80, 81, 890, 894, 903, 2802, 895, 79, 80, 81, 901, 79, 80, 81, 79, 80, 81, 902, 2802, 2802, 891, 892, 897, 905, 79, 80, 81, 893, 898, 79, 80, 81, 2802, 894, 903, 904, 895, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 902, 79, 80, 81, 906, 79, 80, 81, 907, 909, 79, 80, 81, 911, 910, 79, 80, 81, 904, 912, 79, 80, 81, 2802, 916, 915, 79, 80, 81, 79, 80, 81, 2802, 2802, 906, 79, 80, 81, 907, 909, 917, 913, 2802, 911, 910, 918, 79, 80, 81, 912, 914, 79, 80, 81, 2802, 915, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 917, 913, 925, 2802, 919, 918, 2802, 2802, 935, 926, 914, 79, 80, 81, 920, 929, 931, 79, 80, 81, 2802, 79, 80, 81, 921, 2802, 2802, 79, 80, 81, 2802, 2802, 925, 927, 919, 922, 923, 928, 924, 926, 79, 80, 81, 2802, 920, 929, 931, 2802, 934, 79, 80, 81, 2802, 2802, 921, 79, 80, 81, 930, 2802, 79, 80, 81, 927, 936, 922, 923, 928, 924, 932, 79, 80, 81, 2802, 2802, 79, 80, 81, 934, 2802, 933, 942, 79, 80, 81, 79, 80, 81, 930, 79, 80, 81, 1071, 2802, 936, 79, 80, 81, 945, 932, 943, 79, 80, 81, 79, 80, 81, 944, 937, 938, 949, 942, 79, 80, 81, 939, 79, 80, 81, 79, 80, 81, 2802, 946, 79, 80, 81, 947, 945, 948, 943, 940, 950, 2802, 2802, 941, 2802, 944, 937, 938, 949, 79, 80, 81, 951, 939, 2802, 2802, 79, 80, 81, 952, 2802, 946, 79, 80, 81, 947, 955, 948, 2802, 940, 950, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2802, 951, 956, 2802, 2802, 79, 80, 81, 952, 79, 80, 81, 2802, 953, 2802, 955, 79, 80, 81, 79, 80, 81, 571, 571, 571, 571, 571, 2802, 79, 80, 81, 2802, 956, 571, 571, 571, 571, 571, 571, 585, 585, 585, 585, 585, 961, 962, 963, 966, 79, 80, 81, 585, 585, 585, 585, 585, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 964, 965, 970, 79, 80, 81, 2802, 2802, 961, 962, 963, 966, 79, 80, 81, 2802, 967, 79, 80, 81, 79, 80, 81, 968, 2802, 79, 80, 81, 973, 2802, 964, 965, 970, 969, 971, 972, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 967, 2802, 79, 80, 81, 2802, 974, 968, 79, 80, 81, 975, 973, 79, 80, 81, 977, 969, 971, 972, 79, 80, 81, 79, 80, 81, 2802, 976, 978, 2802, 79, 80, 81, 979, 980, 79, 80, 81, 79, 80, 81, 975, 981, 79, 80, 81, 977, 2802, 982, 983, 984, 79, 80, 81, 79, 80, 81, 976, 978, 79, 80, 81, 985, 979, 980, 2802, 2802, 79, 80, 81, 2802, 2802, 981, 986, 987, 79, 80, 81, 982, 983, 984, 79, 80, 81, 990, 79, 80, 81, 2802, 79, 80, 81, 985, 988, 79, 80, 81, 2802, 989, 79, 80, 81, 993, 986, 987, 2802, 79, 80, 81, 2802, 2802, 991, 2802, 2802, 990, 79, 80, 81, 79, 80, 81, 992, 994, 988, 2802, 2802, 996, 995, 989, 79, 80, 81, 993, 997, 79, 80, 81, 998, 79, 80, 81, 991, 79, 80, 81, 79, 80, 81, 2802, 2802, 1006, 992, 994, 79, 80, 81, 996, 995, 79, 80, 81, 2802, 999, 997, 79, 80, 81, 998, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1002, 1007, 1005, 1006, 2802, 79, 80, 81, 1017, 2802, 2802, 1003, 79, 80, 81, 999, 2802, 1004, 2802, 1000, 79, 80, 81, 1001, 1018, 79, 80, 81, 2802, 2802, 1002, 1007, 1005, 79, 80, 81, 2802, 1008, 1017, 1014, 2802, 1003, 79, 80, 81, 2802, 2802, 1004, 1009, 1000, 79, 80, 81, 1001, 1018, 2802, 2802, 79, 80, 81, 79, 80, 81, 1015, 1010, 2802, 2802, 1008, 1011, 1014, 1020, 1016, 1012, 1019, 2802, 79, 80, 81, 1009, 1024, 1021, 1013, 2802, 2802, 79, 80, 81, 2802, 1025, 79, 80, 81, 2802, 1015, 1010, 79, 80, 81, 1011, 2802, 1020, 1016, 1012, 1019, 79, 80, 81, 1029, 1031, 1024, 1021, 1013, 79, 80, 81, 1022, 79, 80, 81, 1023, 79, 80, 81, 1034, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1030, 1026, 1029, 1031, 2802, 2802, 1027, 2802, 1036, 2802, 1022, 2802, 1028, 1033, 1023, 2802, 2802, 1032, 1034, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1030, 1026, 1082, 79, 80, 81, 1027, 1035, 1036, 79, 80, 81, 1028, 1033, 1037, 1038, 1039, 1032, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1040, 79, 80, 81, 1035, 1041, 1043, 1056, 2802, 2802, 1042, 1037, 1038, 1039, 1044, 79, 80, 81, 2802, 2802, 1045, 79, 80, 81, 2802, 79, 80, 81, 1046, 2802, 1040, 79, 80, 81, 2802, 1041, 1043, 1056, 1047, 2802, 1042, 79, 80, 81, 1044, 1048, 2802, 79, 80, 81, 1045, 1049, 2802, 1050, 1051, 79, 80, 81, 1046, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1047, 79, 80, 81, 79, 80, 81, 1048, 79, 80, 81, 1052, 1053, 1049, 1055, 1050, 1051, 1058, 1061, 1054, 2802, 2802, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1057, 1059, 1060, 1052, 1053, 2802, 1055, 2802, 2802, 1058, 1061, 1054, 79, 80, 81, 1062, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1063, 79, 80, 81, 1064, 1057, 1059, 1060, 2802, 2802, 1065, 79, 80, 81, 1068, 2802, 79, 80, 81, 1066, 1062, 1067, 1072, 79, 80, 81, 1069, 1070, 2802, 2802, 1063, 79, 80, 81, 1064, 2802, 1074, 79, 80, 81, 1065, 2802, 2802, 1076, 1068, 79, 80, 81, 2802, 1066, 2802, 1067, 1072, 79, 80, 81, 1069, 1070, 1073, 1075, 79, 80, 81, 79, 80, 81, 1074, 79, 80, 81, 79, 80, 81, 1076, 79, 80, 81, 1077, 79, 80, 81, 1078, 1079, 2802, 79, 80, 81, 1080, 1073, 1075, 1084, 1081, 79, 80, 81, 1099, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2802, 1077, 79, 80, 81, 1078, 1079, 1083, 79, 80, 81, 1080, 79, 80, 81, 1081, 79, 80, 81, 1099, 79, 80, 81, 1085, 1086, 79, 80, 81, 79, 80, 81, 1087, 79, 80, 81, 2802, 2802, 1083, 2802, 2802, 1088, 1089, 1090, 1091, 2802, 79, 80, 81, 2802, 79, 80, 81, 2802, 1085, 1086, 1095, 79, 80, 81, 1092, 2802, 1087, 2802, 1096, 79, 80, 81, 79, 80, 81, 1088, 1089, 1090, 1091, 79, 80, 81, 79, 80, 81, 1093, 1097, 1098, 1102, 1094, 1095, 79, 80, 81, 1092, 79, 80, 81, 1096, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1100, 1103, 79, 80, 81, 1101, 1093, 1097, 1098, 1102, 1094, 79, 80, 81, 1104, 1107, 2802, 2802, 1105, 79, 80, 81, 1106, 79, 80, 81, 2802, 79, 80, 81, 1100, 1103, 2802, 1108, 2802, 1101, 2802, 2802, 79, 80, 81, 2802, 2802, 1112, 1104, 1107, 2802, 2802, 1105, 1113, 2802, 1109, 1106, 79, 80, 81, 79, 80, 81, 1118, 79, 80, 81, 1108, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1112, 1110, 79, 80, 81, 1114, 1113, 1119, 1109, 1111, 1117, 2802, 79, 80, 81, 2802, 1118, 1129, 2802, 2802, 79, 80, 81, 1115, 1130, 79, 80, 81, 79, 80, 81, 1110, 1116, 1126, 2802, 1114, 2802, 1119, 1128, 1111, 1117, 2802, 79, 80, 81, 2802, 1127, 1129, 2802, 2802, 79, 80, 81, 1115, 1130, 79, 80, 81, 1131, 2802, 79, 80, 81, 1126, 79, 80, 81, 1120, 1128, 1137, 79, 80, 81, 79, 80, 81, 1127, 79, 80, 81, 1132, 1121, 1122, 1123, 1134, 1124, 1125, 1133, 1131, 79, 80, 81, 2802, 2802, 79, 80, 81, 1120, 1135, 1137, 79, 80, 81, 1136, 1139, 2802, 79, 80, 81, 2802, 1132, 1121, 1122, 1123, 1134, 1124, 1125, 1133, 79, 80, 81, 79, 80, 81, 1138, 79, 80, 81, 1135, 1158, 79, 80, 81, 1136, 1139, 1140, 2802, 1148, 2802, 79, 80, 81, 1141, 79, 80, 81, 79, 80, 81, 1142, 1143, 79, 80, 81, 1138, 79, 80, 81, 1144, 1145, 1147, 79, 80, 81, 2802, 1140, 2802, 1148, 1149, 79, 80, 81, 1141, 79, 80, 81, 1146, 2802, 2802, 1142, 1143, 79, 80, 81, 2802, 79, 80, 81, 1144, 1145, 1147, 2802, 79, 80, 81, 79, 80, 81, 1149, 79, 80, 81, 1150, 79, 80, 81, 1146, 1152, 1151, 1153, 1156, 2802, 79, 80, 81, 1154, 79, 80, 81, 79, 80, 81, 2802, 1155, 79, 80, 81, 79, 80, 81, 2802, 1157, 1150, 2802, 2802, 1159, 2802, 1152, 1151, 1153, 1156, 1160, 1161, 2802, 2802, 1154, 2802, 79, 80, 81, 79, 80, 81, 1155, 2802, 79, 80, 81, 79, 80, 81, 1157, 79, 80, 81, 1159, 79, 80, 81, 2802, 1162, 1160, 1161, 1163, 79, 80, 81, 1165, 79, 80, 81, 1164, 1166, 79, 80, 81, 1169, 1168, 79, 80, 81, 2802, 1171, 1170, 79, 80, 81, 79, 80, 81, 1162, 2802, 1167, 1163, 79, 80, 81, 1165, 79, 80, 81, 1164, 1166, 79, 80, 81, 1169, 1168, 79, 80, 81, 2802, 1171, 1170, 2802, 1172, 1173, 2802, 1176, 79, 80, 81, 1167, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1174, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1172, 1173, 1175, 1176, 1178, 1179, 1177, 1183, 1180, 79, 80, 81, 2802, 2802, 79, 80, 81, 1174, 1181, 1182, 2802, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 2802, 2802, 1175, 1268, 1178, 1179, 1177, 1183, 1180, 79, 80, 81, 79, 80, 81, 1184, 79, 80, 81, 1182, 79, 80, 81, 1187, 79, 80, 81, 1186, 79, 80, 81, 79, 80, 81, 1190, 79, 80, 81, 1185, 1191, 2802, 79, 80, 81, 2802, 1184, 2802, 1188, 1194, 2802, 1212, 1189, 1192, 1187, 79, 80, 81, 1186, 2802, 2802, 1193, 79, 80, 81, 1190, 2802, 79, 80, 81, 1191, 79, 80, 81, 2802, 79, 80, 81, 1188, 1194, 2802, 1212, 1189, 1192, 1195, 79, 80, 81, 79, 80, 81, 1193, 79, 80, 81, 79, 80, 81, 1196, 1199, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1197, 1200, 1195, 1201, 1203, 2802, 1205, 1204, 1198, 79, 80, 81, 79, 80, 81, 2802, 1196, 1199, 2802, 1207, 79, 80, 81, 1202, 79, 80, 81, 79, 80, 81, 1197, 1200, 2802, 1201, 1203, 2802, 1205, 1204, 1198, 79, 80, 81, 79, 80, 81, 1206, 79, 80, 81, 1207, 79, 80, 81, 1202, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1208, 1209, 1211, 79, 80, 81, 1214, 1213, 2802, 1206, 1215, 79, 80, 81, 79, 80, 81, 2802, 2802, 1216, 1210, 2802, 79, 80, 81, 2802, 2802, 1217, 1218, 1219, 1208, 1209, 1211, 79, 80, 81, 1214, 1213, 2802, 2802, 1215, 79, 80, 81, 79, 80, 81, 1220, 1221, 1216, 1210, 79, 80, 81, 79, 80, 81, 1217, 1218, 1219, 79, 80, 81, 79, 80, 81, 1222, 79, 80, 81, 1313, 79, 80, 81, 79, 80, 81, 1220, 1221, 1223, 1224, 1226, 1225, 2802, 1227, 2802, 1228, 79, 80, 81, 1229, 79, 80, 81, 2802, 1231, 1222, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1223, 1224, 1226, 1225, 2802, 1227, 1230, 1228, 2802, 2802, 1232, 1229, 2802, 79, 80, 81, 1231, 79, 80, 81, 1233, 1234, 1235, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1236, 1230, 79, 80, 81, 1232, 2802, 79, 80, 81, 1237, 1238, 79, 80, 81, 1233, 1234, 1235, 1242, 1239, 79, 80, 81, 1240, 79, 80, 81, 79, 80, 81, 1236, 79, 80, 81, 2802, 79, 80, 81, 2802, 2802, 1237, 1238, 79, 80, 81, 1241, 2802, 1251, 1242, 1239, 79, 80, 81, 1240, 1248, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1249, 1241, 1250, 1251, 79, 80, 81, 1243, 1244, 1252, 1248, 2802, 79, 80, 81, 2802, 1255, 2802, 2802, 1245, 1254, 79, 80, 81, 1246, 1247, 1253, 1256, 2802, 2802, 1249, 2802, 1250, 79, 80, 81, 2802, 1243, 1244, 1252, 79, 80, 81, 79, 80, 81, 1255, 2802, 2802, 1245, 1254, 1257, 1258, 2802, 1246, 1247, 1253, 1256, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1259, 79, 80, 81, 79, 80, 81, 1260, 1261, 1257, 1258, 79, 80, 81, 2802, 2802, 1262, 1263, 1267, 2802, 2802, 79, 80, 81, 1264, 1269, 79, 80, 81, 2802, 1259, 1276, 79, 80, 81, 2802, 2802, 1260, 1261, 79, 80, 81, 2802, 79, 80, 81, 1262, 1263, 1267, 2802, 79, 80, 81, 1265, 1264, 1269, 1273, 2802, 1266, 2802, 2802, 1276, 2802, 79, 80, 81, 1270, 79, 80, 81, 79, 80, 81, 1271, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1265, 1272, 1275, 1273, 1274, 1266, 79, 80, 81, 1277, 2802, 1279, 2802, 1270, 2802, 2802, 79, 80, 81, 1278, 1271, 2802, 79, 80, 81, 1280, 79, 80, 81, 2802, 2802, 1272, 1275, 2802, 1274, 79, 80, 81, 1281, 1277, 1285, 1279, 79, 80, 81, 2802, 79, 80, 81, 1278, 1282, 79, 80, 81, 1283, 1280, 79, 80, 81, 1286, 1289, 1290, 79, 80, 81, 79, 80, 81, 1281, 1287, 1285, 2802, 2802, 79, 80, 81, 2802, 1284, 2802, 2802, 1282, 2802, 1288, 1291, 1283, 1292, 79, 80, 81, 1286, 1289, 1290, 2802, 79, 80, 81, 1294, 1295, 1301, 1287, 1293, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1288, 1291, 1296, 1292, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1294, 1295, 1301, 1297, 1293, 1298, 2802, 1303, 79, 80, 81, 79, 80, 81, 1340, 79, 80, 81, 1296, 1300, 1304, 1299, 1307, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1297, 2802, 1298, 1302, 1303, 2802, 2802, 1305, 1306, 2802, 79, 80, 81, 79, 80, 81, 1300, 1304, 1299, 1307, 2802, 2802, 1308, 1311, 79, 80, 81, 2802, 2802, 79, 80, 81, 2802, 1302, 79, 80, 81, 1305, 1306, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1308, 1311, 1312, 2802, 79, 80, 81, 2802, 79, 80, 81, 2802, 1315, 2802, 1316, 1314, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1309, 2802, 2802, 1312, 2802, 1317, 1310, 1319, 1310, 2802, 1310, 2802, 2802, 1315, 1318, 1316, 1314, 2802, 2802, 1320, 2802, 1310, 2802, 2802, 1310, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1317, 1310, 1319, 1310, 1321, 1310, 79, 80, 81, 1318, 2802, 79, 80, 81, 1320, 1322, 1310, 1323, 1324, 1310, 1325, 79, 80, 81, 2802, 2802, 79, 80, 81, 1326, 2802, 79, 80, 81, 1321, 1327, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1322, 2802, 1323, 1324, 1328, 1325, 2802, 2802, 1329, 1330, 79, 80, 81, 1332, 1326, 79, 80, 81, 1331, 1333, 1327, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1334, 1328, 79, 80, 81, 1329, 1330, 1335, 1336, 1341, 1332, 1337, 2802, 2802, 1344, 1331, 1333, 79, 80, 81, 2802, 79, 80, 81, 2802, 2802, 1345, 79, 80, 81, 1334, 79, 80, 81, 79, 80, 81, 1335, 1336, 1341, 1338, 1337, 1339, 2802, 1344, 2802, 79, 80, 81, 1342, 79, 80, 81, 79, 80, 81, 1345, 79, 80, 81, 1343, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1338, 2802, 1339, 79, 80, 81, 1346, 1347, 1350, 1342, 2802, 2802, 79, 80, 81, 79, 80, 81, 2802, 2802, 1343, 79, 80, 81, 1348, 2802, 2802, 1349, 1351, 1352, 1353, 79, 80, 81, 1354, 2802, 1346, 1347, 1350, 79, 80, 81, 79, 80, 81, 1355, 2802, 79, 80, 81, 2802, 79, 80, 81, 1348, 2802, 1356, 1349, 1351, 1352, 1353, 1357, 1358, 2802, 1354, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1355, 1359, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1356, 79, 80, 81, 1406, 1357, 1358, 79, 80, 81, 1360, 79, 80, 81, 1361, 1362, 1363, 1365, 2802, 2802, 1359, 1364, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 2802, 1360, 2802, 1366, 1370, 1361, 1362, 1363, 1365, 2802, 2802, 1367, 1364, 1372, 1373, 1374, 79, 80, 81, 1368, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1366, 1370, 2802, 1371, 1369, 79, 80, 81, 1367, 1375, 1372, 1373, 1374, 2802, 2802, 1376, 1368, 79, 80, 81, 1377, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1371, 1369, 2802, 79, 80, 81, 1375, 1380, 1381, 79, 80, 81, 1376, 79, 80, 81, 1378, 1377, 1383, 79, 80, 81, 79, 80, 81, 1382, 1385, 2802, 1384, 1388, 2802, 79, 80, 81, 79, 80, 81, 1380, 1381, 2802, 1379, 2802, 2802, 79, 80, 81, 1378, 2802, 1383, 1386, 1387, 79, 80, 81, 1389, 1382, 1385, 2802, 1384, 1388, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1386, 1387, 79, 80, 81, 1389, 79, 80, 81, 1390, 1391, 1394, 2802, 79, 80, 81, 1392, 1396, 79, 80, 81, 1393, 79, 80, 81, 2802, 1395, 79, 80, 81, 79, 80, 81, 2802, 2802, 1397, 79, 80, 81, 1390, 1391, 1394, 2802, 2802, 1398, 2802, 1392, 1396, 79, 80, 81, 1393, 2802, 79, 80, 81, 1395, 2802, 2802, 79, 80, 81, 79, 80, 81, 1397, 1399, 79, 80, 81, 1400, 79, 80, 81, 1398, 1401, 1404, 79, 80, 81, 1405, 1402, 79, 80, 81, 2802, 79, 80, 81, 2802, 1407, 79, 80, 81, 2802, 1409, 1399, 1403, 2802, 1408, 1400, 1412, 1410, 2802, 2802, 1401, 1404, 79, 80, 81, 1405, 1402, 79, 80, 81, 2802, 2802, 79, 80, 81, 1407, 2802, 79, 80, 81, 1409, 2802, 1403, 1411, 1408, 1413, 1412, 1410, 1414, 79, 80, 81, 1418, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2802, 1411, 1421, 1413, 2802, 2802, 1414, 2802, 2802, 1419, 1418, 1420, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1415, 79, 80, 81, 2802, 1427, 1416, 1433, 1416, 1424, 1416, 1421, 79, 80, 81, 79, 80, 81, 1419, 1422, 1420, 1416, 1426, 1430, 1416, 1423, 79, 80, 81, 1425, 79, 80, 81, 2802, 1417, 1427, 1416, 1433, 1416, 1424, 1416, 1428, 79, 80, 81, 1429, 79, 80, 81, 1422, 2802, 1416, 1426, 1430, 1416, 1423, 79, 80, 81, 2802, 2802, 79, 80, 81, 1431, 1435, 2802, 79, 80, 81, 1432, 1428, 79, 80, 81, 1429, 2802, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 1434, 1436, 1437, 1439, 1440, 79, 80, 81, 1431, 1435, 2802, 79, 80, 81, 1432, 79, 80, 81, 1438, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 1441, 2802, 1434, 1436, 1437, 1439, 1440, 79, 80, 81, 1442, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1438, 1443, 2802, 2802, 79, 80, 81, 1444, 1449, 1447, 1441, 79, 80, 81, 1445, 1446, 79, 80, 81, 2802, 1442, 2802, 2802, 1448, 1451, 2802, 2802, 79, 80, 81, 2802, 1443, 79, 80, 81, 2802, 2802, 1444, 1449, 1447, 1450, 1452, 2802, 2802, 1445, 1446, 1453, 79, 80, 81, 79, 80, 81, 1448, 1451, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1450, 1452, 79, 80, 81, 1454, 1453, 1455, 1456, 79, 80, 81, 2802, 1462, 79, 80, 81, 79, 80, 81, 1459, 2802, 79, 80, 81, 2802, 1457, 1460, 1461, 1458, 79, 80, 81, 2802, 2802, 1454, 2802, 1455, 1456, 2802, 1465, 2802, 2802, 1462, 1463, 79, 80, 81, 1464, 2802, 1459, 2802, 2802, 79, 80, 81, 1457, 1460, 1461, 1458, 79, 80, 81, 1466, 79, 80, 81, 79, 80, 81, 1465, 79, 80, 81, 1463, 79, 80, 81, 1464, 2802, 79, 80, 81, 1467, 1471, 1473, 79, 80, 81, 79, 80, 81, 1472, 1466, 1474, 2802, 79, 80, 81, 1468, 1469, 79, 80, 81, 1470, 79, 80, 81, 1477, 79, 80, 81, 1475, 1467, 1476, 1473, 79, 80, 81, 79, 80, 81, 1472, 2802, 2802, 1478, 79, 80, 81, 1468, 1469, 2802, 2802, 1479, 1470, 79, 80, 81, 1477, 79, 80, 81, 1475, 1480, 1476, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1478, 2802, 79, 80, 81, 79, 80, 81, 1479, 1481, 1482, 79, 80, 81, 1483, 1485, 2802, 2802, 1480, 79, 80, 81, 79, 80, 81, 1484, 1488, 79, 80, 81, 79, 80, 81, 2802, 2802, 1486, 79, 80, 81, 1481, 1482, 79, 80, 81, 1483, 1485, 1487, 79, 80, 81, 79, 80, 81, 2802, 2802, 1484, 2802, 1489, 79, 80, 81, 1490, 79, 80, 81, 1486, 2802, 79, 80, 81, 79, 80, 81, 1496, 2802, 2802, 1487, 79, 80, 81, 1491, 1492, 2802, 1493, 79, 80, 81, 1489, 1494, 1495, 2802, 1490, 2802, 2802, 1497, 2802, 79, 80, 81, 2802, 79, 80, 81, 1496, 79, 80, 81, 79, 80, 81, 1491, 1492, 2802, 1493, 1498, 79, 80, 81, 1494, 1495, 1499, 79, 80, 81, 1497, 1500, 1504, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1503, 79, 80, 81, 1498, 2802, 2802, 1501, 1507, 2802, 1499, 79, 80, 81, 2802, 1500, 1504, 79, 80, 81, 2802, 2802, 1502, 79, 80, 81, 79, 80, 81, 2802, 1503, 1505, 1508, 1509, 79, 80, 81, 1501, 1507, 1506, 1510, 2802, 79, 80, 81, 1511, 1513, 2802, 2802, 79, 80, 81, 1502, 1512, 79, 80, 81, 79, 80, 81, 2802, 1505, 1508, 1509, 79, 80, 81, 1514, 2802, 1506, 1510, 79, 80, 81, 2802, 1511, 1513, 79, 80, 81, 2802, 2802, 1516, 1512, 1515, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1514, 1517, 79, 80, 81, 79, 80, 81, 1518, 1521, 1520, 1519, 79, 80, 81, 1516, 2802, 2802, 1523, 79, 80, 81, 79, 80, 81, 1524, 2802, 79, 80, 81, 2802, 1517, 1522, 1526, 79, 80, 81, 2802, 1518, 1521, 1520, 1519, 79, 80, 81, 79, 80, 81, 1523, 1525, 2802, 2802, 79, 80, 81, 1524, 1527, 1529, 79, 80, 81, 1528, 1522, 1526, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1525, 79, 80, 81, 79, 80, 81, 1527, 1529, 1530, 1531, 2802, 1528, 79, 80, 81, 1532, 1533, 1548, 1542, 79, 80, 81, 1534, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 1535, 79, 80, 81, 2802, 2802, 1530, 1531, 1536, 79, 80, 81, 1537, 1532, 1533, 2802, 1542, 79, 80, 81, 1534, 1538, 1539, 1541, 79, 80, 81, 79, 80, 81, 1535, 2802, 79, 80, 81, 79, 80, 81, 1536, 79, 80, 81, 1537, 1540, 79, 80, 81, 79, 80, 81, 1543, 1538, 1539, 1541, 79, 80, 81, 1544, 79, 80, 81, 79, 80, 81, 1545, 1546, 1551, 1609, 79, 80, 81, 2802, 2802, 1540, 1547, 79, 80, 81, 2802, 2802, 1543, 1549, 79, 80, 81, 2802, 1550, 1544, 79, 80, 81, 79, 80, 81, 1545, 1546, 1551, 1609, 2802, 2802, 79, 80, 81, 1552, 1547, 79, 80, 81, 79, 80, 81, 1549, 1553, 79, 80, 81, 1550, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1554, 79, 80, 81, 2802, 2802, 1555, 1552, 2802, 79, 80, 81, 1556, 2802, 1557, 1558, 1553, 79, 80, 81, 1559, 1560, 1563, 79, 80, 81, 79, 80, 81, 1561, 1554, 1562, 2802, 79, 80, 81, 1555, 2802, 79, 80, 81, 2802, 1556, 2802, 1557, 1558, 2802, 79, 80, 81, 1559, 1560, 1563, 79, 80, 81, 79, 80, 81, 1561, 1566, 1562, 2802, 2802, 1567, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1564, 1568, 79, 80, 81, 1569, 79, 80, 81, 79, 80, 81, 1565, 79, 80, 81, 1566, 79, 80, 81, 1567, 79, 80, 81, 2802, 1572, 79, 80, 81, 2802, 1564, 1568, 1577, 1570, 1574, 1569, 79, 80, 81, 2802, 1573, 1575, 1565, 1571, 1576, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1572, 2802, 2802, 79, 80, 81, 1578, 1577, 1570, 1574, 2802, 2802, 79, 80, 81, 1573, 1575, 2802, 1571, 1576, 1579, 1580, 2802, 2802, 79, 80, 81, 1581, 1582, 1583, 79, 80, 81, 79, 80, 81, 1578, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1579, 1580, 79, 80, 81, 1584, 1587, 1581, 1582, 1583, 1588, 1589, 1592, 1585, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1586, 1590, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1584, 1587, 2802, 2802, 1591, 1588, 1589, 1592, 1585, 1593, 1594, 79, 80, 81, 79, 80, 81, 2802, 1595, 1590, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1596, 1597, 79, 80, 81, 1591, 79, 80, 81, 2802, 1593, 1594, 2802, 2802, 1598, 1599, 79, 80, 81, 1595, 1601, 2802, 1603, 2802, 2802, 1602, 1605, 79, 80, 81, 1596, 1597, 2802, 1600, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1598, 1599, 79, 80, 81, 2802, 1601, 1604, 1603, 2802, 2802, 1602, 1605, 79, 80, 81, 79, 80, 81, 1600, 79, 80, 81, 1606, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1607, 1604, 79, 80, 81, 79, 80, 81, 1608, 1610, 1614, 79, 80, 81, 79, 80, 81, 1606, 1612, 1616, 1611, 1613, 1615, 79, 80, 81, 79, 80, 81, 2802, 1607, 2802, 1619, 79, 80, 81, 2802, 2802, 1608, 1610, 1614, 79, 80, 81, 79, 80, 81, 1617, 1612, 1616, 1611, 1613, 1615, 79, 80, 81, 1618, 1649, 1620, 79, 80, 81, 1619, 2802, 79, 80, 81, 79, 80, 81, 1621, 79, 80, 81, 79, 80, 81, 1617, 79, 80, 81, 1622, 79, 80, 81, 1623, 1618, 1649, 1620, 79, 80, 81, 79, 80, 81, 1624, 2802, 79, 80, 81, 1621, 1629, 2802, 79, 80, 81, 79, 80, 81, 1631, 2802, 1622, 2802, 2802, 1309, 1623, 2802, 79, 80, 81, 1309, 1630, 1625, 1632, 1309, 1624, 1633, 2802, 79, 80, 81, 1629, 2802, 2802, 1635, 1309, 2802, 1626, 1309, 1631, 2802, 2802, 79, 80, 81, 79, 80, 81, 1634, 1637, 1309, 1630, 1625, 1632, 1309, 1639, 1633, 79, 80, 81, 2802, 79, 80, 81, 1635, 1309, 2802, 1626, 1309, 79, 80, 81, 1636, 2802, 2802, 79, 80, 81, 1634, 1637, 1638, 2802, 79, 80, 81, 1639, 1640, 1641, 1645, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1642, 1643, 1636, 1666, 2802, 79, 80, 81, 2802, 2802, 1638, 1644, 1646, 79, 80, 81, 1640, 1641, 1645, 1651, 2802, 79, 80, 81, 1647, 2802, 1652, 79, 80, 81, 1642, 1643, 1648, 1666, 79, 80, 81, 2802, 79, 80, 81, 1644, 1646, 2802, 79, 80, 81, 1650, 79, 80, 81, 79, 80, 81, 1647, 2802, 1652, 1653, 79, 80, 81, 1654, 1648, 79, 80, 81, 79, 80, 81, 1657, 2802, 1663, 2802, 79, 80, 81, 1658, 1650, 1655, 2802, 2802, 79, 80, 81, 79, 80, 81, 1653, 1656, 2802, 2802, 1654, 2802, 79, 80, 81, 1659, 2802, 2802, 1657, 1660, 1663, 1661, 1667, 1662, 2802, 1658, 2802, 1655, 2802, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1659, 1664, 1670, 2802, 1660, 1665, 1661, 1667, 1662, 1668, 1689, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1669, 1672, 1671, 2802, 1664, 1670, 2802, 1673, 1665, 1675, 2802, 2802, 1668, 1689, 2802, 79, 80, 81, 2802, 79, 80, 81, 1674, 79, 80, 81, 79, 80, 81, 2802, 1669, 1672, 1671, 1676, 79, 80, 81, 1673, 1677, 1675, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 1678, 1679, 1680, 79, 80, 81, 79, 80, 81, 1684, 2802, 1681, 1676, 2802, 79, 80, 81, 1677, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1685, 2802, 2802, 1678, 1679, 1680, 1686, 1682, 1688, 79, 80, 81, 1684, 1687, 1681, 79, 80, 81, 1683, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1685, 79, 80, 81, 1690, 2802, 1686, 1682, 1688, 2802, 79, 80, 81, 1687, 1691, 1692, 1693, 1694, 1683, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1690, 79, 80, 81, 1695, 79, 80, 81, 1696, 1698, 1691, 1692, 1693, 1694, 1697, 1703, 2802, 1700, 79, 80, 81, 2802, 2802, 1701, 2802, 1699, 2802, 79, 80, 81, 79, 80, 81, 1702, 1695, 79, 80, 81, 1696, 1698, 79, 80, 81, 2802, 1697, 1703, 2802, 1700, 2802, 2802, 79, 80, 81, 1701, 1704, 1699, 1706, 79, 80, 81, 2802, 1708, 1705, 1702, 79, 80, 81, 79, 80, 81, 1707, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1704, 1710, 1706, 1712, 2802, 79, 80, 81, 1705, 79, 80, 81, 79, 80, 81, 1709, 1707, 1711, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1710, 1713, 1712, 79, 80, 81, 1714, 1721, 2802, 1727, 2802, 79, 80, 81, 1709, 1715, 1711, 79, 80, 81, 1716, 1719, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1713, 2802, 79, 80, 81, 1714, 1721, 79, 80, 81, 79, 80, 81, 2802, 1715, 2802, 2802, 1720, 2802, 1716, 1719, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1415, 2802, 79, 80, 81, 1415, 1415, 1717, 1415, 1723, 1415, 1416, 1718, 1416, 1724, 1416, 1731, 1720, 79, 80, 81, 1415, 1722, 1725, 1415, 2802, 1416, 2802, 2802, 1416, 79, 80, 81, 79, 80, 81, 1415, 1717, 1415, 1723, 1415, 1416, 1718, 1416, 1724, 1416, 1726, 2802, 79, 80, 81, 1415, 1722, 1725, 1415, 1728, 1416, 1729, 1730, 1416, 2802, 79, 80, 81, 1732, 79, 80, 81, 2802, 2802, 79, 80, 81, 1733, 1734, 1735, 1726, 2802, 79, 80, 81, 79, 80, 81, 2802, 1728, 1736, 1729, 1730, 2802, 79, 80, 81, 1737, 1732, 1738, 2802, 79, 80, 81, 1739, 2802, 1741, 1733, 1734, 1735, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1736, 79, 80, 81, 79, 80, 81, 1737, 2802, 1738, 1748, 79, 80, 81, 1739, 1740, 1741, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1742, 79, 80, 81, 1743, 1744, 79, 80, 81, 1745, 79, 80, 81, 1740, 79, 80, 81, 2802, 2802, 1747, 1749, 79, 80, 81, 1746, 79, 80, 81, 1750, 2802, 1742, 79, 80, 81, 1743, 1744, 79, 80, 81, 1745, 1751, 2802, 2802, 79, 80, 81, 79, 80, 81, 1747, 1749, 79, 80, 81, 1746, 2802, 2802, 1752, 1750, 1753, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1751, 79, 80, 81, 1754, 1755, 2802, 1759, 79, 80, 81, 2802, 2802, 1760, 79, 80, 81, 1752, 2802, 1753, 1756, 2802, 79, 80, 81, 2802, 2802, 1757, 1761, 79, 80, 81, 2802, 2802, 1754, 1755, 2802, 1759, 1758, 2802, 1762, 2802, 2802, 1760, 2802, 1764, 79, 80, 81, 2802, 1756, 2802, 1763, 1765, 79, 80, 81, 1757, 1761, 1767, 79, 80, 81, 79, 80, 81, 1766, 1768, 1758, 79, 80, 81, 79, 80, 81, 1764, 2802, 2802, 1770, 79, 80, 81, 1763, 1765, 79, 80, 81, 2802, 1769, 1767, 79, 80, 81, 2802, 1776, 2802, 1766, 1768, 2802, 2802, 1771, 79, 80, 81, 1772, 79, 80, 81, 1770, 2802, 1775, 1778, 79, 80, 81, 79, 80, 81, 1769, 1773, 79, 80, 81, 1774, 1776, 2802, 2802, 79, 80, 81, 1771, 2802, 2802, 1777, 1772, 2802, 2802, 79, 80, 81, 1775, 1778, 79, 80, 81, 79, 80, 81, 1779, 1773, 79, 80, 81, 1774, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1777, 79, 80, 81, 1782, 79, 80, 81, 1780, 1783, 1793, 2802, 79, 80, 81, 1779, 79, 80, 81, 2802, 79, 80, 81, 1784, 2802, 1785, 1781, 1786, 79, 80, 81, 2802, 2802, 1791, 1782, 79, 80, 81, 1780, 1783, 1793, 79, 80, 81, 79, 80, 81, 1787, 2802, 79, 80, 81, 1788, 1784, 1789, 1785, 1781, 1786, 1790, 1792, 79, 80, 81, 1791, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1787, 1795, 79, 80, 81, 1788, 1794, 1789, 79, 80, 81, 1790, 1792, 79, 80, 81, 1798, 79, 80, 81, 1796, 1797, 1800, 1799, 79, 80, 81, 79, 80, 81, 2802, 1795, 79, 80, 81, 2802, 1794, 2802, 79, 80, 81, 2802, 79, 80, 81, 1801, 1798, 1802, 1803, 1804, 1796, 1797, 1800, 1799, 1805, 1806, 1811, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1801, 2802, 1802, 1803, 1804, 1807, 79, 80, 81, 1805, 1806, 1811, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1808, 1813, 1809, 79, 80, 81, 2802, 1812, 1814, 1807, 1810, 79, 80, 81, 79, 80, 81, 2802, 2802, 1815, 1816, 79, 80, 81, 2802, 2802, 79, 80, 81, 1817, 1808, 1813, 1809, 79, 80, 81, 2802, 1812, 1814, 1818, 1810, 1821, 1825, 2802, 1819, 1820, 79, 80, 81, 1815, 1816, 79, 80, 81, 79, 80, 81, 1822, 2802, 1817, 2802, 79, 80, 81, 79, 80, 81, 2802, 2802, 1818, 2802, 1821, 1825, 2802, 1819, 1820, 79, 80, 81, 79, 80, 81, 1823, 79, 80, 81, 2802, 1822, 1824, 79, 80, 81, 1826, 1827, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1830, 1829, 79, 80, 81, 2802, 1823, 1828, 1831, 79, 80, 81, 1824, 2802, 1833, 1832, 1826, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1834, 2802, 1830, 1829, 79, 80, 81, 79, 80, 81, 1831, 79, 80, 81, 79, 80, 81, 1832, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1835, 1837, 1842, 1834, 2802, 1838, 1836, 79, 80, 81, 2802, 2802, 79, 80, 81, 1839, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1840, 1841, 2802, 2802, 1835, 1837, 1842, 1849, 2802, 1838, 1836, 2802, 1846, 79, 80, 81, 1843, 1844, 1845, 1839, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1840, 1841, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1846, 2802, 2802, 1850, 1843, 1844, 1845, 79, 80, 81, 1847, 79, 80, 81, 1851, 79, 80, 81, 1853, 1848, 2802, 2802, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 1850, 2802, 2802, 1852, 79, 80, 81, 1847, 1854, 1860, 2802, 1851, 1856, 2802, 1855, 1857, 1848, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 1861, 2802, 2802, 79, 80, 81, 1852, 2802, 79, 80, 81, 1854, 1860, 1858, 2802, 1856, 2802, 1855, 1857, 1859, 1862, 1864, 1868, 79, 80, 81, 2802, 79, 80, 81, 1861, 2802, 2802, 1863, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1858, 79, 80, 81, 2802, 2802, 1859, 1862, 1864, 1868, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1863, 1865, 1870, 79, 80, 81, 1869, 1871, 1872, 1873, 1874, 2802, 1866, 79, 80, 81, 1867, 1877, 2802, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2802, 2802, 1865, 1870, 79, 80, 81, 1869, 1871, 1872, 1873, 1874, 1875, 1866, 1876, 1878, 2802, 1867, 1877, 79, 80, 81, 79, 80, 81, 1879, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1875, 1880, 1876, 1878, 79, 80, 81, 79, 80, 81, 1881, 1882, 2802, 1879, 2802, 1884, 79, 80, 81, 79, 80, 81, 1883, 1888, 79, 80, 81, 2802, 2802, 1885, 2802, 1880, 79, 80, 81, 2802, 1887, 79, 80, 81, 1881, 1882, 79, 80, 81, 1884, 1886, 1890, 79, 80, 81, 1889, 1883, 1888, 2802, 2802, 79, 80, 81, 1885, 1891, 1892, 2802, 79, 80, 81, 1887, 1895, 2802, 79, 80, 81, 1893, 79, 80, 81, 1886, 1890, 79, 80, 81, 1889, 1894, 79, 80, 81, 79, 80, 81, 2802, 1891, 1892, 79, 80, 81, 1896, 1897, 1895, 79, 80, 81, 2802, 1893, 79, 80, 81, 1898, 1899, 2802, 79, 80, 81, 1894, 79, 80, 81, 79, 80, 81, 1900, 1901, 1909, 79, 80, 81, 1896, 1897, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1898, 1899, 79, 80, 81, 1625, 1627, 2802, 2802, 79, 80, 81, 1905, 1900, 1901, 1909, 2802, 2802, 1906, 1907, 1626, 1628, 1908, 1902, 1904, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1910, 1625, 1627, 2802, 79, 80, 81, 2802, 1905, 2802, 79, 80, 81, 2802, 1906, 1907, 1626, 1628, 1908, 1902, 1904, 1911, 1913, 1914, 79, 80, 81, 79, 80, 81, 1910, 79, 80, 81, 1912, 1915, 1916, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 1911, 1913, 1914, 79, 80, 81, 1917, 79, 80, 81, 79, 80, 81, 1912, 2802, 1916, 79, 80, 81, 1918, 1919, 1920, 2802, 79, 80, 81, 1921, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1922, 79, 80, 81, 79, 80, 81, 2802, 1918, 1919, 1920, 79, 80, 81, 1923, 1921, 79, 80, 81, 1924, 1925, 2802, 79, 80, 81, 1926, 79, 80, 81, 1927, 1922, 79, 80, 81, 1928, 79, 80, 81, 2802, 2802, 1929, 79, 80, 81, 1923, 2802, 79, 80, 81, 1924, 1925, 2802, 2802, 1930, 1931, 1926, 2802, 2802, 1932, 1927, 2802, 79, 80, 81, 1928, 1933, 2802, 79, 80, 81, 1929, 2802, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 1930, 1931, 79, 80, 81, 1932, 79, 80, 81, 79, 80, 81, 1933, 1934, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1935, 1936, 79, 80, 81, 1937, 2802, 2802, 1938, 79, 80, 81, 1939, 1942, 1934, 1940, 1941, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 1946, 1936, 79, 80, 81, 1937, 2802, 1943, 1938, 2802, 2802, 1945, 1939, 1942, 2802, 1940, 1941, 2802, 79, 80, 81, 2802, 1947, 1944, 2802, 2802, 79, 80, 81, 2802, 1946, 79, 80, 81, 79, 80, 81, 1943, 79, 80, 81, 1945, 79, 80, 81, 79, 80, 81, 1948, 1950, 79, 80, 81, 1944, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1949, 1951, 1952, 79, 80, 81, 79, 80, 81, 1948, 1953, 1954, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1956, 79, 80, 81, 2802, 1955, 1949, 1951, 1952, 1959, 2802, 79, 80, 81, 2802, 2802, 1953, 1954, 2802, 1957, 1958, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1956, 1960, 79, 80, 81, 1955, 79, 80, 81, 1959, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1957, 1958, 79, 80, 81, 1961, 1962, 1963, 79, 80, 81, 1965, 1960, 2802, 1964, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 1968, 79, 80, 81, 2802, 1967, 2802, 2802, 1961, 1962, 1963, 79, 80, 81, 1965, 1969, 2802, 1964, 2802, 1972, 79, 80, 81, 79, 80, 81, 1976, 79, 80, 81, 1968, 1973, 79, 80, 81, 1967, 79, 80, 81, 2802, 1970, 79, 80, 81, 1975, 1969, 79, 80, 81, 1972, 1974, 1971, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1973, 2802, 1977, 1978, 1981, 1979, 79, 80, 81, 1970, 79, 80, 81, 1975, 2802, 2802, 79, 80, 81, 1974, 1971, 2802, 79, 80, 81, 79, 80, 81, 1980, 79, 80, 81, 1977, 1978, 1981, 1979, 1982, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 1984, 1985, 79, 80, 81, 79, 80, 81, 1983, 1980, 79, 80, 81, 79, 80, 81, 1986, 1982, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2802, 2802, 1984, 1985, 2802, 1987, 1996, 79, 80, 81, 1983, 1988, 2802, 2005, 1995, 79, 80, 81, 1986, 2802, 2802, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 1987, 1996, 1997, 2802, 2802, 1998, 1988, 2000, 2802, 1995, 79, 80, 81, 2802, 79, 80, 81, 1999, 79, 80, 81, 2802, 79, 80, 81, 1989, 79, 80, 81, 2802, 1990, 2802, 1997, 2802, 1991, 1998, 2004, 2000, 1992, 2002, 2001, 1993, 2006, 1994, 79, 80, 81, 1999, 2802, 2802, 79, 80, 81, 2802, 2802, 1989, 2003, 79, 80, 81, 1990, 79, 80, 81, 1991, 2009, 2004, 2802, 1992, 2002, 2001, 1993, 2006, 1994, 2802, 2802, 2010, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2003, 2011, 79, 80, 81, 2007, 79, 80, 81, 2009, 2012, 2008, 2802, 2013, 79, 80, 81, 79, 80, 81, 2010, 79, 80, 81, 2802, 2802, 2014, 2015, 2802, 2802, 2019, 2011, 79, 80, 81, 2007, 2802, 2802, 2016, 2802, 2012, 2008, 2017, 2013, 79, 80, 81, 2802, 79, 80, 81, 2802, 2018, 79, 80, 81, 2014, 2015, 2802, 2020, 2019, 2024, 79, 80, 81, 2021, 2023, 2802, 2016, 79, 80, 81, 2017, 2802, 2802, 2022, 79, 80, 81, 79, 80, 81, 2018, 79, 80, 81, 79, 80, 81, 2020, 2025, 2024, 79, 80, 81, 2021, 2023, 79, 80, 81, 2026, 2802, 79, 80, 81, 2022, 2027, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2028, 2025, 2029, 79, 80, 81, 2030, 79, 80, 81, 2031, 2026, 79, 80, 81, 2032, 2802, 2027, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2028, 2033, 2029, 79, 80, 81, 2030, 79, 80, 81, 2031, 79, 80, 81, 2802, 2032, 2802, 2034, 2035, 79, 80, 81, 79, 80, 81, 2036, 2037, 79, 80, 81, 2802, 2033, 79, 80, 81, 2038, 79, 80, 81, 79, 80, 81, 2039, 2802, 79, 80, 81, 2034, 2035, 79, 80, 81, 2041, 2040, 2044, 2036, 2037, 2043, 2802, 2042, 79, 80, 81, 2802, 2045, 2038, 79, 80, 81, 79, 80, 81, 2039, 2802, 79, 80, 81, 2802, 79, 80, 81, 2802, 2041, 2040, 2044, 2802, 2802, 2043, 2802, 2042, 2046, 79, 80, 81, 2045, 2047, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2046, 79, 80, 81, 2048, 2047, 79, 80, 81, 2049, 79, 80, 81, 2052, 2802, 2050, 79, 80, 81, 79, 80, 81, 2051, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 2048, 79, 80, 81, 2053, 2049, 2054, 2055, 2802, 2052, 2802, 2050, 2057, 79, 80, 81, 2802, 2056, 2051, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 2058, 79, 80, 81, 2053, 2802, 2054, 2055, 79, 80, 81, 2802, 2057, 2059, 2060, 2062, 2061, 2056, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2063, 2064, 2802, 2058, 2802, 79, 80, 81, 79, 80, 81, 2067, 79, 80, 81, 2802, 2059, 2060, 2062, 2061, 2802, 2065, 79, 80, 81, 2066, 2069, 2068, 2802, 2802, 2063, 2064, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2067, 2802, 2802, 79, 80, 81, 2070, 79, 80, 81, 2065, 79, 80, 81, 2066, 2069, 2068, 2071, 2072, 2802, 2802, 79, 80, 81, 2073, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2074, 2076, 2070, 2075, 79, 80, 81, 79, 80, 81, 2802, 2802, 2077, 2802, 2072, 79, 80, 81, 2078, 2802, 2073, 2802, 2802, 2079, 79, 80, 81, 79, 80, 81, 2074, 2076, 2802, 2075, 2080, 79, 80, 81, 2802, 79, 80, 81, 2077, 79, 80, 81, 2802, 2802, 2078, 2081, 79, 80, 81, 2079, 2082, 2083, 2084, 2085, 79, 80, 81, 79, 80, 81, 2080, 79, 80, 81, 79, 80, 81, 2086, 79, 80, 81, 79, 80, 81, 2802, 2081, 2087, 2088, 2093, 2802, 2082, 2083, 2084, 2085, 2802, 2802, 2089, 79, 80, 81, 79, 80, 81, 2090, 79, 80, 81, 2086, 79, 80, 81, 2802, 79, 80, 81, 2802, 2087, 2088, 2093, 2091, 2092, 2094, 2802, 79, 80, 81, 2089, 2095, 2802, 2096, 79, 80, 81, 2090, 2802, 2802, 79, 80, 81, 79, 80, 81, 2101, 79, 80, 81, 79, 80, 81, 2091, 2092, 2094, 79, 80, 81, 2802, 2097, 2095, 2098, 2096, 79, 80, 81, 79, 80, 81, 2099, 2802, 79, 80, 81, 2802, 2101, 2100, 2103, 2102, 2802, 2105, 2802, 2104, 79, 80, 81, 79, 80, 81, 2097, 2802, 2098, 79, 80, 81, 79, 80, 81, 2802, 2099, 79, 80, 81, 79, 80, 81, 2100, 2103, 2102, 2106, 2105, 2107, 2104, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2108, 2802, 2111, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 2106, 2109, 2107, 79, 80, 81, 79, 80, 81, 2110, 79, 80, 81, 2108, 2112, 2111, 2114, 2113, 79, 80, 81, 79, 80, 81, 2118, 79, 80, 81, 79, 80, 81, 2109, 2802, 2802, 2115, 79, 80, 81, 2119, 2110, 79, 80, 81, 2802, 2112, 2802, 2114, 2113, 2802, 2120, 2121, 2802, 2123, 2802, 2118, 2802, 2122, 79, 80, 81, 2802, 79, 80, 81, 2115, 79, 80, 81, 2119, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2120, 2121, 2124, 2123, 79, 80, 81, 2122, 79, 80, 81, 2126, 2127, 2132, 2125, 2129, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2124, 79, 80, 81, 2128, 79, 80, 81, 2130, 2126, 2127, 2132, 2125, 2129, 79, 80, 81, 2131, 79, 80, 81, 79, 80, 81, 2133, 2134, 79, 80, 81, 79, 80, 81, 2135, 2802, 2128, 79, 80, 81, 2130, 2138, 2802, 79, 80, 81, 2136, 2802, 2802, 2131, 2137, 2143, 2802, 79, 80, 81, 2133, 2134, 2802, 79, 80, 81, 2802, 2802, 2135, 2802, 79, 80, 81, 2802, 2139, 2138, 2802, 79, 80, 81, 2136, 2140, 2802, 2141, 2137, 2143, 2802, 79, 80, 81, 2144, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2139, 79, 80, 81, 79, 80, 81, 2140, 2142, 2141, 2145, 79, 80, 81, 2802, 2147, 2144, 79, 80, 81, 79, 80, 81, 2146, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2148, 2142, 79, 80, 81, 79, 80, 81, 2147, 2149, 2150, 79, 80, 81, 2151, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 2152, 2148, 79, 80, 81, 2153, 79, 80, 81, 2156, 2149, 2150, 79, 80, 81, 2151, 2154, 2155, 79, 80, 81, 2162, 79, 80, 81, 2802, 2157, 79, 80, 81, 2152, 2802, 79, 80, 81, 2153, 79, 80, 81, 2156, 2802, 2158, 2159, 79, 80, 81, 2154, 2155, 2161, 2802, 2160, 2162, 2802, 79, 80, 81, 2157, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 2158, 2159, 79, 80, 81, 2802, 2802, 2161, 2163, 2160, 79, 80, 81, 79, 80, 81, 2164, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2165, 2167, 2168, 2172, 79, 80, 81, 79, 80, 81, 2163, 2166, 2170, 79, 80, 81, 2169, 2802, 2164, 2802, 2173, 79, 80, 81, 2174, 2802, 2802, 79, 80, 81, 2165, 2167, 2168, 2172, 79, 80, 81, 2171, 79, 80, 81, 2166, 2170, 79, 80, 81, 2169, 79, 80, 81, 2173, 79, 80, 81, 2174, 79, 80, 81, 79, 80, 81, 2175, 79, 80, 81, 2178, 2802, 2171, 79, 80, 81, 79, 80, 81, 2176, 2802, 79, 80, 81, 79, 80, 81, 2802, 2191, 2177, 79, 80, 81, 2179, 2180, 2802, 2175, 2802, 2802, 2182, 2178, 2188, 2802, 2802, 2181, 79, 80, 81, 2802, 2176, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2177, 79, 80, 81, 2179, 2180, 2187, 79, 80, 81, 2182, 2183, 2188, 2802, 2193, 2181, 2189, 79, 80, 81, 79, 80, 81, 2185, 2802, 2184, 79, 80, 81, 2192, 2802, 79, 80, 81, 2190, 2802, 2187, 2186, 79, 80, 81, 2183, 2802, 2802, 2193, 2802, 2189, 2802, 79, 80, 81, 2802, 2194, 2185, 2199, 2184, 2802, 2802, 2196, 2192, 79, 80, 81, 2802, 2190, 2802, 2195, 2186, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2197, 79, 80, 81, 2194, 2198, 2199, 79, 80, 81, 2196, 79, 80, 81, 2200, 79, 80, 81, 2195, 2201, 2203, 79, 80, 81, 2202, 79, 80, 81, 2802, 2802, 2197, 2802, 79, 80, 81, 2198, 79, 80, 81, 79, 80, 81, 2802, 2204, 2200, 2205, 79, 80, 81, 2201, 2203, 2206, 2208, 2802, 2202, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2209, 79, 80, 81, 2204, 2207, 2205, 79, 80, 81, 2210, 2212, 2206, 2208, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2209, 2211, 79, 80, 81, 2213, 2214, 79, 80, 81, 2210, 2212, 79, 80, 81, 79, 80, 81, 2215, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2211, 79, 80, 81, 2213, 2214, 2216, 2219, 2218, 2221, 2217, 2220, 2802, 79, 80, 81, 2802, 2215, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2222, 79, 80, 81, 79, 80, 81, 2802, 2802, 2216, 2219, 2218, 2221, 2217, 2220, 2223, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 2222, 79, 80, 81, 2224, 79, 80, 81, 79, 80, 81, 2802, 2225, 2226, 2227, 2223, 79, 80, 81, 79, 80, 81, 2228, 2802, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2224, 79, 80, 81, 2229, 79, 80, 81, 2225, 2226, 2227, 2230, 2231, 2233, 2234, 79, 80, 81, 2228, 2802, 2802, 2232, 79, 80, 81, 2802, 2802, 79, 80, 81, 2236, 79, 80, 81, 2229, 2802, 2802, 2235, 2237, 2802, 2802, 2230, 2231, 2233, 2234, 79, 80, 81, 79, 80, 81, 2232, 79, 80, 81, 2802, 79, 80, 81, 2802, 2236, 79, 80, 81, 79, 80, 81, 2235, 2237, 2238, 2239, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2243, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2240, 79, 80, 81, 79, 80, 81, 2241, 2238, 2239, 2242, 2244, 79, 80, 81, 2802, 2250, 2246, 2802, 79, 80, 81, 79, 80, 81, 2245, 79, 80, 81, 2247, 2240, 79, 80, 81, 79, 80, 81, 2241, 2802, 2251, 2242, 2244, 2802, 79, 80, 81, 2802, 2246, 79, 80, 81, 2802, 2802, 2255, 2802, 2245, 2802, 2252, 2253, 2247, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2251, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2255, 2802, 2254, 2248, 2252, 2253, 79, 80, 81, 2249, 2256, 2249, 2257, 2249, 2258, 2802, 2261, 2259, 79, 80, 81, 79, 80, 81, 2249, 2260, 2802, 2249, 79, 80, 81, 2802, 2254, 79, 80, 81, 2802, 2802, 2262, 2249, 2256, 2249, 2257, 2249, 2258, 2802, 2261, 2259, 79, 80, 81, 79, 80, 81, 2249, 2260, 2263, 2249, 79, 80, 81, 79, 80, 81, 2264, 79, 80, 81, 2262, 2802, 79, 80, 81, 79, 80, 81, 2266, 79, 80, 81, 79, 80, 81, 2265, 2267, 2268, 2263, 79, 80, 81, 79, 80, 81, 2802, 2264, 79, 80, 81, 2802, 79, 80, 81, 2269, 79, 80, 81, 2266, 2271, 79, 80, 81, 2802, 2802, 2265, 2267, 2268, 2270, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2272, 2269, 79, 80, 81, 2275, 2271, 2276, 2277, 79, 80, 81, 79, 80, 81, 2270, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2272, 79, 80, 81, 2278, 2275, 2280, 2276, 2277, 79, 80, 81, 79, 80, 81, 2279, 2301, 2282, 2281, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2283, 2802, 79, 80, 81, 2278, 2802, 2280, 2284, 2285, 79, 80, 81, 79, 80, 81, 2279, 2301, 2282, 2281, 2802, 2287, 2288, 79, 80, 81, 2802, 79, 80, 81, 2283, 79, 80, 81, 79, 80, 81, 2286, 2284, 2285, 2302, 2289, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2287, 2288, 2290, 79, 80, 81, 79, 80, 81, 2802, 2291, 2292, 79, 80, 81, 2802, 2286, 79, 80, 81, 2289, 79, 80, 81, 2293, 2294, 2295, 79, 80, 81, 2296, 2802, 2290, 79, 80, 81, 2802, 79, 80, 81, 2291, 2292, 2298, 79, 80, 81, 2297, 2299, 79, 80, 81, 79, 80, 81, 2293, 2294, 2295, 79, 80, 81, 2296, 2300, 2303, 2802, 2306, 2304, 79, 80, 81, 79, 80, 81, 2298, 79, 80, 81, 2297, 2299, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2300, 2303, 2305, 2306, 2304, 2307, 2308, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2309, 2310, 2311, 2305, 2314, 2320, 2307, 2308, 79, 80, 81, 2312, 79, 80, 81, 2802, 2802, 2313, 79, 80, 81, 2317, 79, 80, 81, 2802, 2315, 2316, 2802, 2802, 2309, 2310, 2311, 2802, 2314, 2802, 2802, 79, 80, 81, 2802, 2312, 2802, 2802, 79, 80, 81, 2313, 79, 80, 81, 2317, 79, 80, 81, 2318, 2315, 2316, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2319, 2321, 2322, 2324, 2326, 79, 80, 81, 2802, 2318, 2325, 79, 80, 81, 2323, 79, 80, 81, 79, 80, 81, 2802, 2802, 2327, 79, 80, 81, 79, 80, 81, 2319, 2321, 2322, 2324, 2326, 2332, 79, 80, 81, 2328, 2325, 79, 80, 81, 2323, 2329, 79, 80, 81, 2802, 79, 80, 81, 2327, 2330, 2331, 79, 80, 81, 2802, 2802, 79, 80, 81, 2333, 2332, 79, 80, 81, 2328, 79, 80, 81, 2334, 2802, 2329, 2802, 79, 80, 81, 2335, 79, 80, 81, 2330, 2331, 2336, 2802, 79, 80, 81, 79, 80, 81, 2333, 2337, 2802, 79, 80, 81, 2802, 2360, 2339, 2334, 79, 80, 81, 2802, 2802, 2338, 2335, 2341, 79, 80, 81, 2802, 2336, 2340, 2342, 2343, 2802, 2802, 79, 80, 81, 2337, 79, 80, 81, 79, 80, 81, 2339, 79, 80, 81, 79, 80, 81, 2338, 2802, 2341, 2344, 2345, 79, 80, 81, 2340, 2342, 2343, 79, 80, 81, 2802, 79, 80, 81, 2346, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 2344, 2345, 2802, 2802, 79, 80, 81, 2347, 2348, 2802, 2802, 79, 80, 81, 2349, 2346, 2350, 2352, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2351, 2802, 2347, 2348, 2802, 2353, 79, 80, 81, 2349, 2355, 2350, 2352, 2357, 2802, 2354, 79, 80, 81, 2356, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2351, 2802, 79, 80, 81, 2353, 79, 80, 81, 2802, 2355, 2802, 2358, 2357, 2359, 2354, 2361, 2364, 2365, 2356, 2362, 2802, 79, 80, 81, 2363, 2802, 79, 80, 81, 2802, 79, 80, 81, 2802, 2802, 2366, 2367, 2802, 79, 80, 81, 2358, 2802, 2359, 2368, 2361, 2364, 2365, 2369, 2362, 79, 80, 81, 2802, 2363, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2366, 2367, 79, 80, 81, 2370, 79, 80, 81, 2368, 79, 80, 81, 2369, 2371, 79, 80, 81, 79, 80, 81, 2372, 2373, 2374, 79, 80, 81, 2375, 2376, 79, 80, 81, 2377, 2802, 2802, 2370, 2379, 2802, 79, 80, 81, 79, 80, 81, 2371, 2802, 79, 80, 81, 2802, 2802, 2372, 2373, 2374, 2378, 2802, 2802, 2375, 2376, 2380, 2802, 2802, 2377, 2802, 2802, 2388, 2379, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2383, 79, 80, 81, 79, 80, 81, 2380, 79, 80, 81, 79, 80, 81, 2248, 79, 80, 81, 2802, 2802, 2248, 2802, 2248, 2384, 2248, 79, 80, 81, 2802, 2381, 2383, 2802, 2802, 2385, 2248, 2248, 2386, 2802, 2248, 2802, 2249, 2387, 2249, 2389, 2249, 2802, 79, 80, 81, 2382, 2248, 2802, 2248, 2384, 2248, 2249, 2390, 2802, 2249, 2381, 79, 80, 81, 2385, 2802, 2248, 2386, 2802, 2248, 2802, 2249, 2387, 2249, 2389, 2249, 79, 80, 81, 2391, 2382, 79, 80, 81, 2392, 2395, 2249, 2390, 2393, 2249, 79, 80, 81, 2394, 2396, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2397, 79, 80, 81, 2392, 2395, 2398, 2802, 2393, 79, 80, 81, 2802, 2802, 2396, 79, 80, 81, 2802, 2802, 79, 80, 81, 2400, 2401, 79, 80, 81, 2802, 2802, 2397, 79, 80, 81, 2802, 2802, 2398, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2403, 79, 80, 81, 79, 80, 81, 2400, 2401, 2402, 79, 80, 81, 79, 80, 81, 2404, 79, 80, 81, 79, 80, 81, 2405, 2406, 2407, 79, 80, 81, 2408, 2403, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2410, 79, 80, 81, 2409, 2802, 2404, 79, 80, 81, 79, 80, 81, 2405, 2406, 2407, 79, 80, 81, 2802, 2411, 79, 80, 81, 79, 80, 81, 2802, 2802, 2414, 2410, 2416, 2412, 2802, 2409, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2413, 2417, 2802, 79, 80, 81, 2411, 79, 80, 81, 2415, 2802, 79, 80, 81, 2414, 2419, 2416, 2412, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 2413, 2417, 79, 80, 81, 79, 80, 81, 2418, 2420, 2415, 79, 80, 81, 2802, 2422, 2419, 79, 80, 81, 79, 80, 81, 2421, 79, 80, 81, 2423, 79, 80, 81, 2425, 2802, 2426, 79, 80, 81, 2802, 2418, 2420, 2424, 2427, 79, 80, 81, 2422, 79, 80, 81, 79, 80, 81, 2802, 2421, 2802, 2428, 2802, 2423, 79, 80, 81, 2425, 2802, 2426, 2802, 2802, 79, 80, 81, 2438, 2424, 2427, 79, 80, 81, 79, 80, 81, 2429, 79, 80, 81, 79, 80, 81, 2428, 2430, 79, 80, 81, 79, 80, 81, 2431, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2433, 2802, 2802, 2432, 2429, 2435, 79, 80, 81, 79, 80, 81, 2430, 79, 80, 81, 79, 80, 81, 2431, 2802, 2434, 79, 80, 81, 2436, 2442, 79, 80, 81, 2433, 2437, 2802, 2432, 2802, 2435, 2439, 2802, 79, 80, 81, 2440, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2434, 79, 80, 81, 2436, 2441, 2443, 79, 80, 81, 2437, 79, 80, 81, 2802, 2439, 2802, 79, 80, 81, 2440, 79, 80, 81, 2444, 2802, 2445, 79, 80, 81, 2446, 79, 80, 81, 2447, 2441, 2443, 79, 80, 81, 2802, 2449, 2802, 2802, 79, 80, 81, 2448, 2450, 79, 80, 81, 2802, 2452, 2444, 2802, 2445, 2451, 2802, 2802, 2446, 79, 80, 81, 2447, 79, 80, 81, 79, 80, 81, 2449, 79, 80, 81, 2802, 2453, 2448, 2450, 2454, 79, 80, 81, 2452, 79, 80, 81, 2451, 2455, 2457, 2802, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2456, 2802, 79, 80, 81, 2453, 2802, 2458, 2454, 2459, 2460, 79, 80, 81, 79, 80, 81, 2455, 2457, 2464, 2465, 79, 80, 81, 79, 80, 81, 2802, 2802, 2461, 2456, 79, 80, 81, 79, 80, 81, 2458, 2802, 2459, 2460, 79, 80, 81, 2802, 2462, 79, 80, 81, 2464, 2465, 79, 80, 81, 2466, 2463, 79, 80, 81, 2461, 79, 80, 81, 79, 80, 81, 2468, 79, 80, 81, 2802, 2473, 79, 80, 81, 2462, 2467, 2469, 2802, 79, 80, 81, 2802, 2470, 2466, 2463, 79, 80, 81, 79, 80, 81, 2471, 2472, 2802, 2802, 2468, 2474, 2475, 2802, 79, 80, 81, 79, 80, 81, 2467, 2469, 2802, 2802, 79, 80, 81, 2470, 2802, 79, 80, 81, 2476, 79, 80, 81, 2471, 2472, 79, 80, 81, 2474, 2475, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2477, 2802, 79, 80, 81, 2479, 2491, 2476, 2802, 2802, 79, 80, 81, 2480, 2481, 79, 80, 81, 2482, 2483, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2484, 2477, 2802, 2802, 2487, 2802, 2479, 2802, 2802, 79, 80, 81, 2802, 2489, 2480, 2481, 79, 80, 81, 2482, 2483, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 2484, 79, 80, 81, 2487, 79, 80, 81, 2488, 79, 80, 81, 2485, 2489, 2492, 2486, 2495, 2802, 2490, 2493, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2497, 2498, 2802, 2802, 2488, 2802, 2496, 2802, 2485, 2802, 2492, 2486, 2495, 2802, 2490, 2493, 79, 80, 81, 2802, 2802, 2499, 2503, 79, 80, 81, 2802, 79, 80, 81, 2497, 2498, 79, 80, 81, 2802, 2496, 2504, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2499, 2503, 2505, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2500, 79, 80, 81, 2504, 79, 80, 81, 79, 80, 81, 2501, 2506, 2507, 2510, 2802, 2502, 79, 80, 81, 2505, 79, 80, 81, 2802, 2802, 2509, 79, 80, 81, 2500, 79, 80, 81, 2508, 79, 80, 81, 2802, 2511, 2802, 2501, 2506, 2507, 2510, 2514, 2502, 79, 80, 81, 2512, 2515, 2802, 79, 80, 81, 2509, 2513, 79, 80, 81, 79, 80, 81, 2508, 2516, 79, 80, 81, 2511, 2802, 79, 80, 81, 2517, 2514, 2802, 79, 80, 81, 2512, 2515, 79, 80, 81, 2519, 2802, 2513, 79, 80, 81, 79, 80, 81, 2518, 2516, 2520, 2521, 79, 80, 81, 79, 80, 81, 2517, 79, 80, 81, 79, 80, 81, 2802, 2802, 2522, 2523, 2519, 79, 80, 81, 2524, 2802, 79, 80, 81, 2518, 2802, 2520, 2521, 2526, 2525, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 2522, 2523, 79, 80, 81, 2527, 2524, 2802, 2802, 79, 80, 81, 79, 80, 81, 2526, 2525, 79, 80, 81, 2531, 2528, 2532, 79, 80, 81, 79, 80, 81, 2529, 2536, 79, 80, 81, 2533, 2527, 79, 80, 81, 2534, 2530, 2535, 79, 80, 81, 2537, 79, 80, 81, 2802, 2531, 2528, 2802, 2802, 79, 80, 81, 2802, 2802, 2529, 2536, 79, 80, 81, 2541, 2538, 79, 80, 81, 2534, 2530, 2535, 79, 80, 81, 2537, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2539, 79, 80, 81, 2540, 2542, 2545, 79, 80, 81, 2538, 79, 80, 81, 2544, 79, 80, 81, 2802, 2802, 2546, 2802, 2543, 79, 80, 81, 2548, 79, 80, 81, 2539, 2547, 2802, 2802, 2540, 2542, 2802, 2802, 79, 80, 81, 2549, 2802, 2802, 2544, 2550, 2551, 79, 80, 81, 2546, 2552, 2543, 79, 80, 81, 2548, 2802, 79, 80, 81, 2547, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2549, 79, 80, 81, 2550, 2551, 79, 80, 81, 2553, 2552, 2554, 79, 80, 81, 2562, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2555, 2556, 2559, 2561, 2557, 2802, 2553, 2802, 2554, 79, 80, 81, 2562, 2560, 2564, 2802, 79, 80, 81, 2567, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2555, 2556, 2559, 2561, 2557, 79, 80, 81, 2563, 2565, 79, 80, 81, 2560, 2564, 2566, 79, 80, 81, 2567, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2568, 2569, 79, 80, 81, 2563, 2565, 2570, 79, 80, 81, 2571, 2566, 2802, 79, 80, 81, 2572, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2569, 79, 80, 81, 2573, 2575, 2570, 79, 80, 81, 2571, 79, 80, 81, 2574, 2578, 2572, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2576, 79, 80, 81, 79, 80, 81, 2573, 2575, 79, 80, 81, 2802, 2577, 2579, 2802, 2802, 2574, 2578, 79, 80, 81, 2580, 79, 80, 81, 79, 80, 81, 2802, 2576, 2802, 2581, 2582, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2577, 2579, 79, 80, 81, 79, 80, 81, 2583, 2580, 2584, 2588, 2586, 79, 80, 81, 79, 80, 81, 2581, 2582, 79, 80, 81, 2585, 79, 80, 81, 2587, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2583, 2802, 2584, 2588, 2586, 2802, 2589, 2802, 2595, 2590, 79, 80, 81, 79, 80, 81, 2585, 2591, 2802, 2802, 2587, 79, 80, 81, 2802, 79, 80, 81, 2596, 79, 80, 81, 79, 80, 81, 2802, 2589, 2592, 2595, 2590, 2802, 2593, 2597, 2802, 2802, 2594, 2598, 2591, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2596, 2802, 79, 80, 81, 2802, 79, 80, 81, 2592, 2802, 2802, 2599, 2593, 2597, 2600, 2602, 2594, 2598, 79, 80, 81, 2604, 2601, 2603, 2802, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2599, 2802, 2802, 2600, 2602, 79, 80, 81, 2605, 2802, 2604, 2601, 2603, 2802, 2802, 79, 80, 81, 2606, 2607, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2608, 2609, 79, 80, 81, 79, 80, 81, 2802, 2605, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2606, 2607, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2608, 2609, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2610, 79, 80, 81, 2611, 2612, 2637, 79, 80, 81, 79, 80, 81, 2613, 2616, 2802, 2615, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 2619, 2617, 2610, 79, 80, 81, 2611, 2612, 2618, 2620, 79, 80, 81, 2802, 2802, 2613, 2616, 2621, 2615, 2802, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2619, 2617, 79, 80, 81, 79, 80, 81, 2618, 2620, 79, 80, 81, 79, 80, 81, 2622, 2621, 79, 80, 81, 2623, 79, 80, 81, 2624, 2625, 79, 80, 81, 2802, 2629, 2627, 79, 80, 81, 79, 80, 81, 2802, 2630, 2802, 79, 80, 81, 2802, 2622, 2626, 2628, 2802, 2802, 2623, 79, 80, 81, 2624, 2625, 2802, 2631, 2802, 2802, 2629, 2627, 2802, 79, 80, 81, 79, 80, 81, 2630, 79, 80, 81, 79, 80, 81, 2626, 2628, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2631, 79, 80, 81, 2632, 79, 80, 81, 2633, 2634, 2635, 2644, 2636, 79, 80, 81, 2638, 79, 80, 81, 79, 80, 81, 2639, 2640, 79, 80, 81, 79, 80, 81, 2802, 2802, 2642, 2632, 2802, 2802, 2641, 2633, 2634, 2635, 2802, 2636, 79, 80, 81, 2638, 79, 80, 81, 79, 80, 81, 2639, 2640, 79, 80, 81, 79, 80, 81, 2643, 2645, 2642, 79, 80, 81, 2641, 79, 80, 81, 2646, 79, 80, 81, 79, 80, 81, 2682, 2802, 79, 80, 81, 2647, 2802, 2802, 79, 80, 81, 2648, 2649, 2643, 2645, 2650, 2651, 79, 80, 81, 79, 80, 81, 2646, 2652, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2647, 79, 80, 81, 2653, 2655, 2648, 2649, 2802, 2802, 2650, 2651, 79, 80, 81, 79, 80, 81, 2654, 2652, 79, 80, 81, 2802, 2802, 2656, 2658, 79, 80, 81, 79, 80, 81, 2657, 2653, 2655, 2659, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 2654, 79, 80, 81, 79, 80, 81, 2656, 2658, 2802, 2660, 2663, 79, 80, 81, 2657, 2802, 2661, 2659, 2662, 2665, 79, 80, 81, 2802, 2664, 79, 80, 81, 79, 80, 81, 2802, 2802, 79, 80, 81, 79, 80, 81, 2660, 2663, 2802, 2802, 79, 80, 81, 2661, 2666, 2662, 2665, 2668, 79, 80, 81, 2664, 2667, 2669, 79, 80, 81, 79, 80, 81, 2671, 79, 80, 81, 79, 80, 81, 2670, 79, 80, 81, 2672, 2802, 2802, 2666, 2681, 2680, 2668, 2673, 2802, 2802, 2674, 2667, 2669, 79, 80, 81, 79, 80, 81, 2671, 2802, 79, 80, 81, 2802, 2677, 2670, 79, 80, 81, 2672, 79, 80, 81, 2681, 2680, 2802, 2673, 2802, 2675, 2674, 2678, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2676, 79, 80, 81, 2677, 79, 80, 81, 2679, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2675, 2802, 2678, 2802, 2683, 2684, 2686, 2687, 2688, 79, 80, 81, 2676, 79, 80, 81, 2685, 2689, 2802, 2802, 2679, 79, 80, 81, 2690, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2683, 2684, 2686, 2687, 2688, 79, 80, 81, 79, 80, 81, 2802, 2685, 2689, 2802, 79, 80, 81, 2691, 2694, 2690, 2692, 2695, 2697, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2693, 2696, 2802, 2691, 2694, 2802, 2692, 2695, 2697, 2699, 2700, 2698, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2802, 2702, 2802, 79, 80, 81, 2701, 2703, 2693, 2696, 79, 80, 81, 79, 80, 81, 2802, 2699, 2700, 2698, 2802, 79, 80, 81, 79, 80, 81, 2704, 79, 80, 81, 2702, 2705, 79, 80, 81, 2707, 2703, 79, 80, 81, 2802, 2802, 2706, 2708, 79, 80, 81, 2802, 2802, 79, 80, 81, 2709, 79, 80, 81, 2704, 2710, 2714, 2802, 2802, 2705, 2802, 2802, 2715, 2707, 2712, 2802, 2711, 79, 80, 81, 2706, 2708, 79, 80, 81, 79, 80, 81, 2713, 2802, 2709, 2802, 79, 80, 81, 2710, 2714, 2802, 2802, 79, 80, 81, 2715, 2802, 2712, 2802, 2711, 2802, 2802, 79, 80, 81, 2716, 79, 80, 81, 2802, 2802, 2713, 2717, 79, 80, 81, 2718, 2720, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2802, 2716, 2719, 2721, 79, 80, 81, 2802, 2717, 79, 80, 81, 2718, 2722, 2724, 79, 80, 81, 2725, 79, 80, 81, 2723, 79, 80, 81, 2726, 2802, 79, 80, 81, 2802, 2719, 2802, 2802, 79, 80, 81, 79, 80, 81, 2727, 2728, 2802, 2724, 79, 80, 81, 2725, 2731, 2733, 2729, 2723, 79, 80, 81, 2726, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2730, 2727, 2728, 2802, 2732, 2734, 79, 80, 81, 2731, 2733, 2729, 79, 80, 81, 2735, 2802, 79, 80, 81, 2736, 79, 80, 81, 79, 80, 81, 2802, 2741, 2737, 2730, 79, 80, 81, 2732, 2734, 79, 80, 81, 2802, 2802, 79, 80, 81, 2738, 2735, 79, 80, 81, 2802, 2736, 79, 80, 81, 2739, 2740, 79, 80, 81, 2737, 79, 80, 81, 2742, 2743, 2744, 79, 80, 81, 79, 80, 81, 2802, 2802, 2738, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2739, 2740, 79, 80, 81, 2745, 79, 80, 81, 2742, 2743, 2744, 79, 80, 81, 2746, 2749, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2747, 79, 80, 81, 2748, 2802, 79, 80, 81, 2745, 79, 80, 81, 2802, 2802, 2750, 2802, 2751, 2802, 2746, 2749, 2753, 2755, 2802, 79, 80, 81, 2802, 2802, 2752, 2747, 79, 80, 81, 2748, 2802, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 2750, 2754, 2751, 79, 80, 81, 2753, 2755, 79, 80, 81, 79, 80, 81, 2752, 2756, 79, 80, 81, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2757, 2760, 2761, 2754, 2802, 79, 80, 81, 2759, 2758, 79, 80, 81, 2802, 79, 80, 81, 2756, 79, 80, 81, 79, 80, 81, 2802, 2802, 2762, 2769, 2802, 2802, 2757, 2763, 2761, 79, 80, 81, 2764, 2765, 2759, 2758, 2802, 79, 80, 81, 2802, 2766, 2767, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2762, 2769, 79, 80, 81, 2763, 2772, 79, 80, 81, 2764, 2765, 2768, 79, 80, 81, 79, 80, 81, 2766, 2767, 79, 80, 81, 2770, 2771, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2772, 2802, 79, 80, 81, 2773, 2768, 79, 80, 81, 2774, 79, 80, 81, 79, 80, 81, 2802, 2770, 2771, 2775, 2777, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2773, 2776, 79, 80, 81, 2774, 2778, 79, 80, 81, 2781, 2802, 79, 80, 81, 2775, 2777, 2779, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2780, 2782, 2802, 2776, 2802, 79, 80, 81, 2778, 2802, 2802, 2783, 2781, 79, 80, 81, 2784, 2802, 2802, 2779, 79, 80, 81, 2785, 2802, 79, 80, 81, 2786, 2802, 2780, 2802, 2787, 79, 80, 81, 2802, 2802, 79, 80, 81, 2783, 2788, 79, 80, 81, 2784, 79, 80, 81, 79, 80, 81, 2785, 79, 80, 81, 2802, 2786, 79, 80, 81, 2787, 2789, 2790, 79, 80, 81, 79, 80, 81, 2791, 2788, 2802, 2802, 79, 80, 81, 2792, 2802, 79, 80, 81, 79, 80, 81, 79, 80, 81, 2802, 2793, 2794, 2797, 2789, 2790, 79, 80, 81, 79, 80, 81, 2791, 2802, 79, 80, 81, 2802, 2802, 2792, 79, 80, 81, 2795, 2798, 2802, 2796, 2802, 79, 80, 81, 2793, 2794, 2799, 2800, 79, 80, 81, 79, 80, 81, 2802, 79, 80, 81, 2801, 79, 80, 81, 79, 80, 81, 2802, 2795, 2798, 2802, 2796, 79, 80, 81, 2802, 2802, 2802, 2799, 2800, 2802, 79, 80, 81, 79, 80, 81, 2802, 2802, 2802, 2801, 2802, 79, 80, 81, 2802, 2802, 79, 80, 81, 2802, 79, 80, 81, 79, 80, 81, 69, 69, 69, 69, 69, 69, 73, 73, 73, 73, 73, 73, 77, 2802, 77, 77, 77, 77, 78, 2802, 2802, 78, 83, 83, 83, 83, 83, 83, 249, 2802, 249, 2802, 249, 249, 257, 257, 257, 257, 257, 257, 77, 2802, 77, 77, 77, 77, 83, 83, 83, 83, 83, 83, 263, 263, 263, 263, 263, 263, 256, 2802, 256, 256, 256, 256, 262, 2802, 262, 262, 262, 262, 583, 2802, 583, 583, 583, 583, 957, 2802, 957, 957, 957, 957, 959, 2802, 959, 959, 959, 959, 1309, 1309, 7, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802 } ; static yyconst flex_int16_t yy_chk[15745] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 17, 12, 14, 14, 14, 23, 23, 17, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 26, 249, 26, 26, 26, 26, 26, 27, 98, 27, 27, 27, 27, 27, 26, 30, 30, 26, 32, 32, 66, 66, 68, 68, 27, 87, 73, 76, 73, 76, 79, 79, 40, 85, 12, 17, 26, 34, 34, 40, 34, 34, 1626, 41, 58, 40, 34, 41, 34, 81, 81, 41, 50, 34, 34, 34, 34, 41, 78, 78, 78, 43, 40, 93, 93, 112, 112, 34, 34, 40, 34, 34, 1626, 41, 58, 40, 34, 41, 34, 73, 76, 41, 50, 34, 34, 34, 34, 41, 40, 40, 40, 43, 50, 50, 50, 34, 34, 34, 35, 80, 58, 58, 58, 41, 41, 41, 118, 43, 43, 43, 252, 252, 83, 44, 262, 55, 75, 44, 35, 83, 253, 253, 35, 55, 260, 260, 35, 59, 1717, 35, 71, 256, 35, 1902, 86, 70, 118, 35, 109, 109, 109, 86, 35, 44, 257, 55, 257, 44, 35, 118, 118, 118, 35, 55, 261, 261, 35, 59, 1717, 35, 262, 104, 35, 1902, 258, 83, 258, 35, 67, 44, 44, 44, 35, 64, 57, 55, 55, 55, 35, 35, 35, 36, 256, 59, 59, 59, 57, 86, 36, 36, 62, 104, 36, 125, 57, 36, 36, 257, 36, 270, 270, 36, 104, 104, 104, 33, 57, 259, 57, 259, 28, 36, 88, 88, 88, 88, 88, 258, 36, 36, 291, 25, 36, 125, 57, 36, 36, 16, 36, 291, 291, 36, 11, 125, 125, 125, 57, 7, 57, 579, 581, 36, 36, 36, 37, 6, 106, 5, 37, 45, 4, 106, 37, 45, 57, 57, 57, 45, 37, 106, 259, 37, 582, 45, 37, 580, 116, 89, 37, 89, 89, 89, 89, 89, 37, 959, 106, 63, 37, 45, 957, 106, 37, 45, 89, 63, 581, 45, 37, 106, 579, 37, 958, 45, 37, 3, 116, 63, 37, 63, 106, 106, 106, 0, 37, 37, 37, 38, 582, 45, 45, 45, 116, 116, 116, 63, 580, 0, 38, 263, 38, 959, 1903, 38, 38, 38, 263, 63, 38, 63, 38, 957, 0, 94, 960, 94, 0, 38, 94, 94, 94, 94, 94, 958, 0, 63, 63, 63, 38, 126, 38, 0, 1903, 38, 38, 38, 0, 0, 38, 126, 38, 90, 90, 90, 90, 90, 264, 38, 38, 38, 39, 102, 263, 264, 39, 0, 90, 0, 39, 126, 960, 39, 2116, 2117, 39, 103, 105, 39, 102, 126, 39, 108, 105, 108, 39, 92, 92, 92, 92, 92, 39, 102, 0, 0, 39, 126, 126, 126, 39, 139, 92, 39, 2116, 2117, 39, 103, 105, 39, 102, 264, 39, 108, 105, 108, 39, 42, 0, 42, 42, 102, 102, 102, 110, 122, 42, 42, 42, 42, 113, 139, 42, 42, 103, 103, 103, 0, 105, 105, 105, 108, 108, 108, 139, 139, 139, 42, 111, 42, 42, 158, 158, 158, 110, 122, 42, 42, 42, 42, 113, 265, 42, 42, 0, 110, 110, 110, 265, 2274, 122, 122, 122, 0, 42, 42, 42, 46, 111, 51, 1310, 46, 2381, 51, 0, 46, 2399, 51, 113, 113, 113, 46, 2478, 51, 46, 1310, 2558, 46, 51, 2274, 0, 46, 111, 111, 111, 0, 0, 46, 119, 51, 1310, 46, 2381, 51, 265, 46, 2399, 51, 162, 162, 162, 46, 2478, 51, 46, 1310, 2558, 46, 51, 0, 0, 46, 47, 0, 47, 47, 47, 0, 119, 51, 51, 51, 0, 117, 0, 0, 47, 0, 117, 119, 119, 119, 47, 47, 0, 144, 95, 95, 95, 95, 95, 0, 47, 0, 47, 47, 47, 95, 95, 95, 95, 95, 95, 117, 0, 0, 47, 0, 117, 131, 0, 128, 47, 47, 107, 144, 128, 107, 0, 117, 117, 117, 47, 47, 47, 48, 144, 144, 144, 114, 114, 48, 0, 48, 0, 48, 0, 48, 107, 131, 48, 128, 48, 114, 107, 0, 128, 107, 0, 131, 131, 131, 128, 128, 128, 48, 0, 0, 132, 114, 114, 48, 0, 48, 0, 48, 0, 48, 107, 0, 48, 198, 48, 114, 107, 107, 107, 135, 0, 123, 48, 48, 48, 49, 114, 114, 114, 123, 132, 0, 49, 0, 121, 123, 49, 115, 121, 49, 0, 141, 49, 198, 115, 49, 132, 132, 132, 135, 115, 123, 225, 225, 225, 49, 198, 198, 198, 123, 134, 0, 49, 0, 121, 123, 49, 115, 121, 49, 0, 141, 49, 0, 115, 49, 0, 135, 135, 135, 115, 123, 123, 123, 0, 49, 49, 49, 52, 0, 134, 115, 115, 115, 121, 121, 121, 141, 141, 141, 52, 52, 52, 52, 52, 0, 0, 134, 134, 134, 140, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 0, 0, 52, 140, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 120, 140, 140, 140, 52, 52, 52, 53, 0, 120, 0, 53, 0, 0, 53, 53, 120, 120, 243, 0, 127, 53, 0, 138, 53, 0, 53, 244, 244, 244, 120, 53, 251, 251, 251, 0, 127, 53, 0, 120, 0, 53, 0, 0, 53, 53, 120, 120, 0, 0, 127, 53, 136, 138, 53, 0, 53, 0, 120, 120, 120, 53, 54, 138, 138, 138, 127, 130, 130, 0, 54, 130, 54, 133, 54, 0, 0, 54, 54, 127, 127, 127, 136, 0, 0, 133, 0, 0, 133, 243, 243, 243, 54, 0, 136, 136, 136, 130, 130, 0, 54, 130, 54, 133, 54, 0, 0, 54, 54, 0, 130, 130, 130, 167, 0, 133, 0, 146, 133, 54, 54, 54, 56, 146, 0, 0, 56, 0, 0, 56, 56, 143, 0, 133, 133, 133, 56, 0, 143, 56, 143, 56, 0, 167, 155, 0, 149, 146, 149, 167, 167, 167, 56, 146, 0, 0, 56, 0, 0, 56, 56, 143, 0, 146, 146, 146, 56, 0, 143, 56, 143, 56, 124, 0, 155, 124, 149, 0, 149, 159, 143, 143, 143, 124, 124, 124, 147, 157, 137, 147, 137, 137, 124, 0, 137, 149, 149, 149, 155, 155, 155, 0, 124, 0, 0, 124, 180, 0, 137, 159, 0, 148, 0, 124, 124, 124, 147, 157, 137, 147, 137, 137, 124, 0, 137, 148, 159, 159, 159, 147, 147, 147, 124, 124, 124, 129, 180, 129, 137, 0, 129, 148, 0, 157, 157, 157, 129, 142, 137, 137, 137, 142, 0, 129, 129, 148, 0, 145, 142, 180, 180, 180, 142, 145, 0, 129, 0, 129, 0, 145, 129, 148, 148, 148, 0, 0, 129, 142, 0, 0, 150, 142, 0, 129, 129, 150, 151, 145, 142, 154, 160, 163, 142, 145, 0, 129, 129, 129, 0, 145, 152, 154, 0, 142, 142, 142, 145, 145, 145, 0, 150, 0, 165, 0, 152, 150, 151, 153, 0, 154, 160, 163, 153, 166, 0, 153, 150, 150, 150, 0, 152, 154, 151, 151, 151, 160, 160, 160, 154, 154, 154, 156, 165, 156, 152, 0, 0, 153, 0, 163, 163, 163, 153, 166, 0, 153, 0, 188, 0, 164, 152, 152, 152, 164, 153, 153, 153, 0, 165, 165, 165, 156, 0, 156, 0, 166, 166, 166, 0, 168, 178, 0, 0, 156, 156, 156, 161, 188, 161, 164, 169, 161, 0, 164, 0, 169, 161, 161, 282, 282, 282, 161, 161, 187, 161, 164, 164, 164, 0, 168, 178, 0, 185, 188, 188, 188, 161, 0, 161, 0, 169, 161, 178, 178, 178, 169, 161, 161, 168, 168, 168, 161, 161, 187, 161, 170, 205, 169, 169, 169, 170, 179, 185, 161, 161, 161, 0, 0, 179, 171, 0, 171, 171, 170, 0, 0, 170, 171, 170, 0, 187, 187, 187, 173, 173, 170, 205, 0, 173, 0, 170, 179, 185, 185, 185, 205, 205, 205, 179, 171, 0, 171, 171, 170, 227, 0, 170, 171, 170, 179, 179, 179, 0, 173, 173, 170, 170, 170, 173, 171, 171, 171, 172, 0, 172, 173, 173, 173, 172, 0, 177, 174, 181, 0, 227, 172, 172, 175, 177, 0, 174, 175, 0, 0, 172, 174, 174, 176, 175, 227, 227, 227, 172, 0, 172, 0, 182, 176, 172, 0, 177, 174, 181, 0, 186, 172, 172, 175, 177, 0, 174, 175, 182, 182, 172, 174, 174, 176, 175, 177, 177, 177, 172, 172, 172, 195, 182, 176, 174, 174, 174, 181, 181, 181, 186, 175, 175, 175, 183, 184, 184, 190, 182, 182, 176, 176, 176, 189, 183, 194, 182, 182, 182, 0, 183, 195, 0, 183, 0, 186, 186, 186, 189, 183, 202, 195, 195, 195, 183, 184, 184, 190, 191, 285, 285, 285, 192, 189, 183, 194, 286, 286, 286, 0, 183, 0, 0, 183, 184, 184, 184, 200, 189, 0, 202, 183, 183, 183, 190, 190, 190, 0, 191, 189, 189, 189, 192, 0, 0, 194, 194, 194, 193, 191, 191, 191, 193, 0, 202, 202, 202, 200, 0, 192, 192, 192, 196, 193, 193, 196, 0, 204, 0, 197, 0, 196, 196, 197, 200, 200, 200, 0, 193, 197, 0, 0, 193, 199, 298, 298, 298, 199, 240, 203, 0, 199, 196, 193, 193, 196, 0, 204, 203, 197, 203, 196, 196, 197, 0, 215, 193, 193, 193, 197, 204, 204, 204, 199, 196, 196, 196, 199, 240, 203, 206, 199, 0, 210, 0, 197, 197, 197, 203, 0, 203, 240, 240, 240, 0, 215, 0, 0, 203, 203, 203, 211, 0, 199, 199, 199, 201, 201, 201, 201, 206, 201, 201, 210, 215, 215, 215, 201, 201, 201, 201, 201, 201, 212, 201, 201, 0, 201, 0, 0, 216, 211, 0, 206, 206, 206, 201, 201, 201, 201, 0, 201, 201, 210, 210, 210, 0, 201, 201, 201, 201, 201, 201, 212, 201, 201, 208, 201, 207, 207, 216, 211, 211, 211, 208, 0, 209, 207, 220, 207, 208, 207, 209, 207, 207, 207, 208, 233, 0, 216, 216, 216, 0, 212, 212, 212, 208, 0, 207, 207, 320, 320, 320, 0, 208, 0, 209, 207, 220, 207, 208, 207, 209, 207, 207, 207, 208, 233, 213, 214, 220, 220, 220, 214, 0, 0, 208, 208, 208, 213, 209, 209, 209, 0, 219, 0, 213, 0, 217, 0, 0, 217, 219, 218, 0, 233, 233, 233, 213, 214, 0, 0, 217, 214, 218, 217, 221, 218, 223, 213, 218, 0, 223, 229, 219, 0, 213, 235, 217, 0, 0, 217, 219, 218, 0, 0, 213, 213, 213, 214, 214, 214, 217, 246, 218, 217, 221, 218, 223, 0, 218, 228, 223, 229, 219, 219, 219, 235, 217, 217, 217, 222, 218, 218, 218, 0, 222, 224, 224, 229, 229, 229, 222, 246, 226, 221, 221, 221, 223, 223, 223, 228, 226, 235, 235, 235, 246, 246, 246, 239, 231, 222, 288, 231, 226, 232, 222, 224, 224, 232, 0, 0, 222, 232, 226, 0, 228, 228, 228, 222, 222, 222, 226, 0, 237, 224, 224, 224, 0, 239, 231, 248, 288, 231, 226, 232, 335, 335, 335, 232, 239, 239, 239, 232, 226, 226, 226, 230, 230, 288, 288, 288, 0, 230, 237, 230, 230, 231, 231, 231, 0, 248, 234, 230, 230, 232, 232, 232, 234, 238, 236, 0, 0, 238, 248, 248, 248, 230, 230, 236, 237, 237, 237, 230, 0, 230, 230, 271, 271, 271, 271, 271, 234, 230, 230, 396, 396, 396, 234, 238, 236, 245, 241, 238, 0, 230, 230, 230, 247, 236, 241, 234, 234, 234, 268, 268, 268, 268, 268, 439, 439, 439, 236, 236, 236, 238, 238, 238, 0, 268, 0, 245, 241, 242, 242, 242, 242, 242, 247, 0, 241, 275, 0, 0, 242, 242, 242, 242, 242, 242, 245, 245, 245, 255, 0, 0, 255, 272, 272, 272, 272, 272, 241, 241, 241, 440, 440, 440, 247, 247, 247, 275, 277, 267, 276, 267, 278, 255, 267, 267, 267, 267, 267, 255, 0, 269, 255, 269, 279, 0, 269, 269, 269, 269, 269, 283, 0, 275, 275, 275, 0, 0, 277, 0, 276, 280, 278, 255, 273, 273, 273, 273, 273, 255, 255, 255, 281, 284, 279, 273, 273, 273, 273, 273, 273, 283, 276, 276, 276, 277, 277, 277, 278, 278, 278, 280, 0, 0, 290, 287, 279, 279, 279, 295, 294, 0, 281, 284, 280, 280, 280, 283, 283, 283, 292, 293, 296, 0, 289, 444, 444, 444, 281, 281, 281, 289, 284, 284, 284, 287, 290, 290, 290, 295, 294, 0, 0, 300, 445, 445, 445, 295, 295, 295, 292, 293, 296, 301, 289, 297, 302, 287, 287, 287, 0, 289, 294, 294, 294, 303, 297, 293, 293, 293, 292, 292, 292, 300, 296, 296, 296, 289, 289, 289, 299, 299, 0, 301, 0, 297, 302, 0, 358, 304, 0, 0, 300, 300, 300, 303, 297, 305, 307, 504, 504, 504, 310, 306, 0, 306, 301, 301, 301, 0, 299, 299, 302, 302, 302, 297, 297, 297, 358, 304, 306, 303, 303, 303, 309, 0, 0, 305, 307, 358, 358, 358, 310, 306, 0, 306, 311, 0, 0, 299, 299, 299, 304, 304, 304, 313, 305, 305, 305, 0, 306, 312, 0, 0, 309, 310, 310, 310, 307, 307, 307, 306, 306, 306, 308, 317, 311, 315, 317, 308, 314, 0, 0, 308, 321, 313, 0, 0, 311, 311, 311, 312, 309, 309, 309, 0, 0, 313, 313, 313, 0, 0, 316, 0, 308, 317, 322, 315, 317, 308, 314, 316, 319, 308, 321, 0, 0, 312, 312, 312, 520, 520, 520, 317, 317, 317, 308, 308, 308, 314, 314, 314, 316, 315, 315, 315, 322, 327, 0, 346, 0, 316, 319, 326, 321, 321, 321, 0, 322, 322, 322, 316, 316, 316, 318, 318, 0, 373, 0, 319, 319, 319, 323, 328, 324, 318, 328, 327, 325, 346, 318, 318, 325, 318, 0, 326, 326, 326, 324, 324, 324, 346, 346, 346, 318, 318, 327, 327, 327, 373, 373, 373, 323, 328, 324, 318, 328, 329, 325, 0, 318, 318, 325, 318, 332, 329, 331, 330, 324, 324, 324, 330, 318, 318, 318, 328, 328, 328, 323, 323, 323, 324, 324, 324, 333, 0, 338, 329, 325, 325, 325, 0, 331, 0, 332, 329, 331, 330, 0, 0, 336, 330, 0, 337, 526, 526, 526, 0, 341, 339, 573, 573, 573, 334, 333, 334, 338, 329, 329, 329, 332, 332, 332, 334, 331, 331, 331, 330, 330, 330, 336, 0, 334, 337, 340, 338, 338, 338, 341, 339, 333, 333, 333, 334, 0, 334, 342, 343, 337, 337, 337, 344, 0, 334, 339, 339, 339, 345, 381, 336, 336, 336, 334, 347, 340, 349, 0, 0, 341, 341, 341, 0, 348, 334, 334, 334, 342, 343, 572, 351, 0, 344, 0, 340, 340, 340, 0, 345, 350, 0, 381, 381, 381, 347, 0, 349, 0, 0, 353, 342, 342, 342, 348, 343, 343, 343, 345, 345, 345, 351, 344, 344, 344, 359, 355, 347, 347, 347, 350, 352, 348, 348, 348, 352, 360, 349, 349, 349, 353, 354, 354, 574, 574, 574, 350, 350, 350, 0, 0, 351, 351, 351, 0, 359, 355, 572, 572, 572, 356, 352, 357, 361, 0, 352, 360, 362, 353, 353, 353, 354, 354, 356, 359, 359, 359, 363, 352, 352, 352, 0, 364, 354, 354, 354, 355, 355, 355, 0, 356, 0, 357, 361, 360, 360, 360, 362, 366, 367, 366, 368, 0, 356, 357, 357, 357, 363, 365, 362, 362, 362, 364, 0, 0, 369, 356, 356, 356, 361, 361, 361, 0, 370, 371, 578, 578, 578, 366, 367, 366, 368, 374, 363, 363, 363, 376, 372, 365, 377, 0, 375, 364, 364, 364, 369, 367, 367, 367, 378, 365, 365, 365, 370, 371, 0, 366, 366, 366, 368, 368, 368, 374, 369, 369, 369, 376, 372, 0, 377, 379, 375, 370, 370, 370, 382, 376, 376, 376, 378, 380, 0, 371, 371, 371, 372, 372, 372, 375, 375, 375, 374, 374, 374, 0, 0, 377, 377, 377, 0, 379, 383, 378, 378, 378, 382, 384, 385, 388, 0, 380, 386, 610, 610, 610, 387, 389, 0, 391, 613, 613, 613, 379, 379, 379, 380, 380, 380, 382, 382, 382, 383, 615, 615, 615, 0, 384, 385, 388, 0, 0, 386, 383, 383, 383, 387, 389, 390, 391, 384, 384, 384, 392, 397, 385, 385, 385, 386, 386, 386, 0, 387, 387, 387, 388, 388, 388, 395, 389, 389, 389, 393, 0, 409, 391, 391, 391, 390, 398, 399, 0, 394, 392, 397, 0, 0, 393, 400, 390, 390, 390, 394, 392, 392, 392, 403, 402, 395, 0, 0, 401, 393, 397, 397, 397, 409, 409, 409, 398, 399, 401, 394, 0, 395, 395, 395, 393, 400, 398, 398, 398, 394, 399, 399, 399, 403, 402, 393, 393, 393, 401, 404, 419, 407, 400, 400, 400, 394, 394, 394, 405, 406, 401, 401, 401, 402, 402, 402, 408, 403, 403, 403, 617, 617, 617, 410, 411, 0, 405, 412, 413, 404, 414, 407, 419, 419, 419, 619, 619, 619, 405, 406, 404, 404, 404, 407, 407, 407, 408, 620, 620, 620, 406, 406, 406, 410, 411, 0, 405, 412, 413, 0, 414, 417, 0, 418, 420, 405, 405, 405, 421, 413, 413, 413, 408, 408, 408, 0, 411, 411, 411, 410, 410, 410, 415, 412, 412, 412, 0, 414, 414, 414, 416, 417, 415, 418, 420, 426, 0, 422, 421, 631, 631, 631, 423, 416, 424, 420, 420, 420, 418, 418, 418, 425, 415, 0, 0, 417, 417, 417, 427, 0, 416, 0, 415, 0, 0, 426, 421, 421, 421, 422, 422, 422, 423, 416, 424, 0, 0, 426, 426, 426, 428, 425, 415, 415, 415, 416, 416, 416, 427, 429, 424, 424, 424, 0, 423, 423, 423, 429, 431, 0, 0, 427, 427, 427, 430, 425, 425, 425, 430, 0, 428, 0, 432, 433, 0, 0, 435, 437, 0, 429, 434, 0, 438, 428, 428, 428, 0, 0, 431, 429, 429, 429, 0, 436, 430, 0, 0, 442, 430, 431, 431, 431, 432, 433, 0, 436, 435, 437, 0, 0, 434, 0, 438, 432, 432, 432, 0, 0, 441, 443, 430, 430, 430, 436, 434, 434, 434, 442, 446, 433, 433, 433, 435, 435, 435, 436, 0, 437, 437, 437, 438, 438, 438, 447, 448, 436, 436, 436, 441, 443, 0, 451, 449, 442, 442, 442, 452, 453, 446, 441, 441, 441, 645, 645, 645, 0, 446, 446, 446, 450, 666, 666, 666, 447, 448, 443, 443, 443, 454, 455, 0, 0, 449, 451, 451, 451, 466, 453, 452, 452, 452, 457, 447, 447, 447, 449, 449, 449, 0, 450, 448, 448, 448, 458, 453, 453, 453, 0, 454, 455, 459, 450, 450, 450, 456, 456, 466, 669, 669, 669, 461, 457, 463, 670, 670, 670, 464, 466, 466, 466, 454, 454, 454, 458, 0, 455, 455, 455, 0, 460, 459, 674, 674, 674, 456, 456, 0, 457, 457, 457, 461, 462, 463, 458, 458, 458, 464, 460, 460, 467, 465, 0, 461, 461, 461, 0, 459, 459, 459, 460, 456, 456, 456, 464, 464, 464, 463, 463, 463, 507, 0, 462, 678, 678, 678, 472, 0, 460, 460, 467, 465, 468, 471, 462, 462, 462, 465, 465, 465, 460, 460, 460, 480, 470, 468, 469, 470, 468, 474, 507, 468, 467, 467, 467, 469, 472, 0, 507, 507, 507, 0, 468, 471, 680, 680, 680, 473, 475, 472, 472, 472, 0, 480, 470, 468, 469, 470, 468, 474, 0, 468, 0, 0, 478, 469, 477, 471, 471, 471, 468, 468, 468, 0, 469, 469, 469, 473, 475, 480, 480, 480, 470, 470, 470, 476, 510, 474, 474, 474, 473, 473, 473, 476, 478, 481, 477, 0, 484, 479, 0, 0, 475, 475, 475, 479, 477, 477, 477, 483, 478, 478, 478, 0, 0, 476, 510, 0, 485, 491, 482, 0, 0, 476, 482, 481, 0, 0, 484, 479, 0, 510, 510, 510, 482, 479, 0, 487, 490, 483, 0, 0, 476, 476, 476, 479, 479, 479, 485, 491, 482, 481, 481, 481, 482, 483, 483, 483, 484, 484, 484, 485, 485, 485, 482, 486, 492, 487, 490, 486, 489, 0, 491, 491, 491, 0, 486, 487, 487, 487, 482, 482, 482, 0, 490, 490, 490, 0, 488, 493, 512, 495, 488, 0, 496, 486, 492, 0, 488, 486, 489, 0, 0, 488, 488, 497, 486, 0, 501, 0, 489, 489, 489, 494, 0, 492, 492, 492, 488, 493, 512, 495, 488, 494, 496, 486, 486, 486, 488, 499, 493, 493, 493, 488, 488, 497, 498, 500, 501, 512, 512, 512, 498, 494, 488, 488, 488, 495, 495, 495, 496, 496, 496, 0, 0, 494, 494, 494, 502, 499, 503, 497, 497, 497, 505, 506, 498, 500, 501, 501, 501, 502, 498, 0, 0, 508, 509, 0, 0, 500, 500, 500, 498, 498, 498, 499, 499, 499, 502, 511, 503, 688, 688, 688, 505, 506, 513, 514, 693, 693, 693, 502, 503, 503, 503, 508, 509, 505, 505, 505, 502, 502, 502, 0, 515, 517, 508, 508, 508, 511, 506, 506, 506, 509, 509, 509, 513, 514, 511, 511, 511, 516, 518, 0, 0, 516, 522, 696, 696, 696, 0, 513, 513, 513, 515, 517, 0, 514, 514, 514, 705, 705, 705, 519, 0, 0, 517, 517, 517, 0, 0, 516, 518, 0, 0, 516, 522, 519, 0, 539, 521, 519, 521, 0, 515, 515, 515, 519, 516, 516, 516, 0, 0, 519, 0, 0, 523, 527, 523, 531, 518, 518, 518, 522, 522, 522, 524, 519, 530, 539, 521, 519, 521, 0, 524, 539, 539, 539, 0, 519, 519, 519, 532, 521, 521, 521, 523, 527, 523, 531, 0, 0, 525, 525, 528, 536, 524, 0, 530, 525, 529, 523, 523, 523, 524, 525, 534, 0, 525, 530, 530, 530, 532, 527, 527, 527, 531, 531, 531, 533, 0, 0, 525, 525, 528, 536, 524, 524, 524, 525, 529, 532, 532, 532, 0, 525, 534, 535, 525, 528, 528, 528, 536, 536, 536, 529, 529, 529, 0, 533, 525, 525, 525, 537, 534, 534, 534, 538, 540, 714, 714, 714, 541, 540, 533, 533, 533, 535, 541, 716, 716, 716, 0, 544, 543, 732, 732, 732, 535, 535, 535, 0, 0, 537, 737, 737, 737, 538, 540, 545, 542, 0, 541, 540, 546, 738, 738, 738, 541, 542, 537, 537, 537, 0, 543, 544, 544, 544, 0, 0, 540, 540, 540, 538, 538, 538, 541, 541, 541, 545, 542, 549, 0, 547, 546, 0, 0, 558, 550, 542, 543, 543, 543, 547, 553, 555, 545, 545, 545, 0, 546, 546, 546, 548, 0, 0, 542, 542, 542, 0, 0, 549, 551, 547, 548, 548, 552, 548, 550, 558, 558, 558, 0, 547, 553, 555, 0, 557, 549, 549, 549, 0, 0, 548, 550, 550, 550, 554, 0, 547, 547, 547, 551, 559, 548, 548, 552, 548, 556, 555, 555, 555, 0, 0, 553, 553, 553, 557, 0, 556, 561, 548, 548, 548, 551, 551, 551, 554, 552, 552, 552, 704, 0, 559, 557, 557, 557, 564, 556, 562, 554, 554, 554, 559, 559, 559, 563, 560, 560, 567, 561, 556, 556, 556, 560, 740, 740, 740, 561, 561, 561, 0, 565, 704, 704, 704, 565, 564, 566, 562, 560, 568, 0, 0, 560, 0, 563, 560, 560, 567, 562, 562, 562, 569, 560, 0, 0, 564, 564, 564, 570, 0, 565, 563, 563, 563, 565, 575, 566, 0, 560, 568, 567, 567, 567, 0, 560, 560, 560, 565, 565, 565, 0, 569, 576, 0, 0, 566, 566, 566, 570, 568, 568, 568, 0, 571, 0, 575, 569, 569, 569, 570, 570, 570, 571, 571, 571, 571, 571, 0, 575, 575, 575, 0, 576, 571, 571, 571, 571, 571, 571, 584, 584, 584, 584, 584, 588, 589, 590, 593, 576, 576, 576, 585, 585, 585, 585, 585, 586, 586, 586, 586, 586, 587, 587, 587, 587, 587, 591, 592, 597, 742, 742, 742, 0, 0, 588, 589, 590, 593, 745, 745, 745, 0, 594, 746, 746, 746, 588, 588, 588, 595, 0, 589, 589, 589, 600, 0, 591, 592, 597, 596, 598, 599, 0, 593, 593, 593, 590, 590, 590, 591, 591, 591, 594, 0, 592, 592, 592, 0, 600, 595, 597, 597, 597, 601, 600, 594, 594, 594, 604, 596, 598, 599, 595, 595, 595, 596, 596, 596, 0, 603, 605, 0, 598, 598, 598, 606, 607, 599, 599, 599, 600, 600, 600, 601, 608, 749, 749, 749, 604, 0, 609, 611, 612, 752, 752, 752, 601, 601, 601, 603, 605, 604, 604, 604, 614, 606, 607, 0, 0, 603, 603, 603, 0, 0, 608, 616, 618, 605, 605, 605, 609, 611, 612, 607, 607, 607, 623, 608, 608, 608, 0, 606, 606, 606, 614, 621, 609, 609, 609, 0, 622, 611, 611, 611, 626, 616, 618, 0, 612, 612, 612, 0, 0, 624, 0, 0, 623, 753, 753, 753, 614, 614, 614, 625, 627, 621, 0, 0, 629, 628, 622, 616, 616, 616, 626, 630, 618, 618, 618, 632, 623, 623, 623, 624, 621, 621, 621, 622, 622, 622, 0, 0, 637, 625, 627, 624, 624, 624, 629, 628, 626, 626, 626, 0, 633, 630, 627, 627, 627, 632, 757, 757, 757, 625, 625, 625, 628, 628, 628, 635, 638, 636, 637, 0, 629, 629, 629, 644, 0, 0, 635, 630, 630, 630, 633, 0, 635, 0, 634, 632, 632, 632, 634, 646, 637, 637, 637, 0, 0, 635, 638, 636, 633, 633, 633, 0, 639, 644, 641, 0, 635, 636, 636, 636, 0, 0, 635, 639, 634, 644, 644, 644, 634, 646, 0, 0, 638, 638, 638, 635, 635, 635, 642, 640, 0, 0, 639, 640, 641, 648, 643, 640, 647, 0, 634, 634, 634, 639, 651, 649, 640, 0, 0, 646, 646, 646, 0, 651, 639, 639, 639, 0, 642, 640, 641, 641, 641, 640, 0, 648, 643, 640, 647, 642, 642, 642, 653, 655, 651, 649, 640, 643, 643, 643, 650, 648, 648, 648, 650, 651, 651, 651, 658, 640, 640, 640, 0, 0, 647, 647, 647, 649, 649, 649, 654, 652, 653, 655, 0, 0, 652, 0, 660, 0, 650, 0, 652, 657, 650, 0, 0, 656, 658, 0, 0, 653, 653, 653, 658, 658, 658, 759, 759, 759, 654, 652, 718, 655, 655, 655, 652, 659, 660, 650, 650, 650, 652, 657, 661, 662, 663, 656, 654, 654, 654, 660, 660, 660, 652, 652, 652, 656, 656, 656, 657, 657, 657, 664, 718, 718, 718, 659, 665, 668, 686, 0, 0, 667, 661, 662, 663, 671, 659, 659, 659, 0, 0, 672, 772, 772, 772, 0, 662, 662, 662, 673, 0, 664, 661, 661, 661, 0, 665, 668, 686, 675, 0, 667, 663, 663, 663, 671, 676, 0, 686, 686, 686, 672, 677, 0, 679, 681, 668, 668, 668, 673, 664, 664, 664, 667, 667, 667, 665, 665, 665, 675, 671, 671, 671, 672, 672, 672, 676, 673, 673, 673, 682, 683, 677, 685, 679, 681, 689, 692, 684, 0, 0, 675, 675, 675, 0, 676, 676, 676, 677, 677, 677, 679, 679, 679, 681, 681, 681, 687, 690, 691, 682, 683, 0, 685, 0, 0, 689, 692, 684, 685, 685, 685, 694, 682, 682, 682, 683, 683, 683, 684, 684, 684, 695, 689, 689, 689, 697, 687, 690, 691, 0, 0, 698, 692, 692, 692, 701, 0, 687, 687, 687, 699, 694, 700, 706, 690, 690, 690, 702, 703, 0, 0, 695, 694, 694, 694, 697, 0, 708, 691, 691, 691, 698, 0, 0, 710, 701, 697, 697, 697, 0, 699, 0, 700, 706, 695, 695, 695, 702, 703, 707, 709, 699, 699, 699, 706, 706, 706, 708, 698, 698, 698, 701, 701, 701, 710, 700, 700, 700, 711, 702, 702, 702, 712, 713, 0, 703, 703, 703, 715, 707, 709, 720, 717, 708, 708, 708, 735, 783, 783, 783, 707, 707, 707, 0, 710, 710, 710, 0, 711, 785, 785, 785, 712, 713, 719, 709, 709, 709, 715, 711, 711, 711, 717, 720, 720, 720, 735, 712, 712, 712, 721, 722, 713, 713, 713, 715, 715, 715, 723, 717, 717, 717, 0, 0, 719, 0, 0, 724, 725, 726, 727, 0, 735, 735, 735, 0, 719, 719, 719, 0, 721, 722, 730, 787, 787, 787, 728, 0, 723, 0, 731, 721, 721, 721, 722, 722, 722, 724, 725, 726, 727, 723, 723, 723, 724, 724, 724, 729, 733, 734, 741, 729, 730, 727, 727, 727, 728, 725, 725, 725, 731, 726, 726, 726, 793, 793, 793, 728, 728, 728, 0, 736, 743, 731, 731, 731, 739, 729, 733, 734, 741, 729, 730, 730, 730, 744, 750, 0, 0, 747, 741, 741, 741, 748, 729, 729, 729, 0, 733, 733, 733, 736, 743, 0, 751, 0, 739, 0, 0, 734, 734, 734, 0, 0, 755, 744, 750, 0, 0, 747, 756, 0, 751, 748, 743, 743, 743, 750, 750, 750, 761, 736, 736, 736, 751, 739, 739, 739, 747, 747, 747, 744, 744, 744, 755, 754, 748, 748, 748, 758, 756, 762, 751, 754, 760, 0, 755, 755, 755, 0, 761, 767, 0, 0, 751, 751, 751, 758, 768, 800, 800, 800, 756, 756, 756, 754, 758, 764, 0, 758, 0, 762, 766, 754, 760, 0, 761, 761, 761, 0, 765, 767, 0, 0, 754, 754, 754, 758, 768, 760, 760, 760, 769, 0, 762, 762, 762, 764, 758, 758, 758, 763, 766, 776, 768, 768, 768, 764, 764, 764, 765, 767, 767, 767, 770, 763, 763, 763, 773, 763, 763, 771, 769, 765, 765, 765, 0, 0, 766, 766, 766, 763, 774, 776, 809, 809, 809, 775, 778, 0, 776, 776, 776, 0, 770, 763, 763, 763, 773, 763, 763, 771, 769, 769, 769, 770, 770, 770, 777, 763, 763, 763, 774, 799, 771, 771, 771, 775, 778, 779, 0, 789, 0, 773, 773, 773, 780, 814, 814, 814, 778, 778, 778, 781, 782, 774, 774, 774, 777, 775, 775, 775, 784, 786, 788, 799, 799, 799, 0, 779, 0, 789, 790, 825, 825, 825, 780, 777, 777, 777, 786, 0, 0, 781, 782, 779, 779, 779, 0, 780, 780, 780, 784, 786, 788, 0, 781, 781, 781, 789, 789, 789, 790, 782, 782, 782, 791, 788, 788, 788, 786, 794, 792, 794, 797, 0, 784, 784, 784, 795, 852, 852, 852, 786, 786, 786, 0, 796, 790, 790, 790, 867, 867, 867, 0, 798, 791, 0, 0, 801, 0, 794, 792, 794, 797, 802, 803, 0, 0, 795, 0, 791, 791, 791, 792, 792, 792, 796, 0, 794, 794, 794, 795, 795, 795, 798, 797, 797, 797, 801, 796, 796, 796, 0, 804, 802, 803, 805, 798, 798, 798, 807, 887, 887, 887, 806, 808, 801, 801, 801, 812, 811, 905, 905, 905, 0, 815, 813, 803, 803, 803, 802, 802, 802, 804, 0, 810, 805, 906, 906, 906, 807, 804, 804, 804, 806, 808, 912, 912, 912, 812, 811, 807, 807, 807, 0, 815, 813, 0, 816, 817, 0, 820, 805, 805, 805, 810, 806, 806, 806, 808, 808, 808, 811, 811, 811, 818, 810, 810, 810, 812, 812, 812, 813, 813, 813, 815, 815, 815, 816, 817, 819, 820, 822, 823, 821, 827, 824, 913, 913, 913, 0, 0, 820, 820, 820, 818, 824, 826, 0, 0, 816, 816, 816, 0, 0, 817, 817, 817, 0, 0, 819, 904, 822, 823, 821, 827, 824, 818, 818, 818, 821, 821, 821, 828, 827, 827, 827, 826, 824, 824, 824, 830, 822, 822, 822, 829, 819, 819, 819, 823, 823, 823, 833, 904, 904, 904, 828, 834, 0, 826, 826, 826, 0, 828, 0, 831, 837, 0, 853, 832, 835, 830, 932, 932, 932, 829, 0, 0, 836, 942, 942, 942, 833, 0, 830, 830, 830, 834, 828, 828, 828, 0, 829, 829, 829, 831, 837, 0, 853, 832, 835, 838, 831, 831, 831, 832, 832, 832, 836, 835, 835, 835, 833, 833, 833, 839, 841, 834, 834, 834, 837, 837, 837, 853, 853, 853, 836, 836, 836, 840, 842, 838, 843, 845, 0, 846, 845, 840, 943, 943, 943, 945, 945, 945, 0, 839, 841, 0, 848, 946, 946, 946, 844, 838, 838, 838, 950, 950, 950, 840, 842, 0, 843, 845, 0, 846, 845, 840, 841, 841, 841, 842, 842, 842, 847, 839, 839, 839, 848, 845, 845, 845, 844, 846, 846, 846, 843, 843, 843, 840, 840, 840, 844, 844, 844, 849, 850, 851, 848, 848, 848, 855, 854, 0, 847, 856, 954, 954, 954, 964, 964, 964, 0, 0, 856, 850, 0, 847, 847, 847, 0, 0, 857, 858, 859, 849, 850, 851, 968, 968, 968, 855, 854, 0, 0, 856, 849, 849, 849, 970, 970, 970, 860, 861, 856, 850, 855, 855, 855, 851, 851, 851, 857, 858, 859, 850, 850, 850, 854, 854, 854, 862, 856, 856, 856, 955, 858, 858, 858, 857, 857, 857, 860, 861, 863, 864, 866, 865, 0, 868, 0, 869, 859, 859, 859, 869, 861, 861, 861, 0, 871, 862, 0, 0, 860, 860, 860, 955, 955, 955, 978, 978, 978, 0, 863, 864, 866, 865, 0, 868, 870, 869, 0, 0, 872, 869, 0, 866, 866, 866, 871, 862, 862, 862, 873, 874, 875, 864, 864, 864, 863, 863, 863, 865, 865, 865, 868, 868, 868, 876, 870, 869, 869, 869, 872, 0, 871, 871, 871, 877, 878, 983, 983, 983, 873, 874, 875, 882, 879, 870, 870, 870, 880, 872, 872, 872, 873, 873, 873, 876, 985, 985, 985, 0, 875, 875, 875, 0, 0, 877, 878, 874, 874, 874, 881, 0, 888, 882, 879, 986, 986, 986, 880, 884, 0, 0, 876, 876, 876, 880, 880, 880, 878, 878, 878, 0, 0, 877, 877, 877, 879, 879, 879, 885, 881, 886, 888, 882, 882, 882, 883, 883, 889, 884, 0, 881, 881, 881, 0, 892, 0, 0, 883, 891, 884, 884, 884, 883, 883, 890, 893, 0, 0, 885, 0, 886, 888, 888, 888, 0, 883, 883, 889, 885, 885, 885, 989, 989, 989, 892, 0, 0, 883, 891, 894, 895, 0, 883, 883, 890, 893, 886, 886, 886, 889, 889, 889, 0, 0, 883, 883, 883, 891, 891, 891, 896, 890, 890, 890, 892, 892, 892, 897, 898, 894, 895, 893, 893, 893, 0, 0, 899, 900, 903, 0, 0, 895, 895, 895, 901, 907, 996, 996, 996, 0, 896, 914, 1015, 1015, 1015, 0, 0, 897, 898, 894, 894, 894, 0, 896, 896, 896, 899, 900, 903, 0, 898, 898, 898, 902, 901, 907, 909, 0, 902, 0, 0, 914, 0, 897, 897, 897, 908, 907, 907, 907, 903, 903, 903, 908, 899, 899, 899, 900, 900, 900, 901, 901, 901, 902, 908, 911, 909, 910, 902, 914, 914, 914, 915, 0, 917, 0, 908, 0, 0, 902, 902, 902, 916, 908, 0, 909, 909, 909, 918, 1017, 1017, 1017, 0, 0, 908, 911, 0, 910, 1051, 1051, 1051, 919, 915, 921, 917, 908, 908, 908, 0, 910, 910, 910, 916, 919, 915, 915, 915, 920, 918, 911, 911, 911, 922, 925, 926, 916, 916, 916, 917, 917, 917, 919, 923, 921, 0, 0, 918, 918, 918, 0, 920, 0, 0, 919, 0, 924, 927, 920, 928, 921, 921, 921, 922, 925, 926, 0, 919, 919, 919, 930, 931, 937, 923, 929, 922, 922, 922, 0, 0, 925, 925, 925, 920, 920, 920, 924, 927, 933, 928, 923, 923, 923, 926, 926, 926, 924, 924, 924, 0, 930, 931, 937, 934, 929, 935, 0, 939, 928, 928, 928, 927, 927, 927, 994, 929, 929, 929, 933, 936, 940, 935, 947, 0, 937, 937, 937, 931, 931, 931, 930, 930, 930, 934, 0, 935, 938, 939, 0, 0, 941, 944, 0, 933, 933, 933, 994, 994, 994, 936, 940, 935, 947, 0, 0, 948, 951, 934, 934, 934, 0, 0, 935, 935, 935, 0, 938, 939, 939, 939, 941, 944, 940, 940, 940, 936, 936, 936, 947, 947, 947, 0, 941, 941, 941, 948, 951, 952, 0, 938, 938, 938, 0, 944, 944, 944, 0, 961, 0, 962, 956, 951, 951, 951, 1055, 1055, 1055, 1061, 1061, 1061, 0, 948, 948, 948, 949, 0, 0, 952, 0, 963, 949, 966, 949, 0, 949, 0, 0, 961, 965, 962, 956, 0, 0, 967, 0, 949, 0, 0, 949, 961, 961, 961, 0, 952, 952, 952, 962, 962, 962, 963, 949, 966, 949, 969, 949, 956, 956, 956, 965, 0, 963, 963, 963, 967, 971, 949, 972, 973, 949, 974, 965, 965, 965, 0, 0, 966, 966, 966, 975, 0, 949, 949, 949, 969, 976, 967, 967, 967, 969, 969, 969, 1063, 1063, 1063, 971, 0, 972, 973, 977, 974, 0, 0, 979, 980, 973, 973, 973, 982, 975, 972, 972, 972, 981, 984, 976, 0, 971, 971, 971, 0, 0, 974, 974, 974, 975, 975, 975, 987, 977, 976, 976, 976, 979, 980, 988, 990, 995, 982, 991, 0, 0, 999, 981, 984, 980, 980, 980, 0, 981, 981, 981, 0, 0, 1000, 977, 977, 977, 987, 979, 979, 979, 982, 982, 982, 988, 990, 995, 992, 991, 993, 0, 999, 0, 984, 984, 984, 997, 995, 995, 995, 988, 988, 988, 1000, 987, 987, 987, 998, 999, 999, 999, 990, 990, 990, 991, 991, 991, 992, 0, 993, 1000, 1000, 1000, 1001, 1002, 1005, 997, 0, 0, 992, 992, 992, 993, 993, 993, 0, 0, 998, 997, 997, 997, 1003, 0, 0, 1004, 1006, 1007, 1008, 998, 998, 998, 1009, 0, 1001, 1002, 1005, 1064, 1064, 1064, 1065, 1065, 1065, 1010, 0, 1001, 1001, 1001, 0, 1005, 1005, 1005, 1003, 0, 1011, 1004, 1006, 1007, 1008, 1012, 1013, 0, 1009, 1002, 1002, 1002, 0, 1006, 1006, 1006, 1008, 1008, 1008, 1010, 1014, 1009, 1009, 1009, 1003, 1003, 1003, 1004, 1004, 1004, 1011, 1007, 1007, 1007, 1066, 1012, 1013, 1011, 1011, 1011, 1016, 1010, 1010, 1010, 1018, 1019, 1020, 1022, 0, 0, 1014, 1021, 1012, 1012, 1012, 1067, 1067, 1067, 1013, 1013, 1013, 0, 0, 1014, 1014, 1014, 1066, 1066, 1066, 0, 1016, 0, 1023, 1026, 1018, 1019, 1020, 1022, 0, 0, 1024, 1021, 1028, 1029, 1030, 1018, 1018, 1018, 1025, 1020, 1020, 1020, 1019, 1019, 1019, 0, 1016, 1016, 1016, 1021, 1021, 1021, 1023, 1026, 0, 1027, 1025, 1022, 1022, 1022, 1024, 1031, 1028, 1029, 1030, 0, 0, 1032, 1025, 1026, 1026, 1026, 1033, 0, 1023, 1023, 1023, 0, 0, 1029, 1029, 1029, 1024, 1024, 1024, 1027, 1025, 0, 1028, 1028, 1028, 1031, 1035, 1036, 1030, 1030, 1030, 1032, 1025, 1025, 1025, 1034, 1033, 1038, 1031, 1031, 1031, 1027, 1027, 1027, 1037, 1040, 0, 1039, 1043, 0, 1032, 1032, 1032, 1068, 1068, 1068, 1035, 1036, 0, 1034, 0, 0, 1033, 1033, 1033, 1034, 0, 1038, 1041, 1042, 1070, 1070, 1070, 1044, 1037, 1040, 0, 1039, 1043, 1036, 1036, 1036, 1035, 1035, 1035, 1038, 1038, 1038, 1039, 1039, 1039, 1034, 1034, 1034, 1040, 1040, 1040, 0, 1041, 1042, 1037, 1037, 1037, 1044, 1043, 1043, 1043, 1045, 1046, 1049, 0, 1041, 1041, 1041, 1047, 1052, 1042, 1042, 1042, 1048, 1083, 1083, 1083, 0, 1050, 1044, 1044, 1044, 1091, 1091, 1091, 0, 0, 1053, 1092, 1092, 1092, 1045, 1046, 1049, 0, 0, 1054, 0, 1047, 1052, 1105, 1105, 1105, 1048, 0, 1049, 1049, 1049, 1050, 0, 0, 1052, 1052, 1052, 1046, 1046, 1046, 1053, 1056, 1045, 1045, 1045, 1057, 1047, 1047, 1047, 1054, 1058, 1060, 1048, 1048, 1048, 1062, 1059, 1050, 1050, 1050, 0, 1054, 1054, 1054, 0, 1069, 1053, 1053, 1053, 0, 1072, 1056, 1059, 0, 1071, 1057, 1075, 1073, 0, 0, 1058, 1060, 1056, 1056, 1056, 1062, 1059, 1057, 1057, 1057, 0, 0, 1058, 1058, 1058, 1069, 0, 1062, 1062, 1062, 1072, 0, 1059, 1074, 1071, 1076, 1075, 1073, 1077, 1060, 1060, 1060, 1079, 1059, 1059, 1059, 1071, 1071, 1071, 1069, 1069, 1069, 1075, 1075, 1075, 0, 1072, 1072, 1072, 1073, 1073, 1073, 0, 1074, 1082, 1076, 0, 0, 1077, 0, 0, 1080, 1079, 1081, 1074, 1074, 1074, 1107, 1107, 1107, 1077, 1077, 1077, 1078, 1076, 1076, 1076, 0, 1087, 1078, 1095, 1078, 1085, 1078, 1082, 1110, 1110, 1110, 1079, 1079, 1079, 1080, 1084, 1081, 1078, 1086, 1090, 1078, 1084, 1082, 1082, 1082, 1085, 1081, 1081, 1081, 0, 1078, 1087, 1078, 1095, 1078, 1085, 1078, 1088, 1080, 1080, 1080, 1089, 1087, 1087, 1087, 1084, 0, 1078, 1086, 1090, 1078, 1084, 1095, 1095, 1095, 0, 0, 1085, 1085, 1085, 1093, 1097, 0, 1084, 1084, 1084, 1094, 1088, 1112, 1112, 1112, 1089, 0, 0, 1086, 1086, 1086, 0, 0, 1090, 1090, 1090, 1096, 1098, 1099, 1101, 1102, 1119, 1119, 1119, 1093, 1097, 0, 1088, 1088, 1088, 1094, 1089, 1089, 1089, 1100, 0, 1093, 1093, 1093, 0, 0, 1094, 1094, 1094, 1103, 0, 1096, 1098, 1099, 1101, 1102, 1097, 1097, 1097, 1104, 1096, 1096, 1096, 1098, 1098, 1098, 1099, 1099, 1099, 1100, 1106, 0, 0, 1101, 1101, 1101, 1108, 1115, 1113, 1103, 1100, 1100, 1100, 1109, 1111, 1102, 1102, 1102, 0, 1104, 0, 0, 1114, 1117, 0, 0, 1103, 1103, 1103, 0, 1106, 1104, 1104, 1104, 0, 0, 1108, 1115, 1113, 1116, 1118, 0, 0, 1109, 1111, 1120, 1106, 1106, 1106, 1108, 1108, 1108, 1114, 1117, 1109, 1109, 1109, 1113, 1113, 1113, 1111, 1111, 1111, 1115, 1115, 1115, 1117, 1117, 1117, 1116, 1118, 1114, 1114, 1114, 1121, 1120, 1122, 1123, 1128, 1128, 1128, 0, 1129, 1118, 1118, 1118, 1116, 1116, 1116, 1125, 0, 1120, 1120, 1120, 0, 1124, 1126, 1127, 1124, 1135, 1135, 1135, 0, 0, 1121, 0, 1122, 1123, 0, 1132, 0, 0, 1129, 1130, 1121, 1121, 1121, 1131, 0, 1125, 0, 0, 1122, 1122, 1122, 1124, 1126, 1127, 1124, 1123, 1123, 1123, 1133, 1127, 1127, 1127, 1129, 1129, 1129, 1132, 1124, 1124, 1124, 1130, 1126, 1126, 1126, 1131, 0, 1125, 1125, 1125, 1134, 1138, 1141, 1130, 1130, 1130, 1131, 1131, 1131, 1140, 1133, 1142, 0, 1132, 1132, 1132, 1134, 1136, 1137, 1137, 1137, 1136, 1139, 1139, 1139, 1145, 1133, 1133, 1133, 1143, 1134, 1144, 1141, 1138, 1138, 1138, 1154, 1154, 1154, 1140, 0, 0, 1146, 1142, 1142, 1142, 1134, 1136, 0, 0, 1147, 1136, 1134, 1134, 1134, 1145, 1140, 1140, 1140, 1143, 1148, 1144, 1141, 1141, 1141, 0, 1136, 1136, 1136, 1143, 1143, 1143, 1146, 0, 1144, 1144, 1144, 1145, 1145, 1145, 1147, 1149, 1150, 1155, 1155, 1155, 1151, 1153, 0, 0, 1148, 1157, 1157, 1157, 1146, 1146, 1146, 1152, 1159, 1163, 1163, 1163, 1147, 1147, 1147, 0, 0, 1156, 1165, 1165, 1165, 1149, 1150, 1148, 1148, 1148, 1151, 1153, 1158, 1175, 1175, 1175, 1149, 1149, 1149, 0, 0, 1152, 0, 1160, 1159, 1159, 1159, 1161, 1153, 1153, 1153, 1156, 0, 1151, 1151, 1151, 1150, 1150, 1150, 1168, 0, 0, 1158, 1152, 1152, 1152, 1161, 1162, 0, 1164, 1156, 1156, 1156, 1160, 1166, 1167, 0, 1161, 0, 0, 1169, 0, 1158, 1158, 1158, 0, 1160, 1160, 1160, 1168, 1177, 1177, 1177, 1178, 1178, 1178, 1161, 1162, 0, 1164, 1170, 1168, 1168, 1168, 1166, 1167, 1171, 1161, 1161, 1161, 1169, 1172, 1176, 1162, 1162, 1162, 1164, 1164, 1164, 0, 1166, 1166, 1166, 1169, 1169, 1169, 1174, 1167, 1167, 1167, 1170, 0, 0, 1173, 1182, 0, 1171, 1179, 1179, 1179, 0, 1172, 1176, 1170, 1170, 1170, 0, 0, 1173, 1171, 1171, 1171, 1180, 1180, 1180, 0, 1174, 1181, 1183, 1184, 1172, 1172, 1172, 1173, 1182, 1181, 1185, 0, 1176, 1176, 1176, 1186, 1188, 0, 0, 1174, 1174, 1174, 1173, 1187, 1200, 1200, 1200, 1182, 1182, 1182, 0, 1181, 1183, 1184, 1173, 1173, 1173, 1189, 0, 1181, 1185, 1208, 1208, 1208, 0, 1186, 1188, 1181, 1181, 1181, 0, 0, 1190, 1187, 1189, 1184, 1184, 1184, 1183, 1183, 1183, 1188, 1188, 1188, 1213, 1213, 1213, 1189, 1191, 1185, 1185, 1185, 1186, 1186, 1186, 1192, 1195, 1194, 1193, 1187, 1187, 1187, 1190, 0, 0, 1197, 1189, 1189, 1189, 1225, 1225, 1225, 1198, 0, 1190, 1190, 1190, 0, 1191, 1196, 1201, 1231, 1231, 1231, 0, 1192, 1195, 1194, 1193, 1259, 1259, 1259, 1261, 1261, 1261, 1197, 1199, 0, 0, 1195, 1195, 1195, 1198, 1202, 1204, 1191, 1191, 1191, 1203, 1196, 1201, 1192, 1192, 1192, 1193, 1193, 1193, 1194, 1194, 1194, 1196, 1196, 1196, 1197, 1197, 1197, 1199, 1201, 1201, 1201, 1198, 1198, 1198, 1202, 1204, 1205, 1206, 0, 1203, 1199, 1199, 1199, 1207, 1209, 1226, 1219, 1202, 1202, 1202, 1210, 0, 1203, 1203, 1203, 0, 0, 1204, 1204, 1204, 1211, 1277, 1277, 1277, 0, 0, 1205, 1206, 1212, 1287, 1287, 1287, 1214, 1207, 1209, 0, 1219, 1226, 1226, 1226, 1210, 1215, 1216, 1218, 1206, 1206, 1206, 1219, 1219, 1219, 1211, 0, 1205, 1205, 1205, 1210, 1210, 1210, 1212, 1207, 1207, 1207, 1214, 1217, 1209, 1209, 1209, 1211, 1211, 1211, 1220, 1215, 1216, 1218, 1212, 1212, 1212, 1221, 1214, 1214, 1214, 1215, 1215, 1215, 1222, 1223, 1229, 1289, 1292, 1292, 1292, 0, 0, 1217, 1224, 1218, 1218, 1218, 0, 0, 1220, 1227, 1216, 1216, 1216, 0, 1228, 1221, 1295, 1295, 1295, 1220, 1220, 1220, 1222, 1223, 1229, 1289, 0, 0, 1217, 1217, 1217, 1230, 1224, 1289, 1289, 1289, 1223, 1223, 1223, 1227, 1232, 1222, 1222, 1222, 1228, 1221, 1221, 1221, 1224, 1224, 1224, 1229, 1229, 1229, 1233, 1227, 1227, 1227, 0, 0, 1234, 1230, 0, 1228, 1228, 1228, 1235, 0, 1236, 1237, 1232, 1297, 1297, 1297, 1238, 1239, 1242, 1307, 1307, 1307, 1308, 1308, 1308, 1240, 1233, 1241, 0, 1230, 1230, 1230, 1234, 0, 1232, 1232, 1232, 0, 1235, 0, 1236, 1237, 0, 1234, 1234, 1234, 1238, 1239, 1242, 1233, 1233, 1233, 1236, 1236, 1236, 1240, 1244, 1241, 0, 0, 1245, 1242, 1242, 1242, 1235, 1235, 1235, 1237, 1237, 1237, 1243, 1246, 1239, 1239, 1239, 1247, 1238, 1238, 1238, 1312, 1312, 1312, 1243, 1240, 1240, 1240, 1244, 1241, 1241, 1241, 1245, 1316, 1316, 1316, 0, 1249, 1327, 1327, 1327, 0, 1243, 1246, 1254, 1248, 1251, 1247, 1245, 1245, 1245, 0, 1250, 1252, 1243, 1248, 1253, 0, 1244, 1244, 1244, 1246, 1246, 1246, 1243, 1243, 1243, 1249, 0, 0, 1247, 1247, 1247, 1255, 1254, 1248, 1251, 0, 0, 1249, 1249, 1249, 1250, 1252, 0, 1248, 1253, 1256, 1257, 0, 0, 1250, 1250, 1250, 1258, 1260, 1262, 1248, 1248, 1248, 1251, 1251, 1251, 1255, 1254, 1254, 1254, 1252, 1252, 1252, 1253, 1253, 1253, 0, 1255, 1255, 1255, 1256, 1257, 1328, 1328, 1328, 1263, 1265, 1258, 1260, 1262, 1266, 1267, 1270, 1264, 1257, 1257, 1257, 1330, 1330, 1330, 1258, 1258, 1258, 1264, 1268, 1260, 1260, 1260, 1256, 1256, 1256, 0, 1262, 1262, 1262, 1263, 1265, 0, 0, 1269, 1266, 1267, 1270, 1264, 1271, 1272, 1263, 1263, 1263, 1265, 1265, 1265, 0, 1273, 1268, 1264, 1264, 1264, 1267, 1267, 1267, 1270, 1270, 1270, 1274, 1275, 1268, 1268, 1268, 1269, 1266, 1266, 1266, 0, 1271, 1272, 0, 0, 1276, 1278, 1269, 1269, 1269, 1273, 1280, 0, 1282, 0, 0, 1281, 1284, 1271, 1271, 1271, 1274, 1275, 0, 1279, 1331, 1331, 1331, 1272, 1272, 1272, 0, 1273, 1273, 1273, 1276, 1278, 1332, 1332, 1332, 0, 1280, 1283, 1282, 0, 0, 1281, 1284, 1275, 1275, 1275, 1274, 1274, 1274, 1279, 1282, 1282, 1282, 1285, 1280, 1280, 1280, 1278, 1278, 1278, 1276, 1276, 1276, 1281, 1281, 1281, 1286, 1283, 1279, 1279, 1279, 1284, 1284, 1284, 1288, 1290, 1296, 1339, 1339, 1339, 1360, 1360, 1360, 1285, 1293, 1299, 1291, 1294, 1298, 1283, 1283, 1283, 1380, 1380, 1380, 0, 1286, 0, 1302, 1388, 1388, 1388, 0, 0, 1288, 1290, 1296, 1286, 1286, 1286, 1285, 1285, 1285, 1300, 1293, 1299, 1291, 1294, 1298, 1296, 1296, 1296, 1301, 1338, 1303, 1290, 1290, 1290, 1302, 0, 1288, 1288, 1288, 1291, 1291, 1291, 1303, 1299, 1299, 1299, 1293, 1293, 1293, 1300, 1294, 1294, 1294, 1304, 1298, 1298, 1298, 1305, 1301, 1338, 1303, 1300, 1300, 1300, 1302, 1302, 1302, 1306, 0, 1338, 1338, 1338, 1303, 1311, 0, 1301, 1301, 1301, 1392, 1392, 1392, 1314, 0, 1304, 0, 0, 1309, 1305, 0, 1303, 1303, 1303, 1309, 1313, 1309, 1315, 1309, 1306, 1317, 0, 1304, 1304, 1304, 1311, 0, 0, 1319, 1309, 0, 1309, 1309, 1314, 0, 0, 1306, 1306, 1306, 1305, 1305, 1305, 1318, 1321, 1309, 1313, 1309, 1315, 1309, 1323, 1317, 1311, 1311, 1311, 0, 1314, 1314, 1314, 1319, 1309, 0, 1309, 1309, 1313, 1313, 1313, 1320, 0, 0, 1315, 1315, 1315, 1318, 1321, 1322, 0, 1317, 1317, 1317, 1323, 1324, 1325, 1334, 1318, 1318, 1318, 0, 0, 1319, 1319, 1319, 1323, 1323, 1323, 1326, 1329, 1320, 1354, 0, 1321, 1321, 1321, 0, 0, 1322, 1333, 1335, 1320, 1320, 1320, 1324, 1325, 1334, 1341, 0, 1322, 1322, 1322, 1336, 0, 1342, 1324, 1324, 1324, 1326, 1329, 1337, 1354, 1325, 1325, 1325, 0, 1326, 1326, 1326, 1333, 1335, 0, 1334, 1334, 1334, 1340, 1329, 1329, 1329, 1341, 1341, 1341, 1336, 0, 1342, 1343, 1333, 1333, 1333, 1343, 1337, 1354, 1354, 1354, 1335, 1335, 1335, 1345, 0, 1351, 0, 1337, 1337, 1337, 1346, 1340, 1344, 0, 0, 1336, 1336, 1336, 1342, 1342, 1342, 1343, 1344, 0, 0, 1343, 0, 1340, 1340, 1340, 1347, 0, 0, 1345, 1348, 1351, 1349, 1355, 1350, 0, 1346, 0, 1344, 0, 1345, 1345, 1345, 1343, 1343, 1343, 0, 1346, 1346, 1346, 1344, 1344, 1344, 1351, 1351, 1351, 1347, 1352, 1358, 0, 1348, 1353, 1349, 1355, 1350, 1356, 1377, 1347, 1347, 1347, 0, 1348, 1348, 1348, 1349, 1349, 1349, 1350, 1350, 1350, 1355, 1355, 1355, 1357, 1361, 1359, 0, 1352, 1358, 0, 1362, 1353, 1364, 0, 0, 1356, 1377, 0, 1352, 1352, 1352, 0, 1353, 1353, 1353, 1363, 1356, 1356, 1356, 1377, 1377, 1377, 0, 1357, 1361, 1359, 1365, 1358, 1358, 1358, 1362, 1366, 1364, 1357, 1357, 1357, 1359, 1359, 1359, 0, 0, 1362, 1362, 1362, 1367, 1368, 1369, 1363, 1363, 1363, 1361, 1361, 1361, 1372, 0, 1370, 1365, 0, 1364, 1364, 1364, 1366, 1393, 1393, 1393, 1396, 1396, 1396, 1365, 1365, 1365, 1373, 0, 0, 1367, 1368, 1369, 1374, 1371, 1376, 1366, 1366, 1366, 1372, 1375, 1370, 1369, 1369, 1369, 1371, 0, 0, 1367, 1367, 1367, 1370, 1370, 1370, 1398, 1398, 1398, 1373, 1368, 1368, 1368, 1378, 0, 1374, 1371, 1376, 0, 1372, 1372, 1372, 1375, 1379, 1381, 1382, 1383, 1371, 1376, 1376, 1376, 1400, 1400, 1400, 1374, 1374, 1374, 1373, 1373, 1373, 1405, 1405, 1405, 1378, 1371, 1371, 1371, 1384, 1375, 1375, 1375, 1385, 1387, 1379, 1381, 1382, 1383, 1386, 1395, 0, 1390, 1382, 1382, 1382, 0, 0, 1391, 0, 1389, 0, 1378, 1378, 1378, 1379, 1379, 1379, 1394, 1384, 1383, 1383, 1383, 1385, 1387, 1381, 1381, 1381, 0, 1386, 1395, 0, 1390, 0, 0, 1384, 1384, 1384, 1391, 1397, 1389, 1401, 1395, 1395, 1395, 0, 1403, 1399, 1394, 1385, 1385, 1385, 1387, 1387, 1387, 1402, 1386, 1386, 1386, 1389, 1389, 1389, 1390, 1390, 1390, 0, 1391, 1391, 1391, 1397, 1406, 1401, 1408, 0, 1394, 1394, 1394, 1399, 1403, 1403, 1403, 1413, 1413, 1413, 1404, 1402, 1407, 1414, 1414, 1414, 1419, 1419, 1419, 1401, 1401, 1401, 1397, 1397, 1397, 0, 1406, 1409, 1408, 1399, 1399, 1399, 1410, 1420, 0, 1426, 0, 1402, 1402, 1402, 1404, 1411, 1407, 1406, 1406, 1406, 1412, 1417, 1427, 1427, 1427, 1404, 1404, 1404, 1408, 1408, 1408, 1409, 0, 1407, 1407, 1407, 1410, 1420, 1409, 1409, 1409, 1426, 1426, 1426, 0, 1411, 0, 0, 1418, 0, 1412, 1417, 1410, 1410, 1410, 1420, 1420, 1420, 1411, 1411, 1411, 1415, 0, 1412, 1412, 1412, 1416, 1415, 1415, 1415, 1422, 1415, 1416, 1416, 1416, 1423, 1416, 1432, 1418, 1417, 1417, 1417, 1415, 1421, 1424, 1415, 0, 1416, 0, 0, 1416, 1418, 1418, 1418, 1429, 1429, 1429, 1415, 1415, 1415, 1422, 1415, 1416, 1416, 1416, 1423, 1416, 1425, 0, 1432, 1432, 1432, 1415, 1421, 1424, 1415, 1428, 1416, 1430, 1431, 1416, 0, 1422, 1422, 1422, 1433, 1421, 1421, 1421, 0, 0, 1423, 1423, 1423, 1434, 1435, 1436, 1425, 0, 1424, 1424, 1424, 1437, 1437, 1437, 0, 1428, 1438, 1430, 1431, 0, 1425, 1425, 1425, 1439, 1433, 1440, 0, 1428, 1428, 1428, 1441, 0, 1445, 1434, 1435, 1436, 1430, 1430, 1430, 0, 1431, 1431, 1431, 1433, 1433, 1433, 1438, 1435, 1435, 1435, 1442, 1442, 1442, 1439, 0, 1440, 1452, 1436, 1436, 1436, 1441, 1443, 1445, 1434, 1434, 1434, 1444, 1444, 1444, 1439, 1439, 1439, 1438, 1438, 1438, 1445, 1445, 1445, 1446, 1440, 1440, 1440, 1447, 1448, 1441, 1441, 1441, 1449, 1452, 1452, 1452, 1443, 1461, 1461, 1461, 0, 0, 1451, 1453, 1468, 1468, 1468, 1450, 1443, 1443, 1443, 1454, 0, 1446, 1481, 1481, 1481, 1447, 1448, 1489, 1489, 1489, 1449, 1455, 0, 0, 1446, 1446, 1446, 1449, 1449, 1449, 1451, 1453, 1448, 1448, 1448, 1450, 0, 0, 1456, 1454, 1457, 1447, 1447, 1447, 0, 1450, 1450, 1450, 1453, 1453, 1453, 1455, 1451, 1451, 1451, 1458, 1459, 0, 1462, 1455, 1455, 1455, 0, 0, 1463, 1454, 1454, 1454, 1456, 0, 1457, 1460, 0, 1456, 1456, 1456, 0, 0, 1460, 1464, 1513, 1513, 1513, 0, 0, 1458, 1459, 0, 1462, 1460, 0, 1465, 0, 0, 1463, 0, 1467, 1457, 1457, 1457, 0, 1460, 0, 1466, 1469, 1459, 1459, 1459, 1460, 1464, 1471, 1458, 1458, 1458, 1462, 1462, 1462, 1470, 1472, 1460, 1463, 1463, 1463, 1465, 1465, 1465, 1467, 0, 0, 1474, 1460, 1460, 1460, 1466, 1469, 1464, 1464, 1464, 0, 1473, 1471, 1466, 1466, 1466, 0, 1480, 0, 1470, 1472, 0, 0, 1475, 1467, 1467, 1467, 1476, 1469, 1469, 1469, 1474, 0, 1479, 1483, 1470, 1470, 1470, 1471, 1471, 1471, 1473, 1477, 1474, 1474, 1474, 1478, 1480, 0, 0, 1472, 1472, 1472, 1475, 0, 0, 1482, 1476, 0, 0, 1473, 1473, 1473, 1479, 1483, 1475, 1475, 1475, 1517, 1517, 1517, 1484, 1477, 1476, 1476, 1476, 1478, 1480, 1480, 1480, 1483, 1483, 1483, 1477, 1477, 1477, 1482, 1478, 1478, 1478, 1486, 1479, 1479, 1479, 1485, 1487, 1498, 0, 1482, 1482, 1482, 1484, 1518, 1518, 1518, 0, 1484, 1484, 1484, 1488, 0, 1490, 1485, 1491, 1519, 1519, 1519, 0, 0, 1496, 1486, 1521, 1521, 1521, 1485, 1487, 1498, 1530, 1530, 1530, 1532, 1532, 1532, 1492, 0, 1498, 1498, 1498, 1493, 1488, 1494, 1490, 1485, 1491, 1495, 1497, 1486, 1486, 1486, 1496, 0, 1487, 1487, 1487, 1485, 1485, 1485, 1488, 1488, 1488, 1490, 1490, 1490, 1492, 1500, 1491, 1491, 1491, 1493, 1499, 1494, 1496, 1496, 1496, 1495, 1497, 1492, 1492, 1492, 1503, 1493, 1493, 1493, 1501, 1502, 1505, 1504, 1494, 1494, 1494, 1495, 1495, 1495, 0, 1500, 1534, 1534, 1534, 0, 1499, 0, 1497, 1497, 1497, 0, 1499, 1499, 1499, 1506, 1503, 1507, 1508, 1509, 1501, 1502, 1505, 1504, 1510, 1511, 1516, 1500, 1500, 1500, 1501, 1501, 1501, 1502, 1502, 1502, 1504, 1504, 1504, 1505, 1505, 1505, 1503, 1503, 1503, 1506, 0, 1507, 1508, 1509, 1512, 1542, 1542, 1542, 1510, 1511, 1516, 0, 1506, 1506, 1506, 1508, 1508, 1508, 1510, 1510, 1510, 0, 1509, 1509, 1509, 1514, 1522, 1515, 1507, 1507, 1507, 0, 1520, 1523, 1512, 1515, 1516, 1516, 1516, 1511, 1511, 1511, 0, 0, 1524, 1525, 1550, 1550, 1550, 0, 0, 1512, 1512, 1512, 1526, 1514, 1522, 1515, 1551, 1551, 1551, 0, 1520, 1523, 1527, 1515, 1531, 1537, 0, 1528, 1529, 1514, 1514, 1514, 1524, 1525, 1515, 1515, 1515, 1520, 1520, 1520, 1533, 0, 1526, 0, 1522, 1522, 1522, 1523, 1523, 1523, 0, 0, 1527, 0, 1531, 1537, 0, 1528, 1529, 1525, 1525, 1525, 1524, 1524, 1524, 1535, 1531, 1531, 1531, 0, 1533, 1536, 1526, 1526, 1526, 1538, 1539, 1537, 1537, 1537, 1527, 1527, 1527, 1528, 1528, 1528, 1529, 1529, 1529, 1543, 1541, 1552, 1552, 1552, 0, 1535, 1540, 1544, 1533, 1533, 1533, 1536, 0, 1546, 1545, 1538, 0, 0, 1539, 1539, 1539, 1555, 1555, 1555, 1536, 1536, 1536, 1547, 0, 1543, 1541, 1535, 1535, 1535, 1538, 1538, 1538, 1544, 1540, 1540, 1540, 1541, 1541, 1541, 1545, 1546, 1546, 1546, 1544, 1544, 1544, 1543, 1543, 1543, 1548, 1549, 1561, 1547, 0, 1553, 1548, 1556, 1556, 1556, 0, 0, 1545, 1545, 1545, 1554, 1557, 1557, 1557, 0, 1547, 1547, 1547, 1558, 1558, 1558, 1559, 1560, 0, 0, 1548, 1549, 1561, 1567, 0, 1553, 1548, 0, 1565, 1549, 1549, 1549, 1562, 1563, 1564, 1554, 1571, 1571, 1571, 1548, 1548, 1548, 1553, 1553, 1553, 0, 1559, 1560, 1561, 1561, 1561, 1554, 1554, 1554, 0, 1567, 1567, 1567, 1565, 0, 0, 1568, 1562, 1563, 1564, 1559, 1559, 1559, 1566, 1560, 1560, 1560, 1569, 1562, 1562, 1562, 1573, 1566, 0, 0, 1563, 1563, 1563, 1565, 1565, 1565, 0, 0, 1564, 1564, 1564, 1568, 0, 0, 1570, 1572, 1572, 1572, 1566, 1574, 1581, 0, 1569, 1577, 0, 1575, 1578, 1566, 1573, 1573, 1573, 1576, 1576, 1576, 0, 1569, 1569, 1569, 1582, 0, 0, 1568, 1568, 1568, 1570, 0, 1566, 1566, 1566, 1574, 1581, 1579, 0, 1577, 0, 1575, 1578, 1580, 1583, 1585, 1587, 1570, 1570, 1570, 0, 1577, 1577, 1577, 1582, 0, 0, 1584, 1581, 1581, 1581, 1574, 1574, 1574, 1575, 1575, 1575, 1579, 1578, 1578, 1578, 0, 0, 1580, 1583, 1585, 1587, 0, 1579, 1579, 1579, 1582, 1582, 1582, 1580, 1580, 1580, 1584, 1586, 1589, 1585, 1585, 1585, 1588, 1590, 1591, 1592, 1593, 0, 1586, 1583, 1583, 1583, 1586, 1596, 0, 1587, 1587, 1587, 1608, 1608, 1608, 0, 1584, 1584, 1584, 0, 0, 1586, 1589, 1610, 1610, 1610, 1588, 1590, 1591, 1592, 1593, 1594, 1586, 1595, 1597, 0, 1586, 1596, 1590, 1590, 1590, 1593, 1593, 1593, 1598, 1592, 1592, 1592, 0, 1586, 1586, 1586, 1589, 1589, 1589, 1588, 1588, 1588, 1591, 1591, 1591, 1594, 1599, 1595, 1597, 1596, 1596, 1596, 1594, 1594, 1594, 1600, 1601, 0, 1598, 0, 1603, 1597, 1597, 1597, 1595, 1595, 1595, 1602, 1607, 1598, 1598, 1598, 0, 0, 1604, 0, 1599, 1612, 1612, 1612, 0, 1606, 1617, 1617, 1617, 1600, 1601, 1599, 1599, 1599, 1603, 1605, 1611, 1633, 1633, 1633, 1609, 1602, 1607, 0, 0, 1600, 1600, 1600, 1604, 1613, 1614, 0, 1601, 1601, 1601, 1606, 1618, 0, 1602, 1602, 1602, 1615, 1603, 1603, 1603, 1605, 1611, 1604, 1604, 1604, 1609, 1616, 1607, 1607, 1607, 1605, 1605, 1605, 0, 1613, 1614, 1606, 1606, 1606, 1619, 1620, 1618, 1609, 1609, 1609, 0, 1615, 1611, 1611, 1611, 1621, 1622, 0, 1614, 1614, 1614, 1616, 1615, 1615, 1615, 1613, 1613, 1613, 1623, 1624, 1632, 1634, 1634, 1634, 1619, 1620, 1618, 1618, 1618, 1616, 1616, 1616, 1637, 1637, 1637, 1621, 1622, 1619, 1619, 1619, 1625, 1627, 0, 0, 1620, 1620, 1620, 1628, 1623, 1624, 1632, 0, 0, 1629, 1630, 1625, 1627, 1631, 1625, 1627, 1622, 1622, 1622, 1621, 1621, 1621, 1623, 1623, 1623, 1635, 1625, 1627, 0, 1624, 1624, 1624, 0, 1628, 0, 1632, 1632, 1632, 0, 1629, 1630, 1625, 1627, 1631, 1625, 1627, 1636, 1640, 1641, 1628, 1628, 1628, 1629, 1629, 1629, 1635, 1630, 1630, 1630, 1638, 1642, 1645, 1631, 1631, 1631, 0, 1635, 1635, 1635, 1639, 1639, 1639, 1643, 1643, 1643, 0, 1636, 1640, 1641, 1644, 1644, 1644, 1646, 1647, 1647, 1647, 1648, 1648, 1648, 1638, 0, 1645, 1642, 1642, 1642, 1649, 1650, 1651, 0, 1636, 1636, 1636, 1652, 1640, 1640, 1640, 1641, 1641, 1641, 0, 0, 1638, 1638, 1638, 1646, 1646, 1646, 1654, 1645, 1645, 1645, 1653, 1653, 1653, 0, 1649, 1650, 1651, 1655, 1655, 1655, 1656, 1652, 1657, 1657, 1657, 1658, 1660, 0, 1650, 1650, 1650, 1661, 1649, 1649, 1649, 1662, 1654, 1659, 1659, 1659, 1663, 1651, 1651, 1651, 0, 0, 1664, 1652, 1652, 1652, 1656, 0, 1654, 1654, 1654, 1658, 1660, 0, 0, 1665, 1666, 1661, 0, 0, 1667, 1662, 0, 1656, 1656, 1656, 1663, 1669, 0, 1661, 1661, 1661, 1664, 0, 1660, 1660, 1660, 1658, 1658, 1658, 0, 0, 1663, 1663, 1663, 1665, 1666, 1662, 1662, 1662, 1667, 1668, 1668, 1668, 1664, 1664, 1664, 1669, 1670, 1671, 1671, 1671, 1667, 1667, 1667, 1672, 1672, 1672, 1666, 1666, 1666, 1665, 1665, 1665, 1673, 1674, 1675, 1675, 1675, 1676, 0, 0, 1677, 1669, 1669, 1669, 1678, 1681, 1670, 1679, 1680, 1687, 1687, 1687, 1688, 1688, 1688, 0, 1670, 1670, 1670, 1689, 1689, 1689, 1685, 1674, 1673, 1673, 1673, 1676, 0, 1682, 1677, 0, 0, 1684, 1678, 1681, 0, 1679, 1680, 0, 1674, 1674, 1674, 0, 1686, 1683, 0, 0, 1681, 1681, 1681, 0, 1685, 1676, 1676, 1676, 1677, 1677, 1677, 1682, 1678, 1678, 1678, 1684, 1679, 1679, 1679, 1680, 1680, 1680, 1691, 1693, 1682, 1682, 1682, 1683, 1686, 1686, 1686, 1684, 1684, 1684, 1685, 1685, 1685, 1683, 1683, 1683, 1690, 1690, 1690, 1692, 1694, 1695, 1696, 1696, 1696, 1697, 1697, 1697, 1691, 1698, 1699, 1693, 1693, 1693, 1701, 1701, 1701, 1703, 1703, 1703, 1704, 1704, 1704, 1702, 1705, 1705, 1705, 0, 1700, 1692, 1694, 1695, 1708, 0, 1691, 1691, 1691, 0, 0, 1698, 1699, 0, 1706, 1707, 1695, 1695, 1695, 1694, 1694, 1694, 1698, 1698, 1698, 1702, 1710, 1692, 1692, 1692, 1700, 1709, 1709, 1709, 1708, 1711, 1711, 1711, 1699, 1699, 1699, 1700, 1700, 1700, 1706, 1707, 1708, 1708, 1708, 1712, 1713, 1714, 1702, 1702, 1702, 1716, 1710, 0, 1715, 0, 1706, 1706, 1706, 1720, 1720, 1720, 1710, 1710, 1710, 0, 0, 1719, 1707, 1707, 1707, 0, 1718, 0, 0, 1712, 1713, 1714, 1721, 1721, 1721, 1716, 1722, 0, 1715, 0, 1724, 1713, 1713, 1713, 1715, 1715, 1715, 1729, 1714, 1714, 1714, 1719, 1725, 1716, 1716, 1716, 1718, 1712, 1712, 1712, 0, 1723, 1718, 1718, 1718, 1727, 1722, 1719, 1719, 1719, 1724, 1726, 1723, 1728, 1728, 1728, 1732, 1732, 1732, 1729, 1729, 1729, 1725, 0, 1730, 1731, 1737, 1733, 1722, 1722, 1722, 1723, 1734, 1734, 1734, 1727, 0, 0, 1724, 1724, 1724, 1726, 1723, 0, 1725, 1725, 1725, 1727, 1727, 1727, 1735, 1726, 1726, 1726, 1730, 1731, 1737, 1733, 1738, 1723, 1723, 1723, 1736, 1736, 1736, 1730, 1730, 1730, 1739, 1739, 1739, 1741, 1744, 1731, 1731, 1731, 1733, 1733, 1733, 1740, 1735, 1742, 1742, 1742, 1737, 1737, 1737, 1745, 1738, 1743, 1743, 1743, 1761, 1761, 1761, 0, 1735, 1735, 1735, 0, 0, 1741, 1744, 0, 1746, 1750, 1769, 1769, 1769, 1740, 1747, 0, 1759, 1749, 1738, 1738, 1738, 1745, 0, 0, 1740, 1740, 1740, 1741, 1741, 1741, 0, 0, 1745, 1745, 1745, 1744, 1744, 1744, 1746, 1750, 1751, 0, 0, 1752, 1747, 1754, 0, 1749, 1759, 1759, 1759, 0, 1750, 1750, 1750, 1753, 1746, 1746, 1746, 0, 1747, 1747, 1747, 1748, 1749, 1749, 1749, 0, 1748, 0, 1751, 0, 1748, 1752, 1758, 1754, 1748, 1756, 1755, 1748, 1760, 1748, 1751, 1751, 1751, 1753, 0, 0, 1754, 1754, 1754, 0, 0, 1748, 1757, 1773, 1773, 1773, 1748, 1752, 1752, 1752, 1748, 1763, 1758, 0, 1748, 1756, 1755, 1748, 1760, 1748, 0, 0, 1764, 1753, 1753, 1753, 1755, 1755, 1755, 1748, 1748, 1748, 1757, 1765, 1756, 1756, 1756, 1762, 1758, 1758, 1758, 1763, 1766, 1762, 0, 1766, 1760, 1760, 1760, 1757, 1757, 1757, 1764, 1763, 1763, 1763, 0, 0, 1767, 1768, 0, 0, 1774, 1765, 1764, 1764, 1764, 1762, 0, 0, 1770, 0, 1766, 1762, 1771, 1766, 1775, 1775, 1775, 0, 1765, 1765, 1765, 0, 1772, 1762, 1762, 1762, 1767, 1768, 0, 1776, 1774, 1780, 1766, 1766, 1766, 1777, 1779, 0, 1770, 1767, 1767, 1767, 1771, 0, 0, 1778, 1768, 1768, 1768, 1770, 1770, 1770, 1772, 1771, 1771, 1771, 1774, 1774, 1774, 1776, 1783, 1780, 1772, 1772, 1772, 1777, 1779, 1781, 1781, 1781, 1784, 0, 1776, 1776, 1776, 1778, 1786, 1777, 1777, 1777, 1780, 1780, 1780, 1782, 1782, 1782, 1778, 1778, 1778, 1787, 1783, 1790, 1779, 1779, 1779, 1791, 1783, 1783, 1783, 1793, 1784, 1785, 1785, 1785, 1795, 0, 1786, 1788, 1788, 1788, 1789, 1789, 1789, 1792, 1792, 1792, 1794, 1794, 1794, 1787, 1796, 1790, 1786, 1786, 1786, 1791, 1799, 1799, 1799, 1793, 1784, 1784, 1784, 0, 1795, 0, 1797, 1798, 1790, 1790, 1790, 1791, 1791, 1791, 1800, 1801, 1787, 1787, 1787, 0, 1796, 1802, 1802, 1802, 1804, 1793, 1793, 1793, 1795, 1795, 1795, 1805, 0, 1796, 1796, 1796, 1797, 1798, 1803, 1803, 1803, 1807, 1806, 1810, 1800, 1801, 1809, 0, 1808, 1798, 1798, 1798, 0, 1812, 1804, 1797, 1797, 1797, 1811, 1811, 1811, 1805, 0, 1800, 1800, 1800, 0, 1801, 1801, 1801, 0, 1807, 1806, 1810, 0, 0, 1809, 0, 1808, 1813, 1804, 1804, 1804, 1812, 1815, 0, 1805, 1805, 1805, 1806, 1806, 1806, 1809, 1809, 1809, 0, 1810, 1810, 1810, 1807, 1807, 1807, 1808, 1808, 1808, 1812, 1812, 1812, 0, 1813, 1814, 1814, 1814, 1817, 1815, 1816, 1816, 1816, 1818, 1819, 1819, 1819, 1824, 0, 1820, 1815, 1815, 1815, 1821, 1821, 1821, 1822, 1823, 1823, 1823, 1834, 1834, 1834, 1813, 1813, 1813, 0, 0, 1817, 1840, 1840, 1840, 1825, 1818, 1826, 1827, 0, 1824, 0, 1820, 1829, 1854, 1854, 1854, 0, 1828, 1822, 1817, 1817, 1817, 1820, 1820, 1820, 0, 0, 1824, 1824, 1824, 1830, 1818, 1818, 1818, 1825, 0, 1826, 1827, 1822, 1822, 1822, 0, 1829, 1831, 1832, 1835, 1833, 1828, 1829, 1829, 1829, 1825, 1825, 1825, 1827, 1827, 1827, 1836, 1837, 0, 1830, 0, 1826, 1826, 1826, 1828, 1828, 1828, 1841, 1830, 1830, 1830, 0, 1831, 1832, 1835, 1833, 0, 1838, 1832, 1832, 1832, 1839, 1843, 1842, 0, 0, 1836, 1837, 1831, 1831, 1831, 1833, 1833, 1833, 1857, 1857, 1857, 1841, 0, 0, 1835, 1835, 1835, 1844, 1837, 1837, 1837, 1838, 1836, 1836, 1836, 1839, 1843, 1842, 1845, 1846, 0, 0, 1838, 1838, 1838, 1847, 1839, 1839, 1839, 1841, 1841, 1841, 1842, 1842, 1842, 1848, 1850, 1844, 1849, 1858, 1858, 1858, 1843, 1843, 1843, 0, 0, 1851, 0, 1846, 1845, 1845, 1845, 1852, 0, 1847, 0, 0, 1853, 1844, 1844, 1844, 1861, 1861, 1861, 1848, 1850, 0, 1849, 1855, 1863, 1863, 1863, 0, 1846, 1846, 1846, 1851, 1847, 1847, 1847, 0, 0, 1852, 1856, 1850, 1850, 1850, 1853, 1859, 1860, 1862, 1864, 1848, 1848, 1848, 1849, 1849, 1849, 1855, 1853, 1853, 1853, 1851, 1851, 1851, 1865, 1852, 1852, 1852, 1855, 1855, 1855, 0, 1856, 1866, 1867, 1872, 0, 1859, 1860, 1862, 1864, 0, 0, 1868, 1856, 1856, 1856, 1874, 1874, 1874, 1869, 1862, 1862, 1862, 1865, 1860, 1860, 1860, 0, 1859, 1859, 1859, 0, 1866, 1867, 1872, 1870, 1871, 1873, 0, 1864, 1864, 1864, 1868, 1875, 0, 1876, 1865, 1865, 1865, 1869, 0, 0, 1872, 1872, 1872, 1868, 1868, 1868, 1881, 1867, 1867, 1867, 1866, 1866, 1866, 1870, 1871, 1873, 1869, 1869, 1869, 0, 1877, 1875, 1878, 1876, 1870, 1870, 1870, 1871, 1871, 1871, 1879, 0, 1875, 1875, 1875, 0, 1881, 1880, 1883, 1882, 0, 1885, 0, 1884, 1873, 1873, 1873, 1876, 1876, 1876, 1877, 0, 1878, 1881, 1881, 1881, 1887, 1887, 1887, 0, 1879, 1877, 1877, 1877, 1878, 1878, 1878, 1880, 1883, 1882, 1886, 1885, 1888, 1884, 1889, 1889, 1889, 1880, 1880, 1880, 1882, 1882, 1882, 1890, 0, 1895, 1879, 1879, 1879, 1884, 1884, 1884, 0, 0, 1883, 1883, 1883, 1885, 1885, 1885, 1886, 1893, 1888, 1891, 1891, 1891, 1892, 1892, 1892, 1894, 1896, 1896, 1896, 1890, 1897, 1895, 1900, 1898, 1899, 1899, 1899, 1888, 1888, 1888, 1904, 1886, 1886, 1886, 1895, 1895, 1895, 1893, 0, 0, 1901, 1906, 1906, 1906, 1905, 1894, 1890, 1890, 1890, 0, 1897, 0, 1900, 1898, 0, 1907, 1908, 0, 1910, 0, 1904, 0, 1909, 1893, 1893, 1893, 0, 1900, 1900, 1900, 1901, 1894, 1894, 1894, 1905, 0, 1897, 1897, 1897, 1898, 1898, 1898, 1901, 1901, 1901, 1907, 1908, 1911, 1910, 1904, 1904, 1904, 1909, 1905, 1905, 1905, 1913, 1915, 1923, 1912, 1919, 0, 1907, 1907, 1907, 1908, 1908, 1908, 1914, 1914, 1914, 1909, 1909, 1909, 1910, 1910, 1910, 1911, 1916, 1916, 1916, 1917, 1918, 1918, 1918, 1920, 1913, 1915, 1923, 1912, 1919, 1921, 1921, 1921, 1922, 1911, 1911, 1911, 1912, 1912, 1912, 1924, 1925, 1913, 1913, 1913, 1915, 1915, 1915, 1926, 0, 1917, 1919, 1919, 1919, 1920, 1929, 0, 1923, 1923, 1923, 1927, 0, 0, 1922, 1928, 1936, 0, 1917, 1917, 1917, 1924, 1925, 0, 1920, 1920, 1920, 0, 0, 1926, 0, 1922, 1922, 1922, 0, 1930, 1929, 0, 1925, 1925, 1925, 1927, 1931, 0, 1934, 1928, 1936, 0, 1924, 1924, 1924, 1937, 1929, 1929, 1929, 1926, 1926, 1926, 1927, 1927, 1927, 0, 1928, 1928, 1928, 1930, 1932, 1932, 1932, 1933, 1933, 1933, 1931, 1935, 1934, 1940, 1936, 1936, 1936, 0, 1943, 1937, 1930, 1930, 1930, 1934, 1934, 1934, 1941, 1931, 1931, 1931, 0, 1937, 1937, 1937, 1938, 1938, 1938, 1939, 1939, 1939, 1944, 1935, 1942, 1942, 1942, 1940, 1940, 1940, 1943, 1945, 1946, 1935, 1935, 1935, 1947, 1949, 1949, 1949, 1941, 1941, 1941, 1953, 1953, 1953, 1943, 1943, 1943, 0, 0, 1948, 1944, 1954, 1954, 1954, 1950, 1956, 1956, 1956, 1955, 1945, 1946, 1944, 1944, 1944, 1947, 1951, 1952, 1958, 1958, 1958, 1965, 1946, 1946, 1946, 0, 1957, 1945, 1945, 1945, 1948, 0, 1947, 1947, 1947, 1950, 1948, 1948, 1948, 1955, 0, 1959, 1960, 1962, 1962, 1962, 1951, 1952, 1964, 0, 1961, 1965, 0, 1952, 1952, 1952, 1957, 1963, 1963, 1963, 1950, 1950, 1950, 0, 0, 1955, 1955, 1955, 1951, 1951, 1951, 1959, 1960, 1957, 1957, 1957, 0, 0, 1964, 1968, 1961, 1965, 1965, 1965, 1967, 1967, 1967, 1969, 0, 0, 1960, 1960, 1960, 1959, 1959, 1959, 1961, 1961, 1961, 1970, 1972, 1973, 1977, 1979, 1979, 1979, 1964, 1964, 1964, 1968, 1971, 1975, 1982, 1982, 1982, 1974, 0, 1969, 0, 1978, 1985, 1985, 1985, 1980, 0, 0, 1968, 1968, 1968, 1970, 1972, 1973, 1977, 1969, 1969, 1969, 1976, 1986, 1986, 1986, 1971, 1975, 1970, 1970, 1970, 1974, 1972, 1972, 1972, 1978, 1971, 1971, 1971, 1980, 1977, 1977, 1977, 1973, 1973, 1973, 1981, 1974, 1974, 1974, 1988, 0, 1976, 1975, 1975, 1975, 1980, 1980, 1980, 1983, 0, 1978, 1978, 1978, 1976, 1976, 1976, 0, 2000, 1984, 1987, 1987, 1987, 1989, 1990, 0, 1981, 0, 0, 1991, 1988, 1995, 0, 0, 1990, 1997, 1997, 1997, 0, 1983, 1998, 1998, 1998, 1988, 1988, 1988, 1981, 1981, 1981, 1984, 2000, 2000, 2000, 1989, 1990, 1994, 1983, 1983, 1983, 1991, 1992, 1995, 0, 2002, 1990, 1996, 1984, 1984, 1984, 1989, 1989, 1989, 1993, 0, 1992, 1991, 1991, 1991, 2001, 0, 1990, 1990, 1990, 1999, 0, 1994, 1993, 1995, 1995, 1995, 1992, 0, 0, 2002, 0, 1996, 0, 1994, 1994, 1994, 0, 2003, 1993, 2008, 1992, 0, 0, 2005, 2001, 2002, 2002, 2002, 0, 1999, 0, 2004, 1993, 1996, 1996, 1996, 1992, 1992, 1992, 0, 1999, 1999, 1999, 2006, 1993, 1993, 1993, 2003, 2007, 2008, 2001, 2001, 2001, 2005, 2009, 2009, 2009, 2011, 2003, 2003, 2003, 2004, 2012, 2014, 2005, 2005, 2005, 2013, 2004, 2004, 2004, 0, 0, 2006, 0, 2008, 2008, 2008, 2007, 2010, 2010, 2010, 2015, 2015, 2015, 0, 2016, 2011, 2017, 2006, 2006, 2006, 2012, 2014, 2018, 2021, 0, 2013, 0, 0, 2007, 2007, 2007, 2013, 2013, 2013, 2014, 2014, 2014, 2012, 2012, 2012, 2024, 2011, 2011, 2011, 2016, 2019, 2017, 2020, 2020, 2020, 2025, 2027, 2018, 2021, 2022, 2022, 2022, 2016, 2016, 2016, 0, 2021, 2021, 2021, 2023, 2023, 2023, 2018, 2018, 2018, 2024, 2026, 2017, 2017, 2017, 2030, 2032, 2019, 2019, 2019, 2025, 2027, 2028, 2028, 2028, 2029, 2029, 2029, 2033, 2024, 2024, 2024, 2025, 2025, 2025, 2031, 2031, 2031, 2027, 2027, 2027, 2026, 2035, 2035, 2035, 2030, 2032, 2034, 2039, 2037, 2041, 2036, 2040, 0, 2026, 2026, 2026, 0, 2033, 2038, 2038, 2038, 2030, 2030, 2030, 2042, 2042, 2042, 2043, 2048, 2048, 2048, 2032, 2032, 2032, 0, 0, 2034, 2039, 2037, 2041, 2036, 2040, 2044, 2033, 2033, 2033, 2036, 2036, 2036, 2037, 2037, 2037, 2040, 2040, 2040, 0, 0, 2043, 2034, 2034, 2034, 2045, 2039, 2039, 2039, 2041, 2041, 2041, 0, 2046, 2047, 2049, 2044, 2050, 2050, 2050, 2051, 2051, 2051, 2052, 0, 2043, 2043, 2043, 0, 2044, 2044, 2044, 2054, 2054, 2054, 2045, 2057, 2057, 2057, 2053, 2045, 2045, 2045, 2046, 2047, 2049, 2055, 2056, 2059, 2060, 2064, 2064, 2064, 2052, 0, 0, 2058, 2049, 2049, 2049, 0, 0, 2046, 2046, 2046, 2062, 2047, 2047, 2047, 2053, 0, 0, 2061, 2063, 0, 0, 2055, 2056, 2059, 2060, 2053, 2053, 2053, 2052, 2052, 2052, 2058, 2065, 2065, 2065, 0, 2059, 2059, 2059, 0, 2062, 2066, 2066, 2066, 2056, 2056, 2056, 2061, 2063, 2068, 2070, 2055, 2055, 2055, 2060, 2060, 2060, 2058, 2058, 2058, 0, 2074, 2061, 2061, 2061, 2062, 2062, 2062, 2067, 2067, 2067, 2071, 2063, 2063, 2063, 2069, 2069, 2069, 2072, 2068, 2070, 2073, 2075, 2078, 2078, 2078, 0, 2081, 2077, 0, 2068, 2068, 2068, 2074, 2074, 2074, 2076, 2070, 2070, 2070, 2079, 2071, 2084, 2084, 2084, 2094, 2094, 2094, 2072, 0, 2082, 2073, 2075, 0, 2071, 2071, 2071, 0, 2077, 2081, 2081, 2081, 0, 0, 2087, 0, 2076, 0, 2083, 2085, 2079, 2095, 2095, 2095, 2072, 2072, 2072, 2073, 2073, 2073, 2082, 0, 2075, 2075, 2075, 2076, 2076, 2076, 2077, 2077, 2077, 2082, 2082, 2082, 2087, 0, 2086, 2080, 2083, 2085, 2079, 2079, 2079, 2080, 2088, 2080, 2089, 2080, 2090, 0, 2093, 2091, 2087, 2087, 2087, 2096, 2096, 2096, 2080, 2092, 0, 2080, 2083, 2083, 2083, 0, 2086, 2085, 2085, 2085, 0, 0, 2097, 2080, 2088, 2080, 2089, 2080, 2090, 0, 2093, 2091, 2089, 2089, 2089, 2098, 2098, 2098, 2080, 2092, 2100, 2080, 2086, 2086, 2086, 2093, 2093, 2093, 2101, 2088, 2088, 2088, 2097, 0, 2090, 2090, 2090, 2091, 2091, 2091, 2103, 2092, 2092, 2092, 2099, 2099, 2099, 2102, 2104, 2106, 2100, 2105, 2105, 2105, 2097, 2097, 2097, 0, 2101, 2108, 2108, 2108, 0, 2100, 2100, 2100, 2107, 2109, 2109, 2109, 2103, 2111, 2113, 2113, 2113, 0, 0, 2102, 2104, 2106, 2110, 0, 2101, 2101, 2101, 2114, 2114, 2114, 2102, 2102, 2102, 2104, 2104, 2104, 0, 2112, 2107, 2103, 2103, 2103, 2118, 2111, 2119, 2120, 2106, 2106, 2106, 2111, 2111, 2111, 2110, 2115, 2115, 2115, 0, 2107, 2107, 2107, 2121, 2121, 2121, 0, 2110, 2110, 2110, 2112, 2123, 2123, 2123, 2122, 2118, 2126, 2119, 2120, 2124, 2124, 2124, 2112, 2112, 2112, 2125, 2151, 2128, 2127, 2120, 2120, 2120, 2131, 2131, 2131, 0, 2119, 2119, 2119, 2129, 0, 2118, 2118, 2118, 2122, 0, 2126, 2130, 2132, 2133, 2133, 2133, 2137, 2137, 2137, 2125, 2151, 2128, 2127, 0, 2135, 2136, 2144, 2144, 2144, 0, 2151, 2151, 2151, 2129, 2122, 2122, 2122, 2126, 2126, 2126, 2134, 2130, 2132, 2152, 2138, 2125, 2125, 2125, 2127, 2127, 2127, 2128, 2128, 2128, 2135, 2136, 2139, 2129, 2129, 2129, 2132, 2132, 2132, 0, 2140, 2141, 2136, 2136, 2136, 0, 2134, 2130, 2130, 2130, 2138, 2152, 2152, 2152, 2142, 2143, 2145, 2135, 2135, 2135, 2146, 0, 2139, 2134, 2134, 2134, 0, 2138, 2138, 2138, 2140, 2141, 2148, 2139, 2139, 2139, 2147, 2149, 2155, 2155, 2155, 2140, 2140, 2140, 2142, 2143, 2145, 2141, 2141, 2141, 2146, 2150, 2153, 0, 2160, 2154, 2142, 2142, 2142, 2156, 2156, 2156, 2148, 2143, 2143, 2143, 2147, 2149, 2145, 2145, 2145, 0, 2146, 2146, 2146, 2157, 2157, 2157, 2147, 2147, 2147, 2150, 2153, 2158, 2160, 2154, 2161, 2162, 2148, 2148, 2148, 2159, 2159, 2159, 2149, 2149, 2149, 2154, 2154, 2154, 0, 2160, 2160, 2160, 2153, 2153, 2153, 2150, 2150, 2150, 2163, 2164, 2165, 2158, 2168, 2175, 2161, 2162, 2158, 2158, 2158, 2166, 2174, 2174, 2174, 0, 0, 2167, 2162, 2162, 2162, 2171, 2161, 2161, 2161, 0, 2169, 2170, 0, 0, 2163, 2164, 2165, 0, 2168, 0, 0, 2175, 2175, 2175, 0, 2166, 0, 0, 2164, 2164, 2164, 2167, 2165, 2165, 2165, 2171, 2166, 2166, 2166, 2172, 2169, 2170, 2163, 2163, 2163, 2168, 2168, 2168, 2167, 2167, 2167, 2169, 2169, 2169, 2170, 2170, 2170, 2171, 2171, 2171, 2173, 2176, 2177, 2179, 2181, 2192, 2192, 2192, 0, 2172, 2180, 2194, 2194, 2194, 2178, 2206, 2206, 2206, 2172, 2172, 2172, 0, 0, 2182, 2210, 2210, 2210, 2213, 2213, 2213, 2173, 2176, 2177, 2179, 2181, 2187, 2215, 2215, 2215, 2183, 2180, 2173, 2173, 2173, 2178, 2184, 2181, 2181, 2181, 0, 2179, 2179, 2179, 2182, 2185, 2186, 2177, 2177, 2177, 0, 0, 2176, 2176, 2176, 2188, 2187, 2178, 2178, 2178, 2183, 2180, 2180, 2180, 2189, 0, 2184, 0, 2182, 2182, 2182, 2190, 2183, 2183, 2183, 2185, 2186, 2191, 0, 2184, 2184, 2184, 2187, 2187, 2187, 2188, 2193, 0, 2185, 2185, 2185, 0, 2222, 2196, 2189, 2186, 2186, 2186, 0, 0, 2195, 2190, 2198, 2217, 2217, 2217, 0, 2191, 2197, 2199, 2200, 0, 0, 2188, 2188, 2188, 2193, 2220, 2220, 2220, 2189, 2189, 2189, 2196, 2222, 2222, 2222, 2190, 2190, 2190, 2195, 0, 2198, 2201, 2202, 2191, 2191, 2191, 2197, 2199, 2200, 2195, 2195, 2195, 0, 2193, 2193, 2193, 2203, 2196, 2196, 2196, 2200, 2200, 2200, 2197, 2197, 2197, 0, 0, 2198, 2198, 2198, 2201, 2202, 0, 0, 2199, 2199, 2199, 2204, 2205, 0, 0, 2201, 2201, 2201, 2207, 2203, 2208, 2211, 2227, 2227, 2227, 2229, 2229, 2229, 0, 2202, 2202, 2202, 2232, 2232, 2232, 0, 2203, 2203, 2203, 2209, 0, 2204, 2205, 0, 2212, 2233, 2233, 2233, 2207, 2214, 2208, 2211, 2218, 0, 2212, 2205, 2205, 2205, 2216, 2207, 2207, 2207, 0, 2204, 2204, 2204, 2208, 2208, 2208, 2209, 0, 2211, 2211, 2211, 2212, 2209, 2209, 2209, 0, 2214, 0, 2219, 2218, 2221, 2212, 2223, 2226, 2228, 2216, 2224, 0, 2214, 2214, 2214, 2225, 0, 2212, 2212, 2212, 0, 2216, 2216, 2216, 0, 0, 2230, 2231, 0, 2218, 2218, 2218, 2219, 0, 2221, 2234, 2223, 2226, 2228, 2235, 2224, 2242, 2242, 2242, 0, 2225, 2221, 2221, 2221, 2228, 2228, 2228, 0, 2226, 2226, 2226, 2230, 2231, 2219, 2219, 2219, 2236, 2223, 2223, 2223, 2234, 2224, 2224, 2224, 2235, 2237, 2225, 2225, 2225, 2230, 2230, 2230, 2238, 2239, 2240, 2235, 2235, 2235, 2241, 2243, 2231, 2231, 2231, 2244, 0, 0, 2236, 2246, 0, 2234, 2234, 2234, 2252, 2252, 2252, 2237, 0, 2236, 2236, 2236, 0, 0, 2238, 2239, 2240, 2245, 0, 0, 2241, 2243, 2247, 0, 0, 2244, 0, 0, 2256, 2246, 2237, 2237, 2237, 2241, 2241, 2241, 2238, 2238, 2238, 2239, 2239, 2239, 2240, 2240, 2240, 2250, 2243, 2243, 2243, 2245, 2245, 2245, 2247, 2244, 2244, 2244, 2246, 2246, 2246, 2248, 2256, 2256, 2256, 0, 0, 2248, 0, 2248, 2251, 2248, 2247, 2247, 2247, 0, 2248, 2250, 0, 0, 2253, 2249, 2248, 2254, 0, 2248, 0, 2249, 2255, 2249, 2259, 2249, 0, 2250, 2250, 2250, 2249, 2248, 0, 2248, 2251, 2248, 2249, 2260, 0, 2249, 2248, 2257, 2257, 2257, 2253, 0, 2248, 2254, 0, 2248, 0, 2249, 2255, 2249, 2259, 2249, 2251, 2251, 2251, 2261, 2249, 2258, 2258, 2258, 2262, 2265, 2249, 2260, 2263, 2249, 2253, 2253, 2253, 2264, 2267, 2254, 2254, 2254, 2255, 2255, 2255, 2259, 2259, 2259, 2260, 2260, 2260, 2266, 2266, 2266, 2268, 2261, 2261, 2261, 2262, 2265, 2270, 0, 2263, 2269, 2269, 2269, 0, 0, 2267, 2264, 2264, 2264, 0, 0, 2262, 2262, 2262, 2276, 2277, 2263, 2263, 2263, 0, 0, 2268, 2265, 2265, 2265, 0, 0, 2270, 2271, 2271, 2271, 2267, 2267, 2267, 2272, 2272, 2272, 2281, 2270, 2270, 2270, 2275, 2275, 2275, 2276, 2277, 2280, 2268, 2268, 2268, 2278, 2278, 2278, 2282, 2276, 2276, 2276, 2279, 2279, 2279, 2283, 2284, 2285, 2286, 2286, 2286, 2291, 2281, 2277, 2277, 2277, 2287, 2287, 2287, 2288, 2288, 2288, 2293, 2280, 2280, 2280, 2292, 0, 2282, 2281, 2281, 2281, 2289, 2289, 2289, 2283, 2284, 2285, 2290, 2290, 2290, 0, 2294, 2291, 2291, 2291, 2282, 2282, 2282, 0, 0, 2297, 2293, 2302, 2295, 0, 2292, 2283, 2283, 2283, 2284, 2284, 2284, 2285, 2285, 2285, 2296, 2303, 0, 2292, 2292, 2292, 2294, 2298, 2298, 2298, 2301, 0, 2293, 2293, 2293, 2297, 2305, 2302, 2295, 2299, 2299, 2299, 2300, 2300, 2300, 2302, 2302, 2302, 0, 0, 2296, 2303, 2294, 2294, 2294, 2295, 2295, 2295, 2304, 2306, 2301, 2297, 2297, 2297, 0, 2309, 2305, 2296, 2296, 2296, 2303, 2303, 2303, 2307, 2308, 2308, 2308, 2310, 2301, 2301, 2301, 2312, 0, 2313, 2314, 2314, 2314, 0, 2304, 2306, 2311, 2315, 2305, 2305, 2305, 2309, 2322, 2322, 2322, 2304, 2304, 2304, 0, 2307, 0, 2316, 0, 2310, 2337, 2337, 2337, 2312, 0, 2313, 0, 0, 2306, 2306, 2306, 2327, 2311, 2315, 2307, 2307, 2307, 2309, 2309, 2309, 2317, 2310, 2310, 2310, 2311, 2311, 2311, 2316, 2318, 2312, 2312, 2312, 2313, 2313, 2313, 2319, 2316, 2316, 2316, 2315, 2315, 2315, 0, 2327, 2327, 2327, 2321, 0, 0, 2320, 2317, 2324, 2338, 2338, 2338, 2317, 2317, 2317, 2318, 2344, 2344, 2344, 2348, 2348, 2348, 2319, 0, 2323, 2351, 2351, 2351, 2325, 2331, 2354, 2354, 2354, 2321, 2326, 0, 2320, 0, 2324, 2328, 0, 2318, 2318, 2318, 2329, 2319, 2319, 2319, 2320, 2320, 2320, 2321, 2321, 2321, 2323, 2324, 2324, 2324, 2325, 2330, 2332, 2331, 2331, 2331, 2326, 2323, 2323, 2323, 0, 2328, 0, 2325, 2325, 2325, 2329, 2326, 2326, 2326, 2333, 0, 2334, 2328, 2328, 2328, 2335, 2329, 2329, 2329, 2336, 2330, 2332, 2355, 2355, 2355, 0, 2340, 0, 0, 2330, 2330, 2330, 2339, 2341, 2332, 2332, 2332, 0, 2343, 2333, 0, 2334, 2342, 0, 0, 2335, 2357, 2357, 2357, 2336, 2333, 2333, 2333, 2334, 2334, 2334, 2340, 2335, 2335, 2335, 0, 2345, 2339, 2341, 2346, 2336, 2336, 2336, 2343, 2339, 2339, 2339, 2342, 2347, 2350, 0, 2341, 2341, 2341, 2343, 2343, 2343, 0, 2340, 2340, 2340, 2349, 0, 2342, 2342, 2342, 2345, 0, 2352, 2346, 2353, 2356, 2359, 2359, 2359, 2362, 2362, 2362, 2347, 2350, 2361, 2364, 2345, 2345, 2345, 2346, 2346, 2346, 0, 0, 2358, 2349, 2350, 2350, 2350, 2347, 2347, 2347, 2352, 0, 2353, 2356, 2363, 2363, 2363, 0, 2360, 2349, 2349, 2349, 2361, 2364, 2356, 2356, 2356, 2366, 2360, 2353, 2353, 2353, 2358, 2365, 2365, 2365, 2352, 2352, 2352, 2368, 2364, 2364, 2364, 0, 2375, 2358, 2358, 2358, 2360, 2367, 2369, 0, 2361, 2361, 2361, 0, 2371, 2366, 2360, 2370, 2370, 2370, 2373, 2373, 2373, 2372, 2374, 0, 0, 2368, 2376, 2377, 0, 2360, 2360, 2360, 2375, 2375, 2375, 2367, 2369, 0, 0, 2366, 2366, 2366, 2371, 0, 2368, 2368, 2368, 2378, 2367, 2367, 2367, 2372, 2374, 2371, 2371, 2371, 2376, 2377, 2369, 2369, 2369, 2379, 2379, 2379, 2374, 2374, 2374, 2372, 2372, 2372, 2380, 0, 2376, 2376, 2376, 2382, 2396, 2378, 0, 0, 2377, 2377, 2377, 2383, 2384, 2385, 2385, 2385, 2386, 2388, 2378, 2378, 2378, 2387, 2387, 2387, 2389, 2389, 2389, 2390, 2380, 0, 0, 2392, 0, 2382, 0, 0, 2396, 2396, 2396, 0, 2394, 2383, 2384, 2380, 2380, 2380, 2386, 2388, 0, 2382, 2382, 2382, 0, 0, 2383, 2383, 2383, 2390, 2384, 2384, 2384, 2392, 2388, 2388, 2388, 2393, 2386, 2386, 2386, 2391, 2394, 2397, 2391, 2400, 0, 2395, 2398, 0, 2392, 2392, 2392, 2390, 2390, 2390, 2401, 2401, 2401, 2394, 2394, 2394, 0, 2403, 2404, 0, 0, 2393, 0, 2402, 0, 2391, 0, 2397, 2391, 2400, 0, 2395, 2398, 2393, 2393, 2393, 0, 0, 2405, 2409, 2397, 2397, 2397, 0, 2400, 2400, 2400, 2403, 2404, 2406, 2406, 2406, 0, 2402, 2410, 2391, 2391, 2391, 2395, 2395, 2395, 0, 2398, 2398, 2398, 2402, 2402, 2402, 2405, 2409, 2412, 2403, 2403, 2403, 2404, 2404, 2404, 2407, 2407, 2407, 2408, 2409, 2409, 2409, 2410, 2405, 2405, 2405, 2411, 2411, 2411, 2408, 2413, 2414, 2418, 0, 2408, 2410, 2410, 2410, 2412, 2415, 2415, 2415, 0, 0, 2417, 2419, 2419, 2419, 2408, 2412, 2412, 2412, 2416, 2420, 2420, 2420, 0, 2421, 0, 2408, 2413, 2414, 2418, 2424, 2408, 2425, 2425, 2425, 2422, 2427, 0, 2413, 2413, 2413, 2417, 2423, 2408, 2408, 2408, 2426, 2426, 2426, 2416, 2428, 2418, 2418, 2418, 2421, 0, 2414, 2414, 2414, 2429, 2424, 0, 2416, 2416, 2416, 2422, 2427, 2417, 2417, 2417, 2432, 0, 2423, 2421, 2421, 2421, 2422, 2422, 2422, 2431, 2428, 2433, 2434, 2423, 2423, 2423, 2424, 2424, 2424, 2429, 2430, 2430, 2430, 2427, 2427, 2427, 0, 0, 2435, 2436, 2432, 2437, 2437, 2437, 2438, 0, 2428, 2428, 2428, 2431, 0, 2433, 2434, 2439, 2438, 2429, 2429, 2429, 2434, 2434, 2434, 0, 2432, 2432, 2432, 2431, 2431, 2431, 2435, 2436, 2440, 2440, 2440, 2441, 2438, 0, 0, 2433, 2433, 2433, 2436, 2436, 2436, 2439, 2438, 2443, 2443, 2443, 2444, 2442, 2445, 2439, 2439, 2439, 2435, 2435, 2435, 2442, 2450, 2438, 2438, 2438, 2446, 2441, 2449, 2449, 2449, 2447, 2442, 2448, 2454, 2454, 2454, 2451, 2460, 2460, 2460, 0, 2444, 2442, 0, 0, 2445, 2445, 2445, 0, 0, 2442, 2450, 2441, 2441, 2441, 2456, 2452, 2446, 2446, 2446, 2447, 2442, 2448, 2444, 2444, 2444, 2451, 2450, 2450, 2450, 2442, 2442, 2442, 2448, 2448, 2448, 2453, 2447, 2447, 2447, 2455, 2457, 2461, 2451, 2451, 2451, 2452, 2456, 2456, 2456, 2459, 2465, 2465, 2465, 0, 0, 2462, 0, 2458, 2452, 2452, 2452, 2464, 2466, 2466, 2466, 2453, 2463, 0, 0, 2455, 2457, 0, 0, 2461, 2461, 2461, 2467, 0, 0, 2459, 2468, 2469, 2453, 2453, 2453, 2462, 2471, 2458, 2470, 2470, 2470, 2464, 0, 2455, 2455, 2455, 2463, 2457, 2457, 2457, 2458, 2458, 2458, 2459, 2459, 2459, 2467, 2462, 2462, 2462, 2468, 2469, 2463, 2463, 2463, 2472, 2471, 2473, 2464, 2464, 2464, 2482, 2467, 2467, 2467, 0, 0, 2469, 2469, 2469, 2477, 2477, 2477, 2471, 2471, 2471, 2468, 2468, 2468, 2474, 2475, 2479, 2481, 2476, 0, 2472, 0, 2473, 2484, 2484, 2484, 2482, 2480, 2485, 0, 2472, 2472, 2472, 2491, 0, 2473, 2473, 2473, 2482, 2482, 2482, 2487, 2487, 2487, 2474, 2475, 2479, 2481, 2476, 2488, 2488, 2488, 2483, 2486, 2474, 2474, 2474, 2480, 2485, 2489, 2490, 2490, 2490, 2491, 2481, 2481, 2481, 0, 2479, 2479, 2479, 2475, 2475, 2475, 2476, 2476, 2476, 2492, 2493, 2480, 2480, 2480, 2483, 2486, 2496, 2485, 2485, 2485, 2497, 2489, 0, 2491, 2491, 2491, 2500, 2483, 2483, 2483, 0, 2489, 2489, 2489, 2495, 2495, 2495, 2486, 2486, 2486, 2493, 2492, 2492, 2492, 2501, 2505, 2496, 2498, 2498, 2498, 2497, 2499, 2499, 2499, 2502, 2508, 2500, 0, 2493, 2493, 2493, 2497, 2497, 2497, 2503, 2503, 2503, 2506, 2496, 2496, 2496, 2504, 2504, 2504, 2501, 2505, 2509, 2509, 2509, 0, 2507, 2510, 0, 0, 2502, 2508, 2500, 2500, 2500, 2511, 2512, 2512, 2512, 2515, 2515, 2515, 0, 2506, 0, 2513, 2514, 2505, 2505, 2505, 2501, 2501, 2501, 2508, 2508, 2508, 2507, 2510, 2502, 2502, 2502, 2517, 2517, 2517, 2516, 2511, 2518, 2524, 2522, 2506, 2506, 2506, 2507, 2507, 2507, 2513, 2514, 2520, 2520, 2520, 2519, 2513, 2513, 2513, 2523, 2510, 2510, 2510, 2521, 2521, 2521, 2511, 2511, 2511, 2516, 0, 2518, 2524, 2522, 0, 2525, 0, 2529, 2526, 2514, 2514, 2514, 2516, 2516, 2516, 2519, 2527, 0, 0, 2523, 2519, 2519, 2519, 0, 2524, 2524, 2524, 2530, 2518, 2518, 2518, 2522, 2522, 2522, 0, 2525, 2528, 2529, 2526, 0, 2528, 2531, 0, 0, 2528, 2532, 2527, 0, 2523, 2523, 2523, 2525, 2525, 2525, 2526, 2526, 2526, 2530, 0, 2527, 2527, 2527, 0, 2529, 2529, 2529, 2528, 0, 0, 2533, 2528, 2531, 2534, 2537, 2528, 2532, 2535, 2535, 2535, 2541, 2536, 2538, 0, 2530, 2530, 2530, 0, 2531, 2531, 2531, 2532, 2532, 2532, 2539, 2539, 2539, 2528, 2528, 2528, 2533, 0, 0, 2534, 2537, 2540, 2540, 2540, 2545, 0, 2541, 2536, 2538, 0, 0, 2533, 2533, 2533, 2546, 2547, 2534, 2534, 2534, 2536, 2536, 2536, 2542, 2542, 2542, 2549, 2551, 2537, 2537, 2537, 2538, 2538, 2538, 0, 2545, 2541, 2541, 2541, 2543, 2543, 2543, 2544, 2544, 2544, 2546, 2547, 2545, 2545, 2545, 2548, 2548, 2548, 2550, 2550, 2550, 2549, 2551, 2547, 2547, 2547, 2552, 2552, 2552, 2546, 2546, 2546, 2553, 2549, 2549, 2549, 2554, 2555, 2583, 2551, 2551, 2551, 2556, 2556, 2556, 2557, 2560, 0, 2559, 2579, 2579, 2579, 2581, 2581, 2581, 2584, 2584, 2584, 0, 0, 2563, 2561, 2553, 2602, 2602, 2602, 2554, 2555, 2562, 2564, 2583, 2583, 2583, 0, 0, 2557, 2560, 2565, 2559, 0, 0, 2553, 2553, 2553, 2555, 2555, 2555, 2557, 2557, 2557, 2563, 2561, 2554, 2554, 2554, 2559, 2559, 2559, 2562, 2564, 2560, 2560, 2560, 2561, 2561, 2561, 2566, 2565, 2562, 2562, 2562, 2567, 2563, 2563, 2563, 2568, 2569, 2607, 2607, 2607, 0, 2573, 2571, 2615, 2615, 2615, 2564, 2564, 2564, 0, 2574, 0, 2565, 2565, 2565, 0, 2566, 2570, 2572, 0, 0, 2567, 2617, 2617, 2617, 2568, 2569, 0, 2575, 0, 0, 2573, 2571, 0, 2566, 2566, 2566, 2568, 2568, 2568, 2574, 2569, 2569, 2569, 2567, 2567, 2567, 2570, 2572, 2573, 2573, 2573, 2570, 2570, 2570, 2571, 2571, 2571, 2575, 2572, 2572, 2572, 2576, 2574, 2574, 2574, 2577, 2578, 2580, 2591, 2582, 2575, 2575, 2575, 2585, 2620, 2620, 2620, 2622, 2622, 2622, 2586, 2587, 2625, 2625, 2625, 2627, 2627, 2627, 0, 0, 2589, 2576, 0, 0, 2588, 2577, 2578, 2580, 0, 2582, 2591, 2591, 2591, 2585, 2576, 2576, 2576, 2578, 2578, 2578, 2586, 2587, 2577, 2577, 2577, 2582, 2582, 2582, 2590, 2592, 2589, 2586, 2586, 2586, 2588, 2580, 2580, 2580, 2593, 2585, 2585, 2585, 2589, 2589, 2589, 2639, 0, 2587, 2587, 2587, 2594, 0, 0, 2588, 2588, 2588, 2595, 2596, 2590, 2592, 2597, 2598, 2638, 2638, 2638, 2642, 2642, 2642, 2593, 2599, 0, 2590, 2590, 2590, 2592, 2592, 2592, 2639, 2639, 2639, 2594, 2593, 2593, 2593, 2600, 2603, 2595, 2596, 0, 0, 2597, 2598, 2595, 2595, 2595, 2594, 2594, 2594, 2601, 2599, 2596, 2596, 2596, 0, 0, 2604, 2606, 2597, 2597, 2597, 2648, 2648, 2648, 2605, 2600, 2603, 2608, 2598, 2598, 2598, 2658, 2658, 2658, 0, 0, 2599, 2599, 2599, 2601, 2660, 2660, 2660, 2603, 2603, 2603, 2604, 2606, 0, 2609, 2612, 2600, 2600, 2600, 2605, 0, 2610, 2608, 2611, 2616, 2661, 2661, 2661, 0, 2613, 2601, 2601, 2601, 2604, 2604, 2604, 0, 0, 2606, 2606, 2606, 2605, 2605, 2605, 2609, 2612, 0, 0, 2608, 2608, 2608, 2610, 2618, 2611, 2616, 2621, 2609, 2609, 2609, 2613, 2619, 2623, 2610, 2610, 2610, 2611, 2611, 2611, 2626, 2613, 2613, 2613, 2612, 2612, 2612, 2624, 2616, 2616, 2616, 2628, 0, 0, 2618, 2637, 2636, 2621, 2629, 0, 0, 2630, 2619, 2623, 2666, 2666, 2666, 2668, 2668, 2668, 2626, 0, 2618, 2618, 2618, 0, 2633, 2624, 2619, 2619, 2619, 2628, 2621, 2621, 2621, 2637, 2636, 0, 2629, 0, 2631, 2630, 2634, 2623, 2623, 2623, 2626, 2626, 2626, 2624, 2624, 2624, 2632, 2636, 2636, 2636, 2633, 2637, 2637, 2637, 2635, 2628, 2628, 2628, 2629, 2629, 2629, 2630, 2630, 2630, 2631, 0, 2634, 0, 2640, 2641, 2644, 2645, 2646, 2631, 2631, 2631, 2632, 2633, 2633, 2633, 2643, 2647, 0, 0, 2635, 2632, 2632, 2632, 2649, 2671, 2671, 2671, 2634, 2634, 2634, 2635, 2635, 2635, 2640, 2641, 2644, 2645, 2646, 2673, 2673, 2673, 2677, 2677, 2677, 0, 2643, 2647, 0, 2646, 2646, 2646, 2650, 2653, 2649, 2651, 2654, 2656, 2644, 2644, 2644, 2641, 2641, 2641, 2640, 2640, 2640, 2645, 2645, 2645, 2647, 2647, 2647, 2643, 2643, 2643, 2649, 2649, 2649, 2652, 2655, 0, 2650, 2653, 0, 2651, 2654, 2656, 2659, 2662, 2657, 2678, 2678, 2678, 2650, 2650, 2650, 0, 2651, 2651, 2651, 0, 2664, 0, 2656, 2656, 2656, 2663, 2665, 2652, 2655, 2653, 2653, 2653, 2654, 2654, 2654, 0, 2659, 2662, 2657, 0, 2652, 2652, 2652, 2657, 2657, 2657, 2667, 2662, 2662, 2662, 2664, 2669, 2655, 2655, 2655, 2672, 2665, 2663, 2663, 2663, 0, 0, 2670, 2674, 2659, 2659, 2659, 0, 0, 2664, 2664, 2664, 2675, 2665, 2665, 2665, 2667, 2676, 2682, 0, 0, 2669, 0, 0, 2683, 2672, 2680, 0, 2679, 2667, 2667, 2667, 2670, 2674, 2669, 2669, 2669, 2670, 2670, 2670, 2681, 0, 2675, 0, 2672, 2672, 2672, 2676, 2682, 0, 0, 2674, 2674, 2674, 2683, 0, 2680, 0, 2679, 0, 0, 2682, 2682, 2682, 2686, 2683, 2683, 2683, 0, 0, 2681, 2687, 2675, 2675, 2675, 2689, 2691, 2676, 2676, 2676, 2679, 2679, 2679, 2680, 2680, 2680, 2684, 2684, 2684, 2685, 2685, 2685, 0, 0, 2686, 2690, 2692, 2681, 2681, 2681, 0, 2687, 2688, 2688, 2688, 2689, 2693, 2695, 2691, 2691, 2691, 2697, 2687, 2687, 2687, 2694, 2696, 2696, 2696, 2698, 0, 2686, 2686, 2686, 0, 2690, 0, 0, 2692, 2692, 2692, 2689, 2689, 2689, 2699, 2700, 0, 2695, 2693, 2693, 2693, 2697, 2704, 2706, 2701, 2694, 2703, 2703, 2703, 2698, 2690, 2690, 2690, 2695, 2695, 2695, 2694, 2694, 2694, 0, 2697, 2697, 2697, 2702, 2699, 2700, 0, 2705, 2707, 2712, 2712, 2712, 2704, 2706, 2701, 2698, 2698, 2698, 2708, 0, 2699, 2699, 2699, 2709, 2700, 2700, 2700, 2701, 2701, 2701, 0, 2715, 2710, 2702, 2704, 2704, 2704, 2705, 2707, 2706, 2706, 2706, 0, 0, 2702, 2702, 2702, 2711, 2708, 2705, 2705, 2705, 0, 2709, 2707, 2707, 2707, 2713, 2714, 2716, 2716, 2716, 2710, 2715, 2715, 2715, 2717, 2718, 2719, 2726, 2726, 2726, 2709, 2709, 2709, 0, 0, 2711, 2708, 2708, 2708, 2710, 2710, 2710, 2730, 2730, 2730, 2713, 2714, 2733, 2733, 2733, 2720, 2711, 2711, 2711, 2717, 2718, 2719, 2713, 2713, 2713, 2721, 2724, 2719, 2719, 2719, 2735, 2735, 2735, 2718, 2718, 2718, 2722, 2714, 2714, 2714, 2723, 0, 2717, 2717, 2717, 2720, 2736, 2736, 2736, 0, 0, 2725, 0, 2727, 0, 2721, 2724, 2729, 2732, 0, 2720, 2720, 2720, 0, 0, 2728, 2722, 2737, 2737, 2737, 2723, 0, 0, 2724, 2724, 2724, 0, 0, 2721, 2721, 2721, 2725, 2731, 2727, 2739, 2739, 2739, 2729, 2732, 2722, 2722, 2722, 2723, 2723, 2723, 2728, 2734, 2725, 2725, 2725, 2727, 2727, 2727, 2729, 2729, 2729, 2728, 2728, 2728, 2738, 2744, 2745, 2731, 0, 2732, 2732, 2732, 2741, 2740, 2742, 2742, 2742, 0, 2731, 2731, 2731, 2734, 2743, 2743, 2743, 2752, 2752, 2752, 0, 0, 2746, 2754, 0, 0, 2738, 2747, 2745, 2744, 2744, 2744, 2748, 2749, 2741, 2740, 0, 2734, 2734, 2734, 0, 2750, 2751, 2738, 2738, 2738, 2740, 2740, 2740, 2741, 2741, 2741, 2746, 2754, 2745, 2745, 2745, 2747, 2759, 2754, 2754, 2754, 2748, 2749, 2753, 2756, 2756, 2756, 2746, 2746, 2746, 2750, 2751, 2747, 2747, 2747, 2755, 2758, 2748, 2748, 2748, 2757, 2757, 2757, 2765, 2765, 2765, 0, 2759, 0, 2749, 2749, 2749, 2760, 2753, 2750, 2750, 2750, 2761, 2751, 2751, 2751, 2753, 2753, 2753, 0, 2755, 2758, 2762, 2764, 2766, 2766, 2766, 0, 2759, 2759, 2759, 2755, 2755, 2755, 2758, 2758, 2758, 2760, 2763, 2767, 2767, 2767, 2761, 2768, 2769, 2769, 2769, 2773, 0, 2760, 2760, 2760, 2762, 2764, 2771, 2761, 2761, 2761, 2770, 2770, 2770, 0, 2762, 2762, 2762, 2772, 2774, 0, 2763, 0, 2764, 2764, 2764, 2768, 0, 0, 2775, 2773, 2763, 2763, 2763, 2776, 0, 0, 2771, 2768, 2768, 2768, 2777, 0, 2771, 2771, 2771, 2780, 0, 2772, 0, 2781, 2774, 2774, 2774, 0, 0, 2773, 2773, 2773, 2775, 2782, 2772, 2772, 2772, 2776, 2778, 2778, 2778, 2779, 2779, 2779, 2777, 2775, 2775, 2775, 0, 2780, 2776, 2776, 2776, 2781, 2786, 2787, 2777, 2777, 2777, 2783, 2783, 2783, 2788, 2782, 0, 0, 2781, 2781, 2781, 2789, 0, 2780, 2780, 2780, 2784, 2784, 2784, 2785, 2785, 2785, 0, 2790, 2791, 2795, 2786, 2787, 2782, 2782, 2782, 2792, 2792, 2792, 2788, 0, 2787, 2787, 2787, 0, 0, 2789, 2786, 2786, 2786, 2793, 2797, 0, 2794, 0, 2788, 2788, 2788, 2790, 2791, 2798, 2799, 2795, 2795, 2795, 2796, 2796, 2796, 0, 2791, 2791, 2791, 2800, 2789, 2789, 2789, 2801, 2801, 2801, 0, 2793, 2797, 0, 2794, 2790, 2790, 2790, 0, 0, 0, 2798, 2799, 0, 2793, 2793, 2793, 2794, 2794, 2794, 0, 0, 0, 2800, 0, 2799, 2799, 2799, 0, 0, 2797, 2797, 2797, 0, 2800, 2800, 2800, 2798, 2798, 2798, 2803, 2803, 2803, 2803, 2803, 2803, 2804, 2804, 2804, 2804, 2804, 2804, 2805, 0, 2805, 2805, 2805, 2805, 2806, 0, 0, 2806, 2807, 2807, 2807, 2807, 2807, 2807, 2808, 0, 2808, 0, 2808, 2808, 2809, 2809, 2809, 2809, 2809, 2809, 2810, 0, 2810, 2810, 2810, 2810, 2811, 2811, 2811, 2811, 2811, 2811, 2812, 2812, 2812, 2812, 2812, 2812, 2813, 0, 2813, 2813, 2813, 2813, 2814, 0, 2814, 2814, 2814, 2814, 2815, 0, 2815, 2815, 2815, 2815, 2816, 0, 2816, 2816, 2816, 2816, 2817, 0, 2817, 2817, 2817, 2817, 2818, 2818, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802 } ; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #line 1 "mysqlnd_query_lexer.flex" #line 2 "mysqlnd_query_lexer.flex" /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* Compile with : flex mysqlnd_query_lexer.flex */ #include #include "php.h" #include "php_ini.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #include "mysqlnd_ms.h" #include "mysqlnd_query_parser.h" int old_yystate; #define yyerror mysqlnd_qp_error int mysqlnd_qp_error(const char *format, ...); #define YY_DECL int mysqlnd_qp_lex(YYSTYPE * yylval_param, yyscan_t yyscanner TSRMLS_DC) #define YY_NO_INPUT #define YY_NO_UNISTD_H /* In Unicode . is [\0-\x7F] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEF][\x80-\xBF][\x80-\xBF] */ #line 4885 "mysqlnd_query_lexer.c" #define INITIAL 0 #define COMMENT_MODE 1 #define BETWEEN_MODE 2 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #define YY_EXTRA_TYPE zval * /* Holds the entire state of the reentrant scanner. */ struct yyguts_t { /* User-defined. Not touched by flex. */ YY_EXTRA_TYPE yyextra_r; /* The rest are the same as the globals declared in the non-reentrant scanner. */ FILE *yyin_r, *yyout_r; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; int yy_n_chars; int yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; int yy_did_buffer_switch_on_eof; int yy_start_stack_ptr; int yy_start_stack_depth; int *yy_start_stack; yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; int yylineno_r; int yy_flex_debug_r; char *yytext_r; int yy_more_flag; int yy_more_len; YYSTYPE * yylval_r; }; /* end struct yyguts_t */ static int yy_init_globals (yyscan_t yyscanner ); /* This must go here because YYSTYPE and YYLTYPE are included * from bison output in section 1.*/ # define yylval yyg->yylval_r int mysqlnd_qp_lex_init (yyscan_t* scanner); int mysqlnd_qp_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int mysqlnd_qp_lex_destroy (yyscan_t yyscanner ); int mysqlnd_qp_get_debug (yyscan_t yyscanner ); void mysqlnd_qp_set_debug (int debug_flag ,yyscan_t yyscanner ); YY_EXTRA_TYPE mysqlnd_qp_get_extra (yyscan_t yyscanner ); void mysqlnd_qp_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); FILE *mysqlnd_qp_get_in (yyscan_t yyscanner ); void mysqlnd_qp_set_in (FILE * in_str ,yyscan_t yyscanner ); FILE *mysqlnd_qp_get_out (yyscan_t yyscanner ); void mysqlnd_qp_set_out (FILE * out_str ,yyscan_t yyscanner ); int mysqlnd_qp_get_leng (yyscan_t yyscanner ); char *mysqlnd_qp_get_text (yyscan_t yyscanner ); int mysqlnd_qp_get_lineno (yyscan_t yyscanner ); void mysqlnd_qp_set_lineno (int line_number ,yyscan_t yyscanner ); YYSTYPE * mysqlnd_qp_get_lval (yyscan_t yyscanner ); void mysqlnd_qp_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int mysqlnd_qp_wrap (yyscan_t yyscanner ); #else extern int mysqlnd_qp_wrap (yyscan_t yyscanner ); #endif #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner ); #else static int input (yyscan_t yyscanner ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int mysqlnd_qp_lex \ (YYSTYPE * yylval_param ,yyscan_t yyscanner); #define YY_DECL int mysqlnd_qp_lex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; #line 58 "mysqlnd_query_lexer.flex" /* can't use `yylval` here because `yylval` is initialized by flex to `yylval_param` later */ zval * token_value = &yylval_param->zv; const char ** kn = &(yylval_param->kn); smart_str ** comment = &(yylval_param->comment); DBG_ENTER("my_lex_routine"); #line 5131 "mysqlnd_query_lexer.c" yylval = yylval_param; if ( !yyg->yy_init ) { yyg->yy_init = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yyg->yy_start ) yyg->yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { mysqlnd_qp_ensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = mysqlnd_qp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } mysqlnd_qp__load_buffer_state(yyscanner ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yyg->yy_c_buf_p; /* Support of yytext. */ *yy_cp = yyg->yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yyg->yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 2803 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 15652 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yyg->yy_hold_char; yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 67 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ACCESSIBLE"); DBG_RETURN(QC_TOKEN_ACCESSIBLE); } YY_BREAK case 2: YY_RULE_SETUP #line 68 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ACTION"); DBG_RETURN(QC_TOKEN_ACTION); } YY_BREAK case 3: YY_RULE_SETUP #line 69 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ADD"); DBG_RETURN(QC_TOKEN_ADD); } YY_BREAK case 4: YY_RULE_SETUP #line 70 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ADDDATE"); DBG_RETURN(QC_TOKEN_ADDDATE); } YY_BREAK case 5: YY_RULE_SETUP #line 71 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AFTER"); DBG_RETURN(QC_TOKEN_AFTER); } YY_BREAK case 6: YY_RULE_SETUP #line 72 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AGAINST"); DBG_RETURN(QC_TOKEN_AGAINST); } YY_BREAK case 7: YY_RULE_SETUP #line 73 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AGGREGATE"); DBG_RETURN(QC_TOKEN_AGGREGATE); } YY_BREAK case 8: YY_RULE_SETUP #line 74 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ALGORITHM"); DBG_RETURN(QC_TOKEN_ALGORITHM); } YY_BREAK case 9: YY_RULE_SETUP #line 75 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ALL"); DBG_RETURN(QC_TOKEN_ALL); } YY_BREAK case 10: YY_RULE_SETUP #line 76 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ALTER"); DBG_RETURN(QC_TOKEN_ALTER); } YY_BREAK case 11: YY_RULE_SETUP #line 77 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ANALYZE"); DBG_RETURN(QC_TOKEN_ANALYZE); } YY_BREAK case 12: YY_RULE_SETUP #line 78 "mysqlnd_query_lexer.flex" { BEGIN INITIAL; *kn = yytext; DBG_INF("QC_TOKEN_BETWEEN_AND"); DBG_RETURN(QC_TOKEN_BETWEEN_AND); } YY_BREAK case 13: YY_RULE_SETUP #line 79 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AND"); DBG_RETURN(QC_TOKEN_AND); } YY_BREAK case 14: YY_RULE_SETUP #line 80 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ANY"); DBG_RETURN(QC_TOKEN_ANY); } YY_BREAK case 15: YY_RULE_SETUP #line 81 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AS"); DBG_RETURN(QC_TOKEN_AS); } YY_BREAK case 16: YY_RULE_SETUP #line 82 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ASC"); DBG_RETURN(QC_TOKEN_ASC); } YY_BREAK case 17: YY_RULE_SETUP #line 83 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ASCII"); DBG_RETURN(QC_TOKEN_ASCII); } YY_BREAK case 18: YY_RULE_SETUP #line 84 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ASENSITIVE"); DBG_RETURN(QC_TOKEN_ASENSITIVE); } YY_BREAK case 19: YY_RULE_SETUP #line 85 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AT"); DBG_RETURN(QC_TOKEN_AT); } YY_BREAK case 20: YY_RULE_SETUP #line 86 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AUTHORS"); DBG_RETURN(QC_TOKEN_AUTHORS); } YY_BREAK case 21: YY_RULE_SETUP #line 87 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AUTOEXTEND_SIZE"); DBG_RETURN(QC_TOKEN_AUTOEXTEND_SIZE); } YY_BREAK case 22: YY_RULE_SETUP #line 88 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AUTO_INC"); DBG_RETURN(QC_TOKEN_AUTO_INC); } YY_BREAK case 23: YY_RULE_SETUP #line 89 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AVG_ROW_LENGTH"); DBG_RETURN(QC_TOKEN_AVG_ROW_LENGTH); } YY_BREAK case 24: YY_RULE_SETUP #line 90 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_AVG"); DBG_RETURN(QC_TOKEN_AVG); } YY_BREAK case 25: YY_RULE_SETUP #line 91 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BACKUP"); DBG_RETURN(QC_TOKEN_BACKUP); } YY_BREAK case 26: YY_RULE_SETUP #line 92 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BEFORE"); DBG_RETURN(QC_TOKEN_BEFORE); } YY_BREAK case 27: YY_RULE_SETUP #line 93 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BEGIN"); DBG_RETURN(QC_TOKEN_BEGIN); } YY_BREAK case 28: YY_RULE_SETUP #line 94 "mysqlnd_query_lexer.flex" { BEGIN BETWEEN_MODE; *kn = yytext; DBG_INF("QC_TOKEN_BETWEEN"); DBG_RETURN(QC_TOKEN_BETWEEN); } YY_BREAK case 29: YY_RULE_SETUP #line 95 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BIGINT"); DBG_RETURN(QC_TOKEN_BIGINT); } YY_BREAK case 30: YY_RULE_SETUP #line 96 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BINARY"); DBG_RETURN(QC_TOKEN_BINARY); } YY_BREAK case 31: YY_RULE_SETUP #line 97 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BINLOG"); DBG_RETURN(QC_TOKEN_BINLOG); } YY_BREAK case 32: YY_RULE_SETUP #line 98 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BIT"); DBG_RETURN(QC_TOKEN_BIT); } YY_BREAK case 33: YY_RULE_SETUP #line 99 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BLOB"); DBG_RETURN(QC_TOKEN_BLOB); } YY_BREAK case 34: YY_RULE_SETUP #line 100 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BLOCK"); DBG_RETURN(QC_TOKEN_BLOCK); } YY_BREAK case 35: YY_RULE_SETUP #line 101 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BOOLEAN"); DBG_RETURN(QC_TOKEN_BOOLEAN); } YY_BREAK case 36: YY_RULE_SETUP #line 102 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BOOL"); DBG_RETURN(QC_TOKEN_BOOL); } YY_BREAK case 37: YY_RULE_SETUP #line 103 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BOTH"); DBG_RETURN(QC_TOKEN_BOTH); } YY_BREAK case 38: YY_RULE_SETUP #line 104 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BTREE"); DBG_RETURN(QC_TOKEN_BTREE); } YY_BREAK case 39: YY_RULE_SETUP #line 105 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BY"); DBG_RETURN(QC_TOKEN_BY); } YY_BREAK case 40: YY_RULE_SETUP #line 106 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_BYTE"); DBG_RETURN(QC_TOKEN_BYTE); } YY_BREAK case 41: YY_RULE_SETUP #line 107 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CACHE"); DBG_RETURN(QC_TOKEN_CACHE); } YY_BREAK case 42: YY_RULE_SETUP #line 108 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CALL"); DBG_RETURN(QC_TOKEN_CALL); } YY_BREAK case 43: YY_RULE_SETUP #line 109 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CASCADE"); DBG_RETURN(QC_TOKEN_CASCADE); } YY_BREAK case 44: YY_RULE_SETUP #line 110 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CASCADED"); DBG_RETURN(QC_TOKEN_CASCADED); } YY_BREAK case 45: YY_RULE_SETUP #line 111 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CASE"); DBG_RETURN(QC_TOKEN_CASE); } YY_BREAK case 46: YY_RULE_SETUP #line 112 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CAST"); DBG_RETURN(QC_TOKEN_CAST); } YY_BREAK case 47: YY_RULE_SETUP #line 113 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CATALOG_NAME"); DBG_RETURN(QC_TOKEN_CATALOG_NAME); } YY_BREAK case 48: YY_RULE_SETUP #line 114 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHAIN"); DBG_RETURN(QC_TOKEN_CHAIN); } YY_BREAK case 49: YY_RULE_SETUP #line 115 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHANGE"); DBG_RETURN(QC_TOKEN_CHANGE); } YY_BREAK case 50: YY_RULE_SETUP #line 116 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHANGED"); DBG_RETURN(QC_TOKEN_CHANGED); } YY_BREAK case 51: YY_RULE_SETUP #line 117 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHARSET"); DBG_RETURN(QC_TOKEN_CHARSET); } YY_BREAK case 52: YY_RULE_SETUP #line 118 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHAR"); DBG_RETURN(QC_TOKEN_CHAR); } YY_BREAK case 53: YY_RULE_SETUP #line 119 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHECKSUM"); DBG_RETURN(QC_TOKEN_CHECKSUM); } YY_BREAK case 54: YY_RULE_SETUP #line 120 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CHECK"); DBG_RETURN(QC_TOKEN_CHECK); } YY_BREAK case 55: YY_RULE_SETUP #line 121 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CIPHER"); DBG_RETURN(QC_TOKEN_CIPHER); } YY_BREAK case 56: YY_RULE_SETUP #line 122 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CLASS_ORIGIN"); DBG_RETURN(QC_TOKEN_CLASS_ORIGIN); } YY_BREAK case 57: YY_RULE_SETUP #line 123 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CLIENT"); DBG_RETURN(QC_TOKEN_CLIENT); } YY_BREAK case 58: YY_RULE_SETUP #line 124 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CLOSE"); DBG_RETURN(QC_TOKEN_CLOSE); } YY_BREAK case 59: YY_RULE_SETUP #line 125 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COALESCE"); DBG_RETURN(QC_TOKEN_COALESCE); } YY_BREAK case 60: YY_RULE_SETUP #line 126 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CODE"); DBG_RETURN(QC_TOKEN_CODE); } YY_BREAK case 61: YY_RULE_SETUP #line 127 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COLLATE"); DBG_RETURN(QC_TOKEN_COLLATE); } YY_BREAK case 62: YY_RULE_SETUP #line 128 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COLLATION"); DBG_RETURN(QC_TOKEN_COLLATION); } YY_BREAK case 63: YY_RULE_SETUP #line 129 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COLUMNS"); DBG_RETURN(QC_TOKEN_COLUMNS); } YY_BREAK case 64: YY_RULE_SETUP #line 130 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COLUMN"); DBG_RETURN(QC_TOKEN_COLUMN); } YY_BREAK case 65: YY_RULE_SETUP #line 131 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COLUMN_NAME"); DBG_RETURN(QC_TOKEN_COLUMN_NAME); } YY_BREAK case 66: YY_RULE_SETUP #line 132 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COMMENT"); DBG_RETURN(QC_TOKEN_COMMENT); } YY_BREAK case 67: YY_RULE_SETUP #line 133 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COMMITTED"); DBG_RETURN(QC_TOKEN_COMMITTED); } YY_BREAK case 68: YY_RULE_SETUP #line 134 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COMMIT"); DBG_RETURN(QC_TOKEN_COMMIT); } YY_BREAK case 69: YY_RULE_SETUP #line 135 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COMPACT"); DBG_RETURN(QC_TOKEN_COMPACT); } YY_BREAK case 70: YY_RULE_SETUP #line 136 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COMPLETION"); DBG_RETURN(QC_TOKEN_COMPLETION); } YY_BREAK case 71: YY_RULE_SETUP #line 137 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COMPRESSED"); DBG_RETURN(QC_TOKEN_COMPRESSED); } YY_BREAK case 72: YY_RULE_SETUP #line 138 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONCURRENT"); DBG_RETURN(QC_TOKEN_CONCURRENT); } YY_BREAK case 73: YY_RULE_SETUP #line 139 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONDITION"); DBG_RETURN(QC_TOKEN_CONDITION); } YY_BREAK case 74: YY_RULE_SETUP #line 140 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONNECTION"); DBG_RETURN(QC_TOKEN_CONNECTION); } YY_BREAK case 75: YY_RULE_SETUP #line 141 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONSISTENT"); DBG_RETURN(QC_TOKEN_CONSISTENT); } YY_BREAK case 76: YY_RULE_SETUP #line 142 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT"); DBG_RETURN(QC_TOKEN_CONSTRAINT); } YY_BREAK case 77: YY_RULE_SETUP #line 143 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT_CATALOG");DBG_RETURN(QC_TOKEN_CONSTRAINT_CATALOG); } YY_BREAK case 78: YY_RULE_SETUP #line 144 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT_NAME"); DBG_RETURN(QC_TOKEN_CONSTRAINT_NAME); } YY_BREAK case 79: YY_RULE_SETUP #line 145 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT_SCHEMA");DBG_RETURN(QC_TOKEN_CONSTRAINT_SCHEMA); } YY_BREAK case 80: YY_RULE_SETUP #line 146 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONTAINS"); DBG_RETURN(QC_TOKEN_CONTAINS); } YY_BREAK case 81: YY_RULE_SETUP #line 147 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONTEXT"); DBG_RETURN(QC_TOKEN_CONTEXT); } YY_BREAK case 82: YY_RULE_SETUP #line 148 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONTINUE"); DBG_RETURN(QC_TOKEN_CONTINUE); } YY_BREAK case 83: YY_RULE_SETUP #line 149 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONTRIBUTORS"); DBG_RETURN(QC_TOKEN_CONTRIBUTORS); } YY_BREAK case 84: YY_RULE_SETUP #line 150 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CONVERT"); DBG_RETURN(QC_TOKEN_CONVERT); } YY_BREAK case 85: YY_RULE_SETUP #line 151 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_COUNT"); DBG_RETURN(QC_TOKEN_COUNT); } YY_BREAK case 86: YY_RULE_SETUP #line 152 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CPU"); DBG_RETURN(QC_TOKEN_CPU); } YY_BREAK case 87: YY_RULE_SETUP #line 153 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CREATE"); DBG_RETURN(QC_TOKEN_CREATE); } YY_BREAK case 88: YY_RULE_SETUP #line 154 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CROSS"); DBG_RETURN(QC_TOKEN_CROSS); } YY_BREAK case 89: YY_RULE_SETUP #line 155 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CUBE"); DBG_RETURN(QC_TOKEN_CUBE); } YY_BREAK case 90: YY_RULE_SETUP #line 156 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CURDATE"); DBG_RETURN(QC_TOKEN_CURDATE); } YY_BREAK case 91: YY_RULE_SETUP #line 157 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CURRENT_USER"); DBG_RETURN(QC_TOKEN_CURRENT_USER); } YY_BREAK case 92: YY_RULE_SETUP #line 158 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CURSOR"); DBG_RETURN(QC_TOKEN_CURSOR); } YY_BREAK case 93: YY_RULE_SETUP #line 159 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CURSOR_NAME"); DBG_RETURN(QC_TOKEN_CURSOR_NAME); } YY_BREAK case 94: YY_RULE_SETUP #line 160 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CURTIME"); DBG_RETURN(QC_TOKEN_CURTIME); } YY_BREAK case 95: YY_RULE_SETUP #line 161 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATABASE"); DBG_RETURN(QC_TOKEN_DATABASE); } YY_BREAK case 96: YY_RULE_SETUP #line 162 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATABASES"); DBG_RETURN(QC_TOKEN_DATABASES); } YY_BREAK case 97: YY_RULE_SETUP #line 163 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATAFILE"); DBG_RETURN(QC_TOKEN_DATAFILE); } YY_BREAK case 98: YY_RULE_SETUP #line 164 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATA"); DBG_RETURN(QC_TOKEN_DATA); } YY_BREAK case 99: YY_RULE_SETUP #line 165 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATETIME"); DBG_RETURN(QC_TOKEN_DATETIME); } YY_BREAK case 100: YY_RULE_SETUP #line 166 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATE_ADD_INTERVAL");DBG_RETURN(QC_TOKEN_DATE_ADD_INTERVAL); } YY_BREAK case 101: YY_RULE_SETUP #line 167 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATE_SUB_INTERVAL");DBG_RETURN(QC_TOKEN_DATE_SUB_INTERVAL); } YY_BREAK case 102: YY_RULE_SETUP #line 168 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DATE"); DBG_RETURN(QC_TOKEN_DATE); } YY_BREAK case 103: YY_RULE_SETUP #line 169 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DAY_HOUR"); DBG_RETURN(QC_TOKEN_DAY_HOUR); } YY_BREAK case 104: YY_RULE_SETUP #line 170 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DAY_MICROSECOND"); DBG_RETURN(QC_TOKEN_DAY_MICROSECOND); } YY_BREAK case 105: YY_RULE_SETUP #line 171 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DAY_MINUTE"); DBG_RETURN(QC_TOKEN_DAY_MINUTE); } YY_BREAK case 106: YY_RULE_SETUP #line 172 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DAY_SECOND"); DBG_RETURN(QC_TOKEN_DAY_SECOND); } YY_BREAK case 107: YY_RULE_SETUP #line 173 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DAY"); DBG_RETURN(QC_TOKEN_DAY); } YY_BREAK case 108: YY_RULE_SETUP #line 174 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DEALLOCATE"); DBG_RETURN(QC_TOKEN_DEALLOCATE); } YY_BREAK case 109: YY_RULE_SETUP #line 175 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DECIMAL_NUM"); DBG_RETURN(QC_TOKEN_DECIMAL_NUM); } YY_BREAK case 110: YY_RULE_SETUP #line 176 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DECIMAL"); DBG_RETURN(QC_TOKEN_DECIMAL); } YY_BREAK case 111: YY_RULE_SETUP #line 177 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DECLARE"); DBG_RETURN(QC_TOKEN_DECLARE); } YY_BREAK case 112: YY_RULE_SETUP #line 178 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DEFAULT"); DBG_RETURN(QC_TOKEN_DEFAULT); } YY_BREAK case 113: YY_RULE_SETUP #line 179 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DEFINER"); DBG_RETURN(QC_TOKEN_DEFINER); } YY_BREAK case 114: YY_RULE_SETUP #line 180 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DELAYED"); DBG_RETURN(QC_TOKEN_DELAYED); } YY_BREAK case 115: YY_RULE_SETUP #line 181 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DELAY_KEY_WRITE"); DBG_RETURN(QC_TOKEN_DELAY_KEY_WRITE); } YY_BREAK case 116: YY_RULE_SETUP #line 182 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DELETE"); DBG_RETURN(QC_TOKEN_DELETE); } YY_BREAK case 117: YY_RULE_SETUP #line 183 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DESC"); DBG_RETURN(QC_TOKEN_DESC); } YY_BREAK case 118: YY_RULE_SETUP #line 184 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DESCRIBE"); DBG_RETURN(QC_TOKEN_DESCRIBE); } YY_BREAK case 119: YY_RULE_SETUP #line 185 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DES_KEY_FILE"); DBG_RETURN(QC_TOKEN_DES_KEY_FILE); } YY_BREAK case 120: YY_RULE_SETUP #line 186 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DETERMINISTIC"); DBG_RETURN(QC_TOKEN_DETERMINISTIC); } YY_BREAK case 121: YY_RULE_SETUP #line 187 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DIRECTORY"); DBG_RETURN(QC_TOKEN_DIRECTORY); } YY_BREAK case 122: YY_RULE_SETUP #line 188 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DISABLE"); DBG_RETURN(QC_TOKEN_DISABLE); } YY_BREAK case 123: YY_RULE_SETUP #line 189 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DISCARD"); DBG_RETURN(QC_TOKEN_DISCARD); } YY_BREAK case 124: YY_RULE_SETUP #line 190 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DISK"); DBG_RETURN(QC_TOKEN_DISK); } YY_BREAK case 125: YY_RULE_SETUP #line 191 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DISTINCT"); DBG_RETURN(QC_TOKEN_DISTINCT); } YY_BREAK case 126: YY_RULE_SETUP #line 192 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DIV"); DBG_RETURN(QC_TOKEN_DIV); } YY_BREAK case 127: YY_RULE_SETUP #line 193 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DOUBLE"); DBG_RETURN(QC_TOKEN_DOUBLE); } YY_BREAK case 128: YY_RULE_SETUP #line 194 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DO"); DBG_RETURN(QC_TOKEN_DO); } YY_BREAK case 129: YY_RULE_SETUP #line 195 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DROP"); DBG_RETURN(QC_TOKEN_DROP); } YY_BREAK case 130: YY_RULE_SETUP #line 196 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DUAL"); DBG_RETURN(QC_TOKEN_DUAL); } YY_BREAK case 131: YY_RULE_SETUP #line 197 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DUMPFILE"); DBG_RETURN(QC_TOKEN_DUMPFILE); } YY_BREAK case 132: YY_RULE_SETUP #line 198 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DUPLICATE"); DBG_RETURN(QC_TOKEN_DUPLICATE); } YY_BREAK case 133: YY_RULE_SETUP #line 199 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_DYNAMIC"); DBG_RETURN(QC_TOKEN_DYNAMIC); } YY_BREAK case 134: YY_RULE_SETUP #line 200 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EACH"); DBG_RETURN(QC_TOKEN_EACH); } YY_BREAK case 135: YY_RULE_SETUP #line 201 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ELSE"); DBG_RETURN(QC_TOKEN_ELSE); } YY_BREAK case 136: YY_RULE_SETUP #line 202 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ELSEIF"); DBG_RETURN(QC_TOKEN_ELSEIF); } YY_BREAK case 137: YY_RULE_SETUP #line 203 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ENABLE"); DBG_RETURN(QC_TOKEN_ENABLE); } YY_BREAK case 138: YY_RULE_SETUP #line 204 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ENCLOSED"); DBG_RETURN(QC_TOKEN_ENCLOSED); } YY_BREAK case 139: YY_RULE_SETUP #line 205 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_END"); DBG_RETURN(QC_TOKEN_END); } YY_BREAK case 140: YY_RULE_SETUP #line 206 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ENDS"); DBG_RETURN(QC_TOKEN_ENDS); } YY_BREAK case 141: YY_RULE_SETUP #line 207 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ENGINES"); DBG_RETURN(QC_TOKEN_ENGINES); } YY_BREAK case 142: YY_RULE_SETUP #line 208 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ENGINE"); DBG_RETURN(QC_TOKEN_ENGINE); } YY_BREAK case 143: YY_RULE_SETUP #line 209 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ENUM"); DBG_RETURN(QC_TOKEN_ENUM); } YY_BREAK case 144: YY_RULE_SETUP #line 210 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EQUAL"); DBG_RETURN(QC_TOKEN_EQUAL); } YY_BREAK case 145: YY_RULE_SETUP #line 211 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ERRORS"); DBG_RETURN(QC_TOKEN_ERRORS); } YY_BREAK case 146: YY_RULE_SETUP #line 212 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ESCAPED"); DBG_RETURN(QC_TOKEN_ESCAPED); } YY_BREAK case 147: YY_RULE_SETUP #line 213 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ESCAPE"); DBG_RETURN(QC_TOKEN_ESCAPE); } YY_BREAK case 148: YY_RULE_SETUP #line 214 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EVENTS"); DBG_RETURN(QC_TOKEN_EVENTS); } YY_BREAK case 149: YY_RULE_SETUP #line 215 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EVENT"); DBG_RETURN(QC_TOKEN_EVENT); } YY_BREAK case 150: YY_RULE_SETUP #line 216 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EVERY"); DBG_RETURN(QC_TOKEN_EVERY); } YY_BREAK case 151: YY_RULE_SETUP #line 217 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXECUTE"); DBG_RETURN(QC_TOKEN_EXECUTE); } YY_BREAK case 152: YY_RULE_SETUP #line 218 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXISTS"); DBG_RETURN(QC_TOKEN_EXISTS); } YY_BREAK case 153: YY_RULE_SETUP #line 219 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXIT"); DBG_RETURN(QC_TOKEN_EXIT); } YY_BREAK case 154: YY_RULE_SETUP #line 220 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXPANSION"); DBG_RETURN(QC_TOKEN_EXPANSION); } YY_BREAK case 155: YY_RULE_SETUP #line 221 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXTENDED"); DBG_RETURN(QC_TOKEN_EXTENDED); } YY_BREAK case 156: YY_RULE_SETUP #line 222 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXTENT_SIZE"); DBG_RETURN(QC_TOKEN_EXTENT_SIZE); } YY_BREAK case 157: YY_RULE_SETUP #line 223 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_EXTRACT"); DBG_RETURN(QC_TOKEN_EXTRACT); } YY_BREAK case 158: YY_RULE_SETUP #line 224 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FALSE"); DBG_RETURN(QC_TOKEN_FALSE); } YY_BREAK case 159: YY_RULE_SETUP #line 225 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FAST"); DBG_RETURN(QC_TOKEN_FAST); } YY_BREAK case 160: YY_RULE_SETUP #line 226 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FAULTS"); DBG_RETURN(QC_TOKEN_FAULTS); } YY_BREAK case 161: YY_RULE_SETUP #line 227 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FETCH"); DBG_RETURN(QC_TOKEN_FETCH); } YY_BREAK case 162: YY_RULE_SETUP #line 228 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FILE"); DBG_RETURN(QC_TOKEN_FILE); } YY_BREAK case 163: YY_RULE_SETUP #line 229 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FIRST"); DBG_RETURN(QC_TOKEN_FIRST); } YY_BREAK case 164: YY_RULE_SETUP #line 230 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FIXED"); DBG_RETURN(QC_TOKEN_FIXED); } YY_BREAK case 165: YY_RULE_SETUP #line 231 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FLOAT_NUM"); DBG_RETURN(QC_TOKEN_FLOAT_NUM); } YY_BREAK case 166: YY_RULE_SETUP #line 232 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FLOAT"); DBG_RETURN(QC_TOKEN_FLOAT); } YY_BREAK case 167: YY_RULE_SETUP #line 233 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FLUSH"); DBG_RETURN(QC_TOKEN_FLUSH); } YY_BREAK case 168: YY_RULE_SETUP #line 234 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FORCE"); DBG_RETURN(QC_TOKEN_FORCE); } YY_BREAK case 169: YY_RULE_SETUP #line 235 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FOREIGN"); DBG_RETURN(QC_TOKEN_FOREIGN); } YY_BREAK case 170: YY_RULE_SETUP #line 236 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FOR"); DBG_RETURN(QC_TOKEN_FOR); } YY_BREAK case 171: YY_RULE_SETUP #line 237 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FOUND"); DBG_RETURN(QC_TOKEN_FOUND); } YY_BREAK case 172: YY_RULE_SETUP #line 238 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FRAC_SECOND"); DBG_RETURN(QC_TOKEN_FRAC_SECOND); } YY_BREAK case 173: YY_RULE_SETUP #line 239 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FROM"); DBG_RETURN(QC_TOKEN_FROM); } YY_BREAK case 174: YY_RULE_SETUP #line 240 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FULL"); DBG_RETURN(QC_TOKEN_FULL); } YY_BREAK case 175: YY_RULE_SETUP #line 241 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FULLTEXT"); DBG_RETURN(QC_TOKEN_FULLTEXT); } YY_BREAK case 176: YY_RULE_SETUP #line 242 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_FUNCTION"); DBG_RETURN(QC_TOKEN_FUNCTION); } YY_BREAK case 177: YY_RULE_SETUP #line 243 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GEOMETRYCOLLECTION");DBG_RETURN(QC_TOKEN_GEOMETRYCOLLECTION); } YY_BREAK case 178: YY_RULE_SETUP #line 244 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GEOMETRY"); DBG_RETURN(QC_TOKEN_GEOMETRY); } YY_BREAK case 179: YY_RULE_SETUP #line 245 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GET_FORMAT"); DBG_RETURN(QC_TOKEN_GET_FORMAT); } YY_BREAK case 180: YY_RULE_SETUP #line 246 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GLOBAL"); DBG_RETURN(QC_TOKEN_GLOBAL); } YY_BREAK case 181: YY_RULE_SETUP #line 247 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GRANT"); DBG_RETURN(QC_TOKEN_GRANT); } YY_BREAK case 182: YY_RULE_SETUP #line 248 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GRANTS"); DBG_RETURN(QC_TOKEN_GRANTS); } YY_BREAK case 183: YY_RULE_SETUP #line 249 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GROUP"); DBG_RETURN(QC_TOKEN_GROUP); } YY_BREAK case 184: YY_RULE_SETUP #line 250 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GROUP"); DBG_RETURN(QC_TOKEN_GROUP); } YY_BREAK case 185: YY_RULE_SETUP #line 251 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_GROUP_CONCAT"); DBG_RETURN(QC_TOKEN_GROUP_CONCAT); } YY_BREAK case 186: YY_RULE_SETUP #line 252 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HANDLER"); DBG_RETURN(QC_TOKEN_HANDLER); } YY_BREAK case 187: YY_RULE_SETUP #line 253 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HASH"); DBG_RETURN(QC_TOKEN_HASH); } YY_BREAK case 188: YY_RULE_SETUP #line 254 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HAVING"); DBG_RETURN(QC_TOKEN_HAVING); } YY_BREAK case 189: YY_RULE_SETUP #line 255 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HELP"); DBG_RETURN(QC_TOKEN_HELP); } YY_BREAK case 190: YY_RULE_SETUP #line 256 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HEX_NUM"); DBG_RETURN(QC_TOKEN_HEX_NUM); } YY_BREAK case 191: YY_RULE_SETUP #line 257 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HIGH_PRIORITY"); DBG_RETURN(QC_TOKEN_HIGH_PRIORITY); } YY_BREAK case 192: YY_RULE_SETUP #line 258 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HOST"); DBG_RETURN(QC_TOKEN_HOST); } YY_BREAK case 193: YY_RULE_SETUP #line 259 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HOSTS"); DBG_RETURN(QC_TOKEN_HOSTS); } YY_BREAK case 194: YY_RULE_SETUP #line 260 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HOUR_MICROSECOND"); DBG_RETURN(QC_TOKEN_HOUR_MICROSECOND); } YY_BREAK case 195: YY_RULE_SETUP #line 261 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HOUR_MINUTE"); DBG_RETURN(QC_TOKEN_HOUR_MINUTE); } YY_BREAK case 196: YY_RULE_SETUP #line 262 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HOUR_SECOND"); DBG_RETURN(QC_TOKEN_HOUR_SECOND); } YY_BREAK case 197: YY_RULE_SETUP #line 263 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_HOUR"); DBG_RETURN(QC_TOKEN_HOUR); } YY_BREAK case 198: YY_RULE_SETUP #line 264 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IDENT"); DBG_RETURN(QC_TOKEN_IDENT); } YY_BREAK case 199: YY_RULE_SETUP #line 265 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IDENTIFIED"); DBG_RETURN(QC_TOKEN_IDENTIFIED); } YY_BREAK case 200: YY_RULE_SETUP #line 266 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IDENT_QUOTED"); DBG_RETURN(QC_TOKEN_IDENT_QUOTED); } YY_BREAK case 201: YY_RULE_SETUP #line 267 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IF"); DBG_RETURN(QC_TOKEN_IF); } YY_BREAK case 202: YY_RULE_SETUP #line 268 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IGNORE"); DBG_RETURN(QC_TOKEN_IGNORE); } YY_BREAK case 203: YY_RULE_SETUP #line 269 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IGNORE_SERVER_IDS");DBG_RETURN(QC_TOKEN_IGNORE_SERVER_IDS); } YY_BREAK case 204: YY_RULE_SETUP #line 270 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IMPORT"); DBG_RETURN(QC_TOKEN_IMPORT); } YY_BREAK case 205: YY_RULE_SETUP #line 271 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INDEXES"); DBG_RETURN(QC_TOKEN_INDEXES); } YY_BREAK case 206: YY_RULE_SETUP #line 272 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INDEX"); DBG_RETURN(QC_TOKEN_INDEX); } YY_BREAK case 207: YY_RULE_SETUP #line 273 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INFILE"); DBG_RETURN(QC_TOKEN_INFILE); } YY_BREAK case 208: YY_RULE_SETUP #line 274 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INITIAL_SIZE"); DBG_RETURN(QC_TOKEN_INITIAL_SIZE); } YY_BREAK case 209: YY_RULE_SETUP #line 275 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INNER"); DBG_RETURN(QC_TOKEN_INNER); } YY_BREAK case 210: YY_RULE_SETUP #line 276 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INOUT"); DBG_RETURN(QC_TOKEN_INOUT); } YY_BREAK case 211: YY_RULE_SETUP #line 277 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INSENSITIVE"); DBG_RETURN(QC_TOKEN_INSENSITIVE); } YY_BREAK case 212: YY_RULE_SETUP #line 278 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INSERT"); DBG_RETURN(QC_TOKEN_INSERT); } YY_BREAK case 213: YY_RULE_SETUP #line 279 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INSERT_METHOD"); DBG_RETURN(QC_TOKEN_INSERT_METHOD); } YY_BREAK case 214: YY_RULE_SETUP #line 280 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INSTALL"); DBG_RETURN(QC_TOKEN_INSTALL); } YY_BREAK case 215: YY_RULE_SETUP #line 281 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INTERVAL"); DBG_RETURN(QC_TOKEN_INTERVAL); } YY_BREAK case 216: YY_RULE_SETUP #line 282 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INTO"); DBG_RETURN(QC_TOKEN_INTO); } YY_BREAK case 217: YY_RULE_SETUP #line 283 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INT"); DBG_RETURN(QC_TOKEN_INT); } YY_BREAK case 218: YY_RULE_SETUP #line 284 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_INVOKER"); DBG_RETURN(QC_TOKEN_INVOKER); } YY_BREAK case 219: YY_RULE_SETUP #line 285 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IN"); DBG_RETURN(QC_TOKEN_IN); } YY_BREAK case 220: YY_RULE_SETUP #line 286 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IO"); DBG_RETURN(QC_TOKEN_IO); } YY_BREAK case 221: YY_RULE_SETUP #line 287 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IPC"); DBG_RETURN(QC_TOKEN_IPC); } YY_BREAK case 222: YY_RULE_SETUP #line 288 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_IS"); DBG_RETURN(QC_TOKEN_IS); } YY_BREAK case 223: YY_RULE_SETUP #line 289 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ISOLATION"); DBG_RETURN(QC_TOKEN_ISOLATION); } YY_BREAK case 224: YY_RULE_SETUP #line 290 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ISSUER"); DBG_RETURN(QC_TOKEN_ISSUER); } YY_BREAK case 225: YY_RULE_SETUP #line 291 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ITERATE"); DBG_RETURN(QC_TOKEN_ITERATE); } YY_BREAK case 226: YY_RULE_SETUP #line 292 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_JOIN"); DBG_RETURN(QC_TOKEN_JOIN); } YY_BREAK case 227: YY_RULE_SETUP #line 293 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_KEYS"); DBG_RETURN(QC_TOKEN_KEYS); } YY_BREAK case 228: YY_RULE_SETUP #line 294 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_KEY_BLOCK_SIZE"); DBG_RETURN(QC_TOKEN_KEY_BLOCK_SIZE); } YY_BREAK case 229: YY_RULE_SETUP #line 295 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_KEY"); DBG_RETURN(QC_TOKEN_KEY); } YY_BREAK case 230: YY_RULE_SETUP #line 296 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_KILL"); DBG_RETURN(QC_TOKEN_KILL); } YY_BREAK case 231: YY_RULE_SETUP #line 297 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LANGUAGE"); DBG_RETURN(QC_TOKEN_LANGUAGE); } YY_BREAK case 232: YY_RULE_SETUP #line 298 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LAST"); DBG_RETURN(QC_TOKEN_LAST); } YY_BREAK case 233: YY_RULE_SETUP #line 299 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LEADING"); DBG_RETURN(QC_TOKEN_LEADING); } YY_BREAK case 234: YY_RULE_SETUP #line 300 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LEAVES"); DBG_RETURN(QC_TOKEN_LEAVES); } YY_BREAK case 235: YY_RULE_SETUP #line 301 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LEAVE"); DBG_RETURN(QC_TOKEN_LEAVE); } YY_BREAK case 236: YY_RULE_SETUP #line 302 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LEFT"); DBG_RETURN(QC_TOKEN_LEFT); } YY_BREAK case 237: YY_RULE_SETUP #line 303 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LESS"); DBG_RETURN(QC_TOKEN_LESS); } YY_BREAK case 238: YY_RULE_SETUP #line 304 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LEVEL"); DBG_RETURN(QC_TOKEN_LEVEL); } YY_BREAK case 239: YY_RULE_SETUP #line 305 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LEX_HOSTNAME"); DBG_RETURN(QC_TOKEN_LEX_HOSTNAME); } YY_BREAK case 240: YY_RULE_SETUP #line 306 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LIKE"); DBG_RETURN(QC_TOKEN_LIKE); } YY_BREAK case 241: YY_RULE_SETUP #line 307 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LIMIT"); DBG_RETURN(QC_TOKEN_LIMIT); } YY_BREAK case 242: YY_RULE_SETUP #line 308 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LINEAR"); DBG_RETURN(QC_TOKEN_LINEAR); } YY_BREAK case 243: YY_RULE_SETUP #line 309 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LINES"); DBG_RETURN(QC_TOKEN_LINES); } YY_BREAK case 244: YY_RULE_SETUP #line 310 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LINESTRING"); DBG_RETURN(QC_TOKEN_LINESTRING); } YY_BREAK case 245: YY_RULE_SETUP #line 311 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LIST"); DBG_RETURN(QC_TOKEN_LIST); } YY_BREAK case 246: YY_RULE_SETUP #line 312 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOAD"); DBG_RETURN(QC_TOKEN_LOAD); } YY_BREAK case 247: YY_RULE_SETUP #line 313 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOCAL"); DBG_RETURN(QC_TOKEN_LOCAL); } YY_BREAK case 248: YY_RULE_SETUP #line 314 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOCATOR"); DBG_RETURN(QC_TOKEN_LOCATOR); } YY_BREAK case 249: YY_RULE_SETUP #line 315 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOCKS"); DBG_RETURN(QC_TOKEN_LOCKS); } YY_BREAK case 250: YY_RULE_SETUP #line 316 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOCK"); DBG_RETURN(QC_TOKEN_LOCK); } YY_BREAK case 251: YY_RULE_SETUP #line 317 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOGFILE"); DBG_RETURN(QC_TOKEN_LOGFILE); } YY_BREAK case 252: YY_RULE_SETUP #line 318 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOGS"); DBG_RETURN(QC_TOKEN_LOGS); } YY_BREAK case 253: YY_RULE_SETUP #line 319 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LONGBLOB"); DBG_RETURN(QC_TOKEN_LONGBLOB); } YY_BREAK case 254: YY_RULE_SETUP #line 320 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LONGTEXT"); DBG_RETURN(QC_TOKEN_LONGTEXT); } YY_BREAK case 255: YY_RULE_SETUP #line 321 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LONG_NUM"); DBG_RETURN(QC_TOKEN_LONG_NUM); } YY_BREAK case 256: YY_RULE_SETUP #line 322 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LONG"); DBG_RETURN(QC_TOKEN_LONG); } YY_BREAK case 257: YY_RULE_SETUP #line 323 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOOP"); DBG_RETURN(QC_TOKEN_LOOP); } YY_BREAK case 258: YY_RULE_SETUP #line 324 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_LOW_PRIORITY"); DBG_RETURN(QC_TOKEN_LOW_PRIORITY); } YY_BREAK case 259: YY_RULE_SETUP #line 325 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_CONNECT_RETRY"); DBG_RETURN(QC_TOKEN_MASTER_CONNECT_RETRY); } YY_BREAK case 260: YY_RULE_SETUP #line 326 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_HOST"); DBG_RETURN(QC_TOKEN_MASTER_HOST); } YY_BREAK case 261: YY_RULE_SETUP #line 327 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_LOG_FILE"); DBG_RETURN(QC_TOKEN_MASTER_LOG_FILE); } YY_BREAK case 262: YY_RULE_SETUP #line 328 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_LOG_POS"); DBG_RETURN(QC_TOKEN_MASTER_LOG_POS); } YY_BREAK case 263: YY_RULE_SETUP #line 329 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_PASSWORD"); DBG_RETURN(QC_TOKEN_MASTER_PASSWORD); } YY_BREAK case 264: YY_RULE_SETUP #line 330 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_PORT"); DBG_RETURN(QC_TOKEN_MASTER_PORT); } YY_BREAK case 265: YY_RULE_SETUP #line 331 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SERVER_ID"); DBG_RETURN(QC_TOKEN_MASTER_SERVER_ID); } YY_BREAK case 266: YY_RULE_SETUP #line 332 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CAPATH");DBG_RETURN(QC_TOKEN_MASTER_SSL_CAPATH); } YY_BREAK case 267: YY_RULE_SETUP #line 333 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CA"); DBG_RETURN(QC_TOKEN_MASTER_SSL_CA); } YY_BREAK case 268: YY_RULE_SETUP #line 334 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CERT"); DBG_RETURN(QC_TOKEN_MASTER_SSL_CERT); } YY_BREAK case 269: YY_RULE_SETUP #line 335 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CIPHER");DBG_RETURN(QC_TOKEN_MASTER_SSL_CIPHER); } YY_BREAK case 270: YY_RULE_SETUP #line 336 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_KEY"); DBG_RETURN(QC_TOKEN_MASTER_SSL_KEY); } YY_BREAK case 271: YY_RULE_SETUP #line 337 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL"); DBG_RETURN(QC_TOKEN_MASTER_SSL); } YY_BREAK case 272: YY_RULE_SETUP #line 338 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT"); DBG_RETURN(QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT); } YY_BREAK case 273: YY_RULE_SETUP #line 339 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER"); DBG_RETURN(QC_TOKEN_MASTER); } YY_BREAK case 274: YY_RULE_SETUP #line 340 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_USER"); DBG_RETURN(QC_TOKEN_MASTER_USER); } YY_BREAK case 275: YY_RULE_SETUP #line 341 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_HEARTBEAT_PERIOD"); DBG_RETURN(QC_TOKEN_MASTER_HEARTBEAT_PERIOD); } YY_BREAK case 276: YY_RULE_SETUP #line 342 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MATCH"); DBG_RETURN(QC_TOKEN_MATCH); } YY_BREAK case 277: YY_RULE_SETUP #line 343 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_CONNECTIONS_PER_HOUR"); DBG_RETURN(QC_TOKEN_MAX_CONNECTIONS_PER_HOUR); } YY_BREAK case 278: YY_RULE_SETUP #line 344 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_QUERIES_PER_HOUR"); DBG_RETURN(QC_TOKEN_MAX_QUERIES_PER_HOUR); } YY_BREAK case 279: YY_RULE_SETUP #line 345 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_ROWS"); DBG_RETURN(QC_TOKEN_MAX_ROWS); } YY_BREAK case 280: YY_RULE_SETUP #line 346 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_SIZE"); DBG_RETURN(QC_TOKEN_MAX_SIZE); } YY_BREAK case 281: YY_RULE_SETUP #line 347 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX"); DBG_RETURN(QC_TOKEN_MAX); } YY_BREAK case 282: YY_RULE_SETUP #line 348 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_UPDATES_PER_HOUR"); DBG_RETURN(QC_TOKEN_MAX_UPDATES_PER_HOUR); } YY_BREAK case 283: YY_RULE_SETUP #line 349 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_USER_CONNECTIONS"); DBG_RETURN(QC_TOKEN_MAX_USER_CONNECTIONS); } YY_BREAK case 284: YY_RULE_SETUP #line 350 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MAX_VALUE"); DBG_RETURN(QC_TOKEN_MAX_VALUE); } YY_BREAK case 285: YY_RULE_SETUP #line 351 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUMBLOB"); DBG_RETURN(QC_TOKEN_MEDIUMBLOB); } YY_BREAK case 286: YY_RULE_SETUP #line 352 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUMINT"); DBG_RETURN(QC_TOKEN_MEDIUMINT); } YY_BREAK case 287: YY_RULE_SETUP #line 353 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUMTEXT"); DBG_RETURN(QC_TOKEN_MEDIUMTEXT); } YY_BREAK case 288: YY_RULE_SETUP #line 354 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUM"); DBG_RETURN(QC_TOKEN_MEDIUM); } YY_BREAK case 289: YY_RULE_SETUP #line 355 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MEMORY"); DBG_RETURN(QC_TOKEN_MEMORY); } YY_BREAK case 290: YY_RULE_SETUP #line 356 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MERGE"); DBG_RETURN(QC_TOKEN_MERGE); } YY_BREAK case 291: YY_RULE_SETUP #line 357 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MESSAGE_TEXT"); DBG_RETURN(QC_TOKEN_MESSAGE_TEXT); } YY_BREAK case 292: YY_RULE_SETUP #line 358 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MICROSECOND"); DBG_RETURN(QC_TOKEN_MICROSECOND); } YY_BREAK case 293: YY_RULE_SETUP #line 359 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MIGRATE"); DBG_RETURN(QC_TOKEN_MIGRATE); } YY_BREAK case 294: YY_RULE_SETUP #line 360 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MINUTE_MICROSECOND");DBG_RETURN(QC_TOKEN_MINUTE_MICROSECOND); } YY_BREAK case 295: YY_RULE_SETUP #line 361 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MINUTE_SECOND"); DBG_RETURN(QC_TOKEN_MINUTE_SECOND); } YY_BREAK case 296: YY_RULE_SETUP #line 362 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MINUTE"); DBG_RETURN(QC_TOKEN_MINUTE); } YY_BREAK case 297: YY_RULE_SETUP #line 363 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MIN_ROWS"); DBG_RETURN(QC_TOKEN_MIN_ROWS); } YY_BREAK case 298: YY_RULE_SETUP #line 364 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MIN"); DBG_RETURN(QC_TOKEN_MIN); } YY_BREAK case 299: YY_RULE_SETUP #line 365 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MODE"); DBG_RETURN(QC_TOKEN_MODE); } YY_BREAK case 300: YY_RULE_SETUP #line 366 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MODIFIES"); DBG_RETURN(QC_TOKEN_MODIFIES); } YY_BREAK case 301: YY_RULE_SETUP #line 367 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MODIFY"); DBG_RETURN(QC_TOKEN_MODIFY); } YY_BREAK case 302: YY_RULE_SETUP #line 368 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MOD"); DBG_RETURN(QC_TOKEN_MOD); } YY_BREAK case 303: YY_RULE_SETUP #line 369 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MONTH"); DBG_RETURN(QC_TOKEN_MONTH); } YY_BREAK case 304: YY_RULE_SETUP #line 370 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MULTILINESTRING"); DBG_RETURN(QC_TOKEN_MULTILINESTRING); } YY_BREAK case 305: YY_RULE_SETUP #line 371 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MULTIPOINT"); DBG_RETURN(QC_TOKEN_MULTIPOINT); } YY_BREAK case 306: YY_RULE_SETUP #line 372 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MULTIPOLYGON"); DBG_RETURN(QC_TOKEN_MULTIPOLYGON); } YY_BREAK case 307: YY_RULE_SETUP #line 373 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MUTEX"); DBG_RETURN(QC_TOKEN_MUTEX); } YY_BREAK case 308: YY_RULE_SETUP #line 374 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_MYSQL_ERRNO"); DBG_RETURN(QC_TOKEN_MYSQL_ERRNO); } YY_BREAK case 309: YY_RULE_SETUP #line 375 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NAMES"); DBG_RETURN(QC_TOKEN_NAMES); } YY_BREAK case 310: YY_RULE_SETUP #line 376 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NAME"); DBG_RETURN(QC_TOKEN_NAME); } YY_BREAK case 311: YY_RULE_SETUP #line 377 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NATIONAL"); DBG_RETURN(QC_TOKEN_NATIONAL); } YY_BREAK case 312: YY_RULE_SETUP #line 378 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NATURAL"); DBG_RETURN(QC_TOKEN_NATURAL); } YY_BREAK case 313: YY_RULE_SETUP #line 379 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NCHAR_STRING"); DBG_RETURN(QC_TOKEN_NCHAR_STRING); } YY_BREAK case 314: YY_RULE_SETUP #line 380 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NCHAR"); DBG_RETURN(QC_TOKEN_NCHAR); } YY_BREAK case 315: YY_RULE_SETUP #line 381 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NDBCLUSTER"); DBG_RETURN(QC_TOKEN_NDBCLUSTER); } YY_BREAK case 316: YY_RULE_SETUP #line 382 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NEG"); DBG_RETURN(QC_TOKEN_NEG); } YY_BREAK case 317: YY_RULE_SETUP #line 383 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NEW"); DBG_RETURN(QC_TOKEN_NEW); } YY_BREAK case 318: YY_RULE_SETUP #line 384 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NEXT"); DBG_RETURN(QC_TOKEN_NEXT); } YY_BREAK case 319: YY_RULE_SETUP #line 385 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NODEGROUP"); DBG_RETURN(QC_TOKEN_NODEGROUP); } YY_BREAK case 320: YY_RULE_SETUP #line 386 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NONE"); DBG_RETURN(QC_TOKEN_NONE); } YY_BREAK case 321: YY_RULE_SETUP #line 387 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NOT"); DBG_RETURN(QC_TOKEN_NOT); } YY_BREAK case 322: YY_RULE_SETUP #line 388 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NOW"); DBG_RETURN(QC_TOKEN_NOW); } YY_BREAK case 323: YY_RULE_SETUP #line 389 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NO"); DBG_RETURN(QC_TOKEN_NO); } YY_BREAK case 324: YY_RULE_SETUP #line 390 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NO_WAIT"); DBG_RETURN(QC_TOKEN_NO_WAIT); } YY_BREAK case 325: YY_RULE_SETUP #line 391 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NO_WRITE_TO_BINLOG");DBG_RETURN(QC_TOKEN_NO_WRITE_TO_BINLOG); } YY_BREAK case 326: YY_RULE_SETUP #line 392 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NULL"); DBG_RETURN(QC_TOKEN_NULL); } YY_BREAK case 327: YY_RULE_SETUP #line 393 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NUM"); DBG_RETURN(QC_TOKEN_NUM); } YY_BREAK case 328: YY_RULE_SETUP #line 394 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NUMERIC"); DBG_RETURN(QC_TOKEN_NUMERIC); } YY_BREAK case 329: YY_RULE_SETUP #line 395 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_NVARCHAR"); DBG_RETURN(QC_TOKEN_NVARCHAR); } YY_BREAK case 330: YY_RULE_SETUP #line 396 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OFFSET"); DBG_RETURN(QC_TOKEN_OFFSET); } YY_BREAK case 331: YY_RULE_SETUP #line 397 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OLD_PASSWORD"); DBG_RETURN(QC_TOKEN_OLD_PASSWORD); } YY_BREAK case 332: YY_RULE_SETUP #line 398 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ON"); DBG_RETURN(QC_TOKEN_ON); } YY_BREAK case 333: YY_RULE_SETUP #line 399 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ONE_SHOT"); DBG_RETURN(QC_TOKEN_ONE_SHOT); } YY_BREAK case 334: YY_RULE_SETUP #line 400 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ONE"); DBG_RETURN(QC_TOKEN_ONE); } YY_BREAK case 335: YY_RULE_SETUP #line 401 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OPEN"); DBG_RETURN(QC_TOKEN_OPEN); } YY_BREAK case 336: YY_RULE_SETUP #line 402 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OPTIMIZE"); DBG_RETURN(QC_TOKEN_OPTIMIZE); } YY_BREAK case 337: YY_RULE_SETUP #line 403 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OPTIONS"); DBG_RETURN(QC_TOKEN_OPTIONS); } YY_BREAK case 338: YY_RULE_SETUP #line 404 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OPTION"); DBG_RETURN(QC_TOKEN_OPTION); } YY_BREAK case 339: YY_RULE_SETUP #line 405 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OPTIONALLY"); DBG_RETURN(QC_TOKEN_OPTIONALLY); } YY_BREAK case 340: YY_RULE_SETUP #line 406 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ORDER"); DBG_RETURN(QC_TOKEN_ORDER); } YY_BREAK case 341: YY_RULE_SETUP #line 407 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OR"); DBG_RETURN(QC_TOKEN_OR); } YY_BREAK case 342: YY_RULE_SETUP #line 408 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OUTER"); DBG_RETURN(QC_TOKEN_OUTER); } YY_BREAK case 343: YY_RULE_SETUP #line 409 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OUTFILE"); DBG_RETURN(QC_TOKEN_OUTFILE); } YY_BREAK case 344: YY_RULE_SETUP #line 410 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OUT"); DBG_RETURN(QC_TOKEN_OUT); } YY_BREAK case 345: YY_RULE_SETUP #line 411 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_OWNER"); DBG_RETURN(QC_TOKEN_OWNER); } YY_BREAK case 346: YY_RULE_SETUP #line 412 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PACK_KEYS"); DBG_RETURN(QC_TOKEN_PACK_KEYS); } YY_BREAK case 347: YY_RULE_SETUP #line 413 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PAGE"); DBG_RETURN(QC_TOKEN_PAGE); } YY_BREAK case 348: YY_RULE_SETUP #line 414 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PARAM_MARKER"); DBG_RETURN(QC_TOKEN_PARAM_MARKER); } YY_BREAK case 349: YY_RULE_SETUP #line 415 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PARSER"); DBG_RETURN(QC_TOKEN_PARSER); } YY_BREAK case 350: YY_RULE_SETUP #line 416 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PARTIAL"); DBG_RETURN(QC_TOKEN_PARTIAL); } YY_BREAK case 351: YY_RULE_SETUP #line 417 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PARTITIONING"); DBG_RETURN(QC_TOKEN_PARTITIONING); } YY_BREAK case 352: YY_RULE_SETUP #line 418 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PARTITIONS"); DBG_RETURN(QC_TOKEN_PARTITIONS); } YY_BREAK case 353: YY_RULE_SETUP #line 419 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PARTITION"); DBG_RETURN(QC_TOKEN_PARTITION); } YY_BREAK case 354: YY_RULE_SETUP #line 420 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PASSWORD"); DBG_RETURN(QC_TOKEN_PASSWORD); } YY_BREAK case 355: YY_RULE_SETUP #line 421 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PHASE"); DBG_RETURN(QC_TOKEN_PHASE); } YY_BREAK case 356: YY_RULE_SETUP #line 422 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PLUGINS"); DBG_RETURN(QC_TOKEN_PLUGINS); } YY_BREAK case 357: YY_RULE_SETUP #line 423 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PLUGIN"); DBG_RETURN(QC_TOKEN_PLUGIN); } YY_BREAK case 358: YY_RULE_SETUP #line 424 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_POINT"); DBG_RETURN(QC_TOKEN_POINT); } YY_BREAK case 359: YY_RULE_SETUP #line 425 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_POLYGON"); DBG_RETURN(QC_TOKEN_POLYGON); } YY_BREAK case 360: YY_RULE_SETUP #line 426 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PORT"); DBG_RETURN(QC_TOKEN_PORT); } YY_BREAK case 361: YY_RULE_SETUP #line 427 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_POSITION"); DBG_RETURN(QC_TOKEN_POSITION); } YY_BREAK case 362: YY_RULE_SETUP #line 428 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PRECISION"); DBG_RETURN(QC_TOKEN_PRECISION); } YY_BREAK case 363: YY_RULE_SETUP #line 429 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PREPARE"); DBG_RETURN(QC_TOKEN_PREPARE); } YY_BREAK case 364: YY_RULE_SETUP #line 430 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PRESERVE"); DBG_RETURN(QC_TOKEN_PRESERVE); } YY_BREAK case 365: YY_RULE_SETUP #line 431 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PREV"); DBG_RETURN(QC_TOKEN_PREV); } YY_BREAK case 366: YY_RULE_SETUP #line 432 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PRIMARY"); DBG_RETURN(QC_TOKEN_PRIMARY); } YY_BREAK case 367: YY_RULE_SETUP #line 433 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PRIVILEGES"); DBG_RETURN(QC_TOKEN_PRIVILEGES); } YY_BREAK case 368: YY_RULE_SETUP #line 434 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PROCEDURE"); DBG_RETURN(QC_TOKEN_PROCEDURE); } YY_BREAK case 369: YY_RULE_SETUP #line 435 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PROCESS"); DBG_RETURN(QC_TOKEN_PROCESS); } YY_BREAK case 370: YY_RULE_SETUP #line 436 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PROCESSLIST"); DBG_RETURN(QC_TOKEN_PROCESSLIST); } YY_BREAK case 371: YY_RULE_SETUP #line 437 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PROFILE"); DBG_RETURN(QC_TOKEN_PROFILE); } YY_BREAK case 372: YY_RULE_SETUP #line 438 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PROFILES"); DBG_RETURN(QC_TOKEN_PROFILES); } YY_BREAK case 373: YY_RULE_SETUP #line 439 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_PURGE"); DBG_RETURN(QC_TOKEN_PURGE); } YY_BREAK case 374: YY_RULE_SETUP #line 440 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_QUARTER"); DBG_RETURN(QC_TOKEN_QUARTER); } YY_BREAK case 375: YY_RULE_SETUP #line 441 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_QUERY"); DBG_RETURN(QC_TOKEN_QUERY); } YY_BREAK case 376: YY_RULE_SETUP #line 442 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_QUICK"); DBG_RETURN(QC_TOKEN_QUICK); } YY_BREAK case 377: YY_RULE_SETUP #line 443 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RANGE"); DBG_RETURN(QC_TOKEN_RANGE); } YY_BREAK case 378: YY_RULE_SETUP #line 444 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_READS"); DBG_RETURN(QC_TOKEN_READS); } YY_BREAK case 379: YY_RULE_SETUP #line 445 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_READ_ONLY"); DBG_RETURN(QC_TOKEN_READ_ONLY); } YY_BREAK case 380: YY_RULE_SETUP #line 446 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_READ"); DBG_RETURN(QC_TOKEN_READ); } YY_BREAK case 381: YY_RULE_SETUP #line 447 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_READ_WRITE"); DBG_RETURN(QC_TOKEN_READ_WRITE); } YY_BREAK case 382: YY_RULE_SETUP #line 448 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REAL"); DBG_RETURN(QC_TOKEN_REAL); } YY_BREAK case 383: YY_RULE_SETUP #line 449 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REBUILD"); DBG_RETURN(QC_TOKEN_REBUILD); } YY_BREAK case 384: YY_RULE_SETUP #line 450 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RECOVER"); DBG_RETURN(QC_TOKEN_RECOVER); } YY_BREAK case 385: YY_RULE_SETUP #line 451 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REDOFILE"); DBG_RETURN(QC_TOKEN_REDOFILE); } YY_BREAK case 386: YY_RULE_SETUP #line 452 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REDO_BUFFER_SIZE"); DBG_RETURN(QC_TOKEN_REDO_BUFFER_SIZE); } YY_BREAK case 387: YY_RULE_SETUP #line 453 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REDUNDANT"); DBG_RETURN(QC_TOKEN_REDUNDANT); } YY_BREAK case 388: YY_RULE_SETUP #line 454 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REFERENCES"); DBG_RETURN(QC_TOKEN_REFERENCES); } YY_BREAK case 389: YY_RULE_SETUP #line 455 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REGEXP"); DBG_RETURN(QC_TOKEN_REGEXP); } YY_BREAK case 390: YY_RULE_SETUP #line 456 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RELAYLOG"); DBG_RETURN(QC_TOKEN_RELAYLOG); } YY_BREAK case 391: YY_RULE_SETUP #line 457 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RELAY_LOG_FILE"); DBG_RETURN(QC_TOKEN_RELAY_LOG_FILE); } YY_BREAK case 392: YY_RULE_SETUP #line 458 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RELAY_LOG_POS"); DBG_RETURN(QC_TOKEN_RELAY_LOG_POS); } YY_BREAK case 393: YY_RULE_SETUP #line 459 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RELAY_THREAD"); DBG_RETURN(QC_TOKEN_RELAY_THREAD); } YY_BREAK case 394: YY_RULE_SETUP #line 460 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RELEASE"); DBG_RETURN(QC_TOKEN_RELEASE); } YY_BREAK case 395: YY_RULE_SETUP #line 461 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RELOAD"); DBG_RETURN(QC_TOKEN_RELOAD); } YY_BREAK case 396: YY_RULE_SETUP #line 462 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REMOVE"); DBG_RETURN(QC_TOKEN_REMOVE); } YY_BREAK case 397: YY_RULE_SETUP #line 463 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RENAME"); DBG_RETURN(QC_TOKEN_RENAME); } YY_BREAK case 398: YY_RULE_SETUP #line 464 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REORGANIZE"); DBG_RETURN(QC_TOKEN_REORGANIZE); } YY_BREAK case 399: YY_RULE_SETUP #line 465 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REPAIR"); DBG_RETURN(QC_TOKEN_REPAIR); } YY_BREAK case 400: YY_RULE_SETUP #line 466 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REPEATABLE"); DBG_RETURN(QC_TOKEN_REPEATABLE); } YY_BREAK case 401: YY_RULE_SETUP #line 467 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REPEAT"); DBG_RETURN(QC_TOKEN_REPEAT); } YY_BREAK case 402: YY_RULE_SETUP #line 468 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REPLACE"); DBG_RETURN(QC_TOKEN_REPLACE); } YY_BREAK case 403: YY_RULE_SETUP #line 469 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REPLICATION"); DBG_RETURN(QC_TOKEN_REPLICATION); } YY_BREAK case 404: YY_RULE_SETUP #line 470 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REQUIRE"); DBG_RETURN(QC_TOKEN_REQUIRE); } YY_BREAK case 405: YY_RULE_SETUP #line 471 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RESET"); DBG_RETURN(QC_TOKEN_RESET); } YY_BREAK case 406: YY_RULE_SETUP #line 472 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RESIGNAL"); DBG_RETURN(QC_TOKEN_RESIGNAL); } YY_BREAK case 407: YY_RULE_SETUP #line 473 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RESOURCES"); DBG_RETURN(QC_TOKEN_RESOURCES); } YY_BREAK case 408: YY_RULE_SETUP #line 474 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RESTORE"); DBG_RETURN(QC_TOKEN_RESTORE); } YY_BREAK case 409: YY_RULE_SETUP #line 475 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RESTRICT"); DBG_RETURN(QC_TOKEN_RESTRICT); } YY_BREAK case 410: YY_RULE_SETUP #line 476 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RESUME"); DBG_RETURN(QC_TOKEN_RESUME); } YY_BREAK case 411: YY_RULE_SETUP #line 477 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RETURNS"); DBG_RETURN(QC_TOKEN_RETURNS); } YY_BREAK case 412: YY_RULE_SETUP #line 478 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RETURN"); DBG_RETURN(QC_TOKEN_RETURN); } YY_BREAK case 413: YY_RULE_SETUP #line 479 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_REVOKE"); DBG_RETURN(QC_TOKEN_REVOKE); } YY_BREAK case 414: YY_RULE_SETUP #line 480 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RIGHT"); DBG_RETURN(QC_TOKEN_RIGHT); } YY_BREAK case 415: YY_RULE_SETUP #line 481 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ROLLBACK"); DBG_RETURN(QC_TOKEN_ROLLBACK); } YY_BREAK case 416: YY_RULE_SETUP #line 482 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ROLLUP"); DBG_RETURN(QC_TOKEN_ROLLUP); } YY_BREAK case 417: YY_RULE_SETUP #line 483 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ROUTINE"); DBG_RETURN(QC_TOKEN_ROUTINE); } YY_BREAK case 418: YY_RULE_SETUP #line 484 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ROWS"); DBG_RETURN(QC_TOKEN_ROWS); } YY_BREAK case 419: YY_RULE_SETUP #line 485 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ROW_FORMAT"); DBG_RETURN(QC_TOKEN_ROW_FORMAT); } YY_BREAK case 420: YY_RULE_SETUP #line 486 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ROW"); DBG_RETURN(QC_TOKEN_ROW); } YY_BREAK case 421: YY_RULE_SETUP #line 487 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_RTREE"); DBG_RETURN(QC_TOKEN_RTREE); } YY_BREAK case 422: YY_RULE_SETUP #line 488 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SAVEPOINT"); DBG_RETURN(QC_TOKEN_SAVEPOINT); } YY_BREAK case 423: YY_RULE_SETUP #line 489 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SCHEDULE"); DBG_RETURN(QC_TOKEN_SCHEDULE); } YY_BREAK case 424: YY_RULE_SETUP #line 490 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SCHEMA_NAME"); DBG_RETURN(QC_TOKEN_SCHEMA_NAME); } YY_BREAK case 425: YY_RULE_SETUP #line 491 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SECOND_MICROSECOND"); DBG_RETURN(QC_TOKEN_SECOND_MICROSECOND); } YY_BREAK case 426: YY_RULE_SETUP #line 492 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SECOND"); DBG_RETURN(QC_TOKEN_SECOND); } YY_BREAK case 427: YY_RULE_SETUP #line 493 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SECURITY"); DBG_RETURN(QC_TOKEN_SECURITY); } YY_BREAK case 428: YY_RULE_SETUP #line 494 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SELECT"); DBG_RETURN(QC_TOKEN_SELECT); } YY_BREAK case 429: YY_RULE_SETUP #line 495 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SENSITIVE"); DBG_RETURN(QC_TOKEN_SENSITIVE); } YY_BREAK case 430: YY_RULE_SETUP #line 496 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SEPARATOR"); DBG_RETURN(QC_TOKEN_SEPARATOR); } YY_BREAK case 431: YY_RULE_SETUP #line 497 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SERIALIZABLE"); DBG_RETURN(QC_TOKEN_SERIALIZABLE); } YY_BREAK case 432: YY_RULE_SETUP #line 498 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SERIAL"); DBG_RETURN(QC_TOKEN_SERIAL); } YY_BREAK case 433: YY_RULE_SETUP #line 499 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SESSION"); DBG_RETURN(QC_TOKEN_SESSION); } YY_BREAK case 434: YY_RULE_SETUP #line 500 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SERVER"); DBG_RETURN(QC_TOKEN_SERVER); } YY_BREAK case 435: YY_RULE_SETUP #line 501 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SERVER_OPTIONS"); DBG_RETURN(QC_TOKEN_SERVER_OPTIONS); } YY_BREAK case 436: YY_RULE_SETUP #line 502 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SET"); DBG_RETURN(QC_TOKEN_SET); } YY_BREAK case 437: YY_RULE_SETUP #line 503 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SHARE"); DBG_RETURN(QC_TOKEN_SHARE); } YY_BREAK case 438: YY_RULE_SETUP #line 504 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SHIFT_LEFT"); DBG_RETURN(QC_TOKEN_SHIFT_LEFT); } YY_BREAK case 439: YY_RULE_SETUP #line 505 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SHIFT_RIGHT"); DBG_RETURN(QC_TOKEN_SHIFT_RIGHT); } YY_BREAK case 440: YY_RULE_SETUP #line 506 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SHOW"); DBG_RETURN(QC_TOKEN_SHOW); } YY_BREAK case 441: YY_RULE_SETUP #line 507 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SHUTDOWN"); DBG_RETURN(QC_TOKEN_SHUTDOWN); } YY_BREAK case 442: YY_RULE_SETUP #line 508 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SIGNAL"); DBG_RETURN(QC_TOKEN_SIGNAL); } YY_BREAK case 443: YY_RULE_SETUP #line 509 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SIGNED"); DBG_RETURN(QC_TOKEN_SIGNED); } YY_BREAK case 444: YY_RULE_SETUP #line 510 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SIMPLE"); DBG_RETURN(QC_TOKEN_SIMPLE); } YY_BREAK case 445: YY_RULE_SETUP #line 511 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SLAVE"); DBG_RETURN(QC_TOKEN_SLAVE); } YY_BREAK case 446: YY_RULE_SETUP #line 512 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SMALLINT"); DBG_RETURN(QC_TOKEN_SMALLINT); } YY_BREAK case 447: YY_RULE_SETUP #line 513 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SNAPSHOT"); DBG_RETURN(QC_TOKEN_SNAPSHOT); } YY_BREAK case 448: YY_RULE_SETUP #line 514 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SOCKET"); DBG_RETURN(QC_TOKEN_SOCKET); } YY_BREAK case 449: YY_RULE_SETUP #line 515 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SONAME"); DBG_RETURN(QC_TOKEN_SONAME); } YY_BREAK case 450: YY_RULE_SETUP #line 516 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SOUNDS"); DBG_RETURN(QC_TOKEN_SOUNDS); } YY_BREAK case 451: YY_RULE_SETUP #line 517 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SOURCE"); DBG_RETURN(QC_TOKEN_SOURCE); } YY_BREAK case 452: YY_RULE_SETUP #line 518 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SPATIAL"); DBG_RETURN(QC_TOKEN_SPATIAL); } YY_BREAK case 453: YY_RULE_SETUP #line 519 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SPECIFIC"); DBG_RETURN(QC_TOKEN_SPECIFIC); } YY_BREAK case 454: YY_RULE_SETUP #line 520 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQLEXCEPTION"); DBG_RETURN(QC_TOKEN_SQLEXCEPTION); } YY_BREAK case 455: YY_RULE_SETUP #line 521 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQLSTATE"); DBG_RETURN(QC_TOKEN_SQLSTATE); } YY_BREAK case 456: YY_RULE_SETUP #line 522 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQLWARNING"); DBG_RETURN(QC_TOKEN_SQLWARNING); } YY_BREAK case 457: YY_RULE_SETUP #line 523 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_BIG_RESULT"); DBG_RETURN(QC_TOKEN_SQL_BIG_RESULT); } YY_BREAK case 458: YY_RULE_SETUP #line 524 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_BUFFER_RESULT");DBG_RETURN(QC_TOKEN_SQL_BUFFER_RESULT); } YY_BREAK case 459: YY_RULE_SETUP #line 525 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_CACHE"); DBG_RETURN(QC_TOKEN_SQL_CACHE); } YY_BREAK case 460: YY_RULE_SETUP #line 526 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_CALC_FOUND_ROWS"); DBG_RETURN(QC_TOKEN_SQL_CALC_FOUND_ROWS); } YY_BREAK case 461: YY_RULE_SETUP #line 527 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_NO_CACHE"); DBG_RETURN(QC_TOKEN_SQL_NO_CACHE); } YY_BREAK case 462: YY_RULE_SETUP #line 528 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_SMALL_RESULT"); DBG_RETURN(QC_TOKEN_SQL_SMALL_RESULT); } YY_BREAK case 463: YY_RULE_SETUP #line 529 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL"); DBG_RETURN(QC_TOKEN_SQL); } YY_BREAK case 464: YY_RULE_SETUP #line 530 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SQL_THREAD"); DBG_RETURN(QC_TOKEN_SQL_THREAD); } YY_BREAK case 465: YY_RULE_SETUP #line 531 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SSL"); DBG_RETURN(QC_TOKEN_SSL); } YY_BREAK case 466: YY_RULE_SETUP #line 532 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STARTING"); DBG_RETURN(QC_TOKEN_STARTING); } YY_BREAK case 467: YY_RULE_SETUP #line 533 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STARTS"); DBG_RETURN(QC_TOKEN_STARTS); } YY_BREAK case 468: YY_RULE_SETUP #line 534 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_START"); DBG_RETURN(QC_TOKEN_START); } YY_BREAK case 469: YY_RULE_SETUP #line 535 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STATUS"); DBG_RETURN(QC_TOKEN_STATUS); } YY_BREAK case 470: YY_RULE_SETUP #line 536 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STDDEV_SAMP"); DBG_RETURN(QC_TOKEN_STDDEV_SAMP); } YY_BREAK case 471: YY_RULE_SETUP #line 537 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STD"); DBG_RETURN(QC_TOKEN_STD); } YY_BREAK case 472: YY_RULE_SETUP #line 538 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STOP"); DBG_RETURN(QC_TOKEN_STOP); } YY_BREAK case 473: YY_RULE_SETUP #line 539 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STORAGE"); DBG_RETURN(QC_TOKEN_STORAGE); } YY_BREAK case 474: YY_RULE_SETUP #line 540 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STRAIGHT_JOIN");DBG_RETURN(QC_TOKEN_STRAIGHT_JOIN); } YY_BREAK case 475: YY_RULE_SETUP #line 541 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } YY_BREAK case 476: YY_RULE_SETUP #line 542 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUBCLASS_ORIGIN");DBG_RETURN(QC_TOKEN_SUBCLASS_ORIGIN); } YY_BREAK case 477: YY_RULE_SETUP #line 543 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUBDATE"); DBG_RETURN(QC_TOKEN_SUBDATE); } YY_BREAK case 478: YY_RULE_SETUP #line 544 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUBJECT"); DBG_RETURN(QC_TOKEN_SUBJECT); } YY_BREAK case 479: YY_RULE_SETUP #line 545 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUBPARTITIONS");DBG_RETURN(QC_TOKEN_SUBPARTITIONS); } YY_BREAK case 480: YY_RULE_SETUP #line 546 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUBPARTITION"); DBG_RETURN(QC_TOKEN_SUBPARTITION); } YY_BREAK case 481: YY_RULE_SETUP #line 547 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUBSTRING"); DBG_RETURN(QC_TOKEN_SUBSTRING); } YY_BREAK case 482: YY_RULE_SETUP #line 548 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUM"); DBG_RETURN(QC_TOKEN_SUM); } YY_BREAK case 483: YY_RULE_SETUP #line 549 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUPER"); DBG_RETURN(QC_TOKEN_SUPER); } YY_BREAK case 484: YY_RULE_SETUP #line 550 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SUSPEND"); DBG_RETURN(QC_TOKEN_SUSPEND); } YY_BREAK case 485: YY_RULE_SETUP #line 551 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SWAPS"); DBG_RETURN(QC_TOKEN_SWAPS); } YY_BREAK case 486: YY_RULE_SETUP #line 552 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SWITCHES"); DBG_RETURN(QC_TOKEN_SWITCHES); } YY_BREAK case 487: YY_RULE_SETUP #line 553 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_SYSDATE"); DBG_RETURN(QC_TOKEN_SYSDATE); } YY_BREAK case 488: YY_RULE_SETUP #line 554 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TABLES"); DBG_RETURN(QC_TOKEN_TABLES); } YY_BREAK case 489: YY_RULE_SETUP #line 555 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TABLESPACE"); DBG_RETURN(QC_TOKEN_TABLESPACE); } YY_BREAK case 490: YY_RULE_SETUP #line 556 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TABLE_REF_PRIORITY");DBG_RETURN(QC_TOKEN_TABLE_REF_PRIORITY); } YY_BREAK case 491: YY_RULE_SETUP #line 557 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TABLE"); DBG_RETURN(QC_TOKEN_TABLE); } YY_BREAK case 492: YY_RULE_SETUP #line 558 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TABLE_CHECKSUM");DBG_RETURN(QC_TOKEN_TABLE_CHECKSUM); } YY_BREAK case 493: YY_RULE_SETUP #line 559 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TABLE_NAME"); DBG_RETURN(QC_TOKEN_TABLE_NAME); } YY_BREAK case 494: YY_RULE_SETUP #line 560 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TEMPORARY"); DBG_RETURN(QC_TOKEN_TEMPORARY); } YY_BREAK case 495: YY_RULE_SETUP #line 561 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TEMPTABLE"); DBG_RETURN(QC_TOKEN_TEMPTABLE); } YY_BREAK case 496: YY_RULE_SETUP #line 562 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TERMINATED"); DBG_RETURN(QC_TOKEN_TERMINATED); } YY_BREAK case 497: YY_RULE_SETUP #line 563 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TEXT_STRING"); DBG_RETURN(QC_TOKEN_TEXT_STRING); } YY_BREAK case 498: YY_RULE_SETUP #line 564 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TEXT"); DBG_RETURN(QC_TOKEN_TEXT); } YY_BREAK case 499: YY_RULE_SETUP #line 565 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_THAN"); DBG_RETURN(QC_TOKEN_THAN); } YY_BREAK case 500: YY_RULE_SETUP #line 566 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_THEN"); DBG_RETURN(QC_TOKEN_THEN); } YY_BREAK case 501: YY_RULE_SETUP #line 567 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TIMESTAMP"); DBG_RETURN(QC_TOKEN_TIMESTAMP); } YY_BREAK case 502: YY_RULE_SETUP #line 568 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TIMESTAMP_ADD");DBG_RETURN(QC_TOKEN_TIMESTAMP_ADD); } YY_BREAK case 503: YY_RULE_SETUP #line 569 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TIMESTAMP_DIFF");DBG_RETURN(QC_TOKEN_TIMESTAMP_DIFF); } YY_BREAK case 504: YY_RULE_SETUP #line 570 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TIME"); DBG_RETURN(QC_TOKEN_TIME); } YY_BREAK case 505: YY_RULE_SETUP #line 571 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TINYBLOB"); DBG_RETURN(QC_TOKEN_TINYBLOB); } YY_BREAK case 506: YY_RULE_SETUP #line 572 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TINYINT"); DBG_RETURN(QC_TOKEN_TINYINT); } YY_BREAK case 507: YY_RULE_SETUP #line 573 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TINYTEXT"); DBG_RETURN(QC_TOKEN_TINYTEXT); } YY_BREAK case 508: YY_RULE_SETUP #line 574 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TO"); DBG_RETURN(QC_TOKEN_TO); } YY_BREAK case 509: YY_RULE_SETUP #line 575 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRAILING"); DBG_RETURN(QC_TOKEN_TRAILING); } YY_BREAK case 510: YY_RULE_SETUP #line 576 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRANSACTION"); DBG_RETURN(QC_TOKEN_TRANSACTION); } YY_BREAK case 511: YY_RULE_SETUP #line 577 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRIGGERS"); DBG_RETURN(QC_TOKEN_TRIGGERS); } YY_BREAK case 512: YY_RULE_SETUP #line 578 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRIGGER"); DBG_RETURN(QC_TOKEN_TRIGGER); } YY_BREAK case 513: YY_RULE_SETUP #line 579 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRIM"); DBG_RETURN(QC_TOKEN_TRIM); } YY_BREAK case 514: YY_RULE_SETUP #line 580 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRUE"); DBG_RETURN(QC_TOKEN_TRUE); } YY_BREAK case 515: YY_RULE_SETUP #line 581 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TRUNCATE"); DBG_RETURN(QC_TOKEN_TRUNCATE); } YY_BREAK case 516: YY_RULE_SETUP #line 582 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TYPES"); DBG_RETURN(QC_TOKEN_TYPES); } YY_BREAK case 517: YY_RULE_SETUP #line 583 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_TYPE"); DBG_RETURN(QC_TOKEN_TYPE); } YY_BREAK case 518: YY_RULE_SETUP #line 584 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UDF_RETURNS"); DBG_RETURN(QC_TOKEN_UDF_RETURNS); } YY_BREAK case 519: YY_RULE_SETUP #line 585 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ULONGLONG_NUM");DBG_RETURN(QC_TOKEN_ULONGLONG_NUM); } YY_BREAK case 520: YY_RULE_SETUP #line 586 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNCOMMITTED"); DBG_RETURN(QC_TOKEN_UNCOMMITTED); } YY_BREAK case 521: YY_RULE_SETUP #line 587 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNDEFINED"); DBG_RETURN(QC_TOKEN_UNDEFINED); } YY_BREAK case 522: YY_RULE_SETUP #line 588 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNDERSCORE_CHARSET");DBG_RETURN(QC_TOKEN_UNDERSCORE_CHARSET); } YY_BREAK case 523: YY_RULE_SETUP #line 589 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNDOFILE"); DBG_RETURN(QC_TOKEN_UNDOFILE); } YY_BREAK case 524: YY_RULE_SETUP #line 590 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNDO_BUFFER_SIZE");DBG_RETURN(QC_TOKEN_UNDO_BUFFER_SIZE); } YY_BREAK case 525: YY_RULE_SETUP #line 591 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNDO"); DBG_RETURN(QC_TOKEN_UNDO); } YY_BREAK case 526: YY_RULE_SETUP #line 592 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNICODE"); DBG_RETURN(QC_TOKEN_UNICODE); } YY_BREAK case 527: YY_RULE_SETUP #line 593 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNINSTALL"); DBG_RETURN(QC_TOKEN_UNINSTALL); } YY_BREAK case 528: YY_RULE_SETUP #line 594 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNION"); DBG_RETURN(QC_TOKEN_UNION); } YY_BREAK case 529: YY_RULE_SETUP #line 595 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNIQUE"); DBG_RETURN(QC_TOKEN_UNIQUE); } YY_BREAK case 530: YY_RULE_SETUP #line 596 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNKNOWN"); DBG_RETURN(QC_TOKEN_UNKNOWN); } YY_BREAK case 531: YY_RULE_SETUP #line 597 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNLOCK"); DBG_RETURN(QC_TOKEN_UNLOCK); } YY_BREAK case 532: YY_RULE_SETUP #line 598 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNSIGNED"); DBG_RETURN(QC_TOKEN_UNSIGNED); } YY_BREAK case 533: YY_RULE_SETUP #line 599 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UNTIL"); DBG_RETURN(QC_TOKEN_UNTIL); } YY_BREAK case 534: YY_RULE_SETUP #line 600 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UPDATE"); DBG_RETURN(QC_TOKEN_UPDATE); } YY_BREAK case 535: YY_RULE_SETUP #line 601 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UPGRADE"); DBG_RETURN(QC_TOKEN_UPGRADE); } YY_BREAK case 536: YY_RULE_SETUP #line 602 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_USAGE"); DBG_RETURN(QC_TOKEN_USAGE); } YY_BREAK case 537: YY_RULE_SETUP #line 603 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_USER"); DBG_RETURN(QC_TOKEN_USER); } YY_BREAK case 538: YY_RULE_SETUP #line 604 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_USE_FRM"); DBG_RETURN(QC_TOKEN_USE_FRM); } YY_BREAK case 539: YY_RULE_SETUP #line 605 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_USE"); DBG_RETURN(QC_TOKEN_USE); } YY_BREAK case 540: YY_RULE_SETUP #line 606 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_USING"); DBG_RETURN(QC_TOKEN_USING); } YY_BREAK case 541: YY_RULE_SETUP #line 607 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UTC_DATE"); DBG_RETURN(QC_TOKEN_UTC_DATE); } YY_BREAK case 542: YY_RULE_SETUP #line 608 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UTC_TIMESTAMP");DBG_RETURN(QC_TOKEN_UTC_TIMESTAMP); } YY_BREAK case 543: YY_RULE_SETUP #line 609 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_UTC_TIME"); DBG_RETURN(QC_TOKEN_UTC_TIME); } YY_BREAK case 544: YY_RULE_SETUP #line 610 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VALUES"); DBG_RETURN(QC_TOKEN_VALUES); } YY_BREAK case 545: YY_RULE_SETUP #line 611 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VALUE"); DBG_RETURN(QC_TOKEN_VALUE); } YY_BREAK case 546: YY_RULE_SETUP #line 612 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VARBINARY"); DBG_RETURN(QC_TOKEN_VARBINARY); } YY_BREAK case 547: YY_RULE_SETUP #line 613 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VARCHAR"); DBG_RETURN(QC_TOKEN_VARCHAR); } YY_BREAK case 548: YY_RULE_SETUP #line 614 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VARIABLES"); DBG_RETURN(QC_TOKEN_VARIABLES); } YY_BREAK case 549: YY_RULE_SETUP #line 615 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VARIANCE"); DBG_RETURN(QC_TOKEN_VARIANCE); } YY_BREAK case 550: YY_RULE_SETUP #line 616 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VARYING"); DBG_RETURN(QC_TOKEN_VARYING); } YY_BREAK case 551: YY_RULE_SETUP #line 617 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VAR_SAMP"); DBG_RETURN(QC_TOKEN_VAR_SAMP); } YY_BREAK case 552: YY_RULE_SETUP #line 618 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_VIEW"); DBG_RETURN(QC_TOKEN_VIEW); } YY_BREAK case 553: YY_RULE_SETUP #line 619 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WAIT"); DBG_RETURN(QC_TOKEN_WAIT); } YY_BREAK case 554: YY_RULE_SETUP #line 620 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WARNINGS"); DBG_RETURN(QC_TOKEN_WARNINGS); } YY_BREAK case 555: YY_RULE_SETUP #line 621 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WEEK"); DBG_RETURN(QC_TOKEN_WEEK); } YY_BREAK case 556: YY_RULE_SETUP #line 622 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WHEN"); DBG_RETURN(QC_TOKEN_WHEN); } YY_BREAK case 557: YY_RULE_SETUP #line 623 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WHERE"); DBG_RETURN(QC_TOKEN_WHERE); } YY_BREAK case 558: YY_RULE_SETUP #line 624 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WHILE"); DBG_RETURN(QC_TOKEN_WHILE); } YY_BREAK case 559: YY_RULE_SETUP #line 625 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WITH"); DBG_RETURN(QC_TOKEN_WITH); } YY_BREAK case 560: YY_RULE_SETUP #line 626 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WITH_CUBE"); DBG_RETURN(QC_TOKEN_WITH_CUBE); } YY_BREAK case 561: YY_RULE_SETUP #line 627 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WITH_ROLLUP"); DBG_RETURN(QC_TOKEN_WITH_ROLLUP); } YY_BREAK case 562: YY_RULE_SETUP #line 628 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WORK"); DBG_RETURN(QC_TOKEN_WORK); } YY_BREAK case 563: YY_RULE_SETUP #line 629 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WRAPPER"); DBG_RETURN(QC_TOKEN_WRAPPER); } YY_BREAK case 564: YY_RULE_SETUP #line 630 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_WRITE"); DBG_RETURN(QC_TOKEN_WRITE); } YY_BREAK case 565: YY_RULE_SETUP #line 631 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_X509"); DBG_RETURN(QC_TOKEN_X509); } YY_BREAK case 566: YY_RULE_SETUP #line 632 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_XA"); DBG_RETURN(QC_TOKEN_XA); } YY_BREAK case 567: YY_RULE_SETUP #line 633 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_XML"); DBG_RETURN(QC_TOKEN_XML); } YY_BREAK case 568: YY_RULE_SETUP #line 634 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_XOR"); DBG_RETURN(QC_TOKEN_XOR); } YY_BREAK case 569: YY_RULE_SETUP #line 635 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_YEAR_MONTH"); DBG_RETURN(QC_TOKEN_YEAR_MONTH); } YY_BREAK case 570: YY_RULE_SETUP #line 636 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_YEAR"); DBG_RETURN(QC_TOKEN_YEAR); } YY_BREAK case 571: YY_RULE_SETUP #line 637 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_ZEROFILL"); DBG_RETURN(QC_TOKEN_ZEROFILL); } YY_BREAK case 572: YY_RULE_SETUP #line 638 "mysqlnd_query_lexer.flex" { *kn = yytext; DBG_INF("QC_TOKEN_CLIENT_FLAG"); DBG_RETURN(QC_TOKEN_CLIENT_FLAG); } YY_BREAK /* Integers and Floats */ case 573: YY_RULE_SETUP #line 642 "mysqlnd_query_lexer.flex" { ZVAL_LONG(token_value, atoi(yytext)); DBG_INF("QC_TOKEN_INTNUM"); DBG_RETURN(QC_TOKEN_INTNUM); } YY_BREAK case 574: #line 645 "mysqlnd_query_lexer.flex" case 575: #line 646 "mysqlnd_query_lexer.flex" case 576: #line 647 "mysqlnd_query_lexer.flex" case 577: #line 648 "mysqlnd_query_lexer.flex" case 578: YY_RULE_SETUP #line 648 "mysqlnd_query_lexer.flex" { ZVAL_DOUBLE(token_value, atof(yytext)); DBG_INF("QC_TOKEN_FLOATNUM"); DBG_RETURN(QC_TOKEN_FLOATNUM); } YY_BREAK /* Normal strings */ case 579: #line 652 "mysqlnd_query_lexer.flex" case 580: YY_RULE_SETUP #line 652 "mysqlnd_query_lexer.flex" { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } YY_BREAK case 581: *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ yyg->yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 653 "mysqlnd_query_lexer.flex" { yyerror("Unterminated string %s", yytext); } YY_BREAK case 582: *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ yyg->yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 654 "mysqlnd_query_lexer.flex" { yyerror("Unterminated string %s", yytext); } YY_BREAK /* Hex and Bit strings */ case 583: #line 658 "mysqlnd_query_lexer.flex" case 584: YY_RULE_SETUP #line 658 "mysqlnd_query_lexer.flex" { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } YY_BREAK case 585: #line 660 "mysqlnd_query_lexer.flex" case 586: YY_RULE_SETUP #line 660 "mysqlnd_query_lexer.flex" { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } YY_BREAK /* Operators */ case 587: YY_RULE_SETUP #line 663 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_PLUS"); DBG_RETURN(QC_TOKEN_PLUS); } YY_BREAK case 588: YY_RULE_SETUP #line 664 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_MINUS"); DBG_RETURN(QC_TOKEN_MINUS); } YY_BREAK case 589: YY_RULE_SETUP #line 665 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_COMMA"); DBG_RETURN(QC_TOKEN_COMMA); } YY_BREAK case 590: YY_RULE_SETUP #line 666 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_SEMICOLON"); DBG_RETURN(QC_TOKEN_SEMICOLON); } YY_BREAK case 591: YY_RULE_SETUP #line 667 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_BRACKET_OPEN"); DBG_RETURN(QC_TOKEN_BRACKET_OPEN); } YY_BREAK case 592: YY_RULE_SETUP #line 668 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_BRACKET_CLOSE");DBG_RETURN(QC_TOKEN_BRACKET_CLOSE); } YY_BREAK case 593: YY_RULE_SETUP #line 669 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_STAR"); DBG_RETURN(QC_TOKEN_STAR); } YY_BREAK case 594: YY_RULE_SETUP #line 670 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_DOT"); DBG_RETURN(QC_TOKEN_DOT); } YY_BREAK case 595: YY_RULE_SETUP #line 671 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_NOT"); DBG_RETURN(QC_TOKEN_NOT); } YY_BREAK case 596: YY_RULE_SETUP #line 672 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_XOR"); DBG_RETURN(QC_TOKEN_XOR); } YY_BREAK case 597: YY_RULE_SETUP #line 673 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_MOD"); DBG_RETURN(QC_TOKEN_MOD); } YY_BREAK case 598: YY_RULE_SETUP #line 674 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_DIV"); DBG_RETURN(QC_TOKEN_DIV); } YY_BREAK case 599: YY_RULE_SETUP #line 675 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_TILDE"); DBG_RETURN(QC_TOKEN_TILDE); } YY_BREAK case 600: YY_RULE_SETUP #line 676 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_GLOBAL_VAR"); DBG_RETURN(QC_TOKEN_GLOBAL_VAR); } YY_BREAK case 601: YY_RULE_SETUP #line 677 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_SESSION_VAR"); DBG_RETURN(QC_TOKEN_SESSION_VAR); } YY_BREAK case 602: YY_RULE_SETUP #line 678 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_AND"); DBG_RETURN(QC_TOKEN_AND); } YY_BREAK case 603: YY_RULE_SETUP #line 679 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_BIT_AND"); DBG_RETURN(QC_TOKEN_BIT_AND); } YY_BREAK case 604: YY_RULE_SETUP #line 680 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_OR"); DBG_RETURN(QC_TOKEN_OR); } YY_BREAK case 605: YY_RULE_SETUP #line 681 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_BIT_OR"); DBG_RETURN(QC_TOKEN_BIT_OR); } YY_BREAK case 606: YY_RULE_SETUP #line 682 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_EQ"); DBG_RETURN(QC_TOKEN_EQ); } YY_BREAK case 607: YY_RULE_SETUP #line 683 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_NE_TRIPLE"); DBG_RETURN(QC_TOKEN_NE_TRIPLE); } YY_BREAK case 608: YY_RULE_SETUP #line 684 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_GE"); DBG_RETURN(QC_TOKEN_GE); } YY_BREAK case 609: YY_RULE_SETUP #line 685 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_GT"); DBG_RETURN(QC_TOKEN_GT); } YY_BREAK case 610: YY_RULE_SETUP #line 686 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_LE"); DBG_RETURN(QC_TOKEN_LE); } YY_BREAK case 611: YY_RULE_SETUP #line 687 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_LT"); DBG_RETURN(QC_TOKEN_LT); } YY_BREAK case 612: #line 689 "mysqlnd_query_lexer.flex" case 613: YY_RULE_SETUP #line 689 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_SHIFT_LEFT"); DBG_RETURN(QC_TOKEN_SHIFT_LEFT); } YY_BREAK case 614: YY_RULE_SETUP #line 690 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_SHIFT_RIGHT"); DBG_RETURN(QC_TOKEN_SHIFT_RIGHT); } YY_BREAK case 615: YY_RULE_SETUP #line 691 "mysqlnd_query_lexer.flex" { DBG_INF("QC_TOKEN_ASSIGN_TO_VAR");DBG_RETURN(QC_TOKEN_ASSIGN_TO_VAR); } YY_BREAK /* normal identifier */ case 616: YY_RULE_SETUP #line 694 "mysqlnd_query_lexer.flex" { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_IDENTIFIER"); DBG_RETURN(QC_TOKEN_IDENTIFIER); } YY_BREAK /* quoted identifier */ case 617: YY_RULE_SETUP #line 697 "mysqlnd_query_lexer.flex" { ZVAL_STRINGL(token_value, yytext + 1, yyleng - 2, 1); DBG_INF("QC_TOKEN_IDENTIFIER"); DBG_RETURN(QC_TOKEN_IDENTIFIER); } YY_BREAK /* Comments */ case 618: YY_RULE_SETUP #line 704 "mysqlnd_query_lexer.flex" ; { ZVAL_STRINGL(token_value, yytext + 1, yyleng - 1, 1); DBG_INF("QC_TOKEN_COMMENT"); DBG_RETURN(QC_TOKEN_COMMENT); } YY_BREAK case 619: YY_RULE_SETUP #line 710 "mysqlnd_query_lexer.flex" { ZVAL_STRINGL(token_value, yytext + 2, yyleng - 2, 1); DBG_INF("QC_TOKEN_COMMENT"); DBG_RETURN(QC_TOKEN_COMMENT); } YY_BREAK case 620: YY_RULE_SETUP #line 716 "mysqlnd_query_lexer.flex" { old_yystate = YY_START; DBG_INF("entering COMMENT_MODE"); BEGIN COMMENT_MODE; #if VALGRIND_MEMORY_WARNINGS if (*comment) { mnd_efree(*comment); *comment = NULL; } #endif *comment = mnd_ecalloc(1, sizeof(smart_str)); ZVAL_NULL(token_value); } YY_BREAK case 621: YY_RULE_SETUP #line 731 "mysqlnd_query_lexer.flex" { BEGIN old_yystate; DBG_INF("leaving COMMENT_MODE"); DBG_INF("QC_TOKEN_COMMENT"); smart_str_appendc(*comment, '\0'); /* we need to copy the smart_str by value before we set token_value because comment and token_value are the vary same thing (part of an union) if we write something to token_value we will lose comment; */ { smart_str * ss_copy = *comment; ZVAL_STRINGL(token_value, (*comment)->c, (*comment)->len, 1); smart_str_free(ss_copy); mnd_efree(ss_copy); } DBG_INF_FMT("token_value is now:%s", Z_STRVAL_P(token_value)); DBG_RETURN(QC_TOKEN_COMMENT); } YY_BREAK case 622: /* rule 622 can match eol */ YY_RULE_SETUP #line 754 "mysqlnd_query_lexer.flex" { smart_str_appendc(*comment, yytext[0]); } YY_BREAK /* the rest */ case 623: /* rule 623 can match eol */ YY_RULE_SETUP #line 759 "mysqlnd_query_lexer.flex" /* whitespace */ YY_BREAK case 624: YY_RULE_SETUP #line 760 "mysqlnd_query_lexer.flex" { yyerror("report to the developer '%c'\n", *yytext); } YY_BREAK case 625: YY_RULE_SETUP #line 761 "mysqlnd_query_lexer.flex" ECHO; YY_BREAK #line 8381 "mysqlnd_query_lexer.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(COMMENT_MODE): case YY_STATE_EOF(BETWEEN_MODE): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yyg->yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * mysqlnd_qp_lex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yyg->yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yyg->yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_END_OF_FILE: { yyg->yy_did_buffer_switch_on_eof = 0; if ( mysqlnd_qp_wrap(yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yyg->yy_c_buf_p = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; yy_current_state = yy_get_previous_state( yyscanner ); yy_cp = yyg->yy_c_buf_p; yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of mysqlnd_qp_lex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = yyg->yytext_ptr; register int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ mysqlnd_qp_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), yyg->yy_n_chars, (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } if ( yyg->yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; mysqlnd_qp_restart(yyin ,yyscanner); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) mysqlnd_qp_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } yyg->yy_n_chars += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { register yy_state_type yy_current_state; register char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 2803 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { register int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ register char *yy_cp = yyg->yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; yyg->yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 2803 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 2802); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner) #else static int input (yyscan_t yyscanner) #endif { int c; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; *yyg->yy_c_buf_p = yyg->yy_hold_char; if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) /* This was really a NUL. */ *yyg->yy_c_buf_p = '\0'; else { /* need more input */ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ mysqlnd_qp_restart(yyin ,yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( mysqlnd_qp_wrap(yyscanner ) ) return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(yyscanner); #else return input(yyscanner); #endif } case EOB_ACT_CONTINUE_SCAN: yyg->yy_c_buf_p = yyg->yytext_ptr + offset; break; } } } c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ yyg->yy_hold_char = *++yyg->yy_c_buf_p; return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ void mysqlnd_qp_restart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ mysqlnd_qp_ensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = mysqlnd_qp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } mysqlnd_qp__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); mysqlnd_qp__load_buffer_state(yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ void mysqlnd_qp__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with * mysqlnd_qp_pop_buffer_state(); * mysqlnd_qp_push_buffer_state(new_buffer); */ mysqlnd_qp_ensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } YY_CURRENT_BUFFER_LVALUE = new_buffer; mysqlnd_qp__load_buffer_state(yyscanner ); /* We don't actually know whether we did this switch during * EOF (mysqlnd_qp_wrap()) processing, but the only time this flag * is looked at is after mysqlnd_qp_wrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } static void mysqlnd_qp__load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; yyg->yy_hold_char = *yyg->yy_c_buf_p; } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * @param yyscanner The scanner object. * @return the allocated buffer state. */ YY_BUFFER_STATE mysqlnd_qp__create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) mysqlnd_qp_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in mysqlnd_qp__create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) mysqlnd_qp_alloc(b->yy_buf_size + 2 ,yyscanner ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in mysqlnd_qp__create_buffer()" ); b->yy_is_our_buffer = 1; mysqlnd_qp__init_buffer(b,file ,yyscanner); return b; } /** Destroy the buffer. * @param b a buffer created with mysqlnd_qp__create_buffer() * @param yyscanner The scanner object. */ void mysqlnd_qp__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) mysqlnd_qp_free((void *) b->yy_ch_buf ,yyscanner ); mysqlnd_qp_free((void *) b ,yyscanner ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a mysqlnd_qp_restart() or at EOF. */ static void mysqlnd_qp__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; mysqlnd_qp__flush_buffer(b ,yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then mysqlnd_qp__init_buffer was _probably_ * called from mysqlnd_qp_restart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ void mysqlnd_qp__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) mysqlnd_qp__load_buffer_state(yyscanner ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * @param yyscanner The scanner object. */ void mysqlnd_qp_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; mysqlnd_qp_ensure_buffer_stack(yyscanner); /* This block is copied from mysqlnd_qp__switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *yyg->yy_c_buf_p = yyg->yy_hold_char; YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from mysqlnd_qp__switch_to_buffer. */ mysqlnd_qp__load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * @param yyscanner The scanner object. */ void mysqlnd_qp_pop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; mysqlnd_qp__delete_buffer(YY_CURRENT_BUFFER ,yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { mysqlnd_qp__load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void mysqlnd_qp_ensure_buffer_stack (yyscan_t yyscanner) { int num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!yyg->yy_buffer_stack) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; yyg->yy_buffer_stack = (struct yy_buffer_state**)mysqlnd_qp_alloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in mysqlnd_qp_ensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; } if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; yyg->yy_buffer_stack = (struct yy_buffer_state**)mysqlnd_qp_realloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in mysqlnd_qp_ensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); yyg->yy_buffer_stack_max = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE mysqlnd_qp__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) mysqlnd_qp_alloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in mysqlnd_qp__scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; mysqlnd_qp__switch_to_buffer(b ,yyscanner ); return b; } /** Setup the input buffer state to scan a string. The next call to mysqlnd_qp_lex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * mysqlnd_qp__scan_bytes() instead. */ YY_BUFFER_STATE mysqlnd_qp__scan_string (yyconst char * yystr , yyscan_t yyscanner) { return mysqlnd_qp__scan_bytes(yystr,strlen(yystr) ,yyscanner); } /** Setup the input buffer state to scan the given bytes. The next call to mysqlnd_qp_lex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ YY_BUFFER_STATE mysqlnd_qp__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) mysqlnd_qp_alloc(n ,yyscanner ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in mysqlnd_qp__scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = mysqlnd_qp__scan_buffer(buf,n ,yyscanner); if ( ! b ) YY_FATAL_ERROR( "bad buffer in mysqlnd_qp__scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = yyg->yy_hold_char; \ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ yyg->yy_hold_char = *yyg->yy_c_buf_p; \ *yyg->yy_c_buf_p = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ YY_EXTRA_TYPE mysqlnd_qp_get_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; } /** Get the current line number. * @param yyscanner The scanner object. */ int mysqlnd_qp_get_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yylineno; } /** Get the current column number. * @param yyscanner The scanner object. */ int mysqlnd_qp_get_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (! YY_CURRENT_BUFFER) return 0; return yycolumn; } /** Get the input stream. * @param yyscanner The scanner object. */ FILE *mysqlnd_qp_get_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; } /** Get the output stream. * @param yyscanner The scanner object. */ FILE *mysqlnd_qp_get_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; } /** Get the length of the current token. * @param yyscanner The scanner object. */ int mysqlnd_qp_get_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; } /** Get the current token. * @param yyscanner The scanner object. */ char *mysqlnd_qp_get_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; } /** Set the user-defined data. This data is never touched by the scanner. * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ void mysqlnd_qp_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; } /** Set the current line number. * @param line_number * @param yyscanner The scanner object. */ void mysqlnd_qp_set_lineno (int line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) yy_fatal_error( "mysqlnd_qp_set_lineno called with no buffer" , yyscanner); yylineno = line_number; } /** Set the current column. * @param line_number * @param yyscanner The scanner object. */ void mysqlnd_qp_set_column (int column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) yy_fatal_error( "mysqlnd_qp_set_column called with no buffer" , yyscanner); yycolumn = column_no; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * @param yyscanner The scanner object. * @see mysqlnd_qp__switch_to_buffer */ void mysqlnd_qp_set_in (FILE * in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = in_str ; } void mysqlnd_qp_set_out (FILE * out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = out_str ; } int mysqlnd_qp_get_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } void mysqlnd_qp_set_debug (int bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = bdebug ; } /* Accessor methods for yylval and yylloc */ YYSTYPE * mysqlnd_qp_get_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } void mysqlnd_qp_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; } /* User-visible API */ /* mysqlnd_qp_lex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ int mysqlnd_qp_lex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) mysqlnd_qp_alloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); return yy_init_globals ( *ptr_yy_globals ); } /* mysqlnd_qp_lex_init_extra has the same functionality as mysqlnd_qp_lex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). * The user defined value in the first argument will be available to mysqlnd_qp_alloc in * the yyextra field. */ int mysqlnd_qp_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; mysqlnd_qp_set_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } *ptr_yy_globals = (yyscan_t) mysqlnd_qp_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); mysqlnd_qp_set_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. * This function is called from mysqlnd_qp_lex_destroy(), so don't allocate here. */ yyg->yy_buffer_stack = 0; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; yyg->yy_c_buf_p = (char *) 0; yyg->yy_init = 0; yyg->yy_start = 0; yyg->yy_start_stack_ptr = 0; yyg->yy_start_stack_depth = 0; yyg->yy_start_stack = NULL; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * mysqlnd_qp_lex_init() */ return 0; } /* mysqlnd_qp_lex_destroy is for both reentrant and non-reentrant scanners. */ int mysqlnd_qp_lex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ mysqlnd_qp__delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; mysqlnd_qp_pop_buffer_state(yyscanner); } /* Destroy the stack itself. */ mysqlnd_qp_free(yyg->yy_buffer_stack ,yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ mysqlnd_qp_free(yyg->yy_start_stack ,yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * mysqlnd_qp_lex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ mysqlnd_qp_free ( yyscanner , yyscanner ); yyscanner = NULL; return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *mysqlnd_qp_alloc (yy_size_t size , yyscan_t yyscanner) { return (void *) malloc( size ); } void *mysqlnd_qp_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void mysqlnd_qp_free (void * ptr , yyscan_t yyscanner) { free( (char *) ptr ); /* see mysqlnd_qp_realloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 761 "mysqlnd_query_lexer.flex" /* {{{ mysqlnd_qp_error */ int mysqlnd_qp_error(const char *format, ...) { /* do not emit a message */ return 1; } /* }}} */ /* {{{ mysqlnd_qp_free_scanner */ PHPAPI void mysqlnd_qp_free_scanner(struct st_mysqlnd_query_scanner * scanner TSRMLS_DC) { DBG_ENTER("mysqlnd_qp_free_scanner"); if (scanner) { mysqlnd_qp_lex_destroy(*(yyscan_t *) scanner->scanner); mnd_efree(scanner->scanner); mnd_efree(scanner); } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_qp_create_scanner */ PHPAPI struct st_mysqlnd_query_scanner * mysqlnd_qp_create_scanner(TSRMLS_D) { struct st_mysqlnd_query_scanner * ret = mnd_ecalloc(1, sizeof(struct st_mysqlnd_query_scanner)); DBG_ENTER("mysqlnd_qp_create_scanner"); ret->scanner = mnd_ecalloc(1, sizeof(yyscan_t)); if (mysqlnd_qp_lex_init_extra(ret->token_value /* yyextra */,(yyscan_t *) ret->scanner)) { DBG_ERR_FMT("mysqlnd_qp_lex_init_extra failed"); mysqlnd_qp_free_scanner(ret TSRMLS_CC); ret = NULL; } DBG_INF_FMT("ret=%p", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_qp_get_token */ PHPAPI struct st_ms_token_and_value mysqlnd_qp_get_token(struct st_mysqlnd_query_scanner * scanner TSRMLS_DC) { YYSTYPE lex_val; struct st_ms_token_and_value ret = {0}; DBG_ENTER("mysqlnd_qp_get_token"); memset(&lex_val, 0, sizeof(lex_val)); INIT_ZVAL(lex_val.zv); /* mysqlnd_qp_lex expects `yyscan_t`, not `yyscan_t*` */ if ((ret.token = mysqlnd_qp_lex(&lex_val,*(yyscan_t *)scanner->scanner TSRMLS_CC))) { DBG_INF_FMT("token=%d", ret.token); switch (Z_TYPE(lex_val.zv)) { case IS_STRING: DBG_INF_FMT("strval=%s", Z_STRVAL(lex_val.zv)); ret.value = lex_val.zv; break; case IS_LONG: DBG_INF_FMT("lval=%ld", Z_LVAL(lex_val.zv)); ret.value = lex_val.zv; break; case IS_DOUBLE: DBG_INF_FMT("dval=%f", Z_DVAL(lex_val.zv)); ret.value = lex_val.zv; break; case IS_NULL: if (lex_val.kn) { ZVAL_STRING(&ret.value, lex_val.kn, 1); } break; } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_qp_set_string */ PHPAPI void mysqlnd_qp_set_string(struct st_mysqlnd_query_scanner * scanner, const char * const s, size_t len TSRMLS_DC) { DBG_ENTER("mysqlnd_qp_set_string"); /* scan_string/scan_bytes expect `yyscan_t`, not `yyscan_t*` */ mysqlnd_qp__scan_bytes(s,len,*((yyscan_t *)scanner->scanner)); DBG_VOID_RETURN; } /* }}} */ #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION /* {{{ mysqlnd_qp_create_parser */ PHPAPI struct st_mysqlnd_query_parser * mysqlnd_qp_create_parser(TSRMLS_D) { struct st_mysqlnd_query_parser * ret = mnd_ecalloc(1, sizeof(struct st_mysqlnd_query_parser)); DBG_ENTER("mysqlnd_qp_create_parser"); DBG_INF_FMT("ret=%p", ret); ret->scanner = mysqlnd_qp_create_scanner(TSRMLS_C); DBG_INF_FMT("ret->scanner=%p", ret->scanner); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_qp_free_parser */ PHPAPI void mysqlnd_qp_free_parser(struct st_mysqlnd_query_parser * parser TSRMLS_DC) { DBG_ENTER("mysqlnd_qp_free_parser"); if (parser) { mysqlnd_qp_free_scanner(parser->scanner TSRMLS_CC); zend_llist_clean(&parser->parse_info.where_field_list); zend_llist_clean(&parser->parse_info.select_field_list); zend_llist_clean(&parser->parse_info.table_list); mnd_efree(parser); } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_table_list_dtor */ static void mysqlnd_ms_table_list_dtor(void * pDest) { struct st_mysqlnd_ms_table_info * table_info = (struct st_mysqlnd_ms_table_info *) pDest; TSRMLS_FETCH(); if (table_info) { zend_bool pers = table_info->persistent; if (table_info->db) { mnd_pefree(table_info->db, pers); } if (table_info->table) { mnd_pefree(table_info->table, pers); } if (table_info->org_table) { mnd_pefree(table_info->org_table, pers); } } } /* }}} */ /* {{{ mysqlnd_ms_field_list_dtor */ static void mysqlnd_ms_field_list_dtor(void * pDest) { struct st_mysqlnd_ms_field_info * field_info = (struct st_mysqlnd_ms_field_info *) pDest; TSRMLS_FETCH(); if (field_info) { zend_bool pers = field_info->persistent; if (field_info->db) { mnd_pefree(field_info->db, pers); } if (field_info->table) { mnd_pefree(field_info->table, pers); } if (field_info->name) { mnd_pefree(field_info->name, pers); } if (field_info->org_name) { mnd_pefree(field_info->org_name, pers); } if (field_info->custom_data && field_info->free_custom_data) { mnd_pefree(field_info->custom_data, pers); } } } /* }}} */ extern int mysqlnd_qp_parse (void * TSRMLS_DC); /* {{{ mysqlnd_qp_start_parser */ PHPAPI int mysqlnd_qp_start_parser(struct st_mysqlnd_query_parser * parser, const char * const query, const size_t query_len TSRMLS_DC) { int ret; DBG_ENTER("mysqlnd_qp_start_parser"); mysqlnd_qp_set_string(parser->scanner, query, query_len TSRMLS_CC); zend_llist_init(&parser->parse_info.table_list, sizeof(struct st_mysqlnd_ms_table_info), (llist_dtor_func_t) mysqlnd_ms_table_list_dtor, parser->parse_info.persistent /* pers */); zend_llist_init(&parser->parse_info.select_field_list, sizeof(struct st_mysqlnd_ms_field_info), (llist_dtor_func_t) mysqlnd_ms_field_list_dtor, parser->parse_info.persistent /* pers */); zend_llist_init(&parser->parse_info.where_field_list, sizeof(struct st_mysqlnd_ms_field_info), (llist_dtor_func_t) mysqlnd_ms_field_list_dtor, parser->parse_info.persistent /* pers */); parser->parse_info.parse_where = FALSE; DBG_INF("let's run the parser"); ret = mysqlnd_qp_parse(parser TSRMLS_CC); { zend_llist_position pos; struct st_mysqlnd_ms_table_info * tinfo; DBG_INF("------ TABLE LIST -------"); for (tinfo = zend_llist_get_first_ex(&parser->parse_info.table_list, &pos); tinfo; tinfo = zend_llist_get_next_ex(&parser->parse_info.table_list, &pos)) { DBG_INF_FMT("db=[%s] table=[%s] org_table=[%s] statement_type=[%d]", tinfo->db? tinfo->db:"n/a", tinfo->table? tinfo->table:"n/a", tinfo->org_table? tinfo->org_table:"n/a", parser->parse_info.statement ); } } { zend_llist_position pos; struct st_mysqlnd_ms_field_info * finfo; DBG_INF("------ SELECT FIELD LIST -------"); for (finfo = zend_llist_get_first_ex(&parser->parse_info.select_field_list, &pos); finfo; finfo = zend_llist_get_next_ex(&parser->parse_info.select_field_list, &pos)) { DBG_INF_FMT("db=[%s] table=[%s] name=[%s] org_name=[%s]", finfo->db? finfo->db:"n/a", finfo->table? finfo->table:"n/a", finfo->name? finfo->name:"n/a", finfo->org_name? finfo->org_name:"n/a" ); } } { zend_llist_position pos; struct st_mysqlnd_ms_field_info * finfo; DBG_INF("------ WHERE FIELD LIST -------"); for (finfo = zend_llist_get_first_ex(&parser->parse_info.where_field_list, &pos); finfo; finfo = zend_llist_get_next_ex(&parser->parse_info.where_field_list, &pos)) { DBG_INF_FMT("db=[%s] table=[%s] name=[%s] org_name=%s op=[%s]", finfo->db? finfo->db:"n/a", finfo->table? finfo->table:"n/a", finfo->name? finfo->name:"n/a", finfo->org_name? finfo->org_name:"n/a", finfo->custom_data? finfo->custom_data:"n/a" ); } } DBG_RETURN(ret); } /* }}} */ #endif /* MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION */ mysqlnd_ms-1.5.2/mysqlnd_query_lexer.flex0000664000175000017500000021305412161007456020237 0ustar andreyandrey%{ /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ /* Compile with : flex mysqlnd_query_lexer.flex */ #include #include "php.h" #include "php_ini.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #include "mysqlnd_ms.h" #include "mysqlnd_query_parser.h" int old_yystate; #define yyerror mysqlnd_qp_error int mysqlnd_qp_error(const char *format, ...); #define YY_DECL int mysqlnd_qp_lex(YYSTYPE * yylval_param, yyscan_t yyscanner TSRMLS_DC) #define YY_NO_INPUT #define YY_NO_UNISTD_H /* In Unicode . is [\0-\x7F] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEF][\x80-\xBF][\x80-\xBF] */ %} %option 8bit %option prefix="mysqlnd_qp_" %option outfile="mysqlnd_query_lexer.c" %option reentrant noyywrap nounput %option extra-type="zval *" %option bison-bridge %option header-file="mysqlnd_query_lexer.lex.h" %x COMMENT_MODE %s BETWEEN_MODE %% %{ /* can't use `yylval` here because `yylval` is initialized by flex to `yylval_param` later */ zval * token_value = &yylval_param->zv; const char ** kn = &(yylval_param->kn); smart_str ** comment = &(yylval_param->comment); DBG_ENTER("my_lex_routine"); %} (?i:ACCESSIBLE) { *kn = yytext; DBG_INF("QC_TOKEN_ACCESSIBLE"); DBG_RETURN(QC_TOKEN_ACCESSIBLE); } (?i:ACTION) { *kn = yytext; DBG_INF("QC_TOKEN_ACTION"); DBG_RETURN(QC_TOKEN_ACTION); } (?i:ADD) { *kn = yytext; DBG_INF("QC_TOKEN_ADD"); DBG_RETURN(QC_TOKEN_ADD); } (?i:ADDDATE) { *kn = yytext; DBG_INF("QC_TOKEN_ADDDATE"); DBG_RETURN(QC_TOKEN_ADDDATE); } (?i:AFTER) { *kn = yytext; DBG_INF("QC_TOKEN_AFTER"); DBG_RETURN(QC_TOKEN_AFTER); } (?i:AGAINST) { *kn = yytext; DBG_INF("QC_TOKEN_AGAINST"); DBG_RETURN(QC_TOKEN_AGAINST); } (?i:AGGREGATE) { *kn = yytext; DBG_INF("QC_TOKEN_AGGREGATE"); DBG_RETURN(QC_TOKEN_AGGREGATE); } (?i:ALGORITHM) { *kn = yytext; DBG_INF("QC_TOKEN_ALGORITHM"); DBG_RETURN(QC_TOKEN_ALGORITHM); } (?i:ALL) { *kn = yytext; DBG_INF("QC_TOKEN_ALL"); DBG_RETURN(QC_TOKEN_ALL); } (?i:ALTER) { *kn = yytext; DBG_INF("QC_TOKEN_ALTER"); DBG_RETURN(QC_TOKEN_ALTER); } (?i:ANALYZE) { *kn = yytext; DBG_INF("QC_TOKEN_ANALYZE"); DBG_RETURN(QC_TOKEN_ANALYZE); } AND { BEGIN INITIAL; *kn = yytext; DBG_INF("QC_TOKEN_BETWEEN_AND"); DBG_RETURN(QC_TOKEN_BETWEEN_AND); } (?i:AND) { *kn = yytext; DBG_INF("QC_TOKEN_AND"); DBG_RETURN(QC_TOKEN_AND); } (?i:ANY) { *kn = yytext; DBG_INF("QC_TOKEN_ANY"); DBG_RETURN(QC_TOKEN_ANY); } (?i:AS) { *kn = yytext; DBG_INF("QC_TOKEN_AS"); DBG_RETURN(QC_TOKEN_AS); } (?i:ASC) { *kn = yytext; DBG_INF("QC_TOKEN_ASC"); DBG_RETURN(QC_TOKEN_ASC); } (?i:ASCII) { *kn = yytext; DBG_INF("QC_TOKEN_ASCII"); DBG_RETURN(QC_TOKEN_ASCII); } (?i:ASENSITIVE) { *kn = yytext; DBG_INF("QC_TOKEN_ASENSITIVE"); DBG_RETURN(QC_TOKEN_ASENSITIVE); } (?i:AT) { *kn = yytext; DBG_INF("QC_TOKEN_AT"); DBG_RETURN(QC_TOKEN_AT); } (?i:AUTHORS) { *kn = yytext; DBG_INF("QC_TOKEN_AUTHORS"); DBG_RETURN(QC_TOKEN_AUTHORS); } (?i:AUTOEXTEND_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_AUTOEXTEND_SIZE"); DBG_RETURN(QC_TOKEN_AUTOEXTEND_SIZE); } (?i:AUTO_INC) { *kn = yytext; DBG_INF("QC_TOKEN_AUTO_INC"); DBG_RETURN(QC_TOKEN_AUTO_INC); } (?i:AVG_ROW_LENGTH) { *kn = yytext; DBG_INF("QC_TOKEN_AVG_ROW_LENGTH"); DBG_RETURN(QC_TOKEN_AVG_ROW_LENGTH); } (?i:AVG) { *kn = yytext; DBG_INF("QC_TOKEN_AVG"); DBG_RETURN(QC_TOKEN_AVG); } (?i:BACKUP) { *kn = yytext; DBG_INF("QC_TOKEN_BACKUP"); DBG_RETURN(QC_TOKEN_BACKUP); } (?i:BEFORE) { *kn = yytext; DBG_INF("QC_TOKEN_BEFORE"); DBG_RETURN(QC_TOKEN_BEFORE); } (?i:BEGIN) { *kn = yytext; DBG_INF("QC_TOKEN_BEGIN"); DBG_RETURN(QC_TOKEN_BEGIN); } (?i:BETWEEN) { BEGIN BETWEEN_MODE; *kn = yytext; DBG_INF("QC_TOKEN_BETWEEN"); DBG_RETURN(QC_TOKEN_BETWEEN); } (?i:BIGINT) { *kn = yytext; DBG_INF("QC_TOKEN_BIGINT"); DBG_RETURN(QC_TOKEN_BIGINT); } (?i:BINARY) { *kn = yytext; DBG_INF("QC_TOKEN_BINARY"); DBG_RETURN(QC_TOKEN_BINARY); } (?i:BINLOG) { *kn = yytext; DBG_INF("QC_TOKEN_BINLOG"); DBG_RETURN(QC_TOKEN_BINLOG); } (?i:BIT) { *kn = yytext; DBG_INF("QC_TOKEN_BIT"); DBG_RETURN(QC_TOKEN_BIT); } (?i:BLOB) { *kn = yytext; DBG_INF("QC_TOKEN_BLOB"); DBG_RETURN(QC_TOKEN_BLOB); } (?i:BLOCK) { *kn = yytext; DBG_INF("QC_TOKEN_BLOCK"); DBG_RETURN(QC_TOKEN_BLOCK); } (?i:BOOLEAN) { *kn = yytext; DBG_INF("QC_TOKEN_BOOLEAN"); DBG_RETURN(QC_TOKEN_BOOLEAN); } (?i:BOOL) { *kn = yytext; DBG_INF("QC_TOKEN_BOOL"); DBG_RETURN(QC_TOKEN_BOOL); } (?i:BOTH) { *kn = yytext; DBG_INF("QC_TOKEN_BOTH"); DBG_RETURN(QC_TOKEN_BOTH); } (?i:BTREE) { *kn = yytext; DBG_INF("QC_TOKEN_BTREE"); DBG_RETURN(QC_TOKEN_BTREE); } (?i:BY) { *kn = yytext; DBG_INF("QC_TOKEN_BY"); DBG_RETURN(QC_TOKEN_BY); } (?i:BYTE) { *kn = yytext; DBG_INF("QC_TOKEN_BYTE"); DBG_RETURN(QC_TOKEN_BYTE); } (?i:CACHE) { *kn = yytext; DBG_INF("QC_TOKEN_CACHE"); DBG_RETURN(QC_TOKEN_CACHE); } (?i:CALL) { *kn = yytext; DBG_INF("QC_TOKEN_CALL"); DBG_RETURN(QC_TOKEN_CALL); } (?i:CASCADE) { *kn = yytext; DBG_INF("QC_TOKEN_CASCADE"); DBG_RETURN(QC_TOKEN_CASCADE); } (?i:CASCADED) { *kn = yytext; DBG_INF("QC_TOKEN_CASCADED"); DBG_RETURN(QC_TOKEN_CASCADED); } (?i:CASE) { *kn = yytext; DBG_INF("QC_TOKEN_CASE"); DBG_RETURN(QC_TOKEN_CASE); } (?i:CAST) { *kn = yytext; DBG_INF("QC_TOKEN_CAST"); DBG_RETURN(QC_TOKEN_CAST); } (?i:CATALOG_NAME) { *kn = yytext; DBG_INF("QC_TOKEN_CATALOG_NAME"); DBG_RETURN(QC_TOKEN_CATALOG_NAME); } (?i:CHAIN) { *kn = yytext; DBG_INF("QC_TOKEN_CHAIN"); DBG_RETURN(QC_TOKEN_CHAIN); } (?i:CHANGE) { *kn = yytext; DBG_INF("QC_TOKEN_CHANGE"); DBG_RETURN(QC_TOKEN_CHANGE); } (?i:CHANGED) { *kn = yytext; DBG_INF("QC_TOKEN_CHANGED"); DBG_RETURN(QC_TOKEN_CHANGED); } (?i:CHARSET) { *kn = yytext; DBG_INF("QC_TOKEN_CHARSET"); DBG_RETURN(QC_TOKEN_CHARSET); } (?i:CHAR) { *kn = yytext; DBG_INF("QC_TOKEN_CHAR"); DBG_RETURN(QC_TOKEN_CHAR); } (?i:CHECKSUM) { *kn = yytext; DBG_INF("QC_TOKEN_CHECKSUM"); DBG_RETURN(QC_TOKEN_CHECKSUM); } (?i:CHECK) { *kn = yytext; DBG_INF("QC_TOKEN_CHECK"); DBG_RETURN(QC_TOKEN_CHECK); } (?i:CIPHER) { *kn = yytext; DBG_INF("QC_TOKEN_CIPHER"); DBG_RETURN(QC_TOKEN_CIPHER); } (?i:CLASS_ORIGIN) { *kn = yytext; DBG_INF("QC_TOKEN_CLASS_ORIGIN"); DBG_RETURN(QC_TOKEN_CLASS_ORIGIN); } (?i:CLIENT) { *kn = yytext; DBG_INF("QC_TOKEN_CLIENT"); DBG_RETURN(QC_TOKEN_CLIENT); } (?i:CLOSE) { *kn = yytext; DBG_INF("QC_TOKEN_CLOSE"); DBG_RETURN(QC_TOKEN_CLOSE); } (?i:COALESCE) { *kn = yytext; DBG_INF("QC_TOKEN_COALESCE"); DBG_RETURN(QC_TOKEN_COALESCE); } (?i:CODE) { *kn = yytext; DBG_INF("QC_TOKEN_CODE"); DBG_RETURN(QC_TOKEN_CODE); } (?i:COLLATE) { *kn = yytext; DBG_INF("QC_TOKEN_COLLATE"); DBG_RETURN(QC_TOKEN_COLLATE); } (?i:COLLATION) { *kn = yytext; DBG_INF("QC_TOKEN_COLLATION"); DBG_RETURN(QC_TOKEN_COLLATION); } (?i:COLUMNS) { *kn = yytext; DBG_INF("QC_TOKEN_COLUMNS"); DBG_RETURN(QC_TOKEN_COLUMNS); } (?i:COLUMN) { *kn = yytext; DBG_INF("QC_TOKEN_COLUMN"); DBG_RETURN(QC_TOKEN_COLUMN); } (?i:COLUMN_NAME) { *kn = yytext; DBG_INF("QC_TOKEN_COLUMN_NAME"); DBG_RETURN(QC_TOKEN_COLUMN_NAME); } (?i:COMMENT) { *kn = yytext; DBG_INF("QC_TOKEN_COMMENT"); DBG_RETURN(QC_TOKEN_COMMENT); } (?i:COMMITTED) { *kn = yytext; DBG_INF("QC_TOKEN_COMMITTED"); DBG_RETURN(QC_TOKEN_COMMITTED); } (?i:COMMIT) { *kn = yytext; DBG_INF("QC_TOKEN_COMMIT"); DBG_RETURN(QC_TOKEN_COMMIT); } (?i:COMPACT) { *kn = yytext; DBG_INF("QC_TOKEN_COMPACT"); DBG_RETURN(QC_TOKEN_COMPACT); } (?i:COMPLETION) { *kn = yytext; DBG_INF("QC_TOKEN_COMPLETION"); DBG_RETURN(QC_TOKEN_COMPLETION); } (?i:COMPRESSED) { *kn = yytext; DBG_INF("QC_TOKEN_COMPRESSED"); DBG_RETURN(QC_TOKEN_COMPRESSED); } (?i:CONCURRENT) { *kn = yytext; DBG_INF("QC_TOKEN_CONCURRENT"); DBG_RETURN(QC_TOKEN_CONCURRENT); } (?i:CONDITION) { *kn = yytext; DBG_INF("QC_TOKEN_CONDITION"); DBG_RETURN(QC_TOKEN_CONDITION); } (?i:CONNECTION) { *kn = yytext; DBG_INF("QC_TOKEN_CONNECTION"); DBG_RETURN(QC_TOKEN_CONNECTION); } (?i:CONSISTENT) { *kn = yytext; DBG_INF("QC_TOKEN_CONSISTENT"); DBG_RETURN(QC_TOKEN_CONSISTENT); } (?i:CONSTRAINT) { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT"); DBG_RETURN(QC_TOKEN_CONSTRAINT); } (?i:CONSTRAINT_CATALOG) { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT_CATALOG");DBG_RETURN(QC_TOKEN_CONSTRAINT_CATALOG); } (?i:CONSTRAINT_NAME) { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT_NAME"); DBG_RETURN(QC_TOKEN_CONSTRAINT_NAME); } (?i:CONSTRAINT_SCHEMA) { *kn = yytext; DBG_INF("QC_TOKEN_CONSTRAINT_SCHEMA");DBG_RETURN(QC_TOKEN_CONSTRAINT_SCHEMA); } (?i:CONTAINS) { *kn = yytext; DBG_INF("QC_TOKEN_CONTAINS"); DBG_RETURN(QC_TOKEN_CONTAINS); } (?i:CONTEXT) { *kn = yytext; DBG_INF("QC_TOKEN_CONTEXT"); DBG_RETURN(QC_TOKEN_CONTEXT); } (?i:CONTINUE) { *kn = yytext; DBG_INF("QC_TOKEN_CONTINUE"); DBG_RETURN(QC_TOKEN_CONTINUE); } (?i:CONTRIBUTORS) { *kn = yytext; DBG_INF("QC_TOKEN_CONTRIBUTORS"); DBG_RETURN(QC_TOKEN_CONTRIBUTORS); } (?i:CONVERT) { *kn = yytext; DBG_INF("QC_TOKEN_CONVERT"); DBG_RETURN(QC_TOKEN_CONVERT); } (?i:COUNT) { *kn = yytext; DBG_INF("QC_TOKEN_COUNT"); DBG_RETURN(QC_TOKEN_COUNT); } (?i:CPU) { *kn = yytext; DBG_INF("QC_TOKEN_CPU"); DBG_RETURN(QC_TOKEN_CPU); } (?i:CREATE) { *kn = yytext; DBG_INF("QC_TOKEN_CREATE"); DBG_RETURN(QC_TOKEN_CREATE); } (?i:CROSS) { *kn = yytext; DBG_INF("QC_TOKEN_CROSS"); DBG_RETURN(QC_TOKEN_CROSS); } (?i:CUBE) { *kn = yytext; DBG_INF("QC_TOKEN_CUBE"); DBG_RETURN(QC_TOKEN_CUBE); } (?i:CURDATE) { *kn = yytext; DBG_INF("QC_TOKEN_CURDATE"); DBG_RETURN(QC_TOKEN_CURDATE); } (?i:CURRENT_USER) { *kn = yytext; DBG_INF("QC_TOKEN_CURRENT_USER"); DBG_RETURN(QC_TOKEN_CURRENT_USER); } (?i:CURSOR) { *kn = yytext; DBG_INF("QC_TOKEN_CURSOR"); DBG_RETURN(QC_TOKEN_CURSOR); } (?i:CURSOR_NAME) { *kn = yytext; DBG_INF("QC_TOKEN_CURSOR_NAME"); DBG_RETURN(QC_TOKEN_CURSOR_NAME); } (?i:CURTIME) { *kn = yytext; DBG_INF("QC_TOKEN_CURTIME"); DBG_RETURN(QC_TOKEN_CURTIME); } (?i:DATABASE) { *kn = yytext; DBG_INF("QC_TOKEN_DATABASE"); DBG_RETURN(QC_TOKEN_DATABASE); } (?i:DATABASES) { *kn = yytext; DBG_INF("QC_TOKEN_DATABASES"); DBG_RETURN(QC_TOKEN_DATABASES); } (?i:DATAFILE) { *kn = yytext; DBG_INF("QC_TOKEN_DATAFILE"); DBG_RETURN(QC_TOKEN_DATAFILE); } (?i:DATA) { *kn = yytext; DBG_INF("QC_TOKEN_DATA"); DBG_RETURN(QC_TOKEN_DATA); } (?i:DATETIME) { *kn = yytext; DBG_INF("QC_TOKEN_DATETIME"); DBG_RETURN(QC_TOKEN_DATETIME); } (?i:DATE_ADD_INTERVAL) { *kn = yytext; DBG_INF("QC_TOKEN_DATE_ADD_INTERVAL");DBG_RETURN(QC_TOKEN_DATE_ADD_INTERVAL); } (?i:DATE_SUB_INTERVAL) { *kn = yytext; DBG_INF("QC_TOKEN_DATE_SUB_INTERVAL");DBG_RETURN(QC_TOKEN_DATE_SUB_INTERVAL); } (?i:DATE) { *kn = yytext; DBG_INF("QC_TOKEN_DATE"); DBG_RETURN(QC_TOKEN_DATE); } (?i:DAY_HOUR) { *kn = yytext; DBG_INF("QC_TOKEN_DAY_HOUR"); DBG_RETURN(QC_TOKEN_DAY_HOUR); } (?i:DAY_MICROSECOND) { *kn = yytext; DBG_INF("QC_TOKEN_DAY_MICROSECOND"); DBG_RETURN(QC_TOKEN_DAY_MICROSECOND); } (?i:DAY_MINUTE) { *kn = yytext; DBG_INF("QC_TOKEN_DAY_MINUTE"); DBG_RETURN(QC_TOKEN_DAY_MINUTE); } (?i:DAY_SECOND) { *kn = yytext; DBG_INF("QC_TOKEN_DAY_SECOND"); DBG_RETURN(QC_TOKEN_DAY_SECOND); } (?i:DAY) { *kn = yytext; DBG_INF("QC_TOKEN_DAY"); DBG_RETURN(QC_TOKEN_DAY); } (?i:DEALLOCATE) { *kn = yytext; DBG_INF("QC_TOKEN_DEALLOCATE"); DBG_RETURN(QC_TOKEN_DEALLOCATE); } (?i:DECIMAL_NUM) { *kn = yytext; DBG_INF("QC_TOKEN_DECIMAL_NUM"); DBG_RETURN(QC_TOKEN_DECIMAL_NUM); } (?i:DECIMAL) { *kn = yytext; DBG_INF("QC_TOKEN_DECIMAL"); DBG_RETURN(QC_TOKEN_DECIMAL); } (?i:DECLARE) { *kn = yytext; DBG_INF("QC_TOKEN_DECLARE"); DBG_RETURN(QC_TOKEN_DECLARE); } (?i:DEFAULT) { *kn = yytext; DBG_INF("QC_TOKEN_DEFAULT"); DBG_RETURN(QC_TOKEN_DEFAULT); } (?i:DEFINER) { *kn = yytext; DBG_INF("QC_TOKEN_DEFINER"); DBG_RETURN(QC_TOKEN_DEFINER); } (?i:DELAYED) { *kn = yytext; DBG_INF("QC_TOKEN_DELAYED"); DBG_RETURN(QC_TOKEN_DELAYED); } (?i:DELAY_KEY_WRITE) { *kn = yytext; DBG_INF("QC_TOKEN_DELAY_KEY_WRITE"); DBG_RETURN(QC_TOKEN_DELAY_KEY_WRITE); } (?i:DELETE) { *kn = yytext; DBG_INF("QC_TOKEN_DELETE"); DBG_RETURN(QC_TOKEN_DELETE); } (?i:DESC) { *kn = yytext; DBG_INF("QC_TOKEN_DESC"); DBG_RETURN(QC_TOKEN_DESC); } (?i:DESCRIBE) { *kn = yytext; DBG_INF("QC_TOKEN_DESCRIBE"); DBG_RETURN(QC_TOKEN_DESCRIBE); } (?i:DES_KEY_FILE) { *kn = yytext; DBG_INF("QC_TOKEN_DES_KEY_FILE"); DBG_RETURN(QC_TOKEN_DES_KEY_FILE); } (?i:DETERMINISTIC) { *kn = yytext; DBG_INF("QC_TOKEN_DETERMINISTIC"); DBG_RETURN(QC_TOKEN_DETERMINISTIC); } (?i:DIRECTORY) { *kn = yytext; DBG_INF("QC_TOKEN_DIRECTORY"); DBG_RETURN(QC_TOKEN_DIRECTORY); } (?i:DISABLE) { *kn = yytext; DBG_INF("QC_TOKEN_DISABLE"); DBG_RETURN(QC_TOKEN_DISABLE); } (?i:DISCARD) { *kn = yytext; DBG_INF("QC_TOKEN_DISCARD"); DBG_RETURN(QC_TOKEN_DISCARD); } (?i:DISK) { *kn = yytext; DBG_INF("QC_TOKEN_DISK"); DBG_RETURN(QC_TOKEN_DISK); } (?i:DISTINCT) { *kn = yytext; DBG_INF("QC_TOKEN_DISTINCT"); DBG_RETURN(QC_TOKEN_DISTINCT); } (?i:DIV) { *kn = yytext; DBG_INF("QC_TOKEN_DIV"); DBG_RETURN(QC_TOKEN_DIV); } (?i:DOUBLE) { *kn = yytext; DBG_INF("QC_TOKEN_DOUBLE"); DBG_RETURN(QC_TOKEN_DOUBLE); } (?i:DO) { *kn = yytext; DBG_INF("QC_TOKEN_DO"); DBG_RETURN(QC_TOKEN_DO); } (?i:DROP) { *kn = yytext; DBG_INF("QC_TOKEN_DROP"); DBG_RETURN(QC_TOKEN_DROP); } (?i:DUAL) { *kn = yytext; DBG_INF("QC_TOKEN_DUAL"); DBG_RETURN(QC_TOKEN_DUAL); } (?i:DUMPFILE) { *kn = yytext; DBG_INF("QC_TOKEN_DUMPFILE"); DBG_RETURN(QC_TOKEN_DUMPFILE); } (?i:DUPLICATE) { *kn = yytext; DBG_INF("QC_TOKEN_DUPLICATE"); DBG_RETURN(QC_TOKEN_DUPLICATE); } (?i:DYNAMIC) { *kn = yytext; DBG_INF("QC_TOKEN_DYNAMIC"); DBG_RETURN(QC_TOKEN_DYNAMIC); } (?i:EACH) { *kn = yytext; DBG_INF("QC_TOKEN_EACH"); DBG_RETURN(QC_TOKEN_EACH); } (?i:ELSE) { *kn = yytext; DBG_INF("QC_TOKEN_ELSE"); DBG_RETURN(QC_TOKEN_ELSE); } (?i:ELSEIF) { *kn = yytext; DBG_INF("QC_TOKEN_ELSEIF"); DBG_RETURN(QC_TOKEN_ELSEIF); } (?i:ENABLE) { *kn = yytext; DBG_INF("QC_TOKEN_ENABLE"); DBG_RETURN(QC_TOKEN_ENABLE); } (?i:ENCLOSED) { *kn = yytext; DBG_INF("QC_TOKEN_ENCLOSED"); DBG_RETURN(QC_TOKEN_ENCLOSED); } (?i:END) { *kn = yytext; DBG_INF("QC_TOKEN_END"); DBG_RETURN(QC_TOKEN_END); } (?i:ENDS) { *kn = yytext; DBG_INF("QC_TOKEN_ENDS"); DBG_RETURN(QC_TOKEN_ENDS); } (?i:ENGINES) { *kn = yytext; DBG_INF("QC_TOKEN_ENGINES"); DBG_RETURN(QC_TOKEN_ENGINES); } (?i:ENGINE) { *kn = yytext; DBG_INF("QC_TOKEN_ENGINE"); DBG_RETURN(QC_TOKEN_ENGINE); } (?i:ENUM) { *kn = yytext; DBG_INF("QC_TOKEN_ENUM"); DBG_RETURN(QC_TOKEN_ENUM); } (?i:EQUAL) { *kn = yytext; DBG_INF("QC_TOKEN_EQUAL"); DBG_RETURN(QC_TOKEN_EQUAL); } (?i:ERRORS) { *kn = yytext; DBG_INF("QC_TOKEN_ERRORS"); DBG_RETURN(QC_TOKEN_ERRORS); } (?i:ESCAPED) { *kn = yytext; DBG_INF("QC_TOKEN_ESCAPED"); DBG_RETURN(QC_TOKEN_ESCAPED); } (?i:ESCAPE) { *kn = yytext; DBG_INF("QC_TOKEN_ESCAPE"); DBG_RETURN(QC_TOKEN_ESCAPE); } (?i:EVENTS) { *kn = yytext; DBG_INF("QC_TOKEN_EVENTS"); DBG_RETURN(QC_TOKEN_EVENTS); } (?i:EVENT) { *kn = yytext; DBG_INF("QC_TOKEN_EVENT"); DBG_RETURN(QC_TOKEN_EVENT); } (?i:EVERY) { *kn = yytext; DBG_INF("QC_TOKEN_EVERY"); DBG_RETURN(QC_TOKEN_EVERY); } (?i:EXECUTE) { *kn = yytext; DBG_INF("QC_TOKEN_EXECUTE"); DBG_RETURN(QC_TOKEN_EXECUTE); } (?i:EXISTS) { *kn = yytext; DBG_INF("QC_TOKEN_EXISTS"); DBG_RETURN(QC_TOKEN_EXISTS); } (?i:EXIT) { *kn = yytext; DBG_INF("QC_TOKEN_EXIT"); DBG_RETURN(QC_TOKEN_EXIT); } (?i:EXPANSION) { *kn = yytext; DBG_INF("QC_TOKEN_EXPANSION"); DBG_RETURN(QC_TOKEN_EXPANSION); } (?i:EXTENDED) { *kn = yytext; DBG_INF("QC_TOKEN_EXTENDED"); DBG_RETURN(QC_TOKEN_EXTENDED); } (?i:EXTENT_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_EXTENT_SIZE"); DBG_RETURN(QC_TOKEN_EXTENT_SIZE); } (?i:EXTRACT) { *kn = yytext; DBG_INF("QC_TOKEN_EXTRACT"); DBG_RETURN(QC_TOKEN_EXTRACT); } (?i:FALSE) { *kn = yytext; DBG_INF("QC_TOKEN_FALSE"); DBG_RETURN(QC_TOKEN_FALSE); } (?i:FAST) { *kn = yytext; DBG_INF("QC_TOKEN_FAST"); DBG_RETURN(QC_TOKEN_FAST); } (?i:FAULTS) { *kn = yytext; DBG_INF("QC_TOKEN_FAULTS"); DBG_RETURN(QC_TOKEN_FAULTS); } (?i:FETCH) { *kn = yytext; DBG_INF("QC_TOKEN_FETCH"); DBG_RETURN(QC_TOKEN_FETCH); } (?i:FILE) { *kn = yytext; DBG_INF("QC_TOKEN_FILE"); DBG_RETURN(QC_TOKEN_FILE); } (?i:FIRST) { *kn = yytext; DBG_INF("QC_TOKEN_FIRST"); DBG_RETURN(QC_TOKEN_FIRST); } (?i:FIXED) { *kn = yytext; DBG_INF("QC_TOKEN_FIXED"); DBG_RETURN(QC_TOKEN_FIXED); } (?i:FLOAT_NUM) { *kn = yytext; DBG_INF("QC_TOKEN_FLOAT_NUM"); DBG_RETURN(QC_TOKEN_FLOAT_NUM); } (?i:FLOAT) { *kn = yytext; DBG_INF("QC_TOKEN_FLOAT"); DBG_RETURN(QC_TOKEN_FLOAT); } (?i:FLUSH) { *kn = yytext; DBG_INF("QC_TOKEN_FLUSH"); DBG_RETURN(QC_TOKEN_FLUSH); } (?i:FORCE) { *kn = yytext; DBG_INF("QC_TOKEN_FORCE"); DBG_RETURN(QC_TOKEN_FORCE); } (?i:FOREIGN) { *kn = yytext; DBG_INF("QC_TOKEN_FOREIGN"); DBG_RETURN(QC_TOKEN_FOREIGN); } (?i:FOR) { *kn = yytext; DBG_INF("QC_TOKEN_FOR"); DBG_RETURN(QC_TOKEN_FOR); } (?i:FOUND) { *kn = yytext; DBG_INF("QC_TOKEN_FOUND"); DBG_RETURN(QC_TOKEN_FOUND); } (?i:FRAC_SECOND) { *kn = yytext; DBG_INF("QC_TOKEN_FRAC_SECOND"); DBG_RETURN(QC_TOKEN_FRAC_SECOND); } (?i:FROM) { *kn = yytext; DBG_INF("QC_TOKEN_FROM"); DBG_RETURN(QC_TOKEN_FROM); } (?i:FULL) { *kn = yytext; DBG_INF("QC_TOKEN_FULL"); DBG_RETURN(QC_TOKEN_FULL); } (?i:FULLTEXT) { *kn = yytext; DBG_INF("QC_TOKEN_FULLTEXT"); DBG_RETURN(QC_TOKEN_FULLTEXT); } (?i:FUNCTION) { *kn = yytext; DBG_INF("QC_TOKEN_FUNCTION"); DBG_RETURN(QC_TOKEN_FUNCTION); } (?i:GEOMETRYCOLLECTION) { *kn = yytext; DBG_INF("QC_TOKEN_GEOMETRYCOLLECTION");DBG_RETURN(QC_TOKEN_GEOMETRYCOLLECTION); } (?i:GEOMETRY) { *kn = yytext; DBG_INF("QC_TOKEN_GEOMETRY"); DBG_RETURN(QC_TOKEN_GEOMETRY); } (?i:GET_FORMAT) { *kn = yytext; DBG_INF("QC_TOKEN_GET_FORMAT"); DBG_RETURN(QC_TOKEN_GET_FORMAT); } (?i:GLOBAL) { *kn = yytext; DBG_INF("QC_TOKEN_GLOBAL"); DBG_RETURN(QC_TOKEN_GLOBAL); } (?i:GRANT) { *kn = yytext; DBG_INF("QC_TOKEN_GRANT"); DBG_RETURN(QC_TOKEN_GRANT); } (?i:GRANTS) { *kn = yytext; DBG_INF("QC_TOKEN_GRANTS"); DBG_RETURN(QC_TOKEN_GRANTS); } (?i:GROUP[:space]+BY) { *kn = yytext; DBG_INF("QC_TOKEN_GROUP"); DBG_RETURN(QC_TOKEN_GROUP); } (?i:GROUP) { *kn = yytext; DBG_INF("QC_TOKEN_GROUP"); DBG_RETURN(QC_TOKEN_GROUP); } (?i:GROUP_CONCAT) { *kn = yytext; DBG_INF("QC_TOKEN_GROUP_CONCAT"); DBG_RETURN(QC_TOKEN_GROUP_CONCAT); } (?i:HANDLER) { *kn = yytext; DBG_INF("QC_TOKEN_HANDLER"); DBG_RETURN(QC_TOKEN_HANDLER); } (?i:HASH) { *kn = yytext; DBG_INF("QC_TOKEN_HASH"); DBG_RETURN(QC_TOKEN_HASH); } (?i:HAVING) { *kn = yytext; DBG_INF("QC_TOKEN_HAVING"); DBG_RETURN(QC_TOKEN_HAVING); } (?i:HELP) { *kn = yytext; DBG_INF("QC_TOKEN_HELP"); DBG_RETURN(QC_TOKEN_HELP); } (?i:HEX_NUM) { *kn = yytext; DBG_INF("QC_TOKEN_HEX_NUM"); DBG_RETURN(QC_TOKEN_HEX_NUM); } (?i:HIGH_PRIORITY) { *kn = yytext; DBG_INF("QC_TOKEN_HIGH_PRIORITY"); DBG_RETURN(QC_TOKEN_HIGH_PRIORITY); } (?i:HOST) { *kn = yytext; DBG_INF("QC_TOKEN_HOST"); DBG_RETURN(QC_TOKEN_HOST); } (?i:HOSTS) { *kn = yytext; DBG_INF("QC_TOKEN_HOSTS"); DBG_RETURN(QC_TOKEN_HOSTS); } (?i:HOUR_MICROSECOND) { *kn = yytext; DBG_INF("QC_TOKEN_HOUR_MICROSECOND"); DBG_RETURN(QC_TOKEN_HOUR_MICROSECOND); } (?i:HOUR_MINUTE) { *kn = yytext; DBG_INF("QC_TOKEN_HOUR_MINUTE"); DBG_RETURN(QC_TOKEN_HOUR_MINUTE); } (?i:HOUR_SECOND) { *kn = yytext; DBG_INF("QC_TOKEN_HOUR_SECOND"); DBG_RETURN(QC_TOKEN_HOUR_SECOND); } (?i:HOUR) { *kn = yytext; DBG_INF("QC_TOKEN_HOUR"); DBG_RETURN(QC_TOKEN_HOUR); } (?i:IDENT) { *kn = yytext; DBG_INF("QC_TOKEN_IDENT"); DBG_RETURN(QC_TOKEN_IDENT); } (?i:IDENTIFIED) { *kn = yytext; DBG_INF("QC_TOKEN_IDENTIFIED"); DBG_RETURN(QC_TOKEN_IDENTIFIED); } (?i:IDENT_QUOTED) { *kn = yytext; DBG_INF("QC_TOKEN_IDENT_QUOTED"); DBG_RETURN(QC_TOKEN_IDENT_QUOTED); } (?i:IF) { *kn = yytext; DBG_INF("QC_TOKEN_IF"); DBG_RETURN(QC_TOKEN_IF); } (?i:IGNORE) { *kn = yytext; DBG_INF("QC_TOKEN_IGNORE"); DBG_RETURN(QC_TOKEN_IGNORE); } (?i:IGNORE_SERVER_IDS) { *kn = yytext; DBG_INF("QC_TOKEN_IGNORE_SERVER_IDS");DBG_RETURN(QC_TOKEN_IGNORE_SERVER_IDS); } (?i:IMPORT) { *kn = yytext; DBG_INF("QC_TOKEN_IMPORT"); DBG_RETURN(QC_TOKEN_IMPORT); } (?i:INDEXES) { *kn = yytext; DBG_INF("QC_TOKEN_INDEXES"); DBG_RETURN(QC_TOKEN_INDEXES); } (?i:INDEX) { *kn = yytext; DBG_INF("QC_TOKEN_INDEX"); DBG_RETURN(QC_TOKEN_INDEX); } (?i:INFILE) { *kn = yytext; DBG_INF("QC_TOKEN_INFILE"); DBG_RETURN(QC_TOKEN_INFILE); } (?i:INITIAL_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_INITIAL_SIZE"); DBG_RETURN(QC_TOKEN_INITIAL_SIZE); } (?i:INNER) { *kn = yytext; DBG_INF("QC_TOKEN_INNER"); DBG_RETURN(QC_TOKEN_INNER); } (?i:INOUT) { *kn = yytext; DBG_INF("QC_TOKEN_INOUT"); DBG_RETURN(QC_TOKEN_INOUT); } (?i:INSENSITIVE) { *kn = yytext; DBG_INF("QC_TOKEN_INSENSITIVE"); DBG_RETURN(QC_TOKEN_INSENSITIVE); } (?i:INSERT) { *kn = yytext; DBG_INF("QC_TOKEN_INSERT"); DBG_RETURN(QC_TOKEN_INSERT); } (?i:INSERT_METHOD) { *kn = yytext; DBG_INF("QC_TOKEN_INSERT_METHOD"); DBG_RETURN(QC_TOKEN_INSERT_METHOD); } (?i:INSTALL) { *kn = yytext; DBG_INF("QC_TOKEN_INSTALL"); DBG_RETURN(QC_TOKEN_INSTALL); } (?i:INTERVAL) { *kn = yytext; DBG_INF("QC_TOKEN_INTERVAL"); DBG_RETURN(QC_TOKEN_INTERVAL); } (?i:INTO) { *kn = yytext; DBG_INF("QC_TOKEN_INTO"); DBG_RETURN(QC_TOKEN_INTO); } (?i:INT) { *kn = yytext; DBG_INF("QC_TOKEN_INT"); DBG_RETURN(QC_TOKEN_INT); } (?i:INVOKER) { *kn = yytext; DBG_INF("QC_TOKEN_INVOKER"); DBG_RETURN(QC_TOKEN_INVOKER); } (?i:IN) { *kn = yytext; DBG_INF("QC_TOKEN_IN"); DBG_RETURN(QC_TOKEN_IN); } (?i:IO) { *kn = yytext; DBG_INF("QC_TOKEN_IO"); DBG_RETURN(QC_TOKEN_IO); } (?i:IPC) { *kn = yytext; DBG_INF("QC_TOKEN_IPC"); DBG_RETURN(QC_TOKEN_IPC); } (?i:IS) { *kn = yytext; DBG_INF("QC_TOKEN_IS"); DBG_RETURN(QC_TOKEN_IS); } (?i:ISOLATION) { *kn = yytext; DBG_INF("QC_TOKEN_ISOLATION"); DBG_RETURN(QC_TOKEN_ISOLATION); } (?i:ISSUER) { *kn = yytext; DBG_INF("QC_TOKEN_ISSUER"); DBG_RETURN(QC_TOKEN_ISSUER); } (?i:ITERATE) { *kn = yytext; DBG_INF("QC_TOKEN_ITERATE"); DBG_RETURN(QC_TOKEN_ITERATE); } (?i:JOIN) { *kn = yytext; DBG_INF("QC_TOKEN_JOIN"); DBG_RETURN(QC_TOKEN_JOIN); } (?i:KEYS) { *kn = yytext; DBG_INF("QC_TOKEN_KEYS"); DBG_RETURN(QC_TOKEN_KEYS); } (?i:KEY_BLOCK_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_KEY_BLOCK_SIZE"); DBG_RETURN(QC_TOKEN_KEY_BLOCK_SIZE); } (?i:KEY) { *kn = yytext; DBG_INF("QC_TOKEN_KEY"); DBG_RETURN(QC_TOKEN_KEY); } (?i:KILL) { *kn = yytext; DBG_INF("QC_TOKEN_KILL"); DBG_RETURN(QC_TOKEN_KILL); } (?i:LANGUAGE) { *kn = yytext; DBG_INF("QC_TOKEN_LANGUAGE"); DBG_RETURN(QC_TOKEN_LANGUAGE); } (?i:LAST) { *kn = yytext; DBG_INF("QC_TOKEN_LAST"); DBG_RETURN(QC_TOKEN_LAST); } (?i:LEADING) { *kn = yytext; DBG_INF("QC_TOKEN_LEADING"); DBG_RETURN(QC_TOKEN_LEADING); } (?i:LEAVES) { *kn = yytext; DBG_INF("QC_TOKEN_LEAVES"); DBG_RETURN(QC_TOKEN_LEAVES); } (?i:LEAVE) { *kn = yytext; DBG_INF("QC_TOKEN_LEAVE"); DBG_RETURN(QC_TOKEN_LEAVE); } (?i:LEFT) { *kn = yytext; DBG_INF("QC_TOKEN_LEFT"); DBG_RETURN(QC_TOKEN_LEFT); } (?i:LESS) { *kn = yytext; DBG_INF("QC_TOKEN_LESS"); DBG_RETURN(QC_TOKEN_LESS); } (?i:LEVEL) { *kn = yytext; DBG_INF("QC_TOKEN_LEVEL"); DBG_RETURN(QC_TOKEN_LEVEL); } (?i:LEX_HOSTNAME) { *kn = yytext; DBG_INF("QC_TOKEN_LEX_HOSTNAME"); DBG_RETURN(QC_TOKEN_LEX_HOSTNAME); } (?i:LIKE) { *kn = yytext; DBG_INF("QC_TOKEN_LIKE"); DBG_RETURN(QC_TOKEN_LIKE); } (?i:LIMIT) { *kn = yytext; DBG_INF("QC_TOKEN_LIMIT"); DBG_RETURN(QC_TOKEN_LIMIT); } (?i:LINEAR) { *kn = yytext; DBG_INF("QC_TOKEN_LINEAR"); DBG_RETURN(QC_TOKEN_LINEAR); } (?i:LINES) { *kn = yytext; DBG_INF("QC_TOKEN_LINES"); DBG_RETURN(QC_TOKEN_LINES); } (?i:LINESTRING) { *kn = yytext; DBG_INF("QC_TOKEN_LINESTRING"); DBG_RETURN(QC_TOKEN_LINESTRING); } (?i:LIST) { *kn = yytext; DBG_INF("QC_TOKEN_LIST"); DBG_RETURN(QC_TOKEN_LIST); } (?i:LOAD) { *kn = yytext; DBG_INF("QC_TOKEN_LOAD"); DBG_RETURN(QC_TOKEN_LOAD); } (?i:LOCAL) { *kn = yytext; DBG_INF("QC_TOKEN_LOCAL"); DBG_RETURN(QC_TOKEN_LOCAL); } (?i:LOCATOR) { *kn = yytext; DBG_INF("QC_TOKEN_LOCATOR"); DBG_RETURN(QC_TOKEN_LOCATOR); } (?i:LOCKS) { *kn = yytext; DBG_INF("QC_TOKEN_LOCKS"); DBG_RETURN(QC_TOKEN_LOCKS); } (?i:LOCK) { *kn = yytext; DBG_INF("QC_TOKEN_LOCK"); DBG_RETURN(QC_TOKEN_LOCK); } (?i:LOGFILE) { *kn = yytext; DBG_INF("QC_TOKEN_LOGFILE"); DBG_RETURN(QC_TOKEN_LOGFILE); } (?i:LOGS) { *kn = yytext; DBG_INF("QC_TOKEN_LOGS"); DBG_RETURN(QC_TOKEN_LOGS); } (?i:LONGBLOB) { *kn = yytext; DBG_INF("QC_TOKEN_LONGBLOB"); DBG_RETURN(QC_TOKEN_LONGBLOB); } (?i:LONGTEXT) { *kn = yytext; DBG_INF("QC_TOKEN_LONGTEXT"); DBG_RETURN(QC_TOKEN_LONGTEXT); } (?i:LONG_NUM) { *kn = yytext; DBG_INF("QC_TOKEN_LONG_NUM"); DBG_RETURN(QC_TOKEN_LONG_NUM); } (?i:LONG) { *kn = yytext; DBG_INF("QC_TOKEN_LONG"); DBG_RETURN(QC_TOKEN_LONG); } (?i:LOOP) { *kn = yytext; DBG_INF("QC_TOKEN_LOOP"); DBG_RETURN(QC_TOKEN_LOOP); } (?i:LOW_PRIORITY) { *kn = yytext; DBG_INF("QC_TOKEN_LOW_PRIORITY"); DBG_RETURN(QC_TOKEN_LOW_PRIORITY); } (?i:MASTER_CONNECT_RETRY) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_CONNECT_RETRY"); DBG_RETURN(QC_TOKEN_MASTER_CONNECT_RETRY); } (?i:MASTER_HOST) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_HOST"); DBG_RETURN(QC_TOKEN_MASTER_HOST); } (?i:MASTER_LOG_FILE) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_LOG_FILE"); DBG_RETURN(QC_TOKEN_MASTER_LOG_FILE); } (?i:MASTER_LOG_POS) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_LOG_POS"); DBG_RETURN(QC_TOKEN_MASTER_LOG_POS); } (?i:MASTER_PASSWORD) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_PASSWORD"); DBG_RETURN(QC_TOKEN_MASTER_PASSWORD); } (?i:MASTER_PORT) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_PORT"); DBG_RETURN(QC_TOKEN_MASTER_PORT); } (?i:MASTER_SERVER_ID) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SERVER_ID"); DBG_RETURN(QC_TOKEN_MASTER_SERVER_ID); } (?i:MASTER_SSL_CAPATH) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CAPATH");DBG_RETURN(QC_TOKEN_MASTER_SSL_CAPATH); } (?i:MASTER_SSL_CA) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CA"); DBG_RETURN(QC_TOKEN_MASTER_SSL_CA); } (?i:MASTER_SSL_CERT) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CERT"); DBG_RETURN(QC_TOKEN_MASTER_SSL_CERT); } (?i:MASTER_SSL_CIPHER) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_CIPHER");DBG_RETURN(QC_TOKEN_MASTER_SSL_CIPHER); } (?i:MASTER_SSL_KEY) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_KEY"); DBG_RETURN(QC_TOKEN_MASTER_SSL_KEY); } (?i:MASTER_SSL) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL"); DBG_RETURN(QC_TOKEN_MASTER_SSL); } (?i:MASTER_SSL_VERIFY_SERVER_CERT) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT"); DBG_RETURN(QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT); } (?i:MASTER) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER"); DBG_RETURN(QC_TOKEN_MASTER); } (?i:MASTER_USER) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_USER"); DBG_RETURN(QC_TOKEN_MASTER_USER); } (?i:MASTER_HEARTBEAT_PERIOD) { *kn = yytext; DBG_INF("QC_TOKEN_MASTER_HEARTBEAT_PERIOD"); DBG_RETURN(QC_TOKEN_MASTER_HEARTBEAT_PERIOD); } (?i:MATCH) { *kn = yytext; DBG_INF("QC_TOKEN_MATCH"); DBG_RETURN(QC_TOKEN_MATCH); } (?i:MAX_CONNECTIONS_PER_HOUR) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_CONNECTIONS_PER_HOUR"); DBG_RETURN(QC_TOKEN_MAX_CONNECTIONS_PER_HOUR); } (?i:MAX_QUERIES_PER_HOUR) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_QUERIES_PER_HOUR"); DBG_RETURN(QC_TOKEN_MAX_QUERIES_PER_HOUR); } (?i:MAX_ROWS) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_ROWS"); DBG_RETURN(QC_TOKEN_MAX_ROWS); } (?i:MAX_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_SIZE"); DBG_RETURN(QC_TOKEN_MAX_SIZE); } (?i:MAX) { *kn = yytext; DBG_INF("QC_TOKEN_MAX"); DBG_RETURN(QC_TOKEN_MAX); } (?i:MAX_UPDATES_PER_HOUR) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_UPDATES_PER_HOUR"); DBG_RETURN(QC_TOKEN_MAX_UPDATES_PER_HOUR); } (?i:MAX_USER_CONNECTIONS) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_USER_CONNECTIONS"); DBG_RETURN(QC_TOKEN_MAX_USER_CONNECTIONS); } (?i:MAX_VALUE) { *kn = yytext; DBG_INF("QC_TOKEN_MAX_VALUE"); DBG_RETURN(QC_TOKEN_MAX_VALUE); } (?i:MEDIUMBLOB) { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUMBLOB"); DBG_RETURN(QC_TOKEN_MEDIUMBLOB); } (?i:MEDIUMINT) { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUMINT"); DBG_RETURN(QC_TOKEN_MEDIUMINT); } (?i:MEDIUMTEXT) { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUMTEXT"); DBG_RETURN(QC_TOKEN_MEDIUMTEXT); } (?i:MEDIUM) { *kn = yytext; DBG_INF("QC_TOKEN_MEDIUM"); DBG_RETURN(QC_TOKEN_MEDIUM); } (?i:MEMORY) { *kn = yytext; DBG_INF("QC_TOKEN_MEMORY"); DBG_RETURN(QC_TOKEN_MEMORY); } (?i:MERGE) { *kn = yytext; DBG_INF("QC_TOKEN_MERGE"); DBG_RETURN(QC_TOKEN_MERGE); } (?i:MESSAGE_TEXT) { *kn = yytext; DBG_INF("QC_TOKEN_MESSAGE_TEXT"); DBG_RETURN(QC_TOKEN_MESSAGE_TEXT); } (?i:MICROSECOND) { *kn = yytext; DBG_INF("QC_TOKEN_MICROSECOND"); DBG_RETURN(QC_TOKEN_MICROSECOND); } (?i:MIGRATE) { *kn = yytext; DBG_INF("QC_TOKEN_MIGRATE"); DBG_RETURN(QC_TOKEN_MIGRATE); } (?i:MINUTE_MICROSECOND) { *kn = yytext; DBG_INF("QC_TOKEN_MINUTE_MICROSECOND");DBG_RETURN(QC_TOKEN_MINUTE_MICROSECOND); } (?i:MINUTE_SECOND) { *kn = yytext; DBG_INF("QC_TOKEN_MINUTE_SECOND"); DBG_RETURN(QC_TOKEN_MINUTE_SECOND); } (?i:MINUTE) { *kn = yytext; DBG_INF("QC_TOKEN_MINUTE"); DBG_RETURN(QC_TOKEN_MINUTE); } (?i:MIN_ROWS) { *kn = yytext; DBG_INF("QC_TOKEN_MIN_ROWS"); DBG_RETURN(QC_TOKEN_MIN_ROWS); } (?i:MIN) { *kn = yytext; DBG_INF("QC_TOKEN_MIN"); DBG_RETURN(QC_TOKEN_MIN); } (?i:MODE) { *kn = yytext; DBG_INF("QC_TOKEN_MODE"); DBG_RETURN(QC_TOKEN_MODE); } (?i:MODIFIES) { *kn = yytext; DBG_INF("QC_TOKEN_MODIFIES"); DBG_RETURN(QC_TOKEN_MODIFIES); } (?i:MODIFY) { *kn = yytext; DBG_INF("QC_TOKEN_MODIFY"); DBG_RETURN(QC_TOKEN_MODIFY); } (?i:MOD) { *kn = yytext; DBG_INF("QC_TOKEN_MOD"); DBG_RETURN(QC_TOKEN_MOD); } (?i:MONTH) { *kn = yytext; DBG_INF("QC_TOKEN_MONTH"); DBG_RETURN(QC_TOKEN_MONTH); } (?i:MULTILINESTRING) { *kn = yytext; DBG_INF("QC_TOKEN_MULTILINESTRING"); DBG_RETURN(QC_TOKEN_MULTILINESTRING); } (?i:MULTIPOINT) { *kn = yytext; DBG_INF("QC_TOKEN_MULTIPOINT"); DBG_RETURN(QC_TOKEN_MULTIPOINT); } (?i:MULTIPOLYGON) { *kn = yytext; DBG_INF("QC_TOKEN_MULTIPOLYGON"); DBG_RETURN(QC_TOKEN_MULTIPOLYGON); } (?i:MUTEX) { *kn = yytext; DBG_INF("QC_TOKEN_MUTEX"); DBG_RETURN(QC_TOKEN_MUTEX); } (?i:MYSQL_ERRNO) { *kn = yytext; DBG_INF("QC_TOKEN_MYSQL_ERRNO"); DBG_RETURN(QC_TOKEN_MYSQL_ERRNO); } (?i:NAMES) { *kn = yytext; DBG_INF("QC_TOKEN_NAMES"); DBG_RETURN(QC_TOKEN_NAMES); } (?i:NAME) { *kn = yytext; DBG_INF("QC_TOKEN_NAME"); DBG_RETURN(QC_TOKEN_NAME); } (?i:NATIONAL) { *kn = yytext; DBG_INF("QC_TOKEN_NATIONAL"); DBG_RETURN(QC_TOKEN_NATIONAL); } (?i:NATURAL) { *kn = yytext; DBG_INF("QC_TOKEN_NATURAL"); DBG_RETURN(QC_TOKEN_NATURAL); } (?i:NCHAR_STRING) { *kn = yytext; DBG_INF("QC_TOKEN_NCHAR_STRING"); DBG_RETURN(QC_TOKEN_NCHAR_STRING); } (?i:NCHAR) { *kn = yytext; DBG_INF("QC_TOKEN_NCHAR"); DBG_RETURN(QC_TOKEN_NCHAR); } (?i:NDBCLUSTER) { *kn = yytext; DBG_INF("QC_TOKEN_NDBCLUSTER"); DBG_RETURN(QC_TOKEN_NDBCLUSTER); } (?i:NEG) { *kn = yytext; DBG_INF("QC_TOKEN_NEG"); DBG_RETURN(QC_TOKEN_NEG); } (?i:NEW) { *kn = yytext; DBG_INF("QC_TOKEN_NEW"); DBG_RETURN(QC_TOKEN_NEW); } (?i:NEXT) { *kn = yytext; DBG_INF("QC_TOKEN_NEXT"); DBG_RETURN(QC_TOKEN_NEXT); } (?i:NODEGROUP) { *kn = yytext; DBG_INF("QC_TOKEN_NODEGROUP"); DBG_RETURN(QC_TOKEN_NODEGROUP); } (?i:NONE) { *kn = yytext; DBG_INF("QC_TOKEN_NONE"); DBG_RETURN(QC_TOKEN_NONE); } (?i:NOT) { *kn = yytext; DBG_INF("QC_TOKEN_NOT"); DBG_RETURN(QC_TOKEN_NOT); } (?i:NOW) { *kn = yytext; DBG_INF("QC_TOKEN_NOW"); DBG_RETURN(QC_TOKEN_NOW); } (?i:NO) { *kn = yytext; DBG_INF("QC_TOKEN_NO"); DBG_RETURN(QC_TOKEN_NO); } (?i:NO_WAIT) { *kn = yytext; DBG_INF("QC_TOKEN_NO_WAIT"); DBG_RETURN(QC_TOKEN_NO_WAIT); } (?i:NO_WRITE_TO_BINLOG) { *kn = yytext; DBG_INF("QC_TOKEN_NO_WRITE_TO_BINLOG");DBG_RETURN(QC_TOKEN_NO_WRITE_TO_BINLOG); } (?i:NULL) { *kn = yytext; DBG_INF("QC_TOKEN_NULL"); DBG_RETURN(QC_TOKEN_NULL); } (?i:NUM) { *kn = yytext; DBG_INF("QC_TOKEN_NUM"); DBG_RETURN(QC_TOKEN_NUM); } (?i:NUMERIC) { *kn = yytext; DBG_INF("QC_TOKEN_NUMERIC"); DBG_RETURN(QC_TOKEN_NUMERIC); } (?i:NVARCHAR) { *kn = yytext; DBG_INF("QC_TOKEN_NVARCHAR"); DBG_RETURN(QC_TOKEN_NVARCHAR); } (?i:OFFSET) { *kn = yytext; DBG_INF("QC_TOKEN_OFFSET"); DBG_RETURN(QC_TOKEN_OFFSET); } (?i:OLD_PASSWORD) { *kn = yytext; DBG_INF("QC_TOKEN_OLD_PASSWORD"); DBG_RETURN(QC_TOKEN_OLD_PASSWORD); } (?i:ON) { *kn = yytext; DBG_INF("QC_TOKEN_ON"); DBG_RETURN(QC_TOKEN_ON); } (?i:ONE_SHOT) { *kn = yytext; DBG_INF("QC_TOKEN_ONE_SHOT"); DBG_RETURN(QC_TOKEN_ONE_SHOT); } (?i:ONE) { *kn = yytext; DBG_INF("QC_TOKEN_ONE"); DBG_RETURN(QC_TOKEN_ONE); } (?i:OPEN) { *kn = yytext; DBG_INF("QC_TOKEN_OPEN"); DBG_RETURN(QC_TOKEN_OPEN); } (?i:OPTIMIZE) { *kn = yytext; DBG_INF("QC_TOKEN_OPTIMIZE"); DBG_RETURN(QC_TOKEN_OPTIMIZE); } (?i:OPTIONS) { *kn = yytext; DBG_INF("QC_TOKEN_OPTIONS"); DBG_RETURN(QC_TOKEN_OPTIONS); } (?i:OPTION) { *kn = yytext; DBG_INF("QC_TOKEN_OPTION"); DBG_RETURN(QC_TOKEN_OPTION); } (?i:OPTIONALLY) { *kn = yytext; DBG_INF("QC_TOKEN_OPTIONALLY"); DBG_RETURN(QC_TOKEN_OPTIONALLY); } (?i:ORDER) { *kn = yytext; DBG_INF("QC_TOKEN_ORDER"); DBG_RETURN(QC_TOKEN_ORDER); } (?i:OR) { *kn = yytext; DBG_INF("QC_TOKEN_OR"); DBG_RETURN(QC_TOKEN_OR); } (?i:OUTER) { *kn = yytext; DBG_INF("QC_TOKEN_OUTER"); DBG_RETURN(QC_TOKEN_OUTER); } (?i:OUTFILE) { *kn = yytext; DBG_INF("QC_TOKEN_OUTFILE"); DBG_RETURN(QC_TOKEN_OUTFILE); } (?i:OUT) { *kn = yytext; DBG_INF("QC_TOKEN_OUT"); DBG_RETURN(QC_TOKEN_OUT); } (?i:OWNER) { *kn = yytext; DBG_INF("QC_TOKEN_OWNER"); DBG_RETURN(QC_TOKEN_OWNER); } (?i:PACK_KEYS) { *kn = yytext; DBG_INF("QC_TOKEN_PACK_KEYS"); DBG_RETURN(QC_TOKEN_PACK_KEYS); } (?i:PAGE) { *kn = yytext; DBG_INF("QC_TOKEN_PAGE"); DBG_RETURN(QC_TOKEN_PAGE); } (?i:PARAM_MARKER) { *kn = yytext; DBG_INF("QC_TOKEN_PARAM_MARKER"); DBG_RETURN(QC_TOKEN_PARAM_MARKER); } (?i:PARSER) { *kn = yytext; DBG_INF("QC_TOKEN_PARSER"); DBG_RETURN(QC_TOKEN_PARSER); } (?i:PARTIAL) { *kn = yytext; DBG_INF("QC_TOKEN_PARTIAL"); DBG_RETURN(QC_TOKEN_PARTIAL); } (?i:PARTITIONING) { *kn = yytext; DBG_INF("QC_TOKEN_PARTITIONING"); DBG_RETURN(QC_TOKEN_PARTITIONING); } (?i:PARTITIONS) { *kn = yytext; DBG_INF("QC_TOKEN_PARTITIONS"); DBG_RETURN(QC_TOKEN_PARTITIONS); } (?i:PARTITION) { *kn = yytext; DBG_INF("QC_TOKEN_PARTITION"); DBG_RETURN(QC_TOKEN_PARTITION); } (?i:PASSWORD) { *kn = yytext; DBG_INF("QC_TOKEN_PASSWORD"); DBG_RETURN(QC_TOKEN_PASSWORD); } (?i:PHASE) { *kn = yytext; DBG_INF("QC_TOKEN_PHASE"); DBG_RETURN(QC_TOKEN_PHASE); } (?i:PLUGINS) { *kn = yytext; DBG_INF("QC_TOKEN_PLUGINS"); DBG_RETURN(QC_TOKEN_PLUGINS); } (?i:PLUGIN) { *kn = yytext; DBG_INF("QC_TOKEN_PLUGIN"); DBG_RETURN(QC_TOKEN_PLUGIN); } (?i:POINT) { *kn = yytext; DBG_INF("QC_TOKEN_POINT"); DBG_RETURN(QC_TOKEN_POINT); } (?i:POLYGON) { *kn = yytext; DBG_INF("QC_TOKEN_POLYGON"); DBG_RETURN(QC_TOKEN_POLYGON); } (?i:PORT) { *kn = yytext; DBG_INF("QC_TOKEN_PORT"); DBG_RETURN(QC_TOKEN_PORT); } (?i:POSITION) { *kn = yytext; DBG_INF("QC_TOKEN_POSITION"); DBG_RETURN(QC_TOKEN_POSITION); } (?i:PRECISION) { *kn = yytext; DBG_INF("QC_TOKEN_PRECISION"); DBG_RETURN(QC_TOKEN_PRECISION); } (?i:PREPARE) { *kn = yytext; DBG_INF("QC_TOKEN_PREPARE"); DBG_RETURN(QC_TOKEN_PREPARE); } (?i:PRESERVE) { *kn = yytext; DBG_INF("QC_TOKEN_PRESERVE"); DBG_RETURN(QC_TOKEN_PRESERVE); } (?i:PREV) { *kn = yytext; DBG_INF("QC_TOKEN_PREV"); DBG_RETURN(QC_TOKEN_PREV); } (?i:PRIMARY) { *kn = yytext; DBG_INF("QC_TOKEN_PRIMARY"); DBG_RETURN(QC_TOKEN_PRIMARY); } (?i:PRIVILEGES) { *kn = yytext; DBG_INF("QC_TOKEN_PRIVILEGES"); DBG_RETURN(QC_TOKEN_PRIVILEGES); } (?i:PROCEDURE) { *kn = yytext; DBG_INF("QC_TOKEN_PROCEDURE"); DBG_RETURN(QC_TOKEN_PROCEDURE); } (?i:PROCESS) { *kn = yytext; DBG_INF("QC_TOKEN_PROCESS"); DBG_RETURN(QC_TOKEN_PROCESS); } (?i:PROCESSLIST) { *kn = yytext; DBG_INF("QC_TOKEN_PROCESSLIST"); DBG_RETURN(QC_TOKEN_PROCESSLIST); } (?i:PROFILE) { *kn = yytext; DBG_INF("QC_TOKEN_PROFILE"); DBG_RETURN(QC_TOKEN_PROFILE); } (?i:PROFILES) { *kn = yytext; DBG_INF("QC_TOKEN_PROFILES"); DBG_RETURN(QC_TOKEN_PROFILES); } (?i:PURGE) { *kn = yytext; DBG_INF("QC_TOKEN_PURGE"); DBG_RETURN(QC_TOKEN_PURGE); } (?i:QUARTER) { *kn = yytext; DBG_INF("QC_TOKEN_QUARTER"); DBG_RETURN(QC_TOKEN_QUARTER); } (?i:QUERY) { *kn = yytext; DBG_INF("QC_TOKEN_QUERY"); DBG_RETURN(QC_TOKEN_QUERY); } (?i:QUICK) { *kn = yytext; DBG_INF("QC_TOKEN_QUICK"); DBG_RETURN(QC_TOKEN_QUICK); } (?i:RANGE) { *kn = yytext; DBG_INF("QC_TOKEN_RANGE"); DBG_RETURN(QC_TOKEN_RANGE); } (?i:READS) { *kn = yytext; DBG_INF("QC_TOKEN_READS"); DBG_RETURN(QC_TOKEN_READS); } (?i:READ_ONLY) { *kn = yytext; DBG_INF("QC_TOKEN_READ_ONLY"); DBG_RETURN(QC_TOKEN_READ_ONLY); } (?i:READ) { *kn = yytext; DBG_INF("QC_TOKEN_READ"); DBG_RETURN(QC_TOKEN_READ); } (?i:READ_WRITE) { *kn = yytext; DBG_INF("QC_TOKEN_READ_WRITE"); DBG_RETURN(QC_TOKEN_READ_WRITE); } (?i:REAL) { *kn = yytext; DBG_INF("QC_TOKEN_REAL"); DBG_RETURN(QC_TOKEN_REAL); } (?i:REBUILD) { *kn = yytext; DBG_INF("QC_TOKEN_REBUILD"); DBG_RETURN(QC_TOKEN_REBUILD); } (?i:RECOVER) { *kn = yytext; DBG_INF("QC_TOKEN_RECOVER"); DBG_RETURN(QC_TOKEN_RECOVER); } (?i:REDOFILE) { *kn = yytext; DBG_INF("QC_TOKEN_REDOFILE"); DBG_RETURN(QC_TOKEN_REDOFILE); } (?i:REDO_BUFFER_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_REDO_BUFFER_SIZE"); DBG_RETURN(QC_TOKEN_REDO_BUFFER_SIZE); } (?i:REDUNDANT) { *kn = yytext; DBG_INF("QC_TOKEN_REDUNDANT"); DBG_RETURN(QC_TOKEN_REDUNDANT); } (?i:REFERENCES) { *kn = yytext; DBG_INF("QC_TOKEN_REFERENCES"); DBG_RETURN(QC_TOKEN_REFERENCES); } (?i:REGEXP) { *kn = yytext; DBG_INF("QC_TOKEN_REGEXP"); DBG_RETURN(QC_TOKEN_REGEXP); } (?i:RELAYLOG) { *kn = yytext; DBG_INF("QC_TOKEN_RELAYLOG"); DBG_RETURN(QC_TOKEN_RELAYLOG); } (?i:RELAY_LOG_FILE) { *kn = yytext; DBG_INF("QC_TOKEN_RELAY_LOG_FILE"); DBG_RETURN(QC_TOKEN_RELAY_LOG_FILE); } (?i:RELAY_LOG_POS) { *kn = yytext; DBG_INF("QC_TOKEN_RELAY_LOG_POS"); DBG_RETURN(QC_TOKEN_RELAY_LOG_POS); } (?i:RELAY_THREAD) { *kn = yytext; DBG_INF("QC_TOKEN_RELAY_THREAD"); DBG_RETURN(QC_TOKEN_RELAY_THREAD); } (?i:RELEASE) { *kn = yytext; DBG_INF("QC_TOKEN_RELEASE"); DBG_RETURN(QC_TOKEN_RELEASE); } (?i:RELOAD) { *kn = yytext; DBG_INF("QC_TOKEN_RELOAD"); DBG_RETURN(QC_TOKEN_RELOAD); } (?i:REMOVE) { *kn = yytext; DBG_INF("QC_TOKEN_REMOVE"); DBG_RETURN(QC_TOKEN_REMOVE); } (?i:RENAME) { *kn = yytext; DBG_INF("QC_TOKEN_RENAME"); DBG_RETURN(QC_TOKEN_RENAME); } (?i:REORGANIZE) { *kn = yytext; DBG_INF("QC_TOKEN_REORGANIZE"); DBG_RETURN(QC_TOKEN_REORGANIZE); } (?i:REPAIR) { *kn = yytext; DBG_INF("QC_TOKEN_REPAIR"); DBG_RETURN(QC_TOKEN_REPAIR); } (?i:REPEATABLE) { *kn = yytext; DBG_INF("QC_TOKEN_REPEATABLE"); DBG_RETURN(QC_TOKEN_REPEATABLE); } (?i:REPEAT) { *kn = yytext; DBG_INF("QC_TOKEN_REPEAT"); DBG_RETURN(QC_TOKEN_REPEAT); } (?i:REPLACE) { *kn = yytext; DBG_INF("QC_TOKEN_REPLACE"); DBG_RETURN(QC_TOKEN_REPLACE); } (?i:REPLICATION) { *kn = yytext; DBG_INF("QC_TOKEN_REPLICATION"); DBG_RETURN(QC_TOKEN_REPLICATION); } (?i:REQUIRE) { *kn = yytext; DBG_INF("QC_TOKEN_REQUIRE"); DBG_RETURN(QC_TOKEN_REQUIRE); } (?i:RESET) { *kn = yytext; DBG_INF("QC_TOKEN_RESET"); DBG_RETURN(QC_TOKEN_RESET); } (?i:RESIGNAL) { *kn = yytext; DBG_INF("QC_TOKEN_RESIGNAL"); DBG_RETURN(QC_TOKEN_RESIGNAL); } (?i:RESOURCES) { *kn = yytext; DBG_INF("QC_TOKEN_RESOURCES"); DBG_RETURN(QC_TOKEN_RESOURCES); } (?i:RESTORE) { *kn = yytext; DBG_INF("QC_TOKEN_RESTORE"); DBG_RETURN(QC_TOKEN_RESTORE); } (?i:RESTRICT) { *kn = yytext; DBG_INF("QC_TOKEN_RESTRICT"); DBG_RETURN(QC_TOKEN_RESTRICT); } (?i:RESUME) { *kn = yytext; DBG_INF("QC_TOKEN_RESUME"); DBG_RETURN(QC_TOKEN_RESUME); } (?i:RETURNS) { *kn = yytext; DBG_INF("QC_TOKEN_RETURNS"); DBG_RETURN(QC_TOKEN_RETURNS); } (?i:RETURN) { *kn = yytext; DBG_INF("QC_TOKEN_RETURN"); DBG_RETURN(QC_TOKEN_RETURN); } (?i:REVOKE) { *kn = yytext; DBG_INF("QC_TOKEN_REVOKE"); DBG_RETURN(QC_TOKEN_REVOKE); } (?i:RIGHT) { *kn = yytext; DBG_INF("QC_TOKEN_RIGHT"); DBG_RETURN(QC_TOKEN_RIGHT); } (?i:ROLLBACK) { *kn = yytext; DBG_INF("QC_TOKEN_ROLLBACK"); DBG_RETURN(QC_TOKEN_ROLLBACK); } (?i:ROLLUP) { *kn = yytext; DBG_INF("QC_TOKEN_ROLLUP"); DBG_RETURN(QC_TOKEN_ROLLUP); } (?i:ROUTINE) { *kn = yytext; DBG_INF("QC_TOKEN_ROUTINE"); DBG_RETURN(QC_TOKEN_ROUTINE); } (?i:ROWS) { *kn = yytext; DBG_INF("QC_TOKEN_ROWS"); DBG_RETURN(QC_TOKEN_ROWS); } (?i:ROW_FORMAT) { *kn = yytext; DBG_INF("QC_TOKEN_ROW_FORMAT"); DBG_RETURN(QC_TOKEN_ROW_FORMAT); } (?i:ROW) { *kn = yytext; DBG_INF("QC_TOKEN_ROW"); DBG_RETURN(QC_TOKEN_ROW); } (?i:RTREE) { *kn = yytext; DBG_INF("QC_TOKEN_RTREE"); DBG_RETURN(QC_TOKEN_RTREE); } (?i:SAVEPOINT) { *kn = yytext; DBG_INF("QC_TOKEN_SAVEPOINT"); DBG_RETURN(QC_TOKEN_SAVEPOINT); } (?i:SCHEDULE) { *kn = yytext; DBG_INF("QC_TOKEN_SCHEDULE"); DBG_RETURN(QC_TOKEN_SCHEDULE); } (?i:SCHEMA_NAME) { *kn = yytext; DBG_INF("QC_TOKEN_SCHEMA_NAME"); DBG_RETURN(QC_TOKEN_SCHEMA_NAME); } (?i:SECOND_MICROSECOND) { *kn = yytext; DBG_INF("QC_TOKEN_SECOND_MICROSECOND"); DBG_RETURN(QC_TOKEN_SECOND_MICROSECOND); } (?i:SECOND) { *kn = yytext; DBG_INF("QC_TOKEN_SECOND"); DBG_RETURN(QC_TOKEN_SECOND); } (?i:SECURITY) { *kn = yytext; DBG_INF("QC_TOKEN_SECURITY"); DBG_RETURN(QC_TOKEN_SECURITY); } (?i:SELECT) { *kn = yytext; DBG_INF("QC_TOKEN_SELECT"); DBG_RETURN(QC_TOKEN_SELECT); } (?i:SENSITIVE) { *kn = yytext; DBG_INF("QC_TOKEN_SENSITIVE"); DBG_RETURN(QC_TOKEN_SENSITIVE); } (?i:SEPARATOR) { *kn = yytext; DBG_INF("QC_TOKEN_SEPARATOR"); DBG_RETURN(QC_TOKEN_SEPARATOR); } (?i:SERIALIZABLE) { *kn = yytext; DBG_INF("QC_TOKEN_SERIALIZABLE"); DBG_RETURN(QC_TOKEN_SERIALIZABLE); } (?i:SERIAL) { *kn = yytext; DBG_INF("QC_TOKEN_SERIAL"); DBG_RETURN(QC_TOKEN_SERIAL); } (?i:SESSION) { *kn = yytext; DBG_INF("QC_TOKEN_SESSION"); DBG_RETURN(QC_TOKEN_SESSION); } (?i:SERVER) { *kn = yytext; DBG_INF("QC_TOKEN_SERVER"); DBG_RETURN(QC_TOKEN_SERVER); } (?i:SERVER_OPTIONS) { *kn = yytext; DBG_INF("QC_TOKEN_SERVER_OPTIONS"); DBG_RETURN(QC_TOKEN_SERVER_OPTIONS); } (?i:SET) { *kn = yytext; DBG_INF("QC_TOKEN_SET"); DBG_RETURN(QC_TOKEN_SET); } (?i:SHARE) { *kn = yytext; DBG_INF("QC_TOKEN_SHARE"); DBG_RETURN(QC_TOKEN_SHARE); } (?i:SHIFT_LEFT) { *kn = yytext; DBG_INF("QC_TOKEN_SHIFT_LEFT"); DBG_RETURN(QC_TOKEN_SHIFT_LEFT); } (?i:SHIFT_RIGHT) { *kn = yytext; DBG_INF("QC_TOKEN_SHIFT_RIGHT"); DBG_RETURN(QC_TOKEN_SHIFT_RIGHT); } (?i:SHOW) { *kn = yytext; DBG_INF("QC_TOKEN_SHOW"); DBG_RETURN(QC_TOKEN_SHOW); } (?i:SHUTDOWN) { *kn = yytext; DBG_INF("QC_TOKEN_SHUTDOWN"); DBG_RETURN(QC_TOKEN_SHUTDOWN); } (?i:SIGNAL) { *kn = yytext; DBG_INF("QC_TOKEN_SIGNAL"); DBG_RETURN(QC_TOKEN_SIGNAL); } (?i:SIGNED) { *kn = yytext; DBG_INF("QC_TOKEN_SIGNED"); DBG_RETURN(QC_TOKEN_SIGNED); } (?i:SIMPLE) { *kn = yytext; DBG_INF("QC_TOKEN_SIMPLE"); DBG_RETURN(QC_TOKEN_SIMPLE); } (?i:SLAVE) { *kn = yytext; DBG_INF("QC_TOKEN_SLAVE"); DBG_RETURN(QC_TOKEN_SLAVE); } (?i:SMALLINT) { *kn = yytext; DBG_INF("QC_TOKEN_SMALLINT"); DBG_RETURN(QC_TOKEN_SMALLINT); } (?i:SNAPSHOT) { *kn = yytext; DBG_INF("QC_TOKEN_SNAPSHOT"); DBG_RETURN(QC_TOKEN_SNAPSHOT); } (?i:SOCKET) { *kn = yytext; DBG_INF("QC_TOKEN_SOCKET"); DBG_RETURN(QC_TOKEN_SOCKET); } (?i:SONAME) { *kn = yytext; DBG_INF("QC_TOKEN_SONAME"); DBG_RETURN(QC_TOKEN_SONAME); } (?i:SOUNDS) { *kn = yytext; DBG_INF("QC_TOKEN_SOUNDS"); DBG_RETURN(QC_TOKEN_SOUNDS); } (?i:SOURCE) { *kn = yytext; DBG_INF("QC_TOKEN_SOURCE"); DBG_RETURN(QC_TOKEN_SOURCE); } (?i:SPATIAL) { *kn = yytext; DBG_INF("QC_TOKEN_SPATIAL"); DBG_RETURN(QC_TOKEN_SPATIAL); } (?i:SPECIFIC) { *kn = yytext; DBG_INF("QC_TOKEN_SPECIFIC"); DBG_RETURN(QC_TOKEN_SPECIFIC); } (?i:SQLEXCEPTION) { *kn = yytext; DBG_INF("QC_TOKEN_SQLEXCEPTION"); DBG_RETURN(QC_TOKEN_SQLEXCEPTION); } (?i:SQLSTATE) { *kn = yytext; DBG_INF("QC_TOKEN_SQLSTATE"); DBG_RETURN(QC_TOKEN_SQLSTATE); } (?i:SQLWARNING) { *kn = yytext; DBG_INF("QC_TOKEN_SQLWARNING"); DBG_RETURN(QC_TOKEN_SQLWARNING); } (?i:SQL_BIG_RESULT) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_BIG_RESULT"); DBG_RETURN(QC_TOKEN_SQL_BIG_RESULT); } (?i:SQL_BUFFER_RESULT) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_BUFFER_RESULT");DBG_RETURN(QC_TOKEN_SQL_BUFFER_RESULT); } (?i:SQL_CACHE) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_CACHE"); DBG_RETURN(QC_TOKEN_SQL_CACHE); } (?i:SQL_CALC_FOUND_ROWS) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_CALC_FOUND_ROWS"); DBG_RETURN(QC_TOKEN_SQL_CALC_FOUND_ROWS); } (?i:SQL_NO_CACHE) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_NO_CACHE"); DBG_RETURN(QC_TOKEN_SQL_NO_CACHE); } (?i:SQL_SMALL_RESULT) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_SMALL_RESULT"); DBG_RETURN(QC_TOKEN_SQL_SMALL_RESULT); } (?i:SQL) { *kn = yytext; DBG_INF("QC_TOKEN_SQL"); DBG_RETURN(QC_TOKEN_SQL); } (?i:SQL_THREAD) { *kn = yytext; DBG_INF("QC_TOKEN_SQL_THREAD"); DBG_RETURN(QC_TOKEN_SQL_THREAD); } (?i:SSL) { *kn = yytext; DBG_INF("QC_TOKEN_SSL"); DBG_RETURN(QC_TOKEN_SSL); } (?i:STARTING) { *kn = yytext; DBG_INF("QC_TOKEN_STARTING"); DBG_RETURN(QC_TOKEN_STARTING); } (?i:STARTS) { *kn = yytext; DBG_INF("QC_TOKEN_STARTS"); DBG_RETURN(QC_TOKEN_STARTS); } (?i:START) { *kn = yytext; DBG_INF("QC_TOKEN_START"); DBG_RETURN(QC_TOKEN_START); } (?i:STATUS) { *kn = yytext; DBG_INF("QC_TOKEN_STATUS"); DBG_RETURN(QC_TOKEN_STATUS); } (?i:STDDEV_SAMP) { *kn = yytext; DBG_INF("QC_TOKEN_STDDEV_SAMP"); DBG_RETURN(QC_TOKEN_STDDEV_SAMP); } (?i:STD) { *kn = yytext; DBG_INF("QC_TOKEN_STD"); DBG_RETURN(QC_TOKEN_STD); } (?i:STOP) { *kn = yytext; DBG_INF("QC_TOKEN_STOP"); DBG_RETURN(QC_TOKEN_STOP); } (?i:STORAGE) { *kn = yytext; DBG_INF("QC_TOKEN_STORAGE"); DBG_RETURN(QC_TOKEN_STORAGE); } (?i:STRAIGHT[:space]+JOIN) { *kn = yytext; DBG_INF("QC_TOKEN_STRAIGHT_JOIN");DBG_RETURN(QC_TOKEN_STRAIGHT_JOIN); } (?i:STRING) { *kn = yytext; DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } (?i:SUBCLASS_ORIGIN) { *kn = yytext; DBG_INF("QC_TOKEN_SUBCLASS_ORIGIN");DBG_RETURN(QC_TOKEN_SUBCLASS_ORIGIN); } (?i:SUBDATE) { *kn = yytext; DBG_INF("QC_TOKEN_SUBDATE"); DBG_RETURN(QC_TOKEN_SUBDATE); } (?i:SUBJECT) { *kn = yytext; DBG_INF("QC_TOKEN_SUBJECT"); DBG_RETURN(QC_TOKEN_SUBJECT); } (?i:SUBPARTITIONS) { *kn = yytext; DBG_INF("QC_TOKEN_SUBPARTITIONS");DBG_RETURN(QC_TOKEN_SUBPARTITIONS); } (?i:SUBPARTITION) { *kn = yytext; DBG_INF("QC_TOKEN_SUBPARTITION"); DBG_RETURN(QC_TOKEN_SUBPARTITION); } (?i:SUBSTRING) { *kn = yytext; DBG_INF("QC_TOKEN_SUBSTRING"); DBG_RETURN(QC_TOKEN_SUBSTRING); } (?i:SUM) { *kn = yytext; DBG_INF("QC_TOKEN_SUM"); DBG_RETURN(QC_TOKEN_SUM); } (?i:SUPER) { *kn = yytext; DBG_INF("QC_TOKEN_SUPER"); DBG_RETURN(QC_TOKEN_SUPER); } (?i:SUSPEND) { *kn = yytext; DBG_INF("QC_TOKEN_SUSPEND"); DBG_RETURN(QC_TOKEN_SUSPEND); } (?i:SWAPS) { *kn = yytext; DBG_INF("QC_TOKEN_SWAPS"); DBG_RETURN(QC_TOKEN_SWAPS); } (?i:SWITCHES) { *kn = yytext; DBG_INF("QC_TOKEN_SWITCHES"); DBG_RETURN(QC_TOKEN_SWITCHES); } (?i:SYSDATE) { *kn = yytext; DBG_INF("QC_TOKEN_SYSDATE"); DBG_RETURN(QC_TOKEN_SYSDATE); } (?i:TABLES) { *kn = yytext; DBG_INF("QC_TOKEN_TABLES"); DBG_RETURN(QC_TOKEN_TABLES); } (?i:TABLESPACE) { *kn = yytext; DBG_INF("QC_TOKEN_TABLESPACE"); DBG_RETURN(QC_TOKEN_TABLESPACE); } (?i:TABLE_REF_PRIORITY) { *kn = yytext; DBG_INF("QC_TOKEN_TABLE_REF_PRIORITY");DBG_RETURN(QC_TOKEN_TABLE_REF_PRIORITY); } (?i:TABLE) { *kn = yytext; DBG_INF("QC_TOKEN_TABLE"); DBG_RETURN(QC_TOKEN_TABLE); } (?i:TABLE_CHECKSUM) { *kn = yytext; DBG_INF("QC_TOKEN_TABLE_CHECKSUM");DBG_RETURN(QC_TOKEN_TABLE_CHECKSUM); } (?i:TABLE_NAME) { *kn = yytext; DBG_INF("QC_TOKEN_TABLE_NAME"); DBG_RETURN(QC_TOKEN_TABLE_NAME); } (?i:TEMPORARY) { *kn = yytext; DBG_INF("QC_TOKEN_TEMPORARY"); DBG_RETURN(QC_TOKEN_TEMPORARY); } (?i:TEMPTABLE) { *kn = yytext; DBG_INF("QC_TOKEN_TEMPTABLE"); DBG_RETURN(QC_TOKEN_TEMPTABLE); } (?i:TERMINATED) { *kn = yytext; DBG_INF("QC_TOKEN_TERMINATED"); DBG_RETURN(QC_TOKEN_TERMINATED); } (?i:TEXT_STRING) { *kn = yytext; DBG_INF("QC_TOKEN_TEXT_STRING"); DBG_RETURN(QC_TOKEN_TEXT_STRING); } (?i:TEXT) { *kn = yytext; DBG_INF("QC_TOKEN_TEXT"); DBG_RETURN(QC_TOKEN_TEXT); } (?i:THAN) { *kn = yytext; DBG_INF("QC_TOKEN_THAN"); DBG_RETURN(QC_TOKEN_THAN); } (?i:THEN) { *kn = yytext; DBG_INF("QC_TOKEN_THEN"); DBG_RETURN(QC_TOKEN_THEN); } (?i:TIMESTAMP) { *kn = yytext; DBG_INF("QC_TOKEN_TIMESTAMP"); DBG_RETURN(QC_TOKEN_TIMESTAMP); } (?i:TIMESTAMP_ADD) { *kn = yytext; DBG_INF("QC_TOKEN_TIMESTAMP_ADD");DBG_RETURN(QC_TOKEN_TIMESTAMP_ADD); } (?i:TIMESTAMP_DIFF) { *kn = yytext; DBG_INF("QC_TOKEN_TIMESTAMP_DIFF");DBG_RETURN(QC_TOKEN_TIMESTAMP_DIFF); } (?i:TIME) { *kn = yytext; DBG_INF("QC_TOKEN_TIME"); DBG_RETURN(QC_TOKEN_TIME); } (?i:TINYBLOB) { *kn = yytext; DBG_INF("QC_TOKEN_TINYBLOB"); DBG_RETURN(QC_TOKEN_TINYBLOB); } (?i:TINYINT) { *kn = yytext; DBG_INF("QC_TOKEN_TINYINT"); DBG_RETURN(QC_TOKEN_TINYINT); } (?i:TINYTEXT) { *kn = yytext; DBG_INF("QC_TOKEN_TINYTEXT"); DBG_RETURN(QC_TOKEN_TINYTEXT); } (?i:TO) { *kn = yytext; DBG_INF("QC_TOKEN_TO"); DBG_RETURN(QC_TOKEN_TO); } (?i:TRAILING) { *kn = yytext; DBG_INF("QC_TOKEN_TRAILING"); DBG_RETURN(QC_TOKEN_TRAILING); } (?i:TRANSACTION) { *kn = yytext; DBG_INF("QC_TOKEN_TRANSACTION"); DBG_RETURN(QC_TOKEN_TRANSACTION); } (?i:TRIGGERS) { *kn = yytext; DBG_INF("QC_TOKEN_TRIGGERS"); DBG_RETURN(QC_TOKEN_TRIGGERS); } (?i:TRIGGER) { *kn = yytext; DBG_INF("QC_TOKEN_TRIGGER"); DBG_RETURN(QC_TOKEN_TRIGGER); } (?i:TRIM) { *kn = yytext; DBG_INF("QC_TOKEN_TRIM"); DBG_RETURN(QC_TOKEN_TRIM); } (?i:TRUE) { *kn = yytext; DBG_INF("QC_TOKEN_TRUE"); DBG_RETURN(QC_TOKEN_TRUE); } (?i:TRUNCATE) { *kn = yytext; DBG_INF("QC_TOKEN_TRUNCATE"); DBG_RETURN(QC_TOKEN_TRUNCATE); } (?i:TYPES) { *kn = yytext; DBG_INF("QC_TOKEN_TYPES"); DBG_RETURN(QC_TOKEN_TYPES); } (?i:TYPE) { *kn = yytext; DBG_INF("QC_TOKEN_TYPE"); DBG_RETURN(QC_TOKEN_TYPE); } (?i:UDF_RETURNS) { *kn = yytext; DBG_INF("QC_TOKEN_UDF_RETURNS"); DBG_RETURN(QC_TOKEN_UDF_RETURNS); } (?i:ULONGLONG_NUM) { *kn = yytext; DBG_INF("QC_TOKEN_ULONGLONG_NUM");DBG_RETURN(QC_TOKEN_ULONGLONG_NUM); } (?i:UNCOMMITTED) { *kn = yytext; DBG_INF("QC_TOKEN_UNCOMMITTED"); DBG_RETURN(QC_TOKEN_UNCOMMITTED); } (?i:UNDEFINED) { *kn = yytext; DBG_INF("QC_TOKEN_UNDEFINED"); DBG_RETURN(QC_TOKEN_UNDEFINED); } (?i:UNDERSCORE_CHARSET) { *kn = yytext; DBG_INF("QC_TOKEN_UNDERSCORE_CHARSET");DBG_RETURN(QC_TOKEN_UNDERSCORE_CHARSET); } (?i:UNDOFILE) { *kn = yytext; DBG_INF("QC_TOKEN_UNDOFILE"); DBG_RETURN(QC_TOKEN_UNDOFILE); } (?i:UNDO_BUFFER_SIZE) { *kn = yytext; DBG_INF("QC_TOKEN_UNDO_BUFFER_SIZE");DBG_RETURN(QC_TOKEN_UNDO_BUFFER_SIZE); } (?i:UNDO) { *kn = yytext; DBG_INF("QC_TOKEN_UNDO"); DBG_RETURN(QC_TOKEN_UNDO); } (?i:UNICODE) { *kn = yytext; DBG_INF("QC_TOKEN_UNICODE"); DBG_RETURN(QC_TOKEN_UNICODE); } (?i:UNINSTALL) { *kn = yytext; DBG_INF("QC_TOKEN_UNINSTALL"); DBG_RETURN(QC_TOKEN_UNINSTALL); } (?i:UNION) { *kn = yytext; DBG_INF("QC_TOKEN_UNION"); DBG_RETURN(QC_TOKEN_UNION); } (?i:UNIQUE) { *kn = yytext; DBG_INF("QC_TOKEN_UNIQUE"); DBG_RETURN(QC_TOKEN_UNIQUE); } (?i:UNKNOWN) { *kn = yytext; DBG_INF("QC_TOKEN_UNKNOWN"); DBG_RETURN(QC_TOKEN_UNKNOWN); } (?i:UNLOCK) { *kn = yytext; DBG_INF("QC_TOKEN_UNLOCK"); DBG_RETURN(QC_TOKEN_UNLOCK); } (?i:UNSIGNED) { *kn = yytext; DBG_INF("QC_TOKEN_UNSIGNED"); DBG_RETURN(QC_TOKEN_UNSIGNED); } (?i:UNTIL) { *kn = yytext; DBG_INF("QC_TOKEN_UNTIL"); DBG_RETURN(QC_TOKEN_UNTIL); } (?i:UPDATE) { *kn = yytext; DBG_INF("QC_TOKEN_UPDATE"); DBG_RETURN(QC_TOKEN_UPDATE); } (?i:UPGRADE) { *kn = yytext; DBG_INF("QC_TOKEN_UPGRADE"); DBG_RETURN(QC_TOKEN_UPGRADE); } (?i:USAGE) { *kn = yytext; DBG_INF("QC_TOKEN_USAGE"); DBG_RETURN(QC_TOKEN_USAGE); } (?i:USER) { *kn = yytext; DBG_INF("QC_TOKEN_USER"); DBG_RETURN(QC_TOKEN_USER); } (?i:USE_FRM) { *kn = yytext; DBG_INF("QC_TOKEN_USE_FRM"); DBG_RETURN(QC_TOKEN_USE_FRM); } (?i:USE) { *kn = yytext; DBG_INF("QC_TOKEN_USE"); DBG_RETURN(QC_TOKEN_USE); } (?i:USING) { *kn = yytext; DBG_INF("QC_TOKEN_USING"); DBG_RETURN(QC_TOKEN_USING); } (?i:UTC_DATE) { *kn = yytext; DBG_INF("QC_TOKEN_UTC_DATE"); DBG_RETURN(QC_TOKEN_UTC_DATE); } (?i:UTC_TIMESTAMP) { *kn = yytext; DBG_INF("QC_TOKEN_UTC_TIMESTAMP");DBG_RETURN(QC_TOKEN_UTC_TIMESTAMP); } (?i:UTC_TIME) { *kn = yytext; DBG_INF("QC_TOKEN_UTC_TIME"); DBG_RETURN(QC_TOKEN_UTC_TIME); } (?i:VALUES) { *kn = yytext; DBG_INF("QC_TOKEN_VALUES"); DBG_RETURN(QC_TOKEN_VALUES); } (?i:VALUE) { *kn = yytext; DBG_INF("QC_TOKEN_VALUE"); DBG_RETURN(QC_TOKEN_VALUE); } (?i:VARBINARY) { *kn = yytext; DBG_INF("QC_TOKEN_VARBINARY"); DBG_RETURN(QC_TOKEN_VARBINARY); } (?i:VARCHAR) { *kn = yytext; DBG_INF("QC_TOKEN_VARCHAR"); DBG_RETURN(QC_TOKEN_VARCHAR); } (?i:VARIABLES) { *kn = yytext; DBG_INF("QC_TOKEN_VARIABLES"); DBG_RETURN(QC_TOKEN_VARIABLES); } (?i:VARIANCE) { *kn = yytext; DBG_INF("QC_TOKEN_VARIANCE"); DBG_RETURN(QC_TOKEN_VARIANCE); } (?i:VARYING) { *kn = yytext; DBG_INF("QC_TOKEN_VARYING"); DBG_RETURN(QC_TOKEN_VARYING); } (?i:VAR_SAMP) { *kn = yytext; DBG_INF("QC_TOKEN_VAR_SAMP"); DBG_RETURN(QC_TOKEN_VAR_SAMP); } (?i:VIEW) { *kn = yytext; DBG_INF("QC_TOKEN_VIEW"); DBG_RETURN(QC_TOKEN_VIEW); } (?i:WAIT) { *kn = yytext; DBG_INF("QC_TOKEN_WAIT"); DBG_RETURN(QC_TOKEN_WAIT); } (?i:WARNINGS) { *kn = yytext; DBG_INF("QC_TOKEN_WARNINGS"); DBG_RETURN(QC_TOKEN_WARNINGS); } (?i:WEEK) { *kn = yytext; DBG_INF("QC_TOKEN_WEEK"); DBG_RETURN(QC_TOKEN_WEEK); } (?i:WHEN) { *kn = yytext; DBG_INF("QC_TOKEN_WHEN"); DBG_RETURN(QC_TOKEN_WHEN); } (?i:WHERE) { *kn = yytext; DBG_INF("QC_TOKEN_WHERE"); DBG_RETURN(QC_TOKEN_WHERE); } (?i:WHILE) { *kn = yytext; DBG_INF("QC_TOKEN_WHILE"); DBG_RETURN(QC_TOKEN_WHILE); } (?i:WITH) { *kn = yytext; DBG_INF("QC_TOKEN_WITH"); DBG_RETURN(QC_TOKEN_WITH); } (?i:WITH[:spacee]+CUBE) { *kn = yytext; DBG_INF("QC_TOKEN_WITH_CUBE"); DBG_RETURN(QC_TOKEN_WITH_CUBE); } (?i:WITH[:spacee]+ROLLUP) { *kn = yytext; DBG_INF("QC_TOKEN_WITH_ROLLUP"); DBG_RETURN(QC_TOKEN_WITH_ROLLUP); } (?i:WORK) { *kn = yytext; DBG_INF("QC_TOKEN_WORK"); DBG_RETURN(QC_TOKEN_WORK); } (?i:WRAPPER) { *kn = yytext; DBG_INF("QC_TOKEN_WRAPPER"); DBG_RETURN(QC_TOKEN_WRAPPER); } (?i:WRITE) { *kn = yytext; DBG_INF("QC_TOKEN_WRITE"); DBG_RETURN(QC_TOKEN_WRITE); } (?i:X509) { *kn = yytext; DBG_INF("QC_TOKEN_X509"); DBG_RETURN(QC_TOKEN_X509); } (?i:XA) { *kn = yytext; DBG_INF("QC_TOKEN_XA"); DBG_RETURN(QC_TOKEN_XA); } (?i:XML) { *kn = yytext; DBG_INF("QC_TOKEN_XML"); DBG_RETURN(QC_TOKEN_XML); } (?i:XOR) { *kn = yytext; DBG_INF("QC_TOKEN_XOR"); DBG_RETURN(QC_TOKEN_XOR); } (?i:YEAR_MONTH) { *kn = yytext; DBG_INF("QC_TOKEN_YEAR_MONTH"); DBG_RETURN(QC_TOKEN_YEAR_MONTH); } (?i:YEAR) { *kn = yytext; DBG_INF("QC_TOKEN_YEAR"); DBG_RETURN(QC_TOKEN_YEAR); } (?i:ZEROFILL) { *kn = yytext; DBG_INF("QC_TOKEN_ZEROFILL"); DBG_RETURN(QC_TOKEN_ZEROFILL); } (?i:CLIENT_FLAG) { *kn = yytext; DBG_INF("QC_TOKEN_CLIENT_FLAG"); DBG_RETURN(QC_TOKEN_CLIENT_FLAG); } /* Integers and Floats */ -?[0-9]+ { ZVAL_LONG(token_value, atoi(yytext)); DBG_INF("QC_TOKEN_INTNUM"); DBG_RETURN(QC_TOKEN_INTNUM); } -?[0-9]+"."[0-9]* | -?"."[0-9]+ | -?[0-9]+E[-+]?[0-9]+ | -?[0-9]+"."[0-9]*E[-+]?[0-9]+ | -?"."[0-9]+E[-+]?[0-9]+ { ZVAL_DOUBLE(token_value, atof(yytext)); DBG_INF("QC_TOKEN_FLOATNUM"); DBG_RETURN(QC_TOKEN_FLOATNUM); } /* Normal strings */ '(\\.|''|[^'\n])*' | \"(\\.|\"\"|[^"\n])*\" { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } '(\\.|[^'\n])*$ { yyerror("Unterminated string %s", yytext); } \"(\\.|[^"\n])*$ { yyerror("Unterminated string %s", yytext); } /* Hex and Bit strings */ X'[0-9A-F]+' | 0X[0-9A-F]+ { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } 0B[01]+ | B'[01]+' { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_STRING"); DBG_RETURN(QC_TOKEN_STRING); } /* Operators */ \+ { DBG_INF("QC_TOKEN_PLUS"); DBG_RETURN(QC_TOKEN_PLUS); } \- { DBG_INF("QC_TOKEN_MINUS"); DBG_RETURN(QC_TOKEN_MINUS); } \, { DBG_INF("QC_TOKEN_COMMA"); DBG_RETURN(QC_TOKEN_COMMA); } \; { DBG_INF("QC_TOKEN_SEMICOLON"); DBG_RETURN(QC_TOKEN_SEMICOLON); } \( { DBG_INF("QC_TOKEN_BRACKET_OPEN"); DBG_RETURN(QC_TOKEN_BRACKET_OPEN); } \) { DBG_INF("QC_TOKEN_BRACKET_CLOSE");DBG_RETURN(QC_TOKEN_BRACKET_CLOSE); } \* { DBG_INF("QC_TOKEN_STAR"); DBG_RETURN(QC_TOKEN_STAR); } \. { DBG_INF("QC_TOKEN_DOT"); DBG_RETURN(QC_TOKEN_DOT); } ! { DBG_INF("QC_TOKEN_NOT"); DBG_RETURN(QC_TOKEN_NOT); } \^ { DBG_INF("QC_TOKEN_XOR"); DBG_RETURN(QC_TOKEN_XOR); } \% { DBG_INF("QC_TOKEN_MOD"); DBG_RETURN(QC_TOKEN_MOD); } \/ { DBG_INF("QC_TOKEN_DIV"); DBG_RETURN(QC_TOKEN_DIV); } \~ { DBG_INF("QC_TOKEN_TILDE"); DBG_RETURN(QC_TOKEN_TILDE); } "@@" { DBG_INF("QC_TOKEN_GLOBAL_VAR"); DBG_RETURN(QC_TOKEN_GLOBAL_VAR); } \@ { DBG_INF("QC_TOKEN_SESSION_VAR"); DBG_RETURN(QC_TOKEN_SESSION_VAR); } "&&" { DBG_INF("QC_TOKEN_AND"); DBG_RETURN(QC_TOKEN_AND); } \& { DBG_INF("QC_TOKEN_BIT_AND"); DBG_RETURN(QC_TOKEN_BIT_AND); } "||" { DBG_INF("QC_TOKEN_OR"); DBG_RETURN(QC_TOKEN_OR); } \| { DBG_INF("QC_TOKEN_BIT_OR"); DBG_RETURN(QC_TOKEN_BIT_OR); } "=" { DBG_INF("QC_TOKEN_EQ"); DBG_RETURN(QC_TOKEN_EQ); } "<=>" { DBG_INF("QC_TOKEN_NE_TRIPLE"); DBG_RETURN(QC_TOKEN_NE_TRIPLE); } ">=" { DBG_INF("QC_TOKEN_GE"); DBG_RETURN(QC_TOKEN_GE); } ">" { DBG_INF("QC_TOKEN_GT"); DBG_RETURN(QC_TOKEN_GT); } "<=" { DBG_INF("QC_TOKEN_LE"); DBG_RETURN(QC_TOKEN_LE); } "<" { DBG_INF("QC_TOKEN_LT"); DBG_RETURN(QC_TOKEN_LT); } "!=" | "<>" { DBG_INF("QC_TOKEN_NE"); DBG_RETURN(QC_TOKEN_NE); } "<<" { DBG_INF("QC_TOKEN_SHIFT_LEFT"); DBG_RETURN(QC_TOKEN_SHIFT_LEFT); } ">>" { DBG_INF("QC_TOKEN_SHIFT_RIGHT"); DBG_RETURN(QC_TOKEN_SHIFT_RIGHT); } ":=" { DBG_INF("QC_TOKEN_ASSIGN_TO_VAR");DBG_RETURN(QC_TOKEN_ASSIGN_TO_VAR); } /* normal identifier */ ([A-Za-z$_]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEF][\x80-\xBF][\x80-\xBF])([0-9]|[A-Za-z$_]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEF][\x80-\xBF][\x80-\xBF])* { ZVAL_STRINGL(token_value, yytext, yyleng, 1); DBG_INF("QC_TOKEN_IDENTIFIER"); DBG_RETURN(QC_TOKEN_IDENTIFIER); } /* quoted identifier */ `[^`/\\.\n]+` { ZVAL_STRINGL(token_value, yytext + 1, yyleng - 2, 1); DBG_INF("QC_TOKEN_IDENTIFIER"); DBG_RETURN(QC_TOKEN_IDENTIFIER); } /* Comments */ #.* ; { ZVAL_STRINGL(token_value, yytext + 1, yyleng - 1, 1); DBG_INF("QC_TOKEN_COMMENT"); DBG_RETURN(QC_TOKEN_COMMENT); } "--"[ \t].* { ZVAL_STRINGL(token_value, yytext + 2, yyleng - 2, 1); DBG_INF("QC_TOKEN_COMMENT"); DBG_RETURN(QC_TOKEN_COMMENT); } "/*" { old_yystate = YY_START; DBG_INF("entering COMMENT_MODE"); BEGIN COMMENT_MODE; #if VALGRIND_MEMORY_WARNINGS if (*comment) { mnd_efree(*comment); *comment = NULL; } #endif *comment = mnd_ecalloc(1, sizeof(smart_str)); ZVAL_NULL(token_value); } "*/" { BEGIN old_yystate; DBG_INF("leaving COMMENT_MODE"); DBG_INF("QC_TOKEN_COMMENT"); smart_str_appendc(*comment, '\0'); /* we need to copy the smart_str by value before we set token_value because comment and token_value are the vary same thing (part of an union) if we write something to token_value we will lose comment; */ { smart_str * ss_copy = *comment; ZVAL_STRINGL(token_value, (*comment)->c, (*comment)->len, 1); smart_str_free(ss_copy); mnd_efree(ss_copy); } DBG_INF_FMT("token_value is now:%s", Z_STRVAL_P(token_value)); DBG_RETURN(QC_TOKEN_COMMENT); } .|\n { smart_str_appendc(*comment, yytext[0]); } /* the rest */ [ \t\n] /* whitespace */ . { yyerror("report to the developer '%c'\n", *yytext); } %% /* {{{ mysqlnd_qp_error */ int mysqlnd_qp_error(const char *format, ...) { /* do not emit a message */ return 1; } /* }}} */ /* {{{ mysqlnd_qp_free_scanner */ PHPAPI void mysqlnd_qp_free_scanner(struct st_mysqlnd_query_scanner * scanner TSRMLS_DC) { DBG_ENTER("mysqlnd_qp_free_scanner"); if (scanner) { yylex_destroy(*(yyscan_t *) scanner->scanner); mnd_efree(scanner->scanner); mnd_efree(scanner); } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_qp_create_scanner */ PHPAPI struct st_mysqlnd_query_scanner * mysqlnd_qp_create_scanner(TSRMLS_D) { struct st_mysqlnd_query_scanner * ret = mnd_ecalloc(1, sizeof(struct st_mysqlnd_query_scanner)); DBG_ENTER("mysqlnd_qp_create_scanner"); ret->scanner = mnd_ecalloc(1, sizeof(yyscan_t)); if (yylex_init_extra(ret->token_value /* yyextra */, (yyscan_t *) ret->scanner)) { DBG_ERR_FMT("yylex_init_extra failed"); mysqlnd_qp_free_scanner(ret TSRMLS_CC); ret = NULL; } DBG_INF_FMT("ret=%p", ret); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_qp_get_token */ PHPAPI struct st_ms_token_and_value mysqlnd_qp_get_token(struct st_mysqlnd_query_scanner * scanner TSRMLS_DC) { YYSTYPE lex_val; struct st_ms_token_and_value ret = {0}; DBG_ENTER("mysqlnd_qp_get_token"); memset(&lex_val, 0, sizeof(lex_val)); INIT_ZVAL(lex_val.zv); /* yylex expects `yyscan_t`, not `yyscan_t*` */ if ((ret.token = yylex(&lex_val, *(yyscan_t *)scanner->scanner TSRMLS_CC))) { DBG_INF_FMT("token=%d", ret.token); switch (Z_TYPE(lex_val.zv)) { case IS_STRING: DBG_INF_FMT("strval=%s", Z_STRVAL(lex_val.zv)); ret.value = lex_val.zv; break; case IS_LONG: DBG_INF_FMT("lval=%ld", Z_LVAL(lex_val.zv)); ret.value = lex_val.zv; break; case IS_DOUBLE: DBG_INF_FMT("dval=%f", Z_DVAL(lex_val.zv)); ret.value = lex_val.zv; break; case IS_NULL: if (lex_val.kn) { ZVAL_STRING(&ret.value, lex_val.kn, 1); } break; } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_qp_set_string */ PHPAPI void mysqlnd_qp_set_string(struct st_mysqlnd_query_scanner * scanner, const char * const s, size_t len TSRMLS_DC) { DBG_ENTER("mysqlnd_qp_set_string"); /* scan_string/scan_bytes expect `yyscan_t`, not `yyscan_t*` */ yy_scan_bytes(s, len, *((yyscan_t *)scanner->scanner)); DBG_VOID_RETURN; } /* }}} */ #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION /* {{{ mysqlnd_qp_create_parser */ PHPAPI struct st_mysqlnd_query_parser * mysqlnd_qp_create_parser(TSRMLS_D) { struct st_mysqlnd_query_parser * ret = mnd_ecalloc(1, sizeof(struct st_mysqlnd_query_parser)); DBG_ENTER("mysqlnd_qp_create_parser"); DBG_INF_FMT("ret=%p", ret); ret->scanner = mysqlnd_qp_create_scanner(TSRMLS_C); DBG_INF_FMT("ret->scanner=%p", ret->scanner); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_qp_free_parser */ PHPAPI void mysqlnd_qp_free_parser(struct st_mysqlnd_query_parser * parser TSRMLS_DC) { DBG_ENTER("mysqlnd_qp_free_parser"); if (parser) { mysqlnd_qp_free_scanner(parser->scanner TSRMLS_CC); zend_llist_clean(&parser->parse_info.where_field_list); zend_llist_clean(&parser->parse_info.select_field_list); zend_llist_clean(&parser->parse_info.table_list); mnd_efree(parser); } DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_table_list_dtor */ static void mysqlnd_ms_table_list_dtor(void * pDest) { struct st_mysqlnd_ms_table_info * table_info = (struct st_mysqlnd_ms_table_info *) pDest; TSRMLS_FETCH(); if (table_info) { zend_bool pers = table_info->persistent; if (table_info->db) { mnd_pefree(table_info->db, pers); } if (table_info->table) { mnd_pefree(table_info->table, pers); } if (table_info->org_table) { mnd_pefree(table_info->org_table, pers); } } } /* }}} */ /* {{{ mysqlnd_ms_field_list_dtor */ static void mysqlnd_ms_field_list_dtor(void * pDest) { struct st_mysqlnd_ms_field_info * field_info = (struct st_mysqlnd_ms_field_info *) pDest; TSRMLS_FETCH(); if (field_info) { zend_bool pers = field_info->persistent; if (field_info->db) { mnd_pefree(field_info->db, pers); } if (field_info->table) { mnd_pefree(field_info->table, pers); } if (field_info->name) { mnd_pefree(field_info->name, pers); } if (field_info->org_name) { mnd_pefree(field_info->org_name, pers); } if (field_info->custom_data && field_info->free_custom_data) { mnd_pefree(field_info->custom_data, pers); } } } /* }}} */ extern int mysqlnd_qp_parse (void * TSRMLS_DC); /* {{{ mysqlnd_qp_start_parser */ PHPAPI int mysqlnd_qp_start_parser(struct st_mysqlnd_query_parser * parser, const char * const query, const size_t query_len TSRMLS_DC) { int ret; DBG_ENTER("mysqlnd_qp_start_parser"); mysqlnd_qp_set_string(parser->scanner, query, query_len TSRMLS_CC); zend_llist_init(&parser->parse_info.table_list, sizeof(struct st_mysqlnd_ms_table_info), (llist_dtor_func_t) mysqlnd_ms_table_list_dtor, parser->parse_info.persistent /* pers */); zend_llist_init(&parser->parse_info.select_field_list, sizeof(struct st_mysqlnd_ms_field_info), (llist_dtor_func_t) mysqlnd_ms_field_list_dtor, parser->parse_info.persistent /* pers */); zend_llist_init(&parser->parse_info.where_field_list, sizeof(struct st_mysqlnd_ms_field_info), (llist_dtor_func_t) mysqlnd_ms_field_list_dtor, parser->parse_info.persistent /* pers */); parser->parse_info.parse_where = FALSE; DBG_INF("let's run the parser"); ret = mysqlnd_qp_parse(parser TSRMLS_CC); { zend_llist_position pos; struct st_mysqlnd_ms_table_info * tinfo; DBG_INF("------ TABLE LIST -------"); for (tinfo = zend_llist_get_first_ex(&parser->parse_info.table_list, &pos); tinfo; tinfo = zend_llist_get_next_ex(&parser->parse_info.table_list, &pos)) { DBG_INF_FMT("db=[%s] table=[%s] org_table=[%s] statement_type=[%d]", tinfo->db? tinfo->db:"n/a", tinfo->table? tinfo->table:"n/a", tinfo->org_table? tinfo->org_table:"n/a", parser->parse_info.statement ); } } { zend_llist_position pos; struct st_mysqlnd_ms_field_info * finfo; DBG_INF("------ SELECT FIELD LIST -------"); for (finfo = zend_llist_get_first_ex(&parser->parse_info.select_field_list, &pos); finfo; finfo = zend_llist_get_next_ex(&parser->parse_info.select_field_list, &pos)) { DBG_INF_FMT("db=[%s] table=[%s] name=[%s] org_name=[%s]", finfo->db? finfo->db:"n/a", finfo->table? finfo->table:"n/a", finfo->name? finfo->name:"n/a", finfo->org_name? finfo->org_name:"n/a" ); } } { zend_llist_position pos; struct st_mysqlnd_ms_field_info * finfo; DBG_INF("------ WHERE FIELD LIST -------"); for (finfo = zend_llist_get_first_ex(&parser->parse_info.where_field_list, &pos); finfo; finfo = zend_llist_get_next_ex(&parser->parse_info.where_field_list, &pos)) { DBG_INF_FMT("db=[%s] table=[%s] name=[%s] org_name=%s op=[%s]", finfo->db? finfo->db:"n/a", finfo->table? finfo->table:"n/a", finfo->name? finfo->name:"n/a", finfo->org_name? finfo->org_name:"n/a", finfo->custom_data? finfo->custom_data:"n/a" ); } } DBG_RETURN(ret); } /* }}} */ #endif /* MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION */ mysqlnd_ms-1.5.2/mysqlnd_query_lexer.lex.h0000664000175000017500000002147212161007456020320 0ustar andreyandrey#ifndef mysqlnd_qp_HEADER_H #define mysqlnd_qp_HEADER_H 1 #define mysqlnd_qp_IN_HEADER 1 #line 6 "mysqlnd_query_lexer.lex.h" #line 8 "mysqlnd_query_lexer.lex.h" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; #endif /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin yyg->yyin_r #define yyout yyg->yyout_r #define yyextra yyg->yyextra_r #define yyleng yyg->yyleng_r #define yytext yyg->yytext_r #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ void mysqlnd_qp_restart (FILE *input_file ,yyscan_t yyscanner ); void mysqlnd_qp__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__create_buffer (FILE *file,int size ,yyscan_t yyscanner ); void mysqlnd_qp__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); void mysqlnd_qp__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); void mysqlnd_qp_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); void mysqlnd_qp_pop_buffer_state (yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); YY_BUFFER_STATE mysqlnd_qp__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); void *mysqlnd_qp_alloc (yy_size_t ,yyscan_t yyscanner ); void *mysqlnd_qp_realloc (void *,yy_size_t ,yyscan_t yyscanner ); void mysqlnd_qp_free (void * ,yyscan_t yyscanner ); /* Begin user sect3 */ #define mysqlnd_qp_wrap(n) 1 #define YY_SKIP_YYWRAP #define yytext_ptr yytext_r #ifdef YY_HEADER_EXPORT_START_CONDITIONS #define INITIAL 0 #define COMMENT_MODE 1 #define BETWEEN_MODE 2 #endif #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #define YY_EXTRA_TYPE zval * int mysqlnd_qp_lex_init (yyscan_t* scanner); int mysqlnd_qp_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int mysqlnd_qp_lex_destroy (yyscan_t yyscanner ); int mysqlnd_qp_get_debug (yyscan_t yyscanner ); void mysqlnd_qp_set_debug (int debug_flag ,yyscan_t yyscanner ); YY_EXTRA_TYPE mysqlnd_qp_get_extra (yyscan_t yyscanner ); void mysqlnd_qp_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); FILE *mysqlnd_qp_get_in (yyscan_t yyscanner ); void mysqlnd_qp_set_in (FILE * in_str ,yyscan_t yyscanner ); FILE *mysqlnd_qp_get_out (yyscan_t yyscanner ); void mysqlnd_qp_set_out (FILE * out_str ,yyscan_t yyscanner ); int mysqlnd_qp_get_leng (yyscan_t yyscanner ); char *mysqlnd_qp_get_text (yyscan_t yyscanner ); int mysqlnd_qp_get_lineno (yyscan_t yyscanner ); void mysqlnd_qp_set_lineno (int line_number ,yyscan_t yyscanner ); YYSTYPE * mysqlnd_qp_get_lval (yyscan_t yyscanner ); void mysqlnd_qp_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int mysqlnd_qp_wrap (yyscan_t yyscanner ); #else extern int mysqlnd_qp_wrap (yyscan_t yyscanner ); #endif #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int mysqlnd_qp_lex \ (YYSTYPE * yylval_param ,yyscan_t yyscanner); #define YY_DECL int mysqlnd_qp_lex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) #endif /* !YY_DECL */ /* yy_get_previous_state - get the state just before the EOB char was reached */ #undef YY_NEW_FILE #undef YY_FLUSH_BUFFER #undef yy_set_bol #undef yy_new_buffer #undef yy_set_interactive #undef YY_DO_BEFORE_ACTION #ifdef YY_DECL_IS_OURS #undef YY_DECL_IS_OURS #undef YY_DECL #endif #line 761 "mysqlnd_query_lexer.flex" #line 354 "mysqlnd_query_lexer.lex.h" #undef mysqlnd_qp_IN_HEADER #endif /* mysqlnd_qp_HEADER_H */ mysqlnd_ms-1.5.2/mysqlnd_query_parser.c0000664000175000017500000050257112161007456017705 0ustar andreyandrey /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.4.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse mysqlnd_qp_parse #define yylex mysqlnd_qp_lex #define yyerror mysqlnd_qp_error #define yylval mysqlnd_qp_lval #define yychar mysqlnd_qp_char #define yydebug mysqlnd_qp_debug #define yynerrs mysqlnd_qp_nerrs /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 1 "mysqlnd_query_parser.grammar" /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ #include "php.h" #include "mysqlnd_ms.h" #include "zend_llist.h" /* Compile with : bison -o mysqlnd_query_parser.c -d mysqlnd_query_parser.grammar --name-prefix=mysqlnd_qp_ */ #define yyerror mysqlnd_qp_error extern int mysqlnd_qp_error(const char * format, ...); #if defined(PHP_DEBUG) && !defined(YYDEBUG) #define YYDEBUG 1 #else #define YYDEBUG 0 #endif #define YYPARSE_PARAM my_parser TSRMLS_DC #define PINFO (((struct st_mysqlnd_query_parser *) my_parser)->parse_info) #define YYLEX_PARAM *(yyscan_t *)(((struct st_mysqlnd_query_parser *) my_parser)->scanner->scanner) TSRMLS_CC /* Line 189 of yacc.c */ #line 122 "mysqlnd_query_parser.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { QC_TOKEN_ACCESSIBLE = 258, QC_TOKEN_ACTION = 259, QC_TOKEN_ADD = 260, QC_TOKEN_ADDDATE = 261, QC_TOKEN_AFTER = 262, QC_TOKEN_AGAINST = 263, QC_TOKEN_AGGREGATE = 264, QC_TOKEN_ALGORITHM = 265, QC_TOKEN_ALL = 266, QC_TOKEN_ALTER = 267, QC_TOKEN_ANALYZE = 268, QC_TOKEN_AND_AND = 269, QC_TOKEN_AND = 270, QC_TOKEN_BETWEEN_AND = 271, QC_TOKEN_ANY = 272, QC_TOKEN_AS = 273, QC_TOKEN_ASC = 274, QC_TOKEN_ASCII = 275, QC_TOKEN_ASENSITIVE = 276, QC_TOKEN_AT = 277, QC_TOKEN_AUTHORS = 278, QC_TOKEN_AUTOEXTEND_SIZE = 279, QC_TOKEN_AUTO_INC = 280, QC_TOKEN_AVG_ROW_LENGTH = 281, QC_TOKEN_AVG = 282, QC_TOKEN_BACKUP = 283, QC_TOKEN_BEFORE = 284, QC_TOKEN_BEGIN = 285, QC_TOKEN_BETWEEN = 286, QC_TOKEN_BIGINT = 287, QC_TOKEN_BINARY = 288, QC_TOKEN_BINLOG = 289, QC_TOKEN_BIN_NUM = 290, QC_TOKEN_BIT_AND = 291, QC_TOKEN_BIT_OR = 292, QC_TOKEN_BIT = 293, QC_TOKEN_BIT_XOR = 294, QC_TOKEN_BLOB = 295, QC_TOKEN_BLOCK = 296, QC_TOKEN_BOOLEAN = 297, QC_TOKEN_BOOL = 298, QC_TOKEN_BOTH = 299, QC_TOKEN_BTREE = 300, QC_TOKEN_BY = 301, QC_TOKEN_BYTE = 302, QC_TOKEN_CACHE = 303, QC_TOKEN_CALL = 304, QC_TOKEN_CASCADE = 305, QC_TOKEN_CASCADED = 306, QC_TOKEN_CASE = 307, QC_TOKEN_CAST = 308, QC_TOKEN_CATALOG_NAME = 309, QC_TOKEN_CHAIN = 310, QC_TOKEN_CHANGE = 311, QC_TOKEN_CHANGED = 312, QC_TOKEN_CHARSET = 313, QC_TOKEN_CHAR = 314, QC_TOKEN_CHECKSUM = 315, QC_TOKEN_CHECK = 316, QC_TOKEN_CIPHER = 317, QC_TOKEN_CLASS_ORIGIN = 318, QC_TOKEN_CLIENT = 319, QC_TOKEN_CLOSE = 320, QC_TOKEN_COALESCE = 321, QC_TOKEN_CODE = 322, QC_TOKEN_COLLATE = 323, QC_TOKEN_COLLATION = 324, QC_TOKEN_COLUMNS = 325, QC_TOKEN_COLUMN = 326, QC_TOKEN_COLUMN_NAME = 327, QC_TOKEN_COMMENT = 328, QC_TOKEN_COMMITTED = 329, QC_TOKEN_COMMIT = 330, QC_TOKEN_COMPACT = 331, QC_TOKEN_COMPLETION = 332, QC_TOKEN_COMPRESSED = 333, QC_TOKEN_CONCURRENT = 334, QC_TOKEN_CONDITION = 335, QC_TOKEN_CONNECTION = 336, QC_TOKEN_CONSISTENT = 337, QC_TOKEN_CONSTRAINT = 338, QC_TOKEN_CONSTRAINT_CATALOG = 339, QC_TOKEN_CONSTRAINT_NAME = 340, QC_TOKEN_CONSTRAINT_SCHEMA = 341, QC_TOKEN_CONTAINS = 342, QC_TOKEN_CONTEXT = 343, QC_TOKEN_CONTINUE = 344, QC_TOKEN_CONTRIBUTORS = 345, QC_TOKEN_CONVERT = 346, QC_TOKEN_COUNT = 347, QC_TOKEN_CPU = 348, QC_TOKEN_CREATE = 349, QC_TOKEN_CROSS = 350, QC_TOKEN_CUBE = 351, QC_TOKEN_CURDATE = 352, QC_TOKEN_CURRENT_USER = 353, QC_TOKEN_CURSOR = 354, QC_TOKEN_CURSOR_NAME = 355, QC_TOKEN_CURTIME = 356, QC_TOKEN_DATABASE = 357, QC_TOKEN_DATABASES = 358, QC_TOKEN_DATAFILE = 359, QC_TOKEN_DATA = 360, QC_TOKEN_DATETIME = 361, QC_TOKEN_DATE_ADD_INTERVAL = 362, QC_TOKEN_DATE_SUB_INTERVAL = 363, QC_TOKEN_DATE = 364, QC_TOKEN_DAY_HOUR = 365, QC_TOKEN_DAY_MICROSECOND = 366, QC_TOKEN_DAY_MINUTE = 367, QC_TOKEN_DAY_SECOND = 368, QC_TOKEN_DAY = 369, QC_TOKEN_DEALLOCATE = 370, QC_TOKEN_DECIMAL_NUM = 371, QC_TOKEN_DECIMAL = 372, QC_TOKEN_DECLARE = 373, QC_TOKEN_DEFAULT = 374, QC_TOKEN_DEFINER = 375, QC_TOKEN_DELAYED = 376, QC_TOKEN_DELAY_KEY_WRITE = 377, QC_TOKEN_DELETE = 378, QC_TOKEN_DESC = 379, QC_TOKEN_DESCRIBE = 380, QC_TOKEN_DES_KEY_FILE = 381, QC_TOKEN_DETERMINISTIC = 382, QC_TOKEN_DIRECTORY = 383, QC_TOKEN_DISABLE = 384, QC_TOKEN_DISCARD = 385, QC_TOKEN_DISK = 386, QC_TOKEN_DISTINCT = 387, QC_TOKEN_DIV = 388, QC_TOKEN_DOUBLE = 389, QC_TOKEN_DO = 390, QC_TOKEN_DROP = 391, QC_TOKEN_DUAL = 392, QC_TOKEN_DUMPFILE = 393, QC_TOKEN_DUPLICATE = 394, QC_TOKEN_DYNAMIC = 395, QC_TOKEN_EACH = 396, QC_TOKEN_ELSE = 397, QC_TOKEN_ELSEIF = 398, QC_TOKEN_ENABLE = 399, QC_TOKEN_ENCLOSED = 400, QC_TOKEN_END = 401, QC_TOKEN_ENDS = 402, QC_TOKEN_END_OF_INPUT = 403, QC_TOKEN_ENGINES = 404, QC_TOKEN_ENGINE = 405, QC_TOKEN_ENUM = 406, QC_TOKEN_EQ = 407, QC_TOKEN_EQUAL = 408, QC_TOKEN_ERRORS = 409, QC_TOKEN_ESCAPED = 410, QC_TOKEN_ESCAPE = 411, QC_TOKEN_EVENTS = 412, QC_TOKEN_EVENT = 413, QC_TOKEN_EVERY = 414, QC_TOKEN_EXECUTE = 415, QC_TOKEN_EXISTS = 416, QC_TOKEN_EXIT = 417, QC_TOKEN_EXPANSION = 418, QC_TOKEN_EXTENDED = 419, QC_TOKEN_EXTENT_SIZE = 420, QC_TOKEN_EXTRACT = 421, QC_TOKEN_FALSE = 422, QC_TOKEN_FAST = 423, QC_TOKEN_FAULTS = 424, QC_TOKEN_FETCH = 425, QC_TOKEN_FILE = 426, QC_TOKEN_FIRST = 427, QC_TOKEN_FIXED = 428, QC_TOKEN_FLOAT_NUM = 429, QC_TOKEN_FLOAT = 430, QC_TOKEN_FLUSH = 431, QC_TOKEN_FORCE = 432, QC_TOKEN_FOREIGN = 433, QC_TOKEN_FOR = 434, QC_TOKEN_FOUND = 435, QC_TOKEN_FRAC_SECOND = 436, QC_TOKEN_FROM = 437, QC_TOKEN_FULL = 438, QC_TOKEN_FULLTEXT = 439, QC_TOKEN_FUNCTION = 440, QC_TOKEN_GE = 441, QC_TOKEN_GEOMETRYCOLLECTION = 442, QC_TOKEN_GEOMETRY = 443, QC_TOKEN_GET_FORMAT = 444, QC_TOKEN_GLOBAL = 445, QC_TOKEN_GRANT = 446, QC_TOKEN_GRANTS = 447, QC_TOKEN_GROUP = 448, QC_TOKEN_GROUP_CONCAT = 449, QC_TOKEN_GT = 450, QC_TOKEN_HANDLER = 451, QC_TOKEN_HASH = 452, QC_TOKEN_HAVING = 453, QC_TOKEN_HELP = 454, QC_TOKEN_HEX_NUM = 455, QC_TOKEN_HIGH_PRIORITY = 456, QC_TOKEN_HOST = 457, QC_TOKEN_HOSTS = 458, QC_TOKEN_HOUR_MICROSECOND = 459, QC_TOKEN_HOUR_MINUTE = 460, QC_TOKEN_HOUR_SECOND = 461, QC_TOKEN_HOUR = 462, QC_TOKEN_IDENT = 463, QC_TOKEN_IDENTIFIED = 464, QC_TOKEN_IDENT_QUOTED = 465, QC_TOKEN_IF = 466, QC_TOKEN_IGNORE = 467, QC_TOKEN_IGNORE_SERVER_IDS = 468, QC_TOKEN_IMPORT = 469, QC_TOKEN_INDEXES = 470, QC_TOKEN_INDEX = 471, QC_TOKEN_INFILE = 472, QC_TOKEN_INITIAL_SIZE = 473, QC_TOKEN_INNER = 474, QC_TOKEN_INOUT = 475, QC_TOKEN_INSENSITIVE = 476, QC_TOKEN_INSERT = 477, QC_TOKEN_INSERT_METHOD = 478, QC_TOKEN_INSTALL = 479, QC_TOKEN_INTERVAL = 480, QC_TOKEN_INTO = 481, QC_TOKEN_INT = 482, QC_TOKEN_INVOKER = 483, QC_TOKEN_IN = 484, QC_TOKEN_IO = 485, QC_TOKEN_IPC = 486, QC_TOKEN_IS = 487, QC_TOKEN_ISOLATION = 488, QC_TOKEN_ISSUER = 489, QC_TOKEN_ITERATE = 490, QC_TOKEN_JOIN = 491, QC_TOKEN_KEYS = 492, QC_TOKEN_KEY_BLOCK_SIZE = 493, QC_TOKEN_KEY = 494, QC_TOKEN_KILL = 495, QC_TOKEN_LANGUAGE = 496, QC_TOKEN_LAST = 497, QC_TOKEN_LE = 498, QC_TOKEN_LEADING = 499, QC_TOKEN_LEAVES = 500, QC_TOKEN_LEAVE = 501, QC_TOKEN_LEFT = 502, QC_TOKEN_LESS = 503, QC_TOKEN_LEVEL = 504, QC_TOKEN_LEX_HOSTNAME = 505, QC_TOKEN_LIKE = 506, QC_TOKEN_LIMIT = 507, QC_TOKEN_LINEAR = 508, QC_TOKEN_LINES = 509, QC_TOKEN_LINESTRING = 510, QC_TOKEN_LIST = 511, QC_TOKEN_LOAD = 512, QC_TOKEN_LOCAL = 513, QC_TOKEN_LOCATOR = 514, QC_TOKEN_LOCKS = 515, QC_TOKEN_LOCK = 516, QC_TOKEN_LOGFILE = 517, QC_TOKEN_LOGS = 518, QC_TOKEN_LONGBLOB = 519, QC_TOKEN_LONGTEXT = 520, QC_TOKEN_LONG_NUM = 521, QC_TOKEN_LONG = 522, QC_TOKEN_LOOP = 523, QC_TOKEN_LOW_PRIORITY = 524, QC_TOKEN_LT = 525, QC_TOKEN_MASTER_CONNECT_RETRY = 526, QC_TOKEN_MASTER_HOST = 527, QC_TOKEN_MASTER_LOG_FILE = 528, QC_TOKEN_MASTER_LOG_POS = 529, QC_TOKEN_MASTER_PASSWORD = 530, QC_TOKEN_MASTER_PORT = 531, QC_TOKEN_MASTER_SERVER_ID = 532, QC_TOKEN_MASTER_SSL_CAPATH = 533, QC_TOKEN_MASTER_SSL_CA = 534, QC_TOKEN_MASTER_SSL_CERT = 535, QC_TOKEN_MASTER_SSL_CIPHER = 536, QC_TOKEN_MASTER_SSL_KEY = 537, QC_TOKEN_MASTER_SSL = 538, QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT = 539, QC_TOKEN_MASTER = 540, QC_TOKEN_MASTER_USER = 541, QC_TOKEN_MASTER_HEARTBEAT_PERIOD = 542, QC_TOKEN_MATCH = 543, QC_TOKEN_MAX_CONNECTIONS_PER_HOUR = 544, QC_TOKEN_MAX_QUERIES_PER_HOUR = 545, QC_TOKEN_MAX_ROWS = 546, QC_TOKEN_MAX_SIZE = 547, QC_TOKEN_MAX = 548, QC_TOKEN_MAX_UPDATES_PER_HOUR = 549, QC_TOKEN_MAX_USER_CONNECTIONS = 550, QC_TOKEN_MAX_VALUE = 551, QC_TOKEN_MEDIUMBLOB = 552, QC_TOKEN_MEDIUMINT = 553, QC_TOKEN_MEDIUMTEXT = 554, QC_TOKEN_MEDIUM = 555, QC_TOKEN_MEMORY = 556, QC_TOKEN_MERGE = 557, QC_TOKEN_MESSAGE_TEXT = 558, QC_TOKEN_MICROSECOND = 559, QC_TOKEN_MIGRATE = 560, QC_TOKEN_MINUTE_MICROSECOND = 561, QC_TOKEN_MINUTE_SECOND = 562, QC_TOKEN_MINUTE = 563, QC_TOKEN_MIN_ROWS = 564, QC_TOKEN_MIN = 565, QC_TOKEN_MODE = 566, QC_TOKEN_MODIFIES = 567, QC_TOKEN_MODIFY = 568, QC_TOKEN_MOD = 569, QC_TOKEN_MONTH = 570, QC_TOKEN_MULTILINESTRING = 571, QC_TOKEN_MULTIPOINT = 572, QC_TOKEN_MULTIPOLYGON = 573, QC_TOKEN_MUTEX = 574, QC_TOKEN_MYSQL_ERRNO = 575, QC_TOKEN_NAMES = 576, QC_TOKEN_NAME = 577, QC_TOKEN_NATIONAL = 578, QC_TOKEN_NATURAL = 579, QC_TOKEN_NCHAR_STRING = 580, QC_TOKEN_NCHAR = 581, QC_TOKEN_NDBCLUSTER = 582, QC_TOKEN_NE = 583, QC_TOKEN_NE_TRIPLE = 584, QC_TOKEN_NEG = 585, QC_TOKEN_NEW = 586, QC_TOKEN_NEXT = 587, QC_TOKEN_NODEGROUP = 588, QC_TOKEN_NONE = 589, QC_TOKEN_NOT2 = 590, QC_TOKEN_NOT = 591, QC_TOKEN_NOW = 592, QC_TOKEN_NO = 593, QC_TOKEN_NO_WAIT = 594, QC_TOKEN_NO_WRITE_TO_BINLOG = 595, QC_TOKEN_NULL = 596, QC_TOKEN_NUM = 597, QC_TOKEN_NUMERIC = 598, QC_TOKEN_NVARCHAR = 599, QC_TOKEN_OFFSET = 600, QC_TOKEN_OLD_PASSWORD = 601, QC_TOKEN_ON = 602, QC_TOKEN_ONE_SHOT = 603, QC_TOKEN_ONE = 604, QC_TOKEN_OPEN = 605, QC_TOKEN_OPTIMIZE = 606, QC_TOKEN_OPTIONS = 607, QC_TOKEN_OPTION = 608, QC_TOKEN_OPTIONALLY = 609, QC_TOKEN_OR2 = 610, QC_TOKEN_ORDER = 611, QC_TOKEN_OR_OR = 612, QC_TOKEN_OR = 613, QC_TOKEN_OUTER = 614, QC_TOKEN_OUTFILE = 615, QC_TOKEN_OUT = 616, QC_TOKEN_OWNER = 617, QC_TOKEN_PACK_KEYS = 618, QC_TOKEN_PAGE = 619, QC_TOKEN_PARAM_MARKER = 620, QC_TOKEN_PARSER = 621, QC_TOKEN_PARTIAL = 622, QC_TOKEN_PARTITIONING = 623, QC_TOKEN_PARTITIONS = 624, QC_TOKEN_PARTITION = 625, QC_TOKEN_PASSWORD = 626, QC_TOKEN_PHASE = 627, QC_TOKEN_PLUGINS = 628, QC_TOKEN_PLUGIN = 629, QC_TOKEN_POINT = 630, QC_TOKEN_POLYGON = 631, QC_TOKEN_PORT = 632, QC_TOKEN_POSITION = 633, QC_TOKEN_PRECISION = 634, QC_TOKEN_PREPARE = 635, QC_TOKEN_PRESERVE = 636, QC_TOKEN_PREV = 637, QC_TOKEN_PRIMARY = 638, QC_TOKEN_PRIVILEGES = 639, QC_TOKEN_PROCEDURE = 640, QC_TOKEN_PROCESS = 641, QC_TOKEN_PROCESSLIST = 642, QC_TOKEN_PROFILE = 643, QC_TOKEN_PROFILES = 644, QC_TOKEN_PURGE = 645, QC_TOKEN_QUARTER = 646, QC_TOKEN_QUERY = 647, QC_TOKEN_QUICK = 648, QC_TOKEN_RANGE = 649, QC_TOKEN_READS = 650, QC_TOKEN_READ_ONLY = 651, QC_TOKEN_READ = 652, QC_TOKEN_READ_WRITE = 653, QC_TOKEN_REAL = 654, QC_TOKEN_REBUILD = 655, QC_TOKEN_RECOVER = 656, QC_TOKEN_REDOFILE = 657, QC_TOKEN_REDO_BUFFER_SIZE = 658, QC_TOKEN_REDUNDANT = 659, QC_TOKEN_REFERENCES = 660, QC_TOKEN_REGEXP = 661, QC_TOKEN_RELAYLOG = 662, QC_TOKEN_RELAY_LOG_FILE = 663, QC_TOKEN_RELAY_LOG_POS = 664, QC_TOKEN_RELAY_THREAD = 665, QC_TOKEN_RELEASE = 666, QC_TOKEN_RELOAD = 667, QC_TOKEN_REMOVE = 668, QC_TOKEN_RENAME = 669, QC_TOKEN_REORGANIZE = 670, QC_TOKEN_REPAIR = 671, QC_TOKEN_REPEATABLE = 672, QC_TOKEN_REPEAT = 673, QC_TOKEN_REPLACE = 674, QC_TOKEN_REPLICATION = 675, QC_TOKEN_REQUIRE = 676, QC_TOKEN_RESET = 677, QC_TOKEN_RESIGNAL = 678, QC_TOKEN_RESOURCES = 679, QC_TOKEN_RESTORE = 680, QC_TOKEN_RESTRICT = 681, QC_TOKEN_RESUME = 682, QC_TOKEN_RETURNS = 683, QC_TOKEN_RETURN = 684, QC_TOKEN_REVOKE = 685, QC_TOKEN_RIGHT = 686, QC_TOKEN_ROLLBACK = 687, QC_TOKEN_ROLLUP = 688, QC_TOKEN_ROUTINE = 689, QC_TOKEN_ROWS = 690, QC_TOKEN_ROW_FORMAT = 691, QC_TOKEN_ROW = 692, QC_TOKEN_RTREE = 693, QC_TOKEN_SAVEPOINT = 694, QC_TOKEN_SCHEDULE = 695, QC_TOKEN_SCHEMA_NAME = 696, QC_TOKEN_SECOND_MICROSECOND = 697, QC_TOKEN_SECOND = 698, QC_TOKEN_SECURITY = 699, QC_TOKEN_SELECT = 700, QC_TOKEN_SENSITIVE = 701, QC_TOKEN_SEPARATOR = 702, QC_TOKEN_SERIALIZABLE = 703, QC_TOKEN_SERIAL = 704, QC_TOKEN_SESSION = 705, QC_TOKEN_SERVER = 706, QC_TOKEN_SERVER_OPTIONS = 707, QC_TOKEN_SET = 708, QC_TOKEN_SET_VAR = 709, QC_TOKEN_SHARE = 710, QC_TOKEN_SHIFT_LEFT = 711, QC_TOKEN_SHIFT_RIGHT = 712, QC_TOKEN_SHOW = 713, QC_TOKEN_SHUTDOWN = 714, QC_TOKEN_SIGNAL = 715, QC_TOKEN_SIGNED = 716, QC_TOKEN_SIMPLE = 717, QC_TOKEN_SLAVE = 718, QC_TOKEN_SMALLINT = 719, QC_TOKEN_SNAPSHOT = 720, QC_TOKEN_SOCKET = 721, QC_TOKEN_SONAME = 722, QC_TOKEN_SOUNDS = 723, QC_TOKEN_SOURCE = 724, QC_TOKEN_SPATIAL = 725, QC_TOKEN_SPECIFIC = 726, QC_TOKEN_SQLEXCEPTION = 727, QC_TOKEN_SQLSTATE = 728, QC_TOKEN_SQLWARNING = 729, QC_TOKEN_SQL_BIG_RESULT = 730, QC_TOKEN_SQL_BUFFER_RESULT = 731, QC_TOKEN_SQL_CACHE = 732, QC_TOKEN_SQL_CALC_FOUND_ROWS = 733, QC_TOKEN_SQL_NO_CACHE = 734, QC_TOKEN_SQL_SMALL_RESULT = 735, QC_TOKEN_SQL = 736, QC_TOKEN_SQL_THREAD = 737, QC_TOKEN_SSL = 738, QC_TOKEN_STARTING = 739, QC_TOKEN_STARTS = 740, QC_TOKEN_START = 741, QC_TOKEN_STATUS = 742, QC_TOKEN_STDDEV_SAMP = 743, QC_TOKEN_STD = 744, QC_TOKEN_STOP = 745, QC_TOKEN_STORAGE = 746, QC_TOKEN_STRAIGHT_JOIN = 747, QC_TOKEN_STRING = 748, QC_TOKEN_SUBCLASS_ORIGIN = 749, QC_TOKEN_SUBDATE = 750, QC_TOKEN_SUBJECT = 751, QC_TOKEN_SUBPARTITIONS = 752, QC_TOKEN_SUBPARTITION = 753, QC_TOKEN_SUBSTRING = 754, QC_TOKEN_SUM = 755, QC_TOKEN_SUPER = 756, QC_TOKEN_SUSPEND = 757, QC_TOKEN_SWAPS = 758, QC_TOKEN_SWITCHES = 759, QC_TOKEN_SYSDATE = 760, QC_TOKEN_TABLES = 761, QC_TOKEN_TABLESPACE = 762, QC_TOKEN_TABLE_REF_PRIORITY = 763, QC_TOKEN_TABLE = 764, QC_TOKEN_TABLE_CHECKSUM = 765, QC_TOKEN_TABLE_NAME = 766, QC_TOKEN_TEMPORARY = 767, QC_TOKEN_TEMPTABLE = 768, QC_TOKEN_TERMINATED = 769, QC_TOKEN_TEXT_STRING = 770, QC_TOKEN_TEXT = 771, QC_TOKEN_THAN = 772, QC_TOKEN_THEN = 773, QC_TOKEN_TIMESTAMP = 774, QC_TOKEN_TIMESTAMP_ADD = 775, QC_TOKEN_TIMESTAMP_DIFF = 776, QC_TOKEN_TIME = 777, QC_TOKEN_TINYBLOB = 778, QC_TOKEN_TINYINT = 779, QC_TOKEN_TINYTEXT = 780, QC_TOKEN_TO = 781, QC_TOKEN_TRAILING = 782, QC_TOKEN_TRANSACTION = 783, QC_TOKEN_TRIGGERS = 784, QC_TOKEN_TRIGGER = 785, QC_TOKEN_TRIM = 786, QC_TOKEN_TRUE = 787, QC_TOKEN_TRUNCATE = 788, QC_TOKEN_TYPES = 789, QC_TOKEN_TYPE = 790, QC_TOKEN_UDF_RETURNS = 791, QC_TOKEN_ULONGLONG_NUM = 792, QC_TOKEN_UNCOMMITTED = 793, QC_TOKEN_UNDEFINED = 794, QC_TOKEN_UNDERSCORE_CHARSET = 795, QC_TOKEN_UNDOFILE = 796, QC_TOKEN_UNDO_BUFFER_SIZE = 797, QC_TOKEN_UNDO = 798, QC_TOKEN_UNICODE = 799, QC_TOKEN_UNINSTALL = 800, QC_TOKEN_UNION = 801, QC_TOKEN_UNIQUE = 802, QC_TOKEN_UNKNOWN = 803, QC_TOKEN_UNLOCK = 804, QC_TOKEN_UNSIGNED = 805, QC_TOKEN_UNTIL = 806, QC_TOKEN_UPDATE = 807, QC_TOKEN_UPGRADE = 808, QC_TOKEN_USAGE = 809, QC_TOKEN_USER = 810, QC_TOKEN_USE_FRM = 811, QC_TOKEN_USE = 812, QC_TOKEN_USING = 813, QC_TOKEN_UTC_DATE = 814, QC_TOKEN_UTC_TIMESTAMP = 815, QC_TOKEN_UTC_TIME = 816, QC_TOKEN_VALUES = 817, QC_TOKEN_VALUE = 818, QC_TOKEN_VARBINARY = 819, QC_TOKEN_VARCHAR = 820, QC_TOKEN_VARIABLES = 821, QC_TOKEN_VARIANCE = 822, QC_TOKEN_VARYING = 823, QC_TOKEN_VAR_SAMP = 824, QC_TOKEN_VIEW = 825, QC_TOKEN_WAIT = 826, QC_TOKEN_WARNINGS = 827, QC_TOKEN_WEEK = 828, QC_TOKEN_WHEN = 829, QC_TOKEN_WHERE = 830, QC_TOKEN_WHILE = 831, QC_TOKEN_WITH = 832, QC_TOKEN_WITH_CUBE = 833, QC_TOKEN_WITH_ROLLUP = 834, QC_TOKEN_WORK = 835, QC_TOKEN_WRAPPER = 836, QC_TOKEN_WRITE = 837, QC_TOKEN_X509 = 838, QC_TOKEN_XA = 839, QC_TOKEN_XML = 840, QC_TOKEN_XOR = 841, QC_TOKEN_YEAR_MONTH = 842, QC_TOKEN_YEAR = 843, QC_TOKEN_ZEROFILL = 844, QC_TOKEN_CLIENT_FLAG = 845, QC_TOKEN_GLOBAL_VAR = 846, QC_TOKEN_SESSION_VAR = 847, QC_TOKEN_BRACKET_OPEN = 848, QC_TOKEN_BRACKET_CLOSE = 849, QC_TOKEN_PLUS = 850, QC_TOKEN_MINUS = 851, QC_TOKEN_STAR = 852, QC_TOKEN_COMMA = 853, QC_TOKEN_DOT = 854, QC_TOKEN_SEMICOLON = 855, QC_TOKEN_NO_MORE = 856, QC_TOKEN_IDENTIFIER = 857, QC_TOKEN_INTNUM = 858, QC_TOKEN_FLOATNUM = 859, QC_TOKEN_ASSIGN_TO_VAR = 860, QC_TOKEN_TILDE = 861 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 214 of yacc.c */ #line 40 "mysqlnd_query_parser.grammar" zval zv; const char * kn; /* keyword_name */ smart_str * comment; /* Line 214 of yacc.c */ #line 772 "mysqlnd_query_parser.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 46 "mysqlnd_query_parser.grammar" /* so we can override the default declaration */ #define YY_DECL #include "mysqlnd_query_lexer.lex.h" extern int mysqlnd_qp_lex(YYSTYPE * yylval_param, yyscan_t yyscanner TSRMLS_DC); /* Line 264 of yacc.c */ #line 792 "mysqlnd_query_parser.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 14 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 3121 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 607 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 48 /* YYNRULES -- Number of rules. */ #define YYNRULES 396 /* YYNRULES -- Number of states. */ #define YYNSTATES 437 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 861 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint16 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 24, 28, 34, 42, 44, 45, 48, 49, 53, 54, 56, 58, 59, 65, 70, 72, 74, 79, 81, 83, 88, 90, 91, 97, 100, 101, 103, 105, 107, 114, 116, 117, 123, 125, 126, 127, 128, 129, 138, 140, 143, 144, 147, 149, 153, 155, 159, 161, 163, 165, 167, 172, 173, 175, 179, 181, 182, 184, 188, 194, 196, 198, 201, 203, 204, 207, 209, 211, 215, 218, 219, 221, 225, 228, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 570, 572, 574, 576, 578, 580, 582, 584, 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 752, 754, 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 816, 818, 820, 822, 824, 826, 828, 830, 832, 834, 836, 838, 840, 842, 844, 846, 848, 850 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { 608, 0, -1, 630, -1, 628, -1, 626, -1, 623, -1, 621, -1, 619, -1, 617, -1, 616, -1, 611, -1, 610, -1, -1, 634, 609, 1, -1, 634, 94, 509, 614, 647, -1, 634, 136, 612, 618, 613, 647, 615, -1, 512, -1, -1, 211, 161, -1, -1, 211, 336, 161, -1, -1, 426, -1, 50, -1, -1, 634, 12, 629, 509, 647, -1, 634, 414, 618, 647, -1, 509, -1, 506, -1, 634, 419, 620, 647, -1, 627, -1, 121, -1, 634, 533, 622, 647, -1, 509, -1, -1, 634, 123, 624, 182, 647, -1, 625, 624, -1, -1, 393, -1, 269, -1, 212, -1, 634, 552, 627, 629, 647, 453, -1, 269, -1, -1, 634, 222, 226, 629, 647, -1, 212, -1, -1, -1, -1, -1, 634, 445, 631, 635, 632, 648, 633, 650, -1, 73, -1, 634, 73, -1, -1, 634, 597, -1, 636, -1, 637, 598, 636, -1, 637, -1, 634, 638, 645, -1, 643, -1, 639, -1, 603, -1, 493, -1, 643, 593, 640, 594, -1, -1, 641, -1, 641, 598, 642, -1, 642, -1, -1, 644, -1, 644, 599, 644, -1, 644, 599, 644, 599, 644, -1, 602, -1, 653, -1, 18, 644, -1, 644, -1, -1, 647, 645, -1, 137, -1, 644, -1, 644, 599, 644, -1, 182, 649, -1, -1, 646, -1, 649, 598, 646, -1, 575, 651, -1, 643, 152, 652, -1, 603, -1, 493, -1, 654, -1, 20, -1, 28, -1, 30, -1, 47, -1, 48, -1, 58, -1, 60, -1, 65, -1, 75, -1, 87, -1, 115, -1, 135, -1, 146, -1, 160, -1, 176, -1, 196, -1, 199, -1, 202, -1, 224, -1, 241, -1, 338, -1, 350, -1, 352, -1, 362, -1, 366, -1, 370, -1, 377, -1, 380, -1, 413, -1, 416, -1, 422, -1, 425, -1, 432, -1, 439, -1, 444, -1, 451, -1, 461, -1, 466, -1, 463, -1, 467, -1, 486, -1, 490, -1, 533, -1, 544, -1, 545, -1, 581, -1, 584, -1, 553, -1, 4, -1, 6, -1, 7, -1, 8, -1, 9, -1, 10, -1, 17, -1, 22, -1, 23, -1, 25, -1, 24, -1, 26, -1, 27, -1, 34, -1, 38, -1, 41, -1, 43, -1, 42, -1, 45, -1, 51, -1, 55, -1, 57, -1, 62, -1, 64, -1, 66, -1, 67, -1, 69, -1, 70, -1, 74, -1, 76, -1, 77, -1, 78, -1, 79, -1, 81, -1, 82, -1, 88, -1, 90, -1, 93, -1, 96, -1, 105, -1, 104, -1, 106, -1, 109, -1, 114, -1, 120, -1, 122, -1, 126, -1, 128, -1, 129, -1, 130, -1, 131, -1, 138, -1, 139, -1, 140, -1, 147, -1, 151, -1, 150, -1, 149, -1, 154, -1, 156, -1, 158, -1, 157, -1, 159, -1, 163, -1, 164, -1, 165, -1, 169, -1, 168, -1, 180, -1, 144, -1, 183, -1, 171, -1, 172, -1, 173, -1, 181, -1, 188, -1, 187, -1, 189, -1, 192, -1, 190, -1, 197, -1, 203, -1, 207, -1, 209, -1, 228, -1, 214, -1, 215, -1, 218, -1, 230, -1, 231, -1, 233, -1, 234, -1, 223, -1, 238, -1, 242, -1, 245, -1, 248, -1, 249, -1, 255, -1, 256, -1, 258, -1, 260, -1, 262, -1, 263, -1, 291, -1, 285, -1, 272, -1, 276, -1, 273, -1, 274, -1, 286, -1, 275, -1, 277, -1, 271, -1, 283, -1, 279, -1, 278, -1, 280, -1, 281, -1, 282, -1, 289, -1, 290, -1, 292, -1, 294, -1, 295, -1, 296, -1, 300, -1, 301, -1, 302, -1, 304, -1, 305, -1, 308, -1, 309, -1, 313, -1, 311, -1, 315, -1, 316, -1, 317, -1, 318, -1, 319, -1, 322, -1, 321, -1, 323, -1, 326, -1, 327, -1, 332, -1, 331, -1, 339, -1, 333, -1, 334, -1, 344, -1, 345, -1, 346, -1, 348, -1, 349, -1, 363, -1, 364, -1, 367, -1, 368, -1, 369, -1, 371, -1, 372, -1, 374, -1, 373, -1, 375, -1, 376, -1, 381, -1, 382, -1, 384, -1, 386, -1, 387, -1, 388, -1, 389, -1, 391, -1, 392, -1, 393, -1, 396, -1, 400, -1, 401, -1, 403, -1, 402, -1, 404, -1, 408, -1, 409, -1, 410, -1, 412, -1, 415, -1, 417, -1, 420, -1, 424, -1, 427, -1, 428, -1, 433, -1, 434, -1, 435, -1, 436, -1, 437, -1, 438, -1, 440, -1, 443, -1, 449, -1, 448, -1, 450, -1, 462, -1, 455, -1, 459, -1, 465, -1, 468, -1, 469, -1, 477, -1, 476, -1, 479, -1, 482, -1, 485, -1, 487, -1, 491, -1, 493, -1, 495, -1, 496, -1, 498, -1, 497, -1, 501, -1, 502, -1, 503, -1, 504, -1, 506, -1, 510, -1, 507, -1, 512, -1, 513, -1, 516, -1, 517, -1, 528, -1, 529, -1, 519, -1, 520, -1, 521, -1, 522, -1, 534, -1, 535, -1, 536, -1, 185, -1, 538, -1, 539, -1, 542, -1, 541, -1, 548, -1, 551, -1, 555, -1, 556, -1, 566, -1, 570, -1, 563, -1, 572, -1, 571, -1, 573, -1, 580, -1, 583, -1, 588, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 665, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 675, 679, 686, 692, 693, 696, 697, 700, 701, 705, 706, 707, 712, 721, 728, 729, 734, 741, 742, 747, 753, 754, 759, 766, 767, 770, 771, 772, 777, 784, 785, 791, 798, 799, 804, 810, 814, 803, 827, 828, 829, 832, 833, 836, 837, 840, 842, 843, 844, 845, 859, 861, 862, 865, 866, 870, 872, 884, 898, 916, 917, 921, 922, 923, 926, 944, 954, 964, 981, 982, 987, 988, 991, 995, 1007, 1008, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "QC_TOKEN_ACCESSIBLE", "QC_TOKEN_ACTION", "QC_TOKEN_ADD", "QC_TOKEN_ADDDATE", "QC_TOKEN_AFTER", "QC_TOKEN_AGAINST", "QC_TOKEN_AGGREGATE", "QC_TOKEN_ALGORITHM", "QC_TOKEN_ALL", "QC_TOKEN_ALTER", "QC_TOKEN_ANALYZE", "QC_TOKEN_AND_AND", "QC_TOKEN_AND", "QC_TOKEN_BETWEEN_AND", "QC_TOKEN_ANY", "QC_TOKEN_AS", "QC_TOKEN_ASC", "QC_TOKEN_ASCII", "QC_TOKEN_ASENSITIVE", "QC_TOKEN_AT", "QC_TOKEN_AUTHORS", "QC_TOKEN_AUTOEXTEND_SIZE", "QC_TOKEN_AUTO_INC", "QC_TOKEN_AVG_ROW_LENGTH", "QC_TOKEN_AVG", "QC_TOKEN_BACKUP", "QC_TOKEN_BEFORE", "QC_TOKEN_BEGIN", "QC_TOKEN_BETWEEN", "QC_TOKEN_BIGINT", "QC_TOKEN_BINARY", "QC_TOKEN_BINLOG", "QC_TOKEN_BIN_NUM", "QC_TOKEN_BIT_AND", "QC_TOKEN_BIT_OR", "QC_TOKEN_BIT", "QC_TOKEN_BIT_XOR", "QC_TOKEN_BLOB", "QC_TOKEN_BLOCK", "QC_TOKEN_BOOLEAN", "QC_TOKEN_BOOL", "QC_TOKEN_BOTH", "QC_TOKEN_BTREE", "QC_TOKEN_BY", "QC_TOKEN_BYTE", "QC_TOKEN_CACHE", "QC_TOKEN_CALL", "QC_TOKEN_CASCADE", "QC_TOKEN_CASCADED", "QC_TOKEN_CASE", "QC_TOKEN_CAST", "QC_TOKEN_CATALOG_NAME", "QC_TOKEN_CHAIN", "QC_TOKEN_CHANGE", "QC_TOKEN_CHANGED", "QC_TOKEN_CHARSET", "QC_TOKEN_CHAR", "QC_TOKEN_CHECKSUM", "QC_TOKEN_CHECK", "QC_TOKEN_CIPHER", "QC_TOKEN_CLASS_ORIGIN", "QC_TOKEN_CLIENT", "QC_TOKEN_CLOSE", "QC_TOKEN_COALESCE", "QC_TOKEN_CODE", "QC_TOKEN_COLLATE", "QC_TOKEN_COLLATION", "QC_TOKEN_COLUMNS", "QC_TOKEN_COLUMN", "QC_TOKEN_COLUMN_NAME", "QC_TOKEN_COMMENT", "QC_TOKEN_COMMITTED", "QC_TOKEN_COMMIT", "QC_TOKEN_COMPACT", "QC_TOKEN_COMPLETION", "QC_TOKEN_COMPRESSED", "QC_TOKEN_CONCURRENT", "QC_TOKEN_CONDITION", "QC_TOKEN_CONNECTION", "QC_TOKEN_CONSISTENT", "QC_TOKEN_CONSTRAINT", "QC_TOKEN_CONSTRAINT_CATALOG", "QC_TOKEN_CONSTRAINT_NAME", "QC_TOKEN_CONSTRAINT_SCHEMA", "QC_TOKEN_CONTAINS", "QC_TOKEN_CONTEXT", "QC_TOKEN_CONTINUE", "QC_TOKEN_CONTRIBUTORS", "QC_TOKEN_CONVERT", "QC_TOKEN_COUNT", "QC_TOKEN_CPU", "QC_TOKEN_CREATE", "QC_TOKEN_CROSS", "QC_TOKEN_CUBE", "QC_TOKEN_CURDATE", "QC_TOKEN_CURRENT_USER", "QC_TOKEN_CURSOR", "QC_TOKEN_CURSOR_NAME", "QC_TOKEN_CURTIME", "QC_TOKEN_DATABASE", "QC_TOKEN_DATABASES", "QC_TOKEN_DATAFILE", "QC_TOKEN_DATA", "QC_TOKEN_DATETIME", "QC_TOKEN_DATE_ADD_INTERVAL", "QC_TOKEN_DATE_SUB_INTERVAL", "QC_TOKEN_DATE", "QC_TOKEN_DAY_HOUR", "QC_TOKEN_DAY_MICROSECOND", "QC_TOKEN_DAY_MINUTE", "QC_TOKEN_DAY_SECOND", "QC_TOKEN_DAY", "QC_TOKEN_DEALLOCATE", "QC_TOKEN_DECIMAL_NUM", "QC_TOKEN_DECIMAL", "QC_TOKEN_DECLARE", "QC_TOKEN_DEFAULT", "QC_TOKEN_DEFINER", "QC_TOKEN_DELAYED", "QC_TOKEN_DELAY_KEY_WRITE", "QC_TOKEN_DELETE", "QC_TOKEN_DESC", "QC_TOKEN_DESCRIBE", "QC_TOKEN_DES_KEY_FILE", "QC_TOKEN_DETERMINISTIC", "QC_TOKEN_DIRECTORY", "QC_TOKEN_DISABLE", "QC_TOKEN_DISCARD", "QC_TOKEN_DISK", "QC_TOKEN_DISTINCT", "QC_TOKEN_DIV", "QC_TOKEN_DOUBLE", "QC_TOKEN_DO", "QC_TOKEN_DROP", "QC_TOKEN_DUAL", "QC_TOKEN_DUMPFILE", "QC_TOKEN_DUPLICATE", "QC_TOKEN_DYNAMIC", "QC_TOKEN_EACH", "QC_TOKEN_ELSE", "QC_TOKEN_ELSEIF", "QC_TOKEN_ENABLE", "QC_TOKEN_ENCLOSED", "QC_TOKEN_END", "QC_TOKEN_ENDS", "QC_TOKEN_END_OF_INPUT", "QC_TOKEN_ENGINES", "QC_TOKEN_ENGINE", "QC_TOKEN_ENUM", "QC_TOKEN_EQ", "QC_TOKEN_EQUAL", "QC_TOKEN_ERRORS", "QC_TOKEN_ESCAPED", "QC_TOKEN_ESCAPE", "QC_TOKEN_EVENTS", "QC_TOKEN_EVENT", "QC_TOKEN_EVERY", "QC_TOKEN_EXECUTE", "QC_TOKEN_EXISTS", "QC_TOKEN_EXIT", "QC_TOKEN_EXPANSION", "QC_TOKEN_EXTENDED", "QC_TOKEN_EXTENT_SIZE", "QC_TOKEN_EXTRACT", "QC_TOKEN_FALSE", "QC_TOKEN_FAST", "QC_TOKEN_FAULTS", "QC_TOKEN_FETCH", "QC_TOKEN_FILE", "QC_TOKEN_FIRST", "QC_TOKEN_FIXED", "QC_TOKEN_FLOAT_NUM", "QC_TOKEN_FLOAT", "QC_TOKEN_FLUSH", "QC_TOKEN_FORCE", "QC_TOKEN_FOREIGN", "QC_TOKEN_FOR", "QC_TOKEN_FOUND", "QC_TOKEN_FRAC_SECOND", "QC_TOKEN_FROM", "QC_TOKEN_FULL", "QC_TOKEN_FULLTEXT", "QC_TOKEN_FUNCTION", "QC_TOKEN_GE", "QC_TOKEN_GEOMETRYCOLLECTION", "QC_TOKEN_GEOMETRY", "QC_TOKEN_GET_FORMAT", "QC_TOKEN_GLOBAL", "QC_TOKEN_GRANT", "QC_TOKEN_GRANTS", "QC_TOKEN_GROUP", "QC_TOKEN_GROUP_CONCAT", "QC_TOKEN_GT", "QC_TOKEN_HANDLER", "QC_TOKEN_HASH", "QC_TOKEN_HAVING", "QC_TOKEN_HELP", "QC_TOKEN_HEX_NUM", "QC_TOKEN_HIGH_PRIORITY", "QC_TOKEN_HOST", "QC_TOKEN_HOSTS", "QC_TOKEN_HOUR_MICROSECOND", "QC_TOKEN_HOUR_MINUTE", "QC_TOKEN_HOUR_SECOND", "QC_TOKEN_HOUR", "QC_TOKEN_IDENT", "QC_TOKEN_IDENTIFIED", "QC_TOKEN_IDENT_QUOTED", "QC_TOKEN_IF", "QC_TOKEN_IGNORE", "QC_TOKEN_IGNORE_SERVER_IDS", "QC_TOKEN_IMPORT", "QC_TOKEN_INDEXES", "QC_TOKEN_INDEX", "QC_TOKEN_INFILE", "QC_TOKEN_INITIAL_SIZE", "QC_TOKEN_INNER", "QC_TOKEN_INOUT", "QC_TOKEN_INSENSITIVE", "QC_TOKEN_INSERT", "QC_TOKEN_INSERT_METHOD", "QC_TOKEN_INSTALL", "QC_TOKEN_INTERVAL", "QC_TOKEN_INTO", "QC_TOKEN_INT", "QC_TOKEN_INVOKER", "QC_TOKEN_IN", "QC_TOKEN_IO", "QC_TOKEN_IPC", "QC_TOKEN_IS", "QC_TOKEN_ISOLATION", "QC_TOKEN_ISSUER", "QC_TOKEN_ITERATE", "QC_TOKEN_JOIN", "QC_TOKEN_KEYS", "QC_TOKEN_KEY_BLOCK_SIZE", "QC_TOKEN_KEY", "QC_TOKEN_KILL", "QC_TOKEN_LANGUAGE", "QC_TOKEN_LAST", "QC_TOKEN_LE", "QC_TOKEN_LEADING", "QC_TOKEN_LEAVES", "QC_TOKEN_LEAVE", "QC_TOKEN_LEFT", "QC_TOKEN_LESS", "QC_TOKEN_LEVEL", "QC_TOKEN_LEX_HOSTNAME", "QC_TOKEN_LIKE", "QC_TOKEN_LIMIT", "QC_TOKEN_LINEAR", "QC_TOKEN_LINES", "QC_TOKEN_LINESTRING", "QC_TOKEN_LIST", "QC_TOKEN_LOAD", "QC_TOKEN_LOCAL", "QC_TOKEN_LOCATOR", "QC_TOKEN_LOCKS", "QC_TOKEN_LOCK", "QC_TOKEN_LOGFILE", "QC_TOKEN_LOGS", "QC_TOKEN_LONGBLOB", "QC_TOKEN_LONGTEXT", "QC_TOKEN_LONG_NUM", "QC_TOKEN_LONG", "QC_TOKEN_LOOP", "QC_TOKEN_LOW_PRIORITY", "QC_TOKEN_LT", "QC_TOKEN_MASTER_CONNECT_RETRY", "QC_TOKEN_MASTER_HOST", "QC_TOKEN_MASTER_LOG_FILE", "QC_TOKEN_MASTER_LOG_POS", "QC_TOKEN_MASTER_PASSWORD", "QC_TOKEN_MASTER_PORT", "QC_TOKEN_MASTER_SERVER_ID", "QC_TOKEN_MASTER_SSL_CAPATH", "QC_TOKEN_MASTER_SSL_CA", "QC_TOKEN_MASTER_SSL_CERT", "QC_TOKEN_MASTER_SSL_CIPHER", "QC_TOKEN_MASTER_SSL_KEY", "QC_TOKEN_MASTER_SSL", "QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT", "QC_TOKEN_MASTER", "QC_TOKEN_MASTER_USER", "QC_TOKEN_MASTER_HEARTBEAT_PERIOD", "QC_TOKEN_MATCH", "QC_TOKEN_MAX_CONNECTIONS_PER_HOUR", "QC_TOKEN_MAX_QUERIES_PER_HOUR", "QC_TOKEN_MAX_ROWS", "QC_TOKEN_MAX_SIZE", "QC_TOKEN_MAX", "QC_TOKEN_MAX_UPDATES_PER_HOUR", "QC_TOKEN_MAX_USER_CONNECTIONS", "QC_TOKEN_MAX_VALUE", "QC_TOKEN_MEDIUMBLOB", "QC_TOKEN_MEDIUMINT", "QC_TOKEN_MEDIUMTEXT", "QC_TOKEN_MEDIUM", "QC_TOKEN_MEMORY", "QC_TOKEN_MERGE", "QC_TOKEN_MESSAGE_TEXT", "QC_TOKEN_MICROSECOND", "QC_TOKEN_MIGRATE", "QC_TOKEN_MINUTE_MICROSECOND", "QC_TOKEN_MINUTE_SECOND", "QC_TOKEN_MINUTE", "QC_TOKEN_MIN_ROWS", "QC_TOKEN_MIN", "QC_TOKEN_MODE", "QC_TOKEN_MODIFIES", "QC_TOKEN_MODIFY", "QC_TOKEN_MOD", "QC_TOKEN_MONTH", "QC_TOKEN_MULTILINESTRING", "QC_TOKEN_MULTIPOINT", "QC_TOKEN_MULTIPOLYGON", "QC_TOKEN_MUTEX", "QC_TOKEN_MYSQL_ERRNO", "QC_TOKEN_NAMES", "QC_TOKEN_NAME", "QC_TOKEN_NATIONAL", "QC_TOKEN_NATURAL", "QC_TOKEN_NCHAR_STRING", "QC_TOKEN_NCHAR", "QC_TOKEN_NDBCLUSTER", "QC_TOKEN_NE", "QC_TOKEN_NE_TRIPLE", "QC_TOKEN_NEG", "QC_TOKEN_NEW", "QC_TOKEN_NEXT", "QC_TOKEN_NODEGROUP", "QC_TOKEN_NONE", "QC_TOKEN_NOT2", "QC_TOKEN_NOT", "QC_TOKEN_NOW", "QC_TOKEN_NO", "QC_TOKEN_NO_WAIT", "QC_TOKEN_NO_WRITE_TO_BINLOG", "QC_TOKEN_NULL", "QC_TOKEN_NUM", "QC_TOKEN_NUMERIC", "QC_TOKEN_NVARCHAR", "QC_TOKEN_OFFSET", "QC_TOKEN_OLD_PASSWORD", "QC_TOKEN_ON", "QC_TOKEN_ONE_SHOT", "QC_TOKEN_ONE", "QC_TOKEN_OPEN", "QC_TOKEN_OPTIMIZE", "QC_TOKEN_OPTIONS", "QC_TOKEN_OPTION", "QC_TOKEN_OPTIONALLY", "QC_TOKEN_OR2", "QC_TOKEN_ORDER", "QC_TOKEN_OR_OR", "QC_TOKEN_OR", "QC_TOKEN_OUTER", "QC_TOKEN_OUTFILE", "QC_TOKEN_OUT", "QC_TOKEN_OWNER", "QC_TOKEN_PACK_KEYS", "QC_TOKEN_PAGE", "QC_TOKEN_PARAM_MARKER", "QC_TOKEN_PARSER", "QC_TOKEN_PARTIAL", "QC_TOKEN_PARTITIONING", "QC_TOKEN_PARTITIONS", "QC_TOKEN_PARTITION", "QC_TOKEN_PASSWORD", "QC_TOKEN_PHASE", "QC_TOKEN_PLUGINS", "QC_TOKEN_PLUGIN", "QC_TOKEN_POINT", "QC_TOKEN_POLYGON", "QC_TOKEN_PORT", "QC_TOKEN_POSITION", "QC_TOKEN_PRECISION", "QC_TOKEN_PREPARE", "QC_TOKEN_PRESERVE", "QC_TOKEN_PREV", "QC_TOKEN_PRIMARY", "QC_TOKEN_PRIVILEGES", "QC_TOKEN_PROCEDURE", "QC_TOKEN_PROCESS", "QC_TOKEN_PROCESSLIST", "QC_TOKEN_PROFILE", "QC_TOKEN_PROFILES", "QC_TOKEN_PURGE", "QC_TOKEN_QUARTER", "QC_TOKEN_QUERY", "QC_TOKEN_QUICK", "QC_TOKEN_RANGE", "QC_TOKEN_READS", "QC_TOKEN_READ_ONLY", "QC_TOKEN_READ", "QC_TOKEN_READ_WRITE", "QC_TOKEN_REAL", "QC_TOKEN_REBUILD", "QC_TOKEN_RECOVER", "QC_TOKEN_REDOFILE", "QC_TOKEN_REDO_BUFFER_SIZE", "QC_TOKEN_REDUNDANT", "QC_TOKEN_REFERENCES", "QC_TOKEN_REGEXP", "QC_TOKEN_RELAYLOG", "QC_TOKEN_RELAY_LOG_FILE", "QC_TOKEN_RELAY_LOG_POS", "QC_TOKEN_RELAY_THREAD", "QC_TOKEN_RELEASE", "QC_TOKEN_RELOAD", "QC_TOKEN_REMOVE", "QC_TOKEN_RENAME", "QC_TOKEN_REORGANIZE", "QC_TOKEN_REPAIR", "QC_TOKEN_REPEATABLE", "QC_TOKEN_REPEAT", "QC_TOKEN_REPLACE", "QC_TOKEN_REPLICATION", "QC_TOKEN_REQUIRE", "QC_TOKEN_RESET", "QC_TOKEN_RESIGNAL", "QC_TOKEN_RESOURCES", "QC_TOKEN_RESTORE", "QC_TOKEN_RESTRICT", "QC_TOKEN_RESUME", "QC_TOKEN_RETURNS", "QC_TOKEN_RETURN", "QC_TOKEN_REVOKE", "QC_TOKEN_RIGHT", "QC_TOKEN_ROLLBACK", "QC_TOKEN_ROLLUP", "QC_TOKEN_ROUTINE", "QC_TOKEN_ROWS", "QC_TOKEN_ROW_FORMAT", "QC_TOKEN_ROW", "QC_TOKEN_RTREE", "QC_TOKEN_SAVEPOINT", "QC_TOKEN_SCHEDULE", "QC_TOKEN_SCHEMA_NAME", "QC_TOKEN_SECOND_MICROSECOND", "QC_TOKEN_SECOND", "QC_TOKEN_SECURITY", "QC_TOKEN_SELECT", "QC_TOKEN_SENSITIVE", "QC_TOKEN_SEPARATOR", "QC_TOKEN_SERIALIZABLE", "QC_TOKEN_SERIAL", "QC_TOKEN_SESSION", "QC_TOKEN_SERVER", "QC_TOKEN_SERVER_OPTIONS", "QC_TOKEN_SET", "QC_TOKEN_SET_VAR", "QC_TOKEN_SHARE", "QC_TOKEN_SHIFT_LEFT", "QC_TOKEN_SHIFT_RIGHT", "QC_TOKEN_SHOW", "QC_TOKEN_SHUTDOWN", "QC_TOKEN_SIGNAL", "QC_TOKEN_SIGNED", "QC_TOKEN_SIMPLE", "QC_TOKEN_SLAVE", "QC_TOKEN_SMALLINT", "QC_TOKEN_SNAPSHOT", "QC_TOKEN_SOCKET", "QC_TOKEN_SONAME", "QC_TOKEN_SOUNDS", "QC_TOKEN_SOURCE", "QC_TOKEN_SPATIAL", "QC_TOKEN_SPECIFIC", "QC_TOKEN_SQLEXCEPTION", "QC_TOKEN_SQLSTATE", "QC_TOKEN_SQLWARNING", "QC_TOKEN_SQL_BIG_RESULT", "QC_TOKEN_SQL_BUFFER_RESULT", "QC_TOKEN_SQL_CACHE", "QC_TOKEN_SQL_CALC_FOUND_ROWS", "QC_TOKEN_SQL_NO_CACHE", "QC_TOKEN_SQL_SMALL_RESULT", "QC_TOKEN_SQL", "QC_TOKEN_SQL_THREAD", "QC_TOKEN_SSL", "QC_TOKEN_STARTING", "QC_TOKEN_STARTS", "QC_TOKEN_START", "QC_TOKEN_STATUS", "QC_TOKEN_STDDEV_SAMP", "QC_TOKEN_STD", "QC_TOKEN_STOP", "QC_TOKEN_STORAGE", "QC_TOKEN_STRAIGHT_JOIN", "QC_TOKEN_STRING", "QC_TOKEN_SUBCLASS_ORIGIN", "QC_TOKEN_SUBDATE", "QC_TOKEN_SUBJECT", "QC_TOKEN_SUBPARTITIONS", "QC_TOKEN_SUBPARTITION", "QC_TOKEN_SUBSTRING", "QC_TOKEN_SUM", "QC_TOKEN_SUPER", "QC_TOKEN_SUSPEND", "QC_TOKEN_SWAPS", "QC_TOKEN_SWITCHES", "QC_TOKEN_SYSDATE", "QC_TOKEN_TABLES", "QC_TOKEN_TABLESPACE", "QC_TOKEN_TABLE_REF_PRIORITY", "QC_TOKEN_TABLE", "QC_TOKEN_TABLE_CHECKSUM", "QC_TOKEN_TABLE_NAME", "QC_TOKEN_TEMPORARY", "QC_TOKEN_TEMPTABLE", "QC_TOKEN_TERMINATED", "QC_TOKEN_TEXT_STRING", "QC_TOKEN_TEXT", "QC_TOKEN_THAN", "QC_TOKEN_THEN", "QC_TOKEN_TIMESTAMP", "QC_TOKEN_TIMESTAMP_ADD", "QC_TOKEN_TIMESTAMP_DIFF", "QC_TOKEN_TIME", "QC_TOKEN_TINYBLOB", "QC_TOKEN_TINYINT", "QC_TOKEN_TINYTEXT", "QC_TOKEN_TO", "QC_TOKEN_TRAILING", "QC_TOKEN_TRANSACTION", "QC_TOKEN_TRIGGERS", "QC_TOKEN_TRIGGER", "QC_TOKEN_TRIM", "QC_TOKEN_TRUE", "QC_TOKEN_TRUNCATE", "QC_TOKEN_TYPES", "QC_TOKEN_TYPE", "QC_TOKEN_UDF_RETURNS", "QC_TOKEN_ULONGLONG_NUM", "QC_TOKEN_UNCOMMITTED", "QC_TOKEN_UNDEFINED", "QC_TOKEN_UNDERSCORE_CHARSET", "QC_TOKEN_UNDOFILE", "QC_TOKEN_UNDO_BUFFER_SIZE", "QC_TOKEN_UNDO", "QC_TOKEN_UNICODE", "QC_TOKEN_UNINSTALL", "QC_TOKEN_UNION", "QC_TOKEN_UNIQUE", "QC_TOKEN_UNKNOWN", "QC_TOKEN_UNLOCK", "QC_TOKEN_UNSIGNED", "QC_TOKEN_UNTIL", "QC_TOKEN_UPDATE", "QC_TOKEN_UPGRADE", "QC_TOKEN_USAGE", "QC_TOKEN_USER", "QC_TOKEN_USE_FRM", "QC_TOKEN_USE", "QC_TOKEN_USING", "QC_TOKEN_UTC_DATE", "QC_TOKEN_UTC_TIMESTAMP", "QC_TOKEN_UTC_TIME", "QC_TOKEN_VALUES", "QC_TOKEN_VALUE", "QC_TOKEN_VARBINARY", "QC_TOKEN_VARCHAR", "QC_TOKEN_VARIABLES", "QC_TOKEN_VARIANCE", "QC_TOKEN_VARYING", "QC_TOKEN_VAR_SAMP", "QC_TOKEN_VIEW", "QC_TOKEN_WAIT", "QC_TOKEN_WARNINGS", "QC_TOKEN_WEEK", "QC_TOKEN_WHEN", "QC_TOKEN_WHERE", "QC_TOKEN_WHILE", "QC_TOKEN_WITH", "QC_TOKEN_WITH_CUBE", "QC_TOKEN_WITH_ROLLUP", "QC_TOKEN_WORK", "QC_TOKEN_WRAPPER", "QC_TOKEN_WRITE", "QC_TOKEN_X509", "QC_TOKEN_XA", "QC_TOKEN_XML", "QC_TOKEN_XOR", "QC_TOKEN_YEAR_MONTH", "QC_TOKEN_YEAR", "QC_TOKEN_ZEROFILL", "QC_TOKEN_CLIENT_FLAG", "QC_TOKEN_GLOBAL_VAR", "QC_TOKEN_SESSION_VAR", "QC_TOKEN_BRACKET_OPEN", "QC_TOKEN_BRACKET_CLOSE", "QC_TOKEN_PLUS", "QC_TOKEN_MINUS", "QC_TOKEN_STAR", "QC_TOKEN_COMMA", "QC_TOKEN_DOT", "QC_TOKEN_SEMICOLON", "QC_TOKEN_NO_MORE", "QC_TOKEN_IDENTIFIER", "QC_TOKEN_INTNUM", "QC_TOKEN_FLOATNUM", "QC_TOKEN_ASSIGN_TO_VAR", "QC_TOKEN_TILDE", "$accept", "statement", "$@1", "create", "drop", "temporary", "if_exists", "if_not_exists", "restrict", "alter", "rename", "table_or_tables_option", "replace", "replace_option", "truncate", "table_token", "delete", "delete_options", "delete_option", "update", "low_priority", "insert", "ignore", "select", "$@2", "$@3", "$@4", "comment", "query_field_list", "select_field_list", "select_field_list_tail", "select_field", "function_call", "opt_function_call_parameter_list", "function_call_parameter_list", "function_call_parameter", "field", "identifier", "ident_alias", "query_table", "table", "opt_from_clause", "query_table_list", "where_clause", "where_clause_tail", "field_value", "keyword", "keyword_label_in_sp", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint16 yyr1[] = { 0, 607, 608, 608, 608, 608, 608, 608, 608, 608, 608, 608, 609, 608, 610, 611, 612, 612, 613, 613, 614, 614, 615, 615, 615, 616, 617, 618, 618, 619, 620, 620, 621, 622, 622, 623, 624, 624, 625, 625, 625, 626, 627, 627, 628, 629, 629, 631, 632, 633, 630, 634, 634, 634, 635, 635, 636, 636, 637, 638, 638, 638, 638, 639, 640, 640, 641, 641, 642, 643, 643, 643, 644, 644, 645, 645, 645, 646, 647, 647, 647, 648, 648, 649, 649, 650, 651, 652, 652, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 5, 7, 1, 0, 2, 0, 3, 0, 1, 1, 0, 5, 4, 1, 1, 4, 1, 1, 4, 1, 0, 5, 2, 0, 1, 1, 1, 6, 1, 0, 5, 1, 0, 0, 0, 0, 8, 1, 2, 0, 2, 1, 3, 1, 3, 1, 1, 1, 1, 4, 0, 1, 3, 1, 0, 1, 3, 5, 1, 1, 2, 1, 0, 2, 1, 1, 3, 2, 0, 1, 3, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint16 yydefact[] = { 53, 51, 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 12, 1, 46, 52, 0, 37, 17, 0, 0, 43, 47, 34, 43, 0, 45, 0, 21, 40, 39, 38, 0, 37, 16, 0, 46, 28, 27, 0, 31, 42, 0, 30, 53, 33, 0, 46, 13, 0, 0, 0, 0, 36, 19, 0, 138, 139, 140, 141, 142, 143, 144, 90, 145, 146, 148, 147, 149, 150, 91, 92, 151, 152, 153, 155, 154, 156, 93, 94, 157, 158, 159, 95, 96, 160, 161, 97, 162, 163, 164, 165, 166, 98, 167, 168, 169, 170, 171, 172, 99, 173, 174, 175, 176, 178, 177, 179, 180, 181, 100, 182, 183, 184, 185, 186, 187, 188, 101, 78, 189, 190, 191, 207, 102, 192, 195, 194, 193, 196, 197, 199, 198, 200, 103, 201, 202, 203, 205, 204, 209, 210, 211, 104, 206, 212, 208, 379, 214, 213, 215, 217, 216, 105, 218, 106, 107, 219, 220, 221, 223, 224, 225, 230, 108, 222, 226, 227, 228, 229, 231, 109, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 251, 244, 246, 247, 249, 245, 250, 254, 253, 255, 256, 257, 252, 243, 248, 258, 259, 242, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 272, 271, 273, 274, 275, 276, 277, 279, 278, 280, 281, 282, 284, 283, 286, 287, 110, 285, 288, 289, 290, 291, 292, 111, 112, 113, 293, 294, 114, 295, 296, 297, 115, 298, 299, 301, 300, 302, 303, 116, 117, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 318, 317, 319, 320, 321, 322, 323, 118, 324, 119, 325, 326, 120, 327, 121, 328, 329, 122, 330, 331, 332, 333, 334, 335, 123, 336, 337, 124, 339, 338, 340, 125, 342, 343, 126, 341, 128, 344, 127, 129, 345, 346, 348, 347, 349, 350, 351, 130, 352, 131, 353, 354, 355, 356, 358, 357, 359, 360, 361, 362, 363, 365, 364, 366, 367, 368, 369, 372, 373, 374, 375, 370, 371, 132, 376, 377, 378, 380, 381, 383, 382, 133, 134, 384, 385, 137, 386, 387, 390, 388, 389, 392, 391, 393, 394, 135, 395, 136, 396, 72, 79, 26, 73, 89, 29, 0, 48, 55, 57, 32, 0, 25, 0, 14, 35, 0, 0, 44, 0, 62, 54, 61, 76, 60, 59, 69, 82, 53, 0, 20, 18, 24, 80, 0, 75, 58, 64, 0, 0, 49, 0, 56, 41, 23, 22, 15, 74, 0, 65, 67, 70, 83, 76, 81, 0, 63, 68, 0, 77, 0, 0, 50, 66, 71, 84, 0, 85, 0, 88, 87, 86 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 2, 26, 3, 4, 36, 382, 52, 411, 5, 6, 40, 7, 43, 8, 47, 9, 33, 34, 10, 44, 11, 28, 12, 45, 392, 420, 13, 372, 373, 374, 388, 389, 413, 414, 415, 390, 366, 401, 417, 418, 405, 419, 427, 432, 436, 368, 369 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -586 static const yytype_int16 yypact[] = { -62, -586, 27, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, 2569, -586, -183, -586, -478, -187, -480, -193, -494, -112, -586, -474, -233, 39, -586, -467, -166, -586, -586, -586, -136, -187, -586, -494, -183, -586, -586, 1183, -586, -586, 1183, -586, -62, -586, 1183, -183, -586, 1183, -288, 1183, 1183, -586, -162, 1183, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -549, -586, -586, -586, -586, -4, -586, -586, -546, -586, 1183, -586, -106, -586, -586, -104, 1183, -586, 2349, -585, -586, -586, 1766, -586, -534, -535, -115, -62, -385, -586, -586, -40, -586, 2349, -586, -586, -522, 2349, 1183, -586, 596, -586, -586, -586, -586, -586, -586, -515, -518, -586, -514, -586, 1766, -517, -488, -586, -586, 2349, -586, 1183, 2349, -586, -586, -586, -586, -64, -586, -486, -586, -586, -586 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, -586, 54, -586, -586, -586, -586, -586, 57, -586, -586, 68, -586, -20, -586, -586, -586, -586, -44, -586, -299, -586, -586, -586, -586, -586, -327, -330, 155, -321, -326, 210, -586, -586, -586, -586, -586, -586, -586 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -355 static const yytype_int16 yytable[] = { 57, 371, 58, 59, 60, 61, 62, 434, -354, 41, 409, 1, 38, 63, -354, 39, 64, 56, 65, 66, 67, 68, 69, 70, 71, 30, 72, 14, 376, 27, 73, 29, 35, 37, 74, 46, 42, 75, 76, 77, 49, 78, 50, 79, 80, 51, 53, 81, 378, 381, 384, 82, 393, 83, 84, 395, 85, 396, 86, 402, 87, 88, 89, 90, 403, 91, 92, 404, 408, 16, 93, 94, 95, 96, 97, 98, -68, 99, 100, 421, 422, 425, 31, 101, 102, 423, 103, 426, 433, 104, 55, 54, 105, 48, 407, 428, 431, 424, 0, 430, 106, 107, 108, 0, 0, 109, 0, 0, 0, 0, 110, 111, 0, 0, 0, 0, 112, 435, 113, 0, 0, 0, 114, 0, 115, 116, 117, 118, 0, 0, 0, 119, 0, 0, 121, 122, 123, 0, 0, 0, 124, 0, 125, 126, 0, 127, 128, 129, 0, 0, 130, 0, 131, 132, 133, 134, 135, 42, 0, 136, 137, 138, 0, 0, 139, 140, 0, 141, 142, 143, 0, 0, 144, 0, 0, 0, 145, 146, 0, 147, 0, 148, 0, 149, 150, 151, 152, 0, 153, 0, 0, 0, 154, 155, 0, 156, 0, 0, 157, 158, 0, 0, 0, 159, 0, 160, 32, 0, 0, 0, 161, 162, 0, 0, 163, 0, 0, 0, 0, 164, 165, 0, 0, 0, 166, 0, 167, 168, 0, 169, 170, 0, 0, 0, 171, 0, 0, 172, 173, 0, 0, 174, 0, 0, 175, 176, 0, 0, 0, 0, 367, 177, 178, 370, 179, 0, 180, 375, 181, 182, 377, 0, 379, 380, 0, 0, 383, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 0, 196, 197, 0, 0, 198, 199, 200, 201, 0, 202, 203, 204, 0, 0, 0, 205, 206, 207, 0, 208, 209, 0, 0, 210, 211, 0, 212, 0, 213, 0, 214, 215, 216, 217, 218, 0, 219, 220, 221, 0, 0, 222, 223, 0, 0, 0, 224, 225, 226, 227, 0, 0, 0, 228, 229, 0, 0, 0, 0, 230, 231, 232, 0, 233, 234, 235, 0, 236, 406, 0, 0, 0, 0, 0, 0, 0, 0, 237, 238, 239, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 0, 0, 252, 253, 254, 0, 255, 0, 256, 257, 258, 259, 410, 260, 261, 262, 0, 0, 263, 0, 0, 0, 264, 265, 266, 267, 268, 0, 0, 0, 269, 270, 271, 0, 272, 273, 0, 274, 275, 276, 0, 0, 277, 0, 278, 0, 279, 280, 0, 281, 282, 0, 0, 0, 283, 284, 285, 286, 287, 288, 289, 290, 291, 0, 0, 292, 293, 0, 0, 0, 294, 295, 296, 297, 0, 0, 0, 298, 0, 0, 0, 299, 0, 300, 301, 302, 0, 303, 304, 305, 306, 307, 0, 0, 0, 0, 0, 0, 308, 309, 0, 310, 0, 0, 311, 0, 0, 312, 313, 314, 0, 0, 315, 316, 0, 385, 0, 318, 319, 320, 321, 0, 0, 322, 323, 324, 325, 0, 326, 327, 0, 0, 328, 0, 329, 330, 0, 0, 331, 332, 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, 337, 338, 391, 0, 0, 339, 340, 341, 342, 0, 343, 344, 0, 345, 346, 398, 347, 348, 0, 400, 349, 0, 0, 350, 0, 351, 0, 352, 353, 0, 412, 0, 0, 0, 416, 354, 0, 391, 355, 0, 0, 0, 356, 357, 358, 359, 0, 0, 0, 400, 0, 0, 360, 361, 429, 362, 363, 391, 0, 0, 364, 0, 394, 0, 0, 0, 0, 0, 397, 386, 0, 0, 0, 0, 365, 387, 57, 0, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 63, 0, 0, 64, 0, 65, 66, 67, 68, 69, 70, 71, 0, 72, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 75, 76, 77, 0, 78, 0, 79, 80, 0, 0, 81, 0, 0, 0, 82, 0, 83, 84, 0, 85, 0, 86, 0, 87, 88, 89, 90, 0, 91, 92, 0, 0, 16, 93, 94, 95, 96, 97, 98, 0, 99, 100, 0, 0, 0, 0, 101, 102, 0, 103, 0, 0, 104, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 106, 107, 108, 0, 0, 109, 0, 0, 0, 0, 110, 111, 0, 0, 0, 0, 112, 0, 113, 0, 0, 0, 114, 0, 115, 116, 117, 118, 0, 0, 0, 119, 0, 0, 121, 122, 123, 0, 0, 0, 124, 0, 125, 126, 0, 127, 128, 129, 0, 0, 130, 0, 131, 132, 133, 134, 135, 0, 0, 136, 137, 138, 0, 0, 139, 140, 0, 141, 142, 143, 0, 0, 144, 0, 0, 0, 145, 146, 0, 147, 0, 148, 0, 149, 150, 151, 152, 0, 153, 0, 0, 0, 154, 155, 0, 156, 0, 0, 157, 158, 0, 0, 0, 159, 0, 160, 0, 0, 0, 0, 161, 162, 0, 0, 163, 0, 0, 0, 0, 164, 165, 0, 0, 0, 166, 0, 167, 168, 0, 169, 170, 0, 0, 0, 171, 0, 0, 172, 173, 0, 0, 174, 0, 0, 175, 176, 0, 0, 0, 0, 0, 177, 178, 0, 179, 0, 180, 0, 181, 182, 0, 0, 0, 0, 0, 0, 0, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 0, 196, 197, 0, 0, 198, 199, 200, 201, 0, 202, 203, 204, 0, 0, 0, 205, 206, 207, 0, 208, 209, 0, 0, 210, 211, 0, 212, 0, 213, 0, 214, 215, 216, 217, 218, 0, 219, 220, 221, 0, 0, 222, 223, 0, 0, 0, 224, 225, 226, 227, 0, 0, 0, 228, 229, 0, 0, 0, 0, 230, 231, 232, 0, 233, 234, 235, 0, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 238, 239, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 0, 0, 252, 253, 254, 0, 255, 0, 256, 257, 258, 259, 0, 260, 261, 262, 0, 0, 263, 0, 0, 0, 264, 265, 266, 267, 268, 0, 0, 0, 269, 270, 271, 0, 272, 273, 0, 274, 275, 276, 0, 0, 277, 0, 278, 0, 279, 280, 0, 281, 282, 0, 0, 0, 283, 284, 285, 286, 287, 288, 289, 290, 291, 0, 0, 292, 293, 0, 0, 0, 294, 295, 296, 297, 0, 0, 0, 298, 0, 0, 0, 299, 0, 300, 301, 302, 0, 303, 304, 305, 306, 307, 0, 0, 0, 0, 0, 0, 308, 309, 0, 310, 0, 0, 311, 0, 0, 312, 313, 314, 0, 0, 315, 316, 0, 385, 0, 318, 319, 320, 321, 0, 0, 322, 323, 324, 325, 0, 326, 327, 0, 0, 328, 0, 329, 330, 0, 0, 331, 332, 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, 337, 338, 0, 0, 0, 339, 340, 341, 342, 0, 343, 344, 0, 345, 346, 0, 347, 348, 0, 0, 349, 0, 0, 350, 0, 351, 0, 352, 353, 0, 0, 0, 0, 0, 0, 354, 0, 0, 355, 0, 0, 0, 356, 357, 358, 359, 0, 0, 0, 0, 0, 0, 360, 361, 0, 362, 363, 0, 0, 0, 364, 0, 0, 57, 0, 58, 59, 60, 61, 62, 0, 0, 0, 0, 365, 387, 63, 0, 0, 64, 0, 65, 66, 67, 68, 69, 70, 71, 0, 72, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 75, 76, 77, 0, 78, 0, 79, 80, 0, 0, 81, 0, 0, 0, 82, 0, 83, 84, 0, 85, 0, 86, 0, 87, 88, 89, 90, 0, 91, 92, 0, 0, 0, 93, 94, 95, 96, 97, 98, 0, 99, 100, 0, 0, 0, 0, 101, 102, 0, 103, 0, 0, 104, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 106, 107, 108, 0, 0, 109, 0, 0, 0, 0, 110, 111, 0, 0, 0, 0, 112, 0, 113, 0, 0, 0, 114, 0, 115, 116, 117, 118, 0, 0, 0, 119, 0, 120, 121, 122, 123, 0, 0, 0, 124, 0, 125, 126, 0, 127, 128, 129, 0, 0, 130, 0, 131, 132, 133, 134, 135, 0, 0, 136, 137, 138, 0, 0, 139, 140, 0, 141, 142, 143, 0, 0, 144, 0, 0, 0, 145, 146, 0, 147, 0, 148, 0, 149, 150, 151, 152, 0, 153, 0, 0, 0, 154, 155, 0, 156, 0, 0, 157, 158, 0, 0, 0, 159, 0, 160, 0, 0, 0, 0, 161, 162, 0, 0, 163, 0, 0, 0, 0, 164, 165, 0, 0, 0, 166, 0, 167, 168, 0, 169, 170, 0, 0, 0, 171, 0, 0, 172, 173, 0, 0, 174, 0, 0, 175, 176, 0, 0, 0, 0, 0, 177, 178, 0, 179, 0, 180, 0, 181, 182, 0, 0, 0, 0, 0, 0, 0, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 0, 196, 197, 0, 0, 198, 199, 200, 201, 0, 202, 203, 204, 0, 0, 0, 205, 206, 207, 0, 208, 209, 0, 0, 210, 211, 0, 212, 0, 213, 0, 214, 215, 216, 217, 218, 0, 219, 220, 221, 0, 0, 222, 223, 0, 0, 0, 224, 225, 226, 227, 0, 0, 0, 228, 229, 0, 0, 0, 0, 230, 231, 232, 0, 233, 234, 235, 0, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 238, 239, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 0, 0, 252, 253, 254, 0, 255, 0, 256, 257, 258, 259, 0, 260, 261, 262, 0, 0, 263, 0, 0, 0, 264, 265, 266, 267, 268, 0, 0, 0, 269, 270, 271, 0, 272, 273, 0, 274, 275, 276, 0, 0, 277, 0, 278, 0, 279, 280, 0, 281, 282, 0, 0, 0, 283, 284, 285, 286, 287, 288, 289, 290, 291, 0, 0, 292, 293, 0, 0, 0, 294, 295, 296, 297, 0, 0, 0, 298, 0, 0, 0, 299, 0, 300, 301, 302, 0, 303, 304, 305, 306, 307, 0, 0, 0, 0, 0, 0, 308, 309, 0, 310, 0, 0, 311, 0, 0, 312, 313, 314, 0, 0, 315, 316, 0, 317, 0, 318, 319, 320, 321, 0, 0, 322, 323, 324, 325, 0, 326, 327, 0, 0, 328, 0, 329, 330, 0, 0, 331, 332, 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, 337, 338, 0, 0, 0, 339, 340, 341, 342, 0, 343, 344, 0, 345, 346, 0, 347, 348, 0, 0, 349, 0, 0, 350, 0, 351, 0, 352, 353, 0, 0, 0, 0, 0, 0, 354, 0, 0, 355, 0, 0, 0, 356, 357, 358, 359, 0, 0, 0, 0, 0, 0, 360, 361, 0, 362, 363, 0, 0, 57, 364, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 63, 399, 365, 64, 0, 65, 66, 67, 68, 69, 70, 71, 0, 72, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 75, 76, 77, 0, 78, 0, 79, 80, 0, 0, 81, 0, 0, 0, 82, 0, 83, 84, 0, 85, 0, 86, 0, 87, 88, 89, 90, 0, 91, 92, 0, 0, 0, 93, 94, 95, 96, 97, 98, 0, 99, 100, 0, 0, 0, 0, 101, 102, 0, 103, 0, 0, 104, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 106, 107, 108, 0, 0, 109, 0, 0, 0, 0, 110, 111, 0, 0, 0, 0, 112, 0, 113, 0, 0, 0, 114, 0, 115, 116, 117, 118, 0, 0, 0, 119, 0, 0, 121, 122, 123, 0, 0, 0, 124, 0, 125, 126, 0, 127, 128, 129, 0, 0, 130, 0, 131, 132, 133, 134, 135, 0, 0, 136, 137, 138, 0, 0, 139, 140, 0, 141, 142, 143, 0, 0, 144, 0, 0, 0, 145, 146, 0, 147, 0, 148, 0, 149, 150, 151, 152, 0, 153, 0, 0, 0, 154, 155, 0, 156, 0, 0, 157, 158, 0, 0, 0, 159, 0, 160, 0, 0, 0, 0, 161, 162, 0, 0, 163, 0, 0, 0, 0, 164, 165, 0, 0, 0, 166, 0, 167, 168, 0, 169, 170, 0, 0, 0, 171, 0, 0, 172, 173, 0, 0, 174, 0, 0, 175, 176, 0, 0, 0, 0, 0, 177, 178, 0, 179, 0, 180, 0, 181, 182, 0, 0, 0, 0, 0, 0, 0, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 0, 196, 197, 0, 0, 198, 199, 200, 201, 0, 202, 203, 204, 0, 0, 0, 205, 206, 207, 0, 208, 209, 0, 0, 210, 211, 0, 212, 0, 213, 0, 214, 215, 216, 217, 218, 0, 219, 220, 221, 0, 0, 222, 223, 0, 0, 0, 224, 225, 226, 227, 0, 0, 0, 228, 229, 0, 0, 0, 0, 230, 231, 232, 0, 233, 234, 235, 0, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 238, 239, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 0, 0, 252, 253, 254, 0, 255, 0, 256, 257, 258, 259, 0, 260, 261, 262, 0, 0, 263, 0, 0, 0, 264, 265, 266, 267, 268, 0, 0, 0, 269, 270, 271, 0, 272, 273, 0, 274, 275, 276, 0, 0, 277, 0, 278, 0, 279, 280, 0, 281, 282, 0, 0, 0, 283, 284, 285, 286, 287, 288, 289, 290, 291, 0, 0, 292, 293, 0, 0, 0, 294, 295, 296, 297, 0, 0, 0, 298, 0, 0, 0, 299, 0, 300, 301, 302, 0, 303, 304, 305, 306, 307, 0, 0, 0, 0, 0, 0, 308, 309, 0, 310, 0, 0, 311, 0, 0, 312, 313, 314, 0, 0, 315, 316, 0, 317, 0, 318, 319, 320, 321, 0, 0, 322, 323, 324, 325, 0, 326, 327, 0, 0, 328, 0, 329, 330, 0, 0, 331, 332, 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, 337, 338, 0, 0, 0, 339, 340, 341, 342, 0, 343, 344, 0, 345, 346, 0, 347, 348, 0, 0, 349, 0, 0, 350, 0, 351, 0, 352, 353, 0, 0, 0, 0, 0, 0, 354, 0, 0, 355, 0, 0, 0, 356, 357, 358, 359, 0, 0, 0, 0, 0, 0, 360, 361, 0, 362, 363, 0, 0, 57, 364, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 63, 0, 365, 64, 0, 65, 66, 67, 68, 69, 70, 71, 0, 72, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 75, 76, 77, 0, 78, 0, 79, 80, 0, 0, 81, 0, 0, 0, 82, 0, 83, 84, 0, 85, 0, 86, 0, 87, 88, 89, 90, 0, 91, 92, 0, 0, 0, 93, 94, 95, 96, 97, 98, 0, 99, 100, 0, 0, 0, 0, 101, 102, 0, 103, 0, 0, 104, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 106, 107, 108, 0, 0, 109, 0, 0, 0, 0, 110, 111, 0, 0, 0, 0, 112, 0, 113, 0, 0, 0, 114, 0, 115, 116, 117, 118, 0, 0, 0, 119, 0, 0, 121, 122, 123, 0, 0, 0, 124, 0, 125, 126, 0, 127, 128, 129, 0, 0, 130, 0, 131, 132, 133, 134, 135, 0, 0, 136, 137, 138, 0, 0, 139, 140, 0, 141, 142, 143, 0, 0, 144, 0, 0, 0, 145, 146, 0, 147, 0, 148, 0, 149, 150, 151, 152, 0, 153, 0, 0, 0, 154, 155, 0, 156, 0, 0, 157, 158, 0, 0, 0, 159, 0, 160, 0, 0, 0, 0, 161, 162, 0, 0, 163, 0, 0, 0, 0, 164, 165, 0, 0, 0, 166, 0, 167, 168, 15, 169, 170, 0, 0, 0, 171, 0, 0, 172, 173, 0, 0, 174, 0, 0, 175, 176, 0, 0, 0, 0, 0, 177, 178, 0, 179, 0, 180, 0, 181, 182, 0, 0, 0, 0, 0, 0, 0, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 0, 196, 197, 0, 0, 198, 199, 200, 201, 16, 202, 203, 204, 0, 0, 0, 205, 206, 207, 0, 208, 209, 0, 0, 210, 211, 0, 212, 0, 213, 17, 214, 215, 216, 217, 218, 0, 219, 220, 221, 0, 0, 222, 223, 0, 0, 0, 224, 225, 226, 227, 0, 0, 0, 228, 229, 0, 0, 0, 18, 230, 231, 232, 0, 233, 234, 235, 0, 236, 0, 0, 0, 19, 0, 0, 0, 0, 0, 237, 238, 239, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 0, 0, 252, 253, 254, 0, 255, 0, 256, 257, 258, 259, 0, 260, 261, 262, 0, 0, 263, 0, 0, 0, 264, 265, 266, 267, 268, 0, 0, 0, 269, 270, 271, 0, 272, 273, 0, 274, 275, 276, 0, 0, 277, 0, 278, 0, 279, 280, 0, 281, 282, 0, 0, 0, 283, 284, 285, 286, 287, 288, 289, 290, 291, 0, 20, 292, 293, 0, 0, 0, 294, 295, 296, 297, 0, 0, 0, 298, 0, 0, 0, 299, 0, 300, 301, 302, 0, 303, 304, 305, 306, 307, 0, 0, 0, 0, 0, 0, 308, 309, 0, 310, 0, 0, 311, 0, 0, 312, 313, 314, 0, 0, 315, 316, 0, 317, 0, 318, 319, 320, 321, 0, 0, 322, 323, 324, 325, 0, 326, 327, 0, 0, 328, 0, 329, 330, 0, 0, 331, 332, 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, 337, 338, 0, 0, 0, 339, 340, 341, 342, 0, 343, 344, 0, 345, 346, 0, 347, 348, 0, 0, 349, 0, 0, 350, 0, 351, 0, 352, 353, 0, 0, 0, 0, 0, 0, 354, 0, 0, 355, 0, 0, 0, 356, 357, 358, 359, 0, 0, 0, 0, 0, 0, 360, 361, 0, 362, 363, 0, 0, 0, 364, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 }; static const yytype_int16 yycheck[] = { 4, 45, 6, 7, 8, 9, 10, 493, 593, 121, 50, 73, 506, 17, 599, 509, 20, 37, 22, 23, 24, 25, 26, 27, 28, 212, 30, 0, 48, 212, 34, 509, 512, 226, 38, 509, 269, 41, 42, 43, 1, 45, 509, 47, 48, 211, 182, 51, 336, 211, 599, 55, 598, 57, 58, 161, 60, 161, 62, 593, 64, 65, 66, 67, 599, 69, 70, 182, 453, 73, 74, 75, 76, 77, 78, 79, 598, 81, 82, 594, 598, 598, 269, 87, 88, 599, 90, 575, 152, 93, 36, 34, 96, 25, 393, 422, 426, 418, -1, 425, 104, 105, 106, -1, -1, 109, -1, -1, -1, -1, 114, 115, -1, -1, -1, -1, 120, 603, 122, -1, -1, -1, 126, -1, 128, 129, 130, 131, -1, -1, -1, 135, -1, -1, 138, 139, 140, -1, -1, -1, 144, -1, 146, 147, -1, 149, 150, 151, -1, -1, 154, -1, 156, 157, 158, 159, 160, 269, -1, 163, 164, 165, -1, -1, 168, 169, -1, 171, 172, 173, -1, -1, 176, -1, -1, -1, 180, 181, -1, 183, -1, 185, -1, 187, 188, 189, 190, -1, 192, -1, -1, -1, 196, 197, -1, 199, -1, -1, 202, 203, -1, -1, -1, 207, -1, 209, 393, -1, -1, -1, 214, 215, -1, -1, 218, -1, -1, -1, -1, 223, 224, -1, -1, -1, 228, -1, 230, 231, -1, 233, 234, -1, -1, -1, 238, -1, -1, 241, 242, -1, -1, 245, -1, -1, 248, 249, -1, -1, -1, -1, 40, 255, 256, 43, 258, -1, 260, 47, 262, 263, 50, -1, 52, 53, -1, -1, 56, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, 292, -1, 294, 295, 296, -1, -1, -1, 300, 301, 302, -1, 304, 305, -1, -1, 308, 309, -1, 311, -1, 313, -1, 315, 316, 317, 318, 319, -1, 321, 322, 323, -1, -1, 326, 327, -1, -1, -1, 331, 332, 333, 334, -1, -1, -1, 338, 339, -1, -1, -1, -1, 344, 345, 346, -1, 348, 349, 350, -1, 352, 393, -1, -1, -1, -1, -1, -1, -1, -1, 362, 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, -1, -1, 380, 381, 382, -1, 384, -1, 386, 387, 388, 389, 426, 391, 392, 393, -1, -1, 396, -1, -1, -1, 400, 401, 402, 403, 404, -1, -1, -1, 408, 409, 410, -1, 412, 413, -1, 415, 416, 417, -1, -1, 420, -1, 422, -1, 424, 425, -1, 427, 428, -1, -1, -1, 432, 433, 434, 435, 436, 437, 438, 439, 440, -1, -1, 443, 444, -1, -1, -1, 448, 449, 450, 451, -1, -1, -1, 455, -1, -1, -1, 459, -1, 461, 462, 463, -1, 465, 466, 467, 468, 469, -1, -1, -1, -1, -1, -1, 476, 477, -1, 479, -1, -1, 482, -1, -1, 485, 486, 487, -1, -1, 490, 491, -1, 493, -1, 495, 496, 497, 498, -1, -1, 501, 502, 503, 504, -1, 506, 507, -1, -1, 510, -1, 512, 513, -1, -1, 516, 517, -1, 519, 520, 521, 522, -1, -1, -1, -1, -1, 528, 529, 371, -1, -1, 533, 534, 535, 536, -1, 538, 539, -1, 541, 542, 384, 544, 545, -1, 388, 548, -1, -1, 551, -1, 553, -1, 555, 556, -1, 399, -1, -1, -1, 403, 563, -1, 406, 566, -1, -1, -1, 570, 571, 572, 573, -1, -1, -1, 418, -1, -1, 580, 581, 423, 583, 584, 426, -1, -1, 588, -1, 376, -1, -1, -1, -1, -1, 382, 597, -1, -1, -1, -1, 602, 603, 4, -1, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, 17, -1, -1, 20, -1, 22, 23, 24, 25, 26, 27, 28, -1, 30, -1, -1, -1, 34, -1, -1, -1, 38, -1, -1, 41, 42, 43, -1, 45, -1, 47, 48, -1, -1, 51, -1, -1, -1, 55, -1, 57, 58, -1, 60, -1, 62, -1, 64, 65, 66, 67, -1, 69, 70, -1, -1, 73, 74, 75, 76, 77, 78, 79, -1, 81, 82, -1, -1, -1, -1, 87, 88, -1, 90, -1, -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, 104, 105, 106, -1, -1, 109, -1, -1, -1, -1, 114, 115, -1, -1, -1, -1, 120, -1, 122, -1, -1, -1, 126, -1, 128, 129, 130, 131, -1, -1, -1, 135, -1, -1, 138, 139, 140, -1, -1, -1, 144, -1, 146, 147, -1, 149, 150, 151, -1, -1, 154, -1, 156, 157, 158, 159, 160, -1, -1, 163, 164, 165, -1, -1, 168, 169, -1, 171, 172, 173, -1, -1, 176, -1, -1, -1, 180, 181, -1, 183, -1, 185, -1, 187, 188, 189, 190, -1, 192, -1, -1, -1, 196, 197, -1, 199, -1, -1, 202, 203, -1, -1, -1, 207, -1, 209, -1, -1, -1, -1, 214, 215, -1, -1, 218, -1, -1, -1, -1, 223, 224, -1, -1, -1, 228, -1, 230, 231, -1, 233, 234, -1, -1, -1, 238, -1, -1, 241, 242, -1, -1, 245, -1, -1, 248, 249, -1, -1, -1, -1, -1, 255, 256, -1, 258, -1, 260, -1, 262, 263, -1, -1, -1, -1, -1, -1, -1, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, 292, -1, 294, 295, 296, -1, -1, -1, 300, 301, 302, -1, 304, 305, -1, -1, 308, 309, -1, 311, -1, 313, -1, 315, 316, 317, 318, 319, -1, 321, 322, 323, -1, -1, 326, 327, -1, -1, -1, 331, 332, 333, 334, -1, -1, -1, 338, 339, -1, -1, -1, -1, 344, 345, 346, -1, 348, 349, 350, -1, 352, -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, -1, -1, 380, 381, 382, -1, 384, -1, 386, 387, 388, 389, -1, 391, 392, 393, -1, -1, 396, -1, -1, -1, 400, 401, 402, 403, 404, -1, -1, -1, 408, 409, 410, -1, 412, 413, -1, 415, 416, 417, -1, -1, 420, -1, 422, -1, 424, 425, -1, 427, 428, -1, -1, -1, 432, 433, 434, 435, 436, 437, 438, 439, 440, -1, -1, 443, 444, -1, -1, -1, 448, 449, 450, 451, -1, -1, -1, 455, -1, -1, -1, 459, -1, 461, 462, 463, -1, 465, 466, 467, 468, 469, -1, -1, -1, -1, -1, -1, 476, 477, -1, 479, -1, -1, 482, -1, -1, 485, 486, 487, -1, -1, 490, 491, -1, 493, -1, 495, 496, 497, 498, -1, -1, 501, 502, 503, 504, -1, 506, 507, -1, -1, 510, -1, 512, 513, -1, -1, 516, 517, -1, 519, 520, 521, 522, -1, -1, -1, -1, -1, 528, 529, -1, -1, -1, 533, 534, 535, 536, -1, 538, 539, -1, 541, 542, -1, 544, 545, -1, -1, 548, -1, -1, 551, -1, 553, -1, 555, 556, -1, -1, -1, -1, -1, -1, 563, -1, -1, 566, -1, -1, -1, 570, 571, 572, 573, -1, -1, -1, -1, -1, -1, 580, 581, -1, 583, 584, -1, -1, -1, 588, -1, -1, 4, -1, 6, 7, 8, 9, 10, -1, -1, -1, -1, 602, 603, 17, -1, -1, 20, -1, 22, 23, 24, 25, 26, 27, 28, -1, 30, -1, -1, -1, 34, -1, -1, -1, 38, -1, -1, 41, 42, 43, -1, 45, -1, 47, 48, -1, -1, 51, -1, -1, -1, 55, -1, 57, 58, -1, 60, -1, 62, -1, 64, 65, 66, 67, -1, 69, 70, -1, -1, -1, 74, 75, 76, 77, 78, 79, -1, 81, 82, -1, -1, -1, -1, 87, 88, -1, 90, -1, -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, 104, 105, 106, -1, -1, 109, -1, -1, -1, -1, 114, 115, -1, -1, -1, -1, 120, -1, 122, -1, -1, -1, 126, -1, 128, 129, 130, 131, -1, -1, -1, 135, -1, 137, 138, 139, 140, -1, -1, -1, 144, -1, 146, 147, -1, 149, 150, 151, -1, -1, 154, -1, 156, 157, 158, 159, 160, -1, -1, 163, 164, 165, -1, -1, 168, 169, -1, 171, 172, 173, -1, -1, 176, -1, -1, -1, 180, 181, -1, 183, -1, 185, -1, 187, 188, 189, 190, -1, 192, -1, -1, -1, 196, 197, -1, 199, -1, -1, 202, 203, -1, -1, -1, 207, -1, 209, -1, -1, -1, -1, 214, 215, -1, -1, 218, -1, -1, -1, -1, 223, 224, -1, -1, -1, 228, -1, 230, 231, -1, 233, 234, -1, -1, -1, 238, -1, -1, 241, 242, -1, -1, 245, -1, -1, 248, 249, -1, -1, -1, -1, -1, 255, 256, -1, 258, -1, 260, -1, 262, 263, -1, -1, -1, -1, -1, -1, -1, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, 292, -1, 294, 295, 296, -1, -1, -1, 300, 301, 302, -1, 304, 305, -1, -1, 308, 309, -1, 311, -1, 313, -1, 315, 316, 317, 318, 319, -1, 321, 322, 323, -1, -1, 326, 327, -1, -1, -1, 331, 332, 333, 334, -1, -1, -1, 338, 339, -1, -1, -1, -1, 344, 345, 346, -1, 348, 349, 350, -1, 352, -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, -1, -1, 380, 381, 382, -1, 384, -1, 386, 387, 388, 389, -1, 391, 392, 393, -1, -1, 396, -1, -1, -1, 400, 401, 402, 403, 404, -1, -1, -1, 408, 409, 410, -1, 412, 413, -1, 415, 416, 417, -1, -1, 420, -1, 422, -1, 424, 425, -1, 427, 428, -1, -1, -1, 432, 433, 434, 435, 436, 437, 438, 439, 440, -1, -1, 443, 444, -1, -1, -1, 448, 449, 450, 451, -1, -1, -1, 455, -1, -1, -1, 459, -1, 461, 462, 463, -1, 465, 466, 467, 468, 469, -1, -1, -1, -1, -1, -1, 476, 477, -1, 479, -1, -1, 482, -1, -1, 485, 486, 487, -1, -1, 490, 491, -1, 493, -1, 495, 496, 497, 498, -1, -1, 501, 502, 503, 504, -1, 506, 507, -1, -1, 510, -1, 512, 513, -1, -1, 516, 517, -1, 519, 520, 521, 522, -1, -1, -1, -1, -1, 528, 529, -1, -1, -1, 533, 534, 535, 536, -1, 538, 539, -1, 541, 542, -1, 544, 545, -1, -1, 548, -1, -1, 551, -1, 553, -1, 555, 556, -1, -1, -1, -1, -1, -1, 563, -1, -1, 566, -1, -1, -1, 570, 571, 572, 573, -1, -1, -1, -1, -1, -1, 580, 581, -1, 583, 584, -1, -1, 4, 588, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, 17, 18, 602, 20, -1, 22, 23, 24, 25, 26, 27, 28, -1, 30, -1, -1, -1, 34, -1, -1, -1, 38, -1, -1, 41, 42, 43, -1, 45, -1, 47, 48, -1, -1, 51, -1, -1, -1, 55, -1, 57, 58, -1, 60, -1, 62, -1, 64, 65, 66, 67, -1, 69, 70, -1, -1, -1, 74, 75, 76, 77, 78, 79, -1, 81, 82, -1, -1, -1, -1, 87, 88, -1, 90, -1, -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, 104, 105, 106, -1, -1, 109, -1, -1, -1, -1, 114, 115, -1, -1, -1, -1, 120, -1, 122, -1, -1, -1, 126, -1, 128, 129, 130, 131, -1, -1, -1, 135, -1, -1, 138, 139, 140, -1, -1, -1, 144, -1, 146, 147, -1, 149, 150, 151, -1, -1, 154, -1, 156, 157, 158, 159, 160, -1, -1, 163, 164, 165, -1, -1, 168, 169, -1, 171, 172, 173, -1, -1, 176, -1, -1, -1, 180, 181, -1, 183, -1, 185, -1, 187, 188, 189, 190, -1, 192, -1, -1, -1, 196, 197, -1, 199, -1, -1, 202, 203, -1, -1, -1, 207, -1, 209, -1, -1, -1, -1, 214, 215, -1, -1, 218, -1, -1, -1, -1, 223, 224, -1, -1, -1, 228, -1, 230, 231, -1, 233, 234, -1, -1, -1, 238, -1, -1, 241, 242, -1, -1, 245, -1, -1, 248, 249, -1, -1, -1, -1, -1, 255, 256, -1, 258, -1, 260, -1, 262, 263, -1, -1, -1, -1, -1, -1, -1, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, 292, -1, 294, 295, 296, -1, -1, -1, 300, 301, 302, -1, 304, 305, -1, -1, 308, 309, -1, 311, -1, 313, -1, 315, 316, 317, 318, 319, -1, 321, 322, 323, -1, -1, 326, 327, -1, -1, -1, 331, 332, 333, 334, -1, -1, -1, 338, 339, -1, -1, -1, -1, 344, 345, 346, -1, 348, 349, 350, -1, 352, -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, -1, -1, 380, 381, 382, -1, 384, -1, 386, 387, 388, 389, -1, 391, 392, 393, -1, -1, 396, -1, -1, -1, 400, 401, 402, 403, 404, -1, -1, -1, 408, 409, 410, -1, 412, 413, -1, 415, 416, 417, -1, -1, 420, -1, 422, -1, 424, 425, -1, 427, 428, -1, -1, -1, 432, 433, 434, 435, 436, 437, 438, 439, 440, -1, -1, 443, 444, -1, -1, -1, 448, 449, 450, 451, -1, -1, -1, 455, -1, -1, -1, 459, -1, 461, 462, 463, -1, 465, 466, 467, 468, 469, -1, -1, -1, -1, -1, -1, 476, 477, -1, 479, -1, -1, 482, -1, -1, 485, 486, 487, -1, -1, 490, 491, -1, 493, -1, 495, 496, 497, 498, -1, -1, 501, 502, 503, 504, -1, 506, 507, -1, -1, 510, -1, 512, 513, -1, -1, 516, 517, -1, 519, 520, 521, 522, -1, -1, -1, -1, -1, 528, 529, -1, -1, -1, 533, 534, 535, 536, -1, 538, 539, -1, 541, 542, -1, 544, 545, -1, -1, 548, -1, -1, 551, -1, 553, -1, 555, 556, -1, -1, -1, -1, -1, -1, 563, -1, -1, 566, -1, -1, -1, 570, 571, 572, 573, -1, -1, -1, -1, -1, -1, 580, 581, -1, 583, 584, -1, -1, 4, 588, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, 17, -1, 602, 20, -1, 22, 23, 24, 25, 26, 27, 28, -1, 30, -1, -1, -1, 34, -1, -1, -1, 38, -1, -1, 41, 42, 43, -1, 45, -1, 47, 48, -1, -1, 51, -1, -1, -1, 55, -1, 57, 58, -1, 60, -1, 62, -1, 64, 65, 66, 67, -1, 69, 70, -1, -1, -1, 74, 75, 76, 77, 78, 79, -1, 81, 82, -1, -1, -1, -1, 87, 88, -1, 90, -1, -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, 104, 105, 106, -1, -1, 109, -1, -1, -1, -1, 114, 115, -1, -1, -1, -1, 120, -1, 122, -1, -1, -1, 126, -1, 128, 129, 130, 131, -1, -1, -1, 135, -1, -1, 138, 139, 140, -1, -1, -1, 144, -1, 146, 147, -1, 149, 150, 151, -1, -1, 154, -1, 156, 157, 158, 159, 160, -1, -1, 163, 164, 165, -1, -1, 168, 169, -1, 171, 172, 173, -1, -1, 176, -1, -1, -1, 180, 181, -1, 183, -1, 185, -1, 187, 188, 189, 190, -1, 192, -1, -1, -1, 196, 197, -1, 199, -1, -1, 202, 203, -1, -1, -1, 207, -1, 209, -1, -1, -1, -1, 214, 215, -1, -1, 218, -1, -1, -1, -1, 223, 224, -1, -1, -1, 228, -1, 230, 231, 12, 233, 234, -1, -1, -1, 238, -1, -1, 241, 242, -1, -1, 245, -1, -1, 248, 249, -1, -1, -1, -1, -1, 255, 256, -1, 258, -1, 260, -1, 262, 263, -1, -1, -1, -1, -1, -1, -1, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, 292, 73, 294, 295, 296, -1, -1, -1, 300, 301, 302, -1, 304, 305, -1, -1, 308, 309, -1, 311, -1, 313, 94, 315, 316, 317, 318, 319, -1, 321, 322, 323, -1, -1, 326, 327, -1, -1, -1, 331, 332, 333, 334, -1, -1, -1, 338, 339, -1, -1, -1, 123, 344, 345, 346, -1, 348, 349, 350, -1, 352, -1, -1, -1, 136, -1, -1, -1, -1, -1, 362, 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, -1, -1, 380, 381, 382, -1, 384, -1, 386, 387, 388, 389, -1, 391, 392, 393, -1, -1, 396, -1, -1, -1, 400, 401, 402, 403, 404, -1, -1, -1, 408, 409, 410, -1, 412, 413, -1, 415, 416, 417, -1, -1, 420, -1, 422, -1, 424, 425, -1, 427, 428, -1, -1, -1, 432, 433, 434, 435, 436, 437, 438, 439, 440, -1, 222, 443, 444, -1, -1, -1, 448, 449, 450, 451, -1, -1, -1, 455, -1, -1, -1, 459, -1, 461, 462, 463, -1, 465, 466, 467, 468, 469, -1, -1, -1, -1, -1, -1, 476, 477, -1, 479, -1, -1, 482, -1, -1, 485, 486, 487, -1, -1, 490, 491, -1, 493, -1, 495, 496, 497, 498, -1, -1, 501, 502, 503, 504, -1, 506, 507, -1, -1, 510, -1, 512, 513, -1, -1, 516, 517, -1, 519, 520, 521, 522, -1, -1, -1, -1, -1, 528, 529, -1, -1, -1, 533, 534, 535, 536, -1, 538, 539, -1, 541, 542, -1, 544, 545, -1, -1, 548, -1, -1, 551, -1, 553, -1, 555, 556, -1, -1, -1, -1, -1, -1, 563, -1, -1, 566, -1, -1, -1, 570, 571, 572, 573, -1, -1, -1, -1, -1, -1, 580, 581, -1, 583, 584, -1, -1, -1, 588, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 602, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 414, -1, -1, -1, -1, 419, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 552 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint16 yystos[] = { 0, 73, 608, 610, 611, 616, 617, 619, 621, 623, 626, 628, 630, 634, 0, 12, 73, 94, 123, 136, 222, 414, 419, 445, 533, 552, 609, 212, 629, 509, 212, 269, 393, 624, 625, 512, 612, 226, 506, 509, 618, 121, 269, 620, 627, 631, 509, 622, 627, 1, 509, 211, 614, 182, 624, 618, 629, 4, 6, 7, 8, 9, 10, 17, 20, 22, 23, 24, 25, 26, 27, 28, 30, 34, 38, 41, 42, 43, 45, 47, 48, 51, 55, 57, 58, 60, 62, 64, 65, 66, 67, 69, 70, 74, 75, 76, 77, 78, 79, 81, 82, 87, 88, 90, 93, 96, 104, 105, 106, 109, 114, 115, 120, 122, 126, 128, 129, 130, 131, 135, 137, 138, 139, 140, 144, 146, 147, 149, 150, 151, 154, 156, 157, 158, 159, 160, 163, 164, 165, 168, 169, 171, 172, 173, 176, 180, 181, 183, 185, 187, 188, 189, 190, 192, 196, 197, 199, 202, 203, 207, 209, 214, 215, 218, 223, 224, 228, 230, 231, 233, 234, 238, 241, 242, 245, 248, 249, 255, 256, 258, 260, 262, 263, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 285, 286, 289, 290, 291, 292, 294, 295, 296, 300, 301, 302, 304, 305, 308, 309, 311, 313, 315, 316, 317, 318, 319, 321, 322, 323, 326, 327, 331, 332, 333, 334, 338, 339, 344, 345, 346, 348, 349, 350, 352, 362, 363, 364, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 380, 381, 382, 384, 386, 387, 388, 389, 391, 392, 393, 396, 400, 401, 402, 403, 404, 408, 409, 410, 412, 413, 415, 416, 417, 420, 422, 424, 425, 427, 428, 432, 433, 434, 435, 436, 437, 438, 439, 440, 443, 444, 448, 449, 450, 451, 455, 459, 461, 462, 463, 465, 466, 467, 468, 469, 476, 477, 479, 482, 485, 486, 487, 490, 491, 493, 495, 496, 497, 498, 501, 502, 503, 504, 506, 507, 510, 512, 513, 516, 517, 519, 520, 521, 522, 528, 529, 533, 534, 535, 536, 538, 539, 541, 542, 544, 545, 548, 551, 553, 555, 556, 563, 566, 570, 571, 572, 573, 580, 581, 583, 584, 588, 602, 644, 647, 653, 654, 647, 634, 635, 636, 637, 647, 629, 647, 336, 647, 647, 211, 613, 647, 599, 493, 597, 603, 638, 639, 643, 644, 632, 598, 647, 161, 161, 647, 644, 18, 644, 645, 593, 599, 182, 648, 634, 636, 453, 50, 426, 615, 644, 640, 641, 642, 644, 646, 647, 649, 633, 594, 598, 599, 645, 598, 575, 650, 642, 644, 646, 643, 651, 152, 493, 603, 652 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else # define YYLEX yylex (&yylval) #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 12: /* Line 1455 of yacc.c */ #line 675 "mysqlnd_query_parser.grammar" { zval_dtor(&(yyvsp[(1) - (1)].zv)); ;} break; case 13: /* Line 1455 of yacc.c */ #line 675 "mysqlnd_query_parser.grammar" { YYABORT; ;} break; case 14: /* Line 1455 of yacc.c */ #line 680 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_CREATE; zval_dtor(&(yyvsp[(1) - (5)].zv)); YYACCEPT; ;} break; case 15: /* Line 1455 of yacc.c */ #line 687 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_DROP; zval_dtor(&(yyvsp[(1) - (7)].zv)); ;} break; case 25: /* Line 1455 of yacc.c */ #line 713 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_ALTER; zval_dtor(&(yyvsp[(1) - (5)].zv)); YYACCEPT; ;} break; case 26: /* Line 1455 of yacc.c */ #line 722 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_RENAME; zval_dtor(&(yyvsp[(1) - (4)].zv)); YYACCEPT; ;} break; case 29: /* Line 1455 of yacc.c */ #line 735 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_REPLACE; zval_dtor(&(yyvsp[(1) - (4)].zv)); YYACCEPT; ;} break; case 32: /* Line 1455 of yacc.c */ #line 748 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_TRUNCATE; zval_dtor(&(yyvsp[(1) - (4)].zv)); ;} break; case 35: /* Line 1455 of yacc.c */ #line 760 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_DELETE; zval_dtor(&(yyvsp[(1) - (5)].zv)); YYACCEPT; ;} break; case 41: /* Line 1455 of yacc.c */ #line 778 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_UPDATE; zval_dtor(&(yyvsp[(1) - (6)].zv)); YYACCEPT; ;} break; case 44: /* Line 1455 of yacc.c */ #line 792 "mysqlnd_query_parser.grammar" { PINFO.statement = STATEMENT_INSERT; zval_dtor(&(yyvsp[(1) - (5)].zv)); YYACCEPT; ;} break; case 47: /* Line 1455 of yacc.c */ #line 804 "mysqlnd_query_parser.grammar" { zval_dtor(&(yyvsp[(1) - (2)].zv)); PINFO.statement = STATEMENT_SELECT; PINFO.active_field_list = &PINFO.select_field_list; ;} break; case 48: /* Line 1455 of yacc.c */ #line 810 "mysqlnd_query_parser.grammar" { PINFO.active_field_list = NULL; ;} break; case 49: /* Line 1455 of yacc.c */ #line 814 "mysqlnd_query_parser.grammar" { if (!PINFO.parse_where) { YYACCEPT; } PINFO.active_field_list = &PINFO.where_field_list; ;} break; case 50: /* Line 1455 of yacc.c */ #line 821 "mysqlnd_query_parser.grammar" { PINFO.active_field_list = NULL; YYACCEPT; ;} break; case 52: /* Line 1455 of yacc.c */ #line 828 "mysqlnd_query_parser.grammar" { zval_dtor(&(yyvsp[(2) - (2)].zv)); ;} break; case 53: /* Line 1455 of yacc.c */ #line 829 "mysqlnd_query_parser.grammar" { ZVAL_NULL(&(yyval.zv)); ;} break; case 54: /* Line 1455 of yacc.c */ #line 832 "mysqlnd_query_parser.grammar" { zval_dtor(&(yyvsp[(1) - (2)].zv)); ;} break; case 58: /* Line 1455 of yacc.c */ #line 840 "mysqlnd_query_parser.grammar" { zval_dtor(&(yyvsp[(1) - (3)].zv)); zval_dtor(&(yyvsp[(3) - (3)].zv)); ;} break; case 62: /* Line 1455 of yacc.c */ #line 846 "mysqlnd_query_parser.grammar" { DBG_BLOCK_ENTER("string identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.name = mnd_pestrndup(Z_STRVAL((yyvsp[(1) - (1)].zv)), Z_STRLEN((yyvsp[(1) - (1)].zv)), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&(yyvsp[(1) - (1)].zv)); DBG_BLOCK_LEAVE; ;} break; case 69: /* Line 1455 of yacc.c */ #line 873 "mysqlnd_query_parser.grammar" { DBG_BLOCK_ENTER("identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.name = mnd_pestrndup(Z_STRVAL((yyvsp[(1) - (1)].zv)), Z_STRLEN((yyvsp[(1) - (1)].zv)), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&(yyvsp[(1) - (1)].zv)); DBG_BLOCK_LEAVE; ;} break; case 70: /* Line 1455 of yacc.c */ #line 885 "mysqlnd_query_parser.grammar" { DBG_BLOCK_ENTER("identifier . identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.table = mnd_pestrndup(Z_STRVAL((yyvsp[(1) - (3)].zv)), Z_STRLEN((yyvsp[(1) - (3)].zv)), finfo.persistent); finfo.name = mnd_pestrndup(Z_STRVAL((yyvsp[(3) - (3)].zv)), Z_STRLEN((yyvsp[(3) - (3)].zv)), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&(yyvsp[(1) - (3)].zv)); zval_dtor(&(yyvsp[(3) - (3)].zv)); DBG_BLOCK_LEAVE; ;} break; case 71: /* Line 1455 of yacc.c */ #line 899 "mysqlnd_query_parser.grammar" { DBG_BLOCK_ENTER("identifier . identifier . identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.db = mnd_pestrndup(Z_STRVAL((yyvsp[(1) - (5)].zv)), Z_STRLEN((yyvsp[(1) - (5)].zv)), finfo.persistent); finfo.table = mnd_pestrndup(Z_STRVAL((yyvsp[(3) - (5)].zv)), Z_STRLEN((yyvsp[(3) - (5)].zv)), finfo.persistent); finfo.name = mnd_pestrndup(Z_STRVAL((yyvsp[(5) - (5)].zv)), Z_STRLEN((yyvsp[(5) - (5)].zv)), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&(yyvsp[(1) - (5)].zv)); zval_dtor(&(yyvsp[(3) - (5)].zv)); zval_dtor(&(yyvsp[(5) - (5)].zv)); DBG_BLOCK_LEAVE; ;} break; case 72: /* Line 1455 of yacc.c */ #line 916 "mysqlnd_query_parser.grammar" { (yyval.zv)=(yyvsp[(1) - (1)].zv); ;} break; case 73: /* Line 1455 of yacc.c */ #line 917 "mysqlnd_query_parser.grammar" { ZVAL_STRING(&((yyval.zv)), (yyvsp[(1) - (1)].kn), 1); ;} break; case 74: /* Line 1455 of yacc.c */ #line 921 "mysqlnd_query_parser.grammar" { (yyval.zv) = (yyvsp[(2) - (2)].zv); ;} break; case 75: /* Line 1455 of yacc.c */ #line 922 "mysqlnd_query_parser.grammar" { (yyval.zv) = (yyvsp[(1) - (1)].zv); ;} break; case 76: /* Line 1455 of yacc.c */ #line 923 "mysqlnd_query_parser.grammar" { ZVAL_NULL(&(yyval.zv)); ;} break; case 77: /* Line 1455 of yacc.c */ #line 927 "mysqlnd_query_parser.grammar" { DBG_BLOCK_ENTER("alias"); if (Z_TYPE((yyvsp[(2) - (2)].zv)) == IS_STRING) { zend_llist_position tmp_pos; struct st_mysqlnd_ms_table_info * tinfo; if ((tinfo = zend_llist_get_last_ex(&PINFO.table_list, &tmp_pos))) { tinfo->org_table = tinfo->table; tinfo->table = mnd_pestrndup(Z_STRVAL((yyvsp[(2) - (2)].zv)), Z_STRLEN((yyvsp[(2) - (2)].zv)), tinfo->persistent); DBG_INF_FMT("ident_alias type = %d", Z_TYPE((yyvsp[(2) - (2)].zv))); } } zval_dtor(&(yyvsp[(2) - (2)].zv)); DBG_BLOCK_LEAVE ;} break; case 78: /* Line 1455 of yacc.c */ #line 945 "mysqlnd_query_parser.grammar" { struct st_mysqlnd_ms_table_info tinfo = {0}; DBG_BLOCK_ENTER("table"); tinfo.persistent = PINFO.persistent; tinfo.table = mnd_pestrndup("DUAL", sizeof("DUAL") - 1, tinfo.persistent); zend_llist_add_element(&PINFO.table_list, &tinfo); DBG_INF_FMT("table=%s", tinfo.table); DBG_BLOCK_LEAVE; ;} break; case 79: /* Line 1455 of yacc.c */ #line 955 "mysqlnd_query_parser.grammar" { struct st_mysqlnd_ms_table_info tinfo = {0}; DBG_BLOCK_ENTER("table"); tinfo.persistent = PINFO.persistent; tinfo.table = mnd_pestrndup(Z_STRVAL((yyvsp[(1) - (1)].zv)), Z_STRLEN((yyvsp[(1) - (1)].zv)), tinfo.persistent); zend_llist_add_element(&PINFO.table_list, &tinfo); zval_dtor(&(yyvsp[(1) - (1)].zv)); DBG_BLOCK_LEAVE; ;} break; case 80: /* Line 1455 of yacc.c */ #line 965 "mysqlnd_query_parser.grammar" { struct st_mysqlnd_ms_table_info tinfo = {0}; DBG_BLOCK_ENTER("db.table"); tinfo.persistent = PINFO.persistent; tinfo.db = mnd_pestrndup(Z_STRVAL((yyvsp[(1) - (3)].zv)), Z_STRLEN((yyvsp[(1) - (3)].zv)), tinfo.persistent); tinfo.table = mnd_pestrndup(Z_STRVAL((yyvsp[(3) - (3)].zv)), Z_STRLEN((yyvsp[(3) - (3)].zv)), tinfo.persistent); zend_llist_add_element(&PINFO.table_list, &tinfo); DBG_INF_FMT("table=%s", Z_STRVAL((yyvsp[(3) - (3)].zv))); zval_dtor(&(yyvsp[(1) - (3)].zv)); zval_dtor(&(yyvsp[(3) - (3)].zv)); DBG_BLOCK_LEAVE ;} break; case 82: /* Line 1455 of yacc.c */ #line 982 "mysqlnd_query_parser.grammar" { YYACCEPT; ;} break; case 86: /* Line 1455 of yacc.c */ #line 996 "mysqlnd_query_parser.grammar" { zend_llist_position pos; struct st_mysqlnd_ms_field_info * finfo = zend_llist_get_last_ex(PINFO.active_field_list, &pos); if (finfo) { /* gotta be always true */ finfo->custom_data = "="; } YYACCEPT; ;} break; case 354: /* Line 1455 of yacc.c */ #line 1277 "mysqlnd_query_parser.grammar" { zval_dtor(&(yyvsp[(1) - (1)].zv)); (yyval.kn) = NULL;;} break; /* Line 1455 of yacc.c */ #line 3690 "mysqlnd_query_parser.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } mysqlnd_ms-1.5.2/mysqlnd_query_parser.grammar0000664000175000017500000010362512161007456021106 0ustar andreyandrey%{ /* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrey Hristov | | Ulf Wendel | +----------------------------------------------------------------------+ */ #include "php.h" #include "mysqlnd_ms.h" #include "zend_llist.h" /* Compile with : bison -o mysqlnd_query_parser.c -d mysqlnd_query_parser.grammar --name-prefix=mysqlnd_qp_ */ #define yyerror mysqlnd_qp_error extern int mysqlnd_qp_error(const char * format, ...); #if defined(PHP_DEBUG) && !defined(YYDEBUG) #define YYDEBUG 1 #else #define YYDEBUG 0 #endif #define YYPARSE_PARAM my_parser TSRMLS_DC #define PINFO (((struct st_mysqlnd_query_parser *) my_parser)->parse_info) #define YYLEX_PARAM *(yyscan_t *)(((struct st_mysqlnd_query_parser *) my_parser)->scanner->scanner) TSRMLS_CC %} %union { zval zv; const char * kn; /* keyword_name */ smart_str * comment; } %{ /* so we can override the default declaration */ #define YY_DECL #include "mysqlnd_query_lexer.lex.h" extern int mysqlnd_qp_lex(YYSTYPE * yylval_param, yyscan_t yyscanner TSRMLS_DC); %} %pure_parser /* We should be thread-safe */ %token QC_TOKEN_ACCESSIBLE %token QC_TOKEN_ACTION %token QC_TOKEN_ADD %token QC_TOKEN_ADDDATE %token QC_TOKEN_AFTER %token QC_TOKEN_AGAINST %token QC_TOKEN_AGGREGATE %token QC_TOKEN_ALGORITHM %token QC_TOKEN_ALL %token QC_TOKEN_ALTER %token QC_TOKEN_ANALYZE %token QC_TOKEN_AND_AND %token QC_TOKEN_AND %token QC_TOKEN_BETWEEN_AND %token QC_TOKEN_ANY %token QC_TOKEN_AS %token QC_TOKEN_ASC %token QC_TOKEN_ASCII %token QC_TOKEN_ASENSITIVE %token QC_TOKEN_AT %token QC_TOKEN_AUTHORS %token QC_TOKEN_AUTOEXTEND_SIZE %token QC_TOKEN_AUTO_INC %token QC_TOKEN_AVG_ROW_LENGTH %token QC_TOKEN_AVG %token QC_TOKEN_BACKUP %token QC_TOKEN_BEFORE %token QC_TOKEN_BEGIN %token QC_TOKEN_BETWEEN %token QC_TOKEN_BIGINT %token QC_TOKEN_BINARY %token QC_TOKEN_BINLOG %token QC_TOKEN_BIN_NUM %token QC_TOKEN_BIT_AND %token QC_TOKEN_BIT_OR %token QC_TOKEN_BIT %token QC_TOKEN_BIT_XOR %token QC_TOKEN_BLOB %token QC_TOKEN_BLOCK %token QC_TOKEN_BOOLEAN %token QC_TOKEN_BOOL %token QC_TOKEN_BOTH %token QC_TOKEN_BTREE %token QC_TOKEN_BY %token QC_TOKEN_BYTE %token QC_TOKEN_CACHE %token QC_TOKEN_CALL %token QC_TOKEN_CASCADE %token QC_TOKEN_CASCADED %token QC_TOKEN_CASE %token QC_TOKEN_CAST %token QC_TOKEN_CATALOG_NAME %token QC_TOKEN_CHAIN %token QC_TOKEN_CHANGE %token QC_TOKEN_CHANGED %token QC_TOKEN_CHARSET %token QC_TOKEN_CHAR %token QC_TOKEN_CHECKSUM %token QC_TOKEN_CHECK %token QC_TOKEN_CIPHER %token QC_TOKEN_CLASS_ORIGIN %token QC_TOKEN_CLIENT %token QC_TOKEN_CLOSE %token QC_TOKEN_COALESCE %token QC_TOKEN_CODE %token QC_TOKEN_COLLATE %token QC_TOKEN_COLLATION %token QC_TOKEN_COLUMNS %token QC_TOKEN_COLUMN %token QC_TOKEN_COLUMN_NAME %token QC_TOKEN_COMMENT %token QC_TOKEN_COMMITTED %token QC_TOKEN_COMMIT %token QC_TOKEN_COMPACT %token QC_TOKEN_COMPLETION %token QC_TOKEN_COMPRESSED %token QC_TOKEN_CONCURRENT %token QC_TOKEN_CONDITION %token QC_TOKEN_CONNECTION %token QC_TOKEN_CONSISTENT %token QC_TOKEN_CONSTRAINT %token QC_TOKEN_CONSTRAINT_CATALOG %token QC_TOKEN_CONSTRAINT_NAME %token QC_TOKEN_CONSTRAINT_SCHEMA %token QC_TOKEN_CONTAINS %token QC_TOKEN_CONTEXT %token QC_TOKEN_CONTINUE %token QC_TOKEN_CONTRIBUTORS %token QC_TOKEN_CONVERT %token QC_TOKEN_COUNT %token QC_TOKEN_CPU %token QC_TOKEN_CREATE %token QC_TOKEN_CROSS %token QC_TOKEN_CUBE %token QC_TOKEN_CURDATE %token QC_TOKEN_CURRENT_USER %token QC_TOKEN_CURSOR %token QC_TOKEN_CURSOR_NAME %token QC_TOKEN_CURTIME %token QC_TOKEN_DATABASE %token QC_TOKEN_DATABASES %token QC_TOKEN_DATAFILE %token QC_TOKEN_DATA %token QC_TOKEN_DATETIME %token QC_TOKEN_DATE_ADD_INTERVAL %token QC_TOKEN_DATE_SUB_INTERVAL %token QC_TOKEN_DATE %token QC_TOKEN_DAY_HOUR %token QC_TOKEN_DAY_MICROSECOND %token QC_TOKEN_DAY_MINUTE %token QC_TOKEN_DAY_SECOND %token QC_TOKEN_DAY %token QC_TOKEN_DEALLOCATE %token QC_TOKEN_DECIMAL_NUM %token QC_TOKEN_DECIMAL %token QC_TOKEN_DECLARE %token QC_TOKEN_DEFAULT %token QC_TOKEN_DEFINER %token QC_TOKEN_DELAYED %token QC_TOKEN_DELAY_KEY_WRITE %token QC_TOKEN_DELETE %token QC_TOKEN_DESC %token QC_TOKEN_DESCRIBE %token QC_TOKEN_DES_KEY_FILE %token QC_TOKEN_DETERMINISTIC %token QC_TOKEN_DIRECTORY %token QC_TOKEN_DISABLE %token QC_TOKEN_DISCARD %token QC_TOKEN_DISK %token QC_TOKEN_DISTINCT %token QC_TOKEN_DIV %token QC_TOKEN_DOUBLE %token QC_TOKEN_DO %token QC_TOKEN_DROP %token QC_TOKEN_DUAL %token QC_TOKEN_DUMPFILE %token QC_TOKEN_DUPLICATE %token QC_TOKEN_DYNAMIC %token QC_TOKEN_EACH %token QC_TOKEN_ELSE %token QC_TOKEN_ELSEIF %token QC_TOKEN_ENABLE %token QC_TOKEN_ENCLOSED %token QC_TOKEN_END %token QC_TOKEN_ENDS %token QC_TOKEN_END_OF_INPUT %token QC_TOKEN_ENGINES %token QC_TOKEN_ENGINE %token QC_TOKEN_ENUM %token QC_TOKEN_EQ %token QC_TOKEN_EQUAL %token QC_TOKEN_ERRORS %token QC_TOKEN_ESCAPED %token QC_TOKEN_ESCAPE %token QC_TOKEN_EVENTS %token QC_TOKEN_EVENT %token QC_TOKEN_EVERY %token QC_TOKEN_EXECUTE %token QC_TOKEN_EXISTS %token QC_TOKEN_EXIT %token QC_TOKEN_EXPANSION %token QC_TOKEN_EXTENDED %token QC_TOKEN_EXTENT_SIZE %token QC_TOKEN_EXTRACT %token QC_TOKEN_FALSE %token QC_TOKEN_FAST %token QC_TOKEN_FAULTS %token QC_TOKEN_FETCH %token QC_TOKEN_FILE %token QC_TOKEN_FIRST %token QC_TOKEN_FIXED %token QC_TOKEN_FLOAT_NUM %token QC_TOKEN_FLOAT %token QC_TOKEN_FLUSH %token QC_TOKEN_FORCE %token QC_TOKEN_FOREIGN %token QC_TOKEN_FOR %token QC_TOKEN_FOUND %token QC_TOKEN_FRAC_SECOND %token QC_TOKEN_FROM %token QC_TOKEN_FULL %token QC_TOKEN_FULLTEXT %token QC_TOKEN_FUNCTION %token QC_TOKEN_GE %token QC_TOKEN_GEOMETRYCOLLECTION %token QC_TOKEN_GEOMETRY %token QC_TOKEN_GET_FORMAT %token QC_TOKEN_GLOBAL %token QC_TOKEN_GRANT %token QC_TOKEN_GRANTS %token QC_TOKEN_GROUP %token QC_TOKEN_GROUP_CONCAT %token QC_TOKEN_GT %token QC_TOKEN_HANDLER %token QC_TOKEN_HASH %token QC_TOKEN_HAVING %token QC_TOKEN_HELP %token QC_TOKEN_HEX_NUM %token QC_TOKEN_HIGH_PRIORITY %token QC_TOKEN_HOST %token QC_TOKEN_HOSTS %token QC_TOKEN_HOUR_MICROSECOND %token QC_TOKEN_HOUR_MINUTE %token QC_TOKEN_HOUR_SECOND %token QC_TOKEN_HOUR %token QC_TOKEN_IDENT %token QC_TOKEN_IDENTIFIED %token QC_TOKEN_IDENT_QUOTED %token QC_TOKEN_IF %token QC_TOKEN_IGNORE %token QC_TOKEN_IGNORE_SERVER_IDS %token QC_TOKEN_IMPORT %token QC_TOKEN_INDEXES %token QC_TOKEN_INDEX %token QC_TOKEN_INFILE %token QC_TOKEN_INITIAL_SIZE %token QC_TOKEN_INNER %token QC_TOKEN_INOUT %token QC_TOKEN_INSENSITIVE %token QC_TOKEN_INSERT %token QC_TOKEN_INSERT_METHOD %token QC_TOKEN_INSTALL %token QC_TOKEN_INTERVAL %token QC_TOKEN_INTO %token QC_TOKEN_INT %token QC_TOKEN_INVOKER %token QC_TOKEN_IN %token QC_TOKEN_IO %token QC_TOKEN_IPC %token QC_TOKEN_IS %token QC_TOKEN_ISOLATION %token QC_TOKEN_ISSUER %token QC_TOKEN_ITERATE %token QC_TOKEN_JOIN %token QC_TOKEN_KEYS %token QC_TOKEN_KEY_BLOCK_SIZE %token QC_TOKEN_KEY %token QC_TOKEN_KILL %token QC_TOKEN_LANGUAGE %token QC_TOKEN_LAST %token QC_TOKEN_LE %token QC_TOKEN_LEADING %token QC_TOKEN_LEAVES %token QC_TOKEN_LEAVE %token QC_TOKEN_LEFT %token QC_TOKEN_LESS %token QC_TOKEN_LEVEL %token QC_TOKEN_LEX_HOSTNAME %token QC_TOKEN_LIKE %token QC_TOKEN_LIMIT %token QC_TOKEN_LINEAR %token QC_TOKEN_LINES %token QC_TOKEN_LINESTRING %token QC_TOKEN_LIST %token QC_TOKEN_LOAD %token QC_TOKEN_LOCAL %token QC_TOKEN_LOCATOR %token QC_TOKEN_LOCKS %token QC_TOKEN_LOCK %token QC_TOKEN_LOGFILE %token QC_TOKEN_LOGS %token QC_TOKEN_LONGBLOB %token QC_TOKEN_LONGTEXT %token QC_TOKEN_LONG_NUM %token QC_TOKEN_LONG %token QC_TOKEN_LOOP %token QC_TOKEN_LOW_PRIORITY %token QC_TOKEN_LT %token QC_TOKEN_MASTER_CONNECT_RETRY %token QC_TOKEN_MASTER_HOST %token QC_TOKEN_MASTER_LOG_FILE %token QC_TOKEN_MASTER_LOG_POS %token QC_TOKEN_MASTER_PASSWORD %token QC_TOKEN_MASTER_PORT %token QC_TOKEN_MASTER_SERVER_ID %token QC_TOKEN_MASTER_SSL_CAPATH %token QC_TOKEN_MASTER_SSL_CA %token QC_TOKEN_MASTER_SSL_CERT %token QC_TOKEN_MASTER_SSL_CIPHER %token QC_TOKEN_MASTER_SSL_KEY %token QC_TOKEN_MASTER_SSL %token QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT %token QC_TOKEN_MASTER %token QC_TOKEN_MASTER_USER %token QC_TOKEN_MASTER_HEARTBEAT_PERIOD %token QC_TOKEN_MATCH %token QC_TOKEN_MAX_CONNECTIONS_PER_HOUR %token QC_TOKEN_MAX_QUERIES_PER_HOUR %token QC_TOKEN_MAX_ROWS %token QC_TOKEN_MAX_SIZE %token QC_TOKEN_MAX %token QC_TOKEN_MAX_UPDATES_PER_HOUR %token QC_TOKEN_MAX_USER_CONNECTIONS %token QC_TOKEN_MAX_VALUE %token QC_TOKEN_MEDIUMBLOB %token QC_TOKEN_MEDIUMINT %token QC_TOKEN_MEDIUMTEXT %token QC_TOKEN_MEDIUM %token QC_TOKEN_MEMORY %token QC_TOKEN_MERGE %token QC_TOKEN_MESSAGE_TEXT %token QC_TOKEN_MICROSECOND %token QC_TOKEN_MIGRATE %token QC_TOKEN_MINUTE_MICROSECOND %token QC_TOKEN_MINUTE_SECOND %token QC_TOKEN_MINUTE %token QC_TOKEN_MIN_ROWS %token QC_TOKEN_MIN %token QC_TOKEN_MODE %token QC_TOKEN_MODIFIES %token QC_TOKEN_MODIFY %token QC_TOKEN_MOD %token QC_TOKEN_MONTH %token QC_TOKEN_MULTILINESTRING %token QC_TOKEN_MULTIPOINT %token QC_TOKEN_MULTIPOLYGON %token QC_TOKEN_MUTEX %token QC_TOKEN_MYSQL_ERRNO %token QC_TOKEN_NAMES %token QC_TOKEN_NAME %token QC_TOKEN_NATIONAL %token QC_TOKEN_NATURAL %token QC_TOKEN_NCHAR_STRING %token QC_TOKEN_NCHAR %token QC_TOKEN_NDBCLUSTER %token QC_TOKEN_NE %token QC_TOKEN_NE_TRIPLE %token QC_TOKEN_NEG %token QC_TOKEN_NEW %token QC_TOKEN_NEXT %token QC_TOKEN_NODEGROUP %token QC_TOKEN_NONE %token QC_TOKEN_NOT2 %token QC_TOKEN_NOT %token QC_TOKEN_NOW %token QC_TOKEN_NO %token QC_TOKEN_NO_WAIT %token QC_TOKEN_NO_WRITE_TO_BINLOG %token QC_TOKEN_NULL %token QC_TOKEN_NUM %token QC_TOKEN_NUMERIC %token QC_TOKEN_NVARCHAR %token QC_TOKEN_OFFSET %token QC_TOKEN_OLD_PASSWORD %token QC_TOKEN_ON %token QC_TOKEN_ONE_SHOT %token QC_TOKEN_ONE %token QC_TOKEN_OPEN %token QC_TOKEN_OPTIMIZE %token QC_TOKEN_OPTIONS %token QC_TOKEN_OPTION %token QC_TOKEN_OPTIONALLY %token QC_TOKEN_OR2 %token QC_TOKEN_ORDER %token QC_TOKEN_OR_OR %token QC_TOKEN_OR %token QC_TOKEN_OUTER %token QC_TOKEN_OUTFILE %token QC_TOKEN_OUT %token QC_TOKEN_OWNER %token QC_TOKEN_PACK_KEYS %token QC_TOKEN_PAGE %token QC_TOKEN_PARAM_MARKER %token QC_TOKEN_PARSER %token QC_TOKEN_PARTIAL %token QC_TOKEN_PARTITIONING %token QC_TOKEN_PARTITIONS %token QC_TOKEN_PARTITION %token QC_TOKEN_PASSWORD %token QC_TOKEN_PHASE %token QC_TOKEN_PLUGINS %token QC_TOKEN_PLUGIN %token QC_TOKEN_POINT %token QC_TOKEN_POLYGON %token QC_TOKEN_PORT %token QC_TOKEN_POSITION %token QC_TOKEN_PRECISION %token QC_TOKEN_PREPARE %token QC_TOKEN_PRESERVE %token QC_TOKEN_PREV %token QC_TOKEN_PRIMARY %token QC_TOKEN_PRIVILEGES %token QC_TOKEN_PROCEDURE %token QC_TOKEN_PROCESS %token QC_TOKEN_PROCESSLIST %token QC_TOKEN_PROFILE %token QC_TOKEN_PROFILES %token QC_TOKEN_PURGE %token QC_TOKEN_QUARTER %token QC_TOKEN_QUERY %token QC_TOKEN_QUICK %token QC_TOKEN_RANGE %token QC_TOKEN_READS %token QC_TOKEN_READ_ONLY %token QC_TOKEN_READ %token QC_TOKEN_READ_WRITE %token QC_TOKEN_REAL %token QC_TOKEN_REBUILD %token QC_TOKEN_RECOVER %token QC_TOKEN_REDOFILE %token QC_TOKEN_REDO_BUFFER_SIZE %token QC_TOKEN_REDUNDANT %token QC_TOKEN_REFERENCES %token QC_TOKEN_REGEXP %token QC_TOKEN_RELAYLOG %token QC_TOKEN_RELAY_LOG_FILE %token QC_TOKEN_RELAY_LOG_POS %token QC_TOKEN_RELAY_THREAD %token QC_TOKEN_RELEASE %token QC_TOKEN_RELOAD %token QC_TOKEN_REMOVE %token QC_TOKEN_RENAME %token QC_TOKEN_REORGANIZE %token QC_TOKEN_REPAIR %token QC_TOKEN_REPEATABLE %token QC_TOKEN_REPEAT %token QC_TOKEN_REPLACE %token QC_TOKEN_REPLICATION %token QC_TOKEN_REQUIRE %token QC_TOKEN_RESET %token QC_TOKEN_RESIGNAL %token QC_TOKEN_RESOURCES %token QC_TOKEN_RESTORE %token QC_TOKEN_RESTRICT %token QC_TOKEN_RESUME %token QC_TOKEN_RETURNS %token QC_TOKEN_RETURN %token QC_TOKEN_REVOKE %token QC_TOKEN_RIGHT %token QC_TOKEN_ROLLBACK %token QC_TOKEN_ROLLUP %token QC_TOKEN_ROUTINE %token QC_TOKEN_ROWS %token QC_TOKEN_ROW_FORMAT %token QC_TOKEN_ROW %token QC_TOKEN_RTREE %token QC_TOKEN_SAVEPOINT %token QC_TOKEN_SCHEDULE %token QC_TOKEN_SCHEMA_NAME %token QC_TOKEN_SECOND_MICROSECOND %token QC_TOKEN_SECOND %token QC_TOKEN_SECURITY %token QC_TOKEN_SELECT %token QC_TOKEN_SENSITIVE %token QC_TOKEN_SEPARATOR %token QC_TOKEN_SERIALIZABLE %token QC_TOKEN_SERIAL %token QC_TOKEN_SESSION %token QC_TOKEN_SERVER %token QC_TOKEN_SERVER_OPTIONS %token QC_TOKEN_SET %token QC_TOKEN_SET_VAR %token QC_TOKEN_SHARE %token QC_TOKEN_SHIFT_LEFT %token QC_TOKEN_SHIFT_RIGHT %token QC_TOKEN_SHOW %token QC_TOKEN_SHUTDOWN %token QC_TOKEN_SIGNAL %token QC_TOKEN_SIGNED %token QC_TOKEN_SIMPLE %token QC_TOKEN_SLAVE %token QC_TOKEN_SMALLINT %token QC_TOKEN_SNAPSHOT %token QC_TOKEN_SOCKET %token QC_TOKEN_SONAME %token QC_TOKEN_SOUNDS %token QC_TOKEN_SOURCE %token QC_TOKEN_SPATIAL %token QC_TOKEN_SPECIFIC %token QC_TOKEN_SQLEXCEPTION %token QC_TOKEN_SQLSTATE %token QC_TOKEN_SQLWARNING %token QC_TOKEN_SQL_BIG_RESULT %token QC_TOKEN_SQL_BUFFER_RESULT %token QC_TOKEN_SQL_CACHE %token QC_TOKEN_SQL_CALC_FOUND_ROWS %token QC_TOKEN_SQL_NO_CACHE %token QC_TOKEN_SQL_SMALL_RESULT %token QC_TOKEN_SQL %token QC_TOKEN_SQL_THREAD %token QC_TOKEN_SSL %token QC_TOKEN_STARTING %token QC_TOKEN_STARTS %token QC_TOKEN_START %token QC_TOKEN_STATUS %token QC_TOKEN_STDDEV_SAMP %token QC_TOKEN_STD %token QC_TOKEN_STOP %token QC_TOKEN_STORAGE %token QC_TOKEN_STRAIGHT_JOIN %token QC_TOKEN_STRING %token QC_TOKEN_SUBCLASS_ORIGIN %token QC_TOKEN_SUBDATE %token QC_TOKEN_SUBJECT %token QC_TOKEN_SUBPARTITIONS %token QC_TOKEN_SUBPARTITION %token QC_TOKEN_SUBSTRING %token QC_TOKEN_SUM %token QC_TOKEN_SUPER %token QC_TOKEN_SUSPEND %token QC_TOKEN_SWAPS %token QC_TOKEN_SWITCHES %token QC_TOKEN_SYSDATE %token QC_TOKEN_TABLES %token QC_TOKEN_TABLESPACE %token QC_TOKEN_TABLE_REF_PRIORITY %token QC_TOKEN_TABLE %token QC_TOKEN_TABLE_CHECKSUM %token QC_TOKEN_TABLE_NAME %token QC_TOKEN_TEMPORARY %token QC_TOKEN_TEMPTABLE %token QC_TOKEN_TERMINATED %token QC_TOKEN_TEXT_STRING %token QC_TOKEN_TEXT %token QC_TOKEN_THAN %token QC_TOKEN_THEN %token QC_TOKEN_TIMESTAMP %token QC_TOKEN_TIMESTAMP_ADD %token QC_TOKEN_TIMESTAMP_DIFF %token QC_TOKEN_TIME %token QC_TOKEN_TINYBLOB %token QC_TOKEN_TINYINT %token QC_TOKEN_TINYTEXT %token QC_TOKEN_TO %token QC_TOKEN_TRAILING %token QC_TOKEN_TRANSACTION %token QC_TOKEN_TRIGGERS %token QC_TOKEN_TRIGGER %token QC_TOKEN_TRIM %token QC_TOKEN_TRUE %token QC_TOKEN_TRUNCATE %token QC_TOKEN_TYPES %token QC_TOKEN_TYPE %token QC_TOKEN_UDF_RETURNS %token QC_TOKEN_ULONGLONG_NUM %token QC_TOKEN_UNCOMMITTED %token QC_TOKEN_UNDEFINED %token QC_TOKEN_UNDERSCORE_CHARSET %token QC_TOKEN_UNDOFILE %token QC_TOKEN_UNDO_BUFFER_SIZE %token QC_TOKEN_UNDO %token QC_TOKEN_UNICODE %token QC_TOKEN_UNINSTALL %token QC_TOKEN_UNION %token QC_TOKEN_UNIQUE %token QC_TOKEN_UNKNOWN %token QC_TOKEN_UNLOCK %token QC_TOKEN_UNSIGNED %token QC_TOKEN_UNTIL %token QC_TOKEN_UPDATE %token QC_TOKEN_UPGRADE %token QC_TOKEN_USAGE %token QC_TOKEN_USER %token QC_TOKEN_USE_FRM %token QC_TOKEN_USE %token QC_TOKEN_USING %token QC_TOKEN_UTC_DATE %token QC_TOKEN_UTC_TIMESTAMP %token QC_TOKEN_UTC_TIME %token QC_TOKEN_VALUES %token QC_TOKEN_VALUE %token QC_TOKEN_VARBINARY %token QC_TOKEN_VARCHAR %token QC_TOKEN_VARIABLES %token QC_TOKEN_VARIANCE %token QC_TOKEN_VARYING %token QC_TOKEN_VAR_SAMP %token QC_TOKEN_VIEW %token QC_TOKEN_WAIT %token QC_TOKEN_WARNINGS %token QC_TOKEN_WEEK %token QC_TOKEN_WHEN %token QC_TOKEN_WHERE %token QC_TOKEN_WHILE %token QC_TOKEN_WITH %token QC_TOKEN_WITH_CUBE %token QC_TOKEN_WITH_ROLLUP %token QC_TOKEN_WORK %token QC_TOKEN_WRAPPER %token QC_TOKEN_WRITE %token QC_TOKEN_X509 %token QC_TOKEN_XA %token QC_TOKEN_XML %token QC_TOKEN_XOR %token QC_TOKEN_YEAR_MONTH %token QC_TOKEN_YEAR %token QC_TOKEN_ZEROFILL %token QC_TOKEN_CLIENT_FLAG %token QC_TOKEN_GLOBAL_VAR %token QC_TOKEN_SESSION_VAR %token QC_TOKEN_BRACKET_OPEN %token QC_TOKEN_BRACKET_CLOSE %token QC_TOKEN_PLUS %token QC_TOKEN_MINUS %token QC_TOKEN_STAR %token QC_TOKEN_COMMA %token QC_TOKEN_DOT %token QC_TOKEN_SEMICOLON %token QC_TOKEN_NO_MORE %token QC_TOKEN_IDENTIFIER %token QC_TOKEN_INTNUM %token QC_TOKEN_FLOATNUM %token QC_TOKEN_ASSIGN_TO_VAR %token QC_TOKEN_TILDE %type ident_alias identifier comment %type keyword keyword_label_in_sp %% statement: select | insert | update | delete | truncate | replace | rename | alter | drop | create | comment { zval_dtor(&$1); } error { YYABORT; } ; create: comment QC_TOKEN_CREATE QC_TOKEN_TABLE if_not_exists table { PINFO.statement = STATEMENT_CREATE; zval_dtor(&$1); YYACCEPT; } drop: comment QC_TOKEN_DROP temporary table_or_tables_option if_exists table restrict { PINFO.statement = STATEMENT_DROP; zval_dtor(&$1); } temporary: QC_TOKEN_TEMPORARY | ; if_exists: QC_TOKEN_IF QC_TOKEN_EXISTS | ; if_not_exists: QC_TOKEN_IF QC_TOKEN_NOT QC_TOKEN_EXISTS | ; restrict: QC_TOKEN_RESTRICT | QC_TOKEN_CASCADE | /* deliberately empty */ ; /* ALTER */ alter: comment QC_TOKEN_ALTER ignore QC_TOKEN_TABLE table { PINFO.statement = STATEMENT_ALTER; zval_dtor(&$1); YYACCEPT; } /* RENAME */ rename: comment QC_TOKEN_RENAME table_or_tables_option table { PINFO.statement = STATEMENT_RENAME; zval_dtor(&$1); YYACCEPT; } table_or_tables_option: QC_TOKEN_TABLE | QC_TOKEN_TABLES ; /* REPLACE */ replace: comment QC_TOKEN_REPLACE replace_option table { PINFO.statement = STATEMENT_REPLACE; zval_dtor(&$1); YYACCEPT; } replace_option: low_priority | QC_TOKEN_DELAYED ; /* TRUNCATE */ truncate: comment QC_TOKEN_TRUNCATE table_token table { PINFO.statement = STATEMENT_TRUNCATE; zval_dtor(&$1); } table_token: QC_TOKEN_TABLE | ; /* DELETE */ delete: comment QC_TOKEN_DELETE delete_options QC_TOKEN_FROM table { PINFO.statement = STATEMENT_DELETE; zval_dtor(&$1); YYACCEPT; } delete_options: delete_option delete_options | ; delete_option: QC_TOKEN_QUICK | QC_TOKEN_LOW_PRIORITY | QC_TOKEN_IGNORE ; /* UPDATE */ update: comment QC_TOKEN_UPDATE low_priority ignore table QC_TOKEN_SET { PINFO.statement = STATEMENT_UPDATE; zval_dtor(&$1); YYACCEPT; } low_priority: QC_TOKEN_LOW_PRIORITY | ; /* INSERT */ insert: comment QC_TOKEN_INSERT QC_TOKEN_INTO ignore table { PINFO.statement = STATEMENT_INSERT; zval_dtor(&$1); YYACCEPT; } ignore: QC_TOKEN_IGNORE | ; /* SELECT */ select: comment QC_TOKEN_SELECT { zval_dtor(&$1); PINFO.statement = STATEMENT_SELECT; PINFO.active_field_list = &PINFO.select_field_list; } query_field_list { PINFO.active_field_list = NULL; } opt_from_clause { if (!PINFO.parse_where) { YYACCEPT; } PINFO.active_field_list = &PINFO.where_field_list; } where_clause { PINFO.active_field_list = NULL; YYACCEPT; } ; comment: QC_TOKEN_COMMENT | comment QC_TOKEN_COMMENT { zval_dtor(&$2); } | { ZVAL_NULL(&$$); } ; query_field_list: comment QC_TOKEN_STAR { zval_dtor(&$1); } | select_field_list ; select_field_list: select_field_list_tail QC_TOKEN_COMMA select_field_list | select_field_list_tail ; select_field_list_tail: comment select_field ident_alias { zval_dtor(&$1); zval_dtor(&$3); } select_field: field | function_call | QC_TOKEN_INTNUM | QC_TOKEN_STRING { DBG_BLOCK_ENTER("string identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.name = mnd_pestrndup(Z_STRVAL($1), Z_STRLEN($1), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&$1); DBG_BLOCK_LEAVE; } ; function_call: field QC_TOKEN_BRACKET_OPEN opt_function_call_parameter_list QC_TOKEN_BRACKET_CLOSE; opt_function_call_parameter_list: | function_call_parameter_list ; function_call_parameter_list: function_call_parameter_list QC_TOKEN_COMMA function_call_parameter | function_call_parameter ; function_call_parameter:; field: identifier { DBG_BLOCK_ENTER("identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.name = mnd_pestrndup(Z_STRVAL($1), Z_STRLEN($1), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&$1); DBG_BLOCK_LEAVE; } | identifier QC_TOKEN_DOT identifier { DBG_BLOCK_ENTER("identifier . identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.table = mnd_pestrndup(Z_STRVAL($1), Z_STRLEN($1), finfo.persistent); finfo.name = mnd_pestrndup(Z_STRVAL($3), Z_STRLEN($3), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&$1); zval_dtor(&$3); DBG_BLOCK_LEAVE; } | identifier QC_TOKEN_DOT identifier QC_TOKEN_DOT identifier { DBG_BLOCK_ENTER("identifier . identifier . identifier"); if (PINFO.active_field_list) { struct st_mysqlnd_ms_field_info finfo = {0}; finfo.persistent = PINFO.persistent; finfo.db = mnd_pestrndup(Z_STRVAL($1), Z_STRLEN($1), finfo.persistent); finfo.table = mnd_pestrndup(Z_STRVAL($3), Z_STRLEN($3), finfo.persistent); finfo.name = mnd_pestrndup(Z_STRVAL($5), Z_STRLEN($5), finfo.persistent); zend_llist_add_element(PINFO.active_field_list, &finfo); } zval_dtor(&$1); zval_dtor(&$3); zval_dtor(&$5); DBG_BLOCK_LEAVE; } ; identifier: QC_TOKEN_IDENTIFIER { $$=$1; } | keyword { ZVAL_STRING(&($$), $1, 1); } ; ident_alias: QC_TOKEN_AS identifier { $$ = $2; } | identifier { $$ = $1; } | { ZVAL_NULL(&$$); } ; query_table: table ident_alias { DBG_BLOCK_ENTER("alias"); if (Z_TYPE($2) == IS_STRING) { zend_llist_position tmp_pos; struct st_mysqlnd_ms_table_info * tinfo; if ((tinfo = zend_llist_get_last_ex(&PINFO.table_list, &tmp_pos))) { tinfo->org_table = tinfo->table; tinfo->table = mnd_pestrndup(Z_STRVAL($2), Z_STRLEN($2), tinfo->persistent); DBG_INF_FMT("ident_alias type = %d", Z_TYPE($2)); } } zval_dtor(&$2); DBG_BLOCK_LEAVE } ; table: QC_TOKEN_DUAL { struct st_mysqlnd_ms_table_info tinfo = {0}; DBG_BLOCK_ENTER("table"); tinfo.persistent = PINFO.persistent; tinfo.table = mnd_pestrndup("DUAL", sizeof("DUAL") - 1, tinfo.persistent); zend_llist_add_element(&PINFO.table_list, &tinfo); DBG_INF_FMT("table=%s", tinfo.table); DBG_BLOCK_LEAVE; } | identifier { struct st_mysqlnd_ms_table_info tinfo = {0}; DBG_BLOCK_ENTER("table"); tinfo.persistent = PINFO.persistent; tinfo.table = mnd_pestrndup(Z_STRVAL($1), Z_STRLEN($1), tinfo.persistent); zend_llist_add_element(&PINFO.table_list, &tinfo); zval_dtor(&$1); DBG_BLOCK_LEAVE; } | identifier QC_TOKEN_DOT identifier { struct st_mysqlnd_ms_table_info tinfo = {0}; DBG_BLOCK_ENTER("db.table"); tinfo.persistent = PINFO.persistent; tinfo.db = mnd_pestrndup(Z_STRVAL($1), Z_STRLEN($1), tinfo.persistent); tinfo.table = mnd_pestrndup(Z_STRVAL($3), Z_STRLEN($3), tinfo.persistent); zend_llist_add_element(&PINFO.table_list, &tinfo); DBG_INF_FMT("table=%s", Z_STRVAL($3)); zval_dtor(&$1); zval_dtor(&$3); DBG_BLOCK_LEAVE } ; opt_from_clause: QC_TOKEN_FROM query_table_list | { YYACCEPT; } ; query_table_list: query_table | query_table_list QC_TOKEN_COMMA query_table ; where_clause: QC_TOKEN_WHERE where_clause_tail ; where_clause_tail: field QC_TOKEN_EQ field_value { zend_llist_position pos; struct st_mysqlnd_ms_field_info * finfo = zend_llist_get_last_ex(PINFO.active_field_list, &pos); if (finfo) { /* gotta be always true */ finfo->custom_data = "="; } YYACCEPT; } ; field_value: QC_TOKEN_INTNUM | QC_TOKEN_STRING ; keyword: keyword_label_in_sp | QC_TOKEN_ASCII | QC_TOKEN_BACKUP | QC_TOKEN_BEGIN | QC_TOKEN_BYTE | QC_TOKEN_CACHE | QC_TOKEN_CHARSET | QC_TOKEN_CHECKSUM | QC_TOKEN_CLOSE | QC_TOKEN_COMMIT | QC_TOKEN_CONTAINS | QC_TOKEN_DEALLOCATE | QC_TOKEN_DO | QC_TOKEN_END | QC_TOKEN_EXECUTE | QC_TOKEN_FLUSH | QC_TOKEN_HANDLER | QC_TOKEN_HELP | QC_TOKEN_HOST | QC_TOKEN_INSTALL | QC_TOKEN_LANGUAGE | QC_TOKEN_NO | QC_TOKEN_OPEN | QC_TOKEN_OPTIONS | QC_TOKEN_OWNER | QC_TOKEN_PARSER | QC_TOKEN_PARTITION | QC_TOKEN_PORT | QC_TOKEN_PREPARE | QC_TOKEN_REMOVE | QC_TOKEN_REPAIR | QC_TOKEN_RESET | QC_TOKEN_RESTORE | QC_TOKEN_ROLLBACK | QC_TOKEN_SAVEPOINT | QC_TOKEN_SECURITY | QC_TOKEN_SERVER | QC_TOKEN_SIGNED | QC_TOKEN_SOCKET | QC_TOKEN_SLAVE | QC_TOKEN_SONAME | QC_TOKEN_START | QC_TOKEN_STOP | QC_TOKEN_TRUNCATE | QC_TOKEN_UNICODE | QC_TOKEN_UNINSTALL | QC_TOKEN_WRAPPER | QC_TOKEN_XA | QC_TOKEN_UPGRADE ; keyword_label_in_sp: QC_TOKEN_ACTION | QC_TOKEN_ADDDATE | QC_TOKEN_AFTER | QC_TOKEN_AGAINST | QC_TOKEN_AGGREGATE | QC_TOKEN_ALGORITHM | QC_TOKEN_ANY | QC_TOKEN_AT | QC_TOKEN_AUTHORS | QC_TOKEN_AUTO_INC | QC_TOKEN_AUTOEXTEND_SIZE | QC_TOKEN_AVG_ROW_LENGTH | QC_TOKEN_AVG | QC_TOKEN_BINLOG | QC_TOKEN_BIT | QC_TOKEN_BLOCK | QC_TOKEN_BOOL | QC_TOKEN_BOOLEAN | QC_TOKEN_BTREE | QC_TOKEN_CASCADED | QC_TOKEN_CHAIN | QC_TOKEN_CHANGED | QC_TOKEN_CIPHER | QC_TOKEN_CLIENT | QC_TOKEN_COALESCE | QC_TOKEN_CODE | QC_TOKEN_COLLATION | QC_TOKEN_COLUMNS | QC_TOKEN_COMMITTED | QC_TOKEN_COMPACT | QC_TOKEN_COMPLETION | QC_TOKEN_COMPRESSED | QC_TOKEN_CONCURRENT | QC_TOKEN_CONNECTION | QC_TOKEN_CONSISTENT | QC_TOKEN_CONTEXT | QC_TOKEN_CONTRIBUTORS | QC_TOKEN_CPU | QC_TOKEN_CUBE | QC_TOKEN_DATA | QC_TOKEN_DATAFILE | QC_TOKEN_DATETIME | QC_TOKEN_DATE | QC_TOKEN_DAY | QC_TOKEN_DEFINER | QC_TOKEN_DELAY_KEY_WRITE | QC_TOKEN_DES_KEY_FILE | QC_TOKEN_DIRECTORY | QC_TOKEN_DISABLE | QC_TOKEN_DISCARD | QC_TOKEN_DISK | QC_TOKEN_DUMPFILE | QC_TOKEN_DUPLICATE | QC_TOKEN_DYNAMIC | QC_TOKEN_ENDS | QC_TOKEN_ENUM | QC_TOKEN_ENGINE | QC_TOKEN_ENGINES | QC_TOKEN_ERRORS | QC_TOKEN_ESCAPE | QC_TOKEN_EVENT | QC_TOKEN_EVENTS | QC_TOKEN_EVERY | QC_TOKEN_EXPANSION | QC_TOKEN_EXTENDED | QC_TOKEN_EXTENT_SIZE | QC_TOKEN_FAULTS | QC_TOKEN_FAST | QC_TOKEN_FOUND | QC_TOKEN_ENABLE | QC_TOKEN_FULL | QC_TOKEN_FILE | QC_TOKEN_FIRST | QC_TOKEN_FIXED | QC_TOKEN_FRAC_SECOND | QC_TOKEN_GEOMETRY | QC_TOKEN_GEOMETRYCOLLECTION | QC_TOKEN_GET_FORMAT | QC_TOKEN_GRANTS | QC_TOKEN_GLOBAL | QC_TOKEN_HASH | QC_TOKEN_HOSTS | QC_TOKEN_HOUR | QC_TOKEN_IDENTIFIED | QC_TOKEN_INVOKER | QC_TOKEN_IMPORT | QC_TOKEN_INDEXES | QC_TOKEN_INITIAL_SIZE | QC_TOKEN_IO | QC_TOKEN_IPC | QC_TOKEN_ISOLATION | QC_TOKEN_ISSUER | QC_TOKEN_INSERT_METHOD | QC_TOKEN_KEY_BLOCK_SIZE | QC_TOKEN_LAST | QC_TOKEN_LEAVES | QC_TOKEN_LESS | QC_TOKEN_LEVEL | QC_TOKEN_LINESTRING | QC_TOKEN_LIST | QC_TOKEN_LOCAL | QC_TOKEN_LOCKS | QC_TOKEN_LOGFILE | QC_TOKEN_LOGS | QC_TOKEN_MAX_ROWS | QC_TOKEN_MASTER | QC_TOKEN_MASTER_HOST | QC_TOKEN_MASTER_PORT | QC_TOKEN_MASTER_LOG_FILE | QC_TOKEN_MASTER_LOG_POS | QC_TOKEN_MASTER_USER | QC_TOKEN_MASTER_PASSWORD | QC_TOKEN_MASTER_SERVER_ID | QC_TOKEN_MASTER_CONNECT_RETRY | QC_TOKEN_MASTER_SSL | QC_TOKEN_MASTER_SSL_CA | QC_TOKEN_MASTER_SSL_CAPATH | QC_TOKEN_MASTER_SSL_CERT | QC_TOKEN_MASTER_SSL_CIPHER | QC_TOKEN_MASTER_SSL_KEY | QC_TOKEN_MAX_CONNECTIONS_PER_HOUR | QC_TOKEN_MAX_QUERIES_PER_HOUR | QC_TOKEN_MAX_SIZE | QC_TOKEN_MAX_UPDATES_PER_HOUR | QC_TOKEN_MAX_USER_CONNECTIONS | QC_TOKEN_MAX_VALUE | QC_TOKEN_MEDIUM | QC_TOKEN_MEMORY | QC_TOKEN_MERGE | QC_TOKEN_MICROSECOND | QC_TOKEN_MIGRATE | QC_TOKEN_MINUTE | QC_TOKEN_MIN_ROWS | QC_TOKEN_MODIFY | QC_TOKEN_MODE | QC_TOKEN_MONTH | QC_TOKEN_MULTILINESTRING | QC_TOKEN_MULTIPOINT | QC_TOKEN_MULTIPOLYGON | QC_TOKEN_MUTEX | QC_TOKEN_NAME | QC_TOKEN_NAMES | QC_TOKEN_NATIONAL | QC_TOKEN_NCHAR | QC_TOKEN_NDBCLUSTER | QC_TOKEN_NEXT | QC_TOKEN_NEW | QC_TOKEN_NO_WAIT | QC_TOKEN_NODEGROUP | QC_TOKEN_NONE | QC_TOKEN_NVARCHAR | QC_TOKEN_OFFSET | QC_TOKEN_OLD_PASSWORD | QC_TOKEN_ONE_SHOT | QC_TOKEN_ONE | QC_TOKEN_PACK_KEYS | QC_TOKEN_PAGE | QC_TOKEN_PARTIAL | QC_TOKEN_PARTITIONING | QC_TOKEN_PARTITIONS | QC_TOKEN_PASSWORD | QC_TOKEN_PHASE | QC_TOKEN_PLUGIN | QC_TOKEN_PLUGINS | QC_TOKEN_POINT | QC_TOKEN_POLYGON | QC_TOKEN_PRESERVE | QC_TOKEN_PREV | QC_TOKEN_PRIVILEGES | QC_TOKEN_PROCESS | QC_TOKEN_PROCESSLIST | QC_TOKEN_PROFILE | QC_TOKEN_PROFILES | QC_TOKEN_QUARTER | QC_TOKEN_QUERY | QC_TOKEN_QUICK | QC_TOKEN_READ_ONLY | QC_TOKEN_REBUILD | QC_TOKEN_RECOVER | QC_TOKEN_REDO_BUFFER_SIZE | QC_TOKEN_REDOFILE | QC_TOKEN_REDUNDANT | QC_TOKEN_RELAY_LOG_FILE | QC_TOKEN_RELAY_LOG_POS | QC_TOKEN_RELAY_THREAD | QC_TOKEN_RELOAD | QC_TOKEN_REORGANIZE | QC_TOKEN_REPEATABLE | QC_TOKEN_REPLICATION | QC_TOKEN_RESOURCES | QC_TOKEN_RESUME | QC_TOKEN_RETURNS | QC_TOKEN_ROLLUP | QC_TOKEN_ROUTINE | QC_TOKEN_ROWS | QC_TOKEN_ROW_FORMAT | QC_TOKEN_ROW | QC_TOKEN_RTREE | QC_TOKEN_SCHEDULE | QC_TOKEN_SECOND | QC_TOKEN_SERIAL | QC_TOKEN_SERIALIZABLE | QC_TOKEN_SESSION | QC_TOKEN_SIMPLE | QC_TOKEN_SHARE | QC_TOKEN_SHUTDOWN | QC_TOKEN_SNAPSHOT | QC_TOKEN_SOUNDS | QC_TOKEN_SOURCE | QC_TOKEN_SQL_CACHE | QC_TOKEN_SQL_BUFFER_RESULT | QC_TOKEN_SQL_NO_CACHE | QC_TOKEN_SQL_THREAD | QC_TOKEN_STARTS | QC_TOKEN_STATUS | QC_TOKEN_STORAGE | QC_TOKEN_STRING { zval_dtor(&$1); $$ = NULL;} | QC_TOKEN_SUBDATE | QC_TOKEN_SUBJECT | QC_TOKEN_SUBPARTITION | QC_TOKEN_SUBPARTITIONS | QC_TOKEN_SUPER | QC_TOKEN_SUSPEND | QC_TOKEN_SWAPS | QC_TOKEN_SWITCHES | QC_TOKEN_TABLES | QC_TOKEN_TABLE_CHECKSUM | QC_TOKEN_TABLESPACE | QC_TOKEN_TEMPORARY | QC_TOKEN_TEMPTABLE | QC_TOKEN_TEXT | QC_TOKEN_THAN | QC_TOKEN_TRANSACTION | QC_TOKEN_TRIGGERS | QC_TOKEN_TIMESTAMP | QC_TOKEN_TIMESTAMP_ADD | QC_TOKEN_TIMESTAMP_DIFF | QC_TOKEN_TIME | QC_TOKEN_TYPES | QC_TOKEN_TYPE | QC_TOKEN_UDF_RETURNS | QC_TOKEN_FUNCTION | QC_TOKEN_UNCOMMITTED | QC_TOKEN_UNDEFINED | QC_TOKEN_UNDO_BUFFER_SIZE | QC_TOKEN_UNDOFILE | QC_TOKEN_UNKNOWN | QC_TOKEN_UNTIL | QC_TOKEN_USER | QC_TOKEN_USE_FRM | QC_TOKEN_VARIABLES | QC_TOKEN_VIEW | QC_TOKEN_VALUE | QC_TOKEN_WARNINGS | QC_TOKEN_WAIT | QC_TOKEN_WEEK | QC_TOKEN_WORK | QC_TOKEN_X509 | QC_TOKEN_YEAR ; mysqlnd_ms-1.5.2/mysqlnd_query_parser.h0000664000175000017500000004706112161007456017710 0ustar andreyandrey /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { QC_TOKEN_ACCESSIBLE = 258, QC_TOKEN_ACTION = 259, QC_TOKEN_ADD = 260, QC_TOKEN_ADDDATE = 261, QC_TOKEN_AFTER = 262, QC_TOKEN_AGAINST = 263, QC_TOKEN_AGGREGATE = 264, QC_TOKEN_ALGORITHM = 265, QC_TOKEN_ALL = 266, QC_TOKEN_ALTER = 267, QC_TOKEN_ANALYZE = 268, QC_TOKEN_AND_AND = 269, QC_TOKEN_AND = 270, QC_TOKEN_BETWEEN_AND = 271, QC_TOKEN_ANY = 272, QC_TOKEN_AS = 273, QC_TOKEN_ASC = 274, QC_TOKEN_ASCII = 275, QC_TOKEN_ASENSITIVE = 276, QC_TOKEN_AT = 277, QC_TOKEN_AUTHORS = 278, QC_TOKEN_AUTOEXTEND_SIZE = 279, QC_TOKEN_AUTO_INC = 280, QC_TOKEN_AVG_ROW_LENGTH = 281, QC_TOKEN_AVG = 282, QC_TOKEN_BACKUP = 283, QC_TOKEN_BEFORE = 284, QC_TOKEN_BEGIN = 285, QC_TOKEN_BETWEEN = 286, QC_TOKEN_BIGINT = 287, QC_TOKEN_BINARY = 288, QC_TOKEN_BINLOG = 289, QC_TOKEN_BIN_NUM = 290, QC_TOKEN_BIT_AND = 291, QC_TOKEN_BIT_OR = 292, QC_TOKEN_BIT = 293, QC_TOKEN_BIT_XOR = 294, QC_TOKEN_BLOB = 295, QC_TOKEN_BLOCK = 296, QC_TOKEN_BOOLEAN = 297, QC_TOKEN_BOOL = 298, QC_TOKEN_BOTH = 299, QC_TOKEN_BTREE = 300, QC_TOKEN_BY = 301, QC_TOKEN_BYTE = 302, QC_TOKEN_CACHE = 303, QC_TOKEN_CALL = 304, QC_TOKEN_CASCADE = 305, QC_TOKEN_CASCADED = 306, QC_TOKEN_CASE = 307, QC_TOKEN_CAST = 308, QC_TOKEN_CATALOG_NAME = 309, QC_TOKEN_CHAIN = 310, QC_TOKEN_CHANGE = 311, QC_TOKEN_CHANGED = 312, QC_TOKEN_CHARSET = 313, QC_TOKEN_CHAR = 314, QC_TOKEN_CHECKSUM = 315, QC_TOKEN_CHECK = 316, QC_TOKEN_CIPHER = 317, QC_TOKEN_CLASS_ORIGIN = 318, QC_TOKEN_CLIENT = 319, QC_TOKEN_CLOSE = 320, QC_TOKEN_COALESCE = 321, QC_TOKEN_CODE = 322, QC_TOKEN_COLLATE = 323, QC_TOKEN_COLLATION = 324, QC_TOKEN_COLUMNS = 325, QC_TOKEN_COLUMN = 326, QC_TOKEN_COLUMN_NAME = 327, QC_TOKEN_COMMENT = 328, QC_TOKEN_COMMITTED = 329, QC_TOKEN_COMMIT = 330, QC_TOKEN_COMPACT = 331, QC_TOKEN_COMPLETION = 332, QC_TOKEN_COMPRESSED = 333, QC_TOKEN_CONCURRENT = 334, QC_TOKEN_CONDITION = 335, QC_TOKEN_CONNECTION = 336, QC_TOKEN_CONSISTENT = 337, QC_TOKEN_CONSTRAINT = 338, QC_TOKEN_CONSTRAINT_CATALOG = 339, QC_TOKEN_CONSTRAINT_NAME = 340, QC_TOKEN_CONSTRAINT_SCHEMA = 341, QC_TOKEN_CONTAINS = 342, QC_TOKEN_CONTEXT = 343, QC_TOKEN_CONTINUE = 344, QC_TOKEN_CONTRIBUTORS = 345, QC_TOKEN_CONVERT = 346, QC_TOKEN_COUNT = 347, QC_TOKEN_CPU = 348, QC_TOKEN_CREATE = 349, QC_TOKEN_CROSS = 350, QC_TOKEN_CUBE = 351, QC_TOKEN_CURDATE = 352, QC_TOKEN_CURRENT_USER = 353, QC_TOKEN_CURSOR = 354, QC_TOKEN_CURSOR_NAME = 355, QC_TOKEN_CURTIME = 356, QC_TOKEN_DATABASE = 357, QC_TOKEN_DATABASES = 358, QC_TOKEN_DATAFILE = 359, QC_TOKEN_DATA = 360, QC_TOKEN_DATETIME = 361, QC_TOKEN_DATE_ADD_INTERVAL = 362, QC_TOKEN_DATE_SUB_INTERVAL = 363, QC_TOKEN_DATE = 364, QC_TOKEN_DAY_HOUR = 365, QC_TOKEN_DAY_MICROSECOND = 366, QC_TOKEN_DAY_MINUTE = 367, QC_TOKEN_DAY_SECOND = 368, QC_TOKEN_DAY = 369, QC_TOKEN_DEALLOCATE = 370, QC_TOKEN_DECIMAL_NUM = 371, QC_TOKEN_DECIMAL = 372, QC_TOKEN_DECLARE = 373, QC_TOKEN_DEFAULT = 374, QC_TOKEN_DEFINER = 375, QC_TOKEN_DELAYED = 376, QC_TOKEN_DELAY_KEY_WRITE = 377, QC_TOKEN_DELETE = 378, QC_TOKEN_DESC = 379, QC_TOKEN_DESCRIBE = 380, QC_TOKEN_DES_KEY_FILE = 381, QC_TOKEN_DETERMINISTIC = 382, QC_TOKEN_DIRECTORY = 383, QC_TOKEN_DISABLE = 384, QC_TOKEN_DISCARD = 385, QC_TOKEN_DISK = 386, QC_TOKEN_DISTINCT = 387, QC_TOKEN_DIV = 388, QC_TOKEN_DOUBLE = 389, QC_TOKEN_DO = 390, QC_TOKEN_DROP = 391, QC_TOKEN_DUAL = 392, QC_TOKEN_DUMPFILE = 393, QC_TOKEN_DUPLICATE = 394, QC_TOKEN_DYNAMIC = 395, QC_TOKEN_EACH = 396, QC_TOKEN_ELSE = 397, QC_TOKEN_ELSEIF = 398, QC_TOKEN_ENABLE = 399, QC_TOKEN_ENCLOSED = 400, QC_TOKEN_END = 401, QC_TOKEN_ENDS = 402, QC_TOKEN_END_OF_INPUT = 403, QC_TOKEN_ENGINES = 404, QC_TOKEN_ENGINE = 405, QC_TOKEN_ENUM = 406, QC_TOKEN_EQ = 407, QC_TOKEN_EQUAL = 408, QC_TOKEN_ERRORS = 409, QC_TOKEN_ESCAPED = 410, QC_TOKEN_ESCAPE = 411, QC_TOKEN_EVENTS = 412, QC_TOKEN_EVENT = 413, QC_TOKEN_EVERY = 414, QC_TOKEN_EXECUTE = 415, QC_TOKEN_EXISTS = 416, QC_TOKEN_EXIT = 417, QC_TOKEN_EXPANSION = 418, QC_TOKEN_EXTENDED = 419, QC_TOKEN_EXTENT_SIZE = 420, QC_TOKEN_EXTRACT = 421, QC_TOKEN_FALSE = 422, QC_TOKEN_FAST = 423, QC_TOKEN_FAULTS = 424, QC_TOKEN_FETCH = 425, QC_TOKEN_FILE = 426, QC_TOKEN_FIRST = 427, QC_TOKEN_FIXED = 428, QC_TOKEN_FLOAT_NUM = 429, QC_TOKEN_FLOAT = 430, QC_TOKEN_FLUSH = 431, QC_TOKEN_FORCE = 432, QC_TOKEN_FOREIGN = 433, QC_TOKEN_FOR = 434, QC_TOKEN_FOUND = 435, QC_TOKEN_FRAC_SECOND = 436, QC_TOKEN_FROM = 437, QC_TOKEN_FULL = 438, QC_TOKEN_FULLTEXT = 439, QC_TOKEN_FUNCTION = 440, QC_TOKEN_GE = 441, QC_TOKEN_GEOMETRYCOLLECTION = 442, QC_TOKEN_GEOMETRY = 443, QC_TOKEN_GET_FORMAT = 444, QC_TOKEN_GLOBAL = 445, QC_TOKEN_GRANT = 446, QC_TOKEN_GRANTS = 447, QC_TOKEN_GROUP = 448, QC_TOKEN_GROUP_CONCAT = 449, QC_TOKEN_GT = 450, QC_TOKEN_HANDLER = 451, QC_TOKEN_HASH = 452, QC_TOKEN_HAVING = 453, QC_TOKEN_HELP = 454, QC_TOKEN_HEX_NUM = 455, QC_TOKEN_HIGH_PRIORITY = 456, QC_TOKEN_HOST = 457, QC_TOKEN_HOSTS = 458, QC_TOKEN_HOUR_MICROSECOND = 459, QC_TOKEN_HOUR_MINUTE = 460, QC_TOKEN_HOUR_SECOND = 461, QC_TOKEN_HOUR = 462, QC_TOKEN_IDENT = 463, QC_TOKEN_IDENTIFIED = 464, QC_TOKEN_IDENT_QUOTED = 465, QC_TOKEN_IF = 466, QC_TOKEN_IGNORE = 467, QC_TOKEN_IGNORE_SERVER_IDS = 468, QC_TOKEN_IMPORT = 469, QC_TOKEN_INDEXES = 470, QC_TOKEN_INDEX = 471, QC_TOKEN_INFILE = 472, QC_TOKEN_INITIAL_SIZE = 473, QC_TOKEN_INNER = 474, QC_TOKEN_INOUT = 475, QC_TOKEN_INSENSITIVE = 476, QC_TOKEN_INSERT = 477, QC_TOKEN_INSERT_METHOD = 478, QC_TOKEN_INSTALL = 479, QC_TOKEN_INTERVAL = 480, QC_TOKEN_INTO = 481, QC_TOKEN_INT = 482, QC_TOKEN_INVOKER = 483, QC_TOKEN_IN = 484, QC_TOKEN_IO = 485, QC_TOKEN_IPC = 486, QC_TOKEN_IS = 487, QC_TOKEN_ISOLATION = 488, QC_TOKEN_ISSUER = 489, QC_TOKEN_ITERATE = 490, QC_TOKEN_JOIN = 491, QC_TOKEN_KEYS = 492, QC_TOKEN_KEY_BLOCK_SIZE = 493, QC_TOKEN_KEY = 494, QC_TOKEN_KILL = 495, QC_TOKEN_LANGUAGE = 496, QC_TOKEN_LAST = 497, QC_TOKEN_LE = 498, QC_TOKEN_LEADING = 499, QC_TOKEN_LEAVES = 500, QC_TOKEN_LEAVE = 501, QC_TOKEN_LEFT = 502, QC_TOKEN_LESS = 503, QC_TOKEN_LEVEL = 504, QC_TOKEN_LEX_HOSTNAME = 505, QC_TOKEN_LIKE = 506, QC_TOKEN_LIMIT = 507, QC_TOKEN_LINEAR = 508, QC_TOKEN_LINES = 509, QC_TOKEN_LINESTRING = 510, QC_TOKEN_LIST = 511, QC_TOKEN_LOAD = 512, QC_TOKEN_LOCAL = 513, QC_TOKEN_LOCATOR = 514, QC_TOKEN_LOCKS = 515, QC_TOKEN_LOCK = 516, QC_TOKEN_LOGFILE = 517, QC_TOKEN_LOGS = 518, QC_TOKEN_LONGBLOB = 519, QC_TOKEN_LONGTEXT = 520, QC_TOKEN_LONG_NUM = 521, QC_TOKEN_LONG = 522, QC_TOKEN_LOOP = 523, QC_TOKEN_LOW_PRIORITY = 524, QC_TOKEN_LT = 525, QC_TOKEN_MASTER_CONNECT_RETRY = 526, QC_TOKEN_MASTER_HOST = 527, QC_TOKEN_MASTER_LOG_FILE = 528, QC_TOKEN_MASTER_LOG_POS = 529, QC_TOKEN_MASTER_PASSWORD = 530, QC_TOKEN_MASTER_PORT = 531, QC_TOKEN_MASTER_SERVER_ID = 532, QC_TOKEN_MASTER_SSL_CAPATH = 533, QC_TOKEN_MASTER_SSL_CA = 534, QC_TOKEN_MASTER_SSL_CERT = 535, QC_TOKEN_MASTER_SSL_CIPHER = 536, QC_TOKEN_MASTER_SSL_KEY = 537, QC_TOKEN_MASTER_SSL = 538, QC_TOKEN_MASTER_SSL_VERIFY_SERVER_CERT = 539, QC_TOKEN_MASTER = 540, QC_TOKEN_MASTER_USER = 541, QC_TOKEN_MASTER_HEARTBEAT_PERIOD = 542, QC_TOKEN_MATCH = 543, QC_TOKEN_MAX_CONNECTIONS_PER_HOUR = 544, QC_TOKEN_MAX_QUERIES_PER_HOUR = 545, QC_TOKEN_MAX_ROWS = 546, QC_TOKEN_MAX_SIZE = 547, QC_TOKEN_MAX = 548, QC_TOKEN_MAX_UPDATES_PER_HOUR = 549, QC_TOKEN_MAX_USER_CONNECTIONS = 550, QC_TOKEN_MAX_VALUE = 551, QC_TOKEN_MEDIUMBLOB = 552, QC_TOKEN_MEDIUMINT = 553, QC_TOKEN_MEDIUMTEXT = 554, QC_TOKEN_MEDIUM = 555, QC_TOKEN_MEMORY = 556, QC_TOKEN_MERGE = 557, QC_TOKEN_MESSAGE_TEXT = 558, QC_TOKEN_MICROSECOND = 559, QC_TOKEN_MIGRATE = 560, QC_TOKEN_MINUTE_MICROSECOND = 561, QC_TOKEN_MINUTE_SECOND = 562, QC_TOKEN_MINUTE = 563, QC_TOKEN_MIN_ROWS = 564, QC_TOKEN_MIN = 565, QC_TOKEN_MODE = 566, QC_TOKEN_MODIFIES = 567, QC_TOKEN_MODIFY = 568, QC_TOKEN_MOD = 569, QC_TOKEN_MONTH = 570, QC_TOKEN_MULTILINESTRING = 571, QC_TOKEN_MULTIPOINT = 572, QC_TOKEN_MULTIPOLYGON = 573, QC_TOKEN_MUTEX = 574, QC_TOKEN_MYSQL_ERRNO = 575, QC_TOKEN_NAMES = 576, QC_TOKEN_NAME = 577, QC_TOKEN_NATIONAL = 578, QC_TOKEN_NATURAL = 579, QC_TOKEN_NCHAR_STRING = 580, QC_TOKEN_NCHAR = 581, QC_TOKEN_NDBCLUSTER = 582, QC_TOKEN_NE = 583, QC_TOKEN_NE_TRIPLE = 584, QC_TOKEN_NEG = 585, QC_TOKEN_NEW = 586, QC_TOKEN_NEXT = 587, QC_TOKEN_NODEGROUP = 588, QC_TOKEN_NONE = 589, QC_TOKEN_NOT2 = 590, QC_TOKEN_NOT = 591, QC_TOKEN_NOW = 592, QC_TOKEN_NO = 593, QC_TOKEN_NO_WAIT = 594, QC_TOKEN_NO_WRITE_TO_BINLOG = 595, QC_TOKEN_NULL = 596, QC_TOKEN_NUM = 597, QC_TOKEN_NUMERIC = 598, QC_TOKEN_NVARCHAR = 599, QC_TOKEN_OFFSET = 600, QC_TOKEN_OLD_PASSWORD = 601, QC_TOKEN_ON = 602, QC_TOKEN_ONE_SHOT = 603, QC_TOKEN_ONE = 604, QC_TOKEN_OPEN = 605, QC_TOKEN_OPTIMIZE = 606, QC_TOKEN_OPTIONS = 607, QC_TOKEN_OPTION = 608, QC_TOKEN_OPTIONALLY = 609, QC_TOKEN_OR2 = 610, QC_TOKEN_ORDER = 611, QC_TOKEN_OR_OR = 612, QC_TOKEN_OR = 613, QC_TOKEN_OUTER = 614, QC_TOKEN_OUTFILE = 615, QC_TOKEN_OUT = 616, QC_TOKEN_OWNER = 617, QC_TOKEN_PACK_KEYS = 618, QC_TOKEN_PAGE = 619, QC_TOKEN_PARAM_MARKER = 620, QC_TOKEN_PARSER = 621, QC_TOKEN_PARTIAL = 622, QC_TOKEN_PARTITIONING = 623, QC_TOKEN_PARTITIONS = 624, QC_TOKEN_PARTITION = 625, QC_TOKEN_PASSWORD = 626, QC_TOKEN_PHASE = 627, QC_TOKEN_PLUGINS = 628, QC_TOKEN_PLUGIN = 629, QC_TOKEN_POINT = 630, QC_TOKEN_POLYGON = 631, QC_TOKEN_PORT = 632, QC_TOKEN_POSITION = 633, QC_TOKEN_PRECISION = 634, QC_TOKEN_PREPARE = 635, QC_TOKEN_PRESERVE = 636, QC_TOKEN_PREV = 637, QC_TOKEN_PRIMARY = 638, QC_TOKEN_PRIVILEGES = 639, QC_TOKEN_PROCEDURE = 640, QC_TOKEN_PROCESS = 641, QC_TOKEN_PROCESSLIST = 642, QC_TOKEN_PROFILE = 643, QC_TOKEN_PROFILES = 644, QC_TOKEN_PURGE = 645, QC_TOKEN_QUARTER = 646, QC_TOKEN_QUERY = 647, QC_TOKEN_QUICK = 648, QC_TOKEN_RANGE = 649, QC_TOKEN_READS = 650, QC_TOKEN_READ_ONLY = 651, QC_TOKEN_READ = 652, QC_TOKEN_READ_WRITE = 653, QC_TOKEN_REAL = 654, QC_TOKEN_REBUILD = 655, QC_TOKEN_RECOVER = 656, QC_TOKEN_REDOFILE = 657, QC_TOKEN_REDO_BUFFER_SIZE = 658, QC_TOKEN_REDUNDANT = 659, QC_TOKEN_REFERENCES = 660, QC_TOKEN_REGEXP = 661, QC_TOKEN_RELAYLOG = 662, QC_TOKEN_RELAY_LOG_FILE = 663, QC_TOKEN_RELAY_LOG_POS = 664, QC_TOKEN_RELAY_THREAD = 665, QC_TOKEN_RELEASE = 666, QC_TOKEN_RELOAD = 667, QC_TOKEN_REMOVE = 668, QC_TOKEN_RENAME = 669, QC_TOKEN_REORGANIZE = 670, QC_TOKEN_REPAIR = 671, QC_TOKEN_REPEATABLE = 672, QC_TOKEN_REPEAT = 673, QC_TOKEN_REPLACE = 674, QC_TOKEN_REPLICATION = 675, QC_TOKEN_REQUIRE = 676, QC_TOKEN_RESET = 677, QC_TOKEN_RESIGNAL = 678, QC_TOKEN_RESOURCES = 679, QC_TOKEN_RESTORE = 680, QC_TOKEN_RESTRICT = 681, QC_TOKEN_RESUME = 682, QC_TOKEN_RETURNS = 683, QC_TOKEN_RETURN = 684, QC_TOKEN_REVOKE = 685, QC_TOKEN_RIGHT = 686, QC_TOKEN_ROLLBACK = 687, QC_TOKEN_ROLLUP = 688, QC_TOKEN_ROUTINE = 689, QC_TOKEN_ROWS = 690, QC_TOKEN_ROW_FORMAT = 691, QC_TOKEN_ROW = 692, QC_TOKEN_RTREE = 693, QC_TOKEN_SAVEPOINT = 694, QC_TOKEN_SCHEDULE = 695, QC_TOKEN_SCHEMA_NAME = 696, QC_TOKEN_SECOND_MICROSECOND = 697, QC_TOKEN_SECOND = 698, QC_TOKEN_SECURITY = 699, QC_TOKEN_SELECT = 700, QC_TOKEN_SENSITIVE = 701, QC_TOKEN_SEPARATOR = 702, QC_TOKEN_SERIALIZABLE = 703, QC_TOKEN_SERIAL = 704, QC_TOKEN_SESSION = 705, QC_TOKEN_SERVER = 706, QC_TOKEN_SERVER_OPTIONS = 707, QC_TOKEN_SET = 708, QC_TOKEN_SET_VAR = 709, QC_TOKEN_SHARE = 710, QC_TOKEN_SHIFT_LEFT = 711, QC_TOKEN_SHIFT_RIGHT = 712, QC_TOKEN_SHOW = 713, QC_TOKEN_SHUTDOWN = 714, QC_TOKEN_SIGNAL = 715, QC_TOKEN_SIGNED = 716, QC_TOKEN_SIMPLE = 717, QC_TOKEN_SLAVE = 718, QC_TOKEN_SMALLINT = 719, QC_TOKEN_SNAPSHOT = 720, QC_TOKEN_SOCKET = 721, QC_TOKEN_SONAME = 722, QC_TOKEN_SOUNDS = 723, QC_TOKEN_SOURCE = 724, QC_TOKEN_SPATIAL = 725, QC_TOKEN_SPECIFIC = 726, QC_TOKEN_SQLEXCEPTION = 727, QC_TOKEN_SQLSTATE = 728, QC_TOKEN_SQLWARNING = 729, QC_TOKEN_SQL_BIG_RESULT = 730, QC_TOKEN_SQL_BUFFER_RESULT = 731, QC_TOKEN_SQL_CACHE = 732, QC_TOKEN_SQL_CALC_FOUND_ROWS = 733, QC_TOKEN_SQL_NO_CACHE = 734, QC_TOKEN_SQL_SMALL_RESULT = 735, QC_TOKEN_SQL = 736, QC_TOKEN_SQL_THREAD = 737, QC_TOKEN_SSL = 738, QC_TOKEN_STARTING = 739, QC_TOKEN_STARTS = 740, QC_TOKEN_START = 741, QC_TOKEN_STATUS = 742, QC_TOKEN_STDDEV_SAMP = 743, QC_TOKEN_STD = 744, QC_TOKEN_STOP = 745, QC_TOKEN_STORAGE = 746, QC_TOKEN_STRAIGHT_JOIN = 747, QC_TOKEN_STRING = 748, QC_TOKEN_SUBCLASS_ORIGIN = 749, QC_TOKEN_SUBDATE = 750, QC_TOKEN_SUBJECT = 751, QC_TOKEN_SUBPARTITIONS = 752, QC_TOKEN_SUBPARTITION = 753, QC_TOKEN_SUBSTRING = 754, QC_TOKEN_SUM = 755, QC_TOKEN_SUPER = 756, QC_TOKEN_SUSPEND = 757, QC_TOKEN_SWAPS = 758, QC_TOKEN_SWITCHES = 759, QC_TOKEN_SYSDATE = 760, QC_TOKEN_TABLES = 761, QC_TOKEN_TABLESPACE = 762, QC_TOKEN_TABLE_REF_PRIORITY = 763, QC_TOKEN_TABLE = 764, QC_TOKEN_TABLE_CHECKSUM = 765, QC_TOKEN_TABLE_NAME = 766, QC_TOKEN_TEMPORARY = 767, QC_TOKEN_TEMPTABLE = 768, QC_TOKEN_TERMINATED = 769, QC_TOKEN_TEXT_STRING = 770, QC_TOKEN_TEXT = 771, QC_TOKEN_THAN = 772, QC_TOKEN_THEN = 773, QC_TOKEN_TIMESTAMP = 774, QC_TOKEN_TIMESTAMP_ADD = 775, QC_TOKEN_TIMESTAMP_DIFF = 776, QC_TOKEN_TIME = 777, QC_TOKEN_TINYBLOB = 778, QC_TOKEN_TINYINT = 779, QC_TOKEN_TINYTEXT = 780, QC_TOKEN_TO = 781, QC_TOKEN_TRAILING = 782, QC_TOKEN_TRANSACTION = 783, QC_TOKEN_TRIGGERS = 784, QC_TOKEN_TRIGGER = 785, QC_TOKEN_TRIM = 786, QC_TOKEN_TRUE = 787, QC_TOKEN_TRUNCATE = 788, QC_TOKEN_TYPES = 789, QC_TOKEN_TYPE = 790, QC_TOKEN_UDF_RETURNS = 791, QC_TOKEN_ULONGLONG_NUM = 792, QC_TOKEN_UNCOMMITTED = 793, QC_TOKEN_UNDEFINED = 794, QC_TOKEN_UNDERSCORE_CHARSET = 795, QC_TOKEN_UNDOFILE = 796, QC_TOKEN_UNDO_BUFFER_SIZE = 797, QC_TOKEN_UNDO = 798, QC_TOKEN_UNICODE = 799, QC_TOKEN_UNINSTALL = 800, QC_TOKEN_UNION = 801, QC_TOKEN_UNIQUE = 802, QC_TOKEN_UNKNOWN = 803, QC_TOKEN_UNLOCK = 804, QC_TOKEN_UNSIGNED = 805, QC_TOKEN_UNTIL = 806, QC_TOKEN_UPDATE = 807, QC_TOKEN_UPGRADE = 808, QC_TOKEN_USAGE = 809, QC_TOKEN_USER = 810, QC_TOKEN_USE_FRM = 811, QC_TOKEN_USE = 812, QC_TOKEN_USING = 813, QC_TOKEN_UTC_DATE = 814, QC_TOKEN_UTC_TIMESTAMP = 815, QC_TOKEN_UTC_TIME = 816, QC_TOKEN_VALUES = 817, QC_TOKEN_VALUE = 818, QC_TOKEN_VARBINARY = 819, QC_TOKEN_VARCHAR = 820, QC_TOKEN_VARIABLES = 821, QC_TOKEN_VARIANCE = 822, QC_TOKEN_VARYING = 823, QC_TOKEN_VAR_SAMP = 824, QC_TOKEN_VIEW = 825, QC_TOKEN_WAIT = 826, QC_TOKEN_WARNINGS = 827, QC_TOKEN_WEEK = 828, QC_TOKEN_WHEN = 829, QC_TOKEN_WHERE = 830, QC_TOKEN_WHILE = 831, QC_TOKEN_WITH = 832, QC_TOKEN_WITH_CUBE = 833, QC_TOKEN_WITH_ROLLUP = 834, QC_TOKEN_WORK = 835, QC_TOKEN_WRAPPER = 836, QC_TOKEN_WRITE = 837, QC_TOKEN_X509 = 838, QC_TOKEN_XA = 839, QC_TOKEN_XML = 840, QC_TOKEN_XOR = 841, QC_TOKEN_YEAR_MONTH = 842, QC_TOKEN_YEAR = 843, QC_TOKEN_ZEROFILL = 844, QC_TOKEN_CLIENT_FLAG = 845, QC_TOKEN_GLOBAL_VAR = 846, QC_TOKEN_SESSION_VAR = 847, QC_TOKEN_BRACKET_OPEN = 848, QC_TOKEN_BRACKET_CLOSE = 849, QC_TOKEN_PLUS = 850, QC_TOKEN_MINUS = 851, QC_TOKEN_STAR = 852, QC_TOKEN_COMMA = 853, QC_TOKEN_DOT = 854, QC_TOKEN_SEMICOLON = 855, QC_TOKEN_NO_MORE = 856, QC_TOKEN_IDENTIFIER = 857, QC_TOKEN_INTNUM = 858, QC_TOKEN_FLOATNUM = 859, QC_TOKEN_ASSIGN_TO_VAR = 860, QC_TOKEN_TILDE = 861 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 1676 of yacc.c */ #line 40 "mysqlnd_query_parser.grammar" zval zv; const char * kn; /* keyword_name */ smart_str * comment; /* Line 1676 of yacc.c */ #line 666 "mysqlnd_query_parser.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif mysqlnd_ms-1.5.2/php_mysqlnd_ms.c0000664000175000017500000005317612161007456016454 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: php_mysqlnd_ms.c 329770 2013-03-13 15:28:49Z uw $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/info.h" #include "ext/mysqlnd/mysqlnd.h" #include "ext/mysqlnd/mysqlnd_debug.h" #include "ext/mysqlnd/mysqlnd_priv.h" #if PHP_VERSION_ID >= 50400 #include "ext/mysqlnd/mysqlnd_ext_plugin.h" #endif #include "mysqlnd_ms.h" #include "mysqlnd_ms_config_json.h" #include "ext/standard/php_rand.h" #include "mysqlnd_ms_filter_qos.h" #include "mysqlnd_ms_switch.h" #ifndef mnd_sprintf #define mnd_sprintf spprintf #define mnd_sprintf_free efree #endif #define STR_W_LEN(str) str, (sizeof(str) - 1) const MYSQLND_STRING mysqlnd_ms_stats_values_names[MS_STAT_LAST] = { { STR_W_LEN("use_slave") }, { STR_W_LEN("use_master") }, { STR_W_LEN("use_slave_guess") }, { STR_W_LEN("use_master_guess") }, { STR_W_LEN("use_slave_sql_hint") }, { STR_W_LEN("use_master_sql_hint") }, { STR_W_LEN("use_last_used_sql_hint") }, { STR_W_LEN("use_slave_callback") }, { STR_W_LEN("use_master_callback") }, { STR_W_LEN("non_lazy_connections_slave_success") }, { STR_W_LEN("non_lazy_connections_slave_failure") }, { STR_W_LEN("non_lazy_connections_master_success") }, { STR_W_LEN("non_lazy_connections_master_failure") }, { STR_W_LEN("lazy_connections_slave_success") }, { STR_W_LEN("lazy_connections_slave_failure") }, { STR_W_LEN("lazy_connections_master_success") }, { STR_W_LEN("lazy_connections_master_failure") }, { STR_W_LEN("trx_autocommit_on") }, { STR_W_LEN("trx_autocommit_off") }, { STR_W_LEN("trx_master_forced") }, #ifndef MYSQLND_HAS_INJECTION_FEATURE /* TODO: document */ { STR_W_LEN("gtid_autocommit_injections_success") }, { STR_W_LEN("gtid_autocommit_injections_failure") }, { STR_W_LEN("gtid_commit_injections_success") }, { STR_W_LEN("gtid_commit_injections_failure") }, { STR_W_LEN("gtid_implicit_commit_injections_success") }, { STR_W_LEN("gtid_implicit_commit_injections_failure") }, #endif }; /* }}} */ ZEND_DECLARE_MODULE_GLOBALS(mysqlnd_ms) unsigned int mysqlnd_ms_plugin_id; static zend_bool mysqlnd_ms_global_config_loaded = FALSE; struct st_mysqlnd_ms_json_config * mysqlnd_ms_json_config = NULL; /* {{{ php_mysqlnd_ms_config_init_globals */ static void php_mysqlnd_ms_config_init_globals(zend_mysqlnd_ms_globals * mysqlnd_ms_globals) { mysqlnd_ms_globals->enable = FALSE; mysqlnd_ms_globals->force_config_usage = FALSE; mysqlnd_ms_globals->config_file = NULL; mysqlnd_ms_globals->collect_statistics = FALSE; mysqlnd_ms_globals->multi_master = FALSE; mysqlnd_ms_globals->disable_rw_split = FALSE; mysqlnd_ms_globals->config_startup_error = NULL; } /* }}} */ /* {{{ PHP_GINIT_FUNCTION */ static PHP_GINIT_FUNCTION(mysqlnd_ms) { php_mysqlnd_ms_config_init_globals(mysqlnd_ms_globals); } /* }}} */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(mysqlnd_ms) { if (MYSQLND_MS_G(enable)) { MYSQLND_MS_CONFIG_JSON_LOCK(mysqlnd_ms_json_config); if (FALSE == mysqlnd_ms_global_config_loaded) { mysqlnd_ms_config_json_load_configuration(mysqlnd_ms_json_config TSRMLS_CC); mysqlnd_ms_global_config_loaded = TRUE; } MYSQLND_MS_CONFIG_JSON_UNLOCK(mysqlnd_ms_json_config); } return SUCCESS; } /* }}} */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(mysqlnd_ms) { if (MYSQLND_MS_G(enable) && MYSQLND_MS_G(config_startup_error)) { mnd_sprintf_free(MYSQLND_MS_G(config_startup_error)); } return SUCCESS; } /* }}} */ /* {{{ PHP_INI */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("mysqlnd_ms.enable", "0", PHP_INI_SYSTEM, OnUpdateBool, enable, zend_mysqlnd_ms_globals, mysqlnd_ms_globals) STD_PHP_INI_ENTRY("mysqlnd_ms.force_config_usage", "0", PHP_INI_SYSTEM, OnUpdateBool, force_config_usage, zend_mysqlnd_ms_globals, mysqlnd_ms_globals) STD_PHP_INI_ENTRY("mysqlnd_ms.config_file", NULL, PHP_INI_SYSTEM, OnUpdateString, config_file, zend_mysqlnd_ms_globals, mysqlnd_ms_globals) STD_PHP_INI_ENTRY("mysqlnd_ms.collect_statistics", "0", PHP_INI_SYSTEM, OnUpdateBool, collect_statistics, zend_mysqlnd_ms_globals, mysqlnd_ms_globals) STD_PHP_INI_ENTRY("mysqlnd_ms.multi_master", "0", PHP_INI_SYSTEM, OnUpdateBool, multi_master, zend_mysqlnd_ms_globals, mysqlnd_ms_globals) STD_PHP_INI_ENTRY("mysqlnd_ms.disable_rw_split", "0", PHP_INI_SYSTEM, OnUpdateBool, disable_rw_split, zend_mysqlnd_ms_globals, mysqlnd_ms_globals) PHP_INI_END() /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(mysqlnd_ms) { ZEND_INIT_MODULE_GLOBALS(mysqlnd_ms, php_mysqlnd_ms_config_init_globals, NULL); REGISTER_INI_ENTRIES(); if (MYSQLND_MS_G(enable)) { mysqlnd_ms_plugin_id = mysqlnd_plugin_register(); mysqlnd_ms_register_hooks(); mysqlnd_stats_init(&mysqlnd_ms_stats, MS_STAT_LAST); mysqlnd_ms_json_config = mysqlnd_ms_config_json_init(TSRMLS_C); } REGISTER_STRING_CONSTANT("MYSQLND_MS_VERSION", MYSQLND_MS_VERSION, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_VERSION_ID", MYSQLND_MS_VERSION_ID, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("MYSQLND_MS_MASTER_SWITCH", MASTER_SWITCH, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("MYSQLND_MS_SLAVE_SWITCH", SLAVE_SWITCH, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("MYSQLND_MS_LAST_USED_SWITCH", LAST_USED_SWITCH, CONST_CS | CONST_PERSISTENT); #ifdef ALL_SERVER_DISPATCH REGISTER_STRING_CONSTANT("MYSQLND_MS_ALL_SERVER_SWITCH", ALL_SERVER_SWITCH, CONST_CS | CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("MYSQLND_MS_QUERY_USE_MASTER", USE_MASTER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QUERY_USE_SLAVE", USE_SLAVE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QUERY_USE_LAST_USED", USE_LAST_USED, CONST_CS | CONST_PERSISTENT); #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION REGISTER_LONG_CONSTANT("MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION", 1, CONST_CS | CONST_PERSISTENT); #endif #ifdef MYSQLND_MS_HAVE_MYSQLND_QC REGISTER_LONG_CONSTANT("MYSQLND_MS_HAVE_CACHE_SUPPORT", 1, CONST_CS | CONST_PERSISTENT); #endif #if PHP_VERSION_ID >= 50399 REGISTER_LONG_CONSTANT("MYSQLND_MS_QOS_CONSISTENCY_STRONG", CONSISTENCY_STRONG, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QOS_CONSISTENCY_SESSION", CONSISTENCY_SESSION, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL", CONSISTENCY_EVENTUAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QOS_OPTION_GTID", QOS_OPTION_GTID, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QOS_OPTION_AGE", QOS_OPTION_AGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLND_MS_QOS_OPTION_CACHE", QOS_OPTION_CACHE, CONST_CS | CONST_PERSISTENT); #endif return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(mysqlnd_ms) { UNREGISTER_INI_ENTRIES(); if (MYSQLND_MS_G(enable)) { mysqlnd_stats_end(mysqlnd_ms_stats); mysqlnd_ms_config_json_free(mysqlnd_ms_json_config TSRMLS_CC); mysqlnd_ms_json_config = NULL; } return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(mysqlnd_ms) { char buf[64]; php_info_print_table_start(); php_info_print_table_header(2, "mysqlnd_ms support", "enabled"); snprintf(buf, sizeof(buf), "%s (%d)", MYSQLND_MS_VERSION, MYSQLND_MS_VERSION_ID); php_info_print_table_row(2, "Mysqlnd master/slave plugin version", buf); php_info_print_table_row(2, "Plugin active", MYSQLND_MS_G(enable) ? "yes" : "no"); #if PHP_VERSION_ID >= 50399 php_info_print_table_row(2, "Transaction mode trx_stickiness supported", "yes"); php_info_print_table_row(2, "mysqlnd_ms_get_last_used_connection() supported", "yes"); php_info_print_table_row(2, "mysqlnd_ms_set_qos() supported", "yes"); #else php_info_print_table_row(2, "Transaction mode trx_stickiness supported", "no"); php_info_print_table_row(2, "mysqlnd_ms_get_last_used_connection() supported", "no"); php_info_print_table_row(2, "mysqlnd_ms_set_qos() supported", "no"); #endif php_info_print_table_row(2, "Table partitioning filter supported", #ifdef MYSQLND_MS_HAVE_FILTER_TABLE_PARTITION "yes" #else "no" #endif ); php_info_print_table_row(2, "Query caching through mysqlnd_qc supported", #ifdef MYSQLND_MS_HAVE_MYSQLND_QC "yes" #else "no" #endif ); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqlnd_ms_match_wild, 0, 0, 2) ZEND_ARG_INFO(0, haystack) ZEND_ARG_INFO(0, wild) ZEND_END_ARG_INFO() /* {{{ proto long mysqlnd_ms_match_wild(string haystack, string wild) */ static PHP_FUNCTION(mysqlnd_ms_match_wild) { char * str; char * wild; int tmp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &str, &tmp, &wild, &tmp) == FAILURE) { return; } RETURN_BOOL(mysqlnd_ms_match_wild(str, wild TSRMLS_CC)); } /* }}} */ #if PHP_VERSION_ID > 50399 ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqlnd_ms_get_last_used_connection, 0, 0, 1) ZEND_ARG_INFO(0, object) ZEND_END_ARG_INFO() /* {{{ proto array mysqlnd_ms_get_last_used_connection(object handle) */ static PHP_FUNCTION(mysqlnd_ms_get_last_used_connection) { zval * handle; MYSQLND * proxy_conn; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &handle) == FAILURE) { return; } if (!(proxy_conn = zval_to_mysqlnd(handle TSRMLS_CC))) { RETURN_FALSE; } { MYSQLND_MS_CONN_DATA ** conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(proxy_conn->data, mysqlnd_ms_plugin_id); const MYSQLND_CONN_DATA * conn = (conn_data && (*conn_data) && (*conn_data)->stgy.last_used_conn)? (*conn_data)->stgy.last_used_conn:proxy_conn->data; array_init(return_value); add_assoc_string_ex(return_value, "scheme", sizeof("scheme"), conn->scheme? conn->scheme:"", 1); add_assoc_string_ex(return_value, "host_info", sizeof("host_info"), conn->host_info? conn->host_info:"", 1); add_assoc_string_ex(return_value, "host", sizeof("host"), conn->host? conn->host:"", 1); add_assoc_long_ex(return_value, "port", sizeof("port"), conn->port); add_assoc_string_ex(return_value, "socket_or_pipe", sizeof("socket_or_pipe"), conn->unix_socket? conn->unix_socket:"", 1); add_assoc_long_ex(return_value, "thread_id", sizeof("thread_id"), conn->thread_id); add_assoc_string_ex(return_value, "last_message", sizeof("last_message"), conn->last_message? conn->last_message:"", 1); add_assoc_long_ex(return_value, "errno", sizeof("errno"), MYSQLND_MS_ERROR_INFO(conn).error_no); add_assoc_string_ex(return_value, "error", sizeof("error"), (char *) MYSQLND_MS_ERROR_INFO(conn).error, 1); add_assoc_string_ex(return_value, "sqlstate", sizeof("sqlstate"), (char *) MYSQLND_MS_ERROR_INFO(conn).sqlstate, 1); } } /* }}} */ ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqlnd_ms_get_last_gtid, 0, 0, 1) ZEND_ARG_INFO(0, object) ZEND_END_ARG_INFO() /* {{{ proto string mysqlnd_ms_last_gtid(object handle) */ static PHP_FUNCTION(mysqlnd_ms_get_last_gtid) { zval * handle; MYSQLND * proxy_conn; MYSQLND_CONN_DATA * conn = NULL; MYSQLND_MS_CONN_DATA ** conn_data = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &handle) == FAILURE) { return; } if (!(proxy_conn = zval_to_mysqlnd(handle TSRMLS_CC))) { RETURN_FALSE; } { MYSQLND_RES * res = NULL; zval * row; zval ** gtid; conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(proxy_conn->data, mysqlnd_ms_plugin_id); if (!conn_data || !(*conn_data)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " No mysqlnd_ms connection or no statement has been run yet"); RETURN_FALSE; } if (!(*conn_data)->stgy.last_used_conn) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " No mysqlnd_ms connection or no ID has been injected yet"); RETURN_FALSE; } conn = (*conn_data)->stgy.last_used_conn; MS_LOAD_CONN_DATA(conn_data, conn); if (!conn_data || !(*conn_data)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to fetch plugin data. Please report a bug"); RETURN_FALSE; } if (!(*conn_data)->global_trx.fetch_last_gtid) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL to fetch last global transaction ID is not set"); RETURN_FALSE; } (*conn_data)->skip_ms_calls = TRUE; if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(send_query)(conn, (*conn_data)->global_trx.fetch_last_gtid, (*conn_data)->global_trx.fetch_last_gtid_len TSRMLS_CC)) { goto getlastidfailure; } if (PASS != MS_CALL_ORIGINAL_CONN_DATA_METHOD(reap_query)(conn TSRMLS_CC)) { goto getlastidfailure; } if (!(res = MS_CALL_ORIGINAL_CONN_DATA_METHOD(store_result)(conn TSRMLS_CC))) { goto getlastidfailure; } (*conn_data)->skip_ms_calls = FALSE; MAKE_STD_ZVAL(row); mysqlnd_fetch_into(res, MYSQLND_FETCH_NUM, row, MYSQLND_MYSQL); if (Z_TYPE_P(row) != IS_ARRAY) { zval_ptr_dtor(&row); res->m.free_result(res, FALSE TSRMLS_CC); RETURN_FALSE; } if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(row), 0, (void**)>id)) { char gtid_str[64]; strncpy(gtid_str, Z_STRVAL_PP(gtid), sizeof(gtid_str) - 1); zval_ptr_dtor(&row); res->m.free_result(res, FALSE TSRMLS_CC); RETURN_STRING(gtid_str, 1); } else { /* no error code set on line, we need to bail explicitly */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read GTID from result set. Please report a bug"); } } getlastidfailure: if (conn_data && (*conn_data)) { (*conn_data)->skip_ms_calls = FALSE; } RETURN_FALSE; } /* }}} */ ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqlnd_ms_set_qos, 0, 0, 2) ZEND_ARG_INFO(0, object) ZEND_ARG_INFO(0, service_level) ZEND_ARG_INFO(0, option) ZEND_ARG_INFO(0, option_value) ZEND_END_ARG_INFO() /* {{{ proto bool mysqlnd_ms_set_qos) */ static PHP_FUNCTION(mysqlnd_ms_set_qos) { zval * handle; double option; zval * option_value = NULL; double service_level; MYSQLND * proxy_conn; MYSQLND_MS_FILTER_QOS_OPTION_DATA option_data; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zd|dz!", &handle, &service_level, &option, &option_value) == FAILURE) { return; } if (ZEND_NUM_ARGS() > 2) { switch ((int)option) { case QOS_OPTION_GTID: if (service_level != CONSISTENCY_SESSION) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "GTID option value must be used with MYSQLND_MS_QOS_CONSISTENCY_SESSION only"); RETURN_FALSE; } if (!option_value) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option value required"); RETURN_FALSE; } if ((Z_TYPE_P(option_value) != IS_STRING) && (Z_TYPE_P(option_value) != IS_LONG) && (Z_TYPE_P(option_value) != IS_DOUBLE)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "GTID must be a number or a string"); } convert_to_string(option_value); option_data.gtid_len = spprintf(&(option_data.gtid), 0, "%s", Z_STRVAL_P(option_value)); if (0 == option_data.gtid_len) { efree(option_data.gtid); php_error_docref(NULL TSRMLS_CC, E_WARNING, "GTID is empty"); RETURN_FALSE; } break; case QOS_OPTION_AGE: if (service_level != CONSISTENCY_EVENTUAL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum age option value must be used with MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL only"); RETURN_FALSE; } if (!option_value) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option value required"); RETURN_FALSE; } convert_to_long(option_value); option_data.age = Z_LVAL_P(option_value); if (option_data.age < 0L) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum age must have a positive value"); RETURN_FALSE; } break; case QOS_OPTION_CACHE: #ifdef MYSQLND_MS_HAVE_MYSQLND_QC if (service_level != CONSISTENCY_EVENTUAL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache TTL option value must be used with MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL only"); RETURN_FALSE; } if (!option_value) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option value required"); RETURN_FALSE; } convert_to_long(option_value); option_data.ttl = (uint)Z_LVAL_P(option_value); if (option_data.ttl < 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache TTL must be at least one"); RETURN_FALSE; } #else php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache support is not available with this build"); RETURN_FALSE; #endif break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option"); RETURN_FALSE; break; } } else { option = QOS_OPTION_NONE; } if (!(proxy_conn = zval_to_mysqlnd(handle TSRMLS_CC))) { RETURN_FALSE; } { MYSQLND_MS_CONN_DATA ** conn_data = NULL; conn_data = (MYSQLND_MS_CONN_DATA **) mysqlnd_plugin_get_plugin_connection_data_data(proxy_conn->data, mysqlnd_ms_plugin_id); if (!conn_data || !(*conn_data)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " No mysqlnd_ms connection"); RETURN_FALSE; } if ((*conn_data)->stgy.in_transaction && (*conn_data)->stgy.trx_stop_switching) { php_error_docref(NULL TSRMLS_CC, E_WARNING, MYSQLND_MS_ERROR_PREFIX " No change allowed in the middle of a transaction"); RETURN_FALSE; } } switch ((int)service_level) { case CONSISTENCY_STRONG: if (PASS == mysqlnd_ms_section_filters_prepend_qos(proxy_conn, (enum mysqlnd_ms_filter_qos_consistency)service_level, (enum mysqlnd_ms_filter_qos_option)option, &option_data TSRMLS_CC)) RETURN_TRUE; break; case CONSISTENCY_EVENTUAL: /* GTID is free'd by the function called */ if (PASS == mysqlnd_ms_section_filters_prepend_qos(proxy_conn, (enum mysqlnd_ms_filter_qos_consistency)service_level, (enum mysqlnd_ms_filter_qos_option)option, &option_data TSRMLS_CC)) RETURN_TRUE; break; case CONSISTENCY_SESSION: if (PASS == mysqlnd_ms_section_filters_prepend_qos(proxy_conn, (enum mysqlnd_ms_filter_qos_consistency)service_level, (enum mysqlnd_ms_filter_qos_option)option, &option_data TSRMLS_CC)) RETURN_TRUE; break; default: /* TODO: decide wheter warning, error or nothing */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid service level"); RETURN_FALSE; break; } RETURN_FALSE; } #endif ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqlnd_ms_query_is_select, 0, 0, 1) ZEND_ARG_INFO(0, query) ZEND_END_ARG_INFO() /* {{{ proto long mysqlnd_ms_query_is_select(string query) Parse query and propose where to send it */ static PHP_FUNCTION(mysqlnd_ms_query_is_select) { char * query; int query_len; zend_bool forced; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) { return; } RETURN_LONG(mysqlnd_ms_query_is_select(query, query_len, &forced TSRMLS_CC)); } /* }}} */ ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqlnd_ms_get_stats, 0, 0, 0) ZEND_END_ARG_INFO() /* {{{ proto array mysqlnd_ms_get_stats() Return statistics on connections and queries */ static PHP_FUNCTION(mysqlnd_ms_get_stats) { DBG_ENTER("mysqlnd_ms_get_stats"); if (zend_parse_parameters_none() == FAILURE) { DBG_VOID_RETURN; } if (!MYSQLND_MS_G(enable)) { DBG_VOID_RETURN; } mysqlnd_fill_stats_hash(mysqlnd_ms_stats, mysqlnd_ms_stats_values_names, return_value TSRMLS_CC ZEND_FILE_LINE_CC); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_ms_deps[] */ static const zend_module_dep mysqlnd_ms_deps[] = { ZEND_MOD_REQUIRED("mysqlnd") ZEND_MOD_REQUIRED("standard") ZEND_MOD_REQUIRED("json") #ifdef MYSQLND_MS_HAVE_MYSQLND_QC ZEND_MOD_REQUIRED("mysqlnd_qc") #else /* ensure proper plugin load order for lazy */ ZEND_MOD_OPTIONAL("mysqlnd_qc") #endif {NULL, NULL, NULL} }; /* }}} */ /* {{{ mysqlnd_ms_functions */ static const zend_function_entry mysqlnd_ms_functions[] = { PHP_FE(mysqlnd_ms_match_wild, arginfo_mysqlnd_ms_match_wild) PHP_FE(mysqlnd_ms_query_is_select, arginfo_mysqlnd_ms_query_is_select) PHP_FE(mysqlnd_ms_get_stats, arginfo_mysqlnd_ms_get_stats) #if PHP_VERSION_ID > 50399 PHP_FE(mysqlnd_ms_get_last_used_connection, arginfo_mysqlnd_ms_get_last_used_connection) PHP_FE(mysqlnd_ms_get_last_gtid, arginfo_mysqlnd_ms_get_last_gtid) PHP_FE(mysqlnd_ms_set_qos, arginfo_mysqlnd_ms_set_qos) #endif {NULL, NULL, NULL} /* Must be the last line in mysqlnd_ms_functions[] */ }; /* }}} */ /* {{{ mysqlnd_ms_module_entry */ zend_module_entry mysqlnd_ms_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, mysqlnd_ms_deps, "mysqlnd_ms", mysqlnd_ms_functions, PHP_MINIT(mysqlnd_ms), PHP_MSHUTDOWN(mysqlnd_ms), PHP_RINIT(mysqlnd_ms), PHP_RSHUTDOWN(mysqlnd_ms), PHP_MINFO(mysqlnd_ms), MYSQLND_MS_VERSION, PHP_MODULE_GLOBALS(mysqlnd_ms), PHP_GINIT(mysqlnd_ms), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ #ifdef COMPILE_DL_MYSQLND_MS ZEND_GET_MODULE(mysqlnd_ms) #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/php_mysqlnd_ms.h0000664000175000017500000000321412161007456016445 0ustar andreyandrey/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2008 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Andrey Hristov | | Ulf Wendel | | Johannes Schlueter | +----------------------------------------------------------------------+ */ /* $Id: php_mysqlnd_ms.h 310972 2011-05-12 14:32:53Z johannes $ */ #ifndef PHP_MYSQLND_MS_H #define PHP_MYSQLND_MS_H extern zend_module_entry mysqlnd_ms_module_entry; #define phpext_mysqlnd_ms_ptr &mysqlnd_ms_module_entry #endif /* PHP_MYSQLND_MS_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ mysqlnd_ms-1.5.2/README0000664000175000017500000000716312161007456014126 0ustar andreyandreyIntroduction ============ The mysqlnd replication and load balancing plugin (mysqlnd_ms) adds easy to use MySQL replication support to all PHP MySQL extensions that use mysqlnd. As of version PHP 5.3.3 the MySQL native driver for PHP (mysqlnd) features an internal plugin C API. C plugins, such as the replication and load balancing plugin, can extend the functionality of mysqlnd. The MySQL native driver for PHP is a C library which ships together with PHP as of PHP 5.3.0. It serves as a drop-in replacement for the MySQL Client Library (AKA libmysql/libmysqlclient). Using mysqlnd has several advantages: no extra downloads because it comes with PHP, PHP license, lower memory consumption in certain cases, new functionality such as asynchronous queries. Mysqlnd plugins such as the replication and load balancing plugin operate mostly transparent from an user perspective. The replication and load balancing plugin supports all PHP applications and all PHP MySQL extensions ( mysqli, mysql, PDO_MYSQL). It does not change existing APIs. Therefore, it can easily be used with existing PHP applications. Key Features ============ * Transparent and therefore easy to use o supports all PHP MySQL extensions o no API changes o very little, if any, application changes required, dependent on the usage scenario required * Featured read-write split strategies o Automatic detection of SELECT, supports SQL hints to overrule automatism o user-defined * Featured load balancing strategies o Round Robin: choose different slave in round robin fashion for every slave request. o Random: choose random slave for every slave request. o Random once (sticky): choose random slave once to run all slave requests for the duration of a web request. o User-defined. The application can register callbacks with mysqlnd_ms. Limitations =========== The built-in read/write-split mechanism is very basic. Every query which starts with SELECT is considered a read request to be sent to a MySQL slave server. All other queries, including, for example, SHOW statements, are considered as write requests to be sent to the MySQL master server. The build-in behaviour can be overruled using SQL hints or an user-defined callback function. The read/write splitter is not aware of multi-statements. Multi-statements are considered as one statement. The decision of where to run the statement will be based on the beginning of the statement string. The plugin does not support native prepared statements. Please note that PDO_MySQL is using a client-side prepared statement emulation by default. Client-side emulated prepared statements are fully supported by the replication and load balancing plugin because the emulation is not using native prepared statements. If you are using PHP based database abstraction, please consult the vendor manual to learn if a client-side prepared statement emulation is used. On the name =========== The shortcut mysqlnd_ms stands for mysqlnd master slave plugin. The name was choosen for a quick-and-dirty proof-of-concept. In the beginning the developers did not expect to continue using the code base. Installation ============ If your system has the PEAR and PECL tools installed this plugin can be installed by a single command from the command line. If you want to use the stable version: # pecl install mysqlnd_ms If you want to use an alpha version: # pecl install mysqlnd_ms-alpha Further information =================== Please refer to the full documentation on http://php.net/mysqlnd_ms
$bin_label ($bin_file)
$output