Skip to content

Commit 090210d

Browse files
abnegateclaude
andcommitted
DAT-1076: Add Capability enum and supports() method to replace getSupportFor* methods
- Create Capability enum with all existing capability types (54 capabilities) - Create NotSupported exception class for cleaner error handling - Add abstract supports() method to Adapter base class - Add requireSupport() helper method that throws NotSupported when capability is missing - Add getAdapterName() abstract method for error messages - Implement supports() method in SQL, MariaDB, MySQL, SQLite, Postgres, Mongo, and Pool adapters - Add supports() wrapper method to Database class This provides a unified API for checking adapter capabilities: if (!$this->supports(Capability::FullTextIndex)) { throw new NotSupported(Capability::FullTextIndex->value, $this->getAdapterName()); } Or using the helper method: $this->requireSupport(Capability::FullTextIndex); The existing getSupportFor* methods are preserved for backward compatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5339475 commit 090210d

11 files changed

Lines changed: 260 additions & 0 deletions

File tree

src/Database/Adapter.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Utopia\Database\Exception\Conflict as ConflictException;
99
use Utopia\Database\Exception\Duplicate as DuplicateException;
1010
use Utopia\Database\Exception\Limit as LimitException;
11+
use Utopia\Database\Exception\NotSupported as NotSupportedException;
1112
use Utopia\Database\Exception\Relationship as RelationshipException;
1213
use Utopia\Database\Exception\Restricted as RestrictedException;
1314
use Utopia\Database\Exception\Timeout as TimeoutException;
@@ -1519,4 +1520,32 @@ public function getSupportForRegex(): bool
15191520
{
15201521
return $this->getSupportForPCRERegex() || $this->getSupportForPOSIXRegex();
15211522
}
1523+
1524+
/**
1525+
* Get the adapter name for error messages
1526+
*
1527+
* @return string
1528+
*/
1529+
abstract public function getAdapterName(): string;
1530+
1531+
/**
1532+
* Check if the adapter supports a specific capability
1533+
*
1534+
* @param Capability $capability
1535+
* @return bool
1536+
*/
1537+
abstract public function supports(Capability $capability): bool;
1538+
1539+
/**
1540+
* Require that a capability is supported, throwing an exception if not
1541+
*
1542+
* @param Capability $capability
1543+
* @throws NotSupportedException
1544+
*/
1545+
public function requireSupport(Capability $capability): void
1546+
{
1547+
if (!$this->supports($capability)) {
1548+
throw new NotSupportedException($capability->value, $this->getAdapterName());
1549+
}
1550+
}
15221551
}

src/Database/Adapter/MariaDB.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,4 +2283,9 @@ public function getSupportForPOSIXRegex(): bool
22832283
{
22842284
return false;
22852285
}
2286+
2287+
public function getAdapterName(): string
2288+
{
2289+
return 'MariaDB';
2290+
}
22862291
}

