@@ -4202,7 +4202,7 @@ public function getReservedPrefixTestData(): array {
42024202 * @dataProvider getInformationSchemaIsReadonlyTestData
42034203 */
42044204 public function testInformationSchemaIsReadonly ( string $ query ): void {
4205- $ this ->assertQuery ( 'CREATE TABLE t1 (id INT) ' );
4205+ $ this ->assertQuery ( 'CREATE TABLE tables (id INT) ' );
42064206 $ this ->expectException ( WP_SQLite_Driver_Exception::class );
42074207 $ this ->expectExceptionMessage ( "Access denied for user 'sqlite'@'%' to database 'information_schema' " );
42084208 $ this ->assertQuery ( $ query );
@@ -4211,20 +4211,30 @@ public function testInformationSchemaIsReadonly( string $query ): void {
42114211 public function getInformationSchemaIsReadonlyTestData (): array {
42124212 return array (
42134213 array ( 'INSERT INTO information_schema.tables (table_name) VALUES ("t") ' ),
4214+ array ( 'REPLACE INTO information_schema.tables (table_name) VALUES ("t") ' ),
42144215 array ( 'UPDATE information_schema.tables SET table_name = "new_t" WHERE table_name = "t" ' ),
4216+ array ( 'UPDATE information_schema.tables, information_schema.columns SET table_name = "new_t" WHERE table_name = "t" ' ),
42154217 array ( 'DELETE FROM information_schema.tables WHERE table_name = "t" ' ),
4218+ array ( 'DELETE it FROM t, information_schema.tables it WHERE table_name = "t" ' ),
4219+ array ( 'TRUNCATE information_schema.tables ' ),
42164220 array ( 'CREATE TABLE information_schema.new_table (id INT) ' ),
42174221 array ( 'ALTER TABLE information_schema.tables ADD COLUMN new_column INT ' ),
42184222 array ( 'DROP TABLE information_schema.tables ' ),
4219- array ( 'TRUNCATE information_schema.tables ' ),
4223+ array ( 'LOCK TABLES information_schema.tables READ ' ),
4224+ array ( 'CREATE INDEX idx_name ON information_schema.tables (name) ' ),
4225+ array ( 'DROP INDEX `PRIMARY` ON information_schema.tables ' ),
4226+ array ( 'ANALYZE TABLE information_schema.tables ' ),
4227+ array ( 'CHECK TABLE information_schema.tables ' ),
4228+ array ( 'OPTIMIZE TABLE information_schema.tables ' ),
4229+ array ( 'REPAIR TABLE information_schema.tables ' ),
42204230 );
42214231 }
42224232
42234233 /**
42244234 * @dataProvider getInformationSchemaIsReadonlyWithUseTestData
42254235 */
42264236 public function testInformationSchemaIsReadonlyWithUse ( string $ query ): void {
4227- $ this ->assertQuery ( 'CREATE TABLE t1 (id INT) ' );
4237+ $ this ->assertQuery ( 'CREATE TABLE tables (id INT) ' );
42284238 $ this ->expectException ( WP_SQLite_Driver_Exception::class );
42294239 $ this ->expectExceptionMessage ( "Access denied for user 'sqlite'@'%' to database 'information_schema' " );
42304240 $ this ->assertQuery ( 'USE information_schema ' );
@@ -4234,12 +4244,22 @@ public function testInformationSchemaIsReadonlyWithUse( string $query ): void {
42344244 public function getInformationSchemaIsReadonlyWithUseTestData (): array {
42354245 return array (
42364246 array ( 'INSERT INTO tables (table_name) VALUES ("t") ' ),
4247+ array ( 'REPLACE INTO tables (table_name) VALUES ("t") ' ),
42374248 array ( 'UPDATE tables SET table_name = "new_t" WHERE table_name = "t" ' ),
4249+ array ( 'UPDATE tables, columns SET table_name = "new_t" WHERE table_name = "t" ' ),
42384250 array ( 'DELETE FROM tables WHERE table_name = "t" ' ),
4251+ array ( 'DELETE it FROM t, tables it WHERE table_name = "t" ' ),
4252+ array ( 'TRUNCATE tables ' ),
42394253 array ( 'CREATE TABLE new_table (id INT) ' ),
42404254 array ( 'ALTER TABLE tables ADD COLUMN new_column INT ' ),
42414255 array ( 'DROP TABLE tables ' ),
4242- array ( 'TRUNCATE tables ' ),
4256+ array ( 'LOCK TABLES tables READ ' ),
4257+ array ( 'CREATE INDEX idx_name ON tables (name) ' ),
4258+ array ( 'DROP INDEX `PRIMARY` ON tables ' ),
4259+ array ( 'ANALYZE TABLE tables ' ),
4260+ array ( 'CHECK TABLE tables ' ),
4261+ array ( 'OPTIMIZE TABLE tables ' ),
4262+ array ( 'REPAIR TABLE tables ' ),
42434263 );
42444264 }
42454265
@@ -9537,4 +9557,256 @@ public function testInsertIntoSetSyntaxInNonStrictMode(): void {
95379557 $ result
95389558 );
95399559 }
9560+
9561+ public function testFullyQualifiedTableName (): void {
9562+ // Ensure "information_schema.tables" is empty.
9563+ $ this ->assertQuery ( 'DROP TABLE _options, _dates ' );
9564+ $ result = $ this ->assertQuery ( 'SELECT * FROM information_schema.tables ' );
9565+ $ this ->assertCount ( 0 , $ result );
9566+
9567+ // Switch to the "information_schema" database.
9568+ $ this ->assertQuery ( 'USE information_schema ' );
9569+
9570+ // CREATE TABLE
9571+ $ this ->assertQuery ( 'CREATE TABLE wp.t (id INT PRIMARY KEY) ' );
9572+ $ result = $ this ->assertQuery ( 'SHOW TABLES FROM wp ' );
9573+ $ this ->assertCount ( 1 , $ result );
9574+
9575+ // INSERT
9576+ $ this ->assertQuery ( 'INSERT INTO wp.t (id) VALUES (1) ' );
9577+ $ result = $ this ->assertQuery ( 'SELECT * FROM wp.t ' );
9578+ $ this ->assertEquals ( array ( (object ) array ( 'id ' => '1 ' ) ), $ result );
9579+
9580+ // SELECT
9581+ $ result = $ this ->assertQuery ( 'SELECT * FROM wp.t ' );
9582+ $ this ->assertEquals ( array ( (object ) array ( 'id ' => '1 ' ) ), $ result );
9583+
9584+ // UPDATE
9585+ $ this ->assertQuery ( 'UPDATE wp.t SET id = 2 ' );
9586+ $ result = $ this ->assertQuery ( 'SELECT * FROM wp.t ' );
9587+ $ this ->assertEquals ( array ( (object ) array ( 'id ' => '2 ' ) ), $ result );
9588+
9589+ // DELETE
9590+ $ this ->assertQuery ( 'DELETE FROM wp.t ' );
9591+ $ result = $ this ->assertQuery ( 'SELECT * FROM wp.t ' );
9592+ $ this ->assertCount ( 0 , $ result );
9593+
9594+ // TRUNCATE TABLE
9595+ $ this ->assertQuery ( 'INSERT INTO wp.t (id) VALUES (1) ' );
9596+ $ this ->assertQuery ( 'TRUNCATE TABLE wp.t ' );
9597+ $ result = $ this ->assertQuery ( 'SELECT * FROM wp.t ' );
9598+ $ this ->assertCount ( 0 , $ result );
9599+
9600+ // SHOW CREATE TABLE
9601+ $ result = $ this ->assertQuery ( 'SHOW CREATE TABLE wp.t ' );
9602+ $ this ->assertEquals (
9603+ array (
9604+ (object ) array (
9605+ 'Create Table ' => implode (
9606+ "\n" ,
9607+ array (
9608+ 'CREATE TABLE `t` ( ' ,
9609+ ' `id` int NOT NULL, ' ,
9610+ ' PRIMARY KEY (`id`) ' ,
9611+ ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ' ,
9612+ )
9613+ ),
9614+ ),
9615+ ),
9616+ $ result
9617+ );
9618+
9619+ // SHOW COLUMNS
9620+ $ result = $ this ->assertQuery ( 'SHOW COLUMNS FROM wp.t ' );
9621+ $ this ->assertEquals (
9622+ array (
9623+ (object ) array (
9624+ 'Field ' => 'id ' ,
9625+ 'Type ' => 'int ' ,
9626+ 'Null ' => 'NO ' ,
9627+ 'Key ' => 'PRI ' ,
9628+ 'Default ' => null ,
9629+ 'Extra ' => '' ,
9630+ ),
9631+ ),
9632+ $ result
9633+ );
9634+
9635+ // SHOW COLUMNS with both qualified table name and "FROM database" clause.
9636+ // In case both are present, the "FROM database" clause takes precedence.
9637+ $ result = $ this ->assertQuery ( 'SHOW COLUMNS FROM information_schema.t FROM wp ' );
9638+ $ this ->assertEquals (
9639+ array (
9640+ (object ) array (
9641+ 'Field ' => 'id ' ,
9642+ 'Type ' => 'int ' ,
9643+ 'Null ' => 'NO ' ,
9644+ 'Key ' => 'PRI ' ,
9645+ 'Default ' => null ,
9646+ 'Extra ' => '' ,
9647+ ),
9648+ ),
9649+ $ result
9650+ );
9651+
9652+ // SHOW INDEXES
9653+ $ result = $ this ->assertQuery ( 'SHOW INDEXES FROM wp.t ' );
9654+ $ this ->assertCount ( 1 , $ result );
9655+ $ this ->assertEquals ( 'PRIMARY ' , $ result [0 ]->Key_name );
9656+
9657+ // SHOW INDEXES with both qualified table name and "FROM database" clause.
9658+ // In case both are present, the "FROM database" clause takes precedence.
9659+ $ result = $ this ->assertQuery ( 'SHOW INDEXES FROM information_schema.t FROM wp ' );
9660+ $ this ->assertCount ( 1 , $ result );
9661+ $ this ->assertEquals ( 'PRIMARY ' , $ result [0 ]->Key_name );
9662+
9663+ // DESCRIBE
9664+ $ result = $ this ->assertQuery ( 'DESCRIBE wp.t ' );
9665+ $ this ->assertCount ( 1 , $ result );
9666+ $ this ->assertEquals ( 'id ' , $ result [0 ]->Field );
9667+ $ this ->assertEquals ( 'int ' , $ result [0 ]->Type );
9668+ $ this ->assertEquals ( 'NO ' , $ result [0 ]->Null );
9669+ $ this ->assertEquals ( 'PRI ' , $ result [0 ]->Key );
9670+ $ this ->assertEquals ( null , $ result [0 ]->Default );
9671+ $ this ->assertEquals ( '' , $ result [0 ]->Extra );
9672+
9673+ // SHOW TABLES
9674+ $ result = $ this ->assertQuery ( 'SHOW TABLES FROM wp ' );
9675+ $ this ->assertCount ( 1 , $ result );
9676+ $ this ->assertEquals ( 't ' , $ result [0 ]->Tables_in_wp );
9677+
9678+ // SHOW TABLE STATUS
9679+ $ result = $ this ->assertQuery ( 'SHOW TABLE STATUS FROM wp ' );
9680+ $ this ->assertCount ( 1 , $ result );
9681+ $ this ->assertEquals ( 't ' , $ result [0 ]->Name );
9682+
9683+ // ALTER TABLE
9684+ $ this ->assertQuery ( 'ALTER TABLE wp.t ADD COLUMN name VARCHAR(255) ' );
9685+ $ result = $ this ->assertQuery ( 'SHOW COLUMNS FROM wp.t ' );
9686+ $ this ->assertCount ( 2 , $ result );
9687+
9688+ // CREATE INDEX
9689+ $ this ->assertQuery ( 'CREATE INDEX idx_name ON wp.t (name) ' );
9690+ $ result = $ this ->assertQuery ( 'SHOW INDEXES FROM wp.t ' );
9691+ $ this ->assertCount ( 2 , $ result );
9692+ $ this ->assertEquals ( 'idx_name ' , $ result [1 ]->Key_name );
9693+
9694+ // DROP INDEX
9695+ $ this ->assertQuery ( 'DROP INDEX idx_name ON wp.t ' );
9696+ $ result = $ this ->assertQuery ( 'SHOW INDEXES FROM wp.t ' );
9697+ $ this ->assertCount ( 1 , $ result );
9698+ $ this ->assertEquals ( 'PRIMARY ' , $ result [0 ]->Key_name );
9699+
9700+ // LOCK TABLE
9701+ $ this ->assertQuery ( 'LOCK TABLES wp.t READ ' );
9702+
9703+ // UNLOCK TABLE
9704+ $ this ->assertQuery ( 'UNLOCK TABLES ' );
9705+
9706+ // ANALYZE TABLE
9707+ $ this ->assertQuery ( 'ANALYZE TABLE wp.t ' );
9708+
9709+ // CHECK TABLE
9710+ $ this ->assertQuery ( 'CHECK TABLE wp.t ' );
9711+
9712+ // OPTIMIZE TABLE
9713+ $ this ->assertQuery ( 'OPTIMIZE TABLE wp.t ' );
9714+
9715+ // REPAIR TABLE
9716+ $ this ->assertQuery ( 'REPAIR TABLE wp.t ' );
9717+
9718+ // DROP TABLE
9719+ $ this ->assertQuery ( 'DROP TABLE wp.t ' );
9720+ $ result = $ this ->assertQuery ( 'SHOW TABLES FROM wp ' );
9721+ $ this ->assertCount ( 0 , $ result );
9722+ }
9723+
9724+ public function testWriteWithUsageOfInformationSchemaTables (): void {
9725+ // Ensure "information_schema.tables" is empty.
9726+ $ this ->assertQuery ( 'DROP TABLE _options, _dates ' );
9727+ $ result = $ this ->assertQuery ( 'SELECT * FROM information_schema.tables ' );
9728+ $ this ->assertCount ( 0 , $ result );
9729+
9730+ // Create a table.
9731+ $ this ->assertQuery ( 'CREATE TABLE t (id INT, value VARCHAR(255)) ' );
9732+
9733+ // INSERT with SELECT from information schema.
9734+ $ this ->assertQuery ( 'INSERT INTO t (id, value) SELECT 1, table_name FROM information_schema.tables ' );
9735+ $ result = $ this ->assertQuery ( 'SELECT * FROM t ' );
9736+ $ this ->assertCount ( 1 , $ result );
9737+ $ this ->assertEquals (
9738+ array (
9739+ (object ) array (
9740+ 'id ' => '1 ' ,
9741+ 'value ' => 't ' ,
9742+ ),
9743+ ),
9744+ $ result
9745+ );
9746+
9747+ // INSERT with subselect from information schema.
9748+ $ this ->assertQuery ( 'INSERT INTO t (id, value) SELECT 2, table_name FROM (SELECT table_name FROM information_schema.tables) ' );
9749+ $ result = $ this ->assertQuery ( 'SELECT * FROM t ' );
9750+ $ this ->assertCount ( 2 , $ result );
9751+ $ this ->assertEquals (
9752+ array (
9753+ (object ) array (
9754+ 'id ' => '1 ' ,
9755+ 'value ' => 't ' ,
9756+ ),
9757+ (object ) array (
9758+ 'id ' => '2 ' ,
9759+ 'value ' => 't ' ,
9760+ ),
9761+ ),
9762+ $ result
9763+ );
9764+
9765+ // INSERT with JOIN on information schema.
9766+ $ this ->assertQuery (
9767+ 'INSERT INTO t (id, value)
9768+ SELECT 3, it.table_name
9769+ FROM information_schema.schemata s
9770+ JOIN information_schema.tables it ON s.schema_name = it.table_schema '
9771+ );
9772+ $ result = $ this ->assertQuery ( 'SELECT * FROM t ' );
9773+ $ this ->assertCount ( 3 , $ result );
9774+ $ this ->assertEquals (
9775+ array (
9776+ (object ) array (
9777+ 'id ' => '1 ' ,
9778+ 'value ' => 't ' ,
9779+ ),
9780+ (object ) array (
9781+ 'id ' => '2 ' ,
9782+ 'value ' => 't ' ,
9783+ ),
9784+ (object ) array (
9785+ 'id ' => '3 ' ,
9786+ 'value ' => 't ' ,
9787+ ),
9788+ ),
9789+ $ result
9790+ );
9791+
9792+ // TODO: UPDATE with JOIN on information schema is not supported yet.
9793+
9794+ // DELETE with JOIN on information schema.
9795+ $ this ->assertQuery ( 'UPDATE t SET value = "other" WHERE id > 1 ' );
9796+ $ this ->assertQuery ( 'DELETE t FROM t JOIN information_schema.tables it ON t.value = it.table_name ' );
9797+ $ result = $ this ->assertQuery ( 'SELECT * FROM t ' );
9798+ $ this ->assertEquals (
9799+ array (
9800+ (object ) array (
9801+ 'id ' => '2 ' ,
9802+ 'value ' => 'other ' ,
9803+ ),
9804+ (object ) array (
9805+ 'id ' => '3 ' ,
9806+ 'value ' => 'other ' ,
9807+ ),
9808+ ),
9809+ $ result
9810+ );
9811+ }
95409812}
0 commit comments