diff --git a/.gitattributes b/.gitattributes index 0e7b2047..5583f369 100644 --- a/.gitattributes +++ b/.gitattributes @@ -28,6 +28,7 @@ /.gitignore export-ignore /.scrutinizer.yml export-ignore /phpunit.xml.dist export-ignore +/tests export-ignore /docs export-ignore # Avoid merge conflicts in CHANGELOG diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e8213523..32dba9c7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: run: composer self-update - name: Install dependencies with composer. - run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + run: composer config preferred-install.yiisoft/db source && composer update --no-interaction --no-progress --optimize-autoloader --ansi - name: Run tests with phpunit with code coverage. run: vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index 14d58d9b..72427de4 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -58,7 +58,7 @@ jobs: tools: composer:v2, pecl - name: Install dependencies with composer. - run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader + run: composer config preferred-install.yiisoft/db source && composer update --no-interaction --no-progress --optimize-autoloader --ansi - name: Run infection. run: | diff --git a/composer.dev.json b/composer.dev.json new file mode 100644 index 00000000..a814a278 --- /dev/null +++ b/composer.dev.json @@ -0,0 +1,7 @@ +{ + "autoload-dev": { + "psr-4": { + "Yiisoft\\Db\\Tests\\": "vendor/yiisoft/db/tests" + } + } +} diff --git a/composer.json b/composer.json index b5e087d6..21e34104 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,7 @@ "roave/infection-static-analysis-plugin": "^1.16", "spatie/phpunit-watcher": "^1.23", "vimeo/psalm": "^4.18", + "wikimedia/composer-merge-plugin": "^2.0", "yiisoft/aliases": "^2.0", "yiisoft/cache": "^2.0" }, @@ -46,13 +47,20 @@ "extra": { "branch-alias": { "dev-master": "1.0.x-dev" + }, + "merge-plugin": { + "include": [ + "composer.dev.json" + ], + "merge-dev": true } }, "config": { "sort-packages": true, "allow-plugins": { "infection/extension-installer": true, - "composer/package-versions-deprecated": true + "composer/package-versions-deprecated": true, + "wikimedia/composer-merge-plugin": true } }, "prefer-stable": true, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4e691f01..d5d01958 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,13 +1,15 @@ - + diff --git a/src/CommandPDO.php b/src/CommandPDO.php index 5ce47d99..9df263f5 100644 --- a/src/CommandPDO.php +++ b/src/CommandPDO.php @@ -6,12 +6,13 @@ use PDO; use PDOException; +use Throwable; use Yiisoft\Db\Driver\PDO\CommandPDO as AbstractCommandPDO; +use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; use Yiisoft\Db\Exception\ConvertException; use Yiisoft\Db\QueryBuilder\QueryBuilder; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; use Yiisoft\Db\Schema\Schema; -use Yiisoft\Db\Schema\SchemaInterface; use function array_keys; use function count; @@ -28,11 +29,6 @@ public function queryBuilder(): QueryBuilderInterface return $this->db->getQueryBuilder(); } - public function schema(): SchemaInterface - { - return $this->db->getSchema(); - } - public function insertEx(string $table, array $columns): bool|array { $params = []; @@ -45,6 +41,7 @@ public function insertEx(string $table, array $columns): bool|array $returnParams = []; $returning = []; + foreach ($returnColumns as $name) { /** @noRector \Rector\Php71\Rector\FuncCall\CountOnNullRector */ $phName = QueryBuilder::PARAM_PREFIX . (count($params) + count($returnParams)); @@ -82,7 +79,7 @@ public function insertEx(string $table, array $columns): bool|array $result = []; foreach ($returnParams as $value) { - /** @var mixed */ + /** @psalm-var mixed */ $result[$value['column']] = $value['value']; } @@ -111,6 +108,11 @@ protected function bindPendingParams(): void } } + /** + * @psalm-suppress UnusedClosureParam + * + * @throws Throwable + */ protected function internalExecute(?string $rawSql): void { $attempt = 0; @@ -122,7 +124,10 @@ protected function internalExecute(?string $rawSql): void && $this->isolationLevel !== null && $this->db->getTransaction() === null ) { - $this->db->transaction(fn (string $rawSql) => $this->internalExecute($rawSql), $this->isolationLevel); + $this->db->transaction( + fn (ConnectionPDOInterface $db) => $this->internalExecute($rawSql), + $this->isolationLevel + ); } else { $this->pdoStatement?->execute(); } diff --git a/src/DDLQueryBuilder.php b/src/DDLQueryBuilder.php index a8e4b248..3b9f14c5 100644 --- a/src/DDLQueryBuilder.php +++ b/src/DDLQueryBuilder.php @@ -22,6 +22,14 @@ public function __construct( parent::__construct($queryBuilder, $quoter, $schema); } + /** + * @throws NotSupportedException + */ + public function addDefaultValue(string $name, string $table, string $column, mixed $value): string + { + throw new NotSupportedException(__METHOD__ . ' is not supported by Oracle.'); + } + public function addForeignKey( string $name, string $table, @@ -76,6 +84,14 @@ public function dropCommentFromTable(string $table): string return 'COMMENT ON TABLE ' . $this->quoter->quoteTableName($table) . " IS ''"; } + /** + * @throws NotSupportedException + */ + public function dropDefaultValue(string $name, string $table): string + { + throw new NotSupportedException(__METHOD__ . ' is not supported by Oracle.'); + } + public function dropIndex(string $name, string $table): string { return 'DROP INDEX ' . $this->quoter->quoteTableName($name); diff --git a/src/Schema.php b/src/Schema.php index e0211b0e..97207786 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -95,7 +95,9 @@ protected function findSchemaNames(): array } /** - * @throws Exception|InvalidConfigException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable */ protected function findTableNames(string $schema = ''): array { @@ -137,7 +139,9 @@ protected function findTableNames(string $schema = ''): array } /** - * @throws Exception|InvalidConfigException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable */ protected function loadTableSchema(string $name): TableSchemaInterface|null { @@ -152,7 +156,10 @@ protected function loadTableSchema(string $name): TableSchemaInterface|null } /** - * @throws Exception|InvalidConfigException|NotSupportedException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException + * @throws Throwable */ protected function loadTablePrimaryKey(string $tableName): Constraint|null { @@ -162,7 +169,10 @@ protected function loadTablePrimaryKey(string $tableName): Constraint|null } /** - * @throws Exception|InvalidConfigException|NotSupportedException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException + * @throws Throwable */ protected function loadTableForeignKeys(string $tableName): array { @@ -172,7 +182,10 @@ protected function loadTableForeignKeys(string $tableName): array } /** - * @throws Exception|InvalidConfigException|NotSupportedException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException + * @throws Throwable */ protected function loadTableIndexes(string $tableName): array { @@ -224,7 +237,10 @@ protected function loadTableIndexes(string $tableName): array } /** - * @throws Exception|InvalidConfigException|NotSupportedException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException + * @throws Throwable */ protected function loadTableUniques(string $tableName): array { @@ -234,7 +250,10 @@ protected function loadTableUniques(string $tableName): array } /** - * @throws Exception|InvalidConfigException|NotSupportedException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException + * @throws Throwable */ protected function loadTableChecks(string $tableName): array { @@ -248,7 +267,7 @@ protected function loadTableChecks(string $tableName): array */ protected function loadTableDefaultValues(string $tableName): array { - throw new NotSupportedException('Oracle does not support default value constraints.'); + throw new NotSupportedException(__METHOD__ . ' is not supported by Oracle.'); } /** @@ -273,7 +292,8 @@ public function createColumnSchemaBuilder(string $type, array|int|string $length * * @param TableSchemaInterface $table the table schema. * - * @throws Exception|Throwable + * @throws Exception + * @throws Throwable * * @return bool whether the table exists. */ @@ -331,7 +351,9 @@ protected function findColumns(TableSchemaInterface $table): bool /** * Sequence name of table. * - * @throws Exception|InvalidConfigException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable * * @return bool|float|int|string|null whether the sequence exists. * @@ -425,7 +447,10 @@ protected function createColumn(array|string $column): ColumnSchema /** * Finds constraints and fills them into TableSchemaInterface object passed. * - * @throws Exception|InvalidConfigException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable + * * @psalm-suppress PossiblyNullArrayOffset */ protected function findConstraints(TableSchemaInterface $table): void @@ -525,7 +550,9 @@ protected function findConstraints(TableSchemaInterface $table): void * * @param TableSchemaInterface $table the table metadata. * - * @throws Exception|InvalidConfigException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable * * @return array all unique indexes for the given table. */ @@ -626,7 +653,10 @@ protected function extractColumnSize( * - uniques * - checks * - * @throws Exception|InvalidConfigException|NotSupportedException|Throwable + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException + * @throws Throwable * * @return mixed constraints. */ diff --git a/tests/CommandPDOTest.php b/tests/CommandPDOTest.php new file mode 100644 index 00000000..5ed48cdf --- /dev/null +++ b/tests/CommandPDOTest.php @@ -0,0 +1,46 @@ +markTestSkipped('It must be implemented.'); + } +} diff --git a/tests/CommandTest.php b/tests/CommandTest.php index 20173fb5..fa3b9388 100644 --- a/tests/CommandTest.php +++ b/tests/CommandTest.php @@ -4,529 +4,366 @@ namespace Yiisoft\Db\Oracle\Tests; -use PDO; -use Yiisoft\Db\Command\Param; -use Yiisoft\Db\Connection\Connection; +use ReflectionException; +use Throwable; use Yiisoft\Db\Exception\Exception; -use Yiisoft\Db\Exception\InvalidArgumentException; use Yiisoft\Db\Exception\InvalidCallException; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; -use Yiisoft\Db\Expression\Expression; -use Yiisoft\Db\Oracle\Schema; +use Yiisoft\Db\Oracle\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; -use Yiisoft\Db\TestSupport\TestCommandTrait; +use Yiisoft\Db\Schema\Schema; +use Yiisoft\Db\Tests\Common\CommonCommandTest; +use Yiisoft\Db\Tests\Support\Assert; +use Yiisoft\Db\Transaction\TransactionInterface; + +use function is_resource; +use function str_pad; +use function stream_get_contents; /** * @group oracle - * @group upsert + * + * @psalm-suppress PropertyNotSetInConstructor */ -final class CommandTest extends TestCase +final class CommandTest extends CommonCommandTest { - use TestCommandTrait; + use TestTrait; protected string $upsertTestCharCast = 'CAST([[address]] AS VARCHAR(255))'; - public function testAddDropPrimaryKey(): void - { - $db = $this->getConnection(); - - $tableName = 'test_pk'; - $name = 'test_pk_constraint'; - - $schema = $db->getSchema(); - - if ($schema->getTableSchema($tableName) !== null) { - $db->createCommand()->dropTable($tableName)->execute(); - } - - $db->createCommand()->createTable($tableName, [ - 'int1' => 'integer not null', - 'int2' => 'integer not null', - ])->execute(); - - $this->assertNull($schema->getTablePrimaryKey($tableName, true)); - - $db->createCommand()->addPrimaryKey($name, $tableName, ['int1'])->execute(); - $pk = $schema->getTablePrimaryKey($tableName, true); - - $this->assertNotNull($pk); - $this->assertEquals(['int1'], $pk->getColumnNames()); - - $db->createCommand()->dropPrimaryKey($name, $tableName)->execute(); - - $this->assertNull($schema->getTablePrimaryKey($tableName, true)); - - $db->createCommand()->addPrimaryKey($name, $tableName, ['int1', 'int2'])->execute(); - $pk = $schema->getTablePrimaryKey($tableName, true); - - $this->assertNotNull($pk); - $this->assertEquals(['int1', 'int2'], $pk->getColumnNames()); - } - - public function testAutoQuoting(): void + /** + * @throws Exception + * @throws InvalidConfigException + */ + public function testAddDefaultValue(): void { $db = $this->getConnection(); - $sql = 'SELECT [[id]], [[t.name]] FROM {{customer}} t'; - $command = $db->createCommand($sql); - $this->assertEquals('SELECT "id", "t"."name" FROM "customer" t', $command->getSql()); - } - - public function testLastInsertId(): void - { - $db = $this->getConnection(true); - - $sql = 'INSERT INTO {{profile}}([[description]]) VALUES (\'non duplicate\')'; - - $command = $db->createCommand($sql); - - $command->execute(); - - $this->assertEquals(3, $db->getLastInsertID('profile_SEQ')); - } + $command = $db->createCommand(); - public function testLastInsertIdException(): void - { - $db = $this->getConnection(); - $db->close(); + $this->expectException(NotSupportedException::class); + $this->expectExceptionMessage( + 'Yiisoft\Db\Oracle\DDLQueryBuilder::addDefaultValue is not supported by Oracle.' + ); - $this->expectException(InvalidCallException::class); - $db->getLastInsertID('profile_SEQ'); + $command->addDefaultValue('{{name}}', '{{table}}', 'column', 'value'); } - public function testLastInsertIdNotSupportedException(): void - { - $db = $this->getConnection(); - $db->close(); - - $this->expectException(InvalidArgumentException::class); - $db->getLastInsertID(); + /** + * @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::batchInsert() + * + * @throws Throwable + */ + public function testBatchInsert( + string $table, + array $columns, + array $values, + string $expected, + array $expectedParams = [], + int $insertedRow = 1 + ): void { + parent::testBatchInsert($table, $columns, $values, $expected, $expectedParams, $insertedRow); } + /** + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable + */ public function testCLOBStringInsertion(): void { $db = $this->getConnection(); - if ($db->getSchema()->getTableSchema('longstring') !== null) { - $db->createCommand()->dropTable('longstring')->execute(); - } - - $db->createCommand()->createTable('longstring', ['message' => Schema::TYPE_TEXT])->execute(); - - $longData = str_pad('-', 4001, '-=', STR_PAD_LEFT); - $db->createCommand()->insert('longstring', [ - 'message' => $longData, - ])->execute(); - - $this->assertEquals(1, $db->createCommand('SELECT count(*) FROM {{longstring}}')->queryScalar()); - - $db->createCommand()->dropTable('longstring')->execute(); - } - - public function testInsert(): void - { - $db = $this->getConnection(); - - $db->createCommand('DELETE FROM {{customer}}')->execute(); - $command = $db->createCommand(); + $schema = $db->getSchema(); - $command->insert( - '{{customer}}', - [ - 'email' => 't1@example.com', - 'name' => 'test', - 'address' => 'test address', - ] - )->execute(); - - $this->assertEquals(1, $db->createCommand('SELECT COUNT(*) FROM {{customer}}')->queryScalar()); + if ($schema->getTableSchema('longstring') !== null) { + $command->dropTable('longstring')->execute(); + } - $record = $db->createCommand('SELECT [[email]], [[name]], [[address]] FROM {{customer}}')->queryOne(); + $command->createTable('longstring', ['message' => Schema::TYPE_TEXT])->execute(); + $longData = str_pad('-', 4001, '-=', STR_PAD_LEFT); + $command->insert('longstring', ['message' => $longData])->execute(); + + $this->assertSame( + '1', + $command->setSql( + <<queryScalar(), + ); - $this->assertEquals([ - 'email' => 't1@example.com', - 'name' => 'test', - 'address' => 'test address', - ], $record); + $command->dropTable('longstring')->execute(); } - public function testQueryCache() + /** + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable + */ + public function testCreateTable(): void { $db = $this->getConnection(true); - $this->assertNotNull($this->queryCache); - - $this->queryCache->setEnable(true); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user1', $command->bindValue(':id', 1)->queryScalar()); - - $update = $db->createCommand('UPDATE {{customer}} SET [[name]] = :name WHERE [[id]] = :id'); - $update->bindValues([':id' => 1, ':name' => 'user11'])->execute(); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user11', $command->bindValue(':id', 1)->queryScalar()); - - $db->cache(function (Connection $db) use ($update) { - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user2', $command->bindValue(':id', 2)->queryScalar()); - - $update->bindValues([':id' => 2, ':name' => 'user22'])->execute(); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user2', $command->bindValue(':id', 2)->queryScalar()); - - $db->noCache(function () use ($db) { - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user22', $command->bindValue(':id', 2)->queryScalar()); - }); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user2', $command->bindValue(':id', 2)->queryScalar()); - }, 10); - - $this->queryCache->setEnable(false); - - $db->cache(function (Connection $db) use ($update) { - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user22', $command->bindValue(':id', 2)->queryScalar()); - - $update->bindValues([':id' => 2, ':name' => 'user2'])->execute(); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); - - $this->assertEquals('user2', $command->bindValue(':id', 2)->queryScalar()); - }, 10); - - $this->queryCache->setEnable(true); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id')->cache(); - - $this->assertEquals('user11', $command->bindValue(':id', 1)->queryScalar()); - - $update->bindValues([':id' => 1, ':name' => 'user1'])->execute(); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id')->cache(); - - $this->assertEquals('user11', $command->bindValue(':id', 1)->queryScalar()); - - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id')->noCache(); - - $this->assertEquals('user1', $command->bindValue(':id', 1)->queryScalar()); - - $db->cache(function (Connection $db) { - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); + $command = $db->createCommand(); + $schema = $db->getSchema(); - $this->assertEquals('user11', $command->bindValue(':id', 1)->queryScalar()); + if ($schema->getTableSchema('testCreateTable') !== null) { + $command->setSql( + <<execute(); + $command->dropTable('testCreateTable')->execute(); + } - $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id')->noCache(); + $command->createTable( + '{{testCreateTable}}', + ['id' => Schema::TYPE_PK, 'bar' => Schema::TYPE_INTEGER] + )->execute(); + $command->setSql( + <<execute(); + $command->setSql( + <<execute(); + $records = $command->setSql( + <<queryAll(); - $this->assertEquals('user1', $command->bindValue(':id', 1)->queryScalar()); - }, 10); + $this->assertSame([['id' => '1', 'bar' => '1']], $records); } /** - * verify that {{}} are not going to be replaced in parameters. + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable */ - public function testNoTablenameReplacement(): void + public function testCreateView(): void { - $db = $this->getConnection(true); - - $db->createCommand()->insert( - '{{customer}}', - [ - 'name' => 'Some {{weird}} name', - 'email' => 'test@example.com', - 'address' => 'Some {{%weird}} address', - ] - )->execute(); + $db = $this->getConnection(); - $customerId = $db->getLastInsertID('customer_SEQ'); + $command = $db->createCommand(); + $schema = $db->getSchema(); - $customer = $db->createCommand('SELECT * FROM {{customer}} WHERE "id"=' . $customerId)->queryOne(); + if ($schema->getTableSchema('testCreateView') !== null) { + $command->dropView('testCreateView')->execute(); + } - $this->assertIsArray($customer); - $this->assertEquals('Some {{weird}} name', $customer['name']); - $this->assertEquals('Some {{%weird}} address', $customer['address']); + if ($schema->getTableSchema('testCreateViewTable') !== null) { + $command->setSql( + <<execute(); + $command->dropTable('testCreateViewTable')->execute(); + } - $db->createCommand()->update( - '{{customer}}', + $subquery = (new Query($db))->select('{{bar}}')->from('{{testCreateViewTable}}')->where(['>', '{{bar}}', '5']); + $command->createTable( + '{{testCreateViewTable}}', [ - 'name' => 'Some {{updated}} name', - 'address' => 'Some {{%updated}} address', + '[[id]]' => Schema::TYPE_PK, + '[[bar]]' => Schema::TYPE_INTEGER, ], - ['id' => $customerId] )->execute(); + $command->setSql( + <<execute(); + $command->setSql( + <<execute(); + $command->setSql( + <<execute(); + $command->createView('{{testCreateView}}', $subquery)->execute(); - $customer = $db->createCommand('SELECT * FROM {{customer}} WHERE "id"=' . $customerId)->queryOne(); + $records = $db->createCommand( + <<queryAll(); - $this->assertIsArray($customer); - $this->assertEquals('Some {{updated}} name', $customer['name']); - $this->assertEquals('Some {{%updated}} address', $customer['address']); + $this->assertSame([['bar' => '6']], $records); } - public function testBindParamValue(): void + /** + * @throws Exception + * @throws InvalidConfigException + */ + public function testDropDefaultValue(): void { - $db = $this->getConnection(true); - - /** bindParam */ - $sql = 'INSERT INTO {{customer}}([[email]], [[name]], [[address]]) VALUES (:email, :name, :address)'; - $command = $db->createCommand($sql); - $email = 'user4@example.com'; - $name = 'user4'; - $address = 'address4'; - $command->bindParam(':email', $email); - $command->bindParam(':name', $name); - $command->bindParam(':address', $address); - $command->execute(); + $db = $this->getConnection(); - $sql = 'SELECT [[name]] FROM {{customer}} WHERE [[email]] = :email'; - $command = $db->createCommand($sql); - $command->bindParam(':email', $email); - $this->assertEquals($name, $command->queryScalar()); - - $sql = <<<'SQL' -INSERT INTO {{type}} ([[int_col]], [[char_col]], [[float_col]], [[blob_col]], [[numeric_col]], [[bool_col]]) - VALUES (:int_col, :char_col, :float_col, :blob_col, :numeric_col, :bool_col) -SQL; - $command = $db->createCommand($sql); - $intCol = 123; - $charCol = str_repeat('abc', 33) . 'x'; // a 100 char string - $boolCol = '0'; - $command->bindParam(':int_col', $intCol, PDO::PARAM_INT); - $command->bindParam(':char_col', $charCol); - $command->bindParam(':bool_col', $boolCol, PDO::PARAM_BOOL); - - /** can't bind floats without support from a custom PDO driver */ - $floatCol = 2; - $numericCol = 3; - /** can't use blobs without support from a custom PDO driver */ - $blobCol = null; - $command->bindParam(':float_col', $floatCol, PDO::PARAM_INT); - $command->bindParam(':numeric_col', $numericCol, PDO::PARAM_INT); - $command->bindParam(':blob_col', $blobCol); - - $this->assertEquals(1, $command->execute()); + $command = $db->createCommand(); - $command = $db->createCommand( - 'SELECT [[int_col]], [[char_col]], [[float_col]], [[blob_col]], [[numeric_col]], [[bool_col]] FROM {{type}}' + $this->expectException(NotSupportedException::class); + $this->expectExceptionMessage( + 'Yiisoft\Db\Oracle\DDLQueryBuilder::dropDefaultValue is not supported by Oracle.' ); - $row = $command->queryOne(); - - $this->assertIsArray($row); - $this->assertEquals($intCol, $row['int_col']); - $this->assertEquals($charCol, $row['char_col']); - $this->assertEquals($floatCol, $row['float_col']); - $this->assertEquals($blobCol, $row['blob_col']); - $this->assertEquals($numericCol, $row['numeric_col']); - $this->assertEquals($boolCol, (int)$row['bool_col']); - - /** bindValue */ - $sql = 'INSERT INTO {{customer}}([[email]], [[name]], [[address]]) VALUES (:email, \'user5\', \'address5\')'; - $command = $db->createCommand($sql); - $command->bindValue(':email', 'user5@example.com'); - $command->execute(); - $sql = 'SELECT [[email]] FROM {{customer}} WHERE [[name]] = :name'; - $command = $db->createCommand($sql); - $command->bindValue(':name', 'user5'); - $this->assertEquals('user5@example.com', $command->queryScalar()); - } - - public function bindParamsNonWhereProvider(): array - { - return [ - ['SELECT SUBSTR("name", :len) FROM {{customer}} WHERE [[email]] = :email GROUP BY SUBSTR("name", :len)'], - ['SELECT SUBSTR("name", :len) FROM {{customer}} WHERE [[email]] = :email ORDER BY SUBSTR("name", :len)'], - ['SELECT SUBSTR("name", :len) FROM {{customer}} WHERE [[email]] = :email'], - ]; + $command->dropDefaultValue('{{name}}', '{{table}}'); } /** - * Test whether param binding works in other places than WHERE. - * - * @dataProvider bindParamsNonWhereProvider + * @throws Exception + * @throws InvalidConfigException + * @throws ReflectionException + * @throws Throwable */ - public function testBindParamsNonWhere(string $sql): void + public function testExecuteWithTransaction(): void { $db = $this->getConnection(true); - $db->createCommand()->insert( - '{{customer}}', - ['name' => 'testParams', 'email' => 'testParams@example.com', 'address' => '1'] - )->execute(); + $this->assertNull($db->getTransaction()); - $params = [ - ':email' => 'testParams@example.com', - ':len' => 5, - ]; + $command = $db->createCommand( + <<createCommand($sql, $params); + Assert::invokeMethod($command, 'requireTransaction'); - $this->assertEquals('Params', $command->queryScalar()); - } + $command->execute(); - /** - * Data provider for testInsertSelectFailed. - * - * @return array - */ - public function invalidSelectColumns() - { - return [ - [[]], - ['*'], - [['*']], - ]; - } + $this->assertNull($db->getTransaction()); - /** - * Test INSERT INTO ... SELECT SQL statement with wrong query object. - * - * @dataProvider invalidSelectColumns - */ - public function testInsertSelectFailed(mixed $invalidSelectColumns): void - { - $db = $this->getConnection(); - $query = new Query($db); + $this->assertEquals( + 1, + $db->createCommand( + <<queryScalar(), + ); - $query->select($invalidSelectColumns)->from('{{customer}}'); + $command = $db->createCommand( + <<createCommand(); + Assert::invokeMethod($command, 'requireTransaction', [TransactionInterface::READ_COMMITTED]); - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('select query object with enumerated (named) parameters'); + $command->execute(); - $command->insert( - '{{customer}}', - $query - )->execute(); + $this->assertNull($db->getTransaction()); + + $this->assertEquals( + 1, + $db->createCommand( + <<queryScalar(), + ); } /** - * @dataProvider dataInsertVarbinary + * @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::rawSql() * - * @throws \Throwable - * @throws \Yiisoft\Db\Exception\Exception - * @throws \Yiisoft\Db\Exception\InvalidConfigException + * @throws Exception + * @throws InvalidConfigException + * @throws NotSupportedException */ - public function testInsertVarbinary($expectedData, $testData) - { - $db = $this->getConnection(); - - $db->createCommand()->delete('T_upsert_varbinary')->execute(); - - $db->createCommand()->insert('T_upsert_varbinary', ['id' => 1, 'blob_col' => $testData])->execute(); - - $query = (new Query($db)) - ->select(['blob_col']) - ->from('T_upsert_varbinary') - ->where(['id' => 1]); - - $resultData = $query->createCommand()->queryOne(); - - $this->assertIsArray($resultData); - - $resultBlob = is_resource($resultData['blob_col']) ? stream_get_contents($resultData['blob_col']) : $resultData['blob_col']; - - $this->assertEquals($expectedData, $resultBlob); - } - - public function dataInsertVarbinary() + public function testGetRawSql(string $sql, array $params, string $expectedRawSql): void { - return [ - [ - json_encode(['string' => 'string', 'integer' => 1234]), - json_encode(['string' => 'string', 'integer' => 1234]), - ], - [ - serialize(['string' => 'string', 'integer' => 1234]), - new Param(serialize(['string' => 'string', 'integer' => 1234]), PDO::PARAM_LOB), - ], - [ - 'simple string', - 'simple string', - ], - ]; + parent::testGetRawSql($sql, $params, $expectedRawSql); } /** - * @dataProvider upsertProviderTrait + * @throws Exception + * @throws InvalidCallException + * @throws InvalidConfigException + * @throws Throwable */ - public function testUpsert(array $firstData, array $secondData): void - { - $db = $this->getConnection(true); - - $this->assertEquals(0, $db->createCommand('SELECT COUNT(*) FROM {{T_upsert}}')->queryScalar()); - $this->performAndCompareUpsertResult($db, $firstData); - $this->assertEquals(1, $db->createCommand('SELECT COUNT(*) FROM {{T_upsert}}')->queryScalar()); - $this->performAndCompareUpsertResult($db, $secondData); - } - public function testsInsertQueryAsColumnValue(): void { $db = $this->getConnection(true); - $time = time(); - - $db->createCommand('DELETE FROM {{order_with_null_fk}}')->execute(); - $command = $db->createCommand(); + $time = (string) time(); - $command->insert('{{order}}', [ - 'customer_id' => 1, - 'created_at' => $time, - 'total' => 42, - ])->execute(); - + $command->delete('{{order_with_null_fk}}')->execute(); + $command->insert('{{order}}', ['customer_id' => 1, 'created_at' => $time, 'total' => 42])->execute(); $columnValueQuery = new Query($db); - $orderId = $db->getLastInsertID('order_SEQ'); - $columnValueQuery->select('created_at')->from('{{order}}')->where(['id' => $orderId]); - - $command = $db->createCommand(); - $command->insert( '{{order_with_null_fk}}', [ 'customer_id' => $orderId, 'created_at' => $columnValueQuery, 'total' => 42, - ] + ], )->execute(); - $this->assertEquals( + $this->assertSame( $time, - $db->createCommand( - 'SELECT [[created_at]] FROM {{order_with_null_fk}} WHERE [[customer_id]] = ' . $orderId - )->queryScalar() + $command->setSql( + <<bindValues([':orderId' => $orderId])->queryScalar(), ); - $db->createCommand('DELETE FROM {{order_with_null_fk}}')->execute(); - $db->createCommand('DELETE FROM {{order}} WHERE [[id]] = ' . $orderId)->execute(); + $command->delete('{{order_with_null_fk}}')->execute(); + $command->delete('{{order}}', ['id' => $orderId])->execute(); } /** - * Test INSERT INTO ... SELECT SQL statement with alias syntax. + * @throws Exception + * @throws InvalidCallException + * @throws InvalidConfigException + * @throws Throwable */ - public function testInsertSelectAlias(): void + public function testInsertExWithPrimaryKeyString(): void { $db = $this->getConnection(); - $db->createCommand('DELETE FROM {{customer}}')->execute(); - $command = $db->createCommand(); + $schema = $db->getSchema(); + + if ($schema->getTableSchema('{{test_insert_ex_string}}') !== null) { + $command->dropTable('{{test_insert_ex_string}}')->execute(); + } + + $command->createTable( + '{{test_insert_ex_string}}', + ['id' => 'varchar(10) primary key', 'name' => 'varchar(10)'], + )->execute(); + + $result = $command->insertEx('{{test_insert_ex_string}}', ['id' => '1', 'name' => 'test']); + $this->assertSame(['id' => '1'], $result); + } + + /** + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable + */ + public function testInsertSelectAlias(): void + { + $db = $this->getConnection(); + + $command = $db->createCommand(); + $command->delete('{{customer}}')->execute(); $command->insert( '{{customer}}', [ @@ -536,21 +373,28 @@ public function testInsertSelectAlias(): void ] )->execute(); - $query = $db->createCommand( - "SELECT 't2@example.com' as [[email]], [[address]] as [[name]], [[name]] as [[address]] from {{customer}}" + $query = $command->setSql( + <<queryOne(); $this->assertIsArray($row); - $command->insert( - '{{customer}}', - $row - )->execute(); + $command->insert('{{customer}}', $row)->execute(); - $this->assertEquals(2, $db->createCommand('SELECT COUNT(*) FROM {{customer}}')->queryScalar()); + $this->assertEquals(2, $command->setSql( + <<queryScalar()); - $record = $db->createCommand('SELECT [[email]], [[name]], [[address]] FROM {{customer}}')->queryAll(); + $record = $command->setSql( + <<queryAll(); $this->assertEquals([ [ @@ -566,316 +410,102 @@ public function testInsertSelectAlias(): void ], $record); } - public function testCreateTable(): void + /** + * @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::insertVarbinary() + * + * @throws Exception + * @throws InvalidConfigException + * @throws Throwable + */ + public function testInsertVarbinary(mixed $expectedData, mixed $testData): void { $db = $this->getConnection(true); - if ($db->getSchema()->getTableSchema('testCreateTable') !== null) { - $db->createCommand('DROP SEQUENCE testCreateTable_SEQ')->execute(); - $db->createCommand()->dropTable('testCreateTable')->execute(); - } - - $db->createCommand()->createTable( - '{{testCreateTable}}', - ['id' => Schema::TYPE_PK, 'bar' => Schema::TYPE_INTEGER] - )->execute(); - - $db->createCommand('CREATE SEQUENCE testCreateTable_SEQ START with 1 INCREMENT BY 1')->execute(); - - $db->createCommand( - 'INSERT INTO {{testCreateTable}} ("id", "bar") VALUES(testCreateTable_SEQ.NEXTVAL, 1)' - )->execute(); - - $records = $db->createCommand('SELECT [[id]], [[bar]] FROM {{testCreateTable}}')->queryAll(); - - $this->assertEquals([ - ['id' => 1, 'bar' => 1], - ], $records); - } - - public function testCreateView(): void - { - $db = $this->getConnection(); - - $subquery = (new Query($db)) - ->select('bar') - ->from('testCreateViewTable') - ->where(['>', 'bar', '5']); - - if ($db->getSchema()->getTableSchema('testCreateView') !== null) { - $db->createCommand()->dropView('testCreateView')->execute(); - } - - if ($db->getSchema()->getTableSchema('testCreateViewTable')) { - $db->createCommand('DROP SEQUENCE testCreateViewTable_SEQ')->execute(); - $db->createCommand()->dropTable('testCreateViewTable')->execute(); - } - - $db->createCommand()->createTable('testCreateViewTable', [ - 'id' => Schema::TYPE_PK, - 'bar' => Schema::TYPE_INTEGER, - ])->execute(); - - $db->createCommand('CREATE SEQUENCE testCreateViewTable_SEQ START with 1 INCREMENT BY 1')->execute(); - - $db->createCommand( - 'INSERT INTO {{testCreateViewTable}} ("id", "bar") VALUES(testCreateTable_SEQ.NEXTVAL, 1)' - )->execute(); - - $db->createCommand( - 'INSERT INTO {{testCreateViewTable}} ("id", "bar") VALUES(testCreateTable_SEQ.NEXTVAL, 6)' - )->execute(); - - $db->createCommand()->createView('testCreateView', $subquery)->execute(); + $command = $db->createCommand(); + $command->delete('{{T_upsert_varbinary}}')->execute(); + $command->insert('{{T_upsert_varbinary}}', ['id' => 1, 'blob_col' => $testData])->execute(); + $query = (new Query($db))->select(['blob_col'])->from('{{T_upsert_varbinary}}')->where(['id' => 1]); + $resultData = $query->createCommand()->queryOne(); - $records = $db->createCommand('SELECT [[bar]] FROM {{testCreateView}}')->queryAll(); + $this->assertIsArray($resultData); - $this->assertEquals([['bar' => 6]], $records); - } + /** @var mixed $resultBlob */ + $resultBlob = is_resource($resultData['blob_col']) ? stream_get_contents($resultData['blob_col']) : $resultData['blob_col']; - public function testColumnCase(): void - { - $this->markTestSkipped('Should be fixed.'); + $this->assertSame($expectedData, $resultBlob); } - public function testInsertExpression(): void + /** + * @throws Exception + * @throws InvalidCallException + * @throws InvalidConfigException + * @throws Throwable + */ + public function testNoTablenameReplacement(): void { - $db = $this->getConnection(); - - $db->createCommand('DELETE FROM {{order_with_null_fk}}')->execute(); + $db = $this->getConnection(true); $command = $db->createCommand(); $command->insert( - '{{order_with_null_fk}}', + '{{customer}}', [ - 'created_at' => new Expression('EXTRACT(YEAR FROM sysdate)'), - 'total' => 1, - ] - )->execute(); - - $this->assertEquals(1, $db->createCommand('SELECT COUNT(*) FROM {{order_with_null_fk}}')->queryScalar()); - - $record = $db->createCommand('SELECT [[created_at]] FROM {{order_with_null_fk}}')->queryOne(); - - $this->assertEquals([ - 'created_at' => date('Y'), - ], $record); - } - - public function testAlterTable(): void - { - $db = $this->getConnection(); - - if ($db->getSchema()->getTableSchema('testAlterTable') !== null) { - $db->createCommand('DROP SEQUENCE testAlterTable_SEQ')->execute(); - $db->createCommand()->dropTable('testAlterTable')->execute(); - } - - $db->createCommand()->createTable( - 'testAlterTable', - ['id' => Schema::TYPE_PK, 'bar' => Schema::TYPE_INTEGER] - )->execute(); - - $db->createCommand('CREATE SEQUENCE testAlterTable_SEQ START with 1 INCREMENT BY 1')->execute(); - - $db->createCommand( - 'INSERT INTO {{testAlterTable}} ([[id]], [[bar]]) VALUES(testAlterTable_SEQ.NEXTVAL, 1)' + 'name' => 'Some {{weird}} name', + 'email' => 'test@example.com', + 'address' => 'Some {{%weird}} address', + ], )->execute(); - $db->createCommand('ALTER TABLE {{testAlterTable}} ADD ([[bar_tmp]] VARCHAR(20))')->execute(); - - $db->createCommand('UPDATE {{testAlterTable}} SET [[bar_tmp]] = [[bar]]')->execute(); + $customerId = $db->getLastInsertID('customer_SEQ'); - $db->createCommand('ALTER TABLE {{testAlterTable}} DROP COLUMN [[bar]]')->execute(); + $customer = $command->setSql( + <<execute(); + $this->assertIsArray($customer); + $this->assertSame('Some {{weird}} name', $customer['name']); + $this->assertSame('Some {{%weird}} address', $customer['address']); - $db->createCommand( - "INSERT INTO {{testAlterTable}} ([[id]], [[bar]]) VALUES(testAlterTable_SEQ.NEXTVAL, 'hello')" + $command->update( + '{{customer}}', + [ + 'name' => 'Some {{updated}} name', + 'address' => 'Some {{%updated}} address', + ], + ['id' => $customerId] )->execute(); - $records = $db->createCommand('SELECT [[id]], [[bar]] FROM {{testAlterTable}}')->queryAll(); - - $this->assertEquals([ - ['id' => 1, 'bar' => 1], - ['id' => 2, 'bar' => 'hello'], - ], $records); - } - - public function batchInsertSqlProvider(): array - { - $data = $this->batchInsertSqlProviderTrait(); + $customer = $command->setSql( + <<changeSqlForOracleBatchInsert($data['issue11242']['expected']); - $data['issue11242']['expectedParams'][':qp3'] = '1'; - - $this->changeSqlForOracleBatchInsert($data['wrongBehavior']['expected']); - $data['wrongBehavior']['expectedParams'][':qp3'] = '0'; - - $this->changeSqlForOracleBatchInsert($data['batchInsert binds params from expression']['expected']); - $data['batchInsert binds params from expression']['expectedParams'][':qp3'] = '0'; - - return $data; + $this->assertIsArray($customer); + $this->assertSame('Some {{updated}} name', $customer['name']); + $this->assertSame('Some {{%updated}} address', $customer['address']); } /** - * Make sure that `{{something}}` in values will not be encoded. - * - * @dataProvider batchInsertSqlProvider - * - * @param string $table - * @param array $columns - * @param array $values - * @param string $expected - * @param array $expectedParams - * @param int $insertedRow - * - * @throws Exception|InvalidConfigException|NotSupportedException - * - * {@see https://github.com/yiisoft/yii2/issues/11242} + * @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::update() */ - public function testBatchInsertSQL( + public function testUpdate( string $table, array $columns, - array $values, - string $expected, - array $expectedParams = [], - int $insertedRow = 1 + array|string $conditions, + array $params, + string $expected ): void { - $db = $this->getConnection(true); - - $command = $db->createCommand(); - - $command->batchInsert($table, $columns, $values); - - $command->prepare(false); - - $this->assertSame($expected, $command->getSql()); - $this->assertSame($expectedParams, $command->getParams()); - - $command->execute(); - $this->assertEquals($insertedRow, (new Query($db))->from($table)->count()); - } - - public function testAddDropCheck(): void - { - $db = $this->getConnection(); - - $tableName = 'test_ck'; - $name = 'test_ck_constraint'; - - $schema = $db->getSchema(); - - if ($schema->getTableSchema($tableName) !== null) { - $db->createCommand()->dropTable($tableName)->execute(); - } - - $db->createCommand()->createTable($tableName, [ - 'int1' => 'integer', - ])->execute(); - - $this->assertEmpty($schema->getTableChecks($tableName, true)); - - $db->createCommand()->addCheck($name, $tableName, '[[int1]] > 1')->execute(); - - $this->assertMatchesRegularExpression( - '/^.*int1.*>.*1.*$/', - $schema->getTableChecks($tableName, true)[0]->getExpression() - ); - - $db->createCommand()->dropCheck($name, $tableName)->execute(); - - $this->assertEmpty($schema->getTableChecks($tableName, true)); + parent::testUpdate($table, $columns, $conditions, $params, $expected); } /** - * Test command getRawSql. - * - * @dataProvider getRawSqlProviderTrait - * - * @param string $sql - * @param array $params - * @param string $expectedRawSql - * - * {@see https://github.com/yiisoft/yii2/issues/8592} - * - * @throws Exception - * @throws InvalidConfigException - * @throws NotSupportedException + * @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::upsert() */ - public function testGetRawSql(string $sql, array $params, string $expectedRawSql): void - { - $db = $this->getConnection(); - - $command = $db->createCommand($sql, $params); - - $this->assertEquals($expectedRawSql, $command->getRawSql()); - } - - public function testAutoRefreshTableSchema(): void + public function testUpsert(array $firstData, array $secondData): void { - $db = $this->getConnection(); - - $tableName = 'test'; - $fkName = 'test_fk'; - - if ($db->getSchema()->getTableSchema($tableName) !== null) { - $db->createCommand()->dropTable($tableName)->execute(); - } - - $this->assertNull($db->getSchema()->getTableSchema($tableName)); - - $db->createCommand()->createTable($tableName, [ - 'id' => 'pk', - 'fk' => 'int', - 'name' => 'string', - ])->execute(); - $initialSchema = $db->getSchema()->getTableSchema($tableName); - $this->assertNotNull($initialSchema); - - $db->createCommand()->addColumn($tableName, 'value', 'integer')->execute(); - $newSchema = $db->getSchema()->getTableSchema($tableName); - $this->assertNotEquals($initialSchema, $newSchema); - - $db->createCommand()->addForeignKey($fkName, $tableName, 'fk', $tableName, 'id')->execute(); - $tableSchema = $db->getSchema()->getTableSchema($tableName); - - $this->assertNotNull($tableSchema); - $this->assertNotEmpty($tableSchema->getForeignKeys()); - - $db->createCommand()->dropForeignKey($fkName, $tableName)->execute(); - $tableSchema = $db->getSchema()->getTableSchema($tableName); - - $this->assertNotNull($tableSchema); - $this->assertEmpty($tableSchema->getForeignKeys()); - - $db->createCommand()->addCommentOnColumn($tableName, 'id', 'Test comment')->execute(); - $tableSchema = $db->getSchema()->getTableSchema($tableName); - - $this->assertNotNull($tableSchema); - - $column = $tableSchema->getColumn('id'); - - $this->assertNotNull($column); - $this->assertNotEmpty($column->getComment()); - - $db->createCommand()->dropCommentFromColumn($tableName, 'id')->execute(); - $tableSchema = $db->getSchema()->getTableSchema($tableName); - - $this->assertNotNull($tableSchema); - - $column = $tableSchema->getColumn('id'); - - $this->assertNotNull($column); - $this->assertEmpty($column->getComment()); - - $db->createCommand()->dropTable($tableName)->execute(); - $this->assertNull($db->getSchema()->getTableSchema($tableName)); + parent::testUpsert($firstData, $secondData); } } diff --git a/tests/Provider/CommandPDOProvider.php b/tests/Provider/CommandPDOProvider.php new file mode 100644 index 00000000..12248e07 --- /dev/null +++ b/tests/Provider/CommandPDOProvider.php @@ -0,0 +1,54 @@ + '1', + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => '1', + 'bool_status' => '1', + 'profile_id' => '1', + ], + ], + ]; + } + + public function bindParamsNonWhere(): array + { + return [ + [ + <<batchInsert($this->getConnection()); + + $batchInsert['multirow']['expected'] = <<changeSqlForOracleBatchInsert($batchInsert['issue11242']['expected']); + + $batchInsert['issue11242']['expectedParams'][':qp3'] = '1'; + + $this->changeSqlForOracleBatchInsert($batchInsert['wrongBehavior']['expected']); + + $batchInsert['wrongBehavior']['expectedParams'][':qp3'] = '0'; + + $this->changeSqlForOracleBatchInsert($batchInsert['batchInsert binds params from expression']['expected']); + + $batchInsert['batchInsert binds params from expression']['expectedParams'][':qp3'] = '0'; + + return $batchInsert; + } + + public function insertVarbinary(): array + { + return [ + [ + json_encode(['string' => 'string', 'integer' => 1234]), + json_encode(['string' => 'string', 'integer' => 1234]), + ], + [ + serialize(['string' => 'string', 'integer' => 1234]), + new Param(serialize(['string' => 'string', 'integer' => 1234]), PDO::PARAM_LOB), + ], + ['simple string', 'simple string'], + ]; + } + + /** + * @throws Exception + * @throws InvalidConfigException + */ + public function rawSql(): array + { + $baseCommandProvider = new BaseCommandProvider(); + + return $baseCommandProvider->rawSql($this->getConnection()); + } + + /** + * @throws Exception + * @throws InvalidConfigException + */ + public function update(): array + { + $baseCommandProvider = new BaseCommandProvider(); + + return $baseCommandProvider->update($this->getConnection()); + } + + /** + * @throws Exception + * @throws InvalidConfigException + */ + public function upsert(): array + { + $baseCommandProvider = new BaseCommandProvider(); + + return $baseCommandProvider->upsert($this->getConnection()); + } +} diff --git a/tests/Fixture/oci.sql b/tests/Support/Fixture/oci.sql similarity index 93% rename from tests/Fixture/oci.sql rename to tests/Support/Fixture/oci.sql index 3d19e4fd..3e733d23 100644 --- a/tests/Fixture/oci.sql +++ b/tests/Support/Fixture/oci.sql @@ -25,8 +25,6 @@ BEGIN EXECUTE IMMEDIATE 'DROP TABLE "dossier"'; EXCEPTION WHEN OTHERS THEN IF SQ BEGIN EXECUTE IMMEDIATE 'DROP TABLE "employee"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "department"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP VIEW "animal_view"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- -BEGIN EXECUTE IMMEDIATE 'DROP TABLE "validator_main"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- -BEGIN EXECUTE IMMEDIATE 'DROP TABLE "validator_ref"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "bit_values"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; -- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "T_constraints_4"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- BEGIN EXECUTE IMMEDIATE 'DROP TABLE "T_constraints_3"'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;-- @@ -305,23 +303,6 @@ CREATE TABLE "T_upsert" ); CREATE SEQUENCE "T_upsert_SEQ"; -/** - * (Postgres-)Database Schema for validator tests - */ - -CREATE TABLE "validator_main" ( - "id" integer not null, - "field1" varchar2(255), - CONSTRAINT "validator_main_PK" PRIMARY KEY ("id") ENABLE -); - -CREATE TABLE "validator_ref" ( - "id" integer not null, - "a_field" varchar2(255), - "ref" integer, - CONSTRAINT "validator_ref_PK" PRIMARY KEY ("id") ENABLE -); - CREATE TABLE "T_upsert_varbinary" ( "id" integer not null, @@ -444,17 +425,6 @@ INSERT INTO "dossier" ("id", "department_id", "employee_id", "summary") VALUES ( INSERT INTO "dossier" ("id", "department_id", "employee_id", "summary") VALUES (2, 2, 1, 'Brilliant employee.'); INSERT INTO "dossier" ("id", "department_id", "employee_id", "summary") VALUES (3, 2, 2, 'Good employee.'); -INSERT INTO "validator_main" ("id", "field1") VALUES (1, 'just a string1'); -INSERT INTO "validator_main" ("id", "field1") VALUES (2, 'just a string2'); -INSERT INTO "validator_main" ("id", "field1") VALUES (3, 'just a string3'); -INSERT INTO "validator_main" ("id", "field1") VALUES (4, 'just a string4'); -INSERT INTO "validator_ref" ("id", "a_field", "ref") VALUES (1, 'ref_to_2', 2); -INSERT INTO "validator_ref" ("id", "a_field", "ref") VALUES (2, 'ref_to_2', 2); -INSERT INTO "validator_ref" ("id", "a_field", "ref") VALUES (3, 'ref_to_3', 3); -INSERT INTO "validator_ref" ("id", "a_field", "ref") VALUES (4, 'ref_to_4', 4); -INSERT INTO "validator_ref" ("id", "a_field", "ref") VALUES (5, 'ref_to_4', 4); -INSERT INTO "validator_ref" ("id", "a_field", "ref") VALUES (6, 'ref_to_5', 5); - INSERT INTO "bit_values" ("id", "val") SELECT 1, '0' FROM SYS.DUAL UNION ALL SELECT 2, '1' FROM SYS.DUAL; diff --git a/tests/Support/TestTrait.php b/tests/Support/TestTrait.php new file mode 100644 index 00000000..b3f38f32 --- /dev/null +++ b/tests/Support/TestTrait.php @@ -0,0 +1,50 @@ +db = new ConnectionPDO( + new PDODriver('oci:dbname=localhost/XE;', 'system', 'oracle', ['charset' => 'AL32UTF8']), + DbHelper::getQueryCache(), + DbHelper::getSchemaCache(), + ); + + if ($fixture) { + DbHelper::loadFixture($this->db, __DIR__ . '/Fixture/oci.sql'); + } + + return $this->db; + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->db->close(); + } + + private function changeSqlForOracleBatchInsert(string &$str): void + { + $str = str_replace('INSERT INTO', 'INSERT ALL INTO', $str) . ' SELECT 1 FROM SYS.DUAL'; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 667fbaaf..0d6e3f31 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -10,6 +10,8 @@ use Yiisoft\Db\Oracle\ConnectionPDO; use Yiisoft\Db\TestSupport\TestTrait; +use function str_replace; + class TestCase extends AbstractTestCase { use TestTrait; @@ -24,15 +26,10 @@ class TestCase extends AbstractTestCase protected array $likeParameterReplacements = []; protected ?ConnectionPDO $db = null; - /** - * @param bool $reset whether to clean up the test database. - * - * @return ConnectionPDO - */ protected function getConnection( - $reset = false, + bool $reset = false, ?string $dsn = null, - string $fixture = __DIR__ . '/Fixture/oci.sql' + string $fixture = __DIR__ . '/Support/Fixture/oci.sql' ): ConnectionPDO { $pdoDriver = new PDODriver($dsn ?? $this->dsn, $this->username, $this->password); $this->db = new ConnectionPDO($pdoDriver, $this->createQueryCache(), $this->createSchemaCache());