Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5466,8 +5466,8 @@ private function translate_table_ref( WP_Parser_Node $node ): string {
}
}

$table_is_temporary = $this->information_schema_builder->temporary_table_exists( $table_name );
$sqlite_table_name = $this->information_schema_builder->get_table_name( $table_is_temporary, $table_name );
// Temporary tables are not listed in the information schema.
$sqlite_table_name = $this->information_schema_builder->get_table_name( false, $table_name );

// We need to fetch the SQLite column information, because the information
// schema tables don't contain records for the information schema itself.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,12 +381,16 @@ public function temporary_table_exists( string $table_name ): bool {
/*
* We could search in the "{$this->temporary_table_prefix}tables" table,
* but it may not exist yet, so using "sqlite_temp_master" is simpler.
*
* The name is matched case-insensitively, as it is in the information
* schema tables. The fetched value is not compared to a string, because
* PDO SQLite returns native types when fetches are not stringified.
*/
$stmt = $this->connection->query(
"SELECT 1 FROM sqlite_temp_master WHERE type = 'table' AND name = ?",
"SELECT 1 FROM sqlite_temp_master WHERE type = 'table' AND name = ? COLLATE NOCASE",
array( $table_name )
);
return $stmt->fetchColumn() === '1';
return false !== $stmt->fetchColumn();
}

/**
Expand Down
59 changes: 58 additions & 1 deletion packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -5842,7 +5842,31 @@ public function getInformationSchemaIsReadonlyWithUseTestData(): array {
);
}

public function testTemporaryTableHasPriorityOverStandardTable(): void {
public function testTemporaryTableIsFoundByDifferentlyCasedName(): void {
// Create a standard and a temporary table with the same name.
$this->assertQuery( 'CREATE TABLE t (a INT)' );
$this->assertQuery( 'CREATE TEMPORARY TABLE t (b INT)' );

// ALTER TABLE will use the temporary table.
$this->assertQuery( 'ALTER TABLE T ADD COLUMN c INT' );
$result = $this->assertQuery( 'SHOW COLUMNS FROM T' );
$this->assertCount( 2, $result );
$this->assertEquals( 'b', $result[0]->Field );
$this->assertEquals( 'c', $result[1]->Field );

// DROP TABLE will remove the temporary table and keep the standard table.
$this->assertQuery( 'DROP TABLE T' );
$result = $this->assertQuery( 'SHOW COLUMNS FROM T' );
$this->assertCount( 1, $result );
$this->assertEquals( 'a', $result[0]->Field );
}

/**
* @dataProvider stringifyFetchesProvider
*/
public function testTemporaryTableHasPriorityOverStandardTable( bool $stringify_fetches ): void {
$this->engine->setAttribute( PDO::ATTR_STRINGIFY_FETCHES, $stringify_fetches );

// Create a standard and a temporary table with the same name.
$this->assertQuery( 'CREATE TABLE t (a INT, INDEX ia(a))' );
$this->assertQuery( 'CREATE TEMPORARY TABLE t (b INT, INDEX ib(b))' );
Expand Down Expand Up @@ -5883,6 +5907,7 @@ public function testTemporaryTableHasPriorityOverStandardTable(): void {
// First DROP TABLE removes the temporary table.
$this->assertQuery( 'DROP TABLE t' );
$result = $this->assertQuery( 'SHOW COLUMNS FROM t' );
$this->assertCount( 1, $result );
$this->assertEquals( 'a', $result[0]->Field );

// Second DROP TABLE removes the standard table.
Expand All @@ -5892,6 +5917,38 @@ public function testTemporaryTableHasPriorityOverStandardTable(): void {
$result = $this->assertQuery( 'SHOW COLUMNS FROM t' );
}

public function stringifyFetchesProvider(): array {
return array(
'stringification disabled' => array( false ),
'stringification enabled' => array( true ),
);
}

public function testTemporaryTableNamedLikeInformationSchemaTable(): void {
// Create a standard table and temporary tables named like information schema tables.
$this->assertQuery( 'CREATE TABLE t (a INT, INDEX ia(a))' );
$this->assertQuery( 'CREATE TEMPORARY TABLE tables (b INT)' );
$this->assertQuery( 'CREATE TEMPORARY TABLE COLUMNS (b INT)' );
$this->assertQuery( 'CREATE TEMPORARY TABLE Statistics (b INT, INDEX ib(b))' );

// The information schema shows the standard table only.
$table_names = "('t', 'tables', 'columns', 'statistics')";

$result = $this->assertQuery( "SELECT table_name FROM information_schema.tables WHERE table_name IN $table_names" );
$this->assertCount( 1, $result );
$this->assertEquals( 't', $result[0]->TABLE_NAME );

$result = $this->assertQuery( "SELECT table_name, column_name FROM information_schema.columns WHERE table_name IN $table_names" );
$this->assertCount( 1, $result );
$this->assertEquals( 't', $result[0]->TABLE_NAME );
$this->assertEquals( 'a', $result[0]->COLUMN_NAME );

$result = $this->assertQuery( "SELECT table_name, index_name FROM information_schema.statistics WHERE table_name IN $table_names" );
$this->assertCount( 1, $result );
$this->assertEquals( 't', $result[0]->TABLE_NAME );
$this->assertEquals( 'ia', $result[0]->INDEX_NAME );
}

public function testStrictSqlModeNullWithoutDefault(): void {
$this->assertQuery( "SET SESSION sql_mode = 'STRICT_ALL_TABLES'" );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,7 @@ private function assertQuery( $expected, string $query ): void {
array_filter(
$executed_queries,
function ( $query ) {
return "SELECT 1 FROM sqlite_temp_master WHERE type = 'table' AND name = ?" !== $query;
return "SELECT 1 FROM sqlite_temp_master WHERE type = 'table' AND name = ? COLLATE NOCASE" !== $query;
}
)
);
Expand Down
Loading