Skip to content

Commit ad191bf

Browse files
authored
Merge pull request #545 from utopia-php/delete-documents-internal-ids
Delete documents & update documents chunks
2 parents 51ff0a6 + ebc812b commit ad191bf

File tree

6 files changed

+421
-731
lines changed

6 files changed

+421
-731
lines changed

src/Database/Adapter.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,11 +701,12 @@ abstract public function deleteDocument(string $collection, string $id): bool;
701701
* Delete Documents
702702
*
703703
* @param string $collection
704-
* @param array<string> $ids
704+
* @param array<string> $internalIds
705+
* @param array<string> $permissionIds
705706
*
706707
* @return int
707708
*/
708-
abstract public function deleteDocuments(string $collection, array $ids): int;
709+
abstract public function deleteDocuments(string $collection, array $internalIds, array $permissionIds): int;
709710

710711
/**
711712
* Find Documents

src/Database/Adapter/MariaDB.php

Lines changed: 5 additions & 321 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,254 +1365,6 @@ public function updateDocument(string $collection, string $id, Document $documen
13651365
return $document;
13661366
}
13671367

1368-
/**
1369-
* Update documents
1370-
*
1371-
* Updates all documents which match the given query.
1372-
*
1373-
* @param string $collection
1374-
* @param Document $updates
1375-
* @param array<Document> $documents
1376-
*
1377-
* @return int
1378-
*
1379-
* @throws DatabaseException
1380-
*/
1381-
public function updateDocuments(string $collection, Document $updates, array $documents): int
1382-
{
1383-
$attributes = $updates->getAttributes();
1384-
1385-
if (!empty($updates->getUpdatedAt())) {
1386-
$attributes['_updatedAt'] = $updates->getUpdatedAt();
1387-
}
1388-
1389-
if (!empty($updates->getPermissions())) {
1390-
$attributes['_permissions'] = json_encode($updates->getPermissions());
1391-
}
1392-
1393-
if (empty($attributes)) {
1394-
return 0;
1395-
}
1396-
1397-
$name = $this->filter($collection);
1398-
1399-
$columns = '';
1400-
1401-
$where = [];
1402-
1403-
$ids = \array_map(fn ($document) => $document->getId(), $documents);
1404-
$where[] = "_uid IN (" . \implode(', ', \array_map(fn ($index) => ":_id_{$index}", \array_keys($ids))) . ")";
1405-
1406-
if ($this->sharedTables) {
1407-
$where[] = "_tenant = :_tenant";
1408-
}
1409-
1410-
$sqlWhere = 'WHERE ' . implode(' AND ', $where);
1411-
1412-
$bindIndex = 0;
1413-
foreach ($attributes as $attribute => $value) {
1414-
$column = $this->filter($attribute);
1415-
$bindKey = 'key_' . $bindIndex;
1416-
$columns .= "`{$column}`" . '=:' . $bindKey;
1417-
1418-
if ($attribute !== \array_key_last($attributes)) {
1419-
$columns .= ',';
1420-
}
1421-
1422-
$bindIndex++;
1423-
}
1424-
1425-
$sql = "
1426-
UPDATE {$this->getSQLTable($name)}
1427-
SET {$columns}
1428-
{$sqlWhere}
1429-
";
1430-
1431-
$sql = $this->trigger(Database::EVENT_DOCUMENTS_UPDATE, $sql);
1432-
$stmt = $this->getPDO()->prepare($sql);
1433-
1434-
if ($this->sharedTables) {
1435-
$stmt->bindValue(':_tenant', $this->tenant);
1436-
}
1437-
1438-
foreach ($ids as $id => $value) {
1439-
$stmt->bindValue(":_id_{$id}", $value);
1440-
}
1441-
1442-
$attributeIndex = 0;
1443-
foreach ($attributes as $attribute => $value) {
1444-
if (is_array($value)) {
1445-
$value = json_encode($value);
1446-
}
1447-
1448-
$bindKey = 'key_' . $attributeIndex;
1449-
$value = (is_bool($value)) ? (int)$value : $value;
1450-
$stmt->bindValue(':' . $bindKey, $value, $this->getPDOType($value));
1451-
$attributeIndex++;
1452-
}
1453-
1454-
$stmt->execute();
1455-
$affected = $stmt->rowCount();
1456-
1457-
// Permissions logic
1458-
if (!empty($updates->getPermissions())) {
1459-
$removeQueries = [];
1460-
$removeBindValues = [];
1461-
1462-
$addQuery = '';
1463-
$addBindValues = [];
1464-
1465-
/* @var $document Document */
1466-
foreach ($documents as $index => $document) {
1467-
// Permissions logic
1468-
$sql = "
1469-
SELECT _type, _permission
1470-
FROM {$this->getSQLTable($name . '_perms')}
1471-
WHERE _document = :_uid
1472-
{$this->getTenantQuery($collection)}
1473-
";
1474-
1475-
$sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql);
1476-
1477-
$permissionsStmt = $this->getPDO()->prepare($sql);
1478-
$permissionsStmt->bindValue(':_uid', $document->getId());
1479-
1480-
if ($this->sharedTables) {
1481-
$permissionsStmt->bindValue(':_tenant', $this->tenant);
1482-
}
1483-
1484-
$permissionsStmt->execute();
1485-
$permissions = $permissionsStmt->fetchAll();
1486-
$permissionsStmt->closeCursor();
1487-
1488-
$initial = [];
1489-
foreach (Database::PERMISSIONS as $type) {
1490-
$initial[$type] = [];
1491-
}
1492-
1493-
$permissions = \array_reduce($permissions, function (array $carry, array $item) {
1494-
$carry[$item['_type']][] = $item['_permission'];
1495-
return $carry;
1496-
}, $initial);
1497-
1498-
// Get removed Permissions
1499-
$removals = [];
1500-
foreach (Database::PERMISSIONS as $type) {
1501-
$diff = array_diff($permissions[$type], $updates->getPermissionsByType($type));
1502-
if (!empty($diff)) {
1503-
$removals[$type] = $diff;
1504-
}
1505-
}
1506-
1507-
// Build inner query to remove permissions
1508-
if (!empty($removals)) {
1509-
foreach ($removals as $type => $permissionsToRemove) {
1510-
$bindKey = 'uid_' . $index;
1511-
$removeBindKeys[] = ':uid_' . $index;
1512-
$removeBindValues[$bindKey] = $document->getId();
1513-
1514-
$removeQueries[] = "(
1515-
_document = :uid_{$index}
1516-
{$this->getTenantQuery($collection)}
1517-
AND _type = '{$type}'
1518-
AND _permission IN (" . \implode(', ', \array_map(function (string $i) use ($permissionsToRemove, $index, $type, &$removeBindKeys, &$removeBindValues) {
1519-
$bindKey = 'remove_' . $type . '_' . $index . '_' . $i;
1520-
$removeBindKeys[] = ':' . $bindKey;
1521-
$removeBindValues[$bindKey] = $permissionsToRemove[$i];
1522-
1523-
return ':' . $bindKey;
1524-
}, \array_keys($permissionsToRemove))) .
1525-
")
1526-
)";
1527-
}
1528-
}
1529-
1530-
// Get added Permissions
1531-
$additions = [];
1532-
foreach (Database::PERMISSIONS as $type) {
1533-
$diff = \array_diff($updates->getPermissionsByType($type), $permissions[$type]);
1534-
if (!empty($diff)) {
1535-
$additions[$type] = $diff;
1536-
}
1537-
}
1538-
1539-
// Build inner query to add permissions
1540-
if (!empty($additions)) {
1541-
foreach ($additions as $type => $permissionsToAdd) {
1542-
foreach ($permissionsToAdd as $i => $permission) {
1543-
$bindKey = 'uid_' . $index;
1544-
$addBindValues[$bindKey] = $document->getId();
1545-
1546-
$bindKey = 'add_' . $type . '_' . $index . '_' . $i;
1547-
$addBindValues[$bindKey] = $permission;
1548-
1549-
$addQuery .= "(:uid_{$index}, '{$type}', :{$bindKey}";
1550-
1551-
if ($this->sharedTables) {
1552-
$addQuery .= ", :_tenant)";
1553-
} else {
1554-
$addQuery .= ")";
1555-
}
1556-
1557-
if ($i !== \array_key_last($permissionsToAdd) || $type !== \array_key_last($additions)) {
1558-
$addQuery .= ', ';
1559-
}
1560-
}
1561-
}
1562-
if ($index !== \array_key_last($documents)) {
1563-
$addQuery .= ', ';
1564-
}
1565-
}
1566-
}
1567-
1568-
if (!empty($removeQueries)) {
1569-
$removeQuery = \implode(' OR ', $removeQueries);
1570-
1571-
$stmtRemovePermissions = $this->getPDO()->prepare("
1572-
DELETE
1573-
FROM {$this->getSQLTable($name . '_perms')}
1574-
WHERE ({$removeQuery})
1575-
");
1576-
1577-
foreach ($removeBindValues as $key => $value) {
1578-
$stmtRemovePermissions->bindValue($key, $value, $this->getPDOType($value));
1579-
}
1580-
1581-
if ($this->sharedTables) {
1582-
$stmtRemovePermissions->bindValue(':_tenant', $this->tenant);
1583-
}
1584-
$stmtRemovePermissions->execute();
1585-
}
1586-
1587-
if (!empty($addQuery)) {
1588-
$sqlAddPermissions = "
1589-
INSERT INTO {$this->getSQLTable($name . '_perms')} (`_document`, `_type`, `_permission`
1590-
";
1591-
1592-
if ($this->sharedTables) {
1593-
$sqlAddPermissions .= ', `_tenant`)';
1594-
} else {
1595-
$sqlAddPermissions .= ')';
1596-
}
1597-
1598-
$sqlAddPermissions .= " VALUES {$addQuery}";
1599-
1600-
$stmtAddPermissions = $this->getPDO()->prepare($sqlAddPermissions);
1601-
1602-
foreach ($addBindValues as $key => $value) {
1603-
$stmtAddPermissions->bindValue($key, $value, $this->getPDOType($value));
1604-
}
1605-
1606-
if ($this->sharedTables) {
1607-
$stmtAddPermissions->bindValue(':_tenant', $this->tenant);
1608-
}
1609-
1610-
$stmtAddPermissions->execute();
1611-
}
1612-
}
1613-
1614-
return $affected;
1615-
}
16161368

