Skip to content

Commit 581d361

Browse files
authored
Fixes for phpMyAdmin, Adminer, etc. (#269)
This is a set of fixes of issues discovered when testing phpMyAdmin and Adminer: - Fix `USE` statement when switching back to the main database (`USE wp`). - Add support for `@@version` and `@@version_comment` system variables. - Add support for `INFORMATION_SCHEMA.CHARACTER_SETS`. - Add support for `INFORMATION_SCHEMA.COLLATIONS`. - Add support for `SHOW COLLATIONS` statement. - Improve `CAST` expression handling. There are more fixes to come, but maybe we can add those in subsequent PRs so that the scope here doesn't explode.
1 parent cbcdaa5 commit 581d361

File tree

4 files changed

+335
-16
lines changed

4 files changed

+335
-16
lines changed

tests/WP_SQLite_Driver_Metadata_Tests.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,105 @@ public function testInformationSchemaQueryHidesSqliteSystemTables() {
9494
$this->assertEquals( 0, count( $result ) );
9595
}
9696

97+
public function testInfromationSchemaCharacterSets(): void {
98+
$result = $this->assertQuery( 'SELECT * FROM INFORMATION_SCHEMA.CHARACTER_SETS ORDER BY CHARACTER_SET_NAME' );
99+
$this->assertEquals(
100+
array(
101+
(object) array(
102+
'CHARACTER_SET_NAME' => 'binary',
103+
'DEFAULT_COLLATE_NAME' => 'binary',
104+
'DESCRIPTION' => 'Binary pseudo charset',
105+
'MAXLEN' => '1',
106+
),
107+
(object) array(
108+
'CHARACTER_SET_NAME' => 'utf8',
109+
'DEFAULT_COLLATE_NAME' => 'utf8_general_ci',
110+
'DESCRIPTION' => 'UTF-8 Unicode',
111+
'MAXLEN' => '3',
112+
),
113+
(object) array(
114+
'CHARACTER_SET_NAME' => 'utf8mb4',
115+
'DEFAULT_COLLATE_NAME' => 'utf8mb4_0900_ai_ci',
116+
'DESCRIPTION' => 'UTF-8 Unicode',
117+
'MAXLEN' => '4',
118+
),
119+
),
120+
$result
121+
);
122+
}
123+
124+
public function testInfromationSchemaCollations(): void {
125+
$result = $this->assertQuery( 'SELECT * FROM INFORMATION_SCHEMA.COLLATIONS ORDER BY COLLATION_NAME' );
126+
$this->assertEquals(
127+
array(
128+
(object) array(
129+
'COLLATION_NAME' => 'binary',
130+
'CHARACTER_SET_NAME' => 'binary',
131+
'ID' => '63',
132+
'IS_DEFAULT' => 'Yes',
133+
'IS_COMPILED' => 'Yes',
134+
'SORTLEN' => '1',
135+
'PAD_ATTRIBUTE' => 'NO PAD',
136+
),
137+
(object) array(
138+
'COLLATION_NAME' => 'utf8_bin',
139+
'CHARACTER_SET_NAME' => 'utf8',
140+
'ID' => '83',
141+
'IS_DEFAULT' => '',
142+
'IS_COMPILED' => 'Yes',
143+
'SORTLEN' => '1',
144+
'PAD_ATTRIBUTE' => 'PAD SPACE',
145+
),
146+
(object) array(
147+
'COLLATION_NAME' => 'utf8_general_ci',
148+
'CHARACTER_SET_NAME' => 'utf8',
149+
'ID' => '33',
150+
'IS_DEFAULT' => 'Yes',
151+
'IS_COMPILED' => 'Yes',
152+
'SORTLEN' => '1',
153+
'PAD_ATTRIBUTE' => 'PAD SPACE',
154+
),
155+
(object) array(
156+
'COLLATION_NAME' => 'utf8_unicode_ci',
157+
'CHARACTER_SET_NAME' => 'utf8',
158+
'ID' => '192',
159+
'IS_DEFAULT' => '',
160+
'IS_COMPILED' => 'Yes',
161+
'SORTLEN' => '8',
162+
'PAD_ATTRIBUTE' => 'PAD SPACE',
163+
),
164+
(object) array(
165+
'COLLATION_NAME' => 'utf8mb4_0900_ai_ci',
166+
'CHARACTER_SET_NAME' => 'utf8mb4',
167+
'ID' => '255',
168+
'IS_DEFAULT' => 'Yes',
169+
'IS_COMPILED' => 'Yes',
170+
'SORTLEN' => '0',
171+
'PAD_ATTRIBUTE' => 'NO PAD',
172+
),
173+
(object) array(
174+
'COLLATION_NAME' => 'utf8mb4_bin',
175+
'CHARACTER_SET_NAME' => 'utf8mb4',
176+
'ID' => '46',
177+
'IS_DEFAULT' => '',
178+
'IS_COMPILED' => 'Yes',
179+
'SORTLEN' => '1',
180+
'PAD_ATTRIBUTE' => 'PAD SPACE',
181+
),
182+
(object) array(
183+
'COLLATION_NAME' => 'utf8mb4_unicode_ci',
184+
'CHARACTER_SET_NAME' => 'utf8mb4',
185+
'ID' => '224',
186+
'IS_DEFAULT' => '',
187+
'IS_COMPILED' => 'Yes',
188+
'SORTLEN' => '8',
189+
'PAD_ATTRIBUTE' => 'PAD SPACE',
190+
),
191+
),
192+
$result
193+
);
194+
}
195+
97196
public function testUseStatement() {
98197
$this->assertQuery( 'CREATE TABLE tables (ENGINE TEXT)' );
99198
$this->assertQuery( "INSERT INTO tables (ENGINE) VALUES ('test')" );
@@ -368,6 +467,19 @@ public function testRepairTable() {
368467
);
369468
}
370469

470+
public function testShowCollation(): void {
471+
$this->assertQuery( 'SHOW COLLATION' );
472+
$actual = $this->engine->get_query_results();
473+
$this->assertCount( 7, $actual );
474+
$this->assertEquals( 'binary', $actual[0]->Collation );
475+
$this->assertEquals( 'utf8_bin', $actual[1]->Collation );
476+
$this->assertEquals( 'utf8_general_ci', $actual[2]->Collation );
477+
$this->assertEquals( 'utf8_unicode_ci', $actual[3]->Collation );
478+
$this->assertEquals( 'utf8mb4_bin', $actual[4]->Collation );
479+
$this->assertEquals( 'utf8mb4_unicode_ci', $actual[5]->Collation );
480+
$this->assertEquals( 'utf8mb4_0900_ai_ci', $actual[6]->Collation );
481+
}
482+
371483
public function testShowDatabases(): void {
372484
// Simple.
373485
$this->assertQuery( 'SHOW DATABASES' );

tests/WP_SQLite_Driver_Tests.php

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6033,6 +6033,14 @@ public function testSetStatement(): void {
60336033
$this->assertQuery( 'SET CHARACTER SET utf8mb4' );
60346034
}
60356035

6036+
public function testBuiltInSystemVariables(): void {
6037+
$result = $this->assertQuery( 'SELECT @@version' );
6038+
$this->assertSame( '8.0.38', $result[0]->{'@@version'} );
6039+
6040+
$result = $this->assertQuery( 'SELECT @@version_comment' );
6041+
$this->assertSame( 'MySQL Community Server - GPL', $result[0]->{'@@version_comment'} );
6042+
}
6043+
60366044
public function testSessionSystemVariables(): void {
60376045
$this->assertQuery( "SET character_set_client = 'latin1'" );
60386046
$result = $this->assertQuery( 'SELECT @@character_set_client' );
@@ -8395,22 +8403,22 @@ public function testColumnInfoForExpressions(): void {
83958403
),
83968404
array(
83978405
// "CAST('2024-01-01' AS DATE)" seems to behave differently in SQLite.
8398-
'native_type' => 'LONGLONG', // "DATE" in MySQL.
8399-
'pdo_type' => PDO::PARAM_INT, // PARAM_STR in MySQL.
8406+
'native_type' => 'VAR_STRING', // "DATE" in MySQL.
8407+
'pdo_type' => PDO::PARAM_STR,
84008408
'flags' => array( 'not_null' ), // Empty in MySQL.
84018409
'table' => '',
84028410
'name' => 'col_expr_11',
8403-
'len' => 21, // 10 in MySQL.
8404-
'precision' => 0,
8411+
'len' => 65535, // 10 in MySQL.
8412+
'precision' => 31, // 0 in MySQL.
84058413
'sqlite:decl_type' => '',
84068414

84078415
// Additional MySQLi metadata.
84088416
'mysqli:orgname' => 'col_expr_11',
84098417
'mysqli:orgtable' => '',
84108418
'mysqli:db' => 'wp',
8411-
'mysqli:charsetnr' => 63,
8412-
'mysqli:flags' => 0, // 128 in MySQL.
8413-
'mysqli:type' => 8, // 10 in MySQL.
8419+
'mysqli:charsetnr' => 255, // 63 in MySQL.
8420+
'mysqli:flags' => 0, // 128 in MySQL.
8421+
'mysqli:type' => 253, // 10 in MySQL.
84148422
),
84158423
array(
84168424
'native_type' => 'VAR_STRING',
@@ -9366,5 +9374,69 @@ public function testDynamicDatabaseNameWithUseStatement(): void {
93669374
$result = $this->assertQuery( 'SELECT * FROM information_schema.tables' );
93679375
$this->assertCount( 1, $result );
93689376
$this->assertEquals( 'tables', $result[0]->TABLE_NAME );
9377+
9378+
// Switch back to the "wp" database.
9379+
$this->assertQuery( 'USE wp' );
9380+
9381+
// Now, unqualified "tables" refers to the "wp.tables".
9382+
$result = $this->assertQuery( 'SELECT * FROM tables' );
9383+
$this->assertCount( 2, $result );
9384+
$this->assertEquals( array( (object) array( 'id' => '1' ), (object) array( 'id' => '2' ) ), $result );
9385+
9386+
// Qualified references should still work.
9387+
$result = $this->assertQuery( 'SELECT * FROM wp.tables' );
9388+
$this->assertCount( 2, $result );
9389+
$this->assertEquals( array( (object) array( 'id' => '1' ), (object) array( 'id' => '2' ) ), $result );
9390+
9391+
$result = $this->assertQuery( 'SELECT * FROM information_schema.tables' );
9392+
$this->assertCount( 1, $result );
9393+
$this->assertEquals( 'tables', $result[0]->TABLE_NAME );
9394+
}
9395+
9396+
public function testCastExpression(): void {
9397+
$result = $this->assertQuery(
9398+
"SELECT
9399+
CAST('abc' AS BINARY) AS expr_1,
9400+
CAST('abc' AS BINARY(2)) AS expr_2,
9401+
CAST('abc' AS CHAR) AS expr_3,
9402+
CAST('abc' AS CHAR(2) CHARACTER SET utf8 BINARY)AS expr_4,
9403+
CAST('abc' AS NCHAR)AS expr_5,
9404+
CAST('abc' AS NATIONAL CHAR (2)) AS expr_6,
9405+
CAST('-10' AS SIGNED) AS expr_7,
9406+
CAST('-10' AS UNSIGNED INT) AS expr_8,
9407+
CAST('2025-10-05 14:05:28' AS DATE) AS expr_9,
9408+
CAST('2025-10-05 14:05:28' AS TIME) AS expr_10,
9409+
CAST('2025-10-05 14:05:28' AS DATETIME) AS expr_11,
9410+
CAST('123.456' AS DECIMAL(10,1)) AS expr_12,
9411+
CAST('123.456' AS FLOAT) AS expr_13,
9412+
CAST('123.456' AS REAL) AS expr_14,
9413+
CAST('123.456' AS DOUBLE) AS expr_15,
9414+
CAST('{\"name\":\"value\"}' AS JSON) AS expr_16
9415+
"
9416+
);
9417+
9418+
$this->assertEquals(
9419+
array(
9420+
(object) array(
9421+
'expr_1' => 'abc',
9422+
'expr_2' => 'abc', // 'ab' In MySQL
9423+
'expr_3' => 'abc',
9424+
'expr_4' => 'abc', // 'ab' In MySQL
9425+
'expr_5' => 'abc',
9426+
'expr_6' => 'abc', // 'ab' In MySQL
9427+
'expr_7' => '-10',
9428+
'expr_8' => '-10', // 18446744073709551606 in MySQL
9429+
'expr_9' => '2025-10-05 14:05:28', // 2025-10-05 in MySQL
9430+
'expr_10' => '2025-10-05 14:05:28', // 14:05:28 in MySQL
9431+
'expr_11' => '2025-10-05 14:05:28',
9432+
'expr_12' => '123.456', // 123.5 in MySQL
9433+
'expr_13' => '123.456',
9434+
'expr_14' => '123.456',
9435+
'expr_15' => '123.456',
9436+
'expr_16' => '{"name":"value"}',
9437+
),
9438+
),
9439+
$result
9440+
);
93699441
}
93709442
}

0 commit comments

Comments
 (0)