diff --git a/includes/sqlite-database-integration/activate.php b/includes/sqlite-database-integration/activate.php index 6af9ba198..e91e18194 100644 --- a/includes/sqlite-database-integration/activate.php +++ b/includes/sqlite-database-integration/activate.php @@ -15,8 +15,9 @@ */ function sqlite_plugin_activation_redirect( $plugin ) { if ( plugin_basename( SQLITE_MAIN_FILE ) === $plugin ) { - wp_redirect( admin_url( 'options-general.php?page=sqlite-integration' ) ); - exit; + if ( wp_safe_redirect( admin_url( 'options-general.php?page=sqlite-integration' ) ) ) { + exit; + } } } add_action( 'activated_plugin', 'sqlite_plugin_activation_redirect' ); diff --git a/includes/sqlite-database-integration/admin-page.php b/includes/sqlite-database-integration/admin-page.php index 99b513980..f0528e886 100644 --- a/includes/sqlite-database-integration/admin-page.php +++ b/includes/sqlite-database-integration/admin-page.php @@ -12,7 +12,13 @@ * @since 1.0.0 */ function sqlite_add_admin_menu() { - add_options_page(__( 'SQLite integration', 'sqlite-database-integration' ), __( 'SQLite integration', 'sqlite-database-integration' ), 'manage_options', 'sqlite-integration', 'sqlite_integration_admin_screen'); + add_options_page( + __( 'SQLite integration', 'sqlite-database-integration' ), + __( 'SQLite integration', 'sqlite-database-integration' ), + 'manage_options', + 'sqlite-integration', + 'sqlite_integration_admin_screen' + ); } add_action( 'admin_menu', 'sqlite_add_admin_menu' ); diff --git a/includes/sqlite-database-integration/deactivate.php b/includes/sqlite-database-integration/deactivate.php index b64fbcfe0..2b79d9a33 100644 --- a/includes/sqlite-database-integration/deactivate.php +++ b/includes/sqlite-database-integration/deactivate.php @@ -33,7 +33,7 @@ function sqlite_plugin_remove_db_file() { // Run an action on `shutdown`, to deactivate the option in the MySQL database. add_action( 'shutdown', - function() { + function () { global $table_prefix; // Get credentials for the MySQL database. diff --git a/includes/sqlite-database-integration/health-check.php b/includes/sqlite-database-integration/health-check.php index cedec502a..6c64550ba 100644 --- a/includes/sqlite-database-integration/health-check.php +++ b/includes/sqlite-database-integration/health-check.php @@ -75,6 +75,7 @@ function sqlite_plugin_filter_site_status_tests( $tests ) { if ( 'sqlite' === $db_engine ) { unset( $tests['direct']['utf8mb4_support'] ); unset( $tests['direct']['sql_server'] ); + unset( $tests['direct']['persistent_object_cache'] ); // Throws an error because DB_NAME is not defined. } return $tests; diff --git a/includes/sqlite-database-integration/load.php b/includes/sqlite-database-integration/load.php index c082c78f9..3af809035 100644 --- a/includes/sqlite-database-integration/load.php +++ b/includes/sqlite-database-integration/load.php @@ -2,9 +2,9 @@ /** * Plugin Name: SQLite Database Integration * Description: SQLite database driver drop-in. - * Author: WordPress Performance Team - * Version: 2.1.2 - * Requires PHP: 5.6 + * Author: The WordPress Team + * Version: 2.1.7 + * Requires PHP: 7.0 * Textdomain: sqlite-database-integration * * This feature plugin allows WordPress to use SQLite instead of MySQL as its database. diff --git a/includes/sqlite-database-integration/readme.txt b/includes/sqlite-database-integration/readme.txt index 83f67a866..296a021a6 100644 --- a/includes/sqlite-database-integration/readme.txt +++ b/includes/sqlite-database-integration/readme.txt @@ -4,12 +4,12 @@ Contributors: wordpressdotorg, aristath Requires at least: 6.0 Tested up to: 6.4 Requires PHP: 5.6 -Stable tag: 2.1.2 +Stable tag: 2.1.7 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Tags: performance, database -SQLite-integration plugin from the WordPress Performance Team. +SQLite integration plugin by the WordPress Team. == Description == diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php index b3db03574..ed80e19b5 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php @@ -103,7 +103,7 @@ public function select( $db, $dbh = null ) { * * @return string escaped */ - function _real_escape( $str ) { + public function _real_escape( $str ) { return addslashes( $str ); } @@ -278,7 +278,7 @@ public function query( $query ) { } $this->result = $this->dbh->query( $query ); - $this->num_queries++; + ++$this->num_queries; if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); @@ -349,7 +349,7 @@ public function has_cap( $db_cap ) { * @see wpdb::db_version() */ public function db_version() { - return '5.5'; + return '8.0'; } /** diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php index f61e59e37..e996a2aa9 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-lexer.php @@ -1,6 +1,6 @@ $method(); if ( $token ) { @@ -1668,10 +1668,10 @@ private function solve_ambiguity_on_function_keywords() { $next = $this->tokens_get_next(); if ( ( WP_SQLite_Token::TYPE_KEYWORD !== $next->type - || ! in_array( $next->value, $this->keyword_name_indicators, true ) + || ! in_array( $next->value, self::KEYWORD_NAME_INDICATORS, true ) ) && ( WP_SQLite_Token::TYPE_OPERATOR !== $next->type - || ! in_array( $next->value, $this->operator_name_indicators, true ) + || ! in_array( $next->value, self::OPERATOR_NAME_INDICATORS, true ) ) && ( null !== $next->value ) ) { @@ -2068,7 +2068,7 @@ public function parse_number() { } elseif ( $this->last + 1 < $this->string_length && '0' === $this->str[ $this->last ] - && ( 'x' === $this->str[ $this->last + 1 ] || 'X' === $this->str[ $this->last + 1 ] ) + && 'x' === $this->str[ $this->last + 1 ] ) { $token .= $this->str[ $this->last++ ]; $state = 2; @@ -2260,7 +2260,7 @@ public function parse_symbol() { if ( null === $str ) { $str = $this->parse_unknown(); - if ( null === $str ) { + if ( null === $str && ! ( $flags & WP_SQLite_Token::FLAG_SYMBOL_PARAMETER ) ) { $this->error( 'Variable name was expected.', $this->str[ $this->last ], $this->last ); } } @@ -2514,15 +2514,10 @@ public static function is_separator( $str ) { * Constructor. * * @param stdClass[] $tokens The initial array of tokens. - * @param int $count The count of tokens in the initial array. */ - public function tokens( array $tokens = array(), $count = -1 ) { - if ( empty( $tokens ) ) { - return; - } - + public function tokens( array $tokens = array() ) { $this->tokens = $tokens; - $this->tokens_count = -1 === $count ? count( $tokens ) : $count; + $this->tokens_count = count( $tokens ); } /** diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php index 59c6ae607..7d4ac5ee7 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php @@ -221,7 +221,7 @@ public function month( $field ) { * From https://www.php.net/manual/en/datetime.format.php: * * n - Numeric representation of a month, without leading zeros. - * 1 through 12 + * 1 through 12 */ return intval( gmdate( 'n', strtotime( $field ) ) ); } @@ -446,14 +446,14 @@ public function isnull( $field ) { * * As 'IF' is a reserved word for PHP, function name must be changed. * - * @param mixed $expression the statement to be evaluated as true or false. - * @param mixed $true statement or value returned if $expression is true. - * @param mixed $false statement or value returned if $expression is false. + * @param mixed $expression The statement to be evaluated as true or false. + * @param mixed $truthy Statement or value returned if $expression is true. + * @param mixed $falsy Statement or value returned if $expression is false. * * @return mixed */ - public function _if( $expression, $true, $false ) { - return ( true === $expression ) ? $true : $false; + public function _if( $expression, $truthy, $falsy ) { + return ( true === $expression ) ? $truthy : $falsy; } /** diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php index 5d1a6c47a..9976cf341 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-token.php @@ -161,7 +161,7 @@ class WP_SQLite_Token { * * @var mixed|string|null */ - public $keyword; + public $keyword = null; /** * The type of this token. @@ -195,11 +195,10 @@ class WP_SQLite_Token { * @param int $flags The flags of the token. */ public function __construct( $token, $type = 0, $flags = 0 ) { - $this->token = $token; - $this->type = $type; - $this->flags = $flags; - $this->keyword = null; - $this->value = $this->extract(); + $this->token = $token; + $this->type = $type; + $this->flags = $flags; + $this->value = $this->extract(); } /** @@ -262,8 +261,8 @@ private function extract() { case self::TYPE_NUMBER: $ret = str_replace( '--', '', $this->token ); // e.g. ---42 === -42. if ( $this->flags & self::FLAG_NUMBER_HEX ) { + $ret = str_replace( array( '-', '+' ), '', $this->token ); if ( $this->flags & self::FLAG_NUMBER_NEGATIVE ) { - $ret = str_replace( '-', '', $this->token ); $ret = -hexdec( $ret ); } else { $ret = hexdec( $ret ); diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php index 0f1d4a302..e5cc54c02 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -31,6 +31,8 @@ class WP_SQLite_Translator { /** * Class variable to reference to the PDO instance. * + * @access private + * * @var PDO object */ private $pdo; @@ -168,6 +170,20 @@ class WP_SQLite_Translator { */ public $executed_sqlite_queries = array(); + /** + * The affected table name. + * + * @var array + */ + private $table_name = array(); + + /** + * The type of the executed query (SELECT, INSERT, etc). + * + * @var array + */ + private $query_type = array(); + /** * The columns to insert. * @@ -178,6 +194,8 @@ class WP_SQLite_Translator { /** * Class variable to store the result of the query. * + * @access private + * * @var array reference to the PHP object */ private $results = null; @@ -192,6 +210,8 @@ class WP_SQLite_Translator { /** * Class variable to store the file name and function to cause error. * + * @access private + * * @var array */ private $errors; @@ -199,6 +219,8 @@ class WP_SQLite_Translator { /** * Class variable to store the error messages. * + * @access private + * * @var array */ private $error_messages = array(); @@ -207,6 +229,7 @@ class WP_SQLite_Translator { * Class variable to store the affected row id. * * @var int integer + * @access private */ private $last_insert_id; @@ -243,7 +266,7 @@ class WP_SQLite_Translator { /** * Variable to keep track of nested transactions level. * - * @var number + * @var int */ private $transaction_level = 0; @@ -312,6 +335,13 @@ class WP_SQLite_Translator { */ private $sqlite_system_tables = array(); + /** + * The last error message from SQLite. + * + * @var string + */ + private $last_sqlite_error; + /** * Constructor. * @@ -385,7 +415,8 @@ public function __construct( $pdo = null ) { // WordPress happens to use no foreign keys. $statement = $this->pdo->query( 'PRAGMA foreign_keys' ); - if ( $statement->fetchColumn( 0 ) == '0' ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual + if ( $statement->fetchColumn( 0 ) == '0' ) { $this->pdo->query( 'PRAGMA foreign_keys = ON' ); } $this->pdo->query( 'PRAGMA encoding="UTF-8";' ); @@ -399,7 +430,7 @@ public function __construct( $pdo = null ) { * * This definition is changed since version 1.7. */ - function __destruct() { + public function __destruct() { if ( defined( 'SQLITE_MEM_DEBUG' ) && SQLITE_MEM_DEBUG ) { $max = ini_get( 'memory_limit' ); if ( is_null( $max ) ) { @@ -591,8 +622,31 @@ public function query( $statement, $mode = PDO::FETCH_OBJ, ...$fetch_mode_args ) } } while ( $error ); + /** + * Notifies that a query has been translated and executed. + * + * @param string $query The executed SQL query. + * @param string $query_type The type of the SQL query (e.g. SELECT, INSERT, UPDATE, DELETE). + * @param string $table_name The name of the table affected by the SQL query. + * @param array $insert_columns The columns affected by the INSERT query (if applicable). + * @param int $last_insert_id The ID of the last inserted row (if applicable). + * @param int $affected_rows The number of affected rows (if applicable). + * + * @since 0.1.0 + */ + do_action( + 'sqlite_translated_query_executed', + $this->mysql_query, + $this->query_type, + $this->table_name, + $this->insert_columns, + $this->last_insert_id, + $this->affected_rows + ); + // Commit the nested transaction. $this->commit(); + return $this->return_value; } catch ( Exception $err ) { // Rollback the nested transaction. @@ -710,11 +764,11 @@ public function get_return_value() { * @throws Exception If the query is not supported. */ private function execute_mysql_query( $query ) { - $tokens = ( new WP_SQLite_Lexer( $query ) )->tokens; - $this->rewriter = new WP_SQLite_Query_Rewriter( $tokens ); - $query_type = $this->rewriter->peek()->value; + $tokens = ( new WP_SQLite_Lexer( $query ) )->tokens; + $this->rewriter = new WP_SQLite_Query_Rewriter( $tokens ); + $this->query_type = $this->rewriter->peek()->value; - switch ( $query_type ) { + switch ( $this->query_type ) { case 'ALTER': $this->execute_alter(); break; @@ -785,11 +839,11 @@ private function execute_mysql_query( $query ) { case 'OPTIMIZE': case 'REPAIR': case 'ANALYZE': - $this->execute_optimize( $query_type ); + $this->execute_optimize( $this->query_type ); break; default: - throw new Exception( 'Unknown query type: ' . $query_type ); + throw new Exception( 'Unknown query type: ' . $this->query_type ); } } @@ -1241,7 +1295,7 @@ private function execute_delete() { // SELECT to fetch the IDs of the rows to delete, then delete them // using a separate DELETE query. - $table_name = $rewriter->skip()->value; + $this->table_name = $rewriter->skip()->value; $rewriter->add( new WP_SQLite_Token( 'SELECT', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) ); /* @@ -1257,11 +1311,11 @@ private function execute_delete() { for ( $i = $index + 1; $i < $rewriter->max; $i++ ) { // Assume the table name is the first token after FROM. if ( ! $rewriter->input_tokens[ $i ]->is_semantically_void() ) { - $table_name = $rewriter->input_tokens[ $i ]->value; + $this->table_name = $rewriter->input_tokens[ $i ]->value; break; } } - if ( ! $table_name ) { + if ( ! $this->table_name ) { throw new Exception( 'Could not find table name for dual delete query.' ); } @@ -1269,7 +1323,7 @@ private function execute_delete() { * Now, let's figure out the primary key name. * This assumes that all listed table names are the same. */ - $q = $this->execute_sqlite_query( 'SELECT l.name FROM pragma_table_info("' . $table_name . '") as l WHERE l.pk = 1;' ); + $q = $this->execute_sqlite_query( 'SELECT l.name FROM pragma_table_info("' . $this->table_name . '") as l WHERE l.pk = 1;' ); $pk_name = $q->fetch()['name']; /* @@ -1317,8 +1371,8 @@ private function execute_delete() { $query = ( count( $ids_to_delete ) - ? "DELETE FROM {$table_name} WHERE {$pk_name} IN (" . implode( ',', $ids_to_delete ) . ')' - : "DELETE FROM {$table_name} WHERE 0=1" + ? "DELETE FROM {$this->table_name} WHERE {$pk_name} IN (" . implode( ',', $ids_to_delete ) . ')' + : "DELETE FROM {$this->table_name} WHERE 0=1" ); $this->execute_sqlite_query( $query ); $this->set_result_from_affected_rows( @@ -1346,7 +1400,8 @@ private function execute_select() { $this->remember_last_reserved_keyword( $token ); if ( ! $table_name ) { - $table_name = $this->peek_table_name( $token ); + $this->table_name = $this->peek_table_name( $token ); + $table_name = $this->peek_table_name( $token ); } if ( $this->skip_sql_calc_found_rows( $token ) ) { @@ -1418,7 +1473,9 @@ private function execute_select() { */ private function execute_truncate() { $this->rewriter->skip(); // TRUNCATE. - $this->rewriter->skip(); // TABLE. + if ( 'TABLE' === strtoupper( $this->rewriter->peek()->value ) ) { + $this->rewriter->skip(); // TABLE. + } $this->rewriter->add( new WP_SQLite_Token( 'DELETE', WP_SQLite_Token::TYPE_KEYWORD ) ); $this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) ); $this->rewriter->add( new WP_SQLite_Token( 'FROM', WP_SQLite_Token::TYPE_KEYWORD ) ); @@ -1435,8 +1492,8 @@ private function execute_truncate() { */ private function execute_describe() { $this->rewriter->skip(); - $table_name = $this->rewriter->consume()->value; - $stmt = $this->execute_sqlite_query( + $this->table_name = $this->rewriter->consume()->value; + $stmt = $this->execute_sqlite_query( "SELECT `name` as `Field`, ( @@ -1465,9 +1522,9 @@ private function execute_describe() { ELSE 'PRI' END ) as `Key` - FROM pragma_table_info(\"$table_name\") p + FROM pragma_table_info(\"$this->table_name\") p LEFT JOIN " . self::DATA_TYPES_CACHE_TABLE . " d - ON d.`table` = \"$table_name\" + ON d.`table` = \"$this->table_name\" AND d.`column_or_index` = p.`name` ; " @@ -1493,6 +1550,17 @@ private function execute_update() { break; } + // Record the table name. + if ( + ! $this->table_name && + ! $token->matches( + WP_SQLite_Token::TYPE_KEYWORD, + WP_SQLite_Token::FLAG_KEYWORD_RESERVED + ) + ) { + $this->table_name = $token->value; + } + $this->remember_last_reserved_keyword( $token ); if ( @@ -1517,7 +1585,6 @@ private function execute_update() { private function execute_insert_or_replace() { $params = array(); $is_in_duplicate_section = false; - $table_name = null; $this->rewriter->consume(); // INSERT or REPLACE. @@ -1531,7 +1598,7 @@ private function execute_insert_or_replace() { // Consume and record the table name. $this->insert_columns = array(); $this->rewriter->consume(); // INTO. - $table_name = $this->rewriter->consume()->value; // Table name. + $this->table_name = $this->rewriter->consume()->value; // Table name. /* * A list of columns is given if the opening parenthesis @@ -1590,7 +1657,7 @@ private function execute_insert_or_replace() { ) ) { $is_in_duplicate_section = true; - $this->translate_on_duplicate_key( $table_name ); + $this->translate_on_duplicate_key( $this->table_name ); continue; } @@ -1606,6 +1673,7 @@ private function execute_insert_or_replace() { if ( is_numeric( $this->last_insert_id ) ) { $this->last_insert_id = (int) $this->last_insert_id; } + $this->last_insert_id = apply_filters( 'sqlite_last_insert_id', $this->last_insert_id, $this->table_name ); } /** @@ -1683,9 +1751,9 @@ private function preprocess_string_literal( $value ) { private function preprocess_like_expr( &$token ) { /* * This code handles escaped wildcards in LIKE clauses. - * If we are within a LIKE expression, we look for \_ and \%, the + * If we are within a LIKE experession, we look for \_ and \%, the * escaped LIKE wildcards, the ones where we want a literal, not a - * wildcard match. We change the \ escape for an ASCII \x1A (SUB) character, + * wildcard match. We change the \ escape for an ASCII \x1a (SUB) character, * so the \ characters won't get munged. * These \_ and \% escape sequences are in the token name, because * the lexer has already done stripcslashes on the value. @@ -1694,7 +1762,7 @@ private function preprocess_like_expr( &$token ) { /* Remove the quotes around the name. */ $unescaped_value = mb_substr( $token->token, 1, -1, 'UTF-8' ); if ( strpos($unescaped_value, '\_') !== false || strpos($unescaped_value, '\%') !== false ) { - $this->like_escape_count ++; + ++$this->like_escape_count; return str_replace( array( '\_', '\%' ), array( self::LIKE_ESCAPE_CHAR . '_', self::LIKE_ESCAPE_CHAR . '%' ), @@ -2320,14 +2388,14 @@ private function translate_like_escape( $token ) { } else { /* open parenthesis during LIKE parameter, count it. */ if ( $token->matches( WP_SQLite_Token::TYPE_OPERATOR, null, array( '(' ) ) ) { - $this->like_expression_nesting ++; + ++$this->like_expression_nesting; return false; } /* close parenthesis matching open parenthesis during LIKE parameter, count it. */ if ( $this->like_expression_nesting > 1 && $token->matches( WP_SQLite_Token::TYPE_OPERATOR, null, array( ')' ) ) ) { - $this->like_expression_nesting --; + --$this->like_expression_nesting; return false; } @@ -2415,12 +2483,20 @@ private function strip_sqlite_system_tables( $tables ) { array_filter( $tables, function ( $table ) { - // Bail early if $table is not an object. - if ( ! is_object( $table ) ) { - return true; + $table_name = false; + if ( is_array( $table ) ) { + if ( isset( $table['Name'] ) ) { + $table_name = $table['Name']; + } elseif ( isset( $table['table_name'] ) ) { + $table_name = $table['table_name']; + } + } elseif ( is_object( $table ) ) { + $table_name = property_exists( $table, 'Name' ) + ? $table->Name // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase + : $table->table_name; } - $table_name = property_exists( $table, 'Name' ) ? $table->Name : $table->table_name; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase - return ! array_key_exists( $table_name, $this->sqlite_system_tables ); + + return $table_name && ! array_key_exists( $table_name, $this->sqlite_system_tables ); }, ARRAY_FILTER_USE_BOTH ) @@ -2591,7 +2667,7 @@ private function execute_alter() { throw new Exception( 'Unknown subject: ' . $subject ); } - $table_name = $this->normalize_column_name( $this->rewriter->consume()->token ); + $this->table_name = $this->normalize_column_name( $this->rewriter->consume()->token ); do { /* * This loop may be executed multiple times if there are multiple operations in the ALTER query. @@ -2603,13 +2679,13 @@ private function execute_alter() { new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( 'TABLE', WP_SQLite_Token::TYPE_KEYWORD ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), - new WP_SQLite_Token( $table_name, WP_SQLite_Token::TYPE_KEYWORD ), + new WP_SQLite_Token( $this->table_name, WP_SQLite_Token::TYPE_KEYWORD ), ) ); $op_type = strtoupper( $this->rewriter->consume()->token ); $op_subject = strtoupper( $this->rewriter->consume()->token ); $mysql_index_type = $this->normalize_mysql_index_type( $op_subject ); - $is_index_op = ! ! $mysql_index_type; + $is_index_op = (bool) $mysql_index_type; if ( 'ADD' === $op_type && 'COLUMN' === $op_subject ) { $column_name = $this->rewriter->consume()->value; @@ -2626,7 +2702,7 @@ private function execute_alter() { ) ); $this->update_data_type_cache( - $table_name, + $this->table_name, $column_name, $mysql_data_type ); @@ -2638,7 +2714,7 @@ private function execute_alter() { $new_field = $this->parse_mysql_create_table_field(); $alter_terminator = end( $this->rewriter->output_tokens ); $this->update_data_type_cache( - $table_name, + $this->table_name, $new_field->name, $new_field->mysql_data_type ); @@ -2659,8 +2735,8 @@ private function execute_alter() { */ // 1. Get the existing table schema. - $old_schema = $this->get_sqlite_create_table( $table_name ); - $old_indexes = $this->get_keys( $table_name, false ); + $old_schema = $this->get_sqlite_create_table( $this->table_name ); + $old_indexes = $this->get_keys( $this->table_name, false ); // 2. Adjust the column definition. @@ -2718,19 +2794,19 @@ private function execute_alter() { } // 3. Copy the data out of the old table - $cache_table_name = "_tmp__{$table_name}_" . rand( 10000000, 99999999 ); + $cache_table_name = "_tmp__{$this->table_name}_" . rand( 10000000, 99999999 ); $this->execute_sqlite_query( - "CREATE TABLE `$cache_table_name` as SELECT * FROM `$table_name`" + "CREATE TABLE `$cache_table_name` as SELECT * FROM `$this->table_name`" ); // 4. Drop the old table to free up the indexes names - $this->execute_sqlite_query( "DROP TABLE `$table_name`" ); + $this->execute_sqlite_query( "DROP TABLE `$this->table_name`" ); // 5. Create a new table from the updated schema $this->execute_sqlite_query( $create_table->get_updated_query() ); // 6. Copy the data from step 3 to the new table - $this->execute_sqlite_query( "INSERT INTO {$table_name} SELECT * FROM $cache_table_name" ); + $this->execute_sqlite_query( "INSERT INTO {$this->table_name} SELECT * FROM $cache_table_name" ); // 7. Drop the old table copy $this->execute_sqlite_query( "DROP TABLE `$cache_table_name`" ); @@ -2759,7 +2835,7 @@ private function execute_alter() { * a part of the CREATE TABLE statement */ $this->execute_sqlite_query( - "CREATE $unique INDEX IF NOT EXISTS `{$row['index']['name']}` ON $table_name (" . implode( ', ', $columns ) . ')' + "CREATE $unique INDEX IF NOT EXISTS `{$row['index']['name']}` ON $this->table_name (" . implode( ', ', $columns ) . ')' ); } @@ -2776,7 +2852,7 @@ private function execute_alter() { } elseif ( 'ADD' === $op_type && $is_index_op ) { $key_name = $this->rewriter->consume()->value; $sqlite_index_type = $this->mysql_index_type_to_sqlite_type( $mysql_index_type ); - $sqlite_index_name = "{$table_name}__$key_name"; + $sqlite_index_name = "{$this->table_name}__$key_name"; $this->rewriter->replace_all( array( new WP_SQLite_Token( 'CREATE', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ), @@ -2787,13 +2863,13 @@ private function execute_alter() { new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( 'ON', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), - new WP_SQLite_Token( '"' . $table_name . '"', WP_SQLite_Token::TYPE_STRING, WP_SQLite_Token::FLAG_STRING_DOUBLE_QUOTES ), + new WP_SQLite_Token( '"' . $this->table_name . '"', WP_SQLite_Token::TYPE_STRING, WP_SQLite_Token::FLAG_STRING_DOUBLE_QUOTES ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( '(', WP_SQLite_Token::TYPE_OPERATOR ), ) ); $this->update_data_type_cache( - $table_name, + $this->table_name, $sqlite_index_name, $mysql_index_type ); @@ -2841,7 +2917,7 @@ private function execute_alter() { new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), new WP_SQLite_Token( 'INDEX', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ), new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ), - new WP_SQLite_Token( "\"{$table_name}__$key_name\"", WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_KEY ), + new WP_SQLite_Token( "\"{$this->table_name}__$key_name\"", WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_KEY ), ) ); } else { @@ -3381,16 +3457,16 @@ private function handle_error( Exception $err ) { * When $wpdb::suppress_errors is set to true or $wpdb::show_errors is set to false, * the error messages are ignored. * - * @param string $line Where the error occurred. - * @param string $function Indicate the function name where the error occurred. - * @param string $message The message. + * @param string $line Where the error occurred. + * @param string $function_name Indicate the function name where the error occurred. + * @param string $message The message. * * @return boolean|void */ - private function set_error( $line, $function, $message ) { + private function set_error( $line, $function_name, $message ) { $this->errors[] = array( 'line' => $line, - 'function' => $function, + 'function' => $function_name, ); $this->error_messages[] = $message; $this->is_error = true; @@ -3543,8 +3619,10 @@ private function flush() { $this->mysql_query = ''; $this->results = null; $this->last_exec_returned = null; + $this->table_name = null; $this->last_insert_id = null; $this->affected_rows = null; + $this->insert_columns = array(); $this->column_data = array(); $this->num_rows = null; $this->return_value = null; @@ -3574,6 +3652,16 @@ public function begin_transaction() { } finally { if ( $success ) { ++$this->transaction_level; + /** + * Notifies that a transaction-related query has been translated and executed. + * + * @param string $command The SQL statement (one of "START TRANSACTION", "COMMIT", "ROLLBACK"). + * @param bool $success Whether the SQL statement was successful or not. + * @param int $nesting_level The nesting level of the transaction. + * + * @since 0.1.0 + */ + do_action( 'sqlite_transaction_query_executed', 'START TRANSACTION', (bool) $this->last_exec_returned, $this->transaction_level - 1 ); } } return $success; @@ -3595,6 +3683,8 @@ public function commit() { } else { $this->execute_sqlite_query( 'RELEASE SAVEPOINT LEVEL' . $this->transaction_level ); } + + do_action( 'sqlite_transaction_query_executed', 'COMMIT', (bool) $this->last_exec_returned, $this->transaction_level ); return $this->last_exec_returned; } @@ -3614,6 +3704,7 @@ public function rollback() { } else { $this->execute_sqlite_query( 'ROLLBACK TO SAVEPOINT LEVEL' . $this->transaction_level ); } + do_action( 'sqlite_transaction_query_executed', 'ROLLBACK', (bool) $this->last_exec_returned, $this->transaction_level ); return $this->last_exec_returned; } } diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/db.php b/includes/sqlite-database-integration/wp-includes/sqlite/db.php index 2053736a4..13c2111dc 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/db.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/db.php @@ -7,7 +7,7 @@ */ // Require the constants file. -require_once dirname( dirname( __DIR__ ) ) . '/constants.php'; +require_once dirname( __DIR__, 2 ) . '/constants.php'; // Bail early if DB_ENGINE is not defined as sqlite. if ( ! defined( 'DB_ENGINE' ) || 'sqlite' !== DB_ENGINE ) { @@ -56,7 +56,7 @@ * that are present in the GitHub repository * but not the plugin published on WordPress.org. */ -$crosscheck_tests_file_path = dirname( dirname( __DIR__ ) ) . '/tests/class-wp-sqlite-crosscheck-db.php'; +$crosscheck_tests_file_path = dirname( __DIR__, 2 ) . '/tests/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(); diff --git a/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php b/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php index 87ace27b0..ffd75abf9 100644 --- a/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php +++ b/includes/sqlite-database-integration/wp-includes/sqlite/install-functions.php @@ -89,7 +89,8 @@ function sqlite_make_db_sqlite() { } catch ( PDOException $err ) { $err_data = $err->errorInfo; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $err_code = $err_data[1]; - if ( 5 == $err_code || 6 == $err_code ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual + if ( 5 == $err_code || 6 == $err_code ) { // If the database is locked, commit again. $pdo_mysql->commit(); } else {