16171369
/**
16181370
* @param string $collection
@@ -1943,79 +1695,6 @@ public function deleteDocument(string $collection, string $id): bool
19431695
return $deleted;
19441696
}
19451697

1946-
/**
1947-
* Delete Documents
1948-
*
1949-
* @param string $collection
1950-
* @param array<string> $ids
1951-
*
1952-
* @return int
1953-
*/
1954-
public function deleteDocuments(string $collection, array $ids): int
1955-
{
1956-
if (empty($ids)) {
1957-
return 0;
1958-
}
1959-
1960-
try {
1961-
$name = $this->filter($collection);
1962-
$where = [];
1963-
1964-
if ($this->sharedTables) {
1965-
$where[] = "_tenant = :_tenant";
1966-
}
1967-
1968-
$where[] = "_uid IN (" . \implode(', ', \array_map(fn ($index) => ":_id_{$index}", \array_keys($ids))) . ")";
1969-
1970-
$sql = "DELETE FROM {$this->getSQLTable($name)} WHERE " . \implode(' AND ', $where);
1971-
1972-
$sql = $this->trigger(Database::EVENT_DOCUMENTS_DELETE, $sql);
1973-
1974-
$stmt = $this->getPDO()->prepare($sql);
1975-
1976-
foreach ($ids as $id => $value) {
1977-
$stmt->bindValue(":_id_{$id}", $value);
1978-
}
1979-
1980-
if ($this->sharedTables) {
1981-
$stmt->bindValue(':_tenant', $this->tenant);
1982-
}
1983-
1984-
$sql = "
1985-
DELETE FROM {$this->getSQLTable($name . '_perms')}
1986-
WHERE _document IN (" . \implode(', ', \array_map(fn ($index) => ":_id_{$index}", \array_keys($ids))) . ")
1987-
";
1988-
1989-
if ($this->sharedTables) {
1990-
$sql .= ' AND _tenant = :_tenant';
1991-
}
1992-
1993-
$sql = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $sql);
1994-
1995-
$stmtPermissions = $this->getPDO()->prepare($sql);
1996-
1997-
foreach ($ids as $id => $value) {
1998-
$stmtPermissions->bindValue(":_id_{$id}", $value);
1999-
}
2000-
2001-
if ($this->sharedTables) {
2002-
$stmtPermissions->bindValue(':_tenant', $this->tenant);
2003-
}
2004-
2005-
if (!$stmt->execute()) {
2006-
throw new DatabaseException('Failed to delete documents');
2007-
}
2008-
2009-
if (!$stmtPermissions->execute()) {
2010-
throw new DatabaseException('Failed to delete permissions');
2011-
}
2012-
} catch (\Throwable $e) {
2013-
throw new DatabaseException($e->getMessage(), $e->getCode(), $e);
2014-
}
2015-
2016-
return $stmt->rowCount();
2017-
}
2018-
20191698
/**
20201699
* Find Documents
20211700
*
@@ -2751,4 +2430,9 @@ public function getSupportForSchemaAttributes(): bool
27512430
return true;
27522431
}
27532432

2433+
protected function quote(string $string): string
2434+
{
2435+
return "`{$string}`";
2436+
}
2437+
27542438
}

0 commit comments

Comments
 (0)