src/Database/Adapter/Mongo.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use MongoDB\BSON\UTCDateTime;
88
use stdClass;
99
use Utopia\Database\Adapter;
10+
use Utopia\Database\Capability;
1011
use Utopia\Database\Change;
1112
use Utopia\Database\Database;
1213
use Utopia\Database\DateTime;
@@ -3467,4 +3468,62 @@ public function getSupportForTrigramIndex(): bool
34673468
{
34683469
return false;
34693470
}
3471+
3472+
public function getAdapterName(): string
3473+
{
3474+
return 'MongoDB';
3475+
}
3476+
3477+
public function supports(Capability $capability): bool
3478+
{
3479+
return match ($capability) {
3480+
Capability::Schemas => $this->getSupportForSchemas(),
3481+
Capability::Attributes => $this->getSupportForAttributes(),
3482+
Capability::SchemaAttributes => $this->getSupportForSchemaAttributes(),
3483+
Capability::Index => $this->getSupportForIndex(),
3484+
Capability::IndexArray => $this->getSupportForIndexArray(),
3485+
Capability::CastIndexArray => $this->getSupportForCastIndexArray(),
3486+
Capability::UniqueIndex => $this->getSupportForUniqueIndex(),
3487+
Capability::FulltextIndex => $this->getSupportForFulltextIndex(),
3488+
Capability::FulltextWildcardIndex => $this->getSupportForFulltextWildcardIndex(),
3489+
Capability::MultipleFulltextIndexes => $this->getSupportForMultipleFulltextIndexes(),
3490+
Capability::TrigramIndex => $this->getSupportForTrigramIndex(),
3491+
Capability::IdenticalIndexes => $this->getSupportForIdenticalIndexes(),
3492+
Capability::Casting => $this->getSupportForCasting(),
3493+
Capability::NumericCasting => false,
3494+
Capability::InternalCasting => $this->getSupportForInternalCasting(),
3495+
Capability::UTCCasting => $this->getSupportForUTCCasting(),
3496+
Capability::QueryContains => $this->getSupportForQueryContains(),
3497+
Capability::JSONOverlaps => false,
3498+
Capability::Timeouts => $this->getSupportForTimeouts(),
3499+
Capability::Relationships => $this->getSupportForRelationships(),
3500+
Capability::UpdateLock => $this->getSupportForUpdateLock(),
3501+
Capability::BatchOperations => $this->getSupportForBatchOperations(),
3502+
Capability::AttributeResizing => $this->getSupportForAttributeResizing(),
3503+
Capability::GetConnectionId => $this->getSupportForGetConnectionId(),
3504+
Capability::Upserts => $this->getSupportForUpserts(),
3505+
Capability::Vectors => $this->getSupportForVectors(),
3506+
Capability::CacheSkipOnFailure => $this->getSupportForCacheSkipOnFailure(),
3507+
Capability::Reconnection => $this->getSupportForReconnection(),
3508+
Capability::Hostname => $this->getSupportForHostname(),
3509+
Capability::BatchCreateAttributes => $this->getSupportForBatchCreateAttributes(),
3510+
Capability::SpatialAttributes => $this->getSupportForSpatialAttributes(),
3511+
Capability::SpatialIndexNull => $this->getSupportForSpatialIndexNull(),
3512+
Capability::SpatialIndexOrder => $this->getSupportForSpatialIndexOrder(),
3513+
Capability::SpatialAxisOrder => $this->getSupportForSpatialAxisOrder(),
3514+
Capability::OptionalSpatialAttributeWithExistingRows => $this->getSupportForOptionalSpatialAttributeWithExistingRows(),
3515+
Capability::BoundaryInclusiveContains => $this->getSupportForBoundaryInclusiveContains(),
3516+
Capability::DistanceBetweenMultiDimensionGeometryInMeters => $this->getSupportForDistanceBetweenMultiDimensionGeometryInMeters(),
3517+
Capability::Object => $this->getSupportForObject(),
3518+
Capability::ObjectIndexes => $this->getSupportForObjectIndexes(),
3519+
Capability::Operators => $this->getSupportForOperators(),
3520+
Capability::OrderRandom => $this->getSupportForOrderRandom(),
3521+
Capability::AlterLocks => $this->getSupportForAlterLocks(),
3522+
Capability::NonUtfCharacters => $this->getSupportNonUtfCharacters(),
3523+
Capability::IntegerBooleans => $this->getSupportForIntegerBooleans(),
3524+
Capability::PCRERegex => $this->getSupportForPCRERegex(),
3525+
Capability::POSIXRegex => $this->getSupportForPOSIXRegex(),
3526+
Capability::Regex => $this->getSupportForRegex(),
3527+
};
3528+
}
34703529
}

src/Database/Adapter/MySQL.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,4 +319,9 @@ protected function getOperatorSQL(string $column, \Utopia\Database\Operator $ope
319319
// For all other operators, use parent implementation
320320
return parent::getOperatorSQL($column, $operator, $bindIndex);
321321
}
322+
323+
public function getAdapterName(): string
324+
{
325+
return 'MySQL';
326+
}
322327
}

src/Database/Adapter/Pool.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Utopia\Database\Adapter;
44

55
use Utopia\Database\Adapter;
6+
use Utopia\Database\Capability;
67
use Utopia\Database\Database;
78
use Utopia\Database\Document;
89
use Utopia\Database\Exception as DatabaseException;
@@ -642,4 +643,14 @@ public function getSupportNonUtfCharacters(): bool
642643
{
643644
return $this->delegate(__FUNCTION__, \func_get_args());
644645
}
646+
647+
public function getAdapterName(): string
648+
{
649+
return $this->delegate(__FUNCTION__, \func_get_args());
650+
}
651+
652+
public function supports(Capability $capability): bool
653+
{
654+
return $this->delegate(__FUNCTION__, \func_get_args());
655+
}
645656
}

