diff --git a/src/Database/Database.php b/src/Database/Database.php index a95d7a12b..eb1f9c0d3 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1306,7 +1306,10 @@ public function createCollection(string $id, array $attributes = [], array $inde $attributes, $this->adapter->getMaxIndexLength(), $this->adapter->getInternalIndexesKeys(), - $this->adapter->getSupportForIndexArray() + $this->adapter->getSupportForIndexArray(), + $this->adapter->getSupportForSpatialAttributes(), + $this->adapter->getSupportForSpatialIndexNull(), + $this->adapter->getSupportForSpatialIndexOrder(), ); foreach ($indexes as $index) { if (!$validator->isValid($index)) { @@ -2251,7 +2254,10 @@ public function updateAttribute(string $collection, string $id, ?string $type = $attributes, $this->adapter->getMaxIndexLength(), $this->adapter->getInternalIndexesKeys(), - $this->adapter->getSupportForIndexArray() + $this->adapter->getSupportForIndexArray(), + $this->adapter->getSupportForSpatialAttributes(), + $this->adapter->getSupportForSpatialIndexNull(), + $this->adapter->getSupportForSpatialIndexOrder(), ); foreach ($indexes as $index) { @@ -3191,7 +3197,10 @@ public function createIndex(string $collection, string $id, string $type, array $collection->getAttribute('attributes', []), $this->adapter->getMaxIndexLength(), $this->adapter->getInternalIndexesKeys(), - $this->adapter->getSupportForIndexArray() + $this->adapter->getSupportForIndexArray(), + $this->adapter->getSupportForSpatialAttributes(), + $this->adapter->getSupportForSpatialIndexNull(), + $this->adapter->getSupportForSpatialIndexOrder(), ); if (!$validator->isValid($index)) { throw new IndexException($validator->getDescription()); diff --git a/src/Database/Validator/Index.php b/src/Database/Validator/Index.php index 2c1337c77..87fa51e78 100644 --- a/src/Database/Validator/Index.php +++ b/src/Database/Validator/Index.php @@ -24,18 +24,30 @@ class Index extends Validator protected bool $arrayIndexSupport; + protected bool $spatialIndexSupport; + + protected bool $spatialIndexNullSupport; + + protected bool $spatialIndexOrderSupport; + /** * @param array $attributes * @param int $maxLength * @param array $reservedKeys * @param bool $arrayIndexSupport + * @param bool $spatialIndexSupport + * @param bool $spatialIndexNullSupport + * @param bool $spatialIndexOrderSupport * @throws DatabaseException */ - public function __construct(array $attributes, int $maxLength, array $reservedKeys = [], bool $arrayIndexSupport = false) + public function __construct(array $attributes, int $maxLength, array $reservedKeys = [], bool $arrayIndexSupport = false, bool $spatialIndexSupport = false, bool $spatialIndexNullSupport = false, bool $spatialIndexOrderSupport = false) { $this->maxLength = $maxLength; $this->reservedKeys = $reservedKeys; $this->arrayIndexSupport = $arrayIndexSupport; + $this->spatialIndexSupport = $spatialIndexSupport; + $this->spatialIndexNullSupport = $spatialIndexNullSupport; + $this->spatialIndexOrderSupport = $spatialIndexOrderSupport; foreach ($attributes as $attribute) { $key = \strtolower($attribute->getAttribute('key', $attribute->getAttribute('$id'))); @@ -289,6 +301,10 @@ public function isValid($value): bool return false; } + if (!$this->checkSpatialIndex($value)) { + return false; + } + return true; } @@ -315,4 +331,47 @@ public function getType(): string { return self::TYPE_OBJECT; } + + /** + * @param Document $index + * @return bool + */ + public function checkSpatialIndex(Document $index): bool + { + $type = $index->getAttribute('type'); + if ($type !== Database::INDEX_SPATIAL) { + return true; + } + + if (!$this->spatialIndexSupport) { + $this->message = 'Spatial indexes are not supported'; + return false; + } + + $attributes = $index->getAttribute('attributes', []); + $orders = $index->getAttribute('orders', []); + + foreach ($attributes as $attributeName) { + $attribute = $this->attributes[\strtolower($attributeName)] ?? new Document(); + $attributeType = $attribute->getAttribute('type', ''); + + if (!\in_array($attributeType, Database::SPATIAL_TYPES, true)) { + $this->message = 'Spatial index can only be created on spatial attributes (point, linestring, polygon). Attribute "' . $attributeName . '" is of type "' . $attributeType . '"'; + return false; + } + + $required = (bool) $attribute->getAttribute('required', false); + if (!$required && !$this->spatialIndexNullSupport) { + $this->message = 'Spatial indexes do not allow null values. Mark the attribute "' . $attributeName . '" as required or create the index on a column with no null values.'; + return false; + } + } + + if (!empty($orders) && !$this->spatialIndexOrderSupport) { + $this->message = 'Spatial indexes with explicit orders are not supported. Remove the orders to create this index.'; + return false; + } + + return true; + } }