Skip to content

Commit 4587c19

Browse files
authored
Merge pull request #495 from utopia-php/0.53.x-rename-json-index
Dependency Exception
2 parents d6067ec + e1d5ab5 commit 4587c19

File tree

8 files changed

+101
-34
lines changed

8 files changed

+101
-34
lines changed

src/Database/Adapter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,13 @@ abstract public function getSupportForAttributeResizing(): bool;
868868
*/
869869
abstract public function getSupportForGetConnectionId(): bool;
870870

871+
/**
872+
* Is cast index as array supported?
873+
*
874+
* @return bool
875+
*/
876+
abstract public function getSupportForCastIndexArray(): bool;
877+
871878
/**
872879
* Get current attribute count from collection document
873880
*

src/Database/Adapter/MariaDB.php

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ public function deleteAttribute(string $collection, string $id, bool $array = fa
438438
return true;
439439
}
440440

441-
throw $e;
441+
throw $this->processException($e);
442442
}
443443
}
444444

@@ -462,9 +462,13 @@ public function renameAttribute(string $collection, string $old, string $new): b
462462

463463
$sql = $this->trigger(Database::EVENT_ATTRIBUTE_UPDATE, $sql);
464464

465-
return $this->getPDO()
466-
->prepare($sql)
467-
->execute();
465+
try {
466+
return $this->getPDO()
467+
->prepare($sql)
468+
->execute();
469+
} catch (PDOException $e) {
470+
throw $this->processException($e);
471+
}
468472
}
469473

470474
/**
@@ -766,7 +770,7 @@ public function createIndex(string $collection, string $id, string $type, array
766770

767771
$attributes[$i] = "`{$attr}`{$length} {$order}";
768772

769-
if (!empty($collectionAttribute['array']) && $this->castIndexArray()) {
773+
if (!empty($collectionAttribute['array']) && $this->getSupportForCastIndexArray()) {
770774
$attributes[$i] = '(CAST(' . $attr . ' AS char(' . Database::ARRAY_INDEX_LENGTH . ') ARRAY))';
771775
}
772776
}
@@ -798,14 +802,6 @@ public function createIndex(string $collection, string $id, string $type, array
798802
}
799803
}
800804

801-
/**
802-
* @return bool
803-
*/
804-
public function castIndexArray(): bool
805-
{
806-
return false;
807-
}
808-
809805
/**
810806
* Delete Index
811807
*

src/Database/Adapter/Mongo.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,11 @@ public function getSupportForSchemaAttributes(): bool
17971797
return false;
17981798
}
17991799

1800+
public function getSupportForCastIndexArray(): bool
1801+
{
1802+
return false;
1803+
}
1804+
18001805
/**
18011806
* Get current attribute count from collection document
18021807
*

src/Database/Adapter/MySQL.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PDOException;
66
use Utopia\Database\Database;
77
use Utopia\Database\Exception as DatabaseException;
8+
use Utopia\Database\Exception\Dependency as DependencyException;
89
use Utopia\Database\Exception\Timeout as TimeoutException;
910

1011
class MySQL extends MariaDB
@@ -74,10 +75,7 @@ public function getSizeOfCollectionOnDisk(string $collection): int
7475
return $size;
7576
}
7677

77-
/**
78-
* @return bool
79-
*/
80-
public function castIndexArray(): bool
78+
public function getSupportForCastIndexArray(): bool
8179
{
8280
return true;
8381
}
@@ -89,6 +87,11 @@ protected function processException(PDOException $e): \Exception
8987
return new TimeoutException($e->getMessage(), $e->getCode(), $e);
9088
}
9189

90+
// Functional index dependency
91+
if ($e->getCode() === 'HY000' && isset($e->errorInfo[1]) && $e->errorInfo[1] === 3837) {
92+
return new DependencyException($e->errorInfo[2], $e->getCode(), $e);
93+
}
94+
9295
return parent::processException($e);
9396
}
9497
}

src/Database/Adapter/SQL.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,11 @@ public function getSupportForQueryContains(): bool
846846
*/
847847
abstract public function getSupportForJSONOverlaps(): bool;
848848

