diff --git a/.gitattributes b/.gitattributes index 693ea9681..5b0cf7f1f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,5 +10,4 @@ wp-setup.sh export-ignore /grammar-tools export-ignore /packages export-ignore /tests export-ignore -/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php export-ignore /wordpress export-ignore diff --git a/packages/mysql-on-sqlite/src/load.php b/packages/mysql-on-sqlite/src/load.php index 165e27e97..8ef704366 100644 --- a/packages/mysql-on-sqlite/src/load.php +++ b/packages/mysql-on-sqlite/src/load.php @@ -36,10 +36,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-mysql-on-sqlite-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-mysql-on-sqlite.php'; -require_once __DIR__ . '/sqlite/class-wp-pdo-proxy-statement.php'; +require_once __DIR__ . '/sqlite/class-wp-mysql-on-sqlite-statement.php'; diff --git a/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-lexer.php b/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-lexer.php index d6ee9970e..cacf63a81 100644 --- a/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-lexer.php +++ b/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-lexer.php @@ -16,6 +16,8 @@ * https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/grammars/MySQLLexer.g4 * https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/grammars/predefined.tokens * https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/mysql/MySQLBaseLexer.cpp + * + * @access private */ class WP_MySQL_Lexer { /** diff --git a/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-parser.php b/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-parser.php index 69282b9c4..0417085fe 100644 --- a/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-parser.php +++ b/packages/mysql-on-sqlite/src/mysql/class-wp-mysql-parser.php @@ -1,5 +1,10 @@ */ diff --git a/packages/mysql-on-sqlite/src/mysql/native/trait-wp-mysql-native-parser-impl.php b/packages/mysql-on-sqlite/src/mysql/native/trait-wp-mysql-native-parser-impl.php index c53e96e53..52628831a 100644 --- a/packages/mysql-on-sqlite/src/mysql/native/trait-wp-mysql-native-parser-impl.php +++ b/packages/mysql-on-sqlite/src/mysql/native/trait-wp-mysql-native-parser-impl.php @@ -13,6 +13,8 @@ * * Adding a public method here is enough to plumb a new public method * through to the native parser; the using class does not need touching. + * + * @access private */ trait WP_MySQL_Native_Parser_Impl { /** diff --git a/packages/mysql-on-sqlite/src/parser/class-wp-parser-grammar.php b/packages/mysql-on-sqlite/src/parser/class-wp-parser-grammar.php index 9bf30b973..5e9222112 100644 --- a/packages/mysql-on-sqlite/src/parser/class-wp-parser-grammar.php +++ b/packages/mysql-on-sqlite/src/parser/class-wp-parser-grammar.php @@ -8,6 +8,8 @@ * representation, and precomputes a lookup table for quick branch selection. * * @TODO: Add more details about the grammar implementation. + * + * @access private */ class WP_Parser_Grammar { /** diff --git a/packages/mysql-on-sqlite/src/parser/class-wp-parser-node.php b/packages/mysql-on-sqlite/src/parser/class-wp-parser-node.php index b61f38d5e..c64c83db8 100644 --- a/packages/mysql-on-sqlite/src/parser/class-wp-parser-node.php +++ b/packages/mysql-on-sqlite/src/parser/class-wp-parser-node.php @@ -8,6 +8,8 @@ * Each node can contain children, consisting of other nodes and grammar tokens. * In this way, a parser node constitutes a recursive structure that represents * a parse (sub)tree at each level of the full grammar tree. + * + * @access private */ class WP_Parser_Node { /** diff --git a/packages/mysql-on-sqlite/src/parser/class-wp-parser-token.php b/packages/mysql-on-sqlite/src/parser/class-wp-parser-token.php index 4132ba382..0f4ea54b2 100644 --- a/packages/mysql-on-sqlite/src/parser/class-wp-parser-token.php +++ b/packages/mysql-on-sqlite/src/parser/class-wp-parser-token.php @@ -7,6 +7,8 @@ * In a parse tree, a token represent a leaf, that is, a node without children. * It is a simple generic container for a token ID and value, that can be used * as a base class and extended for specific use cases. + * + * @access private */ class WP_Parser_Token { /** diff --git a/packages/mysql-on-sqlite/src/parser/class-wp-parser.php b/packages/mysql-on-sqlite/src/parser/class-wp-parser.php index 4436892fa..9953f1a58 100644 --- a/packages/mysql-on-sqlite/src/parser/class-wp-parser.php +++ b/packages/mysql-on-sqlite/src/parser/class-wp-parser.php @@ -7,6 +7,8 @@ * * @TODO: Add a detailed description and list the properties that a grammar must * satisfy in order to be supported by this parser (e.g., no left recursion). + * + * @access private */ class WP_Parser { protected $grammar; diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite-exception.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite-exception.php new file mode 100644 index 000000000..83cf80fbc --- /dev/null +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite-exception.php @@ -0,0 +1,33 @@ +code = $code; + $this->driver = $driver; + } + + public function get_driver(): WP_MySQL_On_SQLite { + return $this->driver; + } +} diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-proxy-statement.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite-statement.php similarity index 94% rename from packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-proxy-statement.php rename to packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite-statement.php index f56340d70..af471f6f8 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-pdo-proxy-statement.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite-statement.php @@ -26,7 +26,12 @@ * we conditionally define traits with different APIs based on the PHP version. */ if ( PHP_VERSION_ID < 80000 ) { - trait WP_PDO_Proxy_Statement_PHP_Compat { + /** + * PHP compatibility methods for WP_MySQL_On_SQLite_Statement. + * + * @access private + */ + trait WP_MySQL_On_SQLite_Statement_PHP_Compat { /** * Set the default fetch mode for this statement. * @@ -61,7 +66,12 @@ public function fetchAll( $mode = null, $class_name = null, $constructor_args = } } } else { - trait WP_PDO_Proxy_Statement_PHP_Compat { + /** + * PHP compatibility methods for WP_MySQL_On_SQLite_Statement. + * + * @access private + */ + trait WP_MySQL_On_SQLite_Statement_PHP_Compat { /** * Set the default fetch mode for this statement. * @@ -88,10 +98,10 @@ public function fetchAll( $mode = PDO::FETCH_DEFAULT, ...$args ): array { } /** - * PDOStatement implementation that operates on in-memory data. + * PDOStatement implementation for MySQL-on-SQLite query results. * - * This class implements a complete PDOStatement interface on top of PHP arrays. - * It is used for result sets that are composed or transformed in the PHP layer. + * Delegates operations to the underlying SQLite statement while adapting + * MySQL-specific behavior such as affected row counts. * * PDO supports the following fetch modes: * - PDO::FETCH_DEFAULT: current default fetch mode (available from PHP 8.0) @@ -108,8 +118,8 @@ public function fetchAll( $mode = PDO::FETCH_DEFAULT, ...$args ): array { * - PDO::FETCH_BOUND: bind values to PHP variables, can't be used with fetchAll() * - PDO::FETCH_FUNC: custom function, only works with fetchAll(), can't be default [1 extra arg] */ -class WP_PDO_Proxy_Statement extends PDOStatement { - use WP_PDO_Proxy_Statement_PHP_Compat; +class WP_MySQL_On_SQLite_Statement extends PDOStatement { + use WP_MySQL_On_SQLite_Statement_PHP_Compat; /** * The original PDO statement. @@ -347,7 +357,7 @@ public function debugDumpParams(): ?bool { /** * Fetch all remaining rows from the result set. * - * This is used internally by the "WP_PDO_Proxy_Statement_PHP_Compat" trait, + * This is used internally by the "WP_MySQL_On_SQLite_Statement_PHP_Compat" trait, * that is defined conditionally based on the current PHP version. * * @param int $mode The fetch mode to use. @@ -361,7 +371,7 @@ private function fetchAllRows( $mode = null, ...$args ): array { /** * Set the default fetch mode for this statement. * - * This is used internally by the "WP_PDO_Proxy_Statement_PHP_Compat" trait, + * This is used internally by the "WP_MySQL_On_SQLite_Statement_PHP_Compat" trait, * that is defined conditionally based on the current PHP version. * * @param int $mode The fetch mode to set as the default. diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php index 7e06150b2..c45a2a8e9 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php @@ -18,7 +18,7 @@ class WP_MySQL_On_SQLite extends PDO { /** * The path to the MySQL SQL grammar file. */ - const MYSQL_GRAMMAR_PATH = __DIR__ . '/../mysql/mysql-grammar.php'; + private const MYSQL_GRAMMAR_PATH = __DIR__ . '/../mysql/mysql-grammar.php'; /** * The minimum required version of SQLite. @@ -31,6 +31,8 @@ class WP_MySQL_On_SQLite extends PDO { /** * An identifier prefix for internal database objects. * + * @access private + * * @TODO: Do not allow accessing objects with this prefix. */ const RESERVED_PREFIX = '_wp_sqlite_'; @@ -40,6 +42,8 @@ class WP_MySQL_On_SQLite extends PDO { * * This special table is used to emulate MySQL global variables and to store * some internal configuration values. + * + * @access private */ const GLOBAL_VARIABLES_TABLE_NAME = self::RESERVED_PREFIX . 'global_variables'; @@ -47,13 +51,15 @@ class WP_MySQL_On_SQLite extends PDO { * Name of the connection-private TEMP table used to build empty result sets * without acquiring a write lock on the database. See create_result_statement_from_data(). */ - const EMPTY_RESULT_TABLE_NAME = self::RESERVED_PREFIX . 'empty_result'; + private const EMPTY_RESULT_TABLE_NAME = self::RESERVED_PREFIX . 'empty_result'; /** * The name of the SQLite driver version variable. * * This internal variable is used to store the latest version of the SQLite * driver that was used to initialize and configure the SQLite database. + * + * @access private */ const DRIVER_VERSION_VARIABLE_NAME = self::RESERVED_PREFIX . 'driver_version'; @@ -62,7 +68,7 @@ class WP_MySQL_On_SQLite extends PDO { * * This is used to translate a MySQL data type to an SQLite data type. */ - const DATA_TYPE_MAP = array( + private const DATA_TYPE_MAP = array( // Numeric data types: WP_MySQL_Lexer::BIT_SYMBOL => 'INTEGER', WP_MySQL_Lexer::BOOL_SYMBOL => 'INTEGER', @@ -128,7 +134,7 @@ class WP_MySQL_On_SQLite extends PDO { * INFORMATION_SCHEMA tables. They keys are MySQL data types normalized * as they appear in the INFORMATION_SCHEMA. Values are SQLite data types. */ - const DATA_TYPE_STRING_MAP = array( + private const DATA_TYPE_STRING_MAP = array( // Numeric data types: 'bit' => 'INTEGER', 'bool' => 'INTEGER', @@ -199,7 +205,7 @@ class WP_MySQL_On_SQLite extends PDO { * https://www.sqlite.org/lang_datefunc.html * https://strftime.org/ */ - const MYSQL_DATE_FORMAT_TO_SQLITE_STRFTIME_MAP = array( + private const MYSQL_DATE_FORMAT_TO_SQLITE_STRFTIME_MAP = array( '%a' => '%D', '%b' => '%M', '%c' => '%n', @@ -241,7 +247,7 @@ class WP_MySQL_On_SQLite extends PDO { * See: * https://dev.mysql.com/doc/refman/8.4/en/data-type-defaults.html#data-type-defaults-implicit */ - const DATA_TYPE_IMPLICIT_DEFAULT_MAP = array( + private const DATA_TYPE_IMPLICIT_DEFAULT_MAP = array( // Numeric data types: 'bit' => '0', 'bool' => '0', @@ -311,7 +317,7 @@ class WP_MySQL_On_SQLite extends PDO { * * This is used to compute the column metadata from the information schema. */ - const COLUMN_INFO_MYSQL_TO_NATIVE_TYPES_MAP = array( + private const COLUMN_INFO_MYSQL_TO_NATIVE_TYPES_MAP = array( // Numeric data types: 'bit' => array( 'BIT', 16, 1, 0 ), 'tinyint' => array( 'TINY', 1, 4, 0 ), @@ -375,7 +381,7 @@ class WP_MySQL_On_SQLite extends PDO { * This is used to compute the MySQL column metadata for non-column fields * that have no records in the information schema (i.e., expressions). */ - const COLUMN_INFO_SQLITE_TO_NATIVE_TYPES_MAP = array( + private const COLUMN_INFO_SQLITE_TO_NATIVE_TYPES_MAP = array( 'NULL' => array( 'NULL', 6, 0, 0 ), 'INT' => array( 'LONGLONG', 8, 21, 0 ), 'INTEGER' => array( 'LONGLONG', 8, 21, 0 ), @@ -644,7 +650,7 @@ class WP_MySQL_On_SQLite extends PDO { * @type string|int|null $synchronous Optional. SQLite synchronous setting. * } * - * @throws WP_SQLite_Driver_Exception When the driver initialization fails. + * @throws WP_MySQL_On_SQLite_Exception When the driver initialization fails. */ public function __construct( string $dsn, @@ -805,7 +811,7 @@ function ( string $sql, array $params ) { * * @return PDOStatement|false PDO statement, or false when the fetch mode is invalid on PHP < 8.1. * - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ #[ReturnTypeWillChange] public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_args ) { @@ -974,7 +980,7 @@ public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_ar $this->last_result_statement = $this->create_result_statement_from_data( array(), array() ); } - $stmt = new WP_PDO_Proxy_Statement( $this->last_result_statement, $this->last_affected_rows ); + $stmt = new WP_MySQL_On_SQLite_Statement( $this->last_result_statement, $this->last_affected_rows ); $stmt->setFetchMode( $fetch_mode, ...$fetch_mode_args ); return $stmt; } catch ( Throwable $e ) { @@ -984,7 +990,7 @@ public function query( string $query, ?int $fetch_mode = null, ...$fetch_mode_ar } catch ( Throwable $rollback_exception ) { // Ignore rollback errors. } - if ( $e instanceof WP_SQLite_Driver_Exception ) { + if ( $e instanceof WP_MySQL_On_SQLite_Exception ) { throw $e; } elseif ( $e instanceof WP_SQLite_Information_Schema_Exception ) { throw $this->convert_information_schema_exception( $e ); @@ -1168,9 +1174,26 @@ public function getAttribute( $attribute ) { return $this->connection->get_pdo()->getAttribute( $attribute ); } + /** + * Get the underlying SQLite PDO instance. + * + * Provides direct SQLite access for advanced use cases. The returned PDO + * bypasses MySQL emulation. Do not retain it across reconnections or modify + * driver-owned state. + * + * @since 3.0.0 + * + * @return PDO The underlying SQLite PDO instance. + */ + public function get_sqlite_pdo(): PDO { + return $this->connection->get_pdo(); + } + /** * Get the SQLite connection instance. * + * @access private + * * @return WP_SQLite_Connection */ public function get_connection(): WP_SQLite_Connection { @@ -1192,6 +1215,8 @@ public function get_sqlite_version(): string { * The saved driver version corresponds to the latest version of the SQLite * driver that was used to initialize and configure the SQLite database. * + * @access private + * * @return string SQLite driver version as a string. * @throws PDOException When the query execution fails. */ @@ -1217,6 +1242,8 @@ public function get_saved_driver_version(): string { /** * Check if a specific SQL mode is active. * + * @access private + * * @param string $mode The SQL mode to check. * @return bool True if the SQL mode is active, false otherwise. */ @@ -1227,6 +1254,8 @@ public function is_sql_mode_active( string $mode ): bool { /** * Get the last executed MySQL query. * + * @access private + * * @return string|null */ public function get_last_mysql_query(): ?string { @@ -1236,6 +1265,8 @@ public function get_last_mysql_query(): ?string { /** * Get SQLite queries executed for the last MySQL query. * + * @access private + * * @return array{ sql: string, params: array }[] */ public function get_last_sqlite_queries(): array { @@ -1258,6 +1289,8 @@ public function get_insert_id() { /** * Tokenize a MySQL query and initialize a parser. * + * @access private + * * @param string $query The MySQL query to parse. * @return WP_MySQL_Parser A parser initialized for the MySQL query. */ @@ -1292,6 +1325,8 @@ private function reset_or_create_parser( $tokens ): WP_MySQL_Parser { /** * Get the number of columns returned by the last emulated query. * + * @access private + * * @return int */ public function get_last_column_count(): int { @@ -1301,6 +1336,8 @@ public function get_last_column_count(): int { /** * Get column metadata for results of the last emulated query. * + * @access private + * * @return array */ public function get_last_column_meta(): array { @@ -1462,6 +1499,8 @@ public function get_last_column_meta(): array { /** * Execute a query in SQLite. * + * @access private + * * @param string $sql The query to execute. * @param array $params The query parameters. * @throws PDOException When the query execution fails. @@ -1475,7 +1514,7 @@ public function execute_sqlite_query( string $sql, array $params = array() ): PD * Translate and execute a MySQL query in SQLite. * * @param WP_Parser_Node $node The "query" AST node with "simpleStatement" child. - * @throws WP_SQLite_Driver_Exception When the query is not supported. + * @throws WP_MySQL_On_SQLite_Exception When the query is not supported. */ private function execute_mysql_query( WP_Parser_Node $node ): void { if ( 'query' !== $node->rule_name ) { @@ -1774,7 +1813,7 @@ private function rollback_user_transaction(): void { * Execute a MySQL transaction or locking statement in SQLite. * * @param WP_Parser_Node $node The "transactionOrLockingStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_transaction_or_locking_statement( WP_Parser_Node $node ): void { $subnode = $node->get_first_child_node(); @@ -1891,7 +1930,7 @@ private function execute_transaction_or_locking_statement( WP_Parser_Node $node * Translate and execute a MySQL SELECT statement in SQLite. * * @param WP_Parser_Node $node The "selectStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_select_statement( WP_Parser_Node $node ): void { /* @@ -1971,7 +2010,7 @@ private function execute_select_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL INSERT or REPLACE statement in SQLite. * * @param WP_Parser_Node $node The "insertStatement" or "replaceStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_insert_or_replace_statement( WP_Parser_Node $node ): void { $parts = array(); @@ -2098,7 +2137,7 @@ function ( $column ) { * Translate and execute a MySQL UPDATE statement in SQLite. * * @param WP_Parser_Node $node The "updateStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_update_statement( WP_Parser_Node $node ): void { // @TODO: Add support for UPDATE with multiple tables and JOINs. @@ -2348,7 +2387,7 @@ private function execute_update_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL DELETE statement in SQLite. * * @param WP_Parser_Node $node The "deleteStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_delete_statement( WP_Parser_Node $node ): void { /* @@ -2489,7 +2528,7 @@ private function execute_delete_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL CREATE TABLE statement in SQLite. * * @param WP_Parser_Node $node The "createStatement" AST node with "createTable" child. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_create_table_statement( WP_Parser_Node $node ): void { $subnode = $node->get_first_child_node(); @@ -2560,7 +2599,7 @@ private function execute_create_table_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL ALTER TABLE statement in SQLite. * * @param WP_Parser_Node $node The "alterStatement" AST node with "alterTable" child. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_alter_table_statement( WP_Parser_Node $node ): void { $table_ref = $node->get_first_descendant_node( 'tableRef' ); @@ -2648,7 +2687,7 @@ private function execute_alter_table_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL DROP TABLE statement in SQLite. * * @param WP_Parser_Node $node The "dropStatement" AST node with "dropTable" child. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_drop_table_statement( WP_Parser_Node $node ): void { // Record the changes in the information schema. @@ -2700,7 +2739,7 @@ private function execute_drop_table_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL TRUNCATE TABLE statement in SQLite. * * @param WP_Parser_Node $node The "truncateTableStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_truncate_table_statement( WP_Parser_Node $node ): void { $table_ref = $node->get_first_child_node( 'tableRef' ); @@ -2731,7 +2770,7 @@ private function execute_truncate_table_statement( WP_Parser_Node $node ): void * Translate and execute a MySQL CREATE INDEX statement in SQLite. * * @param WP_Parser_Node $node The "createStatement" AST node with "createIndex" child. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_create_index_statement( WP_Parser_Node $node ): void { $create_index = $node->get_first_child_node( 'createIndex' ); @@ -2789,7 +2828,7 @@ private function execute_create_index_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL DROP INDEX statement in SQLite. * * @param WP_Parser_Node $node The "dropStatement" AST node with "dropIndex" child. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_drop_index_statement( WP_Parser_Node $node ): void { $drop_index = $node->get_first_child_node( 'dropIndex' ); @@ -2830,7 +2869,7 @@ private function execute_drop_index_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL SHOW statement in SQLite. * * @param WP_Parser_Node $node The "showStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_show_statement( WP_Parser_Node $node ): void { $tokens = $node->get_child_tokens(); @@ -3128,7 +3167,7 @@ private function execute_show_index_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL SHOW TABLE STATUS statement in SQLite. * * @param WP_Parser_Node $node The "showStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_show_table_status_statement( WP_Parser_Node $node ): void { // FROM/IN database. @@ -3215,7 +3254,7 @@ private function execute_show_table_status_statement( WP_Parser_Node $node ): vo * Translate and execute a MySQL SHOW TABLES statement in SQLite. * * @param WP_Parser_Node $node The "showStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_show_tables_statement( WP_Parser_Node $node ): void { // FROM/IN database. @@ -3265,7 +3304,7 @@ private function execute_show_tables_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL SHOW COLUMNS statement in SQLite. * * @param WP_Parser_Node $node The "showStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. * @throws PDOException When given table doesn't exist. */ private function execute_show_columns_statement( WP_Parser_Node $node ): void { @@ -3360,7 +3399,7 @@ private function execute_show_columns_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL DESCRIBE statement in SQLite. * * @param WP_Parser_Node $node The "describeStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_describe_statement( WP_Parser_Node $node ): void { $table_ref = $node->get_first_child_node( 'tableRef' ); @@ -3399,7 +3438,7 @@ private function execute_describe_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL USE statement in SQLite. * * @param WP_Parser_Node $node The "useStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_use_statement( WP_Parser_Node $node ): void { $database_name = $this->unquote_sqlite_identifier( @@ -3424,7 +3463,7 @@ private function execute_use_statement( WP_Parser_Node $node ): void { * Translate and execute a MySQL SET statement in SQLite. * * @param WP_Parser_Node $node The "setStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_set_statement( WP_Parser_Node $node ): void { /* @@ -3537,7 +3576,7 @@ private function execute_set_statement( WP_Parser_Node $node ): void { * @param WP_Parser_Node $value_node The "setExprOrDefault" AST node. * @param int $default_type The currently active default variable type. * One of the SESSION, GLOBAL, PERSIST, PERSIST_ONLY tokens. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_set_system_variable_statement( WP_Parser_Node $set_var_node, @@ -3635,7 +3674,7 @@ private function execute_set_system_variable_statement( * * @param WP_Parser_Node $user_variable The "userVariable" AST node. * @param WP_Parser_Node $expr The "expr" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_set_user_variable_statement( WP_Parser_Node $user_variable, @@ -3660,7 +3699,7 @@ private function execute_set_user_variable_statement( * - REPAIR TABLE * * @param WP_Parser_Node $node A "tableAdministrationStatement" AST node. - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. */ private function execute_administration_statement( WP_Parser_Node $node ): void { $first_token = $node->get_first_child_token(); @@ -3787,7 +3826,7 @@ private function execute_administration_statement( WP_Parser_Node $node ): void * @param WP_Parser_Node $node The "expr" AST node. * @return mixed The value of the expression. */ - public function evaluate_expression( WP_Parser_Node $node ) { + private function evaluate_expression( WP_Parser_Node $node ) { // To support expressions, we'll use a SQLite query. $stmt = $this->execute_sqlite_query( sprintf( 'SELECT %s', $this->translate( $node ) ) @@ -3811,7 +3850,7 @@ public function evaluate_expression( WP_Parser_Node $node ) { * * @param WP_Parser_Node|WP_MySQL_Token $node The AST node to translate. * @return string|null The translated query fragment. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate( $node ): ?string { if ( null === $node ) { @@ -4130,7 +4169,7 @@ private function translate_token( WP_MySQL_Token $token ): ?string { * @param array $nodes The MySQL token to translate. * @param string $separator The separator to use between fragments. * @return string|null The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_sequence( array $nodes, string $separator = ' ' ): ?string { $parts = array(); @@ -4236,7 +4275,7 @@ private function translate_pure_identifier( WP_Parser_Node $node ): string { * (table, view, procedure, trigger, etc.). * @param WP_Parser_Node|null $child_node An identifier node representing an object child name (column, index, etc.). * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_qualified_identifier( ?WP_Parser_Node $schema_node, @@ -4284,7 +4323,7 @@ private function translate_qualified_identifier( * * @param WP_Parser_Node $node The "queryExpression" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_query_expression( WP_Parser_Node $node ): string { // Get the query expression subnode under which we need to look for the @@ -4359,7 +4398,7 @@ private function translate_query_expression( WP_Parser_Node $node ): string { * * @param WP_Parser_Node $node The "querySpecification" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. * @return string|null */ private function translate_query_specification( WP_Parser_Node $node ): string { @@ -4445,7 +4484,7 @@ private function translate_query_specification( WP_Parser_Node $node ): string { * * @param WP_Parser_Node $node The "simpleExprBody" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_simple_expr_body( WP_Parser_Node $node ): string { $token = $node->get_first_child_token(); @@ -4527,7 +4566,7 @@ private function translate_cast_expr( WP_Parser_Node $expr, WP_Parser_Node $cast * * @param WP_Parser_Node $node The "predicateOperations" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_like( WP_Parser_Node $node ): string { $tokens = $node->get_descendant_tokens(); @@ -4571,7 +4610,7 @@ private function translate_like( WP_Parser_Node $node ): string { * * @param WP_Parser_Node $node The "predicateOperations" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_regexp_functions( WP_Parser_Node $node ): string { $tokens = $node->get_descendant_tokens(); @@ -4601,7 +4640,7 @@ private function translate_regexp_functions( WP_Parser_Node $node ): string { * * @param WP_Parser_Node $node The "runtimeFunctionCall" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_runtime_function_call( WP_Parser_Node $node ): string { $child = $node->get_first_child(); @@ -4653,7 +4692,7 @@ private function translate_runtime_function_call( WP_Parser_Node $node ): string * * @param WP_Parser_Node $node The "functionCall" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_function_call( WP_Parser_Node $node ): string { $nodes = $node->get_child_nodes(); @@ -4875,7 +4914,7 @@ private function translate_datetime_literal( string $value ): string { * @param WP_Parser_Node $node The "selectItem" AST node. * @return string The translated expression. */ - public function translate_select_item( WP_Parser_Node $node ): string { + private function translate_select_item( WP_Parser_Node $node ): string { /* * First, let's translate the select item subtree. * @@ -4989,9 +5028,9 @@ public function translate_select_item( WP_Parser_Node $node ): string { * * @param WP_Parser_Node $node The "tableRef" AST node. * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ - public function translate_table_ref( WP_Parser_Node $node ): string { + private function translate_table_ref( WP_Parser_Node $node ): string { // The table reference is in "." or "
" format. $parts = $node->get_descendant_nodes( 'identifier' ); $table = array_pop( $parts ); @@ -5112,7 +5151,7 @@ public function translate_table_ref( WP_Parser_Node $node ): string { * @param array $column_map Optional. A map of column names (old name -> new name) * to use when copying data from the original table. * When not provided, all columns are copied without renaming. - * @throws WP_SQLite_Driver_Exception + * @throws WP_MySQL_On_SQLite_Exception */ private function recreate_table_from_information_schema( bool $table_is_temporary, @@ -5280,7 +5319,7 @@ private function apply_auto_increment_table_option( * @param WP_Parser_Node $like_or_where The "likeOrWhere" AST node. * @param string $like_column The column name to use in the LIKE clause ("table_name", "column_name", etc.). * @return string The translated value. - * @throws WP_SQLite_Driver_Exception When the translation fails. + * @throws WP_MySQL_On_SQLite_Exception When the translation fails. */ private function translate_show_like_or_where_condition( WP_Parser_Node $like_or_where, string $like_column ): string { $like_clause = $like_or_where->get_first_child_node( 'likeClause' ); @@ -6260,7 +6299,7 @@ private function get_database_name( WP_Parser_Node $node ): string { * @param string $table_name The name of the table to create. * @param string|null $new_table_name Override the original table name for ALTER TABLE emulation. * @return string[] Queries to create the table, indexes, and constraints. - * @throws WP_SQLite_Driver_Exception When the table information is missing. + * @throws WP_MySQL_On_SQLite_Exception When the table information is missing. */ private function get_sqlite_create_table_statement( bool $table_is_temporary, @@ -7214,19 +7253,19 @@ private function create_result_statement_from_data( array $columns, array $rows } /** - * Create a new SQLite driver exception. + * Create a new MySQL-on-SQLite driver exception. * * @param string $message The exception message. * @param int|string $code The exception code. For PDO errors, a string representing SQLSTATE. * @param Throwable|null $previous The previous exception. - * @return WP_SQLite_Driver_Exception + * @return WP_MySQL_On_SQLite_Exception */ private function new_driver_exception( string $message, $code = 0, ?Throwable $previous = null - ): WP_SQLite_Driver_Exception { - return new WP_SQLite_Driver_Exception( $this, $message, $code, $previous ); + ): WP_MySQL_On_SQLite_Exception { + return new WP_MySQL_On_SQLite_Exception( $this, $message, $code, $previous ); } /** @@ -7235,10 +7274,10 @@ private function new_driver_exception( * This exception can be used to mark cases that should never occur according * to the MySQL grammar. It may serve as an assertion that should never fail. * - * @return WP_SQLite_Driver_Exception + * @return WP_MySQL_On_SQLite_Exception */ - private function new_invalid_input_exception(): WP_SQLite_Driver_Exception { - return new WP_SQLite_Driver_Exception( $this, 'MySQL query syntax error.' ); + private function new_invalid_input_exception(): WP_MySQL_On_SQLite_Exception { + return new WP_MySQL_On_SQLite_Exception( $this, 'MySQL query syntax error.' ); } /** @@ -7247,10 +7286,10 @@ private function new_invalid_input_exception(): WP_SQLite_Driver_Exception { * This exception can be used to mark MySQL constructs that are not supported. * * @param string $cause The cause, indicating which construct is not supported. - * @return WP_SQLite_Driver_Exception + * @return WP_MySQL_On_SQLite_Exception */ - private function new_not_supported_exception( string $cause ): WP_SQLite_Driver_Exception { - return new WP_SQLite_Driver_Exception( + private function new_not_supported_exception( string $cause ): WP_MySQL_On_SQLite_Exception { + return new WP_MySQL_On_SQLite_Exception( $this, sprintf( 'MySQL query not supported. Cause: %s', $cause ) ); @@ -7259,9 +7298,9 @@ private function new_not_supported_exception( string $cause ): WP_SQLite_Driver_ /** * Create a new access denied exception for the information schema database. * - * @return WP_SQLite_Driver_Exception + * @return WP_MySQL_On_SQLite_Exception */ - private function new_access_denied_to_information_schema_exception(): WP_SQLite_Driver_Exception { + private function new_access_denied_to_information_schema_exception(): WP_MySQL_On_SQLite_Exception { return $this->new_driver_exception( "Access denied for user 'root'@'%' to database 'information_schema'", '42000' 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 280cfc283..45da0863a 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 @@ -9,6 +9,8 @@ * The configurator ensures that tables required for emulating MySQL behaviors * are created and populated with necessary data. It is also able to partially * repair and update these tables and metadata in case of database corruption. + * + * @access private */ class WP_SQLite_Configurator { /** diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php index 2b85f078d..829072ca2 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-connection.php @@ -12,6 +12,8 @@ * It requires PDO with the SQLite driver, and currently, it is only a simple * wrapper that leaks some of the PDO APIs (returns PDOStatement values, etc.). * In the future, we may abstract it away from PDO and support SQLite3 as well. + * + * @access private */ class WP_SQLite_Connection { /** 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 deleted file mode 100644 index 26a01ad2f..000000000 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver-exception.php +++ /dev/null @@ -1,33 +0,0 @@ -code = $code; - $this->driver = $driver; - } - - 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 index d7010ecf3..5adaf2406 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-driver.php @@ -10,13 +10,15 @@ * (e.g., WP CLI SQLite Command), ensure the PDO-based classes are loaded. */ require_once __DIR__ . '/class-wp-mysql-on-sqlite.php'; -require_once __DIR__ . '/class-wp-pdo-proxy-statement.php'; +require_once __DIR__ . '/class-wp-mysql-on-sqlite-statement.php'; /** * Deprecated: A proxy of the WP_MySQL_On_SQLite class preserving the legacy API. * * This class temporarily preserves the legacy constructor and result API while * consumers transition to the PDO-based WP_MySQL_On_SQLite API. + * + * @deprecated 3.0.0 Use WP_MySQL_On_SQLite instead. */ class WP_SQLite_Driver { /** @@ -54,10 +56,11 @@ class WP_SQLite_Driver { * * 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. + * @param WP_SQLite_Connection $connection A SQLite database connection. + * @param string $database The database name. + * @param int $mysql_version The emulated MySQL version as an integer. * - * @throws WP_SQLite_Driver_Exception When the driver initialization fails. + * @throws WP_MySQL_On_SQLite_Exception When the driver initialization fails. */ public function __construct( WP_SQLite_Connection $connection, @@ -65,7 +68,7 @@ public function __construct( int $mysql_version = 80038 ) { $this->mysql_on_sqlite_driver = new WP_MySQL_On_SQLite( - sprintf( 'mysql-on-sqlite:dbname=%s', $database ), + sprintf( 'mysql-on-sqlite:dbname=%s', str_replace( ';', ';;', $database ) ), null, null, array( @@ -74,7 +77,6 @@ public function __construct( '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 ); @@ -155,7 +157,7 @@ public function get_insert_id() { * * @return mixed Return value, depending on the query type. * - * @throws WP_SQLite_Driver_Exception When the query execution fails. + * @throws WP_MySQL_On_SQLite_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 ); @@ -255,26 +257,4 @@ public function commit(): void { 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-builder.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-builder.php index 7c28316df..b113f293b 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-builder.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-builder.php @@ -6,6 +6,8 @@ * This class builds and maintains MySQL INFORMATION_SCHEMA tables in SQLite. * It consumes the AST of MySQL DDL queries and records the schema information * in SQLite tables that emulate the MySQL INFORMATION_SCHEMA. + * + * @access private */ class WP_SQLite_Information_Schema_Builder { /** diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-exception.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-exception.php index 93a9ab88c..7b7e62920 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-exception.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-information-schema-exception.php @@ -5,6 +5,8 @@ * * This class is used to represent errors that may occur when building * the MySQL information schema for emulation in SQLite. + * + * @access private */ class WP_SQLite_Information_Schema_Exception extends Exception { // Information schema exception types. 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 3b60b1fc1..bc860c571 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 @@ -14,6 +14,8 @@ * Currently, it reconstructs schema infromation for missing tables, and removes * stale data for tables that no longer exist. When used with WordPress, it uses * the "wp_get_db_schema()" function to reconstruct WordPress table information. + * + * @access private */ class WP_SQLite_Information_Schema_Reconstructor { /** @@ -76,7 +78,7 @@ public function ensure_correct_information_schema(): void { $sql = $this->generate_create_table_statement( $table ); $ast = $this->driver->create_parser( $sql )->parse(); if ( null === $ast ) { - throw new WP_SQLite_Driver_Exception( $this->driver, 'Failed to parse the MySQL query.' ); + throw new WP_MySQL_On_SQLite_Exception( $this->driver, 'Failed to parse the MySQL query.' ); } } @@ -111,7 +113,7 @@ private function record_drop_table( string $table_name ): void { $sql = sprintf( 'DROP TABLE %s', $this->connection->quote_identifier( $table_name ) ); // TODO: mysql quote $ast = $this->driver->create_parser( $sql )->parse(); if ( null === $ast ) { - throw new WP_SQLite_Driver_Exception( $this->driver, 'Failed to parse the MySQL query.' ); + throw new WP_MySQL_On_SQLite_Exception( $this->driver, 'Failed to parse the MySQL query.' ); } $this->schema_builder->record_drop_table( $ast->get_first_descendant_node( 'dropStatement' ) @@ -233,7 +235,7 @@ private function get_wp_create_table_statements(): array { while ( $parser->next_query() ) { $ast = $parser->get_query_ast(); if ( null === $ast ) { - throw new WP_SQLite_Driver_Exception( $this->driver, 'Failed to parse the MySQL query.' ); + throw new WP_MySQL_On_SQLite_Exception( $this->driver, 'Failed to parse the MySQL query.' ); } $create_node = $ast->get_first_descendant_node( 'createStatement' ); diff --git a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-pdo-user-defined-functions.php b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-pdo-user-defined-functions.php index 9e44bf17d..54dfae7fa 100644 --- a/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-pdo-user-defined-functions.php +++ b/packages/mysql-on-sqlite/src/sqlite/class-wp-sqlite-pdo-user-defined-functions.php @@ -19,6 +19,8 @@ * * This automatically enables ref_to_pdo_obj to replace the function in the SQL statement * to the ones defined here. + * + * @access private */ class WP_SQLite_PDO_User_Defined_Functions { diff --git a/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php index afaf8723f..0116246de 100644 --- a/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Metadata_Tests.php @@ -2291,7 +2291,7 @@ public function testInformationSchemaAlterTableDropConstraint(): void { public function testInformationSchemaAlterTableDropMissingConstraint(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT PRIMARY KEY)' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "SQLSTATE[HY000]: General error: 3940 Constraint 'cnst' does not exist." ); $this->expectExceptionCode( 'HY000' ); $this->assertQuery( 'ALTER TABLE t2 DROP CONSTRAINT cnst' ); @@ -2307,7 +2307,7 @@ public function testInformationSchemaAlterTableDropConstraintWithAmbiguousName() )' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "SQLSTATE[HY000]: General error: 3939 Table has multiple constraints with the name 'cnst'. Please use constraint specific 'DROP' clause." ); $this->expectExceptionCode( 'HY000' ); $this->assertQuery( 'ALTER TABLE t2 DROP CONSTRAINT cnst' ); diff --git a/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php index 261ae3020..2346c96d9 100644 --- a/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_PDO_API_Tests.php @@ -34,6 +34,25 @@ public function test_connection(): void { $this->assertInstanceOf( PDO::class, $driver ); } + public function test_driver_exception_exposes_originating_driver(): void { + $exception = new WP_MySQL_On_SQLite_Exception( $this->driver, 'Test error.' ); + + $this->assertSame( $this->driver, $exception->get_driver() ); + } + + public function test_exposes_underlying_sqlite_pdo(): void { + $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\SQLite::class : PDO::class; + $pdo = new $pdo_class( 'sqlite::memory:' ); + $driver = new WP_MySQL_On_SQLite( + 'mysql-on-sqlite:dbname=wp', + null, + null, + array( 'pdo' => $pdo ) + ); + + $this->assertSame( $pdo, $driver->get_sqlite_pdo() ); + } + public function test_dsn_parsing(): void { // Standard DSN. $driver = new WP_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp' ); @@ -118,6 +137,7 @@ public function test_journal_mode_and_synchronous_driver_options(): void { public function test_query(): void { $result = $this->driver->query( "SELECT 1, 'abc'" ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Statement::class, $result ); $this->assertInstanceOf( PDOStatement::class, $result ); if ( PHP_VERSION_ID < 80000 ) { $this->assertSame( diff --git a/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php index d0993207b..9f23c11ec 100644 --- a/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php @@ -50,7 +50,7 @@ private function assertQueryError( $sql, $error_message ) { $exception = null; try { $this->query( $sql ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception, 'An exception was expected, but none was thrown.' ); @@ -5135,7 +5135,7 @@ public function testCompoundPrimaryKeyWithAutoincrement(): void { * @dataProvider getReservedPrefixTestData */ public function testReservedPrefix( string $query, string $error ): void { - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( $error ); $this->assertQuery( $query ); } @@ -5174,7 +5174,7 @@ public function getReservedPrefixTestData(): array { */ public function testInformationSchemaIsReadonly( string $query ): void { $this->assertQuery( 'CREATE TABLE tables (id INT)' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "Access denied for user 'root'@'%' to database 'information_schema'" ); $this->assertQuery( $query ); } @@ -5206,7 +5206,7 @@ public function getInformationSchemaIsReadonlyTestData(): array { */ public function testInformationSchemaIsReadonlyWithUse( string $query ): void { $this->assertQuery( 'CREATE TABLE tables (id INT)' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "Access denied for user 'root'@'%' to database 'information_schema'" ); $this->assertQuery( 'USE information_schema' ); $this->assertQuery( $query ); @@ -5278,7 +5278,7 @@ public function testTemporaryTableHasPriorityOverStandardTable(): void { $this->assertEquals( 'a', $result[0]->Field ); // Second DROP TABLE removes the standard table. - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "Table 'wp.t' doesn't exist" ); $this->assertQuery( 'DROP TABLE t' ); $result = $this->assertQuery( 'SHOW COLUMNS FROM t' ); @@ -5344,7 +5344,7 @@ public function testStrictSqlModeNotNullWithoutDefault(): void { $exception = null; try { $this->assertQuery( 'INSERT INTO t1 (id) VALUES (1)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5358,7 +5358,7 @@ public function testStrictSqlModeNotNullWithoutDefault(): void { $exception = null; try { $this->assertQuery( 'INSERT INTO t2 (id, value) VALUES (1, NULL)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5373,7 +5373,7 @@ public function testStrictSqlModeNotNullWithoutDefault(): void { try { $this->assertQuery( "INSERT INTO t3 (id, value) VALUES (1, 'initial-value')" ); $this->assertQuery( 'UPDATE t3 SET value = NULL WHERE id = 1' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5398,7 +5398,7 @@ public function testStrictSqlModeNotNullWithDefault(): void { $exception = null; try { $this->assertQuery( 'INSERT INTO t2 (id, value) VALUES (1, NULL)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5413,7 +5413,7 @@ public function testStrictSqlModeNotNullWithDefault(): void { try { $this->assertQuery( "INSERT INTO t3 (id, value) VALUES (1, 'initial-value')" ); $this->assertQuery( 'UPDATE t3 SET value = NULL WHERE id = 1' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5490,7 +5490,7 @@ public function testNonStrictSqlModeNotNullWithoutDefault(): void { $exception = null; try { $this->assertQuery( 'INSERT INTO t2 (id, value) VALUES (1, NULL)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5523,7 +5523,7 @@ public function testNonStrictSqlModeNotNullWithDefault(): void { $exception = null; try { $this->assertQuery( 'INSERT INTO t2 (id, value) VALUES (1, NULL)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -5890,7 +5890,7 @@ public function testNoBackslashEscapesSqlModeIsNotSupported(): void { try { $this->assertQuery( $query ); $this->fail( 'Expected NO_BACKSLASH_ESCAPES to be rejected.' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $this->assertSame( "MySQL query not supported. Cause: SQL mode 'NO_BACKSLASH_ESCAPES'", $e->getMessage() @@ -5903,7 +5903,7 @@ public function testNoBackslashEscapesSqlModeIsNotSupported(): void { } public function testMultiQueryNotSupported(): void { - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( 'Multi-query is not supported.' ); $this->assertQuery( 'SELECT 1; SELECT 2' ); } @@ -5913,11 +5913,11 @@ public function testCreateTableDuplicateTableName(): void { try { $this->assertQuery( 'CREATE TABLE t (id INT)' ); $this->assertQuery( 'CREATE TABLE t (id INT)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42S01]: Base table or view already exists: 1050 Table 't' already exists", $exception->getMessage() ); $this->assertSame( '42S01', $exception->getCode() ); } @@ -5926,11 +5926,11 @@ public function testCreateTableDuplicateColumnName(): void { $exception = null; try { $this->assertQuery( 'CREATE TABLE t (col INT, col INT)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'col'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -5939,11 +5939,11 @@ public function testCreateTableDuplicateKeyName(): void { $exception = null; try { $this->assertQuery( 'CREATE TABLE t (id1 INT, id2 INT, INDEX idx (id1), INDEX idx (id2))' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42000]: Syntax error or access violation: 1061 Duplicate key name 'idx'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -5952,11 +5952,11 @@ public function testCreateTableDuplicateKeyNameWithUnique(): void { $exception = null; try { $this->assertQuery( 'CREATE TABLE t (id1 INT, id2 INT, INDEX idx (id1), UNIQUE idx (id2))' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42000]: Syntax error or access violation: 1061 Duplicate key name 'idx'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -5971,11 +5971,11 @@ public function testAlterTableDuplicateColumnName(): void { try { $this->assertQuery( 'CREATE TABLE t (col INT)' ); $this->assertQuery( 'ALTER TABLE t ADD COLUMN col INT' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'col'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -5985,11 +5985,11 @@ public function testAlterTableDuplicateColumnNameWithMultipleOperations(): void try { $this->assertQuery( 'CREATE TABLE t (id INT)' ); $this->assertQuery( 'ALTER TABLE t ADD COLUMN col INT, ADD COLUMN col INT' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'col'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -5999,11 +5999,11 @@ public function testAlterTableDuplicateKeyName(): void { try { $this->assertQuery( 'CREATE TABLE t (id INT, INDEX idx (id))' ); $this->assertQuery( 'ALTER TABLE t ADD INDEX idx (id)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42000]: Syntax error or access violation: 1061 Duplicate key name 'idx'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -6013,11 +6013,11 @@ public function testAlterTableDuplicateKeyNameWithMultipleOperations(): void { try { $this->assertQuery( 'CREATE TABLE t (id INT)' ); $this->assertQuery( 'ALTER TABLE t ADD INDEX idx (id), ADD INDEX idx (id)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42000]: Syntax error or access violation: 1061 Duplicate key name 'idx'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -6027,11 +6027,11 @@ public function testAlterTableDuplicateKeyNameWithUnique(): void { try { $this->assertQuery( 'CREATE TABLE t (id INT, INDEX idx (id))' ); $this->assertQuery( 'ALTER TABLE t ADD UNIQUE idx (id)' ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } - $this->assertInstanceOf( WP_SQLite_Driver_Exception::class, $exception ); + $this->assertInstanceOf( WP_MySQL_On_SQLite_Exception::class, $exception ); $this->assertSame( "SQLSTATE[42000]: Syntax error or access violation: 1061 Duplicate key name 'idx'", $exception->getMessage() ); $this->assertSame( '42S21', $exception->getCode() ); } @@ -6431,19 +6431,19 @@ public function testColumnNamesAreNotCaseSensitive(): void { } public function testAliasesMustBeAscii(): void { - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( 'The SQLite driver only supports ASCII characters in identifiers.' ); $this->assertQuery( 'SELECT 123 AS `ńôñ-ášçíì`' ); } public function testTableNamesMustBeAscii(): void { - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( 'The SQLite driver only supports ASCII characters in identifiers.' ); $this->assertQuery( 'CREATE TABLE `ńôñ-ášçíì` (id INT)' ); } public function testColumnNamesMustBeAscii(): void { - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( 'The SQLite driver only supports ASCII characters in identifiers.' ); $this->assertQuery( 'CREATE TABLE t (`ńôñ-ášçíì` INT)' ); } @@ -6670,7 +6670,7 @@ public function testCreateIndexWithDuplicateName(): void { $this->assertQuery( 'CREATE TABLE t (id INT, val1 INT, val2 INT)' ); $this->assertQuery( 'CREATE INDEX idx_value ON t (val1)' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "1061 Duplicate key name 'idx_value'" ); $this->assertQuery( 'CREATE INDEX idx_value ON t (val2)' ); @@ -6679,7 +6679,7 @@ public function testCreateIndexWithDuplicateName(): void { public function testCreateIndexOnNonExistentColumn(): void { $this->assertQuery( 'CREATE TABLE t (id INT)' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( "SQLSTATE[42000]: Syntax error or access violation: 1072 Key column 'val' doesn't exist in table" ); $this->assertQuery( 'CREATE INDEX idx_value ON t (val)' ); @@ -6956,7 +6956,7 @@ 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:' ); - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( 'The database name cannot be empty.' ); new WP_MySQL_On_SQLite( 'mysql-on-sqlite:dbname=', @@ -7255,13 +7255,13 @@ public function testLockingStatements(): void { } public function testLockNonExistentTableForRead(): void { - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( "Table 'wp.t' doesn't exist" ); $this->assertQuery( 'LOCK TABLES t READ' ); } public function testLockNonExistentTableForWrite(): void { - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( "Table 'wp.t' doesn't exist" ); $this->assertQuery( 'LOCK TABLES t WRITE' ); } @@ -7270,7 +7270,7 @@ public function testLockMultipleWithNonExistentTable(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT)' ); $this->assertQuery( 'CREATE TABLE t3 (id INT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( "Table 'wp.t2' doesn't exist" ); $this->assertQuery( 'LOCK TABLES t1 READ, t2 READ, t3 WRITE' ); } @@ -7464,7 +7464,7 @@ public function testSelectOrderByAmbiguousColumnError(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' ); $this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'ambiguous column name: name' ); $this->assertQuery( 'SELECT t1.name, t2.name FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name DESC' ); } @@ -7474,7 +7474,7 @@ public function testSelectOrderByAmbiguousColumnErrorWithoutSelectList(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' ); $this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'ambiguous column name: name' ); $this->assertQuery( 'SELECT 1 FROM t1 JOIN t2 ON t2.id = t1.id ORDER BY name' ); } @@ -7526,7 +7526,7 @@ public function testSelectGroupByAmbiguousColumnError(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' ); $this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'ambiguous column name: name' ); $this->assertQuery( 'SELECT t1.name, t2.name FROM t1 JOIN t2 ON t2.id = t1.id GROUP BY name' ); } @@ -7535,7 +7535,7 @@ public function testSelectGroupByAmbiguousColumnErrorWithoutSelectList(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' ); $this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'ambiguous column name: name' ); $this->assertQuery( 'SELECT 1 FROM t1 JOIN t2 ON t2.id = t1.id GROUP BY name' ); } @@ -7575,7 +7575,7 @@ public function testSelectHavingAmbiguousColumnError(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' ); $this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'ambiguous column name: name' ); $this->assertQuery( 'SELECT t1.name, t2.name FROM t1 JOIN t2 ON t2.id = t1.id HAVING name' ); } @@ -7584,13 +7584,13 @@ public function testSelectHavingAmbiguousColumnErrorWithoutSelectList(): void { $this->assertQuery( 'CREATE TABLE t1 (id INT, name TEXT)' ); $this->assertQuery( 'CREATE TABLE t2 (id INT, name TEXT)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'ambiguous column name: name' ); $this->assertQuery( 'SELECT 1 FROM t1 JOIN t2 ON t2.id = t1.id HAVING name' ); } public function testRollbackNonExistentTransactionSavepoint(): void { - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'no such savepoint: sp1' ); $this->assertQuery( 'ROLLBACK TO SAVEPOINT sp1' ); } @@ -7601,7 +7601,7 @@ public function testForeignKeyOnUpdateNoAction(): void { $this->assertQuery( 'INSERT INTO t1 (id) VALUES (1)' ); $this->assertQuery( 'INSERT INTO t2 (id) VALUES (1)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 FOREIGN KEY constraint failed' ); $this->assertQuery( 'UPDATE t1 SET id = 2 WHERE id = 1' ); } @@ -7612,7 +7612,7 @@ public function testForeignKeyOnUpdateRestrict(): void { $this->assertQuery( 'INSERT INTO t1 (id) VALUES (1)' ); $this->assertQuery( 'INSERT INTO t2 (id) VALUES (1)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 FOREIGN KEY constraint failed' ); $this->assertQuery( 'UPDATE t1 SET id = 2 WHERE id = 1' ); } @@ -7657,7 +7657,7 @@ public function testForeignKeyOnDeleteNoAction(): void { $this->assertQuery( 'INSERT INTO t1 (id) VALUES (1)' ); $this->assertQuery( 'INSERT INTO t2 (id) VALUES (1)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 FOREIGN KEY constraint failed' ); $this->assertQuery( 'DELETE FROM t1 WHERE id = 1' ); } @@ -7668,7 +7668,7 @@ public function testForeignKeyOnDeleteRestrict(): void { $this->assertQuery( 'INSERT INTO t1 (id) VALUES (1)' ); $this->assertQuery( 'INSERT INTO t2 (id) VALUES (1)' ); - $this->expectException( 'WP_SQLite_Driver_Exception' ); + $this->expectException( 'WP_MySQL_On_SQLite_Exception' ); $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 FOREIGN KEY constraint failed' ); $this->assertQuery( 'DELETE FROM t1 WHERE id = 1' ); } @@ -10030,7 +10030,7 @@ public function testCheckConstraints(): void { VALUES (0, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10047,7 +10047,7 @@ public function testCheckConstraints(): void { VALUES (1, '', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10064,7 +10064,7 @@ public function testCheckConstraints(): void { VALUES (1, 'test', 100, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10081,7 +10081,7 @@ public function testCheckConstraints(): void { VALUES (1, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', 'invalid JSON') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10098,7 +10098,7 @@ public function testCheckConstraints(): void { VALUES (11, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10115,7 +10115,7 @@ public function testCheckConstraints(): void { VALUES (1, 'test', 50, '2025-01-02 12:00:00', '2025-01-01 12:00:00', '{\"key\":\"value\"}') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10132,7 +10132,7 @@ public function testCheckConstraints(): void { VALUES (1, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"a-very-long-value\"}') " ); - } catch ( WP_SQLite_Driver_Exception $e ) { + } catch ( WP_MySQL_On_SQLite_Exception $e ) { $exception = $e; } $this->assertNotNull( $exception ); @@ -10205,7 +10205,7 @@ public function testAlterTableAddCheckConstraint(): void { $this->assertCount( 1, $result ); // Insert invalid data. - $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectException( WP_MySQL_On_SQLite_Exception::class ); $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c' ); $this->assertQuery( 'INSERT INTO t (id) VALUES (0)' ); } diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_DB_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_DB_Tests.php index 9955103ab..65c84110d 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_DB_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_DB_Tests.php @@ -21,6 +21,16 @@ public function setUp(): void { ); } + public function test_exposes_mysql_on_sqlite_driver(): void { + $wpdb = new class( $this->driver ) extends WP_SQLite_DB { + public function __construct( WP_MySQL_On_SQLite $driver ) { + $this->dbh = $driver; + } + }; + + $this->assertSame( $this->driver, $wpdb->get_driver() ); + } + /** * @dataProvider dataMysqlEscaping */ diff --git a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Compatibility_Tests.php b/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Compatibility_Tests.php index 78fdaedb0..4db88f7a9 100644 --- a/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Compatibility_Tests.php +++ b/packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Compatibility_Tests.php @@ -75,21 +75,4 @@ public function test_preserves_transaction_method_aliases(): void { $this->driver->commit(); $this->assertSame( '1', $this->driver->query( 'SELECT COUNT(*) FROM t' )[0]->{'COUNT(*)'} ); } - - public function test_proxies_legacy_test_helpers(): void { - $this->driver->main_db_name = 'wp_test_new'; - $result = $this->driver->query( - 'SELECT schema_name FROM information_schema.schemata ORDER BY schema_name' - ); - $this->assertSame( 'wp_test_new', $result[1]->SCHEMA_NAME ); - - $quote = Closure::bind( - function ( string $value ) { - return $this->quote_mysql_utf8_string_literal( $value ); - }, - $this->driver, - WP_SQLite_Driver::class - ); - $this->assertSame( "'abc''xyz'", $quote( "abc'xyz" ) ); - } } diff --git a/packages/plugin-sqlite-database-integration/activate.php b/packages/plugin-sqlite-database-integration/activate.php index 5dc21d2b6..fc6cd91d1 100644 --- a/packages/plugin-sqlite-database-integration/activate.php +++ b/packages/plugin-sqlite-database-integration/activate.php @@ -53,19 +53,6 @@ function sqlite_activation() { check_admin_referer( 'sqlite-install' ); - // Handle upgrading from the performance-lab plugin. - if ( isset( $_GET['upgrade-from-pl'] ) ) { - global $wp_filesystem; - require_once ABSPATH . '/wp-admin/includes/file.php'; - // Delete the previous db.php file. - $wp_filesystem->delete( WP_CONTENT_DIR . '/db.php' ); - // Deactivate the performance-lab SQLite module. - $pl_option_name = defined( 'PERFLAB_MODULES_SETTING' ) ? PERFLAB_MODULES_SETTING : 'perflab_modules_settings'; - $pl_option = get_option( $pl_option_name, array() ); - unset( $pl_option['database/sqlite'] ); - update_option( $pl_option_name, $pl_option ); - } - sqlite_plugin_copy_db_file(); // WordPress will automatically redirect to the install screen here. diff --git a/packages/plugin-sqlite-database-integration/admin-notices.php b/packages/plugin-sqlite-database-integration/admin-notices.php index 06e2b6fac..df8028af9 100644 --- a/packages/plugin-sqlite-database-integration/admin-notices.php +++ b/packages/plugin-sqlite-database-integration/admin-notices.php @@ -74,6 +74,3 @@ function sqlite_plugin_admin_notice() { ); } add_action( is_multisite() ? 'network_admin_notices' : 'admin_notices', 'sqlite_plugin_admin_notice' ); // Add the admin notices. - -// Remove the PL-plugin admin notices for SQLite. -remove_action( 'admin_notices', 'perflab_sqlite_plugin_admin_notice' ); diff --git a/packages/plugin-sqlite-database-integration/admin-page.php b/packages/plugin-sqlite-database-integration/admin-page.php index 0d8c81f13..a6e3c4569 100644 --- a/packages/plugin-sqlite-database-integration/admin-page.php +++ b/packages/plugin-sqlite-database-integration/admin-page.php @@ -76,49 +76,17 @@ function sqlite_integration_admin_screen() {

- -
-

- ' . esc_html( basename( WP_CONTENT_DIR ) ) . '/db.php' - ); - ?> -

-
- '1', - 'upgrade-from-pl' => '1', - ), - sqlite_plugin_get_admin_page_url() - ); - ?> - +
+

' . esc_html( basename( WP_CONTENT_DIR ) ) . '/db.php' ); ?> - - -

-

- ' . esc_html( basename( WP_CONTENT_DIR ) ) . '/db.php' - ); - ?> -

-
- +

+

diff --git a/packages/plugin-sqlite-database-integration/constants.php b/packages/plugin-sqlite-database-integration/constants.php index 15e6772a1..713bd3237 100644 --- a/packages/plugin-sqlite-database-integration/constants.php +++ b/packages/plugin-sqlite-database-integration/constants.php @@ -10,9 +10,6 @@ if ( ! defined( 'DB_ENGINE' ) ) { if ( defined( 'SQLITE_DB_DROPIN_VERSION' ) ) { define( 'DB_ENGINE', 'sqlite' ); - } elseif ( defined( 'DATABASE_ENGINE' ) ) { - // backwards compatibility with previous versions of the plugin. - define( 'DB_ENGINE', DATABASE_ENGINE ); } else { define( 'DB_ENGINE', 'mysql' ); } diff --git a/packages/plugin-sqlite-database-integration/db.copy b/packages/plugin-sqlite-database-integration/db.copy index ef8291374..fafd8c874 100644 --- a/packages/plugin-sqlite-database-integration/db.copy +++ b/packages/plugin-sqlite-database-integration/db.copy @@ -36,7 +36,7 @@ if ( ! defined( 'DB_ENGINE' ) ) { // Require the implementation from the plugin. require_once $sqlite_plugin_implementation_folder_path . '/wp-includes/sqlite/db.php'; -// Activate the performance-lab plugin if it is not already activated. +// Activate the SQLite Database Integration plugin if it is not already activated. add_action( 'admin_footer', function() { diff --git a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php deleted file mode 100644 index 7878a4813..000000000 --- a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php +++ /dev/null @@ -1,127 +0,0 @@ -resetDatabases(); - } - - private function resetDatabases() { - if ( file_exists( FQDB ) ) { - unlink( FQDB ); - } - $GLOBALS['mysql']->query( 'DROP DATABASE IF EXISTS ' . DB_NAME ); - $GLOBALS['mysql']->query( 'CREATE DATABASE ' . DB_NAME ); - $GLOBALS['mysql']->query( 'USE ' . DB_NAME ); - } - - public function query( $query ) { - /** - * In MySQL, AUTO_INCREMENT columns don't reuse IDs assigned in rollback transactions - * In SQLite, AUTOINCREMENT columns do reuse IDs assigned in rollback transactions - * - * Let's store the current AUTOINCREMENT value for each table, and restore it afterwards. - */ - if ( preg_match( '/^\s*rollback/i', $query ) ) { - $autoincrements = array(); - $tables = $GLOBALS['@pdo']->query( "SELECT name as `table` FROM sqlite_master WHERE type='table' ORDER BY name" )->fetchAll(); - foreach ( $tables as $table ) { - $table = $table['table']; - $autoincrement = $GLOBALS['@pdo']->query( "SELECT seq FROM sqlite_sequence WHERE name = '$table'" )->fetchColumn(); - $autoincrements[ $table ] = $autoincrement ?: 1; - } - } - $sqlite_retval = parent::query( $query ); - if ( preg_match( '/^\s*rollback/i', $query ) ) { - foreach ( $autoincrements as $table => $autoincrement ) { - $GLOBALS['@pdo']->query( "UPDATE sqlite_sequence SET seq = $autoincrement WHERE name = '$table'" ); - } - } - $this->crosscheck( $query, $sqlite_retval ); - return $sqlite_retval; - } - - private function crosscheck( $query, $sqlite_retval ) { - // echo $query."\n\n"; - // Be lenient on cross-checking some query types - if ( preg_match( '/^\s*SET storage_engine/i', $query ) ) { - return; - } - $this->show_errors = false; - $this->suppress_errors = true; - $GLOBALS['mysql']->show_errors = false; - $GLOBALS['mysql']->suppress_errors = true; - - ob_start(); - $mysql_retval = $GLOBALS['mysql']->query( $query ); - ob_end_clean(); - - $tests = array( - array( 'retval', $mysql_retval, $sqlite_retval ), - array( 'num_rows', $GLOBALS['mysql']->num_rows, $GLOBALS['sqlite']->num_rows ), - array( 'insert_id', $GLOBALS['mysql']->insert_id, $GLOBALS['sqlite']->insert_id ), - array( 'rows_affected', $GLOBALS['mysql']->rows_affected, $GLOBALS['sqlite']->rows_affected ), - ); - - foreach ( $tests as $test ) { - list($factor, $mysql, $sqlite) = $test; - if ( $mysql !== $sqlite ) { - if ( 'insert_id' === $factor ) { - // On multi-inserts MySQL returns the first inserted ID - // while SQLite returns the last one. The cached insert_id - // value stays the same for a number of subsequent queries. - // Let's forgive this for now. - continue; - } - if ( 'rows_affected' === $factor && $mysql_retval === $mysql ) { - // SQLite doesn't provide the rowcount() functionality - continue; - } - if ( 'retval' === $factor && $GLOBALS['mysql']->rows_affected === $mysql ) { - // SQLite doesn't provide the rowcount() functionality - continue; - } - echo "======================================================\n"; - echo "======== *** $factor *** differed for query ========= \n"; - echo "======================================================\n"; - echo "MySQL query: \n"; - echo "$query\n\n"; - - echo "SQLite queries: \n"; - foreach ( $this->dbh->last_translation->queries as $query ) { - echo $query->sql . "\n"; - } - echo "\n"; - - $this->report_factor( - 'error', - $GLOBALS['mysql']->last_error, - $GLOBALS['sqlite']->last_error - ); - foreach ( $tests as $test ) { - $this->report_factor( - $test[0], - $test[1], - $test[2] - ); - } - // throw new Exception(); - break; - } - } - } - - private function report_factor( $factor, $mysql, $sqlite ) { - echo "$factor: \n"; - echo ' MySQL: ' . var_export( $mysql, true ) . "\n"; - echo ' SQLite: ' . var_export( $sqlite, true ) . "\n\n"; - } -} 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 d7100aa8e..03238d465 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 @@ -20,13 +20,6 @@ class WP_SQLite_DB extends wpdb { */ protected $dbh; - /** - * Whether the PDO instance was provided externally through $GLOBALS['@pdo']. - * - * @var bool - */ - private $is_pdo_external; - /** * Backward compatibility, see wpdb::$allow_unsafe_unquoted_parameters. * @@ -63,6 +56,17 @@ public function __construct( $dbname ) { $this->charset = 'utf8mb4'; } + /** + * Returns the active MySQL-on-SQLite driver. + * + * @since 3.0.0 + * + * @return WP_MySQL_On_SQLite|null The active driver, or null while disconnected. + */ + public function get_driver(): ?WP_MySQL_On_SQLite { + return $this->dbh; + } + /** * Method to set character set for the database. * @@ -212,14 +216,8 @@ public function close() { return false; } - /* - * @TODO: Replace and deprecate the $GLOBALS['@pdo'] injection mechanism. - * PDO has no close method and is released only when all references are unset. - * Until then, retain external PDOs so reconnects reuse the same database. - */ if ( - ! $this->is_pdo_external - && isset( $GLOBALS['@pdo'] ) + isset( $GLOBALS['@pdo'] ) && $GLOBALS['@pdo'] === $pdo ) { unset( $GLOBALS['@pdo'] ); @@ -422,14 +420,18 @@ public function db_connect( $allow_bail = true ) { return $this->ready; } + if ( isset( $GLOBALS['@pdo'] ) ) { + trigger_error( + 'Injecting a PDO instance via $GLOBALS[\'@pdo\'] is no longer supported.', + E_USER_DEPRECATED + ); + } + $this->last_error = ''; if ( ! isset( $this->charset ) ) { $this->init_charset(); } - $this->is_pdo_external = isset( $GLOBALS['@pdo'] ); - $pdo = $this->is_pdo_external ? $GLOBALS['@pdo'] : null; - // Migrate the database file from a legacy path, if it exists. if ( ! defined( 'DB_FILE' ) && ! file_exists( FQDB ) ) { $old_db_path = FQDBDIR . '.ht.sqlite.php'; @@ -463,10 +465,7 @@ public function db_connect( $allow_bail = true ) { $options = array( 'journal_mode' => defined( 'SQLITE_JOURNAL_MODE' ) ? SQLITE_JOURNAL_MODE : null, ); - if ( null !== $pdo ) { - $options['pdo'] = $pdo; - } - $dbh = new WP_MySQL_On_SQLite( + $dbh = new WP_MySQL_On_SQLite( sprintf( 'mysql-on-sqlite:path=%s;dbname=%s', str_replace( ';', ';;', FQDB ), @@ -477,9 +476,15 @@ public function db_connect( $allow_bail = true ) { $options ); $dbh->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO - $pdo = $dbh->get_connection()->get_pdo(); - $this->dbh = $dbh; - $GLOBALS['@pdo'] = $pdo; + $this->dbh = $dbh; + + /** + * Exposes the SQLite PDO instance for backward compatibility. + * + * @deprecated 3.0.0 Use WP_SQLite_DB::get_driver() with + * WP_MySQL_On_SQLite::get_sqlite_pdo() instead. + */ + $GLOBALS['@pdo'] = $dbh->get_sqlite_pdo(); } catch ( Throwable $e ) { $this->last_error = $this->format_error_message( $e ); } @@ -811,7 +816,7 @@ private function ensure_database_directory( string $database_path ) { /** - * Format SQLite driver error message. + * Format MySQL-on-SQLite driver error message. * * @return string */ @@ -819,8 +824,8 @@ private function format_error_message( Throwable $e ) { $output = '

 
' . PHP_EOL; // Queries. - if ( $e instanceof WP_SQLite_Driver_Exception ) { - $driver = $e->getDriver(); + if ( $e instanceof WP_MySQL_On_SQLite_Exception ) { + $driver = $e->get_driver(); $output .= '
' . PHP_EOL; $output .= '

MySQL query:

' . PHP_EOL; diff --git a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/db.php b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/db.php index 033135152..7ede214af 100644 --- a/packages/plugin-sqlite-database-integration/wp-includes/sqlite/db.php +++ b/packages/plugin-sqlite-database-integration/wp-includes/sqlite/db.php @@ -51,21 +51,8 @@ require_once __DIR__ . '/class-wp-sqlite-db.php'; require_once __DIR__ . '/install-functions.php'; -$db_name = defined( 'DB_NAME' ) ? DB_NAME : ''; +$db_name = defined( 'DB_NAME' ) ? DB_NAME : ''; +$GLOBALS['wpdb'] = new WP_SQLite_DB( $db_name ); -/* - * Debug: Cross-check with MySQL. - * This is for debugging purpose only and requires files - * that are present in the GitHub repository - * but not the plugin published on WordPress.org. - */ -$crosscheck_tests_file_path = __DIR__ . '/class-wp-sqlite-crosscheck-db.php'; -if ( defined( 'SQLITE_DEBUG_CROSSCHECK' ) && SQLITE_DEBUG_CROSSCHECK && file_exists( $crosscheck_tests_file_path ) ) { - require_once $crosscheck_tests_file_path; - $GLOBALS['wpdb'] = new WP_SQLite_Crosscheck_DB( $db_name ); -} else { - $GLOBALS['wpdb'] = new WP_SQLite_DB( $db_name ); - - // Boot the Query Monitor plugin if it is active. - require_once __DIR__ . '/../../integrations/query-monitor/boot.php'; -} +// Boot the Query Monitor plugin if it is active. +require_once __DIR__ . '/../../integrations/query-monitor/boot.php'; 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 89d1fc1ad..e849fe181 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 @@ -68,53 +68,6 @@ function sqlite_make_db_sqlite() { wp_die( $message, 'Database Error!' ); } - /* - * Debug: Cross-check with MySQL. - * This is for debugging purpose only and requires files - * that are present in the GitHub repository - * but not the plugin published on WordPress.org. - */ - if ( defined( 'SQLITE_DEBUG_CROSSCHECK' ) && SQLITE_DEBUG_CROSSCHECK ) { - $host = DB_HOST; - $port = 3306; - if ( str_contains( $host, ':' ) ) { - $host_parts = explode( ':', $host ); - $host = $host_parts[0]; - $port = $host_parts[1]; - } - $dsn = 'mysql:host=' . $host . '; port=' . $port . '; dbname=' . DB_NAME; - $pdo_class = PHP_VERSION_ID >= 80400 ? PDO\MySQL::class : PDO::class; // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO - $pdo_mysql = new $pdo_class( $dsn, DB_USER, DB_PASSWORD, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ) ); // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO - $pdo_mysql->query( 'SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";' ); - $pdo_mysql->query( 'SET time_zone = "+00:00";' ); - foreach ( $queries as $query ) { - $query = trim( $query ); - if ( empty( $query ) ) { - continue; - } - try { - $pdo_mysql->beginTransaction(); - $pdo_mysql->query( $query ); - } catch ( PDOException $err ) { - $err_data = $err->errorInfo; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - $err_code = $err_data[1]; - // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual - if ( 5 == $err_code || 6 == $err_code ) { - // If the database is locked, commit again. - $pdo_mysql->commit(); - } else { - $pdo_mysql->rollBack(); - $message = sprintf( - 'Error occurred while creating tables or indexes...
Query was: %s
', - var_export( $query, true ) - ); - $message .= sprintf( 'Error message is: %s', $err_data[2] ); - wp_die( $message, 'Database Error!' ); - } - } - } - } - return true; } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index c7dd21335..19dfec077 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -34,7 +34,6 @@ /node_modules/* /build/* /wordpress/* - /packages/plugin-sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php