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

Commit a6a760e

Browse files
authored
New driver fixes from manual testing (#51)
**List of discovered issues:** - [x] Data types from `_mysql_data_types_cache` are sometimes not correctly fetched, as they can be saved in multiple formates (lowercase, uppercase, with or without backticks). - [x] MySQL applies type casting when saving data in non-strict mode, resulting in things like empty string being saved as `0` for an integer, `0000-00-00 00:00:00` for a date, etc. - [x] Functional defaults are incorrectly applied in non-strict mode (`DEFAULT CURRENT_TIMESTAMP` saves a `'CURRENT_TIMESTAMP'` string rather than the correct value). - [x] MySQL `BINARY` type is saved as `INTEGER`, but it's actually a binary string, and `BLOB` would be more suitable. - [x] MySQL supports date and time components without a zero padding, but that doesn't work with date and time functions in SQLite. (E.g.: `2025-3-7 9:5:2` is a valid datetime/timestamp value in MySQL, but SQLite requires it to be `2025-03-07 09:05:02`.) - [x] In multi-process environments (php-fpm), concurrent writes can cause "SQLSTATE[HY000]: General error: 5 database is locked" (`SQLITE_BUSY`).
1 parent a2ea9f8 commit a6a760e

6 files changed

+370
-25
lines changed

.github/workflows/wp-tests-phpunit-run.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const expectedFailures = [
4545
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #6',
4646
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #7',
4747
'Tests_Menu_wpNavMenu::test_wp_nav_menu_should_not_have_has_children_class_with_custom_depth',
48+
'WP_Test_REST_Posts_Controller::test_get_items_orderby_modified_query',
4849
];
4950

5051
console.log( 'Running WordPress PHPUnit tests with expected failures tracking...' );

tests/WP_SQLite_Driver_Tests.php

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3787,6 +3787,53 @@ public function testColumnDefaults(): void {
37873787
"
37883788
);
37893789

3790+
$result = $this->assertQuery( 'DESCRIBE t' );
3791+
$this->assertEquals(
3792+
array(
3793+
(object) array(
3794+
'Field' => 'name',
3795+
'Type' => 'varchar(255)',
3796+
'Null' => 'YES',
3797+
'Key' => '',
3798+
'Default' => 'CURRENT_TIMESTAMP',
3799+
'Extra' => '',
3800+
),
3801+
(object) array(
3802+
'Field' => 'type',
3803+
'Type' => 'varchar(255)',
3804+
'Null' => 'NO',
3805+
'Key' => '',
3806+
'Default' => 'DEFAULT',
3807+
'Extra' => '',
3808+
),
3809+
(object) array(
3810+
'Field' => 'description',
3811+
'Type' => 'varchar(250)',
3812+
'Null' => 'NO',
3813+
'Key' => '',
3814+
'Default' => '',
3815+
'Extra' => '',
3816+
),
3817+
(object) array(
3818+
'Field' => 'created_at',
3819+
'Type' => 'timestamp',
3820+
'Null' => 'YES',
3821+
'Key' => '',
3822+
'Default' => 'CURRENT_TIMESTAMP',
3823+
'Extra' => 'DEFAULT_GENERATED',
3824+
),
3825+
(object) array(
3826+
'Field' => 'updated_at',
3827+
'Type' => 'timestamp',
3828+
'Null' => 'NO',
3829+
'Key' => '',
3830+
'Default' => 'CURRENT_TIMESTAMP',
3831+
'Extra' => 'DEFAULT_GENERATED on update CURRENT_TIMESTAMP',
3832+
),
3833+
),
3834+
$result
3835+
);
3836+
37903837
$result = $this->assertQuery( 'SHOW CREATE TABLE t' );
37913838
$this->assertEquals(
37923839
"CREATE TABLE `t` (\n"
@@ -4379,6 +4426,40 @@ public function testNonStrictSqlModeNotNullWithDefault(): void {
43794426
$this->assertSame( '', $result[0]->value );
43804427
}
43814428

4429+
public function testNonStrictModeWithDefaultCurrentTimestamp(): void {
4430+
$this->assertQuery( "SET SESSION sql_mode = ''" );
4431+
$this->assertQuery( 'CREATE TABLE t (id INT, value TIMESTAMP DEFAULT CURRENT_TIMESTAMP)' );
4432+
4433+
// INSERT without a value saves CURRENT_TIMESTAMP:
4434+
$this->assertQuery( 'INSERT INTO t (id) VALUES (1)' );
4435+
$result = $this->assertQuery( 'SELECT * FROM t' );
4436+
$this->assertCount( 1, $result );
4437+
$this->assertRegExp( '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $result[0]->value );
4438+
4439+
// UPDATE with NULL saves NULL:
4440+
$this->assertQuery( 'UPDATE t SET value = NULL' );
4441+
$result = $this->assertQuery( 'SELECT * FROM t' );
4442+
$this->assertCount( 1, $result );
4443+
$this->assertNull( $result[0]->value );
4444+
}
4445+
4446+
public function testNonStrictModeWithDefaultCurrentTimestampNotNull(): void {
4447+
$this->assertQuery( "SET SESSION sql_mode = ''" );
4448+
$this->assertQuery( 'CREATE TABLE t (id INT, value TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)' );
4449+
4450+
// INSERT without a value saves CURRENT_TIMESTAMP:
4451+
$this->assertQuery( 'INSERT INTO t (id) VALUES (1)' );
4452+
$result = $this->assertQuery( 'SELECT * FROM t' );
4453+
$this->assertCount( 1, $result );
4454+
$this->assertRegExp( '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $result[0]->value );
4455+
4456+
// UPDATE with NULL saves IMPLICIT DEFAULT:
4457+
$this->assertQuery( 'UPDATE t SET value = NULL' );
4458+
$result = $this->assertQuery( 'SELECT * FROM t' );
4459+
$this->assertCount( 1, $result );
4460+
$this->assertSame( '0000-00-00 00:00:00', $result[0]->value );
4461+
}
4462+
43824463
public function testNonStrictSqlModeWithNoListedColumns(): void {
43834464
$this->assertQuery( "SET SESSION sql_mode = ''" );
43844465

@@ -4543,6 +4624,113 @@ public function testNonStrictModeWithReplaceStatement(): void {
45434624
$this->assertSame( 'blue', $result[0]->color );
45444625
}
45454626

4627+
public function testNonStrictModeTypeCasting(): void {
4628+
$this->assertQuery(
4629+
"CREATE TABLE t (
4630+
col_int INT,
4631+
col_float FLOAT,
4632+
col_double DOUBLE,
4633+
col_decimal DECIMAL,
4634+
col_char CHAR(255),
4635+
col_varchar VARCHAR(255),
4636+
col_text TEXT,
4637+
col_bool BOOL,
4638+
col_bit BIT,
4639+
col_binary BINARY(255),
4640+
col_varbinary VARBINARY(255),
4641+
col_blob BLOB,
4642+
col_date DATE,
4643+
col_time TIME,
4644+
col_datetime DATETIME,
4645+
col_timestamp TIMESTAMP,
4646+
col_year YEAR,
4647+
col_enum ENUM('a', 'b', 'c'),
4648+
col_set SET('a', 'b', 'c'),
4649+
col_json JSON
4650+
)"
4651+
);
4652+
4653+
// Set non-strict mode.
4654+
$this->assertQuery( "SET SESSION sql_mode = ''" );
4655+
4656+
// INSERT.
4657+
$this->assertQuery(
4658+
"INSERT INTO t VALUES ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')"
4659+
);
4660+
4661+
$result = $this->assertQuery( 'SELECT * FROM t' );
4662+
$this->assertCount( 1, $result );
4663+
$this->assertSame( '0', $result[0]->col_int );
4664+
$this->assertSame( PHP_VERSION_ID < 80100 ? '0.0' : '0', $result[0]->col_float );
4665+
$this->assertSame( PHP_VERSION_ID < 80100 ? '0.0' : '0', $result[0]->col_double );
4666+
$this->assertSame( PHP_VERSION_ID < 80100 ? '0.0' : '0', $result[0]->col_decimal );
4667+
$this->assertSame( '', $result[0]->col_char );
4668+
$this->assertSame( '', $result[0]->col_varchar );
4669+
$this->assertSame( '', $result[0]->col_text );
4670+
$this->assertSame( '0', $result[0]->col_bool );
4671+
$this->assertSame( '0', $result[0]->col_bit );
4672+
$this->assertSame( PHP_VERSION_ID < 80100 ? null : '', $result[0]->col_binary );
4673+
$this->assertSame( PHP_VERSION_ID < 80100 ? null : '', $result[0]->col_varbinary );
4674+
$this->assertSame( PHP_VERSION_ID < 80100 ? null : '', $result[0]->col_blob );
4675+
$this->assertSame( '0000-00-00', $result[0]->col_date );
4676+
$this->assertSame( '00:00:00', $result[0]->col_time );
4677+
$this->assertSame( '0000-00-00 00:00:00', $result[0]->col_datetime );
4678+
$this->assertSame( '0000-00-00 00:00:00', $result[0]->col_timestamp );
4679+
$this->assertSame( '0000', $result[0]->col_year );
4680+
$this->assertSame( '', $result[0]->col_enum );
4681+
$this->assertSame( '', $result[0]->col_set );
4682+
$this->assertSame( '', $result[0]->col_json ); // TODO: This should not be allowed.
4683+
4684+
// UPDATE.
4685+
$this->assertQuery(
4686+
"UPDATE t SET
4687+
col_int = '',
4688+
col_float = '',
4689+
col_double = '',
4690+
col_decimal = '',
4691+
col_char = '',
4692+
col_varchar = '',
4693+
col_text = '',
4694+
col_bool = '',
4695+
col_bit = '',
4696+
col_binary = '',
4697+
col_varbinary = '',
4698+
col_blob = '',
4699+
col_date = '',
4700+
col_time = '',
4701+
col_datetime = '',
4702+
col_timestamp = '',
4703+
col_year = '',
4704+
col_enum = '',
4705+
col_set = '',
4706+
col_json = ''
4707+
"
4708+
);
4709+
4710+
$result = $this->assertQuery( 'SELECT * FROM t' );
4711+
$this->assertCount( 1, $result );
4712+
$this->assertSame( '0', $result[0]->col_int );
4713+
$this->assertSame( PHP_VERSION_ID < 80100 ? '0.0' : '0', $result[0]->col_float );
4714+
$this->assertSame( PHP_VERSION_ID < 80100 ? '0.0' : '0', $result[0]->col_double );
4715+
$this->assertSame( PHP_VERSION_ID < 80100 ? '0.0' : '0', $result[0]->col_decimal );
4716+
$this->assertSame( '', $result[0]->col_char );
4717+
$this->assertSame( '', $result[0]->col_varchar );
4718+
$this->assertSame( '', $result[0]->col_text );
4719+
$this->assertSame( '0', $result[0]->col_bool );
4720+
$this->assertSame( '0', $result[0]->col_bit );
4721+
$this->assertSame( PHP_VERSION_ID < 80100 ? null : '', $result[0]->col_binary );
4722+
$this->assertSame( PHP_VERSION_ID < 80100 ? null : '', $result[0]->col_varbinary );
4723+
$this->assertSame( PHP_VERSION_ID < 80100 ? null : '', $result[0]->col_blob );
4724+
$this->assertSame( '0000-00-00', $result[0]->col_date );
4725+
$this->assertSame( '00:00:00', $result[0]->col_time );
4726+
$this->assertSame( '0000-00-00 00:00:00', $result[0]->col_datetime );
4727+
$this->assertSame( '0000-00-00 00:00:00', $result[0]->col_timestamp );
4728+
$this->assertSame( '0000', $result[0]->col_year );
4729+
$this->assertSame( '', $result[0]->col_enum );
4730+
$this->assertSame( '', $result[0]->col_set );
4731+
$this->assertSame( '', $result[0]->col_json ); // TODO: This should not be allowed.
4732+
}
4733+
45464734
public function testSessionSqlModes(): void {
45474735
// Syntax: "sql_mode" ("@@sql_mode" for SELECT)
45484736
$this->assertQuery( 'SET sql_mode = "ERROR_FOR_DIVISION_BY_ZERO"' );

tests/WP_SQLite_Driver_Translation_Tests.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ public function testDateAndTimeDataTypes(): void {
11101110

11111111
public function testBinaryDataTypes(): void {
11121112
$this->assertQuery(
1113-
'CREATE TABLE `t` ( `b` INTEGER, `v` BLOB ) STRICT',
1113+
'CREATE TABLE `t` ( `b` BLOB, `v` BLOB ) STRICT',
11141114
'CREATE TABLE t (b BINARY, v VARBINARY(255))'
11151115
);
11161116

0 commit comments

Comments
 (0)