src/Database/Adapter/Postgres.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2842,4 +2842,9 @@ protected function getSQLTable(string $name): string
28422842

28432843
return "{$this->quote($this->getDatabase())}.{$this->quote($table)}";
28442844
}
2845+
2846+
public function getAdapterName(): string
2847+
{
2848+
return 'PostgreSQL';
2849+
}
28452850
}

src/Database/Adapter/SQL.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PDOException;
77
use Swoole\Database\PDOStatementProxy;
88
use Utopia\Database\Adapter;
9+
use Utopia\Database\Capability;
910
use Utopia\Database\Change;
1011
use Utopia\Database\Database;
1112
use Utopia\Database\DateTime;
@@ -3574,4 +3575,62 @@ public function getLockType(): string
35743575

35753576
return '';
35763577
}
3578+
3579+
public function getAdapterName(): string
3580+
{
3581+
return 'SQL';
3582+
}
3583+
3584+
public function supports(Capability $capability): bool
3585+
{
3586+
return match ($capability) {
3587+
Capability::Schemas => $this->getSupportForSchemas(),
3588+
Capability::Attributes => $this->getSupportForAttributes(),
3589+
Capability::SchemaAttributes => $this->getSupportForSchemaAttributes(),
3590+
Capability::Index => $this->getSupportForIndex(),
3591+
Capability::IndexArray => $this->getSupportForIndexArray(),
3592+
Capability::CastIndexArray => $this->getSupportForCastIndexArray(),
3593+
Capability::UniqueIndex => $this->getSupportForUniqueIndex(),
3594+
Capability::FulltextIndex => $this->getSupportForFulltextIndex(),
3595+
Capability::FulltextWildcardIndex => $this->getSupportForFulltextWildcardIndex(),
3596+
Capability::MultipleFulltextIndexes => $this->getSupportForMultipleFulltextIndexes(),
3597+
Capability::TrigramIndex => $this->getSupportForTrigramIndex(),
3598+
Capability::IdenticalIndexes => $this->getSupportForIdenticalIndexes(),
3599+
Capability::Casting => $this->getSupportForCasting(),
3600+
Capability::NumericCasting => $this->getSupportForNumericCasting(),
3601+
Capability::InternalCasting => $this->getSupportForInternalCasting(),
3602+
Capability::UTCCasting => $this->getSupportForUTCCasting(),
3603+
Capability::QueryContains => $this->getSupportForQueryContains(),
3604+
Capability::JSONOverlaps => $this->getSupportForJSONOverlaps(),
3605+
Capability::Timeouts => $this->getSupportForTimeouts(),
3606+
Capability::Relationships => $this->getSupportForRelationships(),
3607+
Capability::UpdateLock => $this->getSupportForUpdateLock(),
3608+
Capability::BatchOperations => $this->getSupportForBatchOperations(),
3609+
Capability::AttributeResizing => $this->getSupportForAttributeResizing(),
3610+
Capability::GetConnectionId => $this->getSupportForGetConnectionId(),
3611+
Capability::Upserts => $this->getSupportForUpserts(),
3612+
Capability::Vectors => $this->getSupportForVectors(),
3613+
Capability::CacheSkipOnFailure => $this->getSupportForCacheSkipOnFailure(),
3614+
Capability::Reconnection => $this->getSupportForReconnection(),
3615+
Capability::Hostname => $this->getSupportForHostname(),
3616+
Capability::BatchCreateAttributes => $this->getSupportForBatchCreateAttributes(),
3617+
Capability::SpatialAttributes => $this->getSupportForSpatialAttributes(),
3618+
Capability::SpatialIndexNull => $this->getSupportForSpatialIndexNull(),
3619+
Capability::SpatialIndexOrder => $this->getSupportForSpatialIndexOrder(),
3620+
Capability::SpatialAxisOrder => $this->getSupportForSpatialAxisOrder(),
3621+
Capability::OptionalSpatialAttributeWithExistingRows => $this->getSupportForOptionalSpatialAttributeWithExistingRows(),
3622+
Capability::BoundaryInclusiveContains => $this->getSupportForBoundaryInclusiveContains(),
3623+
Capability::DistanceBetweenMultiDimensionGeometryInMeters => $this->getSupportForDistanceBetweenMultiDimensionGeometryInMeters(),
3624+
Capability::Object => $this->getSupportForObject(),
3625+
Capability::ObjectIndexes => $this->getSupportForObjectIndexes(),
3626+
Capability::Operators => $this->getSupportForOperators(),
3627+
Capability::OrderRandom => $this->getSupportForOrderRandom(),
3628+
Capability::AlterLocks => $this->getSupportForAlterLocks(),
3629+
Capability::NonUtfCharacters => $this->getSupportNonUtfCharacters(),
3630+
Capability::IntegerBooleans => $this->getSupportForIntegerBooleans(),
3631+
Capability::PCRERegex => $this->getSupportForPCRERegex(),
3632+
Capability::POSIXRegex => $this->getSupportForPOSIXRegex(),
3633+
Capability::Regex => $this->getSupportForRegex(),
3634+
};
3635+
}
35773636
}

