Skip to content

Commit 94e582c

Browse files
committed
Always quote identifiers in driver and reconstructor
1 parent 859fb9f commit 94e582c

File tree

3 files changed

+101
-47
lines changed

3 files changed

+101
-47
lines changed

tests/WP_SQLite_Driver_Tests.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -1229,14 +1229,14 @@ public function testColumnWithOnUpdate() {
12291229
'name' => '_wp_sqlite__tmp_table_created_at_on_update',
12301230
'tbl_name' => '_tmp_table',
12311231
'rootpage' => '0',
1232-
'sql' => "CREATE TRIGGER \"_wp_sqlite__tmp_table_created_at_on_update\"\n\t\t\tAFTER UPDATE ON \"_tmp_table\"\n\t\t\tFOR EACH ROW\n\t\t\tBEGIN\n\t\t\t UPDATE \"_tmp_table\" SET \"created_at\" = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\tEND",
1232+
'sql' => "CREATE TRIGGER `_wp_sqlite__tmp_table_created_at_on_update`\n\t\t\t\tAFTER UPDATE ON `_tmp_table`\n\t\t\t\tFOR EACH ROW\n\t\t\t\tBEGIN\n\t\t\t\t UPDATE `_tmp_table` SET `created_at` = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\t\tEND",
12331233
),
12341234
(object) array(
12351235
'type' => 'trigger',
12361236
'name' => '_wp_sqlite__tmp_table_updated_at_on_update',
12371237
'tbl_name' => '_tmp_table',
12381238
'rootpage' => '0',
1239-
'sql' => "CREATE TRIGGER \"_wp_sqlite__tmp_table_updated_at_on_update\"\n\t\t\tAFTER UPDATE ON \"_tmp_table\"\n\t\t\tFOR EACH ROW\n\t\t\tBEGIN\n\t\t\t UPDATE \"_tmp_table\" SET \"updated_at\" = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\tEND",
1239+
'sql' => "CREATE TRIGGER `_wp_sqlite__tmp_table_updated_at_on_update`\n\t\t\t\tAFTER UPDATE ON `_tmp_table`\n\t\t\t\tFOR EACH ROW\n\t\t\t\tBEGIN\n\t\t\t\t UPDATE `_tmp_table` SET `updated_at` = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;\n\t\t\t\tEND",
12401240
),
12411241
),
12421242
$results

wp-includes/sqlite-ast/class-wp-sqlite-driver.php

