Skip to content

Commit 83278d6

Browse files
authored
Merge pull request #627 from utopia-php/disable-array-index-mysql
Mysql disable array cast index
2 parents eb2f759 + e797c01 commit 83278d6

File tree

8 files changed

+120
-64
lines changed

8 files changed

+120
-64
lines changed

src/Database/Adapter.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,20 @@ abstract public function getSupportForSchemaAttributes(): bool;
892892
*/
893893
abstract public function getSupportForIndex(): bool;
894894

895+
/**
896+
* Is indexing array supported?
897+
*
898+
* @return bool
899+
*/
900+
abstract public function getSupportForIndexArray(): bool;
901+
902+
/**
903+
* Is cast index as array supported?
904+
*
905+
* @return bool
906+
*/
907+
abstract public function getSupportForCastIndexArray(): bool;
908+
895909
/**
896910
* Is unique index supported?
897911
*
@@ -965,13 +979,6 @@ abstract public function getSupportForAttributeResizing(): bool;
965979
*/
966980
abstract public function getSupportForGetConnectionId(): bool;
967981

968-
/**
969-
* Is cast index as array supported?
970-
*
971-
* @return bool
972-
*/
973-
abstract public function getSupportForCastIndexArray(): bool;
974-
975982
/**
976983
* Is upserting supported?
977984
*

src/Database/Adapter/MySQL.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,21 @@ public function getSizeOfCollectionOnDisk(string $collection): int
7878
return $size;
7979
}
8080

81+
public function getSupportForIndexArray(): bool
82+
{
83+
/**
84+
* Disabling index creation due to Mysql bug
85+
* @link https://bugs.mysql.com/bug.php?id=111037
86+
*/
87+
return false;
88+
}
89+
8190
public function getSupportForCastIndexArray(): bool
8291
{
92+
if (!$this->getSupportForIndexArray()) {
93+
return false;
94+
}
95+
8396
return true;
8497
}
8598

src/Database/Adapter/Pool.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,16 @@ public function getSupportForIndex(): bool
335335
return $this->delegate(__FUNCTION__, \func_get_args());
336336
}
337337

338+
public function getSupportForIndexArray(): bool
339+
{
340+
return $this->delegate(__FUNCTION__, \func_get_args());
341+
}
342+
343+
public function getSupportForCastIndexArray(): bool
344+
{
345+
return $this->delegate(__FUNCTION__, \func_get_args());
346+
}
347+
338348
public function getSupportForUniqueIndex(): bool
339349
{
340350
return $this->delegate(__FUNCTION__, \func_get_args());
@@ -390,11 +400,6 @@ public function getSupportForGetConnectionId(): bool
390400
return $this->delegate(__FUNCTION__, \func_get_args());
391401
}
392402

