Skip to content

Refactor Command::insertWithReturningPks() method #324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
use Yiisoft\Db\Constant\DataType;
use Yiisoft\Db\Constant\PhpType;
use Yiisoft\Db\Driver\Pdo\AbstractPdoCommand;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\AbstractQueryBuilder;

use function array_keys;
use function array_map;
use function count;
use function implode;
use function strlen;
Expand All @@ -21,7 +23,7 @@
*/
final class Command extends AbstractPdoCommand
{
public function insertWithReturningPks(string $table, array $columns): array|false
public function insertWithReturningPks(string $table, array|QueryInterface $columns): array|false
{
$tableSchema = $this->db->getSchema()->getTableSchema($table);
$returnColumns = $tableSchema?->getPrimaryKey() ?? [];
Expand All @@ -37,9 +39,9 @@ public function insertWithReturningPks(string $table, array $columns): array|fal
$params = [];
$sql = $this->getQueryBuilder()->insert($table, $columns, $params);

$tableColumns = $tableSchema?->getColumns() ?? [];
/** @var TableSchema $tableSchema */
$tableColumns = $tableSchema->getColumns();
$returnParams = [];
$returning = [];

foreach ($returnColumns as $name) {
$phName = AbstractQueryBuilder::PARAM_PREFIX . (count($params) + count($returnParams));
Expand All @@ -49,18 +51,20 @@ public function insertWithReturningPks(string $table, array $columns): array|fal
'value' => '',
];

if (!isset($tableColumns[$name]) || $tableColumns[$name]->getPhpType() !== PhpType::INT) {
$column = $tableColumns[$name];

if ($column->getPhpType() !== PhpType::INT) {
$returnParams[$phName]['dataType'] = PDO::PARAM_STR;
} else {
$returnParams[$phName]['dataType'] = PDO::PARAM_INT;
}

$returnParams[$phName]['size'] = ($tableColumns[$name]?->getSize() ?? 3998) + 2;

$returning[] = $this->db->getQuoter()->quoteColumnName($name);
$returnParams[$phName]['size'] = ($column->getSize() ?? 3998) + 2;
}

$sql .= ' RETURNING ' . implode(', ', $returning) . ' INTO ' . implode(', ', array_keys($returnParams));
$quotedReturnColumns = array_map($this->db->getQuoter()->quoteColumnName(...), $returnColumns);

$sql .= ' RETURNING ' . implode(', ', $quotedReturnColumns) . ' INTO ' . implode(', ', array_keys($returnParams));

$this->setSql($sql)->bindValues($params);
$this->prepare(false);
Expand All @@ -72,17 +76,22 @@ public function insertWithReturningPks(string $table, array $columns): array|fal

unset($value);

if (!$this->execute()) {
if ($this->execute() === 0) {
return false;
}

$result = [];

foreach ($returnParams as $value) {
/** @psalm-var mixed */
$result[$value['column']] = $value['value'];
}

if ($this->phpTypecasting) {
foreach ($result as $column => &$value) {
$value = $tableColumns[$column]->phpTypecast($value);
}
}

return $result;
}

Expand Down
17 changes: 13 additions & 4 deletions src/DMLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function insertBatch(string $table, iterable $rows, array $columns = [],
return $query . "\nSELECT " . implode(" FROM DUAL UNION ALL\nSELECT ", $values) . ' FROM DUAL';
}

public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string
public function insertWithReturningPks(string $table, array|QueryInterface $columns, array &$params = []): string
{
throw new NotSupportedException(__METHOD__ . ' is not supported by Oracle.');
}
Expand All @@ -59,9 +59,9 @@ public function insertWithReturningPks(string $table, QueryInterface|array $colu
*/
public function upsert(
string $table,
QueryInterface|array $insertColumns,
array|bool $updateColumns,
array &$params = []
array|QueryInterface $insertColumns,
array|bool $updateColumns = true,
array &$params = [],
): string {
$constraints = [];

Expand Down Expand Up @@ -134,6 +134,15 @@ public function upsert(
return "$mergeSql WHEN MATCHED THEN $updateSql WHEN NOT MATCHED THEN $insertSql";
}

public function upsertWithReturningPks(
string $table,
array|QueryInterface $insertColumns,
array|bool $updateColumns = true,
array &$params = [],
): string {
throw new NotSupportedException(__METHOD__ . ' is not supported by Oracle.');
}

protected function prepareInsertValues(string $table, array|QueryInterface $columns, array $params = []): array
{
if (empty($columns)) {
Expand Down
132 changes: 38 additions & 94 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,9 @@
namespace Yiisoft\Db\Oracle\Tests;

use PHPUnit\Framework\Attributes\DataProviderExternal;
use ReflectionException;
use Throwable;
use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Constant\PseudoType;
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\Oracle\Column\ColumnBuilder;
use Yiisoft\Db\Oracle\IndexType;
Expand All @@ -30,19 +25,13 @@

/**
* @group oracle
*
* @psalm-suppress PropertyNotSetInConstructor
*/
final class CommandTest extends CommonCommandTest
{
use TestTrait;

protected string $upsertTestCharCast = 'CAST([[address]] AS VARCHAR(255))';

/**
* @throws Exception
* @throws InvalidConfigException
*/
public function testAddDefaultValue(): void
{
$db = $this->getConnection();
Expand Down Expand Up @@ -108,11 +97,6 @@ public function testBatchInsertWithAutoincrement(): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
public function testCLOBStringInsertion(): void
{
$db = $this->getConnection();
Expand Down Expand Up @@ -142,11 +126,6 @@ public function testCLOBStringInsertion(): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
public function testCreateTable(): void
{
$db = $this->getConnection(true);
Expand Down Expand Up @@ -188,11 +167,6 @@ public function testCreateTable(): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
public function testCreateView(): void
{
$db = $this->getConnection();
Expand Down Expand Up @@ -251,10 +225,6 @@ public function testCreateView(): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidConfigException
*/
public function testDropDefaultValue(): void
{
$db = $this->getConnection();
Expand Down Expand Up @@ -288,12 +258,6 @@ public function testDropTableIfExistsWithNonExistTable(): void
$this->markTestSkipped('Oracle doesn\'t support "IF EXISTS" option on drop table.');
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws ReflectionException
* @throws Throwable
*/
public function testExecuteWithTransaction(): void
{
$db = $this->getConnection(true);
Expand Down Expand Up @@ -345,24 +309,12 @@ public function testExecuteWithTransaction(): void
$db->close();
}

/**
* @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::rawSql
*
* @throws Exception
* @throws InvalidConfigException
* @throws NotSupportedException
*/
#[DataProviderExternal(CommandProvider::class, 'rawSql')]
public function testGetRawSql(string $sql, array $params, string $expectedRawSql): void
{
parent::testGetRawSql($sql, $params, $expectedRawSql);
}

/**
* @throws Exception
* @throws InvalidCallException
* @throws InvalidConfigException
* @throws Throwable
*/
public function testsInsertQueryAsColumnValue(): void
{
$db = $this->getConnection(true);
Expand Down Expand Up @@ -399,12 +351,6 @@ public function testsInsertQueryAsColumnValue(): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidCallException
* @throws InvalidConfigException
* @throws Throwable
*/
public function testInsertWithReturningPksWithPrimaryKeyString(): void
{
$db = $this->getConnection();
Expand Down Expand Up @@ -451,11 +397,6 @@ public function testInsertWithReturningPksWithPrimaryKeySignedDecimal(): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
public function testInsertSelectAlias(): void
{
$db = $this->getConnection();
Expand Down Expand Up @@ -510,13 +451,7 @@ public function testInsertSelectAlias(): void
$db->close();
}

/**
* @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::insertVarbinary
*
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
#[DataProviderExternal(CommandProvider::class, 'insertVarbinary')]
public function testInsertVarbinary(mixed $expectedData, mixed $testData): void
{
$db = $this->getConnection(true);
Expand All @@ -537,12 +472,6 @@ public function testInsertVarbinary(mixed $expectedData, mixed $testData): void
$db->close();
}

/**
* @throws Exception
* @throws InvalidCallException
* @throws InvalidConfigException
* @throws Throwable
*/
public function testNoTablenameReplacement(): void
{
$db = $this->getConnection(true);
Expand Down Expand Up @@ -592,13 +521,7 @@ public function testNoTablenameReplacement(): void
$db->close();
}

/**
* @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::update
*
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
#[DataProviderExternal(CommandProvider::class, 'update')]
public function testUpdate(
string $table,
array $columns,
Expand All @@ -610,25 +533,46 @@ public function testUpdate(
parent::testUpdate($table, $columns, $conditions, $params, $expectedValues, $expectedCount);
}

/**
* @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\CommandProvider::upsert
*
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
#[DataProviderExternal(CommandProvider::class, 'upsert')]
public function testUpsert(array $firstData, array $secondData): void
{
parent::testUpsert($firstData, $secondData);
}

/**
* @throws InvalidConfigException
* @throws InvalidArgumentException
* @throws NotSupportedException
* @throws Exception
* @throws Throwable
*/
public function testUpsertWithReturningPks(): void
{
$db = $this->getConnection();
$command = $db->createCommand();

$this->expectException(NotSupportedException::class);
$this->expectExceptionMessage('Yiisoft\Db\Oracle\DMLQueryBuilder::upsertWithReturningPks is not supported by Oracle.');

$command->upsertWithReturningPks('{{customer}}', ['name' => 'test_1', 'email' => '[email protected]']);
}

public function testUpsertWithReturningPksEmptyValues()
{
$db = $this->getConnection();
$command = $db->createCommand();

$this->expectException(NotSupportedException::class);
$this->expectExceptionMessage('Yiisoft\Db\Oracle\DMLQueryBuilder::upsertWithReturningPks is not supported by Oracle.');

$command->upsertWithReturningPks('null_values', []);
}

public function testUpsertWithReturningPksWithPhpTypecasting(): void
{
$db = $this->getConnection();

$this->expectException(NotSupportedException::class);
$this->expectExceptionMessage('Yiisoft\Db\Oracle\DMLQueryBuilder::upsertWithReturningPks is not supported by Oracle.');

$db->createCommand()
->withPhpTypecasting()
->upsertWithReturningPks('notauto_pk', ['id_1' => 1, 'id_2' => 2.5, 'type' => 'test1']);
}

public function testQueryScalarWithBlob(): void
{
$db = $this->getConnection(true);
Expand Down
Loading
Loading