Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit b865620

Browse files
committed
Create temporary information schema tables at most once per session
1 parent 40cef5b commit b865620

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

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

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)