From b2377fa6b29c08b85c6f8063c3dcc89169a5352e Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Thu, 2 Oct 2025 14:19:49 +0200 Subject: [PATCH 1/6] Add support for CHECK constraints --- tests/WP_SQLite_Driver_Tests.php | 207 ++++++++++++++++++ tests/WP_SQLite_Driver_Translation_Tests.php | 75 +++++-- .../sqlite-ast/class-wp-sqlite-driver.php | 82 ++++++- ...s-wp-sqlite-information-schema-builder.php | 92 ++++++-- 4 files changed, 418 insertions(+), 38 deletions(-) diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index c78ef0fb..51b990ed 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -8976,4 +8976,211 @@ public function testColumnInfoWithZeroRowsPhpBug(): void { $column_info[0] ); } + + public function testCheckConstraints(): void { + $this->assertQuery( + "CREATE TABLE t ( + id INT NOT NULL CHECK (id > 0), + name VARCHAR(255) NOT NULL CHECK (name != ''), + score DOUBLE NOT NULL CHECK (score > 0 AND score < 100), + data JSON CHECK (json_valid(data)), + start_timestamp TIMESTAMP NOT NULL, + end_timestamp TIMESTAMP NOT NULL, + CONSTRAINT c1 CHECK (id < 10), + CONSTRAINT c2 CHECK (start_timestamp < end_timestamp), + CONSTRAINT c3 CHECK (length(data) < 20) + )" + ); + + // Valid data. + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (1, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') + " + ); + + // Invalid ID. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (0, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: t_chk_1', + $exception->getMessage() + ); + + // Invalid name. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (1, '', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: t_chk_2', + $exception->getMessage() + ); + + // Invalid score. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (1, 'test', 100, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: t_chk_3', + $exception->getMessage() + ); + + // Invalid data. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (1, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', 'invalid JSON') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: t_chk_4', + $exception->getMessage() + ); + + // Invalid c1. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (11, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"value\"}') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c1', + $exception->getMessage() + ); + + // Invalid c2. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (1, 'test', 50, '2025-01-02 12:00:00', '2025-01-01 12:00:00', '{\"key\":\"value\"}') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c2', + $exception->getMessage() + ); + + // Invalid c3. + $exception = null; + try { + $this->assertQuery( + "INSERT INTO t (id, name, score, start_timestamp, end_timestamp, data) + VALUES (1, 'test', 50, '2025-01-01 12:00:00', '2025-01-02 12:00:00', '{\"key\":\"a-very-long-value\"}') + " + ); + } catch ( WP_SQLite_Driver_Exception $e ) { + $exception = $e; + } + $this->assertNotNull( $exception ); + $this->assertSame( + 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c3', + $exception->getMessage() + ); + + // SHOW CREATE TABLE + $result = $this->assertQuery( 'SHOW CREATE TABLE t' ); + $this->assertCount( 1, $result ); + $this->assertEquals( + implode( + "\n", + array( + 'CREATE TABLE `t` (', + ' `id` int NOT NULL,', + ' `name` varchar(255) NOT NULL,', + ' `score` double NOT NULL,', + ' `data` json DEFAULT NULL,', + ' `start_timestamp` timestamp NOT NULL,', + ' `end_timestamp` timestamp NOT NULL,', + + // The of the check expressions below is not 100% matching MySQL, + // because in MySQL the expressions are parsed and normalized. + ' CONSTRAINT `c1` CHECK ( id < 10 ),', + ' CONSTRAINT `c2` CHECK ( start_timestamp < end_timestamp ),', + ' CONSTRAINT `c3` CHECK ( length ( data ) < 20 ),', + ' CONSTRAINT `t_chk_1` CHECK ( id > 0 ),', + " CONSTRAINT `t_chk_2` CHECK ( name != '' ),", + ' CONSTRAINT `t_chk_3` CHECK ( score > 0 AND score < 100 ),', + ' CONSTRAINT `t_chk_4` CHECK ( json_valid ( data ) )', + ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci', + ) + ), + $result[0]->{'Create Table'} + ); + } + + public function testAlterTableAddCheckConstraint(): void { + $this->assertQuery( 'CREATE TABLE t (id INT)' ); + + // ADD CONSTRAINT syntax. + $this->assertQuery( 'ALTER TABLE t ADD CONSTRAINT c CHECK (id > 0)' ); + + // ADD CHECK syntax. + $this->assertQuery( 'ALTER TABLE t ADD CHECK (id < 10)' ); + + // SHOW CREATE TABLE + $this->assertQuery( 'SHOW CREATE TABLE t' ); + $result = $this->engine->get_query_results(); + $this->assertEquals( + implode( + "\n", + array( + 'CREATE TABLE `t` (', + ' `id` int DEFAULT NULL,', + ' CONSTRAINT `c` CHECK ( id > 0 ),', + ' CONSTRAINT `t_chk_1` CHECK ( id < 10 )', + ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci', + ) + ), + $result[0]->{'Create Table'} + ); + + // Insert valid data. + $this->assertQuery( 'INSERT INTO t (id) VALUES (1)' ); + + // Insert invalid data. + $this->expectException( WP_SQLite_Driver_Exception::class ); + $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c' ); + $this->assertQuery( 'INSERT INTO t (id) VALUES (0)' ); + } } diff --git a/tests/WP_SQLite_Driver_Translation_Tests.php b/tests/WP_SQLite_Driver_Translation_Tests.php index 07fddb8f..95eb2b3c 100644 --- a/tests/WP_SQLite_Driver_Translation_Tests.php +++ b/tests/WP_SQLite_Driver_Translation_Tests.php @@ -243,6 +243,7 @@ public function testCreateTable(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -267,6 +268,7 @@ public function testCreateTableWithMultipleColumns(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -285,14 +287,15 @@ public function testCreateTableWithBasicConstraints(): void { . " VALUES ('wp', 't', 'id', 1, null, 'NO', 'int', null, null, 10, 0, null, null, null, 'int', 'PRI', 'auto_increment', 'select,insert,update,references', '', '', null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't', 0, 'wp', 'PRIMARY', 1, 'id', 'A', 0, null, null, '', 'BTREE', '', '', 'YES', null)", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't', 'wp', 'PRIMARY', 'PRIMARY KEY')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't', 'wp', 'PRIMARY', 'PRIMARY KEY', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'PRIMARY', 'wp', 't', 'id', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -314,6 +317,7 @@ public function testCreateTableWithEngine(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -335,6 +339,7 @@ public function testCreateTableWithCollate(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -362,14 +367,15 @@ public function testCreateTableWithPrimaryKey(): void { . " VALUES ('wp', 't', 'id', 1, null, 'NO', 'int', null, null, 10, 0, null, null, null, 'int', 'PRI', '', 'select,insert,update,references', '', '', null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't', 0, 'wp', 'PRIMARY', 1, 'id', 'A', 0, null, null, '', 'BTREE', '', '', 'YES', null)", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't', 'wp', 'PRIMARY', 'PRIMARY KEY')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't', 'wp', 'PRIMARY', 'PRIMARY KEY', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'PRIMARY', 'wp', 't', 'id', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -389,14 +395,15 @@ public function testCreateTableWithPrimaryKeyAndAutoincrement(): void { . " VALUES ('wp', 't1', 'id', 1, null, 'NO', 'int', null, null, 10, 0, null, null, null, 'int', 'PRI', 'auto_increment', 'select,insert,update,references', '', '', null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't1', 0, 'wp', 'PRIMARY', 1, 'id', 'A', 0, null, null, '', 'BTREE', '', '', 'YES', null)", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't1', 'wp', 'PRIMARY', 'PRIMARY KEY')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't1', 'wp', 'PRIMARY', 'PRIMARY KEY', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'PRIMARY', 'wp', 't1', 'id', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't1'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't1' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't1' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't1' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't1' ORDER BY tc.constraint_name", ) ); @@ -414,14 +421,15 @@ public function testCreateTableWithPrimaryKeyAndAutoincrement(): void { . " VALUES ('wp', 't2', 'id', 1, null, 'NO', 'int', null, null, 10, 0, null, null, null, 'int', 'PRI', 'auto_increment', 'select,insert,update,references', '', '', null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't2', 0, 'wp', 'PRIMARY', 1, 'id', 'A', 0, null, null, '', 'BTREE', '', '', 'YES', null)", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't2', 'wp', 'PRIMARY', 'PRIMARY KEY')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't2', 'wp', 'PRIMARY', 'PRIMARY KEY', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'PRIMARY', 'wp', 't2', 'id', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't2'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't2' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't2' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't2' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't2' ORDER BY tc.constraint_name", ) ); @@ -441,14 +449,15 @@ public function testCreateTableWithPrimaryKeyAndAutoincrement(): void { 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't3', 0, 'wp', 'PRIMARY', 1, 'id', 'A', 0, null, null, '', 'BTREE', '', '', 'YES', null)", "UPDATE `_wp_sqlite_mysql_information_schema_columns` AS c SET (column_key, is_nullable) = ( SELECT CASE WHEN MAX(s.index_name = 'PRIMARY') THEN 'PRI' WHEN MAX(s.non_unique = 0 AND s.seq_in_index = 1) THEN 'UNI' WHEN MAX(s.seq_in_index = 1) THEN 'MUL' ELSE '' END, CASE WHEN MAX(s.index_name = 'PRIMARY') THEN 'NO' ELSE c.is_nullable END FROM `_wp_sqlite_mysql_information_schema_statistics` AS s WHERE s.table_schema = c.table_schema AND s.table_name = c.table_name AND s.column_name = c.column_name ) WHERE c.table_schema = 'wp' AND c.table_name = 't3'", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't3', 'wp', 'PRIMARY', 'PRIMARY KEY')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't3', 'wp', 'PRIMARY', 'PRIMARY KEY', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'PRIMARY', 'wp', 't3', 'id', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't3'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't3' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't3' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't3' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't3' ORDER BY tc.constraint_name", ) ); } @@ -471,22 +480,23 @@ public function testCreateTableWithInlineUniqueIndexes(): void { . " VALUES ('wp', 't', 'id', 1, null, 'YES', 'int', null, null, 10, 0, null, null, null, 'int', 'UNI', '', 'select,insert,update,references', '', '', null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't', 0, 'wp', 'id', 1, 'id', 'A', 0, null, null, 'YES', 'BTREE', '', '', 'YES', null)", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't', 'wp', 'id', 'UNIQUE')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't', 'wp', 'id', 'UNIQUE', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'id', 'wp', 't', 'id', 1, null, null, null, null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_columns` (`table_schema`, `table_name`, `column_name`, `ordinal_position`, `column_default`, `is_nullable`, `data_type`, `character_maximum_length`, `character_octet_length`, `numeric_precision`, `numeric_scale`, `datetime_precision`, `character_set_name`, `collation_name`, `column_type`, `column_key`, `extra`, `privileges`, `column_comment`, `generation_expression`, `srs_id`)' . " VALUES ('wp', 't', 'name', 2, null, 'YES', 'text', 65535, 65535, null, null, null, 'utf8mb4', 'utf8mb4_0900_ai_ci', 'text', 'UNI', '', 'select,insert,update,references', '', '', null)", 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't', 0, 'wp', 'name', 1, 'name', 'A', 0, null, null, 'YES', 'BTREE', '', '', 'YES', null)", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't', 'wp', 'name', 'UNIQUE')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't', 'wp', 'name', 'UNIQUE', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'name', 'wp', 't', 'name', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -514,8 +524,8 @@ public function testCreateTableWithStandaloneUniqueIndexes(): void { 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't', 0, 'wp', 'id', 1, 'id', 'A', 0, null, null, 'YES', 'BTREE', '', '', 'YES', null)", "UPDATE `_wp_sqlite_mysql_information_schema_columns` AS c SET (column_key, is_nullable) = ( SELECT CASE WHEN MAX(s.index_name = 'PRIMARY') THEN 'PRI' WHEN MAX(s.non_unique = 0 AND s.seq_in_index = 1) THEN 'UNI' WHEN MAX(s.seq_in_index = 1) THEN 'MUL' ELSE '' END, CASE WHEN MAX(s.index_name = 'PRIMARY') THEN 'NO' ELSE c.is_nullable END FROM `_wp_sqlite_mysql_information_schema_statistics` AS s WHERE s.table_schema = c.table_schema AND s.table_name = c.table_name AND s.column_name = c.column_name ) WHERE c.table_schema = 'wp' AND c.table_name = 't'", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't', 'wp', 'id', 'UNIQUE')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't', 'wp', 'id', 'UNIQUE', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'id', 'wp', 't', 'id', 1, null, null, null, null)", "SELECT column_name, data_type, is_nullable, character_maximum_length FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' AND column_name IN ('name')", @@ -523,14 +533,15 @@ public function testCreateTableWithStandaloneUniqueIndexes(): void { 'INSERT INTO `_wp_sqlite_mysql_information_schema_statistics` (`table_schema`, `table_name`, `non_unique`, `index_schema`, `index_name`, `seq_in_index`, `column_name`, `collation`, `cardinality`, `sub_part`, `packed`, `nullable`, `index_type`, `comment`, `index_comment`, `is_visible`, `expression`)' . " VALUES ('wp', 't', 0, 'wp', 'name', 1, 'name', 'A', 0, null, null, 'YES', 'BTREE', '', '', 'YES', null)", "UPDATE `_wp_sqlite_mysql_information_schema_columns` AS c SET (column_key, is_nullable) = ( SELECT CASE WHEN MAX(s.index_name = 'PRIMARY') THEN 'PRI' WHEN MAX(s.non_unique = 0 AND s.seq_in_index = 1) THEN 'UNI' WHEN MAX(s.seq_in_index = 1) THEN 'MUL' ELSE '' END, CASE WHEN MAX(s.index_name = 'PRIMARY') THEN 'NO' ELSE c.is_nullable END FROM `_wp_sqlite_mysql_information_schema_statistics` AS s WHERE s.table_schema = c.table_schema AND s.table_name = c.table_name AND s.column_name = c.column_name ) WHERE c.table_schema = 'wp' AND c.table_name = 't'", - 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`)' - . " VALUES ('wp', 't', 'wp', 'name', 'UNIQUE')", + 'INSERT INTO `_wp_sqlite_mysql_information_schema_table_constraints` (`table_schema`, `table_name`, `constraint_schema`, `constraint_name`, `constraint_type`, `enforced`)' + . " VALUES ('wp', 't', 'wp', 'name', 'UNIQUE', 'YES')", 'INSERT INTO `_wp_sqlite_mysql_information_schema_key_column_usage` (`constraint_schema`, `constraint_name`, `table_schema`, `table_name`, `column_name`, `ordinal_position`, `position_in_unique_constraint`, `referenced_table_schema`, `referenced_table_name`, `referenced_column_name`)' . " VALUES ('wp', 'name', 'wp', 't', 'name', 1, null, null, null, null)", "SELECT * FROM `_wp_sqlite_mysql_information_schema_tables` WHERE table_type = 'BASE TABLE' AND table_schema = 'wp' AND table_name = 't'", "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -600,6 +611,7 @@ public function testAlterTableAddColumn(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -630,6 +642,7 @@ public function testAlterTableAddColumnWithNotNull(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -660,6 +673,7 @@ public function testAlterTableAddColumnWithDefault(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -690,6 +704,7 @@ public function testAlterTableAddColumnWithNotNullAndDefault(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -726,6 +741,7 @@ public function testAlterTableAddMultipleColumns(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -758,6 +774,7 @@ public function testAlterTableDropColumn(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -794,6 +811,7 @@ public function testAlterTableDropMultipleColumns(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -829,6 +847,7 @@ public function testAlterTableAddAndDropColumns(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -864,6 +883,7 @@ public function testAlterTableDropAndAddSingleColumn(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -886,6 +906,7 @@ public function testBitDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -908,6 +929,7 @@ public function testBooleanDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -938,6 +960,7 @@ public function testIntegerDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -964,6 +987,7 @@ public function testFloatDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -990,6 +1014,7 @@ public function testDecimalTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1012,6 +1037,7 @@ public function testCharDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1036,6 +1062,7 @@ public function testVarcharDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1062,6 +1089,7 @@ public function testNationalCharDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1086,6 +1114,7 @@ public function testNcharVarcharDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1110,6 +1139,7 @@ public function testNationalVarcharDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1136,6 +1166,7 @@ public function testTextDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1156,6 +1187,7 @@ public function testEnumDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1184,6 +1216,7 @@ public function testDateAndTimeDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1206,6 +1239,7 @@ public function testBinaryDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1232,6 +1266,7 @@ public function testBlobDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1258,6 +1293,7 @@ public function testBasicSpatialDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1282,6 +1318,7 @@ public function testMultiObjectSpatialDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1304,6 +1341,7 @@ public function testGeometryCollectionDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } @@ -1324,6 +1362,7 @@ public function testSerialDataTypes(): void { "SELECT * FROM `_wp_sqlite_mysql_information_schema_columns` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY ordinal_position", "SELECT * FROM `_wp_sqlite_mysql_information_schema_statistics` WHERE table_schema = 'wp' AND table_name = 't' ORDER BY INDEX_NAME = 'PRIMARY' DESC, NON_UNIQUE = '0' DESC, INDEX_TYPE = 'SPATIAL' DESC, INDEX_TYPE = 'BTREE' DESC, INDEX_TYPE = 'FULLTEXT' DESC, ROWID, SEQ_IN_INDEX", "SELECT * FROM `_wp_sqlite_mysql_information_schema_referential_constraints` WHERE constraint_schema = 'wp' AND table_name = 't' ORDER BY constraint_name", + "SELECT tc.*, cc.check_clause FROM `_wp_sqlite_mysql_information_schema_table_constraints` tc JOIN `_wp_sqlite_mysql_information_schema_check_constraints` cc ON cc.constraint_name = tc.constraint_name WHERE tc.constraint_schema = 'wp' AND tc.table_name = 't' ORDER BY tc.constraint_name", ) ); } diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php b/wp-includes/sqlite-ast/class-wp-sqlite-driver.php index 53a9c32c..7dd28c9f 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-driver.php @@ -4739,7 +4739,26 @@ private function get_sqlite_create_table_statement( } } - // 5. Generate CREATE TABLE statement columns. + // 5. Get CHECK constraint info. + $table_constraints_table = $this->information_schema_builder + ->get_table_name( $table_is_temporary, 'table_constraints' ); + $check_constraints_table = $this->information_schema_builder + ->get_table_name( $table_is_temporary, 'check_constraints' ); + $check_constraints_info = $this->execute_sqlite_query( + sprintf( + 'SELECT tc.*, cc.check_clause + FROM %s tc + JOIN %s cc ON cc.constraint_name = tc.constraint_name + WHERE tc.constraint_schema = ? + AND tc.table_name = ? + ORDER BY tc.constraint_name', + $this->quote_sqlite_identifier( $table_constraints_table ), + $this->quote_sqlite_identifier( $check_constraints_table ) + ), + array( $this->db_name, $table_name ) + )->fetchAll( PDO::FETCH_ASSOC ); + + // 6. Generate CREATE TABLE statement columns. $rows = array(); $on_update_queries = array(); $has_autoincrement = false; @@ -4875,7 +4894,7 @@ function ( $column ) { } } - // 7. Add foreign key constraints. + // 8. Add foreign key constraints. foreach ( $referential_constraints_info as $referential_constraint ) { $column_names = array(); $referenced_column_names = array(); @@ -4910,7 +4929,26 @@ function ( $column ) { $rows[] = $query; } - // 8. Compose the CREATE TABLE statement. + // 9. Add CHECK constraints. + foreach ( $check_constraints_info as $check_constraint ) { + if ( 'NO' === $check_constraint['ENFORCED'] ) { + continue; + } + + // Translate the check clause from MySQL to SQLite. + $ast = $this->create_parser( 'SELECT ' . $check_constraint['CHECK_CLAUSE'] )->parse(); + $expr = $ast->get_first_descendant_node( 'selectItem' )->get_first_child_node(); + $check_clause = $this->translate( $expr ); + + $sql = sprintf( + ' CONSTRAINT %s CHECK %s', + $this->quote_sqlite_identifier( $check_constraint['CONSTRAINT_NAME'] ), + $check_clause + ); + $rows[] = $sql; + } + + // 10. Compose the CREATE TABLE statement. $create_table_query = sprintf( "CREATE %sTABLE %s (\n", $table_is_temporary ? 'TEMPORARY ' : '', @@ -5028,7 +5066,26 @@ private function get_mysql_create_table_statement( bool $table_is_temporary, str } } - // 5. Generate CREATE TABLE statement columns. + // 5. Get CHECK constraint info. + $table_constraints_table = $this->information_schema_builder + ->get_table_name( $table_is_temporary, 'table_constraints' ); + $check_constraints_table = $this->information_schema_builder + ->get_table_name( $table_is_temporary, 'check_constraints' ); + $check_constraints_info = $this->execute_sqlite_query( + sprintf( + 'SELECT tc.*, cc.check_clause + FROM %s tc + JOIN %s cc ON cc.constraint_name = tc.constraint_name + WHERE tc.constraint_schema = ? + AND tc.table_name = ? + ORDER BY tc.constraint_name', + $this->quote_sqlite_identifier( $table_constraints_table ), + $this->quote_sqlite_identifier( $check_constraints_table ) + ), + array( $this->db_name, $table_name ) + )->fetchAll( PDO::FETCH_ASSOC ); + + // 6. Generate CREATE TABLE statement columns. $rows = array(); foreach ( $column_info as $column ) { $sql = ' '; @@ -5072,7 +5129,7 @@ private function get_mysql_create_table_statement( bool $table_is_temporary, str $rows[] = $sql; } - // 6. Generate CREATE TABLE statement constraints, collect indexes. + // 7. Generate CREATE TABLE statement constraints, collect indexes. foreach ( $grouped_constraints as $constraint ) { ksort( $constraint ); $info = $constraint[1]; @@ -5129,7 +5186,7 @@ function ( $column ) { $rows[] = $sql; } - // 7. Add foreign key constraints. + // 8. Add foreign key constraints. foreach ( $referential_constraints_info as $referential_constraint ) { $column_names = array(); $referenced_column_names = array(); @@ -5153,7 +5210,18 @@ function ( $column ) { $rows[] = $sql; } - // 8. Compose the CREATE TABLE statement. + // 9. Add CHECK constraints. + foreach ( $check_constraints_info as $check_constraint ) { + $sql = sprintf( + ' CONSTRAINT %s CHECK %s%s', + $this->quote_mysql_identifier( $check_constraint['CONSTRAINT_NAME'] ), + $check_constraint['CHECK_CLAUSE'], + 'NO' === $check_constraint['ENFORCED'] ? ' /*!80016 NOT ENFORCED */' : '' + ); + $rows[] = $sql; + } + + // 10. Compose the CREATE TABLE statement. $collation = $table_info['TABLE_COLLATION']; $charset = substr( $collation, 0, strpos( $collation, '_' ) ); diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php index cd8e07cf..44873315 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php @@ -22,10 +22,10 @@ class WP_SQLite_Information_Schema_Builder { * - COLUMNS * - STATISTICS (indexes) * - TABLE_CONSTRAINTS + * - CHECK_CONSTRAINTS * * TODO (not yet implemented): * - VIEWS - * - CHECK_CONSTRAINTS * - TRIGGERS */ const INFORMATION_SCHEMA_TABLE_DEFINITIONS = array( @@ -168,6 +168,15 @@ class WP_SQLite_Information_Schema_Builder { REFERENCED_COLUMN_NAME TEXT COLLATE NOCASE, -- referenced column name UNIQUE (CONSTRAINT_SCHEMA, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_SCHEMA) ", + + // INFORMATION_SCHEMA.CHECK_CONSTRAINTS + 'check_constraints' => " + CONSTRAINT_CATALOG TEXT NOT NULL DEFAULT 'def' COLLATE NOCASE, -- always 'def' + CONSTRAINT_SCHEMA TEXT NOT NULL COLLATE NOCASE, -- constraint database name + CONSTRAINT_NAME TEXT NOT NULL COLLATE NOCASE, -- constraint name + CHECK_CLAUSE TEXT NOT NULL COLLATE BINARY, -- check clause + PRIMARY KEY (CONSTRAINT_SCHEMA, CONSTRAINT_NAME) + ", ); /** @@ -531,6 +540,10 @@ public function record_create_table( WP_Parser_Node $node ): void { $table_name, $index_data['index_name'] ?? null ); + $check_constraint_data = $this->extract_check_constraint_data( + $column_node, + $table_name + ); // Save inline column constraints and indexes. if ( null !== $index_data ) { @@ -557,6 +570,12 @@ public function record_create_table( WP_Parser_Node $node ): void { $key_column_usage_item ); } + if ( null !== $check_constraint_data ) { + $this->insert_values( + $this->get_table_name( $table_is_temporary, 'check_constraints' ), + $check_constraint_data + ); + } $column_position += 1; } @@ -1167,16 +1186,15 @@ private function record_add_constraint( ): void { // Get first constraint keyword. $children = $node->get_children(); - $keyword = $children[0] instanceof WP_MySQL_Token ? $children[0] : $children[1]; + if ( $children[0] instanceof WP_Parser_Node && 'constraintName' === $children[0]->rule_name ) { + $keyword = $children[1]; + } else { + $keyword = $children[0]; + } if ( ! $keyword instanceof WP_MySQL_Token ) { $keyword = $keyword->get_first_child_token(); } - // CHECK constraints are not supported yet. - if ( WP_MySQL_Lexer::CHECK_SYMBOL === $keyword->id ) { - throw new \Exception( 'CHECK constraints are not supported yet.' ); - } - // PRIMARY KEY and UNIQUE require an index. if ( WP_MySQL_Lexer::PRIMARY_SYMBOL === $keyword->id @@ -1208,6 +1226,7 @@ private function record_add_constraint( $constraint_data = $this->extract_table_constraint_data( $node, $table_name, $index_name ); $referential_constraint_data = $this->extract_referential_constraint_data( $node, $table_name ); $key_column_usage_data = $this->extract_key_column_usage_data( $node, $table_name, $index_name ); + $check_constraint_data = $this->extract_check_constraint_data( $node, $table_name ); // Save constraint data. if ( null !== $constraint_data ) { @@ -1230,6 +1249,13 @@ private function record_add_constraint( $key_column_usage_item ); } + + if ( null !== $check_constraint_data ) { + $this->insert_values( + $this->get_table_name( $table_is_temporary, 'check_constraints' ), + $check_constraint_data + ); + } } /** @@ -1605,12 +1631,22 @@ public function extract_table_constraint_data( // Index name always takes precedence over constraint name. $name = $index_name ?? $this->get_table_constraint_name( $node, $table_name ); + + // Constraint enforcement. + $constraint_enforcement = $node->get_first_descendant_node( 'constraintEnforcement' ); + if ( $constraint_enforcement && $constraint_enforcement->has_child_token( WP_MySQL_Lexer::NOT_SYMBOL ) ) { + $enforced = 'NO'; + } else { + $enforced = 'YES'; + } + return array( 'table_schema' => $this->db_name, 'table_name' => $table_name, 'constraint_schema' => $this->db_name, 'constraint_name' => $name, 'constraint_type' => $type, + 'enforced' => $enforced, ); } @@ -1768,6 +1804,32 @@ private function extract_key_column_usage_data( return $rows; } + /** + * Extract check constraint data from the "tableConstraintDef" AST node. + * + * @param WP_Parser_Node $node The "tableConstraintDef" AST node. + * @param string $table_name The table name. + * @return array|null The check constraint data as stored in information schema. + */ + private function extract_check_constraint_data( WP_Parser_Node $node, string $table_name ): ?array { + $check_constraint = $node->get_first_descendant_node( 'checkConstraint' ); + if ( null === $check_constraint ) { + return null; + } + + $expr = $check_constraint->get_first_child_node( 'exprWithParentheses' ); + $check_clause = ''; + foreach ( $expr->get_descendant_tokens() as $i => $token ) { + $check_clause .= ( $i > 0 ? ' ' : '' ) . $token->get_bytes(); + } + + return array( + 'constraint_schema' => $this->db_name, + 'constraint_name' => $this->get_table_constraint_name( $node, $table_name ), + 'check_clause' => $check_clause, + ); + } + /** * Update column info from constraint data in the statistics table. * @@ -2431,9 +2493,14 @@ public function get_table_constraint_name( WP_Parser_Node $node, string $table_n return $this->get_value( $name_node->get_first_child_node( 'identifier' ) ); } - // FOREIGN KEY constraint without a name gets a generated name. - if ( $node->get_first_descendant_node( 'references' ) ) { - // Get the highest existing name in format "_ibfk_". + $foreign_key = $node->get_first_descendant_node( 'references' ); + $check_constraint = $node->get_first_descendant_node( 'checkConstraint' ); + + // FOREIGN KEY and CHECK constraints without a name get a generated name. + if ( $foreign_key || $check_constraint ) { + $type = $check_constraint ? 'chk' : 'ibfk'; + + // Get the highest existing name in format "__". $existing_names = $this->connection->query( sprintf( "SELECT DISTINCT constraint_name @@ -2451,7 +2518,7 @@ public function get_table_constraint_name( WP_Parser_Node $node, string $table_n array( $this->db_name, $table_name, - str_replace( array( '_', '%' ), array( '\\_', '\\%' ), $table_name ) . '\\_ibfk\\_%', + str_replace( array( '_', '%' ), array( '\\_', '\\%' ), $table_name ) . "\\_{$type}\\_%", ) )->fetchAll( PDO::FETCH_COLUMN // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__PDO @@ -2465,10 +2532,9 @@ public function get_table_constraint_name( WP_Parser_Node $node, string $table_n $last_name_index = (int) max( $last_name_index, (int) $last_part ); } } - return $table_name . '_ibfk_' . ( $last_name_index + 1 ); + return $table_name . "_{$type}_" . ( $last_name_index + 1 ); } - // TODO: Handle CHECK constraints. return null; } From ea0826cfd6ab678379a3afdf6679d01f68c7b973 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 10 Oct 2025 10:21:50 +0200 Subject: [PATCH 2/6] Implement DROP CONSTRAINT for CHECK constraints --- tests/WP_SQLite_Driver_Tests.php | 20 +++++++++++ ...s-wp-sqlite-information-schema-builder.php | 33 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index 51b990ed..252514c8 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -9183,4 +9183,24 @@ public function testAlterTableAddCheckConstraint(): void { $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c' ); $this->assertQuery( 'INSERT INTO t (id) VALUES (0)' ); } + + public function testAlterTableDropCheckConstraint(): void { + $this->assertQuery( 'CREATE TABLE t (id INT, CONSTRAINT c CHECK (id > 0))' ); + $this->assertQuery( 'ALTER TABLE t DROP CONSTRAINT c' ); + + // SHOW CREATE TABLE + $this->assertQuery( 'SHOW CREATE TABLE t' ); + $result = $this->engine->get_query_results(); + $this->assertEquals( + implode( + "\n", + array( + 'CREATE TABLE `t` (', + ' `id` int DEFAULT NULL', + ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci', + ) + ), + $result[0]->{'Create Table'} + ); + } } diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php index 44873315..7266188b 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php @@ -1301,6 +1301,8 @@ private function record_drop_constraint( $this->record_drop_key( $table_is_temporary, $table_name, $name ); } elseif ( 'FOREIGN KEY' === $constraint_type ) { $this->record_drop_foreign_key( $table_is_temporary, $table_name, $name ); + } elseif ( 'CHECK' === $constraint_type ) { + $this->record_drop_check_constraint( $table_is_temporary, $table_name, $name ); } else { throw new \Exception( "DROP CONSTRAINT for constraint type '$constraint_type' is not supported." @@ -1398,6 +1400,37 @@ private function record_drop_foreign_key( ); } + /** + * Analyze DROP CHECK statement and record data in the information schema. + * + * @param bool $table_is_temporary Whether the table is temporary. + * @param string $table_name The table name. + * @param string $name The check constraint name. + */ + private function record_drop_check_constraint( + bool $table_is_temporary, + string $table_name, + string $name + ): void { + $this->delete_values( + $this->get_table_name( $table_is_temporary, 'table_constraints' ), + array( + 'CONSTRAINT_SCHEMA' => $this->db_name, + 'TABLE_NAME' => $table_name, + 'CONSTRAINT_TYPE' => 'CHECK', + 'CONSTRAINT_NAME' => $name, + ) + ); + + $this->delete_values( + $this->get_table_name( $table_is_temporary, 'check_constraints' ), + array( + 'CONSTRAINT_SCHEMA' => $this->db_name, + 'CONSTRAINT_NAME' => $name, + ) + ); + } + /** * Analyze "columnDefinition" or "fieldDefinition" AST node and extract column data. * From 9cc84c0e20178e409e34c4d31fbc077d56077555 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 10 Oct 2025 10:26:10 +0200 Subject: [PATCH 3/6] Implement DROP CHECK statement --- tests/WP_SQLite_Driver_Tests.php | 9 +++++++-- .../class-wp-sqlite-information-schema-builder.php | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index 252514c8..8907ba40 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -9185,8 +9185,13 @@ public function testAlterTableAddCheckConstraint(): void { } public function testAlterTableDropCheckConstraint(): void { - $this->assertQuery( 'CREATE TABLE t (id INT, CONSTRAINT c CHECK (id > 0))' ); - $this->assertQuery( 'ALTER TABLE t DROP CONSTRAINT c' ); + $this->assertQuery( 'CREATE TABLE t (id INT, CONSTRAINT c1 CHECK (id > 0), CONSTRAINT c2 CHECK (id < 10))' ); + + // DROP CONSTRAINT syntax. + $this->assertQuery( 'ALTER TABLE t DROP CONSTRAINT c1' ); + + // DROP CHECK syntax. + $this->assertQuery( 'ALTER TABLE t DROP CHECK c2' ); // SHOW CREATE TABLE $this->assertQuery( 'SHOW CREATE TABLE t' ); diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php index 7266188b..9965dc11 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php @@ -682,6 +682,13 @@ public function record_alter_table( WP_Parser_Node $node ): void { continue; } + // DROP CHECK + if ( $action->has_child_token( WP_MySQL_Lexer::CHECK_SYMBOL ) ) { + $name = $this->get_value( $action->get_first_child_node( 'identifier' ) ); + $this->record_drop_check_constraint( $table_is_temporary, $table_name, $name ); + continue; + } + // DROP [COLUMN] $column_ref = $action->get_first_child_node( 'fieldIdentifier' ); if ( null !== $column_ref ) { From b5ba184c3a19e77377206dc62c4e11698b3c1bcb Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 10 Oct 2025 10:40:22 +0200 Subject: [PATCH 4/6] Add information schema data tests for CHECK constraints --- tests/WP_SQLite_Driver_Metadata_Tests.php | 217 ++++++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/tests/WP_SQLite_Driver_Metadata_Tests.php b/tests/WP_SQLite_Driver_Metadata_Tests.php index f8db1623..abbd3b39 100644 --- a/tests/WP_SQLite_Driver_Metadata_Tests.php +++ b/tests/WP_SQLite_Driver_Metadata_Tests.php @@ -1878,4 +1878,221 @@ public function testInformationSchemaAlterTableDropConstraintWithAmbiguousName() $this->expectExceptionCode( 'HY000' ); $this->assertQuery( 'ALTER TABLE t2 DROP CONSTRAINT cnst' ); } + + public function testInformationSchemaCheckConstraints(): void { + $this->assertQuery( + "CREATE TABLE t ( + id INT NOT NULL CHECK (id > 0), + name VARCHAR(255) NOT NULL CHECK (name != ''), + score DOUBLE NOT NULL CHECK (score > 0 AND score < 100), + data JSON CHECK (json_valid(data)), + start_timestamp TIMESTAMP NOT NULL, + end_timestamp TIMESTAMP NOT NULL, + CONSTRAINT c1 CHECK (id < 10), + CONSTRAINT c2 CHECK (start_timestamp < end_timestamp), + CONSTRAINT c3 CHECK (length(data) < 20) + )" + ); + + // INFORMATION_SCHEMA.TABLE_CONSTRAINTS + $result = $this->assertQuery( "SELECT * FROM information_schema.table_constraints WHERE table_name = 't' ORDER BY CONSTRAINT_NAME" ); + $this->assertEquals( + array( + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c1', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c2', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c3', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_1', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_2', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_3', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_4', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + ), + $result + ); + + // INFORMATION_SCHEMA.CHECK_CONSTRAINTS + $result = $this->assertQuery( 'SELECT * FROM information_schema.check_constraints ORDER BY CONSTRAINT_NAME' ); + $this->assertCount( 7, $result ); + + $this->assertEquals( + array( + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c1', + 'CHECK_CLAUSE' => '( id < 10 )', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c2', + 'CHECK_CLAUSE' => '( start_timestamp < end_timestamp )', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c3', + 'CHECK_CLAUSE' => '( length ( data ) < 20 )', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_1', + 'CHECK_CLAUSE' => '( id > 0 )', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_2', + 'CHECK_CLAUSE' => "( name != '' )", + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_3', + 'CHECK_CLAUSE' => '( score > 0 AND score < 100 )', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_4', + 'CHECK_CLAUSE' => '( json_valid ( data ) )', + ), + ), + $result + ); + } + + public function testInformationSchemaAlterTableAddCheckConstraint(): void { + $this->assertQuery( 'CREATE TABLE t (id INT)' ); + + // ADD CONSTRAINT syntax. + $this->assertQuery( 'ALTER TABLE t ADD CONSTRAINT c CHECK (id > 0)' ); + + // ADD CHECK syntax. + $this->assertQuery( 'ALTER TABLE t ADD CHECK (id < 10)' ); + + // INFORMATION_SCHEMA.TABLE_CONSTRAINTS + $result = $this->assertQuery( "SELECT * FROM information_schema.table_constraints WHERE table_name = 't' ORDER BY CONSTRAINT_NAME" ); + $this->assertEquals( + array( + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_1', + 'TABLE_SCHEMA' => 'wp', + 'TABLE_NAME' => 't', + 'CONSTRAINT_TYPE' => 'CHECK', + 'ENFORCED' => 'YES', + ), + ), + $result + ); + + // INFORMATION_SCHEMA.CHECK_CONSTRAINTS + $result = $this->assertQuery( 'SELECT * FROM information_schema.check_constraints ORDER BY CONSTRAINT_NAME' ); + $this->assertEquals( + array( + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 'c', + 'CHECK_CLAUSE' => '( id > 0 )', + ), + (object) array( + 'CONSTRAINT_CATALOG' => 'def', + 'CONSTRAINT_SCHEMA' => 'wp', + 'CONSTRAINT_NAME' => 't_chk_1', + 'CHECK_CLAUSE' => '( id < 10 )', + ), + ), + $result + ); + } + + public function testInformationSchemaAlterTableDropCheckConstraint(): void { + $this->assertQuery( 'CREATE TABLE t (id INT, CONSTRAINT c1 CHECK (id > 0), CONSTRAINT c2 CHECK (id < 10))' ); + + $result = $this->assertQuery( "SELECT * FROM information_schema.table_constraints WHERE table_name = 't'" ); + $this->assertCount( 2, $result ); + + $result = $this->assertQuery( 'SELECT * FROM information_schema.check_constraints' ); + $this->assertCount( 2, $result ); + + // DROP CONSTRAINT syntax. + $this->assertQuery( 'ALTER TABLE t DROP CONSTRAINT c1' ); + + // DROP CHECK syntax. + $this->assertQuery( 'ALTER TABLE t DROP CHECK c2' ); + + $result = $this->assertQuery( "SELECT * FROM information_schema.table_constraints WHERE table_name = 't'" ); + $this->assertCount( 0, $result ); + + $result = $this->assertQuery( 'SELECT * FROM information_schema.check_constraints' ); + $this->assertCount( 0, $result ); + } } From 638bab939fc05e81087d9a22303d6434007396e7 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 10 Oct 2025 10:51:08 +0200 Subject: [PATCH 5/6] Improve tests --- tests/WP_SQLite_Driver_Tests.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index 8907ba40..504c5e82 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -9178,6 +9178,9 @@ public function testAlterTableAddCheckConstraint(): void { // Insert valid data. $this->assertQuery( 'INSERT INTO t (id) VALUES (1)' ); + $result = $this->assertQuery( 'SELECT * FROM t' ); + $this->assertCount( 1, $result ); + // Insert invalid data. $this->expectException( WP_SQLite_Driver_Exception::class ); $this->expectExceptionMessage( 'SQLSTATE[23000]: Integrity constraint violation: 19 CHECK constraint failed: c' ); @@ -9207,5 +9210,12 @@ public function testAlterTableDropCheckConstraint(): void { ), $result[0]->{'Create Table'} ); + + // Insert data that would violate the constraints. + $this->assertQuery( 'INSERT INTO t (id) VALUES (0)' ); + $this->assertQuery( 'INSERT INTO t (id) VALUES (100)' ); + + $result = $this->assertQuery( 'SELECT * FROM t' ); + $this->assertCount( 2, $result ); } } From 09a2385a0c17743cad65e9e345fa5269c1941fd2 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Fri, 10 Oct 2025 10:54:11 +0200 Subject: [PATCH 6/6] Add a test for CHECK constraint with NOT ENFORCED --- tests/WP_SQLite_Driver_Tests.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index 504c5e82..c57d670e 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -9218,4 +9218,30 @@ public function testAlterTableDropCheckConstraint(): void { $result = $this->assertQuery( 'SELECT * FROM t' ); $this->assertCount( 2, $result ); } + + public function testCheckConstraintNotEnforced(): void { + $this->assertQuery( 'CREATE TABLE t (id INT, CONSTRAINT c CHECK (id > 0) NOT ENFORCED)' ); + + // Insert data that would violate the constraints. + $this->assertQuery( 'INSERT INTO t (id) VALUES (0)' ); + + $result = $this->assertQuery( 'SELECT * FROM t' ); + $this->assertCount( 1, $result ); + + // SHOW CREATE TABLE + $this->assertQuery( 'SHOW CREATE TABLE t' ); + $result = $this->engine->get_query_results(); + $this->assertEquals( + implode( + "\n", + array( + 'CREATE TABLE `t` (', + ' `id` int DEFAULT NULL,', + ' CONSTRAINT `c` CHECK ( id > 0 ) /*!80016 NOT ENFORCED */', + ') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci', + ) + ), + $result[0]->{'Create Table'} + ); + } }