Skip to content

Commit 3a5c48c

Browse files
authored
fix: query() returned null instead of 0 for statements affecting 0 rows (#325)
### Summary Fixes #322 WP_SQLite_Driver::query() returned null instead of 0 for statements affecting zero rows (e.g., DELETE FROM x WHERE id = 1 when no matching row exists). This caused wpdb::query() to also return null, breaking its documented contract of returning int|bool. ### Problem In WP_SQLite_Driver::query(), the return logic for non-SELECT queries was: 1. rowCount() > 0 - return row count 2. Otherwise - return null This meant any DELETE, UPDATE, INSERT statement with 0 affected rows returned null instead of 0. ### Fix Simplified the logic to always return rowCount() for non-SELECT statements. DELETE / UPDATE / INSERT will now correctly returns 0 instead of null when no rows affected. CREATE / ALTER / DROP / TRUNCATE now returns 0 instead of null, but wp-includes/sqlite/class-wp-sqlite-db.php never reads this value for these queries (it returns true unconditionally at line 448-449) ### Testing - Added testDeleteReturnsZeroAffectedRowsWhenNoMatchingRows - verifies DELETE returns 0 when no rows match. - Added testUpdateReturnsZeroAffectedRowsWhenNoMatchingRows - verifies UPDATE returns 0 when no rows match. - Updated existing test assertions from assertNull to assertSame( 0, ... ) to reflect the corrected behaviour - Full test suite passes (777 tests)
2 parents c92910c + cef3f97 commit 3a5c48c

3 files changed

Lines changed: 51 additions & 28 deletions

File tree

tests/WP_SQLite_Driver_Metadata_Tests.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ public function testTruncateTable() {
719719
'TRUNCATE TABLE wp_comments;'
720720
);
721721
$actual = $this->engine->get_query_results();
722-
$this->assertNull( $actual );
722+
$this->assertSame( 0, $actual );
723723
$this->assertTableEmpty( 'wp_comments', true );
724724
}
725725

tests/WP_SQLite_Driver_Tests.php

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ public function testCreateTable() {
920920
KEY user_email (user_email)
921921
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci"
922922
);
923-
$this->assertNull( $result );
923+
$this->assertSame( 0, $result );
924924

925925
$this->assertQuery( 'DESCRIBE wptests_users;' );
926926
$results = $this->engine->get_query_results();
@@ -1018,7 +1018,7 @@ public function testCreateTableWithTrailingComma() {
10181018
PRIMARY KEY (ID)
10191019
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci'
10201020
);
1021-
$this->assertNull( $result );
1021+
$this->assertSame( 0, $result );
10221022
}
10231023

10241024
public function testCreateTableSpatialIndex() {
@@ -1028,7 +1028,7 @@ public function testCreateTableSpatialIndex() {
10281028
UNIQUE KEY (ID)
10291029
)'
10301030
);
1031-
$this->assertNull( $result );
1031+
$this->assertSame( 0, $result );
10321032
}
10331033

10341034
public function testCreateTableWithMultiValueColumnTypeModifiers() {
@@ -1041,7 +1041,7 @@ enum_column ENUM('a', 'b', 'c') NOT NULL DEFAULT 'a',
10411041
PRIMARY KEY (ID)
10421042
)"
10431043
);
1044-
$this->assertNull( $result );
1044+
$this->assertSame( 0, $result );
10451045

10461046
$this->assertQuery( 'DESCRIBE wptests_users;' );
10471047
$results = $this->engine->get_query_results();
@@ -1090,10 +1090,10 @@ public function testAlterTableAddAndDropColumn() {
10901090
name varchar(20) NOT NULL default ''
10911091
);"
10921092
);
1093-
$this->assertNull( $result );
1093+
$this->assertSame( 0, $result );
10941094

10951095
$result = $this->assertQuery( 'ALTER TABLE _tmp_table ADD COLUMN `column` int;' );
1096-
$this->assertNull( $result );
1096+
$this->assertSame( 0, $result );
10971097

10981098
$this->assertQuery( 'DESCRIBE _tmp_table;' );
10991099
$results = $this->engine->get_query_results();
@@ -1120,7 +1120,7 @@ public function testAlterTableAddAndDropColumn() {
11201120
);
11211121

11221122
$result = $this->assertQuery( 'ALTER TABLE _tmp_table ADD `column2` int;' );
1123-
$this->assertNull( $result );
1123+
$this->assertSame( 0, $result );
11241124

11251125
$this->assertQuery( 'DESCRIBE _tmp_table;' );
11261126
$results = $this->engine->get_query_results();
@@ -1155,7 +1155,7 @@ public function testAlterTableAddAndDropColumn() {
11551155
);
11561156