849+
public function getSupportForCastIndexArray(): bool
850+
{
851+
return false;
852+
}
853+
849854
public function getSupportForRelationships(): bool
850855
{
851856
return true;

src/Database/Database.php

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,34 +2058,40 @@ public function deleteAttribute(string $collection, string $id): bool
20582058
public function renameAttribute(string $collection, string $old, string $new): bool
20592059
{
20602060
$collection = $this->silent(fn () => $this->getCollection($collection));
2061+
2062+
/**
2063+
* @var array<Document> $attributes
2064+
*/
20612065
$attributes = $collection->getAttribute('attributes', []);
2062-
$indexes = $collection->getAttribute('indexes', []);
20632066

2064-
$attribute = \in_array($old, \array_map(fn ($attribute) => $attribute['$id'], $attributes));
2067+
/**
2068+
* @var array<Document> $indexes
2069+
*/
2070+
$indexes = $collection->getAttribute('indexes', []);
20652071

2066-
if ($attribute === false) {
2067-
throw new NotFoundException('Attribute not found');
2068-
}
2072+
$attribute = new Document();
20692073

2070-
$attributeNew = \in_array($new, \array_map(fn ($attribute) => $attribute['$id'], $attributes));
2074+
foreach ($attributes as $value) {
2075+
if ($value->getId() === $old) {
2076+
$attribute = $value;
2077+
}
20712078

2072-
if ($attributeNew !== false) {
2073-
throw new DuplicateException('Attribute name already used');
2079+
if ($value->getId() === $new) {
2080+
throw new DuplicateException('Attribute name already used');
2081+
}
20742082
}
20752083

2076-
foreach ($attributes as $key => $value) {
2077-
if (isset($value['$id']) && $value['$id'] === $old) {
2078-
$attributes[$key]['key'] = $new;
2079-
$attributes[$key]['$id'] = $new;
2080-
$attributeNew = $attributes[$key];
2081-
break;
2082-
}
2084+
if ($attribute->isEmpty()) {
2085+
throw new NotFoundException('Attribute not found');
20832086
}
20842087

2088+
$attribute->setAttribute('$id', $new);
2089+
$attribute->setAttribute('key', $new);
2090+
20852091
foreach ($indexes as $index) {
20862092
$indexAttributes = $index->getAttribute('attributes', []);
20872093

2088-
$indexAttributes = \array_map(fn ($attribute) => ($attribute === $old) ? $new : $attribute, $indexAttributes);
2094+
$indexAttributes = \array_map(fn ($attr) => ($attr === $old) ? $new : $attr, $indexAttributes);
20892095

20902096
$index->setAttribute('attributes', $indexAttributes);
20912097
}
@@ -2099,7 +2105,7 @@ public function renameAttribute(string $collection, string $old, string $new): b
20992105
$this->silent(fn () => $this->updateDocument(self::METADATA, $collection->getId(), $collection));
21002106
}
21012107

2102-
$this->trigger(self::EVENT_ATTRIBUTE_UPDATE, $attributeNew);
2108+
$this->trigger(self::EVENT_ATTRIBUTE_UPDATE, $attribute);
21032109

21042110
return $renamed;
21052111
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Utopia\Database\Exception;
4+
5+
use Utopia\Database\Exception;
6+
7+
class Dependency extends Exception
8+
{
9+
}

tests/e2e/Adapter/Base.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Utopia\Database\Exception as DatabaseException;
1313
use Utopia\Database\Exception\Authorization as AuthorizationException;
1414
use Utopia\Database\Exception\Conflict as ConflictException;
15+
use Utopia\Database\Exception\Dependency as DependencyException;
1516
use Utopia\Database\Exception\Duplicate as DuplicateException;
1617
use Utopia\Database\Exception\Limit as LimitException;
1718
use Utopia\Database\Exception\Query as QueryException;
@@ -2766,6 +2767,15 @@ public function testArrayAttribute(): void
27662767
array: true
27672768
));
27682769

2770+
$this->assertEquals(true, $database->createAttribute(
2771+
$collection,
2772+
'cards',
2773+
Database::VAR_STRING,
2774+
size: 5000,
2775+
required: false,
2776+
array: true
2777+
));
2778+
27692779
$this->assertEquals(true, $database->createAttribute(
27702780
$collection,
27712781
'numbers',
@@ -2889,6 +2899,32 @@ public function testArrayAttribute(): void
28892899
$this->assertEquals('Antony', $document->getAttribute('names')[1]);
28902900
$this->assertEquals(100, $document->getAttribute('numbers')[1]);
28912901

2902+
/**
2903+
* functional index dependency cannot be dropped or rename
2904+
*/
2905+
$database->createIndex($collection, 'idx_cards', Database::INDEX_KEY, ['cards'], [100]);
2906+
2907+
if ($this->getDatabase()->getAdapter()->getSupportForCastIndexArray()) {
2908+
try {
2909+
$database->deleteAttribute($collection, 'cards');
2910+
$this->fail('Failed to throw exception');
2911+
} catch (Throwable $e) {
2912+
$this->assertInstanceOf(DependencyException::class, $e);
2913+
$this->assertEquals("Column 'cards' has a functional index dependency and cannot be dropped or renamed.", $e->getMessage());
2914+
}
2915+
2916+
try {
2917+
$database->renameAttribute($collection, 'cards', 'cards_new');
2918+
$this->fail('Failed to throw exception');
2919+
} catch (Throwable $e) {
2920+
$this->assertInstanceOf(DependencyException::class, $e);
2921+
$this->assertEquals("Column 'cards' has a functional index dependency and cannot be dropped or renamed.", $e->getMessage());
2922+
}
2923+
} else {
2924+
$this->assertTrue($database->renameAttribute($collection, 'cards', 'cards_new'));
2925+
$this->assertTrue($database->deleteAttribute($collection, 'cards_new'));
2926+
}
2927+
28922928
try {
28932929
$database->createIndex($collection, 'indx', Database::INDEX_FULLTEXT, ['names']);
28942930
$this->fail('Failed to throw exception');

0 commit comments

Comments
 (0)