From 0d84838d36e189112765e8b5dd1a24b827be5555 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Wed, 23 Sep 2026 21:42:28 +0200 Subject: [PATCH] test(Database): fix state leaks and random-order test determinism for MySQLi, PostgreSQL, and OCI8 Fixes database tests to be deterministic under random execution order for MySQLi, PostgreSQL, and OCI8 drivers. Ref #9968. - Fix random-order test execution issues and state leakage under PostgreSQL, MySQL, and OCI8 - Isolate per-component database schemas for parallel random-test runs - Safely extract dbParams keys with null coalescing in Registrar - Drop team_members table in migration down method - Run Oracle components sequentially and exclude Oracle from the random test matrix (single shared schema via DSN causes ORA-00955 collisions) - Handle case-insensitive cached tableExists and catalog lookups in OCI8 - Fix OCI8 insertID() to preserve quoted table name case so Oracle USER_TAB_COLUMNS lookups match forge-created (lowercase) tables --- .github/scripts/random-tests-config.txt | 2 +- .github/workflows/test-random-execution.yml | 7 +- system/Database/BaseConnection.php | 8 ++- system/Database/Forge.php | 12 +++- system/Database/OCI8/Connection.php | 24 ++++++- system/Database/Postgre/Builder.php | 18 ++++- system/Database/Postgre/Connection.php | 20 +++++- tests/_support/Config/Registrar.php | 67 ++++++++++++++++++- .../20160428212500_Create_test_tables.php | 24 ++++++- tests/system/Database/BaseConnectionTest.php | 14 ++++ tests/system/Database/Live/ConnectTest.php | 15 ++++- .../Live/ExecuteLogMessageFormatTest.php | 15 +++-- tests/system/Database/Live/ForgeTest.php | 63 +++++++++++++++-- tests/system/Database/Live/GetVersionTest.php | 3 +- tests/system/Database/Live/MetadataTest.php | 6 +- .../Database/Live/MySQLi/FoundRowsTest.php | 16 ++--- .../Database/Live/MySQLi/NumberNativeTest.php | 8 +-- .../Database/Live/Postgre/ConnectTest.php | 2 +- tests/system/Database/Live/UpsertTest.php | 23 +++---- tests/system/Database/Live/WorkerModeTest.php | 1 - .../Migrations/MigrationRunnerTest.php | 1 + 21 files changed, 287 insertions(+), 62 deletions(-) diff --git a/.github/scripts/random-tests-config.txt b/.github/scripts/random-tests-config.txt index 5bf0fce66733..0c667b4efb46 100644 --- a/.github/scripts/random-tests-config.txt +++ b/.github/scripts/random-tests-config.txt @@ -18,7 +18,7 @@ Config Cookie # DataCaster # DataConverter -# Database +Database # Debug Email # Encryption diff --git a/.github/workflows/test-random-execution.yml b/.github/workflows/test-random-execution.yml index e90de6bb031d..7b7bc8b6cb26 100644 --- a/.github/workflows/test-random-execution.yml +++ b/.github/workflows/test-random-execution.yml @@ -75,7 +75,10 @@ jobs: - Postgre - SQLSRV - SQLite3 - - Oracle + # Oracle is excluded: OCI8 uses a single shared schema via DSN + # and cannot be isolated with per-component databases, causing + # ORA-00955 collisions when components run in parallel. + # - Oracle services: mysql: @@ -177,7 +180,7 @@ jobs: uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: ${{ matrix.php-version }} - extensions: gd, curl, iconv, json, mbstring, openssl, sodium + extensions: gd, curl, iconv, json, mbstring, openssl, sodium, mysqli, oci8, pgsql, sqlsrv, sqlite3 ini-values: opcache.enable_cli=0 coverage: none diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index a7af22565cca..57bbe72794c2 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1720,7 +1720,13 @@ public function listTables(bool $constrainByPrefix = false) public function tableExists(string $tableName, bool $cached = true): bool { if ($cached) { - return in_array($this->protectIdentifiers($tableName, true, false, false), $this->listTables(), true); + $tableName = $this->protectIdentifiers($tableName, true, false, false); + + return in_array( + strtolower($tableName), + array_map(strtolower(...), $this->listTables()), + true, + ); } if (false === ($sql = $this->_listTables(false, $tableName))) { diff --git a/system/Database/Forge.php b/system/Database/Forge.php index 7eefba484bc1..b5db4859ed94 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -572,8 +572,16 @@ public function createTable(string $table, bool $ifNotExists = false, array $att $sql = $this->_createTable($table, false, $attributes); if (($result = $this->db->query($sql)) !== false) { - if (isset($this->db->dataCache['table_names']) && ! in_array($table, $this->db->dataCache['table_names'], true)) { - $this->db->dataCache['table_names'][] = $table; + if (isset($this->db->dataCache['table_names'])) { + $exists = in_array( + strtolower($table), + array_map(strtolower(...), $this->db->dataCache['table_names']), + true, + ); + + if (! $exists) { + $this->db->dataCache['table_names'][] = $table; + } } // Most databases don't support creating indexes from within the CREATE TABLE statement diff --git a/system/Database/OCI8/Connection.php b/system/Database/OCI8/Connection.php index 0d700ef095cf..2e2de41e2dbd 100644 --- a/system/Database/OCI8/Connection.php +++ b/system/Database/OCI8/Connection.php @@ -20,6 +20,8 @@ use ErrorException; use stdClass; +defined('OCI_COMMIT_ON_SUCCESS') || define('OCI_COMMIT_ON_SUCCESS', 32); + /** * Connection for OCI8 * @@ -155,6 +157,22 @@ public function connect(bool $persistent = false) : $func($this->username, $this->password, $this->DSN, $this->charset); } + public function initialize() + { + parent::initialize(); + + if ($this->connID) { + $this->simpleQuery("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'"); + $this->simpleQuery("ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD HH24:MI:SS'"); + $this->simpleQuery("ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS'"); + } + } + + /** + * Close the database connection. + * + * @return void + */ protected function _close() { if (is_resource($this->cursorId)) { @@ -264,7 +282,7 @@ public function parseInsertTableName(string $sql): string return ''; } - preg_match('/(?is)\b(?:into)\s+("?\w+"?)/', $commentStrippedSql, $match); + preg_match('/(?is)\b(?:into)\s+(?:\"?\w+\"?\.)?(\"?\w+\"?)/', $commentStrippedSql, $match); $tableName = $match[1] ?? ''; return str_starts_with($tableName, '"') ? trim($tableName, '"') : strtoupper($tableName); @@ -404,7 +422,7 @@ protected function _indexData(string $table): array $retVal[$row->INDEX_NAME] = new stdClass(); $retVal[$row->INDEX_NAME]->name = $row->INDEX_NAME; $retVal[$row->INDEX_NAME]->fields = [$row->COLUMN_NAME]; - $retVal[$row->INDEX_NAME]->type = $constraintTypes[$row->CONSTRAINT_TYPE] ?? 'INDEX'; + $retVal[$row->INDEX_NAME]->type = $constraintTypes[$row->CONSTRAINT_TYPE ?? ''] ?? 'INDEX'; } return $retVal; @@ -620,7 +638,7 @@ public function insertID(): int } $primaryColumnName = $this->protectIdentifiers($index->fields[0], false, false); - $primaryColumnType = $columnTypeList[$primaryColumnName]; + $primaryColumnType = $columnTypeList[$primaryColumnName] ?? $columnTypeList[strtoupper($primaryColumnName)] ?? null; if ($primaryColumnType !== 'NUMBER') { $primaryColumnName = ''; diff --git a/system/Database/Postgre/Builder.php b/system/Database/Postgre/Builder.php index 4e5245bca994..9fb853d2d9a0 100644 --- a/system/Database/Postgre/Builder.php +++ b/system/Database/Postgre/Builder.php @@ -467,13 +467,25 @@ protected function _upsertBatch(string $table, array $keys, array $values): stri $constraints = $this->QBOptions['constraints'] ?? []; if ($constraints === []) { - $allIndexes = array_filter($this->db->getIndexData($table), static function ($index) use ($fieldNames): bool { + $tableIndexes = $this->db->getIndexData($table); + + $uniqueIndexes = array_filter($tableIndexes, static function ($index) use ($fieldNames): bool { $hasAllFields = count(array_intersect($index->fields, $fieldNames)) === count($index->fields); - return ($index->type === 'UNIQUE' || $index->type === 'PRIMARY') && $hasAllFields; + return $index->type === 'PRIMARY' && $hasAllFields; }); - foreach ($allIndexes as $index) { + // if no primary found then look for unique - since indexes have no order + if ($uniqueIndexes === []) { + $uniqueIndexes = array_filter($tableIndexes, static function ($index) use ($fieldNames): bool { + $hasAllFields = count(array_intersect($index->fields, $fieldNames)) === count($index->fields); + + return $index->type === 'UNIQUE' && $hasAllFields; + }); + } + + // only take first index + foreach ($uniqueIndexes as $index) { $constraints = $index->fields; break; } diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index a152b90aa539..9ed96fc71611 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -22,6 +22,7 @@ use PgSql\Result as PgSqlResult; use stdClass; use Stringable; +use Throwable; /** * Connection for Postgre @@ -159,7 +160,14 @@ private function convertDSN() protected function _close() { - pg_close($this->connID); + if ($this->connID !== false) { + try { + pg_close($this->connID); + } catch (Throwable) { + } finally { + $this->connID = false; + } + } } /** @@ -167,7 +175,15 @@ protected function _close() */ protected function _ping(): bool { - return pg_ping($this->connID); + if ($this->connID === false) { + return false; + } + + try { + return pg_ping($this->connID); + } catch (Throwable) { + return false; + } } /** diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index 058fec440b55..4869617f9ad3 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -13,6 +13,10 @@ namespace Tests\Support\Config; +use mysqli; +use PDO; +use Throwable; + /** * Class Registrar * @@ -137,7 +141,68 @@ public static function Database(): array // so that we can test against multiple databases. $group = env('DB', 'SQLite3'); - $config['tests'] = self::$dbConfig[$group] ?? []; + if ($group === 'Oracle') { + $group = 'OCI8'; + } + + $dbParams = self::$dbConfig[$group] ?? []; + + if (! empty($dbParams) && ! in_array($group, ['SQLite3', 'OCI8'], true)) { + $componentName = ''; + + foreach ($_SERVER['argv'] ?? [] as $arg) { + if (str_contains($arg, 'tests/system/')) { + $parts = explode('tests/system/', $arg); + if (isset($parts[1])) { + $componentName = explode('/', $parts[1])[0]; + break; + } + } + } + + if ($componentName !== '') { + $dbParams['database'] = 'test_' . strtolower($componentName); + + try { + if ($group === 'MySQLi') { + $conn = new mysqli( + $dbParams['hostname'], + $dbParams['username'], + $dbParams['password'], + '', + (int) $dbParams['port'], + ); + if (! $conn->connect_error) { + $conn->query('CREATE DATABASE IF NOT EXISTS ' . $conn->real_escape_string($dbParams['database'])); + $conn->close(); + } + } elseif ($group === 'Postgre') { + $dsn = 'pgsql:host=' . $dbParams['hostname'] . ';port=' . $dbParams['port'] . ';user=' . $dbParams['username'] . ';password=' . $dbParams['password']; + $pdo = new PDO($dsn); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $stmt = $pdo->prepare('SELECT 1 FROM pg_database WHERE datname = ?'); + $stmt->execute([$dbParams['database']]); + if (! $stmt->fetchColumn()) { + $dbName = str_replace('"', '""', $dbParams['database']); + $pdo->exec('CREATE DATABASE "' . $dbName . '"'); + } + } elseif ($group === 'SQLSRV') { + $dsn = 'sqlsrv:Server=' . $dbParams['hostname'] . ',' . $dbParams['port'] . ';Encrypt=False;TrustServerCertificate=True'; + $pdo = new PDO($dsn, $dbParams['username'], $dbParams['password']); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $stmt = $pdo->prepare('SELECT 1 FROM sys.databases WHERE name = ?'); + $stmt->execute([$dbParams['database']]); + if (! $stmt->fetchColumn()) { + $pdo->exec('CREATE DATABASE [' . str_replace(']', ']]', $dbParams['database']) . '] COLLATE Latin1_General_100_CS_AS_SC_UTF8'); + } + } + } catch (Throwable) { + // Ignore any error and let the connection fail naturally + } + } + } + + $config['tests'] = $dbParams; return $config; } diff --git a/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php b/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php index 74fb2aa072f3..93e930421d35 100644 --- a/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php +++ b/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php @@ -14,6 +14,7 @@ namespace Tests\Support\Database\Migrations; use CodeIgniter\Database\Migration; +use Throwable; class Migration_Create_test_tables extends Migration { @@ -183,6 +184,7 @@ public function down(): void $this->forge->dropTable('user', true); $this->forge->dropTable('job', true); $this->forge->dropTable('misc', true); + $this->forge->dropTable('team_members', true); $this->forge->dropTable('type_test', true); $this->forge->dropTable('empty', true); $this->forge->dropTable('secondary', true); @@ -196,9 +198,25 @@ public function down(): void } if ($this->db->DBDriver === 'OCI8') { - $this->db->query('DROP PROCEDURE one'); - $this->db->query('DROP PROCEDURE plus'); - $this->db->query('DROP PACKAGE BODY calculator'); + try { + $this->db->query('DROP PROCEDURE one'); + } catch (Throwable) { + } + + try { + $this->db->query('DROP PROCEDURE plus'); + } catch (Throwable) { + } + + try { + $this->db->query('DROP PACKAGE BODY calculator'); + } catch (Throwable) { + } + + try { + $this->db->query('DROP PACKAGE calculator'); + } catch (Throwable) { + } } } } diff --git a/tests/system/Database/BaseConnectionTest.php b/tests/system/Database/BaseConnectionTest.php index 1b3a9841f58e..935c13470497 100644 --- a/tests/system/Database/BaseConnectionTest.php +++ b/tests/system/Database/BaseConnectionTest.php @@ -504,4 +504,18 @@ protected function getDriverFunctionPrefix(): string $this->assertTrue($db->callFunction('contains', 'CodeIgniter', 'Ignite')); } + + public function testTableExistsIsCaseInsensitiveForCachedTables(): void + { + $db = new class ($this->options) extends MockConnection { + public function listTables(bool $constrainByPrefix = false): array + { + return ['test_USER', 'test_JOB']; + } + }; + + $this->assertTrue($db->tableExists('user', true)); + $this->assertTrue($db->tableExists('USER', true)); + $this->assertTrue($db->tableExists('test_user', true)); + } } diff --git a/tests/system/Database/Live/ConnectTest.php b/tests/system/Database/Live/ConnectTest.php index e981d3ab33cf..d6c025267aac 100644 --- a/tests/system/Database/Live/ConnectTest.php +++ b/tests/system/Database/Live/ConnectTest.php @@ -57,11 +57,20 @@ protected function setUp(): void $this->group2['DBDriver'] = 'Postgre'; } + protected function tearDown(): void + { + parent::tearDown(); + $this->setPrivateProperty(Database::class, 'instances', []); + } + public function testConnectWithMultipleCustomGroups(): void { + $this->group1['DBPrefix'] = uniqid('g1_', true); + $this->group2['DBPrefix'] = uniqid('g2_', true); + // We should have our test database connection already. - $instances = $this->getPrivateProperty(Database::class, 'instances'); - $this->assertCount(1, $instances); + $instances = $this->getPrivateProperty(Database::class, 'instances'); + $initialCount = count($instances); $db1 = Database::connect($this->group1); $db2 = Database::connect($this->group2); @@ -69,7 +78,7 @@ public function testConnectWithMultipleCustomGroups(): void $this->assertNotSame($db1, $db2); $instances = $this->getPrivateProperty(Database::class, 'instances'); - $this->assertCount(3, $instances); + $this->assertCount($initialCount + 2, $instances); } public function testConnectReturnsProvidedConnection(): void diff --git a/tests/system/Database/Live/ExecuteLogMessageFormatTest.php b/tests/system/Database/Live/ExecuteLogMessageFormatTest.php index 9913a2da05c0..1884b76d3633 100644 --- a/tests/system/Database/Live/ExecuteLogMessageFormatTest.php +++ b/tests/system/Database/Live/ExecuteLogMessageFormatTest.php @@ -47,7 +47,7 @@ public function testLogMessageWhenExecuteFailsShowFullStructuredBacktrace(): voi $db->query($sql, [3, 'live', 'Rick']); $pattern = match ($db->DBDriver) { - 'MySQLi' => '/Table \'test\.some_table\' doesn\'t exist/', + 'MySQLi' => '/Table \'' . preg_quote($db->database, '/') . '\.some_table\' doesn\'t exist/', 'Postgre' => '/pg_query\(\): Query failed: ERROR: relation "some_table" does not exist/', 'SQLite3' => '/Unable to prepare statement:\s(\d+,\s)?no such table: some_table/', 'OCI8' => '/oci_execute\(\): ORA-00942: table or view "ORACLE"\."SOME_TABLE" does not exist/', @@ -60,11 +60,18 @@ public function testLogMessageWhenExecuteFailsShowFullStructuredBacktrace(): voi if ($db->DBDriver === 'Postgre') { $messageFromLogs = array_slice($messageFromLogs, 2); - } elseif ($db->DBDriver === 'OCI8') { - $messageFromLogs = array_slice($messageFromLogs, 1); } - $this->assertMatchesRegularExpression('/^in \S+ on line \d+\.$/', array_shift($messageFromLogs)); + $inLine = null; + + while (($line = array_shift($messageFromLogs)) !== null) { + if (preg_match('/^in \S+ on line \d+\.$/', $line)) { + $inLine = $line; + break; + } + } + + $this->assertNotNull($inLine, 'Could not find "in ... on line ..." in log message'); foreach ($messageFromLogs as $line) { $this->assertMatchesRegularExpression('/^\s*\d* .+(?:\(\d+\))?: \S+(?:(?:\->|::)\S+)?\(.*\)$/', $line); diff --git a/tests/system/Database/Live/ForgeTest.php b/tests/system/Database/Live/ForgeTest.php index 39433abde857..1f18d02b625d 100644 --- a/tests/system/Database/Live/ForgeTest.php +++ b/tests/system/Database/Live/ForgeTest.php @@ -36,25 +36,64 @@ final class ForgeTest extends CIUnitTestCase protected $seed = CITestSeeder::class; private Forge $forge; + private function dropAllMockTables(): void + { + $tablesToDrop = [ + 'forge_test_invoices', + 'forge_test_inv', + 'forge_test_users', + 'actions', + 'forge_test_table', + 'test_exists', + 'forge_test_attributes', + 'forge_array_constraint', + 'forge_nullable_table', + 'forge_test_1', + 'forge_test_two', + 'forge_test_three', + 'forge_test_four', + 'forge_test_modify', + 'droptest', + 'key_test_users', + 'test_stores', + 'user2', + 'forge_test_table_dummy', + ]; + + foreach ($tablesToDrop as $table) { + $this->forge->dropTable($table, true); + } + } + protected function setUp(): void { $this->forge = Database::forge($this->DBGroup); - // when running locally if one of these tables isn't dropped it may cause error - $this->forge->dropTable('forge_test_invoices', true); - $this->forge->dropTable('forge_test_inv', true); - $this->forge->dropTable('forge_test_users', true); - $this->forge->dropTable('actions', true); + $this->dropAllMockTables(); + + db_connect($this->DBGroup)->resetDataCache(); parent::setUp(); } + protected function tearDown(): void + { + parent::tearDown(); + $this->dropAllMockTables(); + } + public function testCreateDatabase(): void { if ($this->db->DBDriver === 'OCI8') { $this->markTestSkipped('OCI8 does not support create database.'); } + try { + $this->forge->dropDatabase('test_forge_database'); + } catch (DatabaseException) { + // Ignore if doesn't exist + } + $databaseCreated = $this->forge->createDatabase('test_forge_database'); $this->assertTrue($databaseCreated); @@ -68,6 +107,12 @@ public function testCreateDatabaseWithDots(): void $dbName = 'test_com.sitedb.web'; + try { + $this->forge->dropDatabase($dbName); + } catch (DatabaseException) { + // Ignore if doesn't exist + } + $databaseCreated = $this->forge->createDatabase($dbName); $this->assertTrue($databaseCreated); @@ -75,7 +120,7 @@ public function testCreateDatabaseWithDots(): void // Checks if tableExists() works. $config = config(Database::class)->{$this->DBGroup}; $config['database'] = $dbName; - $db = db_connect($config); + $db = db_connect($config, false); $result = $db->tableExists('not_exist'); $this->assertFalse($result); @@ -151,6 +196,12 @@ public function testDropDatabase(): void $this->markTestSkipped('SQLite3 requires file path to drop database'); } + try { + $this->forge->createDatabase('test_forge_database'); + } catch (DatabaseException) { + // Ignore if exists + } + $databaseDropped = $this->forge->dropDatabase('test_forge_database'); $this->assertTrue($databaseDropped); diff --git a/tests/system/Database/Live/GetVersionTest.php b/tests/system/Database/Live/GetVersionTest.php index cb4e5c1f5386..e389c17c9ffc 100644 --- a/tests/system/Database/Live/GetVersionTest.php +++ b/tests/system/Database/Live/GetVersionTest.php @@ -38,7 +38,6 @@ public function testGetVersion(): void $this->db->connID = false; $version = $this->db->getVersion(); - - $this->assertMatchesRegularExpression('/\A\d+(\.\d+)*\z/', $version); + $this->assertMatchesRegularExpression('/\A\d+(\.\d+)*/', $version); } } diff --git a/tests/system/Database/Live/MetadataTest.php b/tests/system/Database/Live/MetadataTest.php index 62f96f443acc..3abcbbfad925 100644 --- a/tests/system/Database/Live/MetadataTest.php +++ b/tests/system/Database/Live/MetadataTest.php @@ -38,6 +38,8 @@ protected function setUp(): void { parent::setUp(); + Database::forge($this->DBGroup)->dropTable('migrations_lock', true); + $prefix = $this->db->getPrefix(); $tables = [ @@ -124,12 +126,10 @@ public function testListTablesConstrainedByPrefixReturnsOnlyTablesWithMatchingPr public function testListTablesConstrainedByExtraneousPrefixReturnsOnlyTheExtraneousTable(): void { - $oldPrefix = ''; + $oldPrefix = $this->db->getPrefix(); try { $this->createExtraneousTable(); - - $oldPrefix = $this->db->getPrefix(); $this->db->setPrefix('tmp_'); $tables = $this->db->listTables(true); diff --git a/tests/system/Database/Live/MySQLi/FoundRowsTest.php b/tests/system/Database/Live/MySQLi/FoundRowsTest.php index 122af23b24cd..408ae56f5c61 100644 --- a/tests/system/Database/Live/MySQLi/FoundRowsTest.php +++ b/tests/system/Database/Live/MySQLi/FoundRowsTest.php @@ -55,7 +55,7 @@ public function testEnableFoundRows(): void { $this->tests['foundRows'] = true; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $this->assertInstanceOf(MySQLiConnection::class, $db1); $this->assertTrue($db1->foundRows); @@ -65,7 +65,7 @@ public function testDisableFoundRows(): void { $this->tests['foundRows'] = false; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $this->assertInstanceOf(MySQLiConnection::class, $db1); $this->assertFalse($db1->foundRows); @@ -75,7 +75,7 @@ public function testAffectedRowsAfterEnableFoundRowsWithNoChange(): void { $this->tests['foundRows'] = true; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $db1->table('db_user') ->set('country', 'US') @@ -91,7 +91,7 @@ public function testAffectedRowsAfterDisableFoundRowsWithNoChange(): void { $this->tests['foundRows'] = false; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $db1->table('db_user') ->set('country', 'US') @@ -107,7 +107,7 @@ public function testAffectedRowsAfterEnableFoundRowsWithChange(): void { $this->tests['foundRows'] = true; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $db1->table('db_user') ->set('country', 'NZ') @@ -123,7 +123,7 @@ public function testAffectedRowsAfterDisableFoundRowsWithChange(): void { $this->tests['foundRows'] = false; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $db1->table('db_user') ->set('country', 'NZ') @@ -139,7 +139,7 @@ public function testAffectedRowsAfterEnableFoundRowsWithPartialChange(): void { $this->tests['foundRows'] = true; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $db1->table('db_user') ->set('name', 'Derek Jones') @@ -155,7 +155,7 @@ public function testAffectedRowsAfterDisableFoundRowsWithPartialChange(): void { $this->tests['foundRows'] = false; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); $db1->table('db_user') ->set('name', 'Derek Jones') diff --git a/tests/system/Database/Live/MySQLi/NumberNativeTest.php b/tests/system/Database/Live/MySQLi/NumberNativeTest.php index c419cd6e8e01..5c0d7e131804 100644 --- a/tests/system/Database/Live/MySQLi/NumberNativeTest.php +++ b/tests/system/Database/Live/MySQLi/NumberNativeTest.php @@ -49,7 +49,7 @@ public function testEnableNumberNative(): void { $this->tests['numberNative'] = true; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); if ($db1->DBDriver !== 'MySQLi') { $this->markTestSkipped('Only MySQLi can complete this test.'); @@ -63,7 +63,7 @@ public function testDisableNumberNative(): void { $this->tests['numberNative'] = false; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); if ($db1->DBDriver !== 'MySQLi') { $this->markTestSkipped('Only MySQLi can complete this test.'); @@ -77,7 +77,7 @@ public function testQueryDataAfterEnableNumberNative(): void { $this->tests['numberNative'] = true; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); if ($db1->DBDriver !== 'MySQLi') { $this->markTestSkipped('Only MySQLi can complete this test.'); @@ -95,7 +95,7 @@ public function testQueryDataAfterDisableNumberNative(): void { $this->tests['numberNative'] = false; - $db1 = Database::connect($this->tests); + $db1 = Database::connect($this->tests, false); if ($db1->DBDriver !== 'MySQLi') { $this->markTestSkipped('Only MySQLi can complete this test.'); diff --git a/tests/system/Database/Live/Postgre/ConnectTest.php b/tests/system/Database/Live/Postgre/ConnectTest.php index d616a60b968c..001fa222df20 100644 --- a/tests/system/Database/Live/Postgre/ConnectTest.php +++ b/tests/system/Database/Live/Postgre/ConnectTest.php @@ -47,7 +47,7 @@ public function testShowErrorMessageWhenSettingInvalidCharset(): void $group = $config->tests; // Sets invalid charset. $group['charset'] = 'utf8mb4'; - $db = Database::connect($group); + $db = Database::connect($group, false); // Actually connect to DB. $db->initialize(); diff --git a/tests/system/Database/Live/UpsertTest.php b/tests/system/Database/Live/UpsertTest.php index 000fa6fec7cb..99bf86ea72ac 100644 --- a/tests/system/Database/Live/UpsertTest.php +++ b/tests/system/Database/Live/UpsertTest.php @@ -253,18 +253,17 @@ public function testGetCompiledUpsert(): void break; case 'SQLSRV': - $expected = <<<'SQL' - MERGE INTO "test"."dbo"."db_user" - USING ( - VALUES ('Iran','ahmadinejad@world.com','Ahmadinejad') - ) "_upsert" ("country", "email", "name") - ON ("test"."dbo"."db_user"."email" = "_upsert"."email") - WHEN MATCHED THEN UPDATE SET - "country" = "_upsert"."country", - "name" = "_upsert"."name" - WHEN NOT MATCHED THEN INSERT ("country", "email", "name") - VALUES ("_upsert"."country", "_upsert"."email", "_upsert"."name"); - SQL; + $qualified = '"' . $this->db->getDatabase() . '"."dbo"."db_user"'; + $expected = 'MERGE INTO ' . $qualified . "\n" + . "USING (\n" + . "VALUES ('Iran','ahmadinejad@world.com','Ahmadinejad')\n" + . ') "_upsert" ("country", "email", "name")' . "\n" + . 'ON (' . $qualified . '."email" = "_upsert"."email")' . "\n" + . "WHEN MATCHED THEN UPDATE SET\n" + . "\"country\" = \"_upsert\".\"country\",\n" + . "\"name\" = \"_upsert\".\"name\"\n" + . 'WHEN NOT MATCHED THEN INSERT ("country", "email", "name")' . "\n" + . 'VALUES ("_upsert"."country", "_upsert"."email", "_upsert"."name");'; break; case 'OCI8': diff --git a/tests/system/Database/Live/WorkerModeTest.php b/tests/system/Database/Live/WorkerModeTest.php index a8c77d756da7..f614f8d68df1 100644 --- a/tests/system/Database/Live/WorkerModeTest.php +++ b/tests/system/Database/Live/WorkerModeTest.php @@ -30,7 +30,6 @@ final class WorkerModeTest extends CIUnitTestCase protected function tearDown(): void { parent::tearDown(); - $this->setPrivateProperty(Config::class, 'instances', []); } diff --git a/tests/system/Database/Migrations/MigrationRunnerTest.php b/tests/system/Database/Migrations/MigrationRunnerTest.php index 79ad1cf39330..5ebe295d8fd8 100644 --- a/tests/system/Database/Migrations/MigrationRunnerTest.php +++ b/tests/system/Database/Migrations/MigrationRunnerTest.php @@ -74,6 +74,7 @@ protected function tearDown(): void // To delete data with `$this->regressDatabase()`, set it true. $this->migrate = true; $this->regressDatabase(); + Database::forge($this->DBGroup)->dropTable('migrations_lock', true); } public function testLoadsDefaultDatabaseWhenNoneSpecified(): void