11571157
$result = $this->assertQuery( 'ALTER TABLE _tmp_table DROP COLUMN `column`;' );
1158-
$this->assertNull( $result );
1158+
$this->assertSame( 0, $result );
11591159

11601160
$this->assertQuery( 'DESCRIBE _tmp_table;' );
11611161
$results = $this->engine->get_query_results();
@@ -1182,7 +1182,7 @@ public function testAlterTableAddAndDropColumn() {
11821182
);
11831183

11841184
$result = $this->assertQuery( 'ALTER TABLE _tmp_table DROP `column2`;' );
1185-
$this->assertNull( $result );
1185+
$this->assertSame( 0, $result );
11861186

11871187
$this->assertQuery( 'DESCRIBE _tmp_table;' );
11881188
$results = $this->engine->get_query_results();
@@ -1209,7 +1209,7 @@ public function testAlterTableAddNotNullVarcharColumn() {
12091209
);
12101210

12111211
$result = $this->assertQuery( "ALTER TABLE _tmp_table ADD COLUMN `column` VARCHAR(20) NOT NULL DEFAULT 'foo';" );
1212-
$this->assertNull( $result );
1212+
$this->assertSame( 0, $result );
12131213

12141214
$this->assertQuery( 'DESCRIBE _tmp_table;' );
12151215
$results = $this->engine->get_query_results();
@@ -1809,7 +1809,7 @@ public function testAlterTableAddIndex() {
18091809
);
18101810

18111811
$result = $this->assertQuery( 'ALTER TABLE _tmp_table ADD INDEX name (name);' );
1812-
$this->assertNull( $result );
1812+
$this->assertSame( 0, $result );
18131813

18141814
// Verify that the index was created in the information schema.
18151815
$this->assertQuery( 'SHOW INDEX FROM _tmp_table;' );
@@ -1862,7 +1862,7 @@ public function testAlterTableAddUniqueIndex() {
18621862
);
18631863

18641864
$result = $this->assertQuery( 'ALTER TABLE _tmp_table ADD UNIQUE INDEX name (name(20));' );
1865-
$this->assertNull( $result );
1865+
$this->assertSame( 0, $result );
18661866

18671867
// Verify that the index was created in the information schema.
18681868
$this->assertQuery( 'SHOW INDEX FROM _tmp_table;' );
@@ -1915,7 +1915,7 @@ public function testAlterTableAddFulltextIndex() {
19151915
);
19161916

19171917
$result = $this->assertQuery( 'ALTER TABLE _tmp_table ADD FULLTEXT INDEX name (name);' );
1918-
$this->assertNull( $result );
1918+
$this->assertSame( 0, $result );
19191919

19201920
// Verify that the index was created in the information schema.
19211921
$this->assertQuery( 'SHOW INDEX FROM _tmp_table;' );
@@ -2038,7 +2038,7 @@ public function testAlterTableModifyColumn() {
20382038

20392039
// Rename the "name" field to "firstname":
20402040
$result = $this->engine->query( "ALTER TABLE _tmp_table CHANGE column name firstname varchar(50) NOT NULL default 'mark';" );
2041-
$this->assertNull( $result );
2041+
$this->assertSame( 0, $result );
20422042

20432043
// Confirm the original data is still there:
20442044
$result = $this->engine->query( 'SELECT * FROM _tmp_table;' );
@@ -2108,7 +2108,7 @@ public function testAlterTableModifyColumnWithSkippedColumnKeyword() {
21082108

21092109
// Rename the "name" field to "firstname":
21102110
$result = $this->engine->query( "ALTER TABLE _tmp_table CHANGE name firstname varchar(50) NOT NULL default 'mark';" );
2111-
$this->assertNull( $result );
2111+
$this->assertSame( 0, $result );
21122112

21132113
// Confirm the original data is still there:
21142114
$result = $this->engine->query( 'SELECT * FROM _tmp_table;' );
@@ -2149,12 +2149,12 @@ public function testAlterTableModifyColumnWithHyphens() {
21492149
`foo-bar` varchar(255) DEFAULT NULL
21502150
)'
21512151
);
2152-
$this->assertNull( $result );
2152+
$this->assertSame( 0, $result );
21532153

21542154
$result = $this->assertQuery(
21552155
'ALTER TABLE wptests_dbdelta_test2 CHANGE COLUMN `foo-bar` `foo-bar` text DEFAULT NULL'
21562156
);
2157-
$this->assertNull( $result );
2157+
$this->assertSame( 0, $result );
21582158

21592159
$result = $this->assertQuery( 'DESCRIBE wptests_dbdelta_test2;' );
21602160
$this->assertNotFalse( $result );
@@ -2183,19 +2183,19 @@ public function testAlterTableModifyColumnComplexChange() {
21832183
PRIMARY KEY (ID, name)
21842184
);"
21852185
);
2186-
$this->assertNull( $result );
2186+
$this->assertSame( 0, $result );
21872187

