diff --git a/.github/workflows/wp-tests-phpunit-native-extension-setup.sh b/.github/workflows/wp-tests-phpunit-native-extension-setup.sh index 943b06c59..956c60737 100644 --- a/.github/workflows/wp-tests-phpunit-native-extension-setup.sh +++ b/.github/workflows/wp-tests-phpunit-native-extension-setup.sh @@ -149,7 +149,7 @@ if ( ! ( $parser_ast instanceof WP_MySQL_Native_Parser_Node ) ) { wp_sqlite_native_parser_verification_fail( 'Native parser did not produce a native-backed AST in the WordPress PHP test container.' ); } -$driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); +$driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); $parser = $driver->create_parser( 'SELECT 1' ); wp_sqlite_assert_native_parser_delegate( $parser, 'WordPress PHP test container SQLite driver did not create a native parser delegate.' ); $parser->next_query(); diff --git a/packages/mysql-on-sqlite/src/load.php b/packages/mysql-on-sqlite/src/load.php index 62387a2e7..810f24df0 100644 --- a/packages/mysql-on-sqlite/src/load.php +++ b/packages/mysql-on-sqlite/src/load.php @@ -3,7 +3,7 @@ define( 'WP_MYSQL_ON_SQLITE_LOADER_PATH', __FILE__ ); /** - * Load the PDO MySQL-on-SQLite driver and its dependencies. + * Load the MySQL-on-SQLite driver and its dependencies. */ require_once __DIR__ . '/php-polyfills.php'; require_once __DIR__ . '/version.php'; @@ -35,11 +35,10 @@ } require_once __DIR__ . '/sqlite/class-wp-sqlite-connection.php'; require_once __DIR__ . '/sqlite/class-wp-sqlite-configurator.php'; -require_once __DIR__ . '/sqlite/class-wp-sqlite-driver.php'; require_once __DIR__ . '/sqlite/class-wp-sqlite-driver-exception.php'; require_once __DIR__ . '/sqlite/class-wp-sqlite-information-schema-builder.php'; require_once __DIR__ . '/sqlite/class-wp-sqlite-information-schema-exception.php'; require_once __DIR__ . '/sqlite/class-wp-sqlite-information-schema-reconstructor.php'; require_once __DIR__ . '/sqlite/class-wp-sqlite-pdo-user-defined-functions.php'; -require_once __DIR__ . '/sqlite/class-wp-pdo-mysql-on-sqlite.php'; +require_once __DIR__ . '/sqlite/class-wp-mysql-on-sqlite.php'; require_once __DIR__ . '/sqlite/class-wp-pdo-proxy-statement.php'; diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php similarity index 99% rename from packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php rename to packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php index cdb8698ee..2b66b6b7a 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-mysql-on-sqlite.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php @@ -14,7 +14,7 @@ * * The driver requires PDO with the SQLite driver, and the PCRE engine. */ -class WP_PDO_MySQL_On_SQLite extends PDO { +class WP_MySQL_On_SQLite extends PDO { /** * The path to the MySQL SQL grammar file. */ @@ -4211,7 +4211,7 @@ private function translate_query_expression( WP_Parser_Node $node ): string { * When the ORDER BY clause is present, we need to disambiguate the item * list and make sure they don't cause an "ambiguous column name" error. * - * @see WP_SQLite_Driver::disambiguate_item() + * @see WP_MySQL_On_SQLite::disambiguate_item() */ $disambiguated_order_list = array(); $order_clause = $node->get_first_child_node( 'orderClause' ); @@ -4279,7 +4279,7 @@ private function translate_query_specification( WP_Parser_Node $node ): string { * When the GROUP BY or HAVING clause is present, we need to disambiguate * the items to ensure they don't cause an "ambiguous column name" error. * - * @see WP_SQLite_Driver::disambiguate_item() + * @see WP_MySQL_On_SQLite::disambiguate_item() */ $group_by_clause = null; $having_clause = null; @@ -5767,7 +5767,7 @@ private function unnest_parenthesized_expression( WP_Parser_Node $node ): WP_Par * consider column references in forms like "db.table.column". * * @param array $disambiguation_map The SELECT item disambiguation map (column name => array of select items). - * @see WP_SQLite_Driver::create_select_item_disambiguation_map() + * @see WP_MySQL_On_SQLite::create_select_item_disambiguation_map() * @param WP_Parser_Node $expr The expression AST node or subnode. * @return string|null The disambiguated and translated expression; * null when the expression cannot be disambiguated. @@ -5806,7 +5806,7 @@ private function disambiguate_item( array $disambiguation_map, WP_Parser_Node $e * Create a SELECT item disambiguation map from a SELECT item list for use * with the ORDER BY, GROUP BY, and HAVING clause disambiguation algorithm. * - * @see WP_SQLite_Driver::disambiguate_item() + * @see WP_MySQL_On_SQLite::disambiguate_item() * * @param WP_Parser_Node $select_item_list The "selectItemList" AST node. * @return array The SELECT item disambiguation map (column name => array of select items). diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-configurator.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-configurator.php index 057ac2eda..280cfc283 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-configurator.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-configurator.php @@ -14,7 +14,7 @@ class WP_SQLite_Configurator { /** * The SQLite driver instance. * - * @var WP_PDO_MySQL_On_SQLite + * @var WP_MySQL_On_SQLite */ private $driver; @@ -35,11 +35,11 @@ class WP_SQLite_Configurator { /** * Constructor. * - * @param WP_PDO_MySQL_On_SQLite $driver The SQLite driver instance. + * @param WP_MySQL_On_SQLite $driver The SQLite driver instance. * @param WP_SQLite_Information_Schema_Builder $schema_builder The information schema builder instance. */ public function __construct( - WP_PDO_MySQL_On_SQLite $driver, + WP_MySQL_On_SQLite $driver, WP_SQLite_Information_Schema_Builder $schema_builder ) { $this->driver = $driver; @@ -100,7 +100,7 @@ private function ensure_global_variables_table(): void { sprintf( 'CREATE TABLE IF NOT EXISTS %s (name TEXT PRIMARY KEY, value TEXT)', $this->driver->get_connection()->quote_identifier( - WP_PDO_MySQL_On_SQLite::GLOBAL_VARIABLES_TABLE_NAME + WP_MySQL_On_SQLite::GLOBAL_VARIABLES_TABLE_NAME ) ) ); @@ -260,11 +260,11 @@ private function save_current_driver_version(): void { sprintf( 'INSERT INTO %s (name, value) VALUES (?, ?) ON CONFLICT(name) DO UPDATE SET value = ?', $this->driver->get_connection()->quote_identifier( - WP_PDO_MySQL_On_SQLite::GLOBAL_VARIABLES_TABLE_NAME + WP_MySQL_On_SQLite::GLOBAL_VARIABLES_TABLE_NAME ) ), array( - WP_PDO_MySQL_On_SQLite::DRIVER_VERSION_VARIABLE_NAME, + WP_MySQL_On_SQLite::DRIVER_VERSION_VARIABLE_NAME, SQLITE_DRIVER_VERSION, SQLITE_DRIVER_VERSION, ) diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver-exception.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver-exception.php index c43aec8ad..26a01ad2f 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver-exception.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver-exception.php @@ -4,20 +4,20 @@ class WP_SQLite_Driver_Exception extends PDOException { /** * The SQLite driver that originated the exception. * - * @var WP_PDO_MySQL_On_SQLite + * @var WP_MySQL_On_SQLite */ private $driver; /** * Constructor. * - * @param WP_PDO_MySQL_On_SQLite $driver The SQLite driver that originated the exception. + * @param WP_MySQL_On_SQLite $driver The SQLite driver that originated the exception. * @param string $message The exception message. * @param int|string $code The exception code. In PDO, it can be a string with value of SQLSTATE. * @param Throwable|null $previous The previous throwable used for the exception chaining. */ public function __construct( - WP_PDO_MySQL_On_SQLite $driver, + WP_MySQL_On_SQLite $driver, string $message, $code = 0, ?Throwable $previous = null @@ -27,7 +27,7 @@ public function __construct( $this->driver = $driver; } - public function getDriver(): WP_PDO_MySQL_On_SQLite { + public function getDriver(): WP_MySQL_On_SQLite { return $this->driver; } } diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver.php deleted file mode 100644 index bb3b68125..000000000 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver.php +++ /dev/null @@ -1,280 +0,0 @@ -dbh->client_info" - a mysqli-specific abstraction leak. - * - * @TODO: This should be fixed in WordPress core. - * - * See: - * https://github.com/WordPress/wordpress-develop/blob/bcdca3f9925f1d3eca7b78d231837c0caf0c8c24/src/wp-admin/includes/class-wp-debug-data.php#L1579 - * - * @var string - */ - public $client_info; - - /** - * The MySQL-on-SQLite driver instance. - * - * @var WP_PDO_MySQL_On_SQLite - */ - private $mysql_on_sqlite_driver; - - /** - * Results of the last emulated query. - * - * @var mixed - */ - private $last_result; - - /** - * Constructor. - * - * Set up an SQLite connection and the MySQL-on-SQLite driver. - * - * @param WP_SQLite_Connection $connection A SQLite database connection. - * @param string $database The database name. - * - * @throws WP_SQLite_Driver_Exception When the driver initialization fails. - */ - public function __construct( - WP_SQLite_Connection $connection, - string $database, - int $mysql_version = 80038 - ) { - $this->mysql_on_sqlite_driver = new WP_PDO_MySQL_On_SQLite( - sprintf( 'mysql-on-sqlite:dbname=%s', $database ), - null, - null, - array( - 'mysql_version' => $mysql_version, - 'pdo' => $connection->get_pdo(), - 'journal_mode' => $connection->query( 'PRAGMA journal_mode' )->fetchColumn(), - ) - ); - $this->main_db_name = $database; - $this->client_info = $this->mysql_on_sqlite_driver->client_info; - - $connection->get_pdo()->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); - } - - /** - * Get the SQLite connection instance. - * - * @return WP_SQLite_Connection - */ - public function get_connection(): WP_SQLite_Connection { - return $this->mysql_on_sqlite_driver->get_connection(); - } - - /** - * Get the version of the SQLite engine. - * - * @return string SQLite engine version as a string. - */ - public function get_sqlite_version(): string { - return $this->mysql_on_sqlite_driver->get_sqlite_version(); - } - - /** - * Get the SQLite driver version saved in the database. - * - * The saved driver version corresponds to the latest version of the SQLite - * driver that was used to initialize and configure the SQLite database. - * - * @return string SQLite driver version as a string. - * @throws PDOException When the query execution fails. - */ - public function get_saved_driver_version(): string { - return $this->mysql_on_sqlite_driver->get_saved_driver_version(); - } - - /** - * Check if a specific SQL mode is active. - * - * @param string $mode The SQL mode to check. - * @return bool True if the SQL mode is active, false otherwise. - */ - public function is_sql_mode_active( string $mode ): bool { - return $this->mysql_on_sqlite_driver->is_sql_mode_active( $mode ); - } - - /** - * Get the last executed MySQL query. - * - * @return string|null - */ - public function get_last_mysql_query(): ?string { - return $this->mysql_on_sqlite_driver->get_last_mysql_query(); - } - - /** - * Get SQLite queries executed for the last MySQL query. - * - * @return array{ sql: string, params: array }[] - */ - public function get_last_sqlite_queries(): array { - return $this->mysql_on_sqlite_driver->get_last_sqlite_queries(); - } - - /** - * Get the auto-increment value generated for the last query. - * - * @return int|string - */ - public function get_insert_id() { - return $this->mysql_on_sqlite_driver->get_insert_id(); - } - - /** - * @param string $query Full SQL statement string. - * @param int $fetch_mode PDO fetch mode. Default is PDO::FETCH_OBJ. - * @param array ...$fetch_mode_args Additional fetch mode arguments. - * - * @return mixed Return value, depending on the query type. - * - * @throws WP_SQLite_Driver_Exception When the query execution fails. - */ - public function query( string $query, $fetch_mode = PDO::FETCH_OBJ, ...$fetch_mode_args ) { - $stmt = $this->mysql_on_sqlite_driver->query( $query, $fetch_mode, ...$fetch_mode_args ); - - if ( $stmt->columnCount() > 0 ) { - $this->last_result = $stmt->fetchAll( $fetch_mode ); - } else { - $this->last_result = $stmt->rowCount(); - } - return $this->last_result; - } - - /** - * Tokenize a MySQL query and initialize a parser. - * - * @param string $query The MySQL query to parse. - * @return WP_MySQL_Parser A parser initialized for the MySQL query. - */ - public function create_parser( string $query ): WP_MySQL_Parser { - return $this->mysql_on_sqlite_driver->create_parser( $query ); - } - - /** - * Get results of the last query. - * - * @return mixed - */ - public function get_query_results() { - return $this->last_result; - } - - /** - * Get return value of the last query() function call. - * - * @return mixed - */ - public function get_last_return_value() { - return $this->last_result; - } - - /** - * Get the number of columns returned by the last emulated query. - * - * @return int - */ - public function get_last_column_count(): int { - return $this->mysql_on_sqlite_driver->get_last_column_count(); - } - - /** - * Get column metadata for results of the last emulated query. - * - * @return array - */ - public function get_last_column_meta(): array { - return $this->mysql_on_sqlite_driver->get_last_column_meta(); - } - - /** - * Execute a query in SQLite. - * - * @param string $sql The query to execute. - * @param array $params The query parameters. - * @throws PDOException When the query execution fails. - * @return PDOStatement The PDO statement object. - */ - public function execute_sqlite_query( string $sql, array $params = array() ): PDOStatement { - return $this->mysql_on_sqlite_driver->execute_sqlite_query( $sql, $params ); - } - - /** - * Begin a new transaction or nested transaction. - */ - public function beginTransaction(): void { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid - $this->mysql_on_sqlite_driver->begin_transaction(); - } - - /** - * A temporary alias for back compatibility. - * - * @see self::beginTransaction() - */ - public function begin_transaction(): void { - $this->beginTransaction(); - } - - /** - * Commit the current transaction or nested transaction. - */ - public function commit(): void { - $this->mysql_on_sqlite_driver->commit(); - } - - /** - * Rollback the current transaction or nested transaction. - */ - public function rollback(): void { - $this->mysql_on_sqlite_driver->rollback(); - } - - /** - * Proxy also the private property "$main_db_name", as it is used in tests. - */ - public function __set( string $name, $value ): void { - if ( 'main_db_name' === $name ) { - $closure = function ( string $value ) { - $this->main_db_name = $value; - }; - $closure->call( $this->mysql_on_sqlite_driver, $value ); - } - } - - /** - * Proxy also this private method, as it is used in tests. - */ - private function quote_mysql_utf8_string_literal( string $utf8_literal ): string { - $closure = function ( string $utf8_literal ) { - return $this->quote_mysql_utf8_string_literal( $utf8_literal ); - }; - return $closure->call( $this->mysql_on_sqlite_driver, $utf8_literal ); - } -} diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-reconstructor.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-reconstructor.php index 57a40f8f2..3b60b1fc1 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-reconstructor.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-reconstructor.php @@ -19,7 +19,7 @@ class WP_SQLite_Information_Schema_Reconstructor { /** * The SQLite driver instance. * - * @var WP_PDO_MySQL_On_SQLite + * @var WP_MySQL_On_SQLite */ private $driver; @@ -40,7 +40,7 @@ class WP_SQLite_Information_Schema_Reconstructor { /** * Constructor. * - * @param WP_PDO_MySQL_On_SQLite $driver The SQLite driver instance. + * @param WP_MySQL_On_SQLite $driver The SQLite driver instance. * @param WP_SQLite_Information_Schema_Builder $schema_builder The information schema builder instance. */ public function __construct( @@ -137,7 +137,7 @@ private function get_sqlite_table_names(): array { array( '_mysql_data_types_cache', 'sqlite\_%', - str_replace( '_', '\_', WP_PDO_MySQL_On_SQLite::RESERVED_PREFIX ) . '%', + str_replace( '_', '\_', WP_MySQL_On_SQLite::RESERVED_PREFIX ) . '%', ) )->fetchAll( PDO::FETCH_COLUMN ); } @@ -763,9 +763,9 @@ private function get_mysql_column_type( string $column_type ): string { /** * Format a MySQL UTF-8 string literal for output in a CREATE TABLE statement. * - * See WP_PDO_MySQL_On_SQLite::quote_mysql_utf8_string_literal(). + * See WP_MySQL_On_SQLite::quote_mysql_utf8_string_literal(). * - * TODO: This is a copy of WP_PDO_MySQL_On_SQLite::quote_mysql_utf8_string_literal(). + * TODO: This is a copy of WP_MySQL_On_SQLite::quote_mysql_utf8_string_literal(). * We may consider extracing it to reusable MySQL helpers. * * @param string $utf8_literal The UTF-8 string literal to escape. diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Concurrency_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Concurrency_Tests.php similarity index 87% rename from packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Concurrency_Tests.php rename to packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Concurrency_Tests.php index 136956044..684bd2c49 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Concurrency_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Concurrency_Tests.php @@ -5,7 +5,7 @@ /** * Tests for concurrent access to the same SQLite database file. */ -class WP_SQLite_Driver_Concurrency_Tests extends TestCase { +class WP_MySQL_On_SQLite_Concurrency_Tests extends TestCase { /** * Path to the temporary SQLite database file used in file-based tests. * @@ -109,7 +109,7 @@ public function testSetQueryOpensReadOnlyTransaction(): void { public function testSetQuerySucceedsWhileAnotherConnectionHoldsWriteLock(): void { // Connection A: set up the database and hold a write transaction. $conn_a = new WP_SQLite_Connection( array( 'path' => $this->db_path ) ); - $driver_a = new WP_SQLite_Driver( $conn_a, 'wp' ); + $driver_a = $this->create_driver( $conn_a ); $driver_a->query( 'CREATE TABLE t (id INT, name VARCHAR(255))' ); $driver_a->query( "INSERT INTO t VALUES (1, 'Alice')" ); @@ -124,13 +124,13 @@ public function testSetQuerySucceedsWhileAnotherConnectionHoldsWriteLock(): void 'timeout' => 0, ) ); - $driver_b = new WP_SQLite_Driver( $conn_b, 'wp' ); + $driver_b = $this->create_driver( $conn_b ); $conn_b->get_pdo()->setAttribute( PDO::ATTR_TIMEOUT, 0 ); // SET writes nothing, so it must not contend for the write lock. $result = $driver_b->query( "SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'" ); - $this->assertSame( 0, $result ); + $this->assertSame( 0, $result->rowCount() ); } finally { $conn_a->get_pdo()->exec( 'ROLLBACK' ); } @@ -139,7 +139,7 @@ public function testSetQuerySucceedsWhileAnotherConnectionHoldsWriteLock(): void private function assertReadOnlyQuerySucceedsUnderWriteLock( string $query ): void { // Connection A: set up the database. $conn_a = new WP_SQLite_Connection( array( 'path' => $this->db_path ) ); - $driver_a = new WP_SQLite_Driver( $conn_a, 'wp' ); + $driver_a = $this->create_driver( $conn_a ); $driver_a->query( 'CREATE TABLE t (id INT, name VARCHAR(255))' ); $driver_a->query( "INSERT INTO t VALUES (1, 'Alice')" ); @@ -154,22 +154,33 @@ private function assertReadOnlyQuerySucceedsUnderWriteLock( string $query ): voi 'timeout' => 0, ) ); - $driver_b = new WP_SQLite_Driver( $conn_b, 'wp' ); + $driver_b = $this->create_driver( $conn_b ); $conn_b->get_pdo()->setAttribute( PDO::ATTR_TIMEOUT, 0 ); $result = $driver_b->query( $query ); - $this->assertIsArray( $result ); - $this->assertNotEmpty( $result ); + $this->assertNotEmpty( $result->fetchAll() ); } finally { $conn_a->get_pdo()->exec( 'ROLLBACK' ); } } - private function create_in_memory_driver(): WP_SQLite_Driver { + private function create_in_memory_driver(): WP_MySQL_On_SQLite { $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; $pdo = new $pdo_class( 'sqlite::memory:' ); $connection = new WP_SQLite_Connection( array( 'pdo' => $pdo ) ); - return new WP_SQLite_Driver( $connection, 'wp' ); + return $this->create_driver( $connection ); + } + + private function create_driver( WP_SQLite_Connection $connection ): WP_MySQL_On_SQLite { + return new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=wp', + null, + null, + array( + 'pdo' => $connection->get_pdo(), + 'journal_mode' => $connection->query( 'PRAGMA journal_mode' )->fetchColumn(), + ) + ); } } diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Metadata_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php similarity index 98% rename from packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Metadata_Tests.php rename to packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php index 6b6f4b7fe..afaf8723f 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Metadata_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php @@ -2,21 +2,27 @@ use PHPUnit\Framework\TestCase; -class WP_SQLite_Driver_Metadata_Tests extends TestCase { - /** @var WP_SQLite_Driver */ +class WP_MySQL_On_SQLite_Metadata_Tests extends TestCase { + /** @var WP_MySQL_On_SQLite */ private $engine; /** @var PDO */ private $sqlite; + /** @var mixed */ + private $last_result; + // Before each test, we create a new database public function setUp(): void { $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; $this->sqlite = new $pdo_class( 'sqlite::memory:' ); - $this->engine = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ), - 'wp' + $this->engine = new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=wp', + null, + null, + array( 'pdo' => $this->sqlite ) ); + $this->engine->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); } public function testCountTables() { @@ -208,7 +214,13 @@ public function testUseStatement() { } private function assertQuery( $sql ) { - $retval = $this->engine->query( $sql ); + $statement = $this->engine->query( $sql, PDO::FETCH_OBJ ); + if ( $statement->columnCount() > 0 ) { + $this->last_result = $statement->fetchAll(); + } else { + $this->last_result = $statement->rowCount(); + } + $retval = $this->last_result; $this->assertNotFalse( $retval ); return $retval; } @@ -385,7 +397,7 @@ public function testOptimizeTable() { 'Msg_text' => 'Operation failed', ), ), - $this->engine->get_query_results() + $this->last_result ); // One good and one missing table. @@ -503,7 +515,7 @@ public function testRepairTable() { public function testShowCollation(): void { // Simple. $this->assertQuery( 'SHOW COLLATION' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 7, $actual ); $this->assertEquals( 'binary', $actual[0]->Collation ); $this->assertEquals( 'utf8_bin', $actual[1]->Collation ); @@ -515,7 +527,7 @@ public function testShowCollation(): void { // With LIKE clause. $this->assertQuery( "SHOW COLLATION LIKE 'utf8%'" ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 6, $actual ); $this->assertEquals( 'utf8_bin', $actual[0]->Collation ); $this->assertEquals( 'utf8_general_ci', $actual[1]->Collation ); @@ -524,7 +536,7 @@ public function testShowCollation(): void { // With WHERE clause. $this->assertQuery( "SHOW COLLATION WHERE Collation = 'utf8_bin'" ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 1, $actual ); $this->assertEquals( 'utf8_bin', $actual[0]->Collation ); } @@ -532,7 +544,7 @@ public function testShowCollation(): void { public function testShowDatabases(): void { // Simple. $this->assertQuery( 'SHOW DATABASES' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( array( (object) array( 'Database' => 'information_schema' ), @@ -543,7 +555,7 @@ public function testShowDatabases(): void { // With LIKE clause. $this->assertQuery( 'SHOW DATABASES LIKE "w%"' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( array( (object) array( 'Database' => 'wp' ) ), $actual @@ -551,7 +563,7 @@ public function testShowDatabases(): void { // With WHERE clause. $this->assertQuery( 'SHOW DATABASES WHERE `Database` = "wp"' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( array( (object) array( 'Database' => 'wp' ) ), $actual @@ -561,7 +573,7 @@ public function testShowDatabases(): void { public function testShowTableSchemas(): void { $this->assertQuery( 'SHOW SCHEMAS' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( array( (object) array( 'Database' => 'information_schema' ), @@ -572,7 +584,7 @@ public function testShowTableSchemas(): void { // With LIKE clause. $this->assertQuery( 'SHOW DATABASES LIKE "inf%"' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( array( (object) array( 'Database' => 'information_schema' ) ), $actual @@ -580,7 +592,7 @@ public function testShowTableSchemas(): void { // With WHERE clause. $this->assertQuery( 'SHOW DATABASES WHERE `Database` = "information_schema"' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( array( (object) array( 'Database' => 'information_schema' ) ), $actual @@ -913,7 +925,7 @@ private function assertTableEmpty( $table_name, $empty_var ) { "SELECT COUNT(*) num FROM $table_name" ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; if ( $empty_var ) { $this->assertEquals( 0, $actual[0]->num, "$table_name is not empty" ); } else { @@ -939,7 +951,7 @@ public function testTruncateTable() { $this->assertQuery( 'TRUNCATE TABLE wp_comments;' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertSame( 0, $actual ); $this->assertTableEmpty( 'wp_comments', true ); } diff --git a/packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php similarity index 94% rename from packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php rename to packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php index 404481a34..ebcb2d71f 100644 --- a/packages/mysql-on-sqlite/tests/WP_PDO_MySQL_On_SQLite_PDO_API_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php @@ -16,12 +16,12 @@ public function __construct( $arg1 = null, $arg2 = null ) { } } -class WP_PDO_MySQL_On_SQLite_PDO_API_Tests extends TestCase { - /** @var WP_PDO_MySQL_On_SQLite */ +class WP_MySQL_On_SQLite_PDO_API_Tests extends TestCase { + /** @var WP_MySQL_On_SQLite */ private $driver; public function setUp(): void { - $this->driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); + $this->driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); // Run all tests with stringified fetch mode results, so we can use // assertions that are consistent across all tested PHP versions. @@ -30,41 +30,41 @@ public function setUp(): void { } public function test_connection(): void { - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=WordPress;' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=WordPress;' ); $this->assertInstanceOf( PDO::class, $driver ); } public function test_dsn_parsing(): void { // Standard DSN. - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp' ); $this->assertSame( 'wp', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with trailing semicolon. - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); $this->assertSame( 'wp', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with whitespace before argument names. - $driver = new WP_PDO_MySQL_On_SQLite( "mysql-on-sqlite: path=:memory:; \n\r\t\v\fdbname=wp" ); + $driver = new WP_MySQL_On_SQLite( "mysql-on-sqlite: path=:memory:; \n\r\t\v\fdbname=wp" ); $this->assertSame( 'wp', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with whitespace in the database name. - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname= w p ' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname= w p ' ); $this->assertSame( ' w p ', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with semicolon in the database name. - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;dbname=w;;p;' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;dbname=w;;p;' ); $this->assertSame( 'w;p', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with semicolon in the database name and a terminating semicolon. - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=w;;;p' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=w;;;p' ); $this->assertSame( 'w;', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with two semicolons in the database name. - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=w;;;;p' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=w;;;;p' ); $this->assertSame( 'w;;p', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); // DSN with a "\0" byte (always terminates the DSN string). - $driver = new WP_PDO_MySQL_On_SQLite( "mysql-on-sqlite:path=:memory:;dbname=w\0p;" ); + $driver = new WP_MySQL_On_SQLite( "mysql-on-sqlite:path=:memory:;dbname=w\0p;" ); $this->assertSame( 'w', $driver->query( 'SELECT DATABASE()' )->fetch()[0] ); } @@ -73,7 +73,7 @@ public function test_journal_mode_defaults_to_wal(): void { unlink( $path ); try { - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=' . $path . ';dbname=wp' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=' . $path . ';dbname=wp' ); $connection = $driver->get_connection(); $this->assertSame( 'wal', @@ -93,7 +93,7 @@ public function test_journal_mode_and_synchronous_driver_options(): void { unlink( $path ); try { - $driver = new WP_PDO_MySQL_On_SQLite( + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=' . $path . ';dbname=wp', null, null, diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Query_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Query_Tests.php similarity index 93% rename from packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Query_Tests.php rename to packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Query_Tests.php index 2fd5d69de..0f3770bbc 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Query_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Query_Tests.php @@ -86,13 +86,16 @@ /** * Unit tests using the WordPress table definitions. */ -class WP_SQLite_Driver_Query_Tests extends TestCase { - /** @var WP_SQLite_Driver */ +class WP_MySQL_On_SQLite_Query_Tests extends TestCase { + /** @var WP_MySQL_On_SQLite */ private $engine; /** @var PDO */ private $sqlite; + /** @var mixed */ + private $last_result; + /** * Before each test, we create a new volatile database and WordPress tables. * @@ -106,10 +109,13 @@ public function setUp(): void { $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; $this->sqlite = new $pdo_class( 'sqlite::memory:' ); - $this->engine = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ), - 'wp' + $this->engine = new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=wp', + null, + null, + array( 'pdo' => $this->sqlite ) ); + $this->engine->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); try { $this->engine->begin_transaction(); @@ -176,7 +182,7 @@ public function testGreatestLeast() { QUERY; $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 1, count( $actual ) ); $this->assertEquals( 'b', $actual[0]->letter ); @@ -185,7 +191,7 @@ public function testGreatestLeast() { QUERY; $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 1, count( $actual ) ); $this->assertEquals( 'a', $actual[0]->letter ); @@ -194,7 +200,7 @@ public function testGreatestLeast() { QUERY; $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 1, count( $actual ) ); $this->assertEquals( 2, $actual[0]->num ); @@ -203,7 +209,7 @@ public function testGreatestLeast() { QUERY; $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 1, count( $actual ) ); $this->assertEquals( 1, $actual[0]->num ); } @@ -215,7 +221,7 @@ public function testLikeEscapingSimpleNoSemicolon() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 40, count( $actual ) ); } @@ -226,7 +232,7 @@ public function testLikeEscapingPercent() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 40, count( $actual ) ); } @@ -237,7 +243,7 @@ public function testLikeEscapingSimpleSemicolon() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 40, count( $actual ) ); } @@ -248,7 +254,7 @@ public function testLikeEscapingBasic() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 30, count( $actual ) ); $last = $actual[ count( $actual ) - 1 ]->meta_key; $this->assertEquals( 'visible_meta_key_30', $last ); @@ -263,7 +269,7 @@ public function testLikeEscapingParenAfterLike() { $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 40, count( $actual ) ); $last = $actual[ count( $actual ) - 1 ]->meta_key; $this->assertEquals( 'visible_meta_key_40', $last ); @@ -276,7 +282,7 @@ public function testLikeEscapingWithConcatFunction() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 30, count( $actual ) ); $last = $actual[ count( $actual ) - 1 ]->meta_key; $this->assertEquals( 'visible_meta_key_30', $last ); @@ -292,7 +298,7 @@ public function testHavingWithoutGroupBy() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 30, count( $actual ) ); $last = $actual[ count( $actual ) - 1 ]->meta_key; $this->assertEquals( 'visible_meta_key_30', $last ); @@ -303,7 +309,7 @@ public function testHavingWithoutGroupBy() { $result = $this->assertQuery( $q ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 30, count( $actual ) ); $last = $actual[ count( $actual ) - 1 ]->meta_key; $this->assertEquals( 'visible_meta_key_30', $last ); @@ -315,7 +321,7 @@ public function testCharLengthSimple() { QUERY; $this->assertQuery( $query ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 0, count( $actual ) ); } @@ -329,7 +335,7 @@ public function testSubstringSimple() { QUERY; $this->assertQuery( $query ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 0, count( $actual ) ); } @@ -357,7 +363,7 @@ public function testCharLengthComplex() { QUERY; $this->assertQuery( $query ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 6, count( $actual ) ); foreach ( $actual as $row ) { self::assertTrue( str_ends_with( $row->option_name, '_' . $row->suffix ) ); @@ -368,7 +374,7 @@ public function testAllTransients() { $this->assertQuery( "SELECT * FROM wp_options WHERE option_name LIKE '\_%transient\_%'" ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 12, count( $actual ) ); } @@ -409,7 +415,7 @@ public function testExpiredTransients() { QUERY; $this->assertQuery( $query ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertEquals( 4, count( $actual ) ); foreach ( $actual as $row ) { self::assertLessThan( time(), $row->option_timeout ); @@ -467,7 +473,7 @@ public function testDeleteExpiredNonSiteTransients() { QUERY; $this->assertQuery( $query ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $count_unexpired = 0; foreach ( $actual as $row ) { if ( str_starts_with( $row->option_name, '_transient' ) ) { @@ -529,7 +535,7 @@ public function testRecoverSerialized() { QUERY; $this->assertQuery( $get ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $retrieved_name = $actual[0]->option_name; $retrieved_string = $actual[0]->option_value; $this->assertEquals( $option_value, $retrieved_string ); @@ -555,7 +561,7 @@ public function testRecoverSerialized() { QUERY; $this->assertQuery( $get ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $retrieved_string = $actual[0]->option_value; $this->assertEquals( $option_value, $retrieved_string ); $unserialized = unserialize( $retrieved_string ); @@ -634,7 +640,7 @@ public function testShowColumns() { $query = 'SHOW COLUMNS FROM t'; $this->assertQuery( $query ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 6, $actual ); foreach ( $actual as $row ) { $this->assertIsObject( $row ); @@ -648,7 +654,13 @@ public function testShowColumns() { } private function assertQuery( $sql ) { - $retval = $this->engine->query( $sql ); + $statement = $this->engine->query( $sql, PDO::FETCH_OBJ ); + if ( $statement->columnCount() > 0 ) { + $this->last_result = $statement->fetchAll(); + } else { + $this->last_result = $statement->rowCount(); + } + $retval = $this->last_result; $this->assertNotFalse( $retval ); return $retval; } diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php similarity index 96% rename from packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Tests.php rename to packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php index 942d30100..f573f37c8 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php @@ -2,30 +2,36 @@ use PHPUnit\Framework\TestCase; -class WP_SQLite_Driver_Tests extends TestCase { - /** @var WP_SQLite_Driver */ +class WP_MySQL_On_SQLite_Tests extends TestCase { + /** @var WP_MySQL_On_SQLite */ private $engine; /** @var PDO */ private $sqlite; + /** @var mixed */ + private $last_result; + // Before each test, we create a new database public function setUp(): void { $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; $this->sqlite = new $pdo_class( 'sqlite::memory:' ); - $this->engine = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ), - 'wp' + $this->engine = new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=wp', + null, + null, + array( 'pdo' => $this->sqlite ) ); - $this->engine->query( + $this->engine->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); + $this->query( "CREATE TABLE _options ( ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, option_name TEXT NOT NULL default '', option_value TEXT NOT NULL default '' );" ); - $this->engine->query( + $this->query( "CREATE TABLE _dates ( ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, option_name TEXT NOT NULL default '', @@ -35,7 +41,7 @@ public function setUp(): void { } private function assertQuery( $sql ) { - $retval = $this->engine->query( $sql ); + $retval = $this->query( $sql ); $this->assertNotFalse( $retval ); return $retval; } @@ -43,7 +49,7 @@ private function assertQuery( $sql ) { private function assertQueryError( $sql, $error_message ) { $exception = null; try { - $this->engine->query( $sql ); + $this->query( $sql ); } catch ( WP_SQLite_Driver_Exception $e ) { $exception = $e; } @@ -51,6 +57,16 @@ private function assertQueryError( $sql, $error_message ) { $this->assertSame( $error_message, $exception->getMessage() ); } + private function query( $sql ) { + $statement = $this->engine->query( $sql, PDO::FETCH_OBJ ); + if ( $statement->columnCount() > 0 ) { + $this->last_result = $statement->fetchAll(); + } else { + $this->last_result = $statement->rowCount(); + } + return $this->last_result; + } + public function testRegexp() { $this->assertQuery( "INSERT INTO _options (option_name, option_value) VALUES ('rss_0123456789abcdef0123456789abcdef', '1');" @@ -61,7 +77,7 @@ public function testRegexp() { $this->assertQuery( "DELETE FROM _options WHERE option_name REGEXP '^rss_.+$'" ); $this->assertQuery( 'SELECT * FROM _options' ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); } /** @@ -75,7 +91,7 @@ public function testRegexps( $operator, $regexp, $expected_result ) { $this->assertQuery( "SELECT ID, option_name FROM _options WHERE option_name $operator '$regexp' ORDER BY id LIMIT 1" ); $this->assertEquals( array( $expected_result ), - $this->engine->get_query_results() + $this->last_result ); } @@ -111,7 +127,7 @@ public function testInsertDateNow() { $this->assertQuery( 'SELECT YEAR(option_value) as y FROM _dates' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( gmdate( 'Y' ), $results[0]->y ); } @@ -128,8 +144,8 @@ public function testUpdateWithLimit() { "UPDATE _dates SET option_value = '2001-05-27 10:08:48' WHERE option_name = 'first' ORDER BY option_name LIMIT 1;" ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first';" ); - $result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second';" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first';" ); + $result2 = $this->query( "SELECT option_value FROM _dates WHERE option_name='second';" ); $this->assertEquals( '2001-05-27 10:08:48', $result1[0]->option_value ); $this->assertEquals( '2003-05-28 00:00:45', $result2[0]->option_value ); @@ -137,14 +153,14 @@ public function testUpdateWithLimit() { $this->assertQuery( "UPDATE _dates SET option_value = '2001-05-27 10:08:49' WHERE option_name = 'first';" ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first';" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first';" ); $this->assertEquals( '2001-05-27 10:08:49', $result1[0]->option_value ); $this->assertQuery( "UPDATE _dates SET option_value = '2001-05-12 10:00:40' WHERE option_name in ( SELECT option_name from _dates );" ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first';" ); - $result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second';" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first';" ); + $result2 = $this->query( "SELECT option_value FROM _dates WHERE option_name='second';" ); $this->assertEquals( '2001-05-12 10:00:40', $result1[0]->option_value ); $this->assertEquals( '2001-05-12 10:00:40', $result2[0]->option_value ); } @@ -160,10 +176,10 @@ public function testUpdateWithLimitNoEndToken() { $this->assertQuery( "UPDATE _dates SET option_value = '2001-05-27 10:08:48' WHERE option_name = 'first' ORDER BY option_name LIMIT 1" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); - $result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); + $result2 = $this->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); $this->assertEquals( '2001-05-27 10:08:48', $result1[0]->option_value ); $this->assertEquals( '2003-05-28 00:00:45', $result2[0]->option_value ); @@ -171,14 +187,14 @@ public function testUpdateWithLimitNoEndToken() { $this->assertQuery( "UPDATE _dates SET option_value = '2001-05-27 10:08:49' WHERE option_name = 'first'" ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); $this->assertEquals( '2001-05-27 10:08:49', $result1[0]->option_value ); $this->assertQuery( "UPDATE _dates SET option_value = '2001-05-12 10:00:40' WHERE option_name in ( SELECT option_name from _dates )" ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); - $result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); + $result2 = $this->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); $this->assertEquals( '2001-05-12 10:00:40', $result1[0]->option_value ); $this->assertEquals( '2001-05-12 10:00:40', $result2[0]->option_value ); } @@ -198,8 +214,8 @@ public function testUpdateWithoutWhereButWithSubSelect() { ); $this->assertSame( 2, $return, 'UPDATE query did not return 2 when two row were changed' ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); - $result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); + $result2 = $this->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); $this->assertEquals( '2025-10-29 13:57:21', $result1[0]->option_value ); $this->assertEquals( '2025-10-29 13:57:21', $result2[0]->option_value ); } @@ -216,8 +232,8 @@ public function testUpdateWithoutWhereButWithLimit() { ); $this->assertSame( 1, $return, 'UPDATE query did not return 2 when two row were changed' ); - $result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); - $result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); + $result1 = $this->query( "SELECT option_value FROM _dates WHERE option_name='first'" ); + $result2 = $this->query( "SELECT option_value FROM _dates WHERE option_name='second'" ); $this->assertEquals( '2025-10-29 13:57:21', $result1[0]->option_value ); $this->assertEquals( '2003-05-27 10:08:48', $result2[0]->option_value ); } @@ -237,14 +253,14 @@ public function testDeleteWithLimit() { $result = $this->assertQuery( "DELETE FROM _dates WHERE option_name LIKE '%' LIMIT 1" ); $this->assertSame( 1, $result ); - $rows = $this->engine->query( 'SELECT option_name FROM _dates ORDER BY option_name' ); + $rows = $this->query( 'SELECT option_name FROM _dates ORDER BY option_name' ); $this->assertCount( 2, $rows ); // ORDER BY + LIMIT: deletes the lexicographically-first remaining row. $result = $this->assertQuery( 'DELETE FROM _dates ORDER BY option_name ASC LIMIT 1' ); $this->assertSame( 1, $result ); - $rows = $this->engine->query( 'SELECT option_name FROM _dates' ); + $rows = $this->query( 'SELECT option_name FROM _dates' ); $this->assertCount( 1, $rows ); $this->assertSame( 'third', $rows[0]->option_name ); } @@ -260,7 +276,7 @@ public function testDeleteWithoutWhereButWithLimit() { $result = $this->assertQuery( 'DELETE FROM _dates LIMIT 1' ); $this->assertSame( 1, $result ); - $rows = $this->engine->query( 'SELECT option_name FROM _dates' ); + $rows = $this->query( 'SELECT option_name FROM _dates' ); $this->assertCount( 1, $rows ); } @@ -275,7 +291,7 @@ public function testDeleteWithAliasAndLimit() { $result = $this->assertQuery( "DELETE FROM _dates AS d WHERE d.option_name = 'a' LIMIT 1" ); $this->assertSame( 1, $result ); - $rows = $this->engine->query( 'SELECT option_name FROM _dates' ); + $rows = $this->query( 'SELECT option_name FROM _dates' ); $this->assertCount( 1, $rows ); $this->assertSame( 'b', $rows[0]->option_name ); } @@ -283,7 +299,7 @@ public function testDeleteWithAliasAndLimit() { public function testCastAsBinary() { // Use a confusing alias to make sure it replaces only the correct token $this->assertQuery( "SELECT CAST('ABC' AS BINARY) as `binary`" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 'ABC', $results[0]->binary ); } @@ -346,7 +362,7 @@ public function testShowCreateTableNotFound() { $this->assertQuery( 'SHOW CREATE TABLE _no_such_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 0, $results ); } @@ -364,7 +380,7 @@ public function testShowCreateTable1() { $this->assertQuery( 'SHOW CREATE TABLE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( "CREATE TABLE `_tmp_table` ( `ID` bigint NOT NULL AUTO_INCREMENT, @@ -392,7 +408,7 @@ public function testShowCreateTableQuoted() { $this->assertQuery( 'SHOW CREATE TABLE `_tmp_table`;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( "CREATE TABLE `_tmp_table` ( `ID` bigint NOT NULL AUTO_INCREMENT, @@ -416,7 +432,7 @@ public function testShowCreateTableSimpleTable() { $this->assertQuery( 'SHOW CREATE TABLE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 'CREATE TABLE `_tmp_table` ( `ID` bigint NOT NULL @@ -445,7 +461,7 @@ public function testShowCreateTableWithAlterAndCreateIndex() { $this->assertQuery( 'SHOW CREATE TABLE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 'CREATE TABLE `_tmp_table` ( `ID` bigint NOT NULL AUTO_INCREMENT, @@ -547,7 +563,7 @@ public function testShowCreateTablePreservesDoubleUnderscoreKeyNames() { $this->assertQuery( 'SHOW CREATE TABLE _tmp__table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 'CREATE TABLE `_tmp__table` ( `ID` bigint NOT NULL AUTO_INCREMENT, @@ -574,7 +590,7 @@ public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() { $this->assertQuery( 'SHOW CREATE TABLE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 'CREATE TABLE `_tmp_table` ( `ID_A` bigint NOT NULL, @@ -625,7 +641,7 @@ public function testShowCreateTableWithDefaultValues(): void { $this->assertQuery( 'SHOW CREATE TABLE _tmp__table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertSame( implode( "\n", @@ -674,7 +690,7 @@ public function testShowCreateTableWithBitDefaultValues(): void { ); $this->assertQuery( 'SHOW CREATE TABLE _tmp_bit_defaults;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $create_table = $results[0]->{'Create Table'}; $this->assertStringContainsString( "`quoted_zero` bit(1) DEFAULT b'0'", $create_table ); $this->assertStringContainsString( "`integer_five` bit(4) DEFAULT b'101'", $create_table ); @@ -687,7 +703,7 @@ public function testShowCreateTableWithBitDefaultValues(): void { $this->assertQuery( 'INSERT INTO _tmp_bit_defaults (id) VALUES (1)' ); $this->assertQuery( 'SELECT * FROM _tmp_bit_defaults' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -717,7 +733,7 @@ public function testUpdateWithBitColumnDefaultValue(): void { $this->assertQuery( 'INSERT INTO _tmp_bit_defaults (id, maintenance) VALUES (1, 0)' ); $this->assertQuery( 'UPDATE _tmp_bit_defaults SET maintenance = DEFAULT' ); $this->assertQuery( 'SELECT maintenance FROM _tmp_bit_defaults' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( 'maintenance' => '5' ) ), $results ); } @@ -898,7 +914,7 @@ public function testShowTablesLike() { 'Tables_in_wp' => '_tmp_table', ), ), - $this->engine->get_query_results() + $this->last_result ); $this->assertQuery( @@ -911,7 +927,7 @@ public function testShowTablesLike() { 'Table_type' => 'BASE TABLE', ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -934,7 +950,7 @@ public function testShowTableStatusFrom() { $this->assertCount( 1, - $this->engine->get_query_results() + $this->last_result ); } @@ -957,7 +973,7 @@ public function testShowTableStatusIn() { $this->assertCount( 1, - $this->engine->get_query_results() + $this->last_result ); } @@ -987,7 +1003,7 @@ public function testShowTableStatusInTwoTables() { $this->assertCount( 2, - $this->engine->get_query_results() + $this->last_result ); } @@ -1025,11 +1041,11 @@ public function testShowTableStatusLike() { ); $this->assertCount( 2, - $this->engine->get_query_results() + $this->last_result ); $this->assertEquals( '_tmp_table1', - $this->engine->get_query_results()[0]->Name + $this->last_result[0]->Name ); } @@ -1059,11 +1075,11 @@ public function testShowTableStatusWhere() { ); $this->assertCount( 1, - $this->engine->get_query_results() + $this->last_result ); $this->assertEquals( '_tmp_table1', - $this->engine->get_query_results()[0]->Name + $this->last_result[0]->Name ); } @@ -1089,7 +1105,7 @@ public function testCreateTable() { $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE wptests_users;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1210,7 +1226,7 @@ enum_column ENUM('a', 'b', 'c') NOT NULL DEFAULT 'a', $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE wptests_users;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1262,7 +1278,7 @@ public function testAlterTableAddAndDropColumn() { $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1289,7 +1305,7 @@ public function testAlterTableAddAndDropColumn() { $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1324,7 +1340,7 @@ public function testAlterTableAddAndDropColumn() { $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1351,7 +1367,7 @@ public function testAlterTableAddAndDropColumn() { $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1378,7 +1394,7 @@ public function testAlterTableAddNotNullVarcharColumn() { $this->assertSame( 0, $result ); $this->assertQuery( 'DESCRIBE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -1979,7 +1995,7 @@ public function testAlterTableAddIndex() { // Verify that the index was created in the information schema. $this->assertQuery( 'SHOW INDEX FROM _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -2032,7 +2048,7 @@ public function testAlterTableAddUniqueIndex() { // Verify that the index was created in the information schema. $this->assertQuery( 'SHOW INDEX FROM _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -2085,7 +2101,7 @@ public function testAlterTableAddFulltextIndex() { // Verify that the index was created in the information schema. $this->assertQuery( 'SHOW INDEX FROM _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -2187,7 +2203,7 @@ public function testAlterTableModifyColumn() { // Primary key violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (1, 'Mike', 'Pearseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (1, 'Mike', 'Pearseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } @@ -2196,18 +2212,18 @@ public function testAlterTableModifyColumn() { // Unique constraint violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } $this->assertStringContainsString( 'UNIQUE constraint failed: _tmp_table.name', $error ); // Rename the "name" field to "firstname": - $result = $this->engine->query( "ALTER TABLE _tmp_table CHANGE column name firstname varchar(50) NOT NULL default 'mark';" ); + $result = $this->query( "ALTER TABLE _tmp_table CHANGE column name firstname varchar(50) NOT NULL default 'mark';" ); $this->assertSame( 0, $result ); // Confirm the original data is still there: - $result = $this->engine->query( 'SELECT * FROM _tmp_table;' ); + $result = $this->query( 'SELECT * FROM _tmp_table;' ); $this->assertCount( 1, $result ); $this->assertEquals( 1, $result[0]->ID ); $this->assertEquals( 'Johnny', $result[0]->firstname ); @@ -2216,7 +2232,7 @@ public function testAlterTableModifyColumn() { // Confirm the primary key is intact: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (1, 'Mike', 'Pearseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (1, 'Mike', 'Pearseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } @@ -2225,16 +2241,16 @@ public function testAlterTableModifyColumn() { // Confirm the unique key is intact: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } $this->assertStringContainsString( 'UNIQUE constraint failed: _tmp_table.firstname', $error ); // Confirm the autoincrement still works: - $result = $this->engine->query( "INSERT INTO _tmp_table (firstname, lastname) VALUES ('John', 'Doe');" ); + $result = $this->query( "INSERT INTO _tmp_table (firstname, lastname) VALUES ('John', 'Doe');" ); $this->assertEquals( true, $result ); - $result = $this->engine->query( "SELECT * FROM _tmp_table WHERE firstname='John';" ); + $result = $this->query( "SELECT * FROM _tmp_table WHERE firstname='John';" ); $this->assertCount( 1, $result ); $this->assertEquals( 2, $result[0]->ID ); } @@ -2257,7 +2273,7 @@ public function testAlterTableModifyColumnWithSkippedColumnKeyword() { // Primary key violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (1, 'Mike', 'Pearseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (1, 'Mike', 'Pearseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } @@ -2266,18 +2282,18 @@ public function testAlterTableModifyColumnWithSkippedColumnKeyword() { // Unique constraint violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } $this->assertStringContainsString( 'UNIQUE constraint failed: _tmp_table.name', $error ); // Rename the "name" field to "firstname": - $result = $this->engine->query( "ALTER TABLE _tmp_table CHANGE name firstname varchar(50) NOT NULL default 'mark';" ); + $result = $this->query( "ALTER TABLE _tmp_table CHANGE name firstname varchar(50) NOT NULL default 'mark';" ); $this->assertSame( 0, $result ); // Confirm the original data is still there: - $result = $this->engine->query( 'SELECT * FROM _tmp_table;' ); + $result = $this->query( 'SELECT * FROM _tmp_table;' ); $this->assertCount( 1, $result ); $this->assertEquals( 1, $result[0]->ID ); $this->assertEquals( 'Johnny', $result[0]->firstname ); @@ -2286,7 +2302,7 @@ public function testAlterTableModifyColumnWithSkippedColumnKeyword() { // Confirm the primary key is intact: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (1, 'Mike', 'Pearseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (1, 'Mike', 'Pearseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } @@ -2295,16 +2311,16 @@ public function testAlterTableModifyColumnWithSkippedColumnKeyword() { // Confirm the unique key is intact: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); + $this->query( "INSERT INTO _tmp_table (ID, firstname, lastname) VALUES (2, 'Johnny', 'Appleseed')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } $this->assertStringContainsString( 'UNIQUE constraint failed: _tmp_table.firstname', $error ); // Confirm the autoincrement still works: - $result = $this->engine->query( "INSERT INTO _tmp_table (firstname, lastname) VALUES ('John', 'Doe');" ); + $result = $this->query( "INSERT INTO _tmp_table (firstname, lastname) VALUES ('John', 'Doe');" ); $this->assertEquals( true, $result ); - $result = $this->engine->query( "SELECT * FROM _tmp_table WHERE firstname='John';" ); + $result = $this->query( "SELECT * FROM _tmp_table WHERE firstname='John';" ); $this->assertCount( 1, $result ); $this->assertEquals( 2, $result[0]->ID ); } @@ -2381,7 +2397,7 @@ public function testAlterTableModifyColumnComplexChange() { // Primary key violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, name) VALUES (1, 'Johnny')" ); + $this->query( "INSERT INTO _tmp_table (ID, name) VALUES (1, 'Johnny')" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } @@ -2390,25 +2406,25 @@ public function testAlterTableModifyColumnComplexChange() { // Unique constraint violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (5, 'Kate', 'Bar');" ); + $this->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (5, 'Kate', 'Bar');" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } $this->assertStringContainsString( 'UNIQUE constraint failed: _tmp_table.name, _tmp_table.lastname', $error ); // No constraint violation: - $result = $this->engine->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (5, 'Joanna', 'Bar');" ); + $result = $this->query( "INSERT INTO _tmp_table (ID, name, lastname) VALUES (5, 'Joanna', 'Bar');" ); $this->assertEquals( 1, $result ); // Now – let's change a few columns: - $result = $this->engine->query( 'ALTER TABLE _tmp_table CHANGE COLUMN name firstname varchar(20)' ); + $result = $this->query( 'ALTER TABLE _tmp_table CHANGE COLUMN name firstname varchar(20)' ); $this->assertSame( 0, $result ); - $result = $this->engine->query( 'ALTER TABLE _tmp_table CHANGE COLUMN date_as_string datetime datetime NOT NULL' ); + $result = $this->query( 'ALTER TABLE _tmp_table CHANGE COLUMN date_as_string datetime datetime NOT NULL' ); $this->assertSame( 0, $result ); // Finally, let's confirm our data is intact and the table is still well-behaved: - $result = $this->engine->query( 'SELECT * FROM _tmp_table ORDER BY ID;' ); + $result = $this->query( 'SELECT * FROM _tmp_table ORDER BY ID;' ); $this->assertCount( 5, $result ); $this->assertEquals( 1, $result[0]->ID ); $this->assertEquals( 'Johnny', $result[0]->firstname ); @@ -2418,7 +2434,7 @@ public function testAlterTableModifyColumnComplexChange() { // Primary key violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, datetime) VALUES (1, 'Johnny', '2010-01-01 12:53:13');" ); + $this->query( "INSERT INTO _tmp_table (ID, firstname, datetime) VALUES (1, 'Johnny', '2010-01-01 12:53:13');" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } @@ -2427,19 +2443,19 @@ public function testAlterTableModifyColumnComplexChange() { // Unique constraint violation: $error = ''; try { - $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, lastname, datetime) VALUES (6, 'Kate', 'Bar', '2010-01-01 12:53:13');" ); + $this->query( "INSERT INTO _tmp_table (ID, firstname, lastname, datetime) VALUES (6, 'Kate', 'Bar', '2010-01-01 12:53:13');" ); } catch ( Throwable $e ) { $error = $e->getMessage(); } $this->assertStringContainsString( 'UNIQUE constraint failed: _tmp_table.firstname, _tmp_table.lastname', $error ); // No constraint violation: - $result = $this->engine->query( "INSERT INTO _tmp_table (ID, firstname, lastname, datetime) VALUES (6, 'Sophie', 'Bar', '2010-01-01 12:53:13');" ); + $result = $this->query( "INSERT INTO _tmp_table (ID, firstname, lastname, datetime) VALUES (6, 'Sophie', 'Bar', '2010-01-01 12:53:13');" ); $this->assertEquals( 1, $result ); } public function testCaseInsensitiveUniqueIndex() { - $result = $this->engine->query( + $result = $this->query( "CREATE TABLE _tmp_table ( ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, name varchar(20) NOT NULL default '', @@ -2451,10 +2467,10 @@ public function testCaseInsensitiveUniqueIndex() { ); $this->assertSame( 0, $result ); - $result1 = $this->engine->query( "INSERT INTO _tmp_table (name, lastname) VALUES ('first', 'last');" ); + $result1 = $this->query( "INSERT INTO _tmp_table (name, lastname) VALUES ('first', 'last');" ); $this->assertEquals( 1, $result1 ); - $result1 = $this->engine->query( 'SELECT COUNT(*) num FROM _tmp_table;' ); + $result1 = $this->query( 'SELECT COUNT(*) num FROM _tmp_table;' ); $this->assertEquals( 1, $result1[0]->num ); // Unique keys should be case-insensitive: @@ -2468,7 +2484,7 @@ public function testCaseInsensitiveUniqueIndex() { } $this->assertStringContainsString( 'UNIQUE constraint failed', $error ); - $result1 = $this->engine->query( 'SELECT COUNT(*) num FROM _tmp_table;' ); + $result1 = $this->query( 'SELECT COUNT(*) num FROM _tmp_table;' ); $this->assertEquals( 1, $result1[0]->num ); // Unique keys should be case-insensitive: @@ -2478,10 +2494,10 @@ public function testCaseInsensitiveUniqueIndex() { self::assertEquals( 0, $result1 ); - $result2 = $this->engine->get_query_results(); + $result2 = $this->last_result; $this->assertEquals( 0, $result2 ); - $result1 = $this->engine->query( 'SELECT COUNT(*)num FROM _tmp_table;' ); + $result1 = $this->query( 'SELECT COUNT(*)num FROM _tmp_table;' ); $this->assertEquals( 1, $result1[0]->num ); // Unique keys should be case-insensitive: @@ -2491,7 +2507,7 @@ public function testCaseInsensitiveUniqueIndex() { $this->assertEquals( 1, $result2 ); - $result1 = $this->engine->query( 'SELECT COUNT(*) num FROM _tmp_table;' ); + $result1 = $this->query( 'SELECT COUNT(*) num FROM _tmp_table;' ); $this->assertEquals( 2, $result1[0]->num ); } @@ -2511,7 +2527,7 @@ public function testOnDuplicateUpdate() { $this->assertEquals( 1, $result2 ); $this->assertQuery( 'SELECT * FROM _tmp_table;' ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); $this->assertEquals( array( (object) array( @@ -2519,7 +2535,7 @@ public function testOnDuplicateUpdate() { 'ID' => 1, ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -2530,7 +2546,7 @@ public function testTruncatesInvalidDates() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('2022-31-01 14:24:12');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 2, $results ); $this->assertEquals( '2022-01-01 14:24:12', $results[0]->option_value ); $this->assertEquals( '0000-00-00 00:00:00', $results[1]->option_value ); @@ -2555,7 +2571,7 @@ public function testZeroDateAcceptedWhenNoZeroDateModeIsOff() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('0000-00-00 00:00:00');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0000-00-00 00:00:00', $results[0]->option_value ); } @@ -2590,7 +2606,7 @@ public function testZeroDateAcceptedWhenNoZeroDateOnButStrictModeOff() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('0000-00-00 00:00:00');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0000-00-00 00:00:00', $results[0]->option_value ); } @@ -2611,7 +2627,7 @@ public function testZeroDateAcceptedForDateColumn() { $this->assertQuery( "INSERT INTO _date_test (col_date) VALUES ('0000-00-00');" ); $this->assertQuery( 'SELECT * FROM _date_test;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0000-00-00', $results[0]->col_date ); } @@ -2642,7 +2658,7 @@ public function testZeroInDateAcceptedWhenNoZeroInDateModeIsOff() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('2020-00-00 00:00:00');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( '2020-00-15 00:00:00', $results[0]->option_value ); $this->assertEquals( '2020-01-00 00:00:00', $results[1]->option_value ); @@ -2676,7 +2692,7 @@ public function testZeroInDateBecomesZeroDateWhenNoZeroInDateOnButStrictOff() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('2020-00-15 00:00:00');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0000-00-00 00:00:00', $results[0]->option_value ); } @@ -2692,7 +2708,7 @@ public function testBothZeroDateModesDisabledAcceptsAll() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('2020-01-00 00:00:00');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( '0000-00-00 00:00:00', $results[0]->option_value ); $this->assertEquals( '2020-00-15 00:00:00', $results[1]->option_value ); @@ -2707,7 +2723,7 @@ public function testValidDatesWorkWithZeroDateModes() { $this->assertQuery( "INSERT INTO _dates (option_value) VALUES ('2022-01-15 14:30:00');" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '2022-01-15 14:30:00', $results[0]->option_value ); } @@ -2722,7 +2738,7 @@ public function testZeroDateInUpdate() { $this->assertQuery( "UPDATE _dates SET option_value = '0000-00-00 00:00:00';" ); $this->assertQuery( 'SELECT * FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0000-00-00 00:00:00', $results[0]->option_value ); } @@ -2766,13 +2782,13 @@ public function testSelectZeroDatesComparison() { // Zero dates compare as less than real dates. $this->assertQuery( "SELECT option_name FROM _dates WHERE option_value < '2000-01-01 00:00:00' ORDER BY option_value;" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 'zero', $results[0]->option_name ); // Equality match on zero date. $this->assertQuery( "SELECT option_name FROM _dates WHERE option_value = '0000-00-00 00:00:00';" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 'zero', $results[0]->option_name ); } @@ -2788,7 +2804,7 @@ public function testSelectZeroDatesOrderBy() { $this->assertQuery( "INSERT INTO _dates (option_name, option_value) VALUES ('c', '2023-01-01 00:00:00');" ); $this->assertQuery( 'SELECT option_name FROM _dates ORDER BY option_value ASC;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( 'a', $results[0]->option_name ); $this->assertEquals( 'b', $results[1]->option_name ); @@ -2808,7 +2824,7 @@ public function testSelectZeroInDates() { // All three rows are readable. $this->assertQuery( 'SELECT option_name, option_value FROM _dates ORDER BY option_value ASC;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( '2020-00-15 00:00:00', $results[0]->option_value ); $this->assertEquals( '2020-01-00 00:00:00', $results[1]->option_value ); @@ -2816,7 +2832,7 @@ public function testSelectZeroInDates() { // Filtering by a zero-in-date value works. $this->assertQuery( "SELECT option_name FROM _dates WHERE option_value = '2020-00-15 00:00:00';" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 'zero-month', $results[0]->option_name ); } @@ -2830,7 +2846,7 @@ public function testDateFunctionsOnZeroDates() { $this->assertQuery( "INSERT INTO _dates (option_name, option_value) VALUES ('zero', '0000-00-00 00:00:00');" ); $this->assertQuery( 'SELECT YEAR(option_value) as y, MONTH(option_value) as m, DAY(option_value) as d FROM _dates;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 0, $results[0]->y ); $this->assertEquals( 0, $results[0]->m ); @@ -2839,7 +2855,7 @@ public function testDateFunctionsOnZeroDates() { public function testDefaultSqlModeDoesNotIncludeNoAutoValueOnZero() { $this->assertQuery( 'SELECT @@sql_mode AS mode;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertStringNotContainsString( 'NO_AUTO_VALUE_ON_ZERO', strtoupper( $results[0]->mode ) ); } @@ -2858,7 +2874,7 @@ public function testAutoIncrementZeroAdvancesSequenceByDefault() { ); $this->assertQuery( 'SELECT ID, option_name FROM _options ORDER BY ID;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( 1, $results[0]->ID ); $this->assertEquals( 'a', $results[0]->option_name ); @@ -2879,7 +2895,7 @@ public function testAutoIncrementZeroAdvancesSequenceForAllInsertShapes() { $this->assertQuery( "REPLACE INTO _options (ID, option_name, option_value) VALUES ('0', 'replace', '3');" ); $this->assertQuery( 'SELECT ID, option_name FROM _options ORDER BY ID;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( 1, $results[0]->ID ); $this->assertEquals( 2, $results[1]->ID ); @@ -2895,7 +2911,7 @@ public function testNoAutoValueOnZeroSqlMode() { ); $this->assertQuery( "SELECT ID FROM _options WHERE option_name = 'a';" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 0, $results[0]->ID ); @@ -2903,7 +2919,7 @@ public function testNoAutoValueOnZeroSqlMode() { "INSERT INTO _options (ID, option_name, option_value) VALUES (NULL, 'b', '2');" ); $this->assertQuery( "SELECT ID FROM _options WHERE option_name = 'b';" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 1, $results[0]->ID ); } @@ -2919,14 +2935,14 @@ public function testCaseInsensitiveSelect() { "INSERT INTO _tmp_table (name) VALUES ('first');" ); $this->assertQuery( "SELECT name FROM _tmp_table WHERE name = 'FIRST';" ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); $this->assertEquals( array( (object) array( 'name' => 'first', ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -2937,7 +2953,7 @@ public function testSelectBetweenDates() { $this->assertQuery( "INSERT INTO _dates (option_name, option_value) VALUES ('fourth', '2016-01-18T00:00:00Z');" ); $this->assertQuery( "SELECT * FROM _dates WHERE option_value BETWEEN '2016-01-15T00:00:00Z' AND '2016-01-17T00:00:00Z' ORDER BY ID;" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEquals( 'first', $results[0]->option_name ); $this->assertEquals( 'second', $results[1]->option_name ); @@ -2958,7 +2974,7 @@ public function testSelectFilterByDatesGtLt() { ORDER BY ID " ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 'second', $results[0]->option_name ); } @@ -2977,7 +2993,7 @@ public function testSelectFilterByDatesZeroHour() { AND MINUTE(option_value) = 42 ' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( 'first', $results[0]->option_name ); } @@ -2986,7 +3002,7 @@ public function testCorrectlyInsertsDatesAndStrings() { $this->assertQuery( "INSERT INTO _dates (option_name, option_value) VALUES ('2016-01-15T00:00:00Z', '2016-01-15T00:00:00Z');" ); $this->assertQuery( 'SELECT * FROM _dates' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '2016-01-15 00:00:00', $results[0]->option_value ); if ( '2016-01-15T00:00:00Z' !== $results[0]->option_name ) { @@ -2999,33 +3015,33 @@ public function testTransactionRollback() { $this->assertQuery( 'BEGIN' ); $this->assertQuery( "INSERT INTO _options (option_name) VALUES ('first');" ); $this->assertQuery( 'SELECT * FROM _options;' ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); $this->assertQuery( 'ROLLBACK' ); $this->assertQuery( 'SELECT * FROM _options;' ); - $this->assertCount( 0, $this->engine->get_query_results() ); + $this->assertCount( 0, $this->last_result ); } public function testTransactionCommit() { $this->assertQuery( 'BEGIN' ); $this->assertQuery( "INSERT INTO _options (option_name) VALUES ('first');" ); $this->assertQuery( 'SELECT * FROM _options;' ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); $this->assertQuery( 'COMMIT' ); $this->assertQuery( 'SELECT * FROM _options;' ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); } public function testStartTransactionCommand() { $this->assertQuery( 'START TRANSACTION' ); $this->assertQuery( "INSERT INTO _options (option_name) VALUES ('first');" ); $this->assertQuery( 'SELECT * FROM _options;' ); - $this->assertCount( 1, $this->engine->get_query_results() ); + $this->assertCount( 1, $this->last_result ); $this->assertQuery( 'ROLLBACK' ); $this->assertQuery( 'SELECT * FROM _options;' ); - $this->assertCount( 0, $this->engine->get_query_results() ); + $this->assertCount( 0, $this->last_result ); } public function testRepeatedTransactionCommands(): void { @@ -3055,7 +3071,7 @@ public function testCount() { $this->assertQuery( "INSERT INTO _options (option_name) VALUES ('second');" ); $this->assertQuery( 'SELECT COUNT(*) as count FROM _options;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertSame( '2', $results[0]->count ); } @@ -3067,7 +3083,7 @@ public function testUpdateDate() { $this->assertQuery( 'SELECT option_value FROM _dates' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '2003-05-27 10:08:48', $results[0]->option_value ); @@ -3077,7 +3093,7 @@ public function testUpdateDate() { $this->assertQuery( 'SELECT option_value FROM _dates' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '2001-05-27 10:08:48', $results[0]->option_value ); } @@ -3089,7 +3105,7 @@ public function testInsertDateLiteral() { $this->assertQuery( 'SELECT option_value FROM _dates' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '2003-05-27 10:08:48', $results[0]->option_value ); } @@ -3113,7 +3129,7 @@ public function testSelectDate1() { FROM _dates' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '2000', $results[0]->year ); $this->assertEquals( '5', $results[0]->month ); @@ -3138,13 +3154,13 @@ public function testSelectDate24HourFormat() { // HOUR(14:08) should yield 14 in the 24 hour format $this->assertQuery( "SELECT HOUR( _dates.option_value ) as hour FROM _dates WHERE option_name = 'second'" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '14', $results[0]->hour ); // HOUR(00:08) should yield 0 in the 24 hour format $this->assertQuery( "SELECT HOUR( _dates.option_value ) as hour FROM _dates WHERE option_name = 'first'" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0', $results[0]->hour ); @@ -3154,7 +3170,7 @@ public function testSelectDate24HourFormat() { WHERE HOUR(_dates.option_value) = 0 ' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); $this->assertEquals( '0', $results[0]->hour ); } @@ -3178,7 +3194,7 @@ public function testSelectByDateFunctions() { AND minute(option_value) = 42 ' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); } @@ -3196,7 +3212,7 @@ public function testSelectByDateFormat() { SELECT * FROM _dates WHERE DATE_FORMAT(option_value, '%H.%i') = 0.42 " ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); } @@ -3215,7 +3231,7 @@ public function testInsertOnDuplicateKey() { $this->assertEquals( 1, $result2 ); $this->assertQuery( 'SELECT COUNT(*) as cnt FROM _tmp_table' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 1, $results[0]->cnt ); } @@ -3229,11 +3245,11 @@ public function testCreateTableCompositePk() { KEY term_taxonomy_id (term_taxonomy_id) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci' ); - $result = $this->engine->query( 'INSERT INTO wptests_term_relationships VALUES (1,2,1),(1,3,2);' ); + $result = $this->query( 'INSERT INTO wptests_term_relationships VALUES (1,2,1),(1,3,2);' ); $this->assertEquals( 2, $result ); $this->expectExceptionMessage( 'UNIQUE constraint failed: wptests_term_relationships.object_id, wptests_term_relationships.term_taxonomy_id' ); - $this->engine->query( 'INSERT INTO wptests_term_relationships VALUES (1,2,2),(1,3,1);' ); + $this->query( 'INSERT INTO wptests_term_relationships VALUES (1,2,2),(1,3,1);' ); } public function testDescribeAccurate() { @@ -3253,7 +3269,7 @@ public function testDescribeAccurate() { $result = $this->assertQuery( 'DESCRIBE wptests_term_relationships;' ); $this->assertNotFalse( $result ); - $fields = $this->engine->get_query_results(); + $fields = $this->last_result; $this->assertEquals( array( @@ -3299,7 +3315,7 @@ public function testAlterTableAddColumnChangesMySQLDataType() { $result = $this->assertQuery( 'DESCRIBE _test;' ); $this->assertNotFalse( $result ); - $fields = $this->engine->get_query_results(); + $fields = $this->last_result; $this->assertEquals( array( @@ -3494,20 +3510,20 @@ public function testShowIndex() { 'Expression' => null, ), ), - $this->engine->get_query_results() + $this->last_result ); // With WHERE clause. $this->assertQuery( "SHOW INDEX FROM wptests_term_relationships WHERE Key_name = 'PRIMARY'" ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 2, $actual ); $this->assertQuery( 'SHOW INDEX FROM wptests_term_relationships WHERE Non_unique = 0' ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 2, $actual ); $this->assertQuery( "SHOW INDEX FROM wptests_term_relationships WHERE Index_type = 'FULLTEXT'" ); - $actual = $this->engine->get_query_results(); + $actual = $this->last_result; $this->assertCount( 2, $actual ); } @@ -3538,31 +3554,31 @@ public function testInsertOnDuplicateKeyCompositePk() { $this->assertEquals( 2, $result2 ); $this->assertQuery( 'SELECT COUNT(*) as cnt FROM wptests_term_relationships' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 2, $results[0]->cnt ); } public function testStringToFloatComparison() { $this->assertQuery( "SELECT ('00.42' = 0.4200) as cmp;" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; if ( 1 !== $results[0]->cmp ) { $this->markTestSkipped( 'Comparing a string and a float returns true in MySQL. In SQLite, they\'re different. Skipping. ' ); } $this->assertEquals( '1', $results[0]->cmp ); $this->assertQuery( "SELECT (0+'00.42' = 0.4200) as cmp;" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( '1', $results[0]->cmp ); } public function testZeroPlusStringToFloatComparison() { $this->assertQuery( "SELECT (0+'00.42' = 0.4200) as cmp;" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( '1', $results[0]->cmp ); $this->assertQuery( "SELECT 0+'1234abcd' = 1234 as cmp;" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( '1', $results[0]->cmp ); } @@ -3693,7 +3709,7 @@ public function testComplexSelectBasedOnDates() { LIMIT 0, 10' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 1, $results ); } @@ -3745,7 +3761,7 @@ public function testOrderByField() { 'sorting_order' => '3', ), ), - $this->engine->get_query_results() + $this->last_result ); $this->assertQuery( 'SELECT option_value FROM _options ORDER BY FIELD(option_name, "User 0000018", "User 0000019", "User 0000020")' ); @@ -3762,7 +3778,7 @@ public function testOrderByField() { 'option_value' => 'third', ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -3779,7 +3795,7 @@ public function testFetchedDataIsStringified() { 'ID' => '1', ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -3886,11 +3902,11 @@ public function testDeleteReturnsZeroAffectedRowsWhenNoMatchingRows() { $result = $this->assertQuery( 'DELETE FROM t WHERE id = 1' ); $this->assertSame( 1, $result ); - $this->assertSame( 1, $this->engine->get_last_return_value() ); + $this->assertSame( 1, $this->last_result ); $result = $this->assertQuery( 'DELETE FROM t WHERE id = 1' ); $this->assertSame( 0, $result ); - $this->assertSame( 0, $this->engine->get_last_return_value() ); + $this->assertSame( 0, $this->last_result ); } public function testUpdateReturnsZeroAffectedRowsWhenNoMatchingRows() { @@ -3902,7 +3918,7 @@ public function testUpdateReturnsZeroAffectedRowsWhenNoMatchingRows() { $result = $this->assertQuery( "UPDATE t SET val = 'c' WHERE id = 999" ); $this->assertSame( 0, $result ); - $this->assertSame( 0, $this->engine->get_last_return_value() ); + $this->assertSame( 0, $this->last_result ); } public function testTranslatesDoubleAlterTable() { @@ -3982,7 +3998,7 @@ public function testTranslatesUtf8Insert() { public function testRandUnseededReturnsFloatInRange() { for ( $i = 0; $i < 100; $i++ ) { $this->assertQuery( 'SELECT RAND() AS r' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $value = (float) $results[0]->r; $this->assertGreaterThanOrEqual( 0.0, $value ); $this->assertLessThan( 1.0, $value ); @@ -3998,7 +4014,7 @@ public function testRandSeededProducesDeterministicValues() { ); foreach ( $seeds_and_expected as $seed => $expected ) { $this->assertQuery( "SELECT RAND($seed) AS r" ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $value = (float) $results[0]->r; $this->assertEqualsWithDelta( $expected, $value, 1e-12, "RAND($seed) mismatch" ); } @@ -4009,13 +4025,13 @@ public function testRandSeededStateIsResetBetweenStatements() { // an intervening statement used a different seed. This pins down the // per-statement flush contract. $this->assertQuery( 'SELECT RAND(3) AS r' ); - $first_of_3 = (float) $this->engine->get_query_results()[0]->r; + $first_of_3 = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(5) AS r' ); - $first_of_5 = (float) $this->engine->get_query_results()[0]->r; + $first_of_5 = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(3) AS r' ); - $first_of_3_again = (float) $this->engine->get_query_results()[0]->r; + $first_of_3_again = (float) $this->last_result[0]->r; $this->assertSame( $first_of_3, $first_of_3_again ); $this->assertNotSame( $first_of_3, $first_of_5 ); @@ -4028,10 +4044,10 @@ public function testRandSeededAndUnseededInSameQueryAreIndependent() { // columns must vary between runs (probability of collision is ~2^-53 // per pair, so a match would indicate a shared state bug, not luck). $this->assertQuery( 'SELECT RAND(1) AS r1, RAND() AS r2, RAND() AS r3' ); - $run1 = $this->engine->get_query_results()[0]; + $run1 = $this->last_result[0]; $this->assertQuery( 'SELECT RAND(1) AS r1, RAND() AS r2, RAND() AS r3' ); - $run2 = $this->engine->get_query_results()[0]; + $run2 = $this->last_result[0]; // Seeded column is stable across runs. $this->assertSame( (float) $run1->r1, (float) $run2->r1 ); @@ -4054,7 +4070,7 @@ public function testRandSeededAndUnseededInSameQueryAreIndependent() { public function testRandMultiRowReturnsDifferentValues() { $this->assertQuery( "INSERT INTO _options (option_name, option_value) VALUES ('a', '1'), ('b', '2'), ('c', '3')" ); $this->assertQuery( 'SELECT RAND() AS r FROM _options' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $values = array_map( function ( $row ) { return $row->r; @@ -4072,7 +4088,7 @@ public function testRandSeededMultiRowProducesDeterministicSequence() { // from the MySQL 8.4 manual example "SELECT i, RAND(3) FROM t". $this->assertQuery( "INSERT INTO _options (option_name, option_value) VALUES ('a', '1'), ('b', '2'), ('c', '3')" ); $this->assertQuery( 'SELECT RAND(3) AS r FROM _options' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertCount( 3, $results ); $this->assertEqualsWithDelta( 0.90576975597606, (float) $results[0]->r, 1e-12 ); $this->assertEqualsWithDelta( 0.37307905813035, (float) $results[1]->r, 1e-12 ); @@ -4081,7 +4097,7 @@ public function testRandSeededMultiRowProducesDeterministicSequence() { // A second identical query must restart the sequence from seed 3, // not continue where the previous statement left off. $this->assertQuery( 'SELECT RAND(3) AS r FROM _options' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEqualsWithDelta( 0.90576975597606, (float) $results[0]->r, 1e-12 ); $this->assertEqualsWithDelta( 0.37307905813035, (float) $results[1]->r, 1e-12 ); $this->assertEqualsWithDelta( 0.14808605345719, (float) $results[2]->r, 1e-12 ); @@ -4095,14 +4111,14 @@ public function testRandNonConstantSeedReinitializesPerRow() { $this->assertQuery( "INSERT INTO _options (option_name, option_value) VALUES ('a', '1'), ('b', '2'), ('c', '3')" ); $this->assertQuery( 'SELECT RAND(CAST(option_value AS SIGNED)) AS r FROM _options ORDER BY option_name' ); - $per_row = $this->engine->get_query_results(); + $per_row = $this->last_result; $this->assertQuery( 'SELECT RAND(1) AS r' ); - $r1 = (float) $this->engine->get_query_results()[0]->r; + $r1 = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(2) AS r' ); - $r2 = (float) $this->engine->get_query_results()[0]->r; + $r2 = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(3) AS r' ); - $r3 = (float) $this->engine->get_query_results()[0]->r; + $r3 = (float) $this->last_result[0]->r; $this->assertEqualsWithDelta( $r1, (float) $per_row[0]->r, 1e-12 ); $this->assertEqualsWithDelta( $r2, (float) $per_row[1]->r, 1e-12 ); @@ -4117,7 +4133,7 @@ public function testRandOrderBy() { // Unseeded `ORDER BY RAND() LIMIT N` — the common "random sample" pattern. $this->assertQuery( 'SELECT option_name FROM _options ORDER BY RAND() LIMIT 2' ); - $rows = $this->engine->get_query_results(); + $rows = $this->last_result; $this->assertCount( 2, $rows ); foreach ( $rows as $row ) { $this->assertContains( $row->option_name, array( 'a', 'b', 'c', 'd', 'e' ) ); @@ -4134,9 +4150,9 @@ function ( $row ) { ); }; $this->assertQuery( 'SELECT option_name FROM _options ORDER BY RAND(1)' ); - $first = $extract( $this->engine->get_query_results() ); + $first = $extract( $this->last_result ); $this->assertQuery( 'SELECT option_name FROM _options ORDER BY RAND(1)' ); - $second = $extract( $this->engine->get_query_results() ); + $second = $extract( $this->last_result ); $this->assertSame( $first, $second ); $sorted = $first; sort( $sorted ); @@ -4149,7 +4165,7 @@ public function testRandNullIsEquivalentToZeroSeed() { $this->assertQuery( 'SELECT RAND(NULL) AS r' ); $this->assertEqualsWithDelta( 0.15522042769493574, - (float) $this->engine->get_query_results()[0]->r, + (float) $this->last_result[0]->r, 1e-12 ); @@ -4158,7 +4174,7 @@ public function testRandNullIsEquivalentToZeroSeed() { $this->assertQuery( 'SELECT RAND(NULLIF(1, 1)) AS r' ); $this->assertEqualsWithDelta( 0.15522042769493574, - (float) $this->engine->get_query_results()[0]->r, + (float) $this->last_result[0]->r, 1e-12 ); } @@ -4167,15 +4183,15 @@ public function testRandFloatSeedRoundsToNearestInteger() { // MySQL's val_int() on DOUBLE rounds to nearest, so RAND(3.9) is // equivalent to RAND(4) and RAND(3.1) to RAND(3). $this->assertQuery( 'SELECT RAND(3.9) AS r' ); - $from_float = (float) $this->engine->get_query_results()[0]->r; + $from_float = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(4) AS r' ); - $from_int = (float) $this->engine->get_query_results()[0]->r; + $from_int = (float) $this->last_result[0]->r; $this->assertSame( $from_int, $from_float ); $this->assertQuery( 'SELECT RAND(3.1) AS r' ); - $from_float = (float) $this->engine->get_query_results()[0]->r; + $from_float = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(3) AS r' ); - $from_int = (float) $this->engine->get_query_results()[0]->r; + $from_int = (float) $this->last_result[0]->r; $this->assertSame( $from_int, $from_float ); } @@ -4183,21 +4199,21 @@ public function testRandStringSeedIsCoercedLikeMySQL() { // Numeric strings are coerced through float-then-round; non-numeric // strings fall back to 0, matching MySQL's val_int() semantics. $this->assertQuery( "SELECT RAND('5') AS r" ); - $from_string = (float) $this->engine->get_query_results()[0]->r; + $from_string = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(5) AS r' ); - $from_int = (float) $this->engine->get_query_results()[0]->r; + $from_int = (float) $this->last_result[0]->r; $this->assertSame( $from_int, $from_string ); $this->assertQuery( "SELECT RAND('3.9') AS r" ); - $from_string = (float) $this->engine->get_query_results()[0]->r; + $from_string = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(4) AS r' ); - $from_int = (float) $this->engine->get_query_results()[0]->r; + $from_int = (float) $this->last_result[0]->r; $this->assertSame( $from_int, $from_string ); $this->assertQuery( "SELECT RAND('abc') AS r" ); - $from_bad_string = (float) $this->engine->get_query_results()[0]->r; + $from_bad_string = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(0) AS r' ); - $from_zero = (float) $this->engine->get_query_results()[0]->r; + $from_zero = (float) $this->last_result[0]->r; $this->assertSame( $from_zero, $from_bad_string ); } @@ -4206,9 +4222,9 @@ public function testRandNegativeSeedIsDeterministicAndInRange() { // before the LCG init). The exact value is defined by the LCG; this // test pins determinism and range, not a reference constant. $this->assertQuery( 'SELECT RAND(-1) AS r' ); - $v1 = (float) $this->engine->get_query_results()[0]->r; + $v1 = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(-1) AS r' ); - $v2 = (float) $this->engine->get_query_results()[0]->r; + $v2 = (float) $this->last_result[0]->r; $this->assertSame( $v1, $v2 ); $this->assertGreaterThanOrEqual( 0.0, $v1 ); $this->assertLessThan( 1.0, $v1 ); @@ -4221,7 +4237,7 @@ public function testRandMultipleCallSitesShareLcgState() { // second call advances the shared stream and returns the next // value. Pin the current behavior so any future change is explicit. $this->assertQuery( 'SELECT RAND(1) AS a, RAND(1) AS b' ); - $row = $this->engine->get_query_results()[0]; + $row = $this->last_result[0]; $this->assertEqualsWithDelta( 0.40540353712198, (float) $row->a, 1e-12 ); $this->assertNotEquals( (float) $row->a, (float) $row->b ); $this->assertGreaterThanOrEqual( 0.0, (float) $row->b ); @@ -4232,9 +4248,9 @@ public function testRandSeededResetsAcrossStatementsInsideTransaction() { // The per-statement flush contract must hold inside a transaction. $this->assertQuery( 'BEGIN' ); $this->assertQuery( 'SELECT RAND(1) AS r' ); - $a = (float) $this->engine->get_query_results()[0]->r; + $a = (float) $this->last_result[0]->r; $this->assertQuery( 'SELECT RAND(1) AS r' ); - $b = (float) $this->engine->get_query_results()[0]->r; + $b = (float) $this->last_result[0]->r; $this->assertQuery( 'COMMIT' ); $this->assertSame( $a, $b ); $this->assertEqualsWithDelta( 0.40540353712198, $a, 1e-12 ); @@ -4244,9 +4260,9 @@ public function testRandInWhereClauseRuns() { $this->assertQuery( "INSERT INTO _options (option_name, option_value) VALUES ('a', '1'), ('b', '2'), ('c', '3')" ); // Sanity: a predicate that is always true / always false. $this->assertQuery( 'SELECT COUNT(*) AS c FROM _options WHERE RAND() < 2' ); - $this->assertSame( 3, (int) $this->engine->get_query_results()[0]->c ); + $this->assertSame( 3, (int) $this->last_result[0]->c ); $this->assertQuery( 'SELECT COUNT(*) AS c FROM _options WHERE RAND() > 2' ); - $this->assertSame( 0, (int) $this->engine->get_query_results()[0]->c ); + $this->assertSame( 0, (int) $this->last_result[0]->c ); } public function testRandInUpdateAndInsert() { @@ -4255,7 +4271,7 @@ public function testRandInUpdateAndInsert() { $this->assertQuery( "SELECT option_value FROM _options WHERE option_name = 'a'" ); $this->assertEqualsWithDelta( 0.40540353712198, - (float) $this->engine->get_query_results()[0]->option_value, + (float) $this->last_result[0]->option_value, 1e-12 ); @@ -4263,7 +4279,7 @@ public function testRandInUpdateAndInsert() { $this->assertQuery( "SELECT option_value FROM _options WHERE option_name = 'b'" ); $this->assertEqualsWithDelta( 0.40540353712198, - (float) $this->engine->get_query_results()[0]->option_value, + (float) $this->last_result[0]->option_value, 1e-12 ); } @@ -4283,7 +4299,7 @@ public function testTranslatesUtf8SELECT() { $this->assertEquals( array( (object) array( 'ą' => 'ąłółźćę†' ) ), - $this->engine->get_query_results() + $this->last_result ); $this->assertQuery( @@ -4292,7 +4308,7 @@ public function testTranslatesUtf8SELECT() { $this->assertEquals( array( (object) array( 'ą' => 'ąłółźćę†' ) ), - $this->engine->get_query_results() + $this->last_result ); $this->assertQuery( 'DELETE FROM _options' ); @@ -4604,7 +4620,7 @@ public function testDatabaseFunction(): void { "CONCAT('test-', (SELECT DATABASE()))" => 'test-wp', ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -4750,7 +4766,7 @@ public function testCharLength(): void { (object) array( 'len' => '2' ), (object) array( 'len' => '3' ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -4768,7 +4784,7 @@ public function testNullCharactersInStrings(): void { array( (object) array( 'name' => "a\0b" ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -4891,7 +4907,7 @@ public function testUnion(): void { (object) array( 'name' => 'a' ), (object) array( 'name' => 'b' ), ), - $this->engine->get_query_results() + $this->last_result ); $this->assertQuery( @@ -4901,7 +4917,7 @@ public function testUnion(): void { array( (object) array( 'name' => 'a' ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -4918,7 +4934,7 @@ public function testUnionAll(): void { (object) array( 'name' => 'a' ), (object) array( 'name' => 'b' ), ), - $this->engine->get_query_results() + $this->last_result ); $this->assertQuery( @@ -4929,7 +4945,7 @@ public function testUnionAll(): void { (object) array( 'name' => 'a' ), (object) array( 'name' => 'a' ), ), - $this->engine->get_query_results() + $this->last_result ); } @@ -4953,7 +4969,7 @@ public function testShowCreateTableWithEmptyDatetimeDefault() { $this->assertQuery( 'SHOW CREATE TABLE _tmp_table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( "CREATE TABLE `_tmp_table` ( @@ -4992,7 +5008,7 @@ public function testShowCreateTablePreservesKeyLengths() { $this->assertQuery( 'SHOW CREATE TABLE _tmp__table;' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 'CREATE TABLE `_tmp__table` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, @@ -6308,14 +6324,14 @@ public function testNoBackslashEscapesSqlModeWithPatternMatching(): void { } public function testQuoteMysqlUtf8StringLiteral(): void { - // WP_SQLite_Driver::quote_mysql_utf8_string_literal() is a private method. + // WP_MySQL_On_SQLite::quote_mysql_utf8_string_literal() is a private method. // Let's use a closure bound to the driver instance to access it for tests. $quote = Closure::bind( function ( string $utf8_literal ) { return $this->quote_mysql_utf8_string_literal( $utf8_literal ); }, $this->engine, - WP_SQLite_Driver::class + WP_MySQL_On_SQLite::class ); $backslash = chr( 92 ); @@ -6967,13 +6983,16 @@ public function testComplexInformationSchemaQueries(): void { } public function testDatabaseNameEmpty(): void { - $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; - $pdo = new $pdo_class( 'sqlite::memory:' ); - $connection = new WP_SQLite_Connection( array( 'pdo' => $pdo ) ); - + $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; + $pdo = new $pdo_class( 'sqlite::memory:' ); $this->expectException( WP_SQLite_Driver_Exception::class ); $this->expectExceptionMessage( 'The database name cannot be empty.' ); - new WP_SQLite_Driver( $connection, '' ); + new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=', + null, + null, + array( 'pdo' => $pdo ) + ); } public function testSelectColumnNames(): void { @@ -7323,7 +7342,7 @@ public function testTransactionSavepoints(): void { public function testRowLeveLockingClauses() { $this->assertQuery( 'CREATE TABLE t (name VARCHAR(255), value VARCHAR(255))' ); - $this->engine->query( "INSERT INTO t (name, value) VALUES ('test_lock', '123')" ); + $this->query( "INSERT INTO t (name, value) VALUES ('test_lock', '123')" ); // FOR UPDATE $res = $this->assertQuery( "SELECT value FROM t WHERE name = 'test_lock' FOR UPDATE" ); @@ -10193,7 +10212,7 @@ public function testAlterTableAddCheckConstraint(): void { // SHOW CREATE TABLE $this->assertQuery( 'SHOW CREATE TABLE t' ); - $result = $this->engine->get_query_results(); + $result = $this->last_result; $this->assertEquals( implode( "\n", @@ -10231,7 +10250,7 @@ public function testAlterTableDropCheckConstraint(): void { // SHOW CREATE TABLE $this->assertQuery( 'SHOW CREATE TABLE t' ); - $result = $this->engine->get_query_results(); + $result = $this->last_result; $this->assertEquals( implode( "\n", @@ -10263,7 +10282,7 @@ public function testCheckConstraintNotEnforced(): void { // SHOW CREATE TABLE $this->assertQuery( 'SHOW CREATE TABLE t' ); - $result = $this->engine->get_query_results(); + $result = $this->last_result; $this->assertEquals( implode( "\n", @@ -10285,7 +10304,7 @@ function ( $name ) { $this->main_db_name = $name; }, $this->engine, - WP_SQLite_Driver::class + WP_MySQL_On_SQLite::class ); // Default database name. @@ -10327,7 +10346,7 @@ function ( $name ) { $this->main_db_name = $name; }, $this->engine, - WP_SQLite_Driver::class + WP_MySQL_On_SQLite::class ); $this->assertQuery( 'CREATE TABLE t (id INT, db_name TEXT)' ); @@ -10373,7 +10392,7 @@ function ( $name ) { $this->main_db_name = $name; }, $this->engine, - WP_SQLite_Driver::class + WP_MySQL_On_SQLite::class ); // Default database name. @@ -11204,7 +11223,7 @@ public function testCastValuesOnInsert(): void { $this->assertQuery( "INSERT INTO t VALUES ('2')" ); $this->assertQuery( "INSERT INTO t VALUES ('3.0')" ); - $is_legacy_sqlite = version_compare( $this->engine->get_sqlite_version(), WP_PDO_MySQL_On_SQLite::MINIMUM_SQLITE_VERSION, '<' ); + $is_legacy_sqlite = version_compare( $this->engine->get_sqlite_version(), WP_MySQL_On_SQLite::MINIMUM_SQLITE_VERSION, '<' ); if ( $is_legacy_sqlite ) { $this->assertQuery( "INSERT INTO t VALUES ('4.5')" ); $this->assertQuery( 'INSERT INTO t VALUES (0x05)' ); @@ -11711,7 +11730,7 @@ public function testCastValuesOnUpdate(): void { $this->assertQuery( "UPDATE t SET value = '3.0'" ); $this->assertSame( '3', $this->assertQuery( 'SELECT * FROM t' )[0]->value ); - $is_legacy_sqlite = version_compare( $this->engine->get_sqlite_version(), WP_PDO_MySQL_On_SQLite::MINIMUM_SQLITE_VERSION, '<' ); + $is_legacy_sqlite = version_compare( $this->engine->get_sqlite_version(), WP_MySQL_On_SQLite::MINIMUM_SQLITE_VERSION, '<' ); if ( $is_legacy_sqlite ) { $this->assertQuery( "UPDATE t SET value = '4.5'" ); $this->assertQuery( 'UPDATE t SET value = 0x05' ); @@ -12338,7 +12357,7 @@ public function testUpdateErrorsInNonStrictMode(): void { } public function testVersionFunction(): void { - $result = $this->engine->query( 'SELECT VERSION()' ); + $result = $this->query( 'SELECT VERSION()' ); $this->assertSame( '8.0.38', $result[0]->{'VERSION()'} ); } @@ -12417,7 +12436,7 @@ public function testCreateTableWithDefaultNowFunction(): void { // SHOW CREATE TABLE $this->assertQuery( 'SHOW CREATE TABLE test_now_default' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( implode( "\n", @@ -12433,7 +12452,7 @@ public function testCreateTableWithDefaultNowFunction(): void { // DESCRIBE $this->assertQuery( 'DESCRIBE test_now_default' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( @@ -12475,14 +12494,14 @@ public function testCreateTableWithDefaultExpressions(): void { // Insert a row and verify the default values $this->assertQuery( 'INSERT INTO t (id) VALUES (1)' ); $this->assertQuery( 'SELECT * FROM t WHERE id = 1' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( 3, $results[0]->col1 ); $this->assertStringStartsWith( ( gmdate( 'Y' ) + 1 ) . '-', $results[0]->col2 ); $this->assertEquals( 'ab', $results[0]->col3 ); // SHOW CREATE TABLE $this->assertQuery( 'SHOW CREATE TABLE t' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( implode( "\n", @@ -12500,7 +12519,7 @@ public function testCreateTableWithDefaultExpressions(): void { // DESCRIBE $this->assertQuery( 'DESCRIBE t' ); - $results = $this->engine->get_query_results(); + $results = $this->last_result; $this->assertEquals( array( (object) array( diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Translation_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Translation_Tests.php similarity index 99% rename from packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Translation_Tests.php rename to packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Translation_Tests.php index 119ec3ac0..894715ad5 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Translation_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Translation_Tests.php @@ -2,7 +2,7 @@ use PHPUnit\Framework\TestCase; -class WP_SQLite_Driver_Translation_Tests extends TestCase { +class WP_MySQL_On_SQLite_Translation_Tests extends TestCase { const GRAMMAR_PATH = __DIR__ . '/../src/mysql/mysql-grammar.php'; /** @@ -11,7 +11,7 @@ class WP_SQLite_Driver_Translation_Tests extends TestCase { private static $grammar; /** - * @var WP_SQLite_Driver + * @var WP_MySQL_On_SQLite */ private $driver; @@ -25,10 +25,8 @@ public static function setUpBeforeClass(): void { } public function setUp(): void { - $this->driver = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'path' => ':memory:' ) ), - 'wp' - ); + $this->driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp' ); + $this->driver->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); $supports_strict_tables = version_compare( $this->driver->get_sqlite_version(), '3.37.0', '>=' ); $this->strict_suffix = $supports_strict_tables ? ' STRICT' : ''; diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php index f598f94ec..d1a8bae2c 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_Connection_Tests.php @@ -179,15 +179,13 @@ public function testExplicitJournalModeSurfacesFailureWhenWalIsUnavailable(): vo } public function testDriverKeepsConfiguredJournalMode(): void { - $connection = new WP_SQLite_Connection( - array( - 'path' => $this->db_path, - 'journal_mode' => 'DELETE', - ) + $driver = new WP_MySQL_On_SQLite( + sprintf( 'mysql-on-sqlite:path=%s;dbname=wp', $this->db_path ), + null, + null, + array( 'journal_mode' => 'DELETE' ) ); - $driver = new WP_SQLite_Driver( $connection, 'wp' ); - $this->assertSame( 'delete', $this->get_journal_mode( $driver->get_connection() ) ); } diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php index 124c4ad82..6ff39c7f5 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_Information_Schema_Reconstructor_Tests.php @@ -11,7 +11,7 @@ class WP_SQLite_Information_Schema_Reconstructor_Tests extends TestCase { PRIMARY KEY(`table`, `column_or_index`) )'; - /** @var WP_SQLite_Driver */ + /** @var WP_MySQL_On_SQLite */ private $engine; /** @var WP_SQLite_Information_Schema_Reconstructor */ @@ -43,13 +43,16 @@ function wp_get_db_schema() { public function setUp(): void { $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; $this->sqlite = new $pdo_class( 'sqlite::memory:' ); - $this->engine = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'pdo' => $this->sqlite ) ), - 'wp' + $this->engine = new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=wp', + null, + null, + array( 'pdo' => $this->sqlite ) ); + $this->engine->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); $builder = new WP_SQLite_Information_Schema_Builder( - WP_PDO_MySQL_On_SQLite::RESERVED_PREFIX, + WP_MySQL_On_SQLite::RESERVED_PREFIX, $this->engine->get_connection() ); @@ -426,7 +429,8 @@ public function testInvalidDataTypeCacheDataForIndexDefinition(): void { } private function assertQuery( $sql ) { - $retval = $this->engine->query( $sql ); + $statement = $this->engine->query( $sql, PDO::FETCH_OBJ ); + $retval = $statement->columnCount() > 0 ? $statement->fetchAll() : $statement->rowCount(); $this->assertNotFalse( $retval ); return $retval; } diff --git a/packages/mysql-on-sqlite/tests/bootstrap.php b/packages/mysql-on-sqlite/tests/bootstrap.php index 3afa3b9dd..424d09aec 100644 --- a/packages/mysql-on-sqlite/tests/bootstrap.php +++ b/packages/mysql-on-sqlite/tests/bootstrap.php @@ -5,7 +5,7 @@ // When on an older SQLite version, enable unsafe back compatibility. $sqlite_version = ( new PDO( 'sqlite::memory:' ) )->query( 'SELECT SQLITE_VERSION();' )->fetch()[0]; -if ( version_compare( $sqlite_version, WP_PDO_MySQL_On_SQLite::MINIMUM_SQLITE_VERSION, '<' ) ) { +if ( version_compare( $sqlite_version, WP_MySQL_On_SQLite::MINIMUM_SQLITE_VERSION, '<' ) ) { define( 'WP_SQLITE_UNSAFE_ENABLE_UNSUPPORTED_VERSIONS', true ); } diff --git a/packages/mysql-on-sqlite/tests/tools/dump-sqlite-query.php b/packages/mysql-on-sqlite/tests/tools/dump-sqlite-query.php index 681351af0..9ae8b53c7 100644 --- a/packages/mysql-on-sqlite/tests/tools/dump-sqlite-query.php +++ b/packages/mysql-on-sqlite/tests/tools/dump-sqlite-query.php @@ -2,10 +2,7 @@ require_once __DIR__ . '/../../src/load.php'; -$driver = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'path' => ':memory:' ) ), - 'wp' -); +$driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp' ); $query = "SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.t1_id WHERE t1.name = 'abc'"; diff --git a/packages/mysql-on-sqlite/tests/tools/verify-native-parser-extension.php b/packages/mysql-on-sqlite/tests/tools/verify-native-parser-extension.php index 84e99ba58..e12683454 100644 --- a/packages/mysql-on-sqlite/tests/tools/verify-native-parser-extension.php +++ b/packages/mysql-on-sqlite/tests/tools/verify-native-parser-extension.php @@ -63,17 +63,17 @@ function wp_sqlite_verify_native_parser_extension(): void { wp_sqlite_native_parser_verification_fail( 'Native parser did not produce the expected query AST.' ); } - $driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); + $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' ); $parser = $driver->create_parser( 'SELECT 1' ); wp_sqlite_assert_native_parser_delegate( $parser, - 'WP_PDO_MySQL_On_SQLite did not create a native parser delegate.' + 'WP_MySQL_On_SQLite did not create a native parser delegate.' ); $parser->next_query(); $ast = $parser->get_query_ast(); if ( ! ( $ast instanceof WP_MySQL_Native_Parser_Node ) ) { - wp_sqlite_native_parser_verification_fail( 'WP_PDO_MySQL_On_SQLite did not produce a native-backed AST.' ); + wp_sqlite_native_parser_verification_fail( 'WP_MySQL_On_SQLite did not produce a native-backed AST.' ); } $reflection = new ReflectionObject( $ast ); diff --git a/packages/mysql-proxy/src/Adapter/class-sqlite-adapter.php b/packages/mysql-proxy/src/Adapter/class-sqlite-adapter.php index adcf88efc..bd76f561a 100644 --- a/packages/mysql-proxy/src/Adapter/class-sqlite-adapter.php +++ b/packages/mysql-proxy/src/Adapter/class-sqlite-adapter.php @@ -2,27 +2,27 @@ namespace WP_MySQL_Proxy\Adapter; +use PDO; use PDOException; use Throwable; use WP_MySQL_Proxy\MySQL_Result; -use WP_SQLite_Connection; -use WP_SQLite_Driver; +use WP_MySQL_On_SQLite; use WP_MySQL_Proxy\MySQL_Protocol; require_once __DIR__ . '/../../../../wp-pdo-mysql-on-sqlite.php'; class SQLite_Adapter implements Adapter { - /** @var WP_SQLite_Driver */ + /** @var WP_MySQL_On_SQLite */ private $sqlite_driver; public function __construct( $sqlite_database_path ) { define( 'FQDB', $sqlite_database_path ); define( 'FQDBDIR', dirname( FQDB ) . '/' ); - $this->sqlite_driver = new WP_SQLite_Driver( - new WP_SQLite_Connection( array( 'path' => $sqlite_database_path ) ), - 'sqlite_database' + $this->sqlite_driver = new WP_MySQL_On_SQLite( + sprintf( 'mysql-on-sqlite:path=%s;dbname=sqlite_database', str_replace( ';', ';;', $sqlite_database_path ) ) ); + $this->sqlite_driver->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); } public function handle_query( string $query ): MySQL_Result { @@ -32,12 +32,12 @@ public function handle_query( string $query ): MySQL_Result { $rows = array(); try { - $return_value = $this->sqlite_driver->query( $query ); + $statement = $this->sqlite_driver->query( $query, PDO::FETCH_OBJ ); $last_insert_id = $this->sqlite_driver->get_insert_id() ?? null; - if ( is_numeric( $return_value ) ) { - $affected_rows = (int) $return_value; - } elseif ( is_array( $return_value ) ) { - $rows = $return_value; + if ( $statement->columnCount() > 0 ) { + $rows = $statement->fetchAll(); + } else { + $affected_rows = $statement->rowCount(); } if ( $this->sqlite_driver->get_last_column_count() > 0 ) { $columns = $this->computeColumnInfo(); diff --git a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php index 072030e7f..b94c66d20 100644 --- a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php +++ b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php @@ -16,7 +16,7 @@ class WP_SQLite_DB extends wpdb { /** * Database Handle * - * @var WP_SQLite_Driver + * @var WP_MySQL_On_SQLite */ protected $dbh; @@ -95,7 +95,7 @@ public function get_col_charset( $table, $column ) { */ public function set_sql_mode( $modes = array() ) { if ( empty( $modes ) ) { - $result = $this->dbh->query( 'SELECT @@SESSION.sql_mode' ); + $result = $this->dbh->query( 'SELECT @@SESSION.sql_mode' )->fetchAll( PDO::FETCH_OBJ ); // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO if ( ! isset( $result[0] ) ) { return; } @@ -311,14 +311,23 @@ public function db_connect( $allow_bail = true ) { $this->ensure_database_directory( FQDB ); try { - $connection = new WP_SQLite_Connection( - array( - 'pdo' => $pdo, - 'path' => FQDB, - 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, - ) + $options = array( + 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, ); - $this->dbh = new WP_SQLite_Driver( $connection, $this->dbname ); + if ( null !== $pdo ) { + $options['pdo'] = $pdo; + } + $this->dbh = new WP_MySQL_On_SQLite( + sprintf( + 'mysql-on-sqlite:path=%s;dbname=%s', + str_replace( ';', ';;', FQDB ), + str_replace( ';', ';;', $this->dbname ) + ), + null, + null, + $options + ); + $this->dbh->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO $GLOBALS['@pdo'] = $this->dbh->get_connection()->get_pdo(); } catch ( Throwable $e ) { $this->last_error = $this->format_error_message( $e ); @@ -435,7 +444,7 @@ public function query( $query ) { if ( preg_match( '/^\s*(create|alter|truncate|drop)\s/i', $query ) ) { $return_val = true; } elseif ( preg_match( '/^\s*(insert|delete|update|replace)\s/i', $query ) ) { - $this->rows_affected = $this->dbh->get_last_return_value(); + $this->rows_affected = $this->result->rowCount(); // Take note of the insert_id. if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) { @@ -447,9 +456,9 @@ public function query( $query ) { } else { $num_rows = 0; - if ( is_array( $this->result ) ) { - $this->last_result = $this->result; - $num_rows = count( $this->result ); + if ( $this->result->columnCount() > 0 ) { + $this->last_result = $this->result->fetchAll(); + $num_rows = count( $this->last_result ); } // Log and return the number of rows selected. @@ -500,7 +509,7 @@ private function _do_query( $query ) { } try { - $this->result = $this->dbh->query( $query ); + $this->result = $this->dbh->query( $query, PDO::FETCH_OBJ ); // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO } catch ( Throwable $e ) { $this->last_error = $this->format_error_message( $e ); } diff --git a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php index ec73f2f04..647a0293e 100644 --- a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php +++ b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/install-functions.php @@ -27,15 +27,16 @@ function sqlite_make_db_sqlite() { try { $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO $pdo = new $pdo_class( 'sqlite:' . FQDB, null, null, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ) ); // phpcs:ignore WordPress.DB.RestrictedClasses - $translator = new WP_SQLite_Driver( - new WP_SQLite_Connection( - array( - 'pdo' => $pdo, - 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, - ) - ), - $wpdb->dbname + $translator = new WP_MySQL_On_SQLite( + sprintf( 'mysql-on-sqlite:dbname=%s', $wpdb->dbname ), + null, + null, + array( + 'pdo' => $pdo, + 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, + ) ); + $translator->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO } catch ( PDOException $err ) { $err_data = $err->errorInfo; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $message = 'Database connection error!
'; @@ -57,7 +58,7 @@ function sqlite_make_db_sqlite() { } $translator->commit(); } catch ( PDOException $err ) { - $translator->rollback(); + $translator->rollBack(); $message = sprintf( 'Error occurred while creating tables or indexes...
Query was: %s
', var_export( $query, true )