From e42c7848c4dba805d4bfbadf95fef51527b93ab7 Mon Sep 17 00:00:00 2001 From: Ambrose Casanova <279373485+ambrose5773@users.noreply.github.com> Date: Fri, 4 Sep 2026 02:55:48 +0000 Subject: [PATCH 1/3] fix: return false from fetchField on empty result SimplePdo::fetchRow() returns null when there are no rows. Guard PdoWrapper::fetchField() so empty queries return false instead of calling getData() on null. Closes #726. --- flight/database/PdoWrapper.php | 5 ++++- tests/PdoWrapperTest.php | 6 ++++++ tests/SimplePdoTest.php | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/flight/database/PdoWrapper.php b/flight/database/PdoWrapper.php index 6f37b25b..4c036cdd 100644 --- a/flight/database/PdoWrapper.php +++ b/flight/database/PdoWrapper.php @@ -91,11 +91,14 @@ public function runQuery(string $sql, array $params = []): PDOStatement * @param string $sql - Ex: "SELECT id FROM table WHERE something = ?" * @param array $params - Ex: [ $something ] * - * @return mixed + * @return mixed|false */ public function fetchField(string $sql, array $params = []) { $result = $this->fetchRow($sql, $params); + if ($result === null || count($result) === 0) { + return false; + } $data = $result->getData(); return reset($data); } diff --git a/tests/PdoWrapperTest.php b/tests/PdoWrapperTest.php index d7e9311b..904d95c9 100644 --- a/tests/PdoWrapperTest.php +++ b/tests/PdoWrapperTest.php @@ -71,6 +71,12 @@ public function testFetchField(): void $this->assertEquals(2, $id); } + public function testFetchFieldReturnsFalseWhenNoResults(): void + { + $id = $this->pdo_wrapper->fetchField('SELECT id FROM test WHERE id = ?', [999]); + $this->assertFalse($id); + } + public function testFetchRow(): void { $row = $this->pdo_wrapper->fetchRow('SELECT * FROM test WHERE name = ?', ['two']); diff --git a/tests/SimplePdoTest.php b/tests/SimplePdoTest.php index 08f8e164..ee416976 100644 --- a/tests/SimplePdoTest.php +++ b/tests/SimplePdoTest.php @@ -468,4 +468,10 @@ public function testFetchFieldReturnsFirstColumn(): void $id = $this->db->fetchField('SELECT id, name FROM users WHERE id = ?', [1]); $this->assertEquals(1, $id); } + + public function testFetchFieldReturnsFalseWhenNoResults(): void + { + $value = $this->db->fetchField('SELECT name FROM users WHERE id = ?', [999]); + $this->assertFalse($value); + } } From 386bdc16a73f6e4e0134b9dffa0ba18dc59dd6a9 Mon Sep 17 00:00:00 2001 From: Ambrose Casanova <279373485+ambrose5773@users.noreply.github.com> Date: Fri, 4 Sep 2026 03:35:12 +0000 Subject: [PATCH 2/3] test: cover fetchField null vs empty vs 0 vs '' Distinguish empty result sets (false) from SQL NULL columns (null), and keep 0 / '' as assertSame on both PdoWrapper and SimplePdo. --- tests/PdoWrapperTest.php | 24 ++++++++++++++++++++++-- tests/SimplePdoTest.php | 26 +++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/tests/PdoWrapperTest.php b/tests/PdoWrapperTest.php index 904d95c9..d3a29287 100644 --- a/tests/PdoWrapperTest.php +++ b/tests/PdoWrapperTest.php @@ -68,13 +68,33 @@ public function testRunQueryDeleteStatement(): void public function testFetchField(): void { $id = $this->pdo_wrapper->fetchField('SELECT id FROM test WHERE name = ?', ['two']); - $this->assertEquals(2, $id); + $this->assertSame(2, $id); } public function testFetchFieldReturnsFalseWhenNoResults(): void { $id = $this->pdo_wrapper->fetchField('SELECT id FROM test WHERE id = ?', [999]); - $this->assertFalse($id); + $this->assertSame(false, $id); + } + + public function testFetchFieldReturnsNullWhenColumnIsSqlNull(): void + { + $this->pdo_wrapper->exec('INSERT INTO test (name) VALUES (NULL)'); + $value = $this->pdo_wrapper->fetchField('SELECT name FROM test WHERE name IS NULL'); + $this->assertNull($value); + } + + public function testFetchFieldReturnsZero(): void + { + $value = $this->pdo_wrapper->fetchField('SELECT 0'); + $this->assertSame(0, $value); + } + + public function testFetchFieldReturnsEmptyString(): void + { + $this->pdo_wrapper->exec('INSERT INTO test (name) VALUES ("")'); + $value = $this->pdo_wrapper->fetchField('SELECT name FROM test WHERE name = ?', ['']); + $this->assertSame('', $value); } public function testFetchRow(): void diff --git a/tests/SimplePdoTest.php b/tests/SimplePdoTest.php index ee416976..c4441af3 100644 --- a/tests/SimplePdoTest.php +++ b/tests/SimplePdoTest.php @@ -460,18 +460,38 @@ public function testTransactionRethrowsException(): void public function testFetchFieldReturnsValue(): void { $name = $this->db->fetchField('SELECT name FROM users WHERE id = ?', [1]); - $this->assertEquals('John', $name); + $this->assertSame('John', $name); } public function testFetchFieldReturnsFirstColumn(): void { $id = $this->db->fetchField('SELECT id, name FROM users WHERE id = ?', [1]); - $this->assertEquals(1, $id); + $this->assertSame(1, $id); } public function testFetchFieldReturnsFalseWhenNoResults(): void { $value = $this->db->fetchField('SELECT name FROM users WHERE id = ?', [999]); - $this->assertFalse($value); + $this->assertSame(false, $value); + } + + public function testFetchFieldReturnsNullWhenColumnIsSqlNull(): void + { + $this->db->exec('INSERT INTO users (name, email) VALUES (NULL, "null@example.com")'); + $value = $this->db->fetchField('SELECT name FROM users WHERE email = ?', ['null@example.com']); + $this->assertNull($value); + } + + public function testFetchFieldReturnsZero(): void + { + $value = $this->db->fetchField('SELECT 0'); + $this->assertSame(0, $value); + } + + public function testFetchFieldReturnsEmptyString(): void + { + $this->db->exec('INSERT INTO users (name, email) VALUES ("", "empty@example.com")'); + $value = $this->db->fetchField('SELECT name FROM users WHERE email = ?', ['empty@example.com']); + $this->assertSame('', $value); } } From 9681cd20c88dcf527545b2d5bb4f76bcb554b7f8 Mon Sep 17 00:00:00 2001 From: Ambrose Casanova <279373485+ambrose5773@users.noreply.github.com> Date: Fri, 4 Sep 2026 03:46:22 +0000 Subject: [PATCH 3/3] test: tolerate PDO numeric strings on PHP < 8.1 assertEquals for integer-ish fetchField values; keep assertSame for false / empty string and assertNull for SQL NULL. --- tests/PdoWrapperTest.php | 6 ++++-- tests/SimplePdoTest.php | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/PdoWrapperTest.php b/tests/PdoWrapperTest.php index d3a29287..132156be 100644 --- a/tests/PdoWrapperTest.php +++ b/tests/PdoWrapperTest.php @@ -68,7 +68,8 @@ public function testRunQueryDeleteStatement(): void public function testFetchField(): void { $id = $this->pdo_wrapper->fetchField('SELECT id FROM test WHERE name = ?', ['two']); - $this->assertSame(2, $id); + // PDO SQLite may return numeric strings on PHP < 8.1 + $this->assertEquals(2, $id); } public function testFetchFieldReturnsFalseWhenNoResults(): void @@ -87,7 +88,8 @@ public function testFetchFieldReturnsNullWhenColumnIsSqlNull(): void public function testFetchFieldReturnsZero(): void { $value = $this->pdo_wrapper->fetchField('SELECT 0'); - $this->assertSame(0, $value); + // PDO SQLite may return '0' on PHP < 8.1 + $this->assertEquals(0, $value); } public function testFetchFieldReturnsEmptyString(): void diff --git a/tests/SimplePdoTest.php b/tests/SimplePdoTest.php index c4441af3..0143381d 100644 --- a/tests/SimplePdoTest.php +++ b/tests/SimplePdoTest.php @@ -466,7 +466,8 @@ public function testFetchFieldReturnsValue(): void public function testFetchFieldReturnsFirstColumn(): void { $id = $this->db->fetchField('SELECT id, name FROM users WHERE id = ?', [1]); - $this->assertSame(1, $id); + // PDO SQLite may return numeric strings on PHP < 8.1 + $this->assertEquals(1, $id); } public function testFetchFieldReturnsFalseWhenNoResults(): void @@ -485,7 +486,8 @@ public function testFetchFieldReturnsNullWhenColumnIsSqlNull(): void public function testFetchFieldReturnsZero(): void { $value = $this->db->fetchField('SELECT 0'); - $this->assertSame(0, $value); + // PDO SQLite may return '0' on PHP < 8.1 + $this->assertEquals(0, $value); } public function testFetchFieldReturnsEmptyString(): void