21882188
// Add a unique index
21892189
$result = $this->assertQuery(
21902190
'ALTER TABLE _tmp_table ADD UNIQUE INDEX "test_unique_composite" (name, lastname);'
21912191
);
2192-
$this->assertNull( $result );
2192+
$this->assertSame( 0, $result );
21932193

21942194
// Add a regular index
21952195
$result = $this->assertQuery(
21962196
'ALTER TABLE _tmp_table ADD INDEX "test_regular" (lastname);'
21972197
);
2198-
$this->assertNull( $result );
2198+
$this->assertSame( 0, $result );
21992199

22002200
// Confirm the table is well-behaved so far:
22012201

@@ -2236,10 +2236,10 @@ public function testAlterTableModifyColumnComplexChange() {
22362236

22372237
// Now – let's change a few columns:
22382238
$result = $this->engine->query( 'ALTER TABLE _tmp_table CHANGE COLUMN name firstname varchar(20)' );
2239-
$this->assertNull( $result );
2239+
$this->assertSame( 0, $result );
22402240

22412241
$result = $this->engine->query( 'ALTER TABLE _tmp_table CHANGE COLUMN date_as_string datetime datetime NOT NULL' );
2242-
$this->assertNull( $result );
2242+
$this->assertSame( 0, $result );
22432243

22442244
// Finally, let's confirm our data is intact and the table is still well-behaved:
22452245
$result = $this->engine->query( 'SELECT * FROM _tmp_table ORDER BY ID;' );
@@ -2283,7 +2283,7 @@ public function testCaseInsensitiveUniqueIndex() {
22832283
UNIQUE KEY last (lastname)
22842284
);"
22852285
);
2286-
$this->assertNull( $result );
2286+
$this->assertSame( 0, $result );
22872287

22882288
$result1 = $this->engine->query( "INSERT INTO _tmp_table (name, lastname) VALUES ('first', 'last');" );
22892289
$this->assertEquals( 1, $result1 );
@@ -3342,6 +3342,31 @@ public function testTranslatesComplexDelete() {
33423342
);
33433343
}
33443344

3345+
public function testDeleteReturnsZeroAffectedRowsWhenNoMatchingRows() {
3346+
$this->assertQuery( 'CREATE TABLE t (id INT)' );
3347+
$this->assertQuery( 'INSERT INTO t (id) VALUES (1)' );
3348+
3349+
$result = $this->assertQuery( 'DELETE FROM t WHERE id = 1' );
3350+
$this->assertSame( 1, $result );
3351+
$this->assertSame( 1, $this->engine->get_last_return_value() );
3352+
3353+
$result = $this->assertQuery( 'DELETE FROM t WHERE id = 1' );
3354+
$this->assertSame( 0, $result );
3355+
$this->assertSame( 0, $this->engine->get_last_return_value() );
3356+
}
3357+
3358+
public function testUpdateReturnsZeroAffectedRowsWhenNoMatchingRows() {
3359+
$this->assertQuery( 'CREATE TABLE t (id INT, val TEXT)' );
3360+
$this->assertQuery( "INSERT INTO t (id, val) VALUES (1, 'a')" );
3361+
3362+
$result = $this->assertQuery( "UPDATE t SET val = 'b' WHERE id = 1" );
3363+
$this->assertSame( 1, $result );
3364+
3365+
$result = $this->assertQuery( "UPDATE t SET val = 'c' WHERE id = 999" );
3366+
$this->assertSame( 0, $result );
3367+
$this->assertSame( 0, $this->engine->get_last_return_value() );
3368+
}
3369+
33453370
public function testTranslatesDoubleAlterTable() {
33463371
$result = $this->assertQuery(
33473372
'ALTER TABLE _options
@@ -3350,7 +3375,7 @@ public function testTranslatesDoubleAlterTable() {
33503375
ADD INDEX test_index2(option_name(140),option_value(51))
33513376
'
33523377
);
3353-
$this->assertNull( $result );
3378+
$this->assertSame( 0, $result );
33543379

33553380
$result = $this->assertQuery(
33563381
'SHOW INDEX FROM _options'

wp-includes/sqlite-ast/class-wp-sqlite-driver.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,8 @@ public function query( string $query, $fetch_mode = PDO::FETCH_OBJ, ...$fetch_mo
161161

162162
if ( $stmt->columnCount() > 0 ) {
163163
$this->last_result = $stmt->fetchAll( $fetch_mode );
164-
} elseif ( $stmt->rowCount() > 0 ) {
165-
$this->last_result = $stmt->rowCount();
166164
} else {
167-
$this->last_result = null;
165+
$this->last_result = $stmt->rowCount();
168166
}
169167
return $this->last_result;
170168
}

0 commit comments

Comments
 (0)