Skip to content

Commit 7bc98a2

Browse files
authored
Fix default null values and NULL value update edge case (#94)
1 parent 703737e commit 7bc98a2

File tree

2 files changed

+80
-10
lines changed

2 files changed

+80
-10
lines changed

tests/WP_SQLite_Translator_Tests.php

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ public function testCreateTable() {
368368
'Type' => 'bigint(20) unsigned',
369369
'Null' => 'NO',
370370
'Key' => 'PRI',
371-
'Default' => null,
371+
'Default' => '0',
372372
'Extra' => '',
373373
),
374374
(object) array(
@@ -1085,7 +1085,7 @@ public function testNestedTransactionWorkComplexModify() {
10851085
'Type' => 'integer',
10861086
'Null' => 'NO',
10871087
'Key' => 'PRI',
1088-
'Default' => null,
1088+
'Default' => '0',
10891089
'Extra' => '',
10901090
),
10911091
(object) array(
@@ -1946,29 +1946,30 @@ public function testOnConflictReplace()
19461946
name varchar(20) NOT NULL default 'default-value',
19471947
unique_name varchar(20) NOT NULL default 'unique-default-value',
19481948
inline_unique_name varchar(20) NOT NULL default 'inline-unique-default-value',
1949+
no_default varchar(20) NOT NULL,
19491950
UNIQUE KEY unique_name (unique_name)
19501951
);"
19511952
);
19521953

19531954
$this->assertQuery(
1954-
"INSERT INTO _tmp_table (ID, name, unique_name, inline_unique_name) VALUES (1, null, null, null);"
1955+
"INSERT INTO _tmp_table VALUES (1, null, null, null, '');"
19551956
);
1956-
$result = $this->assertQuery("SELECT name, unique_name, inline_unique_name FROM _tmp_table");
1957-
1958-
$result = $this->assertQuery("SELECT name, unique_name, inline_unique_name FROM _tmp_table");
1957+
$result = $this->assertQuery("SELECT * FROM _tmp_table WHERE ID = 1");
19591958
$this->assertEquals(
19601959
array(
19611960
(object) array(
1961+
'ID' => '1',
19621962
'name' => 'default-value',
19631963
'unique_name' => 'unique-default-value',
19641964
'inline_unique_name' => 'inline-unique-default-value',
1965+
'no_default' => '',
19651966
),
19661967
),
19671968
$result
19681969
);
19691970

19701971
$this->assertQuery(
1971-
"INSERT INTO _tmp_table (ID, name, unique_name, inline_unique_name) VALUES (2, '1', '2', '3');"
1972+
"INSERT INTO _tmp_table VALUES (2, '1', '2', '3', '4');"
19721973
);
19731974
$this->assertQuery(
19741975
"UPDATE _tmp_table SET name = null WHERE ID = 2;"
@@ -1995,5 +1996,60 @@ public function testOnConflictReplace()
19951996
"UPDATE _tmp_table SET inline_unique_name = NULL WHERE ID = 2;",
19961997
''
19971998
);
1999+
2000+
// WPDB allows for NULL values in columns that don't have a default value and a NOT NULL constraint
2001+
$this->assertQuery(
2002+
"UPDATE _tmp_table SET no_default = NULL WHERE ID = 2;",
2003+
''
2004+
);
2005+
2006+
$result = $this->assertQuery("SELECT * FROM _tmp_table WHERE ID = 2");
2007+
$this->assertEquals(
2008+
array(
2009+
(object) array(
2010+
'ID' => '2',
2011+
'name' => 'default-value',
2012+
'unique_name' => '2',
2013+
'inline_unique_name' => 'inline-unique-default-value',
2014+
'no_default' => '',
2015+
),
2016+
),
2017+
$result
2018+
);
2019+
}
2020+
2021+
public function testDefaultNullValue()
2022+
{
2023+
$this->assertQuery(
2024+
"CREATE TABLE _tmp_table (
2025+
name varchar(20) NOT NULL default NULL,
2026+
no_default varchar(20) NOT NULL
2027+
);"
2028+
);
2029+
2030+
$result = $this->assertQuery(
2031+
"DESCRIBE _tmp_table;"
2032+
);
2033+
$this->assertEquals(
2034+
array(
2035+
(object) array(
2036+
'Field' => 'name',
2037+
'Type' => 'varchar(20)',
2038+
'Null' => 'NO',
2039+
'Key' => '',
2040+
'Default' => 'NULL',
2041+
'Extra' => '',
2042+
),
2043+
(object) array(
2044+
'Field' => 'no_default',
2045+
'Type' => 'varchar(20)',
2046+
'Null' => 'NO',
2047+
'Key' => '',
2048+
'Default' => null,
2049+
'Extra' => '',
2050+
),
2051+
),
2052+
$result
2053+
);
19982054
}
19992055
}

wp-includes/sqlite/class-wp-sqlite-translator.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ private function parse_mysql_create_table_field() {
10401040
$result->name = '';
10411041
$result->sqlite_data_type = '';
10421042
$result->not_null = false;
1043-
$result->default = null;
1043+
$result->default = false;
10441044
$result->auto_increment = false;
10451045
$result->primary_key = false;
10461046

@@ -1128,11 +1128,25 @@ private function make_sqlite_field_definition( $field ) {
11281128
* This mode allows the use of `NULL` when NOT NULL is set on a column that falls back to DEFAULT.
11291129
* SQLite does not support this behavior, so we need to add the `ON CONFLICT REPLACE` clause to the column definition.
11301130
*/
1131-
if (null !== $field->default && $field->not_null) {
1131+
if ($field->not_null) {
11321132
$definition .= ' ON CONFLICT REPLACE';
11331133
}
1134-
if ( null !== $field->default ) {
1134+
/**
1135+
* The value of DEFAULT can be NULL. PHP would print this as an empty string, so we need a special case for it.
1136+
*/
1137+
if (null === $field->default) {
1138+
$definition .= ' DEFAULT NULL';
1139+
} else if (false !== $field->default) {
11351140
$definition .= ' DEFAULT ' . $field->default;
1141+
} else if ($field->not_null) {
1142+
/**
1143+
* If the column is NOT NULL, we need to provide a default value to match WPDB behavior caused by removing the STRICT_TRANS_TABLES mode.
1144+
*/
1145+
if ('text' === $field->sqlite_data_type) {
1146+
$definition .= ' DEFAULT \'\'';
1147+
} else if (in_array($field->sqlite_data_type, array('integer', 'real'), true)) {
1148+
$definition .= ' DEFAULT 0';
1149+
}
11361150
}
11371151

11381152
/*

0 commit comments

Comments
 (0)