@@ -347,6 +347,16 @@ class WP_SQLite_Information_Schema_Builder {
347
347
*/
348
348
private $ temporary_table_prefix ;
349
349
350
+ /**
351
+ * Whether the information schema for temporary tables was already created.
352
+ *
353
+ * This is used to avoid trying to create a temporary information schema
354
+ * for each CREATE TEMPORARY TABLE statement during a single session.
355
+ *
356
+ * @var bool
357
+ */
358
+ private $ temporary_information_schema_exists = false ;
359
+
350
360
/**
351
361
* Query callback.
352
362
*
@@ -420,6 +430,7 @@ public function ensure_temporary_information_schema_tables(): void {
420
430
$ query = str_replace ( 'CREATE TABLE ' , 'CREATE TEMPORARY TABLE ' , $ query );
421
431
$ this ->query ( str_replace ( '<prefix> ' , $ this ->temporary_table_prefix , $ query ) );
422
432
}
433
+ $ this ->temporary_information_schema_exists = true ;
423
434
}
424
435
425
436
/**
@@ -440,23 +451,40 @@ public function record_create_table( WP_Parser_Node $node ): void {
440
451
*/
441
452
$ subnode = $ node ->get_first_child_node ();
442
453
$ table_is_temporary = $ subnode ->has_child_token ( WP_MySQL_Lexer::TEMPORARY_SYMBOL );
443
- if ( true === $ table_is_temporary ) {
454
+ if ( $ table_is_temporary && ! $ this -> temporary_information_schema_exists ) {
444
455
$ this ->ensure_temporary_information_schema_tables ();
445
456
}
446
457
447
458
// 1. Table.
448
- $ this ->insert_values (
449
- $ this ->get_table_name ( $ table_is_temporary , 'tables ' ),
450
- array (
451
- 'table_schema ' => $ this ->db_name ,
452
- 'table_name ' => $ table_name ,
453
- 'table_type ' => 'BASE TABLE ' ,
454
- 'engine ' => $ table_engine ,
455
- 'row_format ' => $ table_row_format ,
456
- 'table_collation ' => $ table_collation ,
457
- )
459
+ $ tables_table_name = $ this ->get_table_name ( $ table_is_temporary , 'tables ' );
460
+ $ table_data = array (
461
+ 'table_schema ' => $ this ->db_name ,
462
+ 'table_name ' => $ table_name ,
463
+ 'table_type ' => 'BASE TABLE ' ,
464
+ 'engine ' => $ table_engine ,
465
+ 'row_format ' => $ table_row_format ,
466
+ 'table_collation ' => $ table_collation ,
458
467
);
459
468
469
+ try {
470
+ $ this ->insert_values ( $ tables_table_name , $ table_data );
471
+ } catch ( PDOException $ e ) {
472
+ /*
473
+ * Even though we keep track of whether the temporary information
474
+ * schema tables already exist, there is a special case in which
475
+ * the tracked information may be incorrect.
476
+ *
477
+ * This can happen when the query is in a transaction that is later
478
+ * rolled back. In that case, let's ensure the schema, and try again.
479
+ */
480
+ if ( $ table_is_temporary && str_contains ( $ e ->getMessage (), 'no such table ' ) ) {
481
+ $ this ->ensure_temporary_information_schema_tables ();
482
+ $ this ->insert_values ( $ tables_table_name , $ table_data );
483
+ } else {
484
+ throw $ e ;
485
+ }
486
+ }
487
+
460
488
// 2. Columns.
461
489
$ column_position = 1 ;
462
490
foreach ( $ node ->get_descendant_nodes ( 'columnDefinition ' ) as $ column_node ) {
0 commit comments