+83-41
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,10 @@ public function get_saved_driver_version(): string {
577577
$default_version = '0.0.0';
578578
try {
579579
$stmt = $this->execute_sqlite_query(
580-
sprintf( 'SELECT value FROM %s WHERE name = ?', self::GLOBAL_VARIABLES_TABLE_NAME ),
580+
sprintf(
581+
'SELECT value FROM %s WHERE name = ?',
582+
$this->quote_sqlite_identifier( self::GLOBAL_VARIABLES_TABLE_NAME )
583+
),
581584
array( self::DRIVER_VERSION_VARIABLE_NAME )
582585
);
583586
return $stmt->fetchColumn() ?? $default_version;
@@ -1212,7 +1215,11 @@ private function execute_delete_statement( WP_Parser_Node $node ): void {
12121215

12131216
$select_list = array();
12141217
foreach ( $table_aliases as $table ) {
1215-
$select_list[] = "\"$table\".rowid AS \"{$table}_rowid\"";
1218+
$select_list[] = sprintf(
1219+
'%s.rowid AS %s',
1220+
$this->quote_sqlite_identifier( $table ),
1221+
$this->quote_sqlite_identifier( $table . '_rowid' )
1222+
);
12161223
}
12171224

12181225
$ids = $this->execute_sqlite_query(
@@ -1288,7 +1295,10 @@ private function execute_create_table_statement( WP_Parser_Node $node ): void {
12881295
if ( $subnode->has_child_node( 'ifNotExists' ) ) {
12891296
$tables_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'tables' );
12901297
$table_exists = $this->execute_sqlite_query(
1291-
"SELECT 1 FROM $tables_table WHERE table_schema = ? AND table_name = ?",
1298+
sprintf(
1299+
'SELECT 1 FROM %s WHERE table_schema = ? AND table_name = ?',
1300+
$this->quote_sqlite_identifier( $tables_table )
1301+
),
12921302
array( $this->db_name, $table_name )
12931303
)->fetchColumn();
12941304

@@ -1329,7 +1339,10 @@ private function execute_alter_table_statement( WP_Parser_Node $node ): void {
13291339
// Save all column names from the original table.
13301340
$columns_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' );
13311341
$column_names = $this->execute_sqlite_query(
1332-
"SELECT COLUMN_NAME FROM $columns_table WHERE table_schema = ? AND table_name = ?",
1342+
sprintf(
1343+
'SELECT COLUMN_NAME FROM %s WHERE table_schema = ? AND table_name = ?',
1344+
$this->quote_sqlite_identifier( $columns_table )
1345+
),
13331346
array( $this->db_name, $table_name )
13341347
)->fetchAll( PDO::FETCH_COLUMN );
13351348

@@ -1437,9 +1450,9 @@ private function execute_truncate_table_statement( WP_Parser_Node $node ): void
14371450
$this->translate( $node->get_first_child_node( 'tableRef' ) )
14381451
);
14391452

1440-
$quoted_table_name = $this->quote_sqlite_identifier( $table_name );
1441-
1442-
$this->execute_sqlite_query( "DELETE FROM $quoted_table_name" );
1453+
$this->execute_sqlite_query(
1454+
sprintf( 'DELETE FROM %s', $this->quote_sqlite_identifier( $table_name ) )
1455+
);
14431456
try {
14441457
$this->execute_sqlite_query( 'DELETE FROM sqlite_sequence WHERE name = ?', array( $table_name ) );
14451458
} catch ( PDOException $e ) {
@@ -1576,7 +1589,7 @@ private function execute_show_index_statement( string $table_name ): void {
15761589
INDEX_COMMENT AS `Index_comment`,
15771590
IS_VISIBLE AS `Visible`,
15781591
EXPRESSION AS `Expression`
1579-
FROM ' . $statistics_table . '
1592+
FROM ' . $this->quote_sqlite_identifier( $statistics_table ) . '
15801593
WHERE table_schema = ?
15811594
AND table_name = ?
15821595
ORDER BY
@@ -1620,7 +1633,8 @@ private function execute_show_table_status_statement( WP_Parser_Node $node ): vo
16201633
);
16211634
$table_info = $this->execute_sqlite_query(
16221635
sprintf(
1623-
"SELECT * FROM $tables_tables WHERE table_schema = ? %s",
1636+
'SELECT * FROM %s WHERE table_schema = ? %s',
1637+
$this->quote_sqlite_identifier( $tables_tables ),
16241638
$condition ?? ''
16251639
),
16261640
array( $database )
@@ -1688,7 +1702,8 @@ private function execute_show_tables_statement( WP_Parser_Node $node ): void {
16881702
);
16891703
$table_info = $this->execute_sqlite_query(
16901704
sprintf(
1691-
"SELECT * FROM $table_tables WHERE table_schema = ? %s",
1705+
'SELECT * FROM %s WHERE table_schema = ? %s',
1706+
$this->quote_sqlite_identifier( $table_tables ),
16921707
$condition ?? ''
16931708
),
16941709
array( $database )
@@ -1745,7 +1760,10 @@ private function execute_show_columns_statement( WP_Parser_Node $node ): void {
17451760
// Check if the table exists.
17461761
$tables_tables = $this->information_schema_builder->get_table_name( $table_is_temporary, 'tables' );
17471762
$table_exists = $this->execute_sqlite_query(
1748-
"SELECT 1 FROM $tables_tables WHERE table_schema = ? AND table_name = ?",
1763+
sprintf(
1764+
'SELECT 1 FROM %s WHERE table_schema = ? AND table_name = ?',
1765+
$this->quote_sqlite_identifier( $tables_tables )
1766+
),
17491767
array( $this->db_name, $table_name )
17501768
)->fetchColumn();
17511769

@@ -1763,10 +1781,11 @@ private function execute_show_columns_statement( WP_Parser_Node $node ): void {
17631781
}
17641782

17651783
// Fetch column information.
1766-
$column_info = $this->execute_sqlite_query(
1784+
$columns_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' );
1785+
$column_info = $this->execute_sqlite_query(
17671786
sprintf(
17681787
'SELECT * FROM %s WHERE table_schema = ? AND table_name = ? %s',
1769-
$this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' ),
1788+
$this->quote_sqlite_identifier( $columns_table ),
17701789
$condition ?? ''
17711790
),
17721791
array( $database, $table_name )
@@ -1808,18 +1827,18 @@ private function execute_describe_statement( WP_Parser_Node $node ): void {
18081827

18091828
$columns_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' );
18101829
$column_info = $this->execute_sqlite_query(
1811-
"
1830+
'
18121831
SELECT
18131832
column_name AS `Field`,
18141833
column_type AS `Type`,
18151834
is_nullable AS `Null`,
18161835
column_key AS `Key`,
18171836
column_default AS `Default`,
18181837
extra AS Extra
1819-
FROM $columns_table
1838+
FROM ' . $this->quote_sqlite_identifier( $columns_table ) . '
18201839
WHERE table_schema = ?
18211840
AND table_name = ?
1822-
",
1841+
',
18231842
array( $this->db_name, $table_name )
18241843
)->fetchAll( PDO::FETCH_OBJ );
18251844

@@ -2015,11 +2034,13 @@ private function execute_administration_statement( WP_Parser_Node $node ): void
20152034
try {
20162035
switch ( $first_token->id ) {
20172036
case WP_MySQL_Lexer::ANALYZE_SYMBOL:
2018-
$stmt = $this->execute_sqlite_query( "ANALYZE $quoted_table_name" );
2037+
$stmt = $this->execute_sqlite_query( sprintf( 'ANALYZE %s', $quoted_table_name ) );
20192038
$errors = $stmt->fetchAll( PDO::FETCH_COLUMN );
20202039
break;
20212040
case WP_MySQL_Lexer::CHECK_SYMBOL:
2022-
$stmt = $this->execute_sqlite_query( "PRAGMA integrity_check($quoted_table_name)" );
2041+
$stmt = $this->execute_sqlite_query(
2042+
sprintf( 'PRAGMA integrity_check(%s)', $quoted_table_name )
2043+
);
20232044
$errors = $stmt->fetchAll( PDO::FETCH_COLUMN );
20242045
if ( 'ok' === $errors[0] ) {
20252046
array_shift( $errors );
@@ -2842,7 +2863,10 @@ private function recreate_table_from_information_schema(
28422863
if ( null === $column_map ) {
28432864
$columns_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' );
28442865
$column_names = $this->execute_sqlite_query(
2845-
"SELECT COLUMN_NAME FROM $columns_table WHERE table_schema = ? AND table_name = ?",
2866+
sprintf(
2867+
'SELECT COLUMN_NAME FROM %s WHERE table_schema = ? AND table_name = ?',
2868+
$this->quote_sqlite_identifier( $columns_table )
2869+
),
28462870
array( $this->db_name, $table_name )
28472871
)->fetchAll( PDO::FETCH_COLUMN );
28482872
$column_map = array_combine( $column_names, $column_names );
@@ -2997,13 +3021,13 @@ private function translate_insert_or_replace_body_in_non_strict_mode(
29973021
$is_temporary = $this->information_schema_builder->temporary_table_exists( $table_name );
29983022
$columns_table = $this->information_schema_builder->get_table_name( $is_temporary, 'columns' );
29993023
$columns = $this->execute_sqlite_query(
3000-
"
3024+
'
30013025
SELECT column_name, is_nullable, column_default, data_type, extra
3002-
FROM $columns_table
3026+
FROM ' . $this->quote_sqlite_identifier( $columns_table ) . '
30033027
WHERE table_schema = ?
30043028
AND table_name = ?
30053029
ORDER BY ordinal_position
3006-
",
3030+
',
30073031
array( $this->db_name, $table_name )
30083032
)->fetchAll( PDO::FETCH_ASSOC );
30093033

@@ -3113,12 +3137,12 @@ private function translate_update_list_in_non_strict_mode( string $table_name, W
31133137
$is_temporary = $this->information_schema_builder->temporary_table_exists( $table_name );
31143138
$columns_table = $this->information_schema_builder->get_table_name( $is_temporary, 'columns' );
31153139
$columns = $this->execute_sqlite_query(
3116-
"
3140+
'
31173141
SELECT column_name, is_nullable, data_type, column_default
3118-
FROM $columns_table
3142+
FROM ' . $this->quote_sqlite_identifier( $columns_table ) . '
31193143
WHERE table_schema = ?
31203144
AND table_name = ?
3121-
",
3145+
',
31223146
array( $this->db_name, $table_name )
31233147
)->fetchAll( PDO::FETCH_ASSOC );
31243148
$column_map = array_combine( array_column( $columns, 'COLUMN_NAME' ), $columns );
@@ -3176,9 +3200,9 @@ private function get_sqlite_create_table_statement(
31763200
// 1. Get table info.
31773201
$tables_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'tables' );
31783202
$table_info = $this->execute_sqlite_query(
3179-
"
3203+
'
31803204
SELECT *
3181-
FROM $tables_table
3205+
FROM ' . $this->quote_sqlite_identifier( $tables_table ) . "
31823206
WHERE table_type = 'BASE TABLE'
31833207
AND table_schema = ?
31843208
AND table_name = ?
@@ -3196,14 +3220,20 @@ private function get_sqlite_create_table_statement(
31963220
// 2. Get column info.
31973221
$columns_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' );
31983222
$column_info = $this->execute_sqlite_query(
3199-
"SELECT * FROM $columns_table WHERE table_schema = ? AND table_name = ?",
3223+
sprintf(
3224+
'SELECT * FROM %s WHERE table_schema = ? AND table_name = ?',
3225+
$this->quote_sqlite_identifier( $columns_table )
3226+
),
32003227
array( $this->db_name, $table_name )
32013228
)->fetchAll( PDO::FETCH_ASSOC );
32023229

32033230
// 3. Get index info, grouped by index name.
32043231
$statistics_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'statistics' );
32053232
$constraint_info = $this->execute_sqlite_query(
3206-
"SELECT * FROM $statistics_table WHERE table_schema = ? AND table_name = ?",
3233+
sprintf(
3234+
'SELECT * FROM %s WHERE table_schema = ? AND table_name = ?',
3235+
$this->quote_sqlite_identifier( $statistics_table )
3236+
),
32073237
array( $this->db_name, $table_name )
32083238
)->fetchAll( PDO::FETCH_ASSOC );
32093239

@@ -3366,9 +3396,9 @@ private function get_mysql_create_table_statement( bool $table_is_temporary, str
33663396
// 1. Get table info.
33673397
$tables_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'tables' );
33683398
$table_info = $this->execute_sqlite_query(
3369-
"
3399+
'
33703400
SELECT *
3371-
FROM $tables_table
3401+
FROM ' . $this->quote_sqlite_identifier( $tables_table ) . "
33723402
WHERE table_type = 'BASE TABLE'
33733403
AND table_schema = ?
33743404
AND table_name = ?
@@ -3383,14 +3413,20 @@ private function get_mysql_create_table_statement( bool $table_is_temporary, str
33833413
// 2. Get column info.
33843414
$columns_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'columns' );
33853415
$column_info = $this->execute_sqlite_query(
3386-
"SELECT * FROM $columns_table WHERE table_schema = ? AND table_name = ?",
3416+
sprintf(
3417+
'SELECT * FROM %s WHERE table_schema = ? AND table_name = ?',
3418+
$this->quote_sqlite_identifier( $columns_table )
3419+
),
33873420
array( $this->db_name, $table_name )
33883421
)->fetchAll( PDO::FETCH_ASSOC );
33893422

33903423
// 3. Get index info, grouped by index name.
33913424
$statistics_table = $this->information_schema_builder->get_table_name( $table_is_temporary, 'statistics' );
33923425
$constraint_info = $this->execute_sqlite_query(
3393-
"SELECT * FROM $statistics_table WHERE table_schema = ? AND table_name = ?",
3426+
sprintf(
3427+
'SELECT * FROM %s WHERE table_schema = ? AND table_name = ?',
3428+
$this->quote_sqlite_identifier( $statistics_table )
3429+
),
33943430
array( $this->db_name, $table_name )
33953431
)->fetchAll( PDO::FETCH_ASSOC );
33963432

@@ -3518,14 +3554,20 @@ private function get_column_on_update_trigger_query( string $table, string $colu
35183554
// but currently that can't happen as we're not creating such tables.
35193555
// See: https://www.sqlite.org/rowidtable.html
35203556
$trigger_name = self::RESERVED_PREFIX . "{$table}_{$column}_on_update";
3521-
return "
3522-
CREATE TRIGGER \"$trigger_name\"
3523-
AFTER UPDATE ON \"$table\"
3524-
FOR EACH ROW
3525-
BEGIN
3526-
UPDATE \"$table\" SET \"$column\" = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;
3527-
END
3528-
";
3557+
return sprintf(
3558+
'
3559+
CREATE TRIGGER %s
3560+
AFTER UPDATE ON %s
3561+
FOR EACH ROW
3562+
BEGIN
3563+
UPDATE %s SET %s = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;
3564+
END
3565+
',
3566+
$this->quote_sqlite_identifier( $trigger_name ),
3567+
$this->quote_sqlite_identifier( $table ),
3568+
$this->quote_sqlite_identifier( $table ),
3569+
$this->quote_sqlite_identifier( $column )
3570+
);
35293571
}
35303572

35313573
/**

wp-includes/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php

+16-4
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ private function get_sqlite_table_names(): array {
122122
private function get_information_schema_table_names(): array {
123123
$tables_table = $this->schema_builder->get_table_name( false, 'tables' );
124124
return $this->driver->execute_sqlite_query(
125-
"SELECT table_name FROM $tables_table ORDER BY table_name"
125+
sprintf(
126+
'SELECT table_name FROM %s ORDER BY table_name',
127+
$this->quote_sqlite_identifier( $tables_table )
128+
)
126129
)->fetchAll( PDO::FETCH_COLUMN );
127130
}
128131

@@ -207,7 +210,10 @@ private function get_wp_create_table_statements(): array {
207210
private function generate_create_table_statement( string $table_name ): string {
208211
// Columns.
209212
$columns = $this->driver->execute_sqlite_query(
210-
sprintf( 'PRAGMA table_xinfo("%s")', $table_name )
213+
sprintf(
214+
'PRAGMA table_xinfo(%s)',
215+
$this->quote_sqlite_identifier( $table_name )
216+
)
211217
)->fetchAll( PDO::FETCH_ASSOC );
212218

213219
$definitions = array();
@@ -245,7 +251,10 @@ private function generate_create_table_statement( string $table_name ): string {
245251

246252
// Indexes and keys.
247253
$keys = $this->driver->execute_sqlite_query(
248-
'SELECT * FROM pragma_index_list("' . $table_name . '")'
254+
sprintf(
255+
'PRAGMA index_list(%s)',
256+
$this->quote_sqlite_identifier( $table_name )
257+
)
249258
)->fetchAll( PDO::FETCH_ASSOC );
250259

251260
foreach ( $keys as $key ) {
@@ -375,7 +384,10 @@ private function generate_key_definition( string $table_name, array $key_info, a
375384

376385
// Key columns.
377386
$key_columns = $this->driver->execute_sqlite_query(
378-
'SELECT * FROM pragma_index_info("' . $key_info['name'] . '")'
387+
sprintf(
388+
'PRAGMA index_info(%s)',
389+
$this->quote_sqlite_identifier( $key_info['name'] )
390+
)
379391
)->fetchAll( PDO::FETCH_ASSOC );
380392
$cols = array();
381393
foreach ( $key_columns as $column ) {

0 commit comments

Comments
 (0)