Skip to content

Commit 71c0b9c

Browse files
committed
Merge branch 'main' into ser-541-tag-4.5.2
2 parents a074126 + 5339475 commit 71c0b9c

File tree

21 files changed

+3536
-171
lines changed

21 files changed

+3536
-171
lines changed

composer.lock

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Database/Adapter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,13 @@ abstract public function getLimitForIndexes(): int;
899899
*/
900900
abstract public function getMaxIndexLength(): int;
901901

902+
/**
903+
* Get the maximum VARCHAR length for this adapter
904+
*
905+
* @return int
906+
*/
907+
abstract public function getMaxVarcharLength(): int;
908+
902909
/**
903910
* Get the maximum UID length for this adapter
904911
*

src/Database/Adapter/MariaDB.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1678,6 +1678,24 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
16781678

16791679
return "VARCHAR({$size})";
16801680

1681+
case Database::VAR_VARCHAR:
1682+
if ($size <= 0) {
1683+
throw new DatabaseException('VARCHAR size ' . $size . ' is invalid; must be > 0. Use TEXT, MEDIUMTEXT, or LONGTEXT instead.');
1684+
}
1685+
if ($size > $this->getMaxVarcharLength()) {
1686+
throw new DatabaseException('VARCHAR size ' . $size . ' exceeds maximum varchar length ' . $this->getMaxVarcharLength() . '. Use TEXT, MEDIUMTEXT, or LONGTEXT instead.');
1687+
}
1688+
return "VARCHAR({$size})";
1689+
1690+
case Database::VAR_TEXT:
1691+
return 'TEXT';
1692+
1693+
case Database::VAR_MEDIUMTEXT:
1694+
return 'MEDIUMTEXT';
1695+
1696+
case Database::VAR_LONGTEXT:
1697+
return 'LONGTEXT';
1698+
16811699
case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554
16821700
$signed = ($signed) ? '' : ' UNSIGNED';
16831701

@@ -1701,7 +1719,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
17011719
return 'DATETIME(3)';
17021720

17031721
default:
1704-
throw new DatabaseException('Unknown type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
1722+
throw new DatabaseException('Unknown type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_VARCHAR . ', ' . Database::VAR_TEXT . ', ' . Database::VAR_MEDIUMTEXT . ', ' . Database::VAR_LONGTEXT . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
17051723
}
17061724
}
17071725

src/Database/Adapter/Mongo.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,7 @@ public function upsertDocuments(Document $collection, string $attribute, array $
15621562
$operations = [];
15631563
foreach ($changes as $change) {
15641564
$document = $change->getNew();
1565+
$oldDocument = $change->getOld();
15651566
$attributes = $document->getAttributes();
15661567
$attributes['_uid'] = $document->getId();
15671568
$attributes['_createdAt'] = $document['$createdAt'];
@@ -1587,6 +1588,9 @@ public function upsertDocuments(Document $collection, string $attribute, array $
15871588

15881589
unset($record['_id']); // Don't update _id
15891590

1591+
// Get fields to unset for schemaless mode
1592+
$unsetFields = $this->getUpsertAttributeRemovals($oldDocument, $document, $record);
1593+
15901594
if (!empty($attribute)) {
15911595
// Get the attribute value before removing it from $set
15921596
$attributeValue = $record[$attribute] ?? 0;
@@ -1595,17 +1599,28 @@ public function upsertDocuments(Document $collection, string $attribute, array $
15951599
// it is requierd to mimic the behaver of SQL on duplicate key update
15961600
unset($record[$attribute]);
15971601

1602+
// Also remove from unset if it was there
1603+
unset($unsetFields[$attribute]);
1604+
15981605
// Increment the specific attribute and update all other fields
15991606
$update = [
16001607
'$inc' => [$attribute => $attributeValue],
16011608
'$set' => $record
16021609
];
1610+
1611+
if (!empty($unsetFields)) {
1612+
$update['$unset'] = $unsetFields;
1613+
}
16031614
} else {
16041615
// Update all fields
16051616
$update = [
16061617
'$set' => $record
16071618
];
16081619

1620+
if (!empty($unsetFields)) {
1621+
$update['$unset'] = $unsetFields;
1622+
}
1623+
16091624
// Add UUID7 _id for new documents in upsert operations
16101625
if (empty($document->getSequence())) {
16111626
$update['$setOnInsert'] = [
@@ -1634,6 +1649,43 @@ public function upsertDocuments(Document $collection, string $attribute, array $
16341649
return \array_map(fn ($change) => $change->getNew(), $changes);
16351650
}
16361651

1652+
/**
1653+
* Get fields to unset for schemaless upsert operations
1654+
*
1655+
* @param Document $oldDocument
1656+
* @param Document $newDocument
1657+
* @param array<string, mixed> $record
1658+
* @return array<string, string>
1659+
*/
1660+
private function getUpsertAttributeRemovals(Document $oldDocument, Document $newDocument, array $record): array
1661+
{
1662+
$unsetFields = [];
1663+
1664+
if ($this->getSupportForAttributes() || $oldDocument->isEmpty()) {
1665+
return $unsetFields;
1666+
}
1667+
1668+
$oldUserAttributes = $oldDocument->getAttributes();
1669+
$newUserAttributes = $newDocument->getAttributes();
1670+
1671+
$protectedFields = ['_uid', '_id', '_createdAt', '_updatedAt', '_permissions', '_tenant'];
1672+
1673+
foreach ($oldUserAttributes as $originalKey => $originalValue) {
1674+
if (in_array($originalKey, $protectedFields) || array_key_exists($originalKey, $newUserAttributes)) {
1675+
continue;
1676+
}
1677+
1678+
$transformed = $this->replaceChars('$', '_', [$originalKey => $originalValue]);
1679+
$dbKey = array_key_first($transformed);
1680+
1681+
if ($dbKey && !array_key_exists($dbKey, $record) && !in_array($dbKey, $protectedFields)) {
1682+
$unsetFields[$dbKey] = '';
1683+
}
1684+
}
1685+
1686+
return $unsetFields;
1687+
}
1688+
16371689
/**
16381690
* Get sequences for documents that were created
16391691
*
@@ -2067,6 +2119,10 @@ private function getMongoTypeCode(string $appwriteType): string
20672119
{
20682120
return match ($appwriteType) {
20692121
Database::VAR_STRING => 'string',
2122+
Database::VAR_VARCHAR => 'string',
2123+
Database::VAR_TEXT => 'string',
2124+
Database::VAR_MEDIUMTEXT => 'string',
2125+
Database::VAR_LONGTEXT => 'string',
20702126
Database::VAR_INTEGER => 'int',
20712127
Database::VAR_FLOAT => 'double',
20722128
Database::VAR_BOOLEAN => 'bool',
@@ -2694,6 +2750,17 @@ public function getLimitForString(): int
26942750
return 2147483647;
26952751
}
26962752

2753+
/**
2754+
* Get max VARCHAR limit
2755+
* MongoDB doesn't distinguish between string types, so using same as string limit
2756+
*
2757+
* @return int
2758+
*/
2759+
public function getMaxVarcharLength(): int
2760+
{
2761+
return 2147483647;
2762+
}
2763+
26972764
/**
26982765
* Get max INT limit
26992766
*

src/Database/Adapter/Pool.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ public function getMaxIndexLength(): int
287287
return $this->delegate(__FUNCTION__, \func_get_args());
288288
}
289289

290+
public function getMaxVarcharLength(): int
291+
{
292+
return $this->delegate(__FUNCTION__, \func_get_args());
293+
}
294+
290295
public function getMaxUIDLength(): int
291296
{
292297
return $this->delegate(__FUNCTION__, \func_get_args());

src/Database/Adapter/Postgres.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,14 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
19221922

19231923
return "VARCHAR({$size})";
19241924

1925+
case Database::VAR_VARCHAR:
1926+
return "VARCHAR({$size})";
1927+
1928+
case Database::VAR_TEXT:
1929+
case Database::VAR_MEDIUMTEXT:
1930+
case Database::VAR_LONGTEXT:
1931+
return 'TEXT'; // PostgreSQL doesn't have MEDIUMTEXT/LONGTEXT, use TEXT
1932+
19251933
case Database::VAR_INTEGER: // We don't support zerofill: https://stackoverflow.com/a/5634147/2299554
19261934

19271935
if ($size >= 8) { // INT = 4 bytes, BIGINT = 8 bytes
@@ -1958,7 +1966,7 @@ protected function getSQLType(string $type, int $size, bool $signed = true, bool
19581966
return "VECTOR({$size})";
19591967

19601968
default:
1961-
throw new DatabaseException('Unknown Type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_OBJECT . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
1969+
throw new DatabaseException('Unknown Type: ' . $type . '. Must be one of ' . Database::VAR_STRING . ', ' . Database::VAR_VARCHAR . ', ' . Database::VAR_TEXT . ', ' . Database::VAR_MEDIUMTEXT . ', ' . Database::VAR_LONGTEXT . ', ' . Database::VAR_INTEGER . ', ' . Database::VAR_FLOAT . ', ' . Database::VAR_BOOLEAN . ', ' . Database::VAR_DATETIME . ', ' . Database::VAR_RELATIONSHIP . ', ' . Database::VAR_OBJECT . ', ' . Database::VAR_POINT . ', ' . Database::VAR_LINESTRING . ', ' . Database::VAR_POLYGON);
19621970
}
19631971
}
19641972

src/Database/Adapter/SQL.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,19 @@ public function getAttributeWidth(Document $collection): int
11441144

11451145
break;
11461146

1147+
case Database::VAR_VARCHAR:
1148+
$total += match (true) {
1149+
$attribute['size'] > 255 => $attribute['size'] * 4 + 2, // VARCHAR(>255) + 2 length
1150+
default => $attribute['size'] * 4 + 1, // VARCHAR(<=255) + 1 length
1151+
};
1152+
break;
1153+
1154+
case Database::VAR_TEXT:
1155+
case Database::VAR_MEDIUMTEXT:
1156+
case Database::VAR_LONGTEXT:
1157+
$total += 20; // Pointer storage for TEXT types
1158+
break;
1159+
11471160
case Database::VAR_INTEGER:
11481161
if ($attribute['size'] >= 8) {
11491162
$total += 8; // BIGINT 8 bytes

0 commit comments

Comments
 (0)