diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index a21ce60be..73535ea11 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -446,7 +446,7 @@ abstract public function createCollection(string $name, array $attributes = [], abstract public function deleteCollection(string $id): bool; /** - * Analyze a collection updating it's metadata on the database engine + * Analyze a collection updating its metadata on the database engine * * @param string $collection * @return bool @@ -1045,4 +1045,13 @@ abstract public function getInternalIndexesKeys(): array; * @throws DatabaseException */ abstract public function getSchemaAttributes(string $collection): array; + + /** + * Get the query to check for tenant when in shared tables mode + * + * @param string $collection The collection being queried + * @param string $parentAlias The alias of the parent collection if in a subquery + * @return string + */ + abstract public function getTenantQuery(string $collection, string $parentAlias = ''): string; } diff --git a/src/Database/Adapter/MariaDB.php b/src/Database/Adapter/MariaDB.php index 45d12e6fd..d4c15d032 100644 --- a/src/Database/Adapter/MariaDB.php +++ b/src/Database/Adapter/MariaDB.php @@ -1123,12 +1123,9 @@ public function updateDocument(string $collection, string $id, Document $documen SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); /** @@ -1200,12 +1197,9 @@ public function updateDocument(string $collection, string $id, Document $documen DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $removeQuery = $sql . $removeQuery; $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); @@ -1287,12 +1281,9 @@ public function updateDocument(string $collection, string $id, Document $documen UPDATE {$this->getSQLTable($name)} SET {$columns} _uid = :_newUid WHERE _uid = :_existingUid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_DOCUMENT_UPDATE, $sql); $stmt = $this->getPDO()->prepare($sql); @@ -1436,12 +1427,9 @@ public function updateDocuments(string $collection, Document $updates, array $do SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); $permissionsStmt = $this->getPDO()->prepare($sql); @@ -1481,14 +1469,9 @@ public function updateDocuments(string $collection, Document $updates, array $do $removeBindKeys[] = ':uid_' . $index; $removeBindValues[$bindKey] = $document->getId(); - $tenantQuery = ''; - if ($this->sharedTables) { - $tenantQuery = ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $removeQueries[] = "( _document = :uid_{$index} - {$tenantQuery} + {$this->getTenantQuery($collection)} AND _type = '{$type}' AND _permission IN (" . \implode(', ', \array_map(function (string $i) use ($permissionsToRemove, $index, $type, &$removeBindKeys, &$removeBindValues) { $bindKey = 'remove_' . $type . '_' . $index . '_' . $i; @@ -1616,11 +1599,9 @@ public function increaseDocumentAttribute(string $collection, string $id, string `{$attribute}` = `{$attribute}` + :val, `_updatedAt` = :updatedAt WHERE _uid = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } $sql .= $sqlMax . $sqlMin; @@ -1656,12 +1637,9 @@ public function deleteDocument(string $collection, string $id): bool $sql = " DELETE FROM {$this->getSQLTable($name)} WHERE _uid = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_DOCUMENT_DELETE, $sql); $stmt = $this->getPDO()->prepare($sql); @@ -1675,12 +1653,9 @@ public function deleteDocument(string $collection, string $id): bool $sql = " DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $sql); $stmtPermissions = $this->getPDO()->prepare($sql); @@ -1886,7 +1861,13 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, } if ($this->sharedTables) { - $where[] = "(table_main._tenant = :_tenant OR table_main._tenant IS NULL)"; + $orIsNull = ''; + + if ($collection === Database::METADATA) { + $orIsNull = " OR table_main._tenant IS NULL"; + } + + $where[] = "(table_main._tenant = :_tenant {$orIsNull})"; } $sqlWhere = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : ''; @@ -2014,7 +1995,13 @@ public function count(string $collection, array $queries = [], ?int $max = null) } if ($this->sharedTables) { - $where[] = "(table_main._tenant = :_tenant OR table_main._tenant IS NULL)"; + $orIsNull = ''; + + if ($collection === Database::METADATA) { + $orIsNull = " OR table_main._tenant IS NULL"; + } + + $where[] = "(table_main._tenant = :_tenant {$orIsNull})"; } $sqlWhere = !empty($where) @@ -2086,7 +2073,13 @@ public function sum(string $collection, string $attribute, array $queries = [], } if ($this->sharedTables) { - $where[] = "(table_main._tenant = :_tenant OR table_main._tenant IS NULL)"; + $orIsNull = ''; + + if ($collection === Database::METADATA) { + $orIsNull = " OR table_main._tenant IS NULL"; + } + + $where[] = "(table_main._tenant = :_tenant {$orIsNull})"; } $sqlWhere = !empty($where) diff --git a/src/Database/Adapter/Mongo.php b/src/Database/Adapter/Mongo.php index 5df46e28e..b67db87ec 100644 --- a/src/Database/Adapter/Mongo.php +++ b/src/Database/Adapter/Mongo.php @@ -798,6 +798,7 @@ private function insertDocument(string $name, array $document): array $filters = []; $filters['_uid'] = $document['_uid']; + if ($this->sharedTables) { $filters['_tenant'] = (string)$this->getTenant(); } @@ -1963,4 +1964,8 @@ public function getSchemaAttributes(string $collection): array return []; } + public function getTenantQuery(string $collection, string $parentAlias = ''): string + { + return (string)$this->getTenant(); + } } diff --git a/src/Database/Adapter/Postgres.php b/src/Database/Adapter/Postgres.php index b55365961..d808a82dc 100644 --- a/src/Database/Adapter/Postgres.php +++ b/src/Database/Adapter/Postgres.php @@ -1161,12 +1161,9 @@ public function updateDocument(string $collection, string $id, Document $documen SELECT _type, _permission FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); /** @@ -1239,12 +1236,9 @@ public function updateDocument(string $collection, string $id, Document $documen DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $removeQuery = $sql . $removeQuery; $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); @@ -1311,12 +1305,9 @@ public function updateDocument(string $collection, string $id, Document $documen UPDATE {$this->getSQLTable($name)} SET {$columns} _uid = :_newUid WHERE _uid = :_existingUid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_DOCUMENT_UPDATE, $sql); $stmt = $this->getPDO()->prepare($sql); @@ -1395,7 +1386,13 @@ public function updateDocuments(string $collection, Document $updates, array $do $where[] = "_uid IN (" . \implode(', ', \array_map(fn ($index) => ":_id_{$index}", \array_keys($ids))) . ")"; if ($this->sharedTables) { - $where[] = "(_tenant = :_tenant OR _tenant IS NULL)"; + $whereTenant = "(_tenant = :_tenant"; + + if ($collection === Database::METADATA) { + $whereTenant .= " OR _tenant IS NULL"; + } + + $where[] = $whereTenant . ')'; } $sqlWhere = 'WHERE ' . implode(' AND ', $where); @@ -1504,14 +1501,9 @@ public function updateDocuments(string $collection, Document $updates, array $do $removeBindKeys[] = ':uid_' . $index; $removeBindValues[$bindKey] = $document->getId(); - $tenantQuery = ''; - if ($this->sharedTables) { - $tenantQuery = ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $removeQueries[] = "( _document = :uid_{$index} - {$tenantQuery} + {$this->getTenantQuery($collection)} AND _type = '{$type}' AND _permission IN (" . \implode(', ', \array_map(function (string $i) use ($permissionsToRemove, $index, $type, &$removeBindKeys, &$removeBindValues) { $bindKey = 'remove_' . $type . '_' . $index . '_' . $i; @@ -1638,13 +1630,10 @@ public function increaseDocumentAttribute(string $collection, string $id, string SET \"{$attribute}\" = \"{$attribute}\" + :val, \"_updatedAt\" = :updatedAt - WHERE _uid = :_uid + WHERE _uid = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql .= $sqlMax . $sqlMin; $sql = $this->trigger(Database::EVENT_DOCUMENT_UPDATE, $sql); @@ -1677,12 +1666,9 @@ public function deleteDocument(string $collection, string $id): bool $sql = " DELETE FROM {$this->getSQLTable($name)} WHERE _uid = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_DOCUMENT_DELETE, $sql); $stmt = $this->getPDO()->prepare($sql); $stmt->bindValue(':_uid', $id, PDO::PARAM_STR); @@ -1694,12 +1680,9 @@ public function deleteDocument(string $collection, string $id): bool $sql = " DELETE FROM {$this->getSQLTable($name . '_perms')} WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= ' AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - $sql = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $sql); $stmtPermissions = $this->getPDO()->prepare($sql); @@ -1903,7 +1886,13 @@ public function find(string $collection, array $queries = [], ?int $limit = 25, } if ($this->sharedTables) { - $where[] = "(table_main._tenant = :_tenant OR table_main._tenant IS NULL)"; + $orIsNull = ''; + + if ($collection === Database::METADATA) { + $orIsNull = " OR table_main._tenant IS NULL"; + } + + $where[] = "(table_main._tenant = :_tenant {$orIsNull})"; } if (Authorization::$status) { @@ -2031,7 +2020,13 @@ public function count(string $collection, array $queries = [], ?int $max = null) } if ($this->sharedTables) { - $where[] = "(table_main._tenant = :_tenant OR table_main._tenant IS NULL)"; + $orIsNull = ''; + + if ($collection === Database::METADATA) { + $orIsNull = " OR table_main._tenant IS NULL"; + } + + $where[] = "(table_main._tenant = :_tenant {$orIsNull})"; } if (Authorization::$status) { @@ -2096,7 +2091,13 @@ public function sum(string $collection, string $attribute, array $queries = [], } if ($this->sharedTables) { - $where[] = "(table_main._tenant = :_tenant OR table_main._tenant IS NULL)"; + $orIsNull = ''; + + if ($collection === Database::METADATA) { + $orIsNull = " OR table_main._tenant IS NULL"; + } + + $where[] = "(table_main._tenant = :_tenant {$orIsNull})"; } if (Authorization::$status) { diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index e5bcda7c1..f731d8bdd 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -216,12 +216,9 @@ public function getDocument(string $collection, string $id, array $queries = [], SELECT {$this->getAttributeProjection($selections)} FROM {$this->getSQLTable($name)} WHERE _uid = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= "AND (_tenant = :_tenant OR _tenant IS NULL)"; - } - if ($this->getSupportForUpdateLock()) { $sql .= " {$forUpdate}"; } @@ -1045,17 +1042,12 @@ protected function getSQLPermissionsCondition(string $collection, array $roles, $roles = array_map(fn (string $role) => $this->getPDO()->quote($role), $roles); - $tenantQuery = ''; - if ($this->sharedTables) { - $tenantQuery = 'AND (_tenant = :_tenant OR _tenant IS NULL)'; - } - return "table_main._uid IN ( SELECT _document FROM {$this->getSQLTable($collection . '_perms')} WHERE _permission IN (" . implode(', ', $roles) . ") AND _type = '{$type}' - {$tenantQuery} + {$this->getTenantQuery($collection)} )"; } @@ -1171,13 +1163,34 @@ public function getInternalIndexesKeys(): array return []; } - protected function processException(PDOException $e): \Exception + public function getSchemaAttributes(string $collection): array { - return $e; + return []; } - public function getSchemaAttributes(string $collection): array + public function getTenantQuery(string $collection, string $parentAlias = ''): string { - return []; + if (!$this->sharedTables) { + return ''; + } + + if (!empty($parentAlias) || $parentAlias === '0') { + $parentAlias .= '.'; + } + + $query = "AND ({$parentAlias}_tenant = :_tenant"; + + if ($collection === Database::METADATA) { + $query .= " OR {$parentAlias}_tenant IS NULL"; + } + + $query .= ")"; + + return $query; + } + + protected function processException(PDOException $e): \Exception + { + return $e; } } diff --git a/src/Database/Adapter/SQLite.php b/src/Database/Adapter/SQLite.php index 07cad6999..8603a6cbb 100644 --- a/src/Database/Adapter/SQLite.php +++ b/src/Database/Adapter/SQLite.php @@ -660,12 +660,9 @@ public function updateDocument(string $collection, string $id, Document $documen SELECT _type, _permission FROM `{$this->getNamespace()}_{$name}_perms` WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= " AND (_tenant = :_tenant OR _tenant IS NULL)"; - } - $sql = $this->trigger(Database::EVENT_PERMISSIONS_READ, $sql); /** @@ -737,12 +734,9 @@ public function updateDocument(string $collection, string $id, Document $documen DELETE FROM `{$this->getNamespace()}_{$name}_perms` WHERE _document = :_uid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= " AND (_tenant = :_tenant OR _tenant IS NULL)"; - } - $removeQuery = $sql . $removeQuery; $removeQuery = $this->trigger(Database::EVENT_PERMISSIONS_DELETE, $removeQuery); @@ -809,12 +803,9 @@ public function updateDocument(string $collection, string $id, Document $documen UPDATE `{$this->getNamespace()}_{$name}` SET {$columns} _uid = :_newUid WHERE _uid = :_existingUid + {$this->getTenantQuery($collection)} "; - if ($this->sharedTables) { - $sql .= " AND (_tenant = :_tenant OR _tenant IS NULL)"; - } - $sql = $this->trigger(Database::EVENT_DOCUMENT_UPDATE, $sql); $stmt = $this->getPDO()->prepare($sql);