393-
public function getSupportForCastIndexArray(): bool
394-
{
395-
return $this->delegate(__FUNCTION__, \func_get_args());
396-
}
397-
398403
public function getSupportForUpserts(): bool
399404
{
400405
return $this->delegate(__FUNCTION__, \func_get_args());

src/Database/Adapter/SQL.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,11 @@ public function getSupportForQueryContains(): bool
13741374
*/
13751375
abstract public function getSupportForJSONOverlaps(): bool;
13761376

1377+
public function getSupportForIndexArray(): bool
1378+
{
1379+
return true;
1380+
}
1381+
13771382
public function getSupportForCastIndexArray(): bool
13781383
{
13791384
return false;

src/Database/Database.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,10 @@ public function createCollection(string $id, array $attributes = [], array $inde
12421242

12431243
$isArray = $collectionAttribute->getAttribute('array', false);
12441244
if ($isArray) {
1245+
if (!$this->adapter->getSupportForIndexArray()) {
1246+
throw new IndexException('Indexing an array attribute is not supported');
1247+
}
1248+
12451249
if ($this->adapter->getMaxIndexLength() > 0) {
12461250
$lengths[$i] = self::ARRAY_INDEX_LENGTH;
12471251
}
@@ -3075,6 +3079,10 @@ public function createIndex(string $collection, string $id, string $type, array
30753079

30763080
$isArray = $collectionAttribute->getAttribute('array', false);
30773081
if ($isArray) {
3082+
if (!$this->adapter->getSupportForIndexArray()) {
3083+
throw new IndexException('Indexing an array attribute is not supported');
3084+
}
3085+
30783086
if ($this->adapter->getMaxIndexLength() > 0) {
30793087
$lengths[$i] = self::ARRAY_INDEX_LENGTH;
30803088
}

tests/e2e/Adapter/Scopes/AttributeTests.php

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,12 +1399,14 @@ public function testArrayAttribute(): void
13991399
$this->assertEquals('Antony', $document->getAttribute('names')[1]);
14001400
$this->assertEquals(100, $document->getAttribute('numbers')[1]);
14011401

1402-
/**
1403-
* functional index dependency cannot be dropped or rename
1404-
*/
1405-
$database->createIndex($collection, 'idx_cards', Database::INDEX_KEY, ['cards'], [100]);
1402+
if ($database->getAdapter()->getSupportForIndexArray()) {
1403+
/**
1404+
* functional index dependency cannot be dropped or rename
1405+
*/
1406+
$database->createIndex($collection, 'idx_cards', Database::INDEX_KEY, ['cards'], [100]);
1407+
}
14061408

1407-
if ($this->getDatabase()->getAdapter()->getSupportForCastIndexArray()) {
1409+
if ($database->getAdapter()->getSupportForCastIndexArray()) {
14081410
/**
14091411
* Delete attribute
14101412
*/
@@ -1443,22 +1445,24 @@ public function testArrayAttribute(): void
14431445
$this->assertTrue($database->deleteAttribute($collection, 'cards_new'));
14441446
}
14451447

1446-
try {
1447-
$database->createIndex($collection, 'indx', Database::INDEX_FULLTEXT, ['names']);
1448-
$this->fail('Failed to throw exception');
1449-
} catch (Throwable $e) {
1450-
if ($this->getDatabase()->getAdapter()->getSupportForFulltextIndex()) {
1451-
$this->assertEquals('"Fulltext" index is forbidden on array attributes', $e->getMessage());
1452-
} else {
1453-
$this->assertEquals('Fulltext index is not supported', $e->getMessage());
1448+
if ($database->getAdapter()->getSupportForIndexArray()) {
1449+
try {
1450+
$database->createIndex($collection, 'indx', Database::INDEX_FULLTEXT, ['names']);
1451+
$this->fail('Failed to throw exception');
1452+
} catch (Throwable $e) {
1453+
if ($database->getAdapter()->getSupportForFulltextIndex()) {
1454+
$this->assertEquals('"Fulltext" index is forbidden on array attributes', $e->getMessage());
1455+
} else {
1456+
$this->assertEquals('Fulltext index is not supported', $e->getMessage());
1457+
}
14541458
}
1455-
}
14561459

1457-
try {
1458-
$database->createIndex($collection, 'indx', Database::INDEX_KEY, ['numbers', 'names'], [100,100]);
1459-
$this->fail('Failed to throw exception');
1460-
} catch (Throwable $e) {
1461-
$this->assertEquals('An index may only contain one array attribute', $e->getMessage());
1460+
try {
1461+
$database->createIndex($collection, 'indx', Database::INDEX_KEY, ['numbers', 'names'], [100,100]);
1462+
$this->fail('Failed to throw exception');
1463+
} catch (Throwable $e) {
1464+
$this->assertEquals('An index may only contain one array attribute', $e->getMessage());
1465+
}
14621466
}
14631467

14641468
$this->assertEquals(true, $database->createAttribute(
@@ -1470,32 +1474,36 @@ public function testArrayAttribute(): void
14701474
array: true
14711475
));
14721476

1473-
if ($database->getAdapter()->getMaxIndexLength() > 0) {
1474-
// If getMaxIndexLength() > 0 We clear length for array attributes
1475-
$database->createIndex($collection, 'indx1', Database::INDEX_KEY, ['long_size'], [], []);
1476-
$database->createIndex($collection, 'indx2', Database::INDEX_KEY, ['long_size'], [1000], []);
1477+
if ($database->getAdapter()->getSupportForIndexArray()) {
1478+
1479+
1480+
if ($database->getAdapter()->getMaxIndexLength() > 0) {
1481+
// If getMaxIndexLength() > 0 We clear length for array attributes
1482+
$database->createIndex($collection, 'indx1', Database::INDEX_KEY, ['long_size'], [], []);
1483+
$database->createIndex($collection, 'indx2', Database::INDEX_KEY, ['long_size'], [1000], []);
1484+
1485+
try {
1486+
$database->createIndex($collection, 'indx_numbers', Database::INDEX_KEY, ['tv_show', 'numbers'], [], []); // [700, 255]
1487+
$this->fail('Failed to throw exception');
1488+
} catch (Throwable $e) {
1489+
$this->assertEquals('Index length is longer than the maximum: ' . $database->getAdapter()->getMaxIndexLength(), $e->getMessage());
1490+
}
1491+
}
1492+
1493+
// We clear orders for array attributes
1494+
$database->createIndex($collection, 'indx3', Database::INDEX_KEY, ['names'], [255], ['desc']);
14771495

14781496
try {
1479-
$database->createIndex($collection, 'indx_numbers', Database::INDEX_KEY, ['tv_show', 'numbers'], [], []); // [700, 255]
1497+
$database->createIndex($collection, 'indx4', Database::INDEX_KEY, ['age', 'names'], [10, 255], []);
14801498
$this->fail('Failed to throw exception');
14811499
} catch (Throwable $e) {
1482-
$this->assertEquals('Index length is longer than the maximum: ' . $database->getAdapter()->getMaxIndexLength(), $e->getMessage());
1500+
$this->assertEquals('Cannot set a length on "integer" attributes', $e->getMessage());
14831501
}
1484-
}
1485-
1486-
// We clear orders for array attributes
1487-
$database->createIndex($collection, 'indx3', Database::INDEX_KEY, ['names'], [255], ['desc']);
14881502

1489-
try {
1490-
$database->createIndex($collection, 'indx4', Database::INDEX_KEY, ['age', 'names'], [10, 255], []);
1491-
$this->fail('Failed to throw exception');
1492-
} catch (Throwable $e) {
1493-
$this->assertEquals('Cannot set a length on "integer" attributes', $e->getMessage());
1503+
$this->assertTrue($database->createIndex($collection, 'indx6', Database::INDEX_KEY, ['age', 'names'], [null, 999], []));
1504+
$this->assertTrue($database->createIndex($collection, 'indx7', Database::INDEX_KEY, ['age', 'booleans'], [0, 999], []));
14941505
}
14951506

1496-
$this->assertTrue($database->createIndex($collection, 'indx6', Database::INDEX_KEY, ['age', 'names'], [null, 999], []));
1497-
$this->assertTrue($database->createIndex($collection, 'indx7', Database::INDEX_KEY, ['age', 'booleans'], [0, 999], []));
1498-
14991507
if ($this->getDatabase()->getAdapter()->getSupportForQueryContains()) {
15001508
try {
15011509
$database->find($collection, [

tests/e2e/Adapter/Scopes/CollectionTests.php

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ public function testRowSizeToLarge(): void
628628

629629
public function testCreateCollectionWithSchemaIndexes(): void
630630
{
631+
/** @var Database $database */
631632
$database = static::getDatabase();
632633

633634
$attributes = [
@@ -650,13 +651,6 @@ public function testCreateCollectionWithSchemaIndexes(): void
650651
];
651652

652653
$indexes = [
653-
new Document([
654-
'$id' => ID::custom('idx_cards'),
655-
'type' => Database::INDEX_KEY,
656-
'attributes' => ['cards'],
657-
'lengths' => [500], // Will be changed to Database::ARRAY_INDEX_LENGTH (255)
658-
'orders' => [Database::ORDER_DESC],
659-
]),
660654
new Document([
661655
'$id' => ID::custom('idx_username'),
662656
'type' => Database::INDEX_KEY,
@@ -673,6 +667,16 @@ public function testCreateCollectionWithSchemaIndexes(): void
673667
]),
674668
];
675669

670+
if ($database->getAdapter()->getSupportForIndexArray()) {
671+
$indexes[] = new Document([
672+
'$id' => ID::custom('idx_cards'),
673+
'type' => Database::INDEX_KEY,
674+
'attributes' => ['cards'],
675+
'lengths' => [500], // Will be changed to Database::ARRAY_INDEX_LENGTH (255)
676+
'orders' => [Database::ORDER_DESC],
677+
]);
678+
}
679+
676680
$collection = $database->createCollection(
677681
'collection98',
678682
$attributes,
@@ -682,16 +686,18 @@ public function testCreateCollectionWithSchemaIndexes(): void
682686
]
683687
);
684688

685-
$this->assertEquals($collection->getAttribute('indexes')[0]['attributes'][0], 'cards');
686-
$this->assertEquals($collection->getAttribute('indexes')[0]['lengths'][0], Database::ARRAY_INDEX_LENGTH);
687-
$this->assertEquals($collection->getAttribute('indexes')[0]['orders'][0], null);
689+
$this->assertEquals($collection->getAttribute('indexes')[0]['attributes'][0], 'username');
690+
$this->assertEquals($collection->getAttribute('indexes')[0]['lengths'][0], null);
688691

689692
$this->assertEquals($collection->getAttribute('indexes')[1]['attributes'][0], 'username');
690-
$this->assertEquals($collection->getAttribute('indexes')[1]['lengths'][0], null);
693+
$this->assertEquals($collection->getAttribute('indexes')[1]['lengths'][0], 99);
694+
$this->assertEquals($collection->getAttribute('indexes')[1]['orders'][0], Database::ORDER_DESC);
691695

692-
$this->assertEquals($collection->getAttribute('indexes')[2]['attributes'][0], 'username');
693-
$this->assertEquals($collection->getAttribute('indexes')[2]['lengths'][0], 99);
694-
$this->assertEquals($collection->getAttribute('indexes')[2]['orders'][0], Database::ORDER_DESC);
696+
if ($database->getAdapter()->getSupportForIndexArray()) {
697+
$this->assertEquals($collection->getAttribute('indexes')[2]['attributes'][0], 'cards');
698+
$this->assertEquals($collection->getAttribute('indexes')[2]['lengths'][0], Database::ARRAY_INDEX_LENGTH);
699+
$this->assertEquals($collection->getAttribute('indexes')[2]['orders'][0], null);
700+
}
695701
}
696702

697703
public function testCollectionUpdate(): Document
@@ -1033,6 +1039,7 @@ public function testSharedTables(): void
10331039
/**
10341040
* Default mode already tested, we'll test 'schema' and 'table' isolation here
10351041
*/
1042+
/** @var Database $database */
10361043
$database = static::getDatabase();
10371044
$sharedTables = $database->getSharedTables();
10381045
$namespace = $database->getNamespace();
@@ -1236,6 +1243,7 @@ public function testCreateDuplicates(): void
12361243
}
12371244
public function testSharedTablesDuplicates(): void
12381245
{
1246+
/** @var Database $database */
12391247
$database = static::getDatabase();
12401248
$sharedTables = $database->getSharedTables();
12411249
$namespace = $database->getNamespace();

tests/e2e/Adapter/Scopes/IndexTests.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ public function testCreateIndex(): void
2828
* Check ticks sounding cast index for reserved words
2929
*/
3030
$database->createAttribute('indexes', 'int', Database::VAR_INTEGER, 8, false, array:true);
31-
$database->createIndex('indexes', 'indx8711', Database::INDEX_KEY, ['int'], [255]);
31+
if ($database->getAdapter()->getSupportForIndexArray()) {
32+
$database->createIndex('indexes', 'indx8711', Database::INDEX_KEY, ['int'], [255]);
33+
}
3234

3335
$database->createAttribute('indexes', 'name', Database::VAR_STRING, 10, false);
3436

0 commit comments

Comments
 (0)