Skip to content
Merged
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
53 changes: 53 additions & 0 deletions src/PDO/CommandPDOOracle.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Yiisoft\Db\Connection\ConnectionPDOInterface;
use Yiisoft\Db\Exception\ConvertException;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Query\QueryBuilder;
use Yiisoft\Db\Query\QueryBuilderInterface;

/**
Expand All @@ -28,6 +29,58 @@ public function queryBuilder(): QueryBuilderInterface
return $this->db->getQueryBuilder();
}

public function insertEx(string $table, array $columns): bool|array
{
$params = [];
$sql = $this->queryBuilder()->insertEx($table, $columns, $params);

$tableSchema = $this->queryBuilder()->schema()->getTableSchema($table);

$returnColumns = $tableSchema?->getPrimaryKey() ?? [];
$columnSchemas = $tableSchema?->getColumns() ?? [];

$returnParams = [];
$returning = [];
foreach ($returnColumns as $name) {
$phName = QueryBuilder::PARAM_PREFIX . (count($params) + count($returnParams));

$returnParams[$phName] = [
'column' => $name,
'value' => '',
];

if (!isset($columnSchemas[$name]) || $columnSchemas[$name]->getPhpType() !== 'integer') {
$returnParams[$phName]['dataType'] = PDO::PARAM_STR;
} else {
$returnParams[$phName]['dataType'] = PDO::PARAM_INT;
}

$returnParams[$phName]['size'] = $columnSchemas[$name]->getSize() ?? -1;

$returning[] = $this->db->getQuoter()->quoteColumnName($name);
}

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

$this->setSql($sql)->bindValues($params);
$this->prepare(false);

foreach ($returnParams as $name => &$value) {
$this->bindParam($name, $value['value'], $value['dataType'], $value['size']);
}

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

$result = [];
foreach ($returnParams as $value) {
$result[$value['column']] = $value['value'];
}

return $result;
}

public function prepare(?bool $forRead = null): void
{
if (isset($this->pdoStatement)) {
Expand Down
59 changes: 0 additions & 59 deletions src/PDO/SchemaPDOOracle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
use Yiisoft\Db\Constraint\ForeignKeyConstraint;
use Yiisoft\Db\Constraint\IndexConstraint;
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\ColumnSchema;
use Yiisoft\Db\Oracle\ColumnSchemaBuilder;
use Yiisoft\Db\Oracle\TableSchema;
use Yiisoft\Db\Query\QueryBuilder;
use Yiisoft\Db\Schema\Schema;

/**
Expand Down Expand Up @@ -681,63 +679,6 @@ protected function extractColumnSize(
$column->scale($scale === '' || $scale === null ? null : (int) $scale);
}

/**
* @throws Exception|InvalidArgumentException|InvalidConfigException|NotSupportedException|Throwable
*/
public function insert($table, $columns): bool|array
{
$params = [];
$returnParams = [];
$sql = $this->db->getQueryBuilder()->insert($table, $columns, $params);
$tableSchema = $this->getTableSchema($table);
$returnColumns = $tableSchema->getPrimaryKey();

if (!empty($returnColumns)) {
$columnSchemas = $tableSchema->getColumns();

$returning = [];
foreach ($returnColumns as $name) {
$phName = QueryBuilder::PARAM_PREFIX . (count($params) + count($returnParams));

$returnParams[$phName] = [
'column' => $name,
'value' => '',
];

if (!isset($columnSchemas[$name]) || $columnSchemas[$name]->getPhpType() !== 'integer') {
$returnParams[$phName]['dataType'] = PDO::PARAM_STR;
} else {
$returnParams[$phName]['dataType'] = PDO::PARAM_INT;
}

$returnParams[$phName]['size'] = $columnSchemas[$name]->getSize() ?? -1;

$returning[] = $this->db->getQuoter()->quoteColumnName($name);
}

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

$command = $this->db->createCommand($sql, $params);

$command->prepare(false);

foreach ($returnParams as $name => &$value) {
$command->getPdoStatement()->bindParam($name, $value['value'], $value['dataType'], $value['size']);
}

if (!$command->execute()) {
return false;
}

$result = [];
foreach ($returnParams as $value) {
$result[$value['column']] = $value['value'];
}

return $result;
}

/**
* Loads multiple types of constraints and returns the specified ones.
*
Expand Down
66 changes: 66 additions & 0 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,72 @@ public function testNoTablenameReplacement(): void
$this->assertEquals('Some {{%updated}} address', $customer['address']);
}

public function testBindParamValue(): 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();

$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(
'SELECT [[int_col]], [[char_col]], [[float_col]], [[blob_col]], [[numeric_col]], [[bool_col]] FROM {{type}}'
);
$row = $command->queryOne();
$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 [
Expand Down