Skip to content

Commit 7ec486b

Browse files
committed
Move back to mariadb
1 parent 5d75600 commit 7ec486b

3 files changed

Lines changed: 238 additions & 233 deletions

File tree

src/Database/Adapter/MariaDB.php

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,239 @@ public function updateDocument(string $collection, string $id, Document $documen
13301330
return $document;
13311331
}
13321332

1333+
/**
1334+
* @param string $collection
1335+
* @param string $attribute
1336+
* @param array<Document> $documents
1337+
* @return array<Document>
1338+
* @throws DatabaseException
1339+
*/
1340+
public function createOrUpdateDocuments(
1341+
string $collection,
1342+
string $attribute,
1343+
array $documents
1344+
): array {
1345+
if (empty($documents)) {
1346+
return $documents;
1347+
}
1348+
1349+
try {
1350+
$name = $this->filter($collection);
1351+
$attribute = $this->filter($attribute);
1352+
1353+
$attributes = [];
1354+
$bindIndex = 0;
1355+
$batchKeys = [];
1356+
$bindValues = [];
1357+
$documentIds = [];
1358+
$documentTenants = [];
1359+
1360+
foreach ($documents as $document) {
1361+
$attributes = $document->getAttributes();
1362+
$attributes['_uid'] = $document->getId();
1363+
$attributes['_createdAt'] = $document->getCreatedAt();
1364+
$attributes['_updatedAt'] = $document->getUpdatedAt();
1365+
$attributes['_permissions'] = \json_encode($document->getPermissions());
1366+
1367+
if (!empty($document->getInternalId())) {
1368+
$attributes['_id'] = $document->getInternalId();
1369+
} else {
1370+
$documentIds[] = $document->getId();
1371+
}
1372+
1373+
if ($this->sharedTables) {
1374+
$attributes['_tenant']
1375+
= $documentTenants[]
1376+
= $document->getTenant();
1377+
}
1378+
1379+
$columns = [];
1380+
foreach (\array_keys($attributes) as $key => $attr) {
1381+
$columns[$key] = "{$this->quote($this->filter($attr))}";
1382+
}
1383+
$columns = '(' . \implode(', ', $columns) . ')';
1384+
1385+
$bindKeys = [];
1386+
1387+
foreach ($attributes as $attrValue) {
1388+
if (\is_array($attrValue)) {
1389+
$attrValue = \json_encode($attrValue);
1390+
}
1391+
$attrValue = (\is_bool($attrValue)) ? (int)$attrValue : $attrValue;
1392+
$bindKey = 'key_' . $bindIndex;
1393+
$bindKeys[] = ':' . $bindKey;
1394+
$bindValues[$bindKey] = $attrValue;
1395+
$bindIndex++;
1396+
}
1397+
1398+
$batchKeys[] = '(' . \implode(', ', $bindKeys) . ')';
1399+
}
1400+
1401+
$getUpdateClause = function (string $attribute, bool $increment = false): string {
1402+
$attribute = $this->quote($this->filter($attribute));
1403+
1404+
if ($increment) {
1405+
$new = "{$attribute} + VALUES({$attribute})";
1406+
} else {
1407+
$new = "VALUES({$attribute})";
1408+
}
1409+
1410+
if ($this->sharedTables) {
1411+
return "{$attribute} = IF(_tenant = VALUES(_tenant), {$new}, {$attribute})";
1412+
}
1413+
1414+
return "{$attribute} = {$new}";
1415+
};
1416+
1417+
if (!empty($attribute)) {
1418+
// Increment specific column by its new value in place
1419+
$updateColumns = [
1420+
$getUpdateClause($attribute, increment: true),
1421+
$getUpdateClause('_updatedAt'),
1422+
];
1423+
} else {
1424+
// Update all columns
1425+
$updateColumns = [];
1426+
foreach (\array_keys($attributes) as $attr) {
1427+
$updateColumns[] = $getUpdateClause($this->filter($attr));
1428+
}
1429+
}
1430+
1431+
$stmt = $this->getPDO()->prepare(
1432+
"
1433+
INSERT INTO {$this->getSQLTable($name)} {$columns}
1434+
VALUES " . \implode(', ', $batchKeys) . "
1435+
ON DUPLICATE KEY UPDATE
1436+
" . \implode(', ', $updateColumns)
1437+
);
1438+
1439+
foreach ($bindValues as $key => $binding) {
1440+
$stmt->bindValue($key, $binding, $this->getPDOType($binding));
1441+
}
1442+
1443+
$stmt->execute();
1444+
1445+
// Fetch existing permissions in bulk after data updates
1446+
$sql = "
1447+
SELECT _document, _type, _permission
1448+
FROM {$this->getSQLTable($name . '_perms')}
1449+
WHERE _document IN (" . \implode(',', \array_map(fn ($index) => ":_key_{$index}", \array_keys($documents))) . ")
1450+
{$this->getTenantQuery($collection, tenantCount: \count($documentTenants))}
1451+
";
1452+
1453+
$stmt = $this->getPDO()->prepare($sql);
1454+
1455+
foreach ($documents as $index => $document) {
1456+
$stmt->bindValue(":_key_{$index}", $document->getId());
1457+
}
1458+
1459+
if ($this->sharedTables) {
1460+
foreach ($documentTenants as $index => $tenant) {
1461+
$stmt->bindValue(":_tenant_{$index}", $tenant);
1462+
}
1463+
}
1464+
1465+
$stmt->execute();
1466+
$existing = $stmt->fetchAll();
1467+
$stmt->closeCursor();
1468+
1469+
// Group permissions by document
1470+
$permissionsByDocument = [];
1471+
foreach ($existing as $row) {
1472+
$permissionsByDocument[$row['_document']][$row['_type']][] = $row['_permission'];
1473+
}
1474+
1475+
foreach ($documentIds as $id) {
1476+
foreach (Database::PERMISSIONS as $type) {
1477+
$permissionsByDocument[$id][$type] = $permissionsByDocument[$id][$type] ?? [];
1478+
}
1479+
}
1480+
1481+
$removeQueries = [];
1482+
$removeBindValues = [];
1483+
$addQueries = [];
1484+
$addBindValues = [];
1485+
1486+
foreach ($documents as $index => $document) {
1487+
$currentPermissions = $permissionsByDocument[$document->getId()] ?? [];
1488+
1489+
// Calculate removals
1490+
foreach (Database::PERMISSIONS as $type) {
1491+
$toRemove = \array_diff($currentPermissions[$type] ?? [], $document->getPermissionsByType($type));
1492+
if (!empty($toRemove)) {
1493+
$removeQueries[] = "(
1494+
_document = :_uid_{$index}
1495+
{$this->getTenantQuery($collection, tenantCount: \count($toRemove))}
1496+
AND _type = '{$type}'
1497+
AND _permission IN (" . \implode(',', \array_map(fn ($i) => ":remove_{$type}_{$index}_{$i}", \array_keys($toRemove))) . ")
1498+
)";
1499+
$removeBindValues[":_uid_{$index}"] = $document->getId();
1500+
$removeBindValues[":_tenant_{$index}"] = $document->getTenant();
1501+
foreach ($toRemove as $i => $perm) {
1502+
$removeBindValues[":remove_{$type}_{$index}_{$i}"] = $perm;
1503+
}
1504+
}
1505+
}
1506+
1507+
// Calculate additions
1508+
foreach (Database::PERMISSIONS as $type) {
1509+
$toAdd = \array_diff($document->getPermissionsByType($type), $currentPermissions[$type] ?? []);
1510+
foreach ($toAdd as $i => $permission) {
1511+
$addQuery = "(:_uid_{$index}, '{$type}', :add_{$type}_{$index}_{$i}";
1512+
1513+
if ($this->sharedTables) {
1514+
$addQuery .= ", :_tenant_{$index}";
1515+
}
1516+
1517+
$addQuery .= ")";
1518+
$addQueries[] = $addQuery;
1519+
$addBindValues[":_uid_{$index}"] = $document->getId();
1520+
$addBindValues[":add_{$type}_{$index}_{$i}"] = $permission;
1521+
1522+
if ($this->sharedTables) {
1523+
$addBindValues[":_tenant_{$index}"] = $document->getTenant();
1524+
}
1525+
}
1526+
}
1527+
}
1528+
1529+
// Execute permission removals
1530+
if (!empty($removeQueries)) {
1531+
$removeQuery = \implode(' OR ', $removeQueries);
1532+
$stmtRemovePermissions = $this->getPDO()->prepare("DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE {$removeQuery}");
1533+
foreach ($removeBindValues as $key => $value) {
1534+
$stmtRemovePermissions->bindValue($key, $value, $this->getPDOType($value));
1535+
}
1536+
$stmtRemovePermissions->execute();
1537+
}
1538+
1539+
// Execute permission additions
1540+
if (!empty($addQueries)) {
1541+
$sqlAddPermissions = "INSERT INTO {$this->getSQLTable($name . '_perms')} (_document, _type, _permission";
1542+
if ($this->sharedTables) {
1543+
$sqlAddPermissions .= ", _tenant";
1544+
}
1545+
$sqlAddPermissions .= ") VALUES " . \implode(', ', $addQueries);
1546+
$stmtAddPermissions = $this->getPDO()->prepare($sqlAddPermissions);
1547+
foreach ($addBindValues as $key => $value) {
1548+
$stmtAddPermissions->bindValue($key, $value, $this->getPDOType($value));
1549+
}
1550+
$stmtAddPermissions->execute();
1551+
}
1552+
1553+
$internalIds = $this->getInternalIds($collection, $documentIds, $documentTenants);
1554+
foreach ($documents as $document) {
1555+
if (isset($internalIds[$document->getId()])) {
1556+
$document['$internalId'] = $internalIds[$document->getId()];
1557+
}
1558+
}
1559+
} catch (PDOException $e) {
1560+
throw $this->processException($e);
1561+
}
1562+
1563+
return $documents;
1564+
}
1565+
13331566
/**
13341567
* Increase or decrease an attribute value
13351568
*

src/Database/Adapter/Postgres.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,11 @@ public function updateDocument(string $collection, string $id, Document $documen
13781378
return $document;
13791379
}
13801380

1381+
public function createOrUpdateDocuments(string $collection, string $attribute, array $documents): array
1382+
{
1383+
throw new \Exception('Not implemented');
1384+
}
1385+
13811386
/**
13821387
* Increase or decrease an attribute value
13831388
*

0 commit comments

Comments
 (0)