src/Database/Adapter/SQLite.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,4 +1913,9 @@ public function getSupportForPOSIXRegex(): bool
19131913
{
19141914
return false;
19151915
}
1916+
1917+
public function getAdapterName(): string
1918+
{
1919+
return 'SQLite';
1920+
}
19161921
}

src/Database/Capability.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Utopia\Database;
4+
5+
/**
6+
* Enum representing database adapter capabilities.
7+
* Used to check if an adapter supports a specific feature.
8+
*/
9+
enum Capability: string
10+
{
11+
case Schemas = 'schemas';
12+
case Attributes = 'attributes';
13+
case SchemaAttributes = 'schema_attributes';
14+
case Index = 'index';
15+
case IndexArray = 'index_array';
16+
case CastIndexArray = 'cast_index_array';
17+
case UniqueIndex = 'unique_index';
18+
case FulltextIndex = 'fulltext_index';
19+
case FulltextWildcardIndex = 'fulltext_wildcard_index';
20+
case MultipleFulltextIndexes = 'multiple_fulltext_indexes';
21+
case TrigramIndex = 'trigram_index';
22+
case IdenticalIndexes = 'identical_indexes';
23+
case Casting = 'casting';
24+
case NumericCasting = 'numeric_casting';
25+
case InternalCasting = 'internal_casting';
26+
case UTCCasting = 'utc_casting';
27+
case QueryContains = 'query_contains';
28+
case JSONOverlaps = 'json_overlaps';
29+
case Timeouts = 'timeouts';
30+
case Relationships = 'relationships';
31+
case UpdateLock = 'update_lock';
32+
case BatchOperations = 'batch_operations';
33+
case AttributeResizing = 'attribute_resizing';
34+
case GetConnectionId = 'get_connection_id';
35+
case Upserts = 'upserts';
36+
case Vectors = 'vectors';
37+
case CacheSkipOnFailure = 'cache_skip_on_failure';
38+
case Reconnection = 'reconnection';
39+
case Hostname = 'hostname';
40+
case BatchCreateAttributes = 'batch_create_attributes';
41+
case SpatialAttributes = 'spatial_attributes';
42+
case SpatialIndexNull = 'spatial_index_null';
43+
case SpatialIndexOrder = 'spatial_index_order';
44+
case SpatialAxisOrder = 'spatial_axis_order';
45+
case OptionalSpatialAttributeWithExistingRows = 'optional_spatial_attribute_with_existing_rows';
46+
case BoundaryInclusiveContains = 'boundary_inclusive_contains';
47+
case DistanceBetweenMultiDimensionGeometryInMeters = 'distance_between_multi_dimension_geometry_in_meters';
48+
case Object = 'object';
49+
case ObjectIndexes = 'object_indexes';
50+
case Operators = 'operators';
51+
case OrderRandom = 'order_random';
52+
case AlterLocks = 'alter_locks';
53+
case NonUtfCharacters = 'non_utf_characters';
54+
case IntegerBooleans = 'integer_booleans';
55+
case PCRERegex = 'pcre_regex';
56+
case POSIXRegex = 'posix_regex';
57+
case Regex = 'regex';
58+
}

src/Database/Database.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,17 @@ public function getAdapter(): Adapter
14931493
return $this->adapter;
14941494
}
14951495

1496+
/**
1497+
* Check if the adapter supports a specific capability
1498+
*
1499+
* @param Capability $capability
1500+
* @return bool
1501+
*/
1502+
public function supports(Capability $capability): bool
1503+
{
1504+
return $this->adapter->supports($capability);
1505+
}
1506+
14961507
/**
14971508
* Run a callback inside a transaction.
14981509
*

0 commit comments

Comments
 (0)