← All changes
|
wp-includes/database/sqlite/class-wp-sqlite-driver.php
+55
-49
2.2.22
→
trunk
View file →
| @@ -2,26 +2,31 @@ | ||
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * The SQLite driver uses PDO. Enable PDO function calls: |
| 5 | 5 | * phpcs:disable WordPress.DB.RestrictedClasses.mysql__PDO |
| 6 | + * | |
| 7 | + * PDO uses camel case naming, enable non-snake case: | |
| 8 | + * phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid | |
| 6 | 9 | */ |
| 7 | 10 | |
| 8 | 11 | /** |
| 9 | - * For back compatibility with dependencies that use their own loader scripts | |
| 10 | - * (e.g., WP CLI SQLite Command), ensure the new PDO-based classes are loaded. | |
| 12 | + * For backward compatibility with dependencies that use their own loader scripts | |
| 13 | + * (e.g., WP CLI SQLite Command), ensure the PDO-based classes are loaded. | |
| 11 | 14 | */ |
| 12 | -require_once __DIR__ . '/class-wp-pdo-mysql-on-sqlite.php'; | |
| 13 | -require_once __DIR__ . '/class-wp-pdo-proxy-statement.php'; | |
| 15 | +require_once __DIR__ . '/class-wp-mysql-on-sqlite.php'; | |
| 16 | +require_once __DIR__ . '/class-wp-mysql-on-sqlite-statement.php'; | |
| 14 | 17 | |
| 15 | 18 | /** |
| 16 | - * Deprecated: A proxy of the WP_PDO_MySQL_On_SQLite class preserving legacy API. | |
| 19 | + * Deprecated: A proxy of the WP_MySQL_On_SQLite class preserving the legacy API. | |
| 17 | 20 | * |
| 18 | - * This is a temporary class to preserve the legacy API for easier transition | |
| 19 | - * to the new PDO-based API, developed in the "WP_PDO_MySQL_On_SQLite" class. | |
| 21 | + * This class temporarily preserves the legacy constructor and result API while | |
| 22 | + * consumers transition to the PDO-based WP_MySQL_On_SQLite API. | |
| 23 | + * | |
| 24 | + * @deprecated 3.0.0 Use WP_MySQL_On_SQLite instead. | |
| 20 | 25 | */ |
| 21 | 26 | class WP_SQLite_Driver { |
| 22 | 27 | /** |
| 23 | - * The SQLite engine version. | |
| 28 | + * The emulated MySQL client library version. | |
| 24 | 29 | * |
| 25 | 30 | * This is a mysqli-like property that is needed to avoid a PHP warning in |
| 26 | 31 | * the WordPress health info. The "WP_Debug_Data::get_wp_database()" method |
| 27 | 32 | * calls "$wpdb->dbh->client_info" - a mysqli-specific abstraction leak. |
| @@ -37,13 +42,20 @@ | ||
| 37 | 42 | |
| 38 | 43 | /** |
| 39 | 44 | * The MySQL-on-SQLite driver instance. |
| 40 | 45 | * |
| 41 | - * @var WP_PDO_MySQL_On_SQLite | |
| 46 | + * @var WP_MySQL_On_SQLite | |
| 42 | 47 | */ |
| 43 | 48 | private $mysql_on_sqlite_driver; |
| 44 | 49 | |
| 45 | 50 | /** |
| 51 | + * Statement returned for the last emulated query. | |
| 52 | + * | |
| 53 | + * @var WP_MySQL_On_SQLite_Statement|null | |
| 54 | + */ | |
| 55 | + private $last_statement; | |
| 56 | + | |
| 57 | + /** | |
| 46 | 58 | * Results of the last emulated query. |
| 47 | 59 | * |
| 48 | 60 | * @var mixed |
| 49 | 61 | */ |
| @@ -53,31 +65,32 @@ | ||
| 53 | 65 | * Constructor. |
| 54 | 66 | * |
| 55 | 67 | * Set up an SQLite connection and the MySQL-on-SQLite driver. |
| 56 | 68 | * |
| 57 | - * @param WP_SQLite_Connection $connection A SQLite database connection. | |
| 58 | - * @param string $database The database name. | |
| 69 | + * @param WP_SQLite_Connection $connection A SQLite database connection. | |
| 70 | + * @param string $database The database name. | |
| 71 | + * @param int $mysql_version The emulated MySQL version as an integer. | |
| 59 | 72 | * |
| 60 | - * @throws WP_SQLite_Driver_Exception When the driver initialization fails. | |
| 73 | + * @throws WP_MySQL_On_SQLite_Exception When the driver initialization fails. | |
| 61 | 74 | */ |
| 62 | 75 | public function __construct( |
| 63 | 76 | WP_SQLite_Connection $connection, |
| 64 | 77 | string $database, |
| 65 | - int $mysql_version = 80038 | |
| 78 | + int $mysql_version = WP_MySQL_On_SQLite::DEFAULT_MYSQL_VERSION | |
| 66 | 79 | ) { |
| 67 | - $this->mysql_on_sqlite_driver = new WP_PDO_MySQL_On_SQLite( | |
| 68 | - sprintf( 'mysql-on-sqlite:dbname=%s', $database ), | |
| 80 | + $this->mysql_on_sqlite_driver = new WP_MySQL_On_SQLite( | |
| 81 | + sprintf( 'mysql-on-sqlite:dbname=%s', str_replace( ';', ';;', $database ) ), | |
| 69 | 82 | null, |
| 70 | 83 | null, |
| 71 | 84 | array( |
| 72 | - 'mysql_version' => $mysql_version, | |
| 73 | - 'pdo' => $connection->get_pdo(), | |
| 85 | + 'mysql_version' => $mysql_version, | |
| 86 | + 'sqlite_pdo' => $connection->get_pdo(), | |
| 87 | + 'sqlite_journal_mode' => $connection->query( 'PRAGMA journal_mode' )->fetchColumn(), | |
| 74 | 88 | ) |
| 75 | 89 | ); |
| 76 | - $this->main_db_name = $database; | |
| 77 | 90 | $this->client_info = $this->mysql_on_sqlite_driver->client_info; |
| 78 | 91 | |
| 79 | - $connection->get_pdo()->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); | |
| 92 | + $this->mysql_on_sqlite_driver->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, true ); | |
| 80 | 93 | } |
| 81 | 94 | |
| 82 | 95 | /** |
| 83 | 96 | * Get the SQLite connection instance. |
| @@ -143,9 +156,13 @@ | ||
| 143 | 156 | * |
| 144 | 157 | * @return int|string |
| 145 | 158 | */ |
| 146 | 159 | public function get_insert_id() { |
| 147 | - return $this->mysql_on_sqlite_driver->get_insert_id(); | |
| 160 | + $last_insert_id = $this->mysql_on_sqlite_driver->lastInsertId(); | |
| 161 | + if ( is_numeric( $last_insert_id ) ) { | |
| 162 | + $last_insert_id = (int) $last_insert_id; | |
| 163 | + } | |
| 164 | + return $last_insert_id; | |
| 148 | 165 | } |
| 149 | 166 | |
| 150 | 167 | /** |
| 151 | 168 | * @param string $query Full SQL statement string. |
| @@ -153,12 +170,14 @@ | ||
| 153 | 170 | * @param array ...$fetch_mode_args Additional fetch mode arguments. |
| 154 | 171 | * |
| 155 | 172 | * @return mixed Return value, depending on the query type. |
| 156 | 173 | * |
| 157 | - * @throws WP_SQLite_Driver_Exception When the query execution fails. | |
| 174 | + * @throws WP_MySQL_On_SQLite_Exception When the query execution fails. | |
| 158 | 175 | */ |
| 159 | 176 | public function query( string $query, $fetch_mode = PDO::FETCH_OBJ, ...$fetch_mode_args ) { |
| 160 | - $stmt = $this->mysql_on_sqlite_driver->query( $query, $fetch_mode, ...$fetch_mode_args ); | |
| 177 | + $this->last_statement = null; | |
| 178 | + $stmt = $this->mysql_on_sqlite_driver->query( $query, $fetch_mode, ...$fetch_mode_args ); | |
| 179 | + $this->last_statement = $stmt; | |
| 161 | 180 | |
| 162 | 181 | if ( $stmt->columnCount() > 0 ) { |
| 163 | 182 | $this->last_result = $stmt->fetchAll( $fetch_mode ); |
| 164 | 183 | } else { |
| @@ -200,9 +219,9 @@ | ||
| 200 | 219 | * |
| 201 | 220 | * @return int |
| 202 | 221 | */ |
| 203 | 222 | public function get_last_column_count(): int { |
| 204 | - return $this->mysql_on_sqlite_driver->get_last_column_count(); | |
| 223 | + return null === $this->last_statement ? 0 : $this->last_statement->columnCount(); | |
| 205 | 224 | } |
| 206 | 225 | |
| 207 | 226 | /** |
| 208 | 227 | * Get column metadata for results of the last emulated query. |
| @@ -209,9 +228,18 @@ | ||
| 209 | 228 | * |
| 210 | 229 | * @return array |
| 211 | 230 | */ |
| 212 | 231 | public function get_last_column_meta(): array { |
| 213 | - return $this->mysql_on_sqlite_driver->get_last_column_meta(); | |
| 232 | + if ( null === $this->last_statement ) { | |
| 233 | + return array(); | |
| 234 | + } | |
| 235 | + | |
| 236 | + $column_meta = array(); | |
| 237 | + $column_count = $this->last_statement->columnCount(); | |
| 238 | + for ( $i = 0; $i < $column_count; $i++ ) { | |
| 239 | + $column_meta[] = $this->last_statement->getColumnMeta( $i ); | |
| 240 | + } | |
| 241 | + return $column_meta; | |
| 214 | 242 | } |
| 215 | 243 | |
| 216 | 244 | /** |
| 217 | 245 | * Execute a query in SQLite. |
| @@ -227,14 +255,14 @@ | ||
| 227 | 255 | |
| 228 | 256 | /** |
| 229 | 257 | * Begin a new transaction or nested transaction. |
| 230 | 258 | */ |
| 231 | - public function beginTransaction(): void { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid | |
| 232 | - $this->mysql_on_sqlite_driver->begin_transaction(); | |
| 259 | + public function beginTransaction(): void { | |
| 260 | + $this->mysql_on_sqlite_driver->beginTransaction(); | |
| 233 | 261 | } |
| 234 | 262 | |
| 235 | 263 | /** |
| 236 | - * A temporary alias for back compatibility. | |
| 264 | + * A temporary alias for backward compatibility. | |
| 237 | 265 | * |
| 238 | 266 | * @see self::beginTransaction() |
| 239 | 267 | */ |
| 240 | 268 | public function begin_transaction(): void { |
| @@ -252,28 +280,6 @@ | ||
| 252 | 280 | * Rollback the current transaction or nested transaction. |
| 253 | 281 | */ |
| 254 | 282 | public function rollback(): void { |
| 255 | 283 | $this->mysql_on_sqlite_driver->rollback(); |
| 256 | - } | |
| 257 | - | |
| 258 | - /** | |
| 259 | - * Proxy also the private property "$main_db_name", as it is used in tests. | |
| 260 | - */ | |
| 261 | - public function __set( string $name, $value ): void { | |
| 262 | - if ( 'main_db_name' === $name ) { | |
| 263 | - $closure = function ( string $value ) { | |
| 264 | - $this->main_db_name = $value; | |
| 265 | - }; | |
| 266 | - $closure->call( $this->mysql_on_sqlite_driver, $value ); | |
| 267 | - } | |
| 268 | - } | |
| 269 | - | |
| 270 | - /** | |
| 271 | - * Proxy also this private method, as it is used in tests. | |
| 272 | - */ | |
| 273 | - private function quote_mysql_utf8_string_literal( string $utf8_literal ): string { | |
| 274 | - $closure = function ( string $utf8_literal ) { | |
| 275 | - return $this->quote_mysql_utf8_string_literal( $utf8_literal ); | |
| 276 | - }; | |
| 277 | - return $closure->call( $this->mysql_on_sqlite_driver, $utf8_literal ); | |
| 278 | 284 | } |
| 279 | 285 | } |