Skip to content

Commit

Permalink
Merge branch 'master' into ease-local-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
samdark authored Feb 14, 2025
2 parents d262091 + c74a84b commit 5530ff5
Show file tree
Hide file tree
Showing 28 changed files with 431 additions and 354 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@
- Enh #279: Separate column type constants (@Tigrov)
- New #280, #291: Realize `ColumnBuilder` class (@Tigrov)
- Enh #281: Update according changes in `ColumnSchemaInterface` (@Tigrov)
- New #282, #291: Add `ColumnDefinitionBuilder` class (@Tigrov)
- New #282, #291, #299, #302: Add `ColumnDefinitionBuilder` class (@Tigrov)
- Bug #285: Fix `DMLQueryBuilder::insertBatch()` method (@Tigrov)
- Enh #283: Refactor `Dsn` class (@Tigrov)
- Enh #286: Use constructor to create columns and initialize properties (@Tigrov)
- Enh #288: Refactor `Schema::findColumns()` method (@Tigrov)
- Enh #289: Refactor `Schema::normalizeDefaultValue()` method and move it to `ColumnFactory` class (@Tigrov)
- New #292: Override `QueryBuilder::prepareBinary()` method (@Tigrov)
- Chg #294: Update `QueryBuilder` constructor (@Tigrov)
- Enh #293: Use `ColumnDefinitionBuilder` to generate table column SQL representation (@Tigrov)
- Enh #296: Remove `ColumnInterface` (@Tigrov)
- Enh #298: Rename `ColumnSchemaInterface` to `ColumnInterface` (@Tigrov)
- Enh #298: Refactor `DMLQueryBuilder::prepareInsertValues()` method (@Tigrov)
- Enh #299: Add `ColumnDefinitionParser` class (@Tigrov)
- Enh #299: Convert database types to lower case (@Tigrov)
- Enh #300: Replace `DbArrayHelper::getColumn()` with `array_column()` (@Tigrov)
- New #301: Add `IndexType` class (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"require-dev": {
"maglnet/composer-require-checker": "^4.2",
"phpunit/phpunit": "^10.0",
"rector/rector": "^1.0",
"rector/rector": "^2.0",
"roave/infection-static-analysis-plugin": "^1.16",
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^5.25",
Expand Down
51 changes: 0 additions & 51 deletions src/Column.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

use Yiisoft\Db\Command\ParamInterface;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Schema\Column\BinaryColumnSchema as BaseBinaryColumnSchema;
use Yiisoft\Db\Schema\Column\BinaryColumn as BaseBinaryColumn;

use function is_string;

final class BinaryColumnSchema extends BaseBinaryColumnSchema
final class BinaryColumn extends BaseBinaryColumn
{
public function dbTypecast(mixed $value): mixed
{
if ($this->getDbType() === 'BLOB') {
if ($this->getDbType() === 'blob') {
if ($value instanceof ParamInterface && is_string($value->getValue())) {
/** @var string */
$value = $value->getValue();
Expand Down
6 changes: 3 additions & 3 deletions src/Column/ColumnBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
namespace Yiisoft\Db\Oracle\Column;

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\Column\ColumnInterface;

final class ColumnBuilder extends \Yiisoft\Db\Schema\Column\ColumnBuilder
{
public static function binary(int|null $size = null): ColumnSchemaInterface
public static function binary(int|null $size = null): ColumnInterface
{
return new BinaryColumnSchema(ColumnType::BINARY, size: $size);
return new BinaryColumn(ColumnType::BINARY, size: $size);
}
}
81 changes: 47 additions & 34 deletions src/Column/ColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
namespace Yiisoft\Db\Oracle\Column;

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Constant\ReferentialAction;
use Yiisoft\Db\QueryBuilder\AbstractColumnDefinitionBuilder;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\Column\ColumnInterface;

use function ceil;
use function log10;
Expand All @@ -16,8 +17,6 @@ final class ColumnDefinitionBuilder extends AbstractColumnDefinitionBuilder
{
protected const AUTO_INCREMENT_KEYWORD = 'GENERATED BY DEFAULT AS IDENTITY';

protected const GENERATE_UUID_EXPRESSION = 'sys_guid()';

protected const TYPES_WITH_SIZE = [
'char',
'nchar',
Expand All @@ -37,7 +36,7 @@ final class ColumnDefinitionBuilder extends AbstractColumnDefinitionBuilder
'number',
];

public function build(ColumnSchemaInterface $column): string
public function build(ColumnInterface $column): string
{
return $this->buildType($column)
. $this->buildAutoIncrement($column)
Expand All @@ -53,8 +52,8 @@ public function build(ColumnSchemaInterface $column): string
protected function buildOnDelete(string $onDelete): string
{
return match ($onDelete = strtoupper($onDelete)) {
'CASCADE',
'SET NULL' => " ON DELETE $onDelete",
ReferentialAction::CASCADE,
ReferentialAction::SET_NULL => " ON DELETE $onDelete",
default => '',
};
}
Expand All @@ -64,39 +63,53 @@ protected function buildOnUpdate(string $onUpdate): string
return '';
}

protected function getDbType(ColumnSchemaInterface $column): string
protected function getDbType(ColumnInterface $column): string
{
$dbType = $column->getDbType();
$size = $column->getSize();
$scale = $column->getScale();

/** @psalm-suppress DocblockTypeContradiction */
return $column->getDbType() ?? match ($column->getType()) {
ColumnType::BOOLEAN => 'number(1)',
ColumnType::BIT => match (true) {
$size === null => 'number(38)',
$size <= 126 => 'number(' . ceil(log10(2 ** $size)) . ')',
default => 'raw(' . ceil($size / 8) . ')',
return match ($dbType) {
default => $dbType,
null => match ($column->getType()) {
ColumnType::BOOLEAN => 'number(1)',
ColumnType::BIT => match (true) {
$size === null => 'number(38)',
$size <= 126 => 'number(' . ceil(log10(2 ** $size)) . ')',
default => 'raw(' . ceil($size / 8) . ')',
},
ColumnType::TINYINT => 'number(' . ($size ?? 3) . ')',
ColumnType::SMALLINT => 'number(' . ($size ?? 5) . ')',
ColumnType::INTEGER => 'number(' . ($size ?? 10) . ')',
ColumnType::BIGINT => 'number(' . ($size ?? 20) . ')',
ColumnType::FLOAT => 'binary_float',
ColumnType::DOUBLE => 'binary_double',
ColumnType::DECIMAL => 'number(' . ($size ?? 10) . ',' . ($scale ?? 0) . ')',
ColumnType::MONEY => 'number(' . ($size ?? 19) . ',' . ($scale ?? 4) . ')',
ColumnType::CHAR => 'char',
ColumnType::STRING => 'varchar2(' . ($size ?? 255) . ')',
ColumnType::TEXT => 'clob',
ColumnType::BINARY => 'blob',
ColumnType::UUID => 'raw(16)',
ColumnType::DATETIME => 'timestamp',
ColumnType::TIMESTAMP => 'timestamp',
ColumnType::DATE => 'date',
ColumnType::TIME => 'interval day(0) to second',
ColumnType::ARRAY => 'clob',
ColumnType::STRUCTURED => 'clob',
ColumnType::JSON => 'clob',
default => 'varchar2',
},
ColumnType::TINYINT => 'number(' . ($size ?? 3) . ')',
ColumnType::SMALLINT => 'number(' . ($size ?? 5) . ')',
ColumnType::INTEGER => 'number(' . ($size ?? 10) . ')',
ColumnType::BIGINT => 'number(' . ($size ?? 20) . ')',
ColumnType::FLOAT => 'binary_float',
ColumnType::DOUBLE => 'binary_double',
ColumnType::DECIMAL => 'number(' . ($size ?? 10) . ',' . ($column->getScale() ?? 0) . ')',
ColumnType::MONEY => 'number(' . ($size ?? 19) . ',' . ($column->getScale() ?? 4) . ')',
ColumnType::CHAR => 'char',
ColumnType::STRING => 'varchar2(' . ($size ?? 255) . ')',
ColumnType::TEXT => 'clob',
ColumnType::BINARY => 'blob',
ColumnType::UUID => 'raw(16)',
ColumnType::DATETIME => 'timestamp',
ColumnType::TIMESTAMP => 'timestamp',
ColumnType::DATE => 'date',
ColumnType::TIME => 'interval day(0) to second',
ColumnType::ARRAY => 'clob',
ColumnType::STRUCTURED => 'clob',
ColumnType::JSON => 'clob',
default => 'varchar2',
'timestamp with time zone' => 'timestamp' . ($size !== null ? "($size)" : '') . ' with time zone',
'timestamp with local time zone' => 'timestamp' . ($size !== null ? "($size)" : '') . ' with local time zone',
'interval day to second' => 'interval day' . ($scale !== null ? "($scale)" : '') . ' to second' . ($size !== null ? "($size)" : ''),
'interval year to month' => 'interval year' . ($scale !== null ? "($scale)" : '') . ' to month',
};
}

protected function getDefaultUuidExpression(): string
{
return 'sys_guid()';
}
}
55 changes: 55 additions & 0 deletions src/Column/ColumnDefinitionParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Oracle\Column;

use function preg_match;
use function preg_replace;
use function strlen;
use function strtolower;
use function substr;

/**
* Parses column definition string. For example, `string(255)` or `int unsigned`.
*/
final class ColumnDefinitionParser extends \Yiisoft\Db\Syntax\ColumnDefinitionParser
{
private const TYPE_PATTERN = '/^('
. 'timestamp\s*(?:\((\d+)\))? with(?: local)? time zone'
. '|interval year\s*(?:\((\d+)\))? to month'
. ')|('
. 'interval day\s*(?:\((\d+)\))? to second'
. '|long raw'
. '|\w*'
. ')\s*(?:\(([^)]+)\))?\s*'
. '/i';

public function parse(string $definition): array
{
preg_match(self::TYPE_PATTERN, $definition, $matches);

$type = strtolower(preg_replace('/\s*\(\d+\)/', '', $matches[4] ?? $matches[1]));
$info = ['type' => $type];

$typeDetails = $matches[6] ?? $matches[2] ?? '';

if ($typeDetails !== '') {
if ($type === 'enum') {
$info += $this->enumInfo($typeDetails);
} else {
$info += $this->sizeInfo($typeDetails);
}
}

$scale = $matches[5] ?? $matches[3] ?? '';

if ($scale !== '') {
$info += ['scale' => (int) $scale];
}

$extra = substr($definition, strlen($matches[0]));

return $info + $this->extraInfo($extra);
}
}
24 changes: 12 additions & 12 deletions src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Schema\Column\AbstractColumnFactory;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\Column\ColumnInterface;

use function preg_replace;
use function rtrim;
use function strtolower;

final class ColumnFactory extends AbstractColumnFactory
{
Expand Down Expand Up @@ -40,19 +38,23 @@ final class ColumnFactory extends AbstractColumnFactory
'binary_double' => ColumnType::DOUBLE, // 64 bit
'float' => ColumnType::DOUBLE, // 126 bit
'date' => ColumnType::DATE,
'interval day to second' => ColumnType::TIME,
'timestamp' => ColumnType::TIMESTAMP,
'timestamp with time zone' => ColumnType::TIMESTAMP,
'timestamp with local time zone' => ColumnType::TIMESTAMP,
'interval day to second' => ColumnType::STRING,
'interval year to month' => ColumnType::STRING,

/** Deprecated */
'long' => ColumnType::TEXT,
];

protected function getType(string $dbType, array $info = []): string
protected function columnDefinitionParser(): ColumnDefinitionParser
{
$dbType = strtolower($dbType);
return new ColumnDefinitionParser();
}

protected function getType(string $dbType, array $info = []): string
{
if ($dbType === 'number') {
return match ($info['scale'] ?? null) {
null => ColumnType::DOUBLE,
Expand All @@ -61,10 +63,8 @@ protected function getType(string $dbType, array $info = []): string
};
}

$dbType = preg_replace('/\([^)]+\)/', '', $dbType);

if ($dbType === 'interval day to second' && isset($info['size']) && $info['size'] > 0) {
return ColumnType::STRING;
if ($dbType === 'interval day to second' && isset($info['scale']) && $info['scale'] === 0) {
return ColumnType::TIME;
}

return parent::getType($dbType, $info);
Expand All @@ -73,13 +73,13 @@ protected function getType(string $dbType, array $info = []): string
protected function getColumnClass(string $type, array $info = []): string
{
if ($type === ColumnType::BINARY) {
return BinaryColumnSchema::class;
return BinaryColumn::class;
}

return parent::getColumnClass($type, $info);
}

protected function normalizeNotNullDefaultValue(string $defaultValue, ColumnSchemaInterface $column): mixed
protected function normalizeNotNullDefaultValue(string $defaultValue, ColumnInterface $column): mixed
{
return parent::normalizeNotNullDefaultValue(rtrim($defaultValue), $column);
}
Expand Down
Loading

0 comments on commit 5530ff5

Please sign in to comment.