Skip to content

Commit f6c4ff0

Browse files
committed
fix: support isNull/isNotNull queries on spatial attributes
MariaDB and Postgres adapters threw "Unknown spatial query method" for any non-spatial query method (e.g. isNull/isNotNull) against a spatial (point/linestring/polygon) attribute, since handleSpatialQueries() only recognized true spatial predicates and threw on anything else. This surfaces whenever a spatial attribute is made optional and later queried for null/not-null, which is a valid and expected use case.
1 parent d5ebecc commit f6c4ff0

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

src/Database/Adapter/MariaDB.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,10 @@ protected function handleSpatialQueries(Query $query, array &$binds, string $att
14431443
$binds[":{$placeholder}_0"] = $this->convertArrayToWKT($query->getValues()[0]);
14441444
return "NOT ST_Contains({$alias}.{$attribute}, " . $this->getSpatialGeomFromText(":{$placeholder}_0", null) . ")";
14451445

1446+
case Query::TYPE_IS_NULL:
1447+
case Query::TYPE_IS_NOT_NULL:
1448+
return "{$alias}.{$attribute} {$this->getSQLOperator($query->getMethod())}";
1449+
14461450
default:
14471451
throw new DatabaseException('Unknown spatial query method: ' . $query->getMethod());
14481452
}

src/Database/Adapter/Postgres.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,10 @@ protected function handleSpatialQueries(Query $query, array &$binds, string $att
15641564
? "NOT ST_Covers({$alias}.{$attribute}, " . $this->getSpatialGeomFromText(":{$placeholder}_0") . ")"
15651565
: "ST_Covers({$alias}.{$attribute}, " . $this->getSpatialGeomFromText(":{$placeholder}_0") . ")";
15661566

1567+
case Query::TYPE_IS_NULL:
1568+
case Query::TYPE_IS_NOT_NULL:
1569+
return "{$alias}.{$attribute} {$this->getSQLOperator($query->getMethod())}";
1570+
15671571
default:
15681572
throw new DatabaseException('Unknown spatial query method: ' . $query->getMethod());
15691573
}

tests/e2e/Adapter/Scopes/SpatialTests.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,53 @@ public function testSpatialQueryCombinations(): void
14771477
}
14781478
}
14791479

1480+
public function testSpatialIsNullIsNotNull(): void
1481+
{
1482+
/** @var Database $database */
1483+
$database = $this->getDatabase();
1484+
if (!$database->getAdapter()->getSupportForSpatialAttributes()) {
1485+
$this->expectNotToPerformAssertions();
1486+
return;
1487+
}
1488+
1489+
$collectionName = 'spatial_null_checks';
1490+
try {
1491+
$database->createCollection($collectionName);
1492+
1493+
$this->assertEquals(true, $database->createAttribute($collectionName, 'name', Database::VAR_STRING, 255, true));
1494+
// Optional spatial attribute: some documents legitimately have no location set.
1495+
$this->assertEquals(true, $database->createAttribute($collectionName, 'location', Database::VAR_POINT, 0, false));
1496+
1497+
$database->createDocument($collectionName, new Document([
1498+
'$id' => 'withLocation',
1499+
'name' => 'Has a location',
1500+
'location' => [40.7829, -73.9654],
1501+
'$permissions' => [Permission::read(Role::any())],
1502+
]));
1503+
1504+
$database->createDocument($collectionName, new Document([
1505+
'$id' => 'withoutLocation',
1506+
'name' => 'No location set',
1507+
'location' => null,
1508+
'$permissions' => [Permission::read(Role::any())],
1509+
]));
1510+
1511+
$withLocation = $database->find($collectionName, [
1512+
Query::isNotNull('location'),
1513+
], Database::PERMISSION_READ);
1514+
$this->assertCount(1, $withLocation);
1515+
$this->assertEquals('withLocation', $withLocation[0]->getId());
1516+
1517+
$withoutLocation = $database->find($collectionName, [
1518+
Query::isNull('location'),
1519+
], Database::PERMISSION_READ);
1520+
$this->assertCount(1, $withoutLocation);
1521+
$this->assertEquals('withoutLocation', $withoutLocation[0]->getId());
1522+
} finally {
1523+
$database->deleteCollection($collectionName);
1524+
}
1525+
}
1526+
14801527
public function testSpatialBulkOperation(): void
14811528
{
14821529
/** @var Database $database */

0 commit comments

Comments
 (0)