Skip to content

Commit

Permalink
Add ColumnDefinitionBuilder (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Oct 15, 2024
1 parent 55bbd32 commit 226d840
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 27 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
from `$table, $columns, $rows` to `$table, $rows, $columns = []` (@Tigrov)
- Enh #260: Support `Traversable` values for `DMLQueryBuilder::batchInsert()` method with empty columns (@Tigrov)
- Enh #255: Implement `SqlParser` and `ExpressionBuilder` driver classes (@Tigrov)
- Enh #236: Implement `ColumnSchemaInterface` classes according to the data type of database table columns
- New #236: Implement `ColumnSchemaInterface` classes according to the data type of database table columns
for type casting performance. Related with yiisoft/db#752 (@Tigrov)
- Chg #272: Replace call of `SchemaInterface::getRawTableName()` to `QuoterInterface::getRawTableName()` (@Tigrov)
- Enh #275: Refactor PHP type of `ColumnSchemaInterface` instances (@Tigrov)
- Enh #277: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov)
- Enh #276: Implement `ColumnFactory` class (@Tigrov)
- New #276: Implement `ColumnFactory` class (@Tigrov)
- Enh #279: Separate column type constants (@Tigrov)
- Enh #280: Realize `ColumnBuilder` class (@Tigrov)
- New #280: Realize `ColumnBuilder` class (@Tigrov)
- Enh #281: Update according changes in `ColumnSchemaInterface` (@Tigrov)
- New #282: Add `ColumnDefinitionBuilder` class (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
20 changes: 20 additions & 0 deletions src/Column/ColumnBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@

final class ColumnBuilder extends \Yiisoft\Db\Schema\Column\ColumnBuilder
{
public static function tinyint(int|null $size = 3): ColumnSchemaInterface
{
return parent::tinyint($size);
}

public static function smallint(int|null $size = 5): ColumnSchemaInterface
{
return parent::smallint($size);
}

public static function integer(int|null $size = 10): ColumnSchemaInterface
{
return parent::integer($size);
}

public static function bigint(int|null $size = 20): ColumnSchemaInterface
{
return parent::bigint($size);
}

public static function binary(int|null $size = null): ColumnSchemaInterface
{
return (new BinaryColumnSchema(ColumnType::BINARY))
Expand Down
100 changes: 100 additions & 0 deletions src/Column/ColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Oracle\Column;

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

use function ceil;
use function log10;
use function strtoupper;

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 = [
'varchar2',
'nvarchar2',
'number',
'float',
'timestamp',
'interval day(0) to second',
'raw',
'urowid',
'char',
'nchar',
];

protected const TYPES_WITH_SCALE = [
'number',
];

public function build(ColumnSchemaInterface $column): string
{
return $this->buildType($column)
. $this->buildAutoIncrement($column)
. $this->buildDefault($column)
. $this->buildPrimaryKey($column)
. $this->buildUnique($column)
. $this->buildNotNull($column)
. $this->buildCheck($column)
. $this->buildReferences($column)
. $this->buildExtra($column);
}

protected function buildOnDelete(string $onDelete): string
{
return match ($onDelete = strtoupper($onDelete)) {
'CASCADE',
'SET NULL' => " ON DELETE $onDelete",
default => '',
};
}

protected function buildOnUpdate(string $onUpdate): string
{
return '';
}

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

/** @psalm-suppress DocblockTypeContradiction */
return 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) . ',' . ($column->getScale() ?? 0) . ')',
ColumnType::MONEY => 'number(' . ($size ?? 19) . ',' . ($column->getScale() ?? 4) . ')',
ColumnType::CHAR => 'char',
ColumnType::STRING => 'varchar2',
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 => 'json',
ColumnType::STRUCTURED => 'json',
ColumnType::JSON => 'json',
default => 'varchar2',
};
}
}
7 changes: 0 additions & 7 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidCallException;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Oracle\Column\ColumnFactory;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
use Yiisoft\Db\Schema\Column\ColumnFactoryInterface;
use Yiisoft\Db\Schema\QuoterInterface;
use Yiisoft\Db\Schema\SchemaInterface;
use Yiisoft\Db\Transaction\TransactionInterface;
Expand Down Expand Up @@ -49,11 +47,6 @@ public function createTransaction(): TransactionInterface
return new Transaction($this);
}

public function getColumnFactory(): ColumnFactoryInterface
{
return new ColumnFactory();
}

/**
* Override base behaviour to support Oracle sequences.
*
Expand Down
1 change: 1 addition & 0 deletions src/DDLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function addForeignKey(

public function alterColumn(string $table, string $column, ColumnInterface|string $type): string
{
/** @psalm-suppress DeprecatedMethod */
return 'ALTER TABLE '
. $this->quoter->quoteTableName($table)
. ' MODIFY '
Expand Down
5 changes: 4 additions & 1 deletion src/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Constant\PseudoType;
use Yiisoft\Db\Oracle\Column\ColumnDefinitionBuilder;
use Yiisoft\Db\QueryBuilder\AbstractQueryBuilder;
use Yiisoft\Db\Schema\QuoterInterface;
use Yiisoft\Db\Schema\SchemaInterface;
Expand Down Expand Up @@ -49,6 +50,8 @@ public function __construct(QuoterInterface $quoter, SchemaInterface $schema)
$ddlBuilder = new DDLQueryBuilder($this, $quoter, $schema);
$dmlBuilder = new DMLQueryBuilder($this, $quoter, $schema);
$dqlBuilder = new DQLQueryBuilder($this, $quoter);
parent::__construct($quoter, $schema, $ddlBuilder, $dmlBuilder, $dqlBuilder);
$columnDefinitionBuilder = new ColumnDefinitionBuilder($this);

parent::__construct($quoter, $schema, $ddlBuilder, $dmlBuilder, $dqlBuilder, $columnDefinitionBuilder);
}
}
10 changes: 9 additions & 1 deletion src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Helper\DbArrayHelper;
use Yiisoft\Db\Oracle\Column\ColumnFactory;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\Column\ColumnFactoryInterface;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\TableSchemaInterface;

Expand Down Expand Up @@ -71,11 +73,17 @@ public function __construct(protected ConnectionInterface $db, SchemaCache $sche
parent::__construct($db, $schemaCache);
}

/** @deprecated Use {@see ColumnBuilder} instead. Will be removed in 2.0. */
public function createColumn(string $type, array|int|string $length = null): ColumnInterface
{
return new Column($type, $length);
}

public function getColumnFactory(): ColumnFactoryInterface
{
return new ColumnFactory();
}

protected function resolveTableName(string $name): TableSchemaInterface
{
$resolvedName = new TableSchema();
Expand Down Expand Up @@ -418,7 +426,7 @@ protected function getTableSequenceName(string $tableName): string|null
*/
private function loadColumnSchema(array $info): ColumnSchemaInterface
{
$columnFactory = $this->db->getColumnFactory();
$columnFactory = $this->db->getSchema()->getColumnFactory();

$dbType = $info['data_type'];
$column = $columnFactory->fromDbType($dbType, [
Expand Down
8 changes: 0 additions & 8 deletions tests/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Oracle\Column\ColumnFactory;
use Yiisoft\Db\Oracle\Tests\Support\TestTrait;
use Yiisoft\Db\Tests\Common\CommonConnectionTest;
use Yiisoft\Db\Transaction\TransactionInterface;
Expand Down Expand Up @@ -131,11 +130,4 @@ public function testSerialized(): void
$this->assertEquals(123, $unserialized->createCommand('SELECT 123 FROM DUAL')->queryScalar());
$this->assertNotNull($connection->getPDO());
}

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

$this->assertInstanceOf(ColumnFactory::class, $db->getColumnFactory());
}
}
23 changes: 16 additions & 7 deletions tests/Provider/ColumnBuilderProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@

namespace Yiisoft\Db\Oracle\Tests\Provider;

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Oracle\Column\BinaryColumnSchema;

class ColumnBuilderProvider extends \Yiisoft\Db\Tests\Provider\ColumnBuilderProvider
{
public static function buildingMethods(): array
{
return [
// building method, args, expected instance of, expected type, expected column method results
...parent::buildingMethods(),
['binary', [], BinaryColumnSchema::class, ColumnType::BINARY],
['binary', [8], BinaryColumnSchema::class, ColumnType::BINARY, ['getSize' => 8]],
];
$values = parent::buildingMethods();

$values['primaryKey()'][4]['getSize'] = 10;
$values['primaryKey(false)'][4]['getSize'] = 10;
$values['smallPrimaryKey()'][4]['getSize'] = 5;
$values['smallPrimaryKey(false)'][4]['getSize'] = 5;
$values['bigPrimaryKey()'][4]['getSize'] = 20;
$values['bigPrimaryKey(false)'][4]['getSize'] = 20;
$values['tinyint()'][4]['getSize'] = 3;
$values['smallint()'][4]['getSize'] = 5;
$values['integer()'][4]['getSize'] = 10;
$values['bigint()'][4]['getSize'] = 20;
$values['binary()'][2] = BinaryColumnSchema::class;
$values['binary(8)'][2] = BinaryColumnSchema::class;

return $values;
}
}
Loading

0 comments on commit 226d840

Please sign in to comment.