@@ -347,6 +347,16 @@ class WP_SQLite_Information_Schema_Builder {
347347 */
348348 private $ temporary_table_prefix ;
349349
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+
350360 /**
351361 * Query callback.
352362 *
@@ -420,6 +430,7 @@ public function ensure_temporary_information_schema_tables(): void {
420430 $ query = str_replace ( 'CREATE TABLE ' , 'CREATE TEMPORARY TABLE ' , $ query );
421431 $ this ->query ( str_replace ( '<prefix> ' , $ this ->temporary_table_prefix , $ query ) );
422432 }
433+ $ this ->temporary_information_schema_exists = true ;
423434 }
424435
425436 /**
@@ -440,23 +451,40 @@ public function record_create_table( WP_Parser_Node $node ): void {
440451 */
441452 $ subnode = $ node ->get_first_child_node ();
442453 $ 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 ) {
444455 $ this ->ensure_temporary_information_schema_tables ();
445456 }
446457
447458 // 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 ,
458467 );
459468
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+
460488 // 2. Columns.
461489 $ column_position = 1 ;
462490 foreach ( $ node ->get_descendant_nodes ( 'columnDefinition ' ) as $ column_node ) {
0 commit comments