diff --git a/app/init/resources.php b/app/init/resources.php index 56cccab428..ce50c1bfea 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -907,11 +907,12 @@ Http::setResource('getDatabasesDB', function (Group $pools, Cache $cache, Docume $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $pool = $pools->get($databaseDSN->getHost()); + $databaseHost = $databaseDSN->getHost(); + $pool = $pools->get($databaseHost); $adapter = new DatabasePool($pool); $database = new Database($adapter, $cache); - $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTables = \array_filter(\explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''))); $database ->setDatabase(APP_DATABASE) @@ -922,7 +923,28 @@ Http::setResource('getDatabasesDB', function (Group $pools, Cache $cache, Docume ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); // inside pools authorization needs to be set first $database->getAdapter()->setSupportForAttributes($databaseType !== DOCUMENTSDB); - if (\in_array($dsn->getHost(), $sharedTables)) { + + // For separate pools (documentsdb/vectorsdb), check their own shared tables config. + // If not configured, use dedicated mode to avoid cross-engine tenant type mismatches. + if ($databaseHost !== $dsn->getHost()) { + $dbTypeSharedTables = match ($databaseType) { + DOCUMENTSDB => \array_filter(\explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES', ''))), + VECTORSDB => \array_filter(\explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES', ''))), + default => [], + }; + + if (\in_array($databaseHost, $dbTypeSharedTables)) { + $database + ->setSharedTables(true) + ->setTenant($project->getSequence()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getSequence()); + } + } elseif (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getSequence()) diff --git a/app/worker.php b/app/worker.php index bffc3b4b7e..fb624b4cb8 100644 --- a/app/worker.php +++ b/app/worker.php @@ -245,7 +245,8 @@ Server::setResource('getDatabasesDB', function (Cache $cache, Registry $register } $pools = $register->get('pools'); - $pool = $pools->get($databaseDSN->getHost()); + $databaseHost = $databaseDSN->getHost(); + $pool = $pools->get($databaseHost); $adapter = new DatabasePool($pool); $database = new Database($adapter, $cache); @@ -254,9 +255,27 @@ Server::setResource('getDatabasesDB', function (Cache $cache, Registry $register ->setAuthorization($authorization); $database->getAdapter()->setSupportForAttributes($databaseType !== DOCUMENTSDB); - $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTables = \array_filter(\explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''))); - if (\in_array($dsn->getHost(), $sharedTables, true)) { + if ($databaseHost !== $dsn->getHost()) { + $dbTypeSharedTables = match ($databaseType) { + DOCUMENTSDB => \array_filter(\explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES', ''))), + VECTORSDB => \array_filter(\explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES', ''))), + default => [], + }; + + if (\in_array($databaseHost, $dbTypeSharedTables)) { + $database + ->setSharedTables(true) + ->setTenant($projectDocument->getSequence()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $projectDocument->getSequence()); + } + } elseif (\in_array($dsn->getHost(), $sharedTables, true)) { $database ->setSharedTables(true) ->setTenant($projectDocument->getSequence()) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php index 3585bc4477..3d07c65250 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Create.php @@ -61,16 +61,16 @@ class Create extends Action $databaseKeys = System::getEnv('_APP_DATABASE_DOCUMENTSDB_KEYS', ''); $databaseOverride = System::getEnv('_APP_DATABASE_DOCUMENTSDB_OVERRIDE'); $dbScheme = System::getEnv('_APP_DB_HOST_DOCUMENTSDB', 'mongodb'); - $databaseSharedTables = \explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES', '')); - $databaseSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES_V1', '')); + $databaseSharedTables = \array_filter(\explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES', ''))); + $databaseSharedTablesV1 = \array_filter(\explode(',', System::getEnv('_APP_DATABASE_DOCUMENTSDB_SHARED_TABLES_V1', ''))); break; case VECTORSDB: $databases = Config::getParam('pools-vectorsdb', []); $databaseKeys = System::getEnv('_APP_DATABASE_VECTORSDB_KEYS', ''); $databaseOverride = System::getEnv('_APP_DATABASE_VECTORSDB_OVERRIDE'); $dbScheme = System::getEnv('_APP_DB_HOST_VECTORSDB', 'postgresql'); - $databaseSharedTables = \explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES', '')); - $databaseSharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES_V1', '')); + $databaseSharedTables = \array_filter(\explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES', ''))); + $databaseSharedTablesV1 = \array_filter(\explode(',', System::getEnv('_APP_DATABASE_VECTORSDB_SHARED_TABLES_V1', ''))); break; default: // legacy/tablesdb @@ -108,7 +108,7 @@ class Create extends Action if ($index !== false) { $selectedDsn = $databases[$index]; } else { - if (!empty($dsn)) { + if (!empty($dsn) && !empty($databaseSharedTables)) { $beforeFilter = \array_values($databases); if ($isSharedTablesV1) { $databases = array_filter($databases, fn ($value) => \in_array($value, $databaseSharedTablesV1)); @@ -118,7 +118,10 @@ class Create extends Action $databases = array_filter($databases, fn ($value) => !\in_array($value, $databaseSharedTables)); } } - $selectedDsn = !empty($databases) ? $databases[array_rand($databases)] : ''; + if (empty($databases)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "No {$databasetype} database pool available for the current shared-tables mode"); + } + $selectedDsn = $databases[array_rand($databases)]; } if (\in_array($selectedDsn, $databaseSharedTables)) {