Skip to content

Commit

Permalink
Realize ColumnBuilder (#360)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Sep 16, 2024
1 parent 80b32d6 commit 72da3f3
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 53 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Enh #355: Implement `ColumnFactory` class (@Tigrov)
- Enh #359: Separate column type constants (@Tigrov)
- Enh #359: Remove `Schema::TYPE_ARRAY` and `Schema::TYPE_STRUCTURED` constants (@Tigrov)
- Enh #360: Realize `ColumnBuilder` class (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
5 changes: 2 additions & 3 deletions src/Column/ArrayColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public function column(ColumnSchemaInterface|null $column): static
public function getColumn(): ColumnSchemaInterface
{
if ($this->column === null) {
$this->column = (new ColumnFactory())->fromType($this->getType());
$this->column->dbType($this->getDbType());
$this->column = (new ColumnFactory())->fromDbType($this->getDbType() ?? '');
$this->column->enumValues($this->getEnumValues());
$this->column->precision($this->getPrecision());
$this->column->scale($this->getScale());
Expand Down Expand Up @@ -101,7 +100,7 @@ public function dbTypecast(mixed $value): ExpressionInterface|null
$value = $this->dbTypecastArray($value, $this->dimension);
}

return new ArrayExpression($value, $this->getDbType(), $this->dimension);
return new ArrayExpression($value, $this->getDbType() ?? $this->getColumn()->getDbType(), $this->dimension);
}

public function phpTypecast(mixed $value): array|null
Expand Down
71 changes: 71 additions & 0 deletions src/Column/ColumnBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Pgsql\Column;

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

final class ColumnBuilder extends \Yiisoft\Db\Schema\Column\ColumnBuilder
{
public static function boolean(): ColumnSchemaInterface
{
return new BooleanColumnSchema(ColumnType::BOOLEAN);
}

public static function bit(int|null $size = null): ColumnSchemaInterface
{
return (new BitColumnSchema(ColumnType::BIT))
->size($size);
}

public static function tinyint(int|null $size = null): ColumnSchemaInterface
{
return (new IntegerColumnSchema(ColumnType::TINYINT))
->size($size);
}

public static function smallint(int|null $size = null): ColumnSchemaInterface
{
return (new IntegerColumnSchema(ColumnType::SMALLINT))
->size($size);
}

public static function integer(int|null $size = null): ColumnSchemaInterface
{
return (new IntegerColumnSchema(ColumnType::INTEGER))
->size($size);
}

public static function bigint(int|null $size = null): ColumnSchemaInterface
{
return (new IntegerColumnSchema(ColumnType::BIGINT))
->size($size);
}

public static function binary(int|null $size = null): ColumnSchemaInterface
{
return (new BinaryColumnSchema(ColumnType::BINARY))
->size($size);
}

public static function array(ColumnSchemaInterface|null $column = null): ColumnSchemaInterface
{
return (new ArrayColumnSchema(ColumnType::ARRAY))
->column($column);
}

/**
* @param string|null $dbType The DB type of the column.
* @param ColumnSchemaInterface[] $columns The columns (name -> instance) that the structured column should contain.
*
* @psalm-param array<string, ColumnSchemaInterface> $columns
*/
public static function structured(string|null $dbType = null, array $columns = []): ColumnSchemaInterface
{
return (new StructuredColumnSchema(ColumnType::STRUCTURED))
->dbType($dbType)
->columns($columns);
}
}
9 changes: 7 additions & 2 deletions src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ final class ColumnFactory extends AbstractColumnFactory
* @psalm-param ColumnType::* $type
* @psalm-param ColumnInfo $info
* @psalm-suppress MoreSpecificImplementedParamType
* @psalm-suppress ArgumentTypeCoercion
*/
public function fromType(string $type, array $info = []): ColumnSchemaInterface
{
Expand All @@ -125,7 +126,6 @@ public function fromType(string $type, array $info = []): ColumnSchemaInterface
->dimension($dimension)
->column($this->fromType($type, $info));
} else {
/** @psalm-suppress ArgumentTypeCoercion */
$column = match ($type) {
ColumnType::BOOLEAN => new BooleanColumnSchema($type),
ColumnType::BIT => new BitColumnSchema($type),
Expand All @@ -141,11 +141,16 @@ public function fromType(string $type, array $info = []): ColumnSchemaInterface
};
}

return $column;
return $column->load($info);
}

protected function getType(string $dbType, array $info = []): string
{
return self::TYPE_MAP[$dbType] ?? ColumnType::STRING;
}

protected function isDbType(string $dbType): bool
{
return isset(self::TYPE_MAP[$dbType]);
}
}
7 changes: 7 additions & 0 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use Yiisoft\Db\Driver\Pdo\AbstractPdoConnection;
use Yiisoft\Db\Driver\Pdo\PdoCommandInterface;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Pgsql\Column\ColumnFactory;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
use Yiisoft\Db\Schema\Column\ColumnFactoryInterface;
use Yiisoft\Db\Schema\Quoter;
use Yiisoft\Db\Schema\QuoterInterface;
use Yiisoft\Db\Schema\SchemaInterface;
Expand Down Expand Up @@ -44,6 +46,11 @@ public function createTransaction(): TransactionInterface
return new Transaction($this);
}

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

public function getLastInsertID(string $sequenceName = null): string
{
if ($sequenceName === null) {
Expand Down
12 changes: 3 additions & 9 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Helper\DbArrayHelper;
use Yiisoft\Db\Pgsql\Column\ArrayColumnSchema;
use Yiisoft\Db\Pgsql\Column\ColumnFactory;
use Yiisoft\Db\Pgsql\Column\SequenceColumnSchemaInterface;
use Yiisoft\Db\Pgsql\Column\StructuredColumnSchemaInterface;
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 @@ -111,11 +109,6 @@ public function createColumn(string $type, array|int|string $length = null): Col
return new Column($type, $length);
}

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

/**
* Resolves the table name and schema name (if any).
*
Expand Down Expand Up @@ -722,6 +715,7 @@ protected function findColumns(TableSchemaInterface $table): bool
*/
private function loadColumnSchema(array $info): ColumnSchemaInterface
{
$columnFactory = $this->db->getColumnFactory();
$dbType = $info['data_type'];

if (!in_array($info['type_scheme'], [$this->defaultSchema, 'pg_catalog'], true)) {
Expand All @@ -737,10 +731,10 @@ private function loadColumnSchema(array $info): ColumnSchemaInterface
$columns = $structured->getColumns();
}

$column = $this->getColumnFactory()
$column = $columnFactory
->fromType(ColumnType::STRUCTURED, ['dimension' => $info['dimension'], 'columns' => $columns]);
} else {
$column = $this->getColumnFactory()
$column = $columnFactory
->fromDbType($dbType, ['dimension' => $info['dimension']]);
}

Expand Down
35 changes: 35 additions & 0 deletions tests/ColumnBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Pgsql\Tests;

use Yiisoft\Db\Pgsql\Column\ColumnBuilder;
use Yiisoft\Db\Pgsql\Tests\Support\TestTrait;
use Yiisoft\Db\Tests\AbstractColumnBuilderTest;

/**
* @group pgsql
*/
final class ColumnBuilderTest extends AbstractColumnBuilderTest
{
use TestTrait;

public function getColumnBuilderClass(): string
{
return ColumnBuilder::class;
}

/**
* @dataProvider \Yiisoft\Db\Pgsql\Tests\Provider\ColumnBuilderProvider::buildingMethods
*/
public function testBuildingMethods(
string $buildingMethod,
array $args,
string $expectedInstanceOf,
string $expectedType,
array $expectedMethodResults = [],
): void {
parent::testBuildingMethods($buildingMethod, $args, $expectedInstanceOf, $expectedType, $expectedMethodResults);
}
}
20 changes: 17 additions & 3 deletions tests/ColumnFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,23 @@ public function testFromDbType(string $dbType, string $expectedType, string $exp
}

/** @dataProvider \Yiisoft\Db\Pgsql\Tests\Provider\ColumnFactoryProvider::definitions */
public function testFromDefinition(string $definition, string $expectedType, string $expectedInstanceOf, array $expectedInfo = []): void
{
parent::testFromDefinition($definition, $expectedType, $expectedInstanceOf, $expectedInfo);
public function testFromDefinition(
string $definition,
string $expectedType,
string $expectedInstanceOf,
array $expectedMethodResults = []
): void {
parent::testFromDefinition($definition, $expectedType, $expectedInstanceOf, $expectedMethodResults);
}

/** @dataProvider \Yiisoft\Db\Pgsql\Tests\Provider\ColumnFactoryProvider::pseudoTypes */
public function testFromPseudoType(
string $pseudoType,
string $expectedType,
string $expectedInstanceOf,
array $expectedMethodResults = []
): void {
parent::testFromPseudoType($pseudoType, $expectedType, $expectedInstanceOf, $expectedMethodResults);
}

/** @dataProvider \Yiisoft\Db\Pgsql\Tests\Provider\ColumnFactoryProvider::types */
Expand Down
16 changes: 10 additions & 6 deletions tests/ColumnSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,12 @@ public function testPhpTypecastColumns(string $className, array $values)
}

/** @dataProvider \Yiisoft\Db\Pgsql\Tests\Provider\ColumnSchemaProvider::dbTypecastArrayColumns */
public function testDbTypecastArrayColumnSchema(string $dbType, string $type, string $phpType, array $values): void
public function testDbTypecastArrayColumnSchema(string $dbType, string $type, array $values): void
{
$arrayCol = new ArrayColumnSchema($type, $phpType);
$arrayCol->dbType($dbType);
$db = $this->getConnection();
$columnFactory = $db->getColumnFactory();

$arrayCol = (new ArrayColumnSchema())->column($columnFactory->fromType($type)->dbType($dbType));

foreach ($values as [$dimension, $expected, $value]) {
$arrayCol->dimension($dimension);
Expand All @@ -331,10 +333,12 @@ public function testDbTypecastArrayColumnSchema(string $dbType, string $type, st
}

/** @dataProvider \Yiisoft\Db\Pgsql\Tests\Provider\ColumnSchemaProvider::phpTypecastArrayColumns */
public function testPhpTypecastArrayColumnSchema(string $dbType, string $type, string $phpType, array $values): void
public function testPhpTypecastArrayColumnSchema(string $dbType, string $type, array $values): void
{
$arrayCol = new ArrayColumnSchema($type, $phpType);
$arrayCol->dbType($dbType);
$db = $this->getConnection();
$columnFactory = $db->getColumnFactory();

$arrayCol = (new ArrayColumnSchema())->column($columnFactory->fromType($type)->dbType($dbType));

foreach ($values as [$dimension, $expected, $value]) {
$arrayCol->dimension($dimension);
Expand Down
8 changes: 8 additions & 0 deletions tests/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Pgsql\Column\ColumnFactory;
use Yiisoft\Db\Pgsql\Tests\Support\TestTrait;
use Yiisoft\Db\Tests\Common\CommonConnectionTest;
use Yiisoft\Db\Transaction\TransactionInterface;
Expand Down Expand Up @@ -133,4 +134,11 @@ static function (ConnectionInterface $db) {

$db->close();
}

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

$this->assertInstanceOf(ColumnFactory::class, $db->getColumnFactory());
}
}
72 changes: 72 additions & 0 deletions tests/Provider/ColumnBuilderProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Pgsql\Tests\Provider;

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Pgsql\Column\ArrayColumnSchema;
use Yiisoft\Db\Pgsql\Column\BinaryColumnSchema;
use Yiisoft\Db\Pgsql\Column\BitColumnSchema;
use Yiisoft\Db\Pgsql\Column\BooleanColumnSchema;
use Yiisoft\Db\Pgsql\Column\ColumnBuilder;
use Yiisoft\Db\Pgsql\Column\IntegerColumnSchema;
use Yiisoft\Db\Pgsql\Column\StructuredColumnSchema;
use Yiisoft\Db\Schema\Column\DoubleColumnSchema;
use Yiisoft\Db\Schema\Column\StringColumnSchema;

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(),
['primaryKey', [], IntegerColumnSchema::class, ColumnType::INTEGER, ['isPrimaryKey' => true, 'isAutoIncrement' => true]],
['primaryKey', [false], IntegerColumnSchema::class, ColumnType::INTEGER, ['isPrimaryKey' => true, 'isAutoIncrement' => false]],
['smallPrimaryKey', [], IntegerColumnSchema::class, ColumnType::SMALLINT, ['isPrimaryKey' => true, 'isAutoIncrement' => true]],
['smallPrimaryKey', [false], IntegerColumnSchema::class, ColumnType::SMALLINT, ['isPrimaryKey' => true, 'isAutoIncrement' => false]],
['bigPrimaryKey', [], IntegerColumnSchema::class, ColumnType::BIGINT, ['isPrimaryKey' => true, 'isAutoIncrement' => true]],
['bigPrimaryKey', [false], IntegerColumnSchema::class, ColumnType::BIGINT, ['isPrimaryKey' => true, 'isAutoIncrement' => false]],
['boolean', [], BooleanColumnSchema::class, ColumnType::BOOLEAN],
['bit', [], BitColumnSchema::class, ColumnType::BIT],
['bit', [1], BitColumnSchema::class, ColumnType::BIT, ['getSize' => 1]],
['tinyint', [], IntegerColumnSchema::class, ColumnType::TINYINT],
['tinyint', [1], IntegerColumnSchema::class, ColumnType::TINYINT, ['getSize' => 1]],
['smallint', [], IntegerColumnSchema::class, ColumnType::SMALLINT],
['smallint', [1], IntegerColumnSchema::class, ColumnType::SMALLINT, ['getSize' => 1]],
['integer', [], IntegerColumnSchema::class, ColumnType::INTEGER],
['integer', [1], IntegerColumnSchema::class, ColumnType::INTEGER, ['getSize' => 1]],
['bigint', [], IntegerColumnSchema::class, ColumnType::BIGINT],
['bigint', [1], IntegerColumnSchema::class, ColumnType::BIGINT, ['getSize' => 1]],
['float', [], DoubleColumnSchema::class, ColumnType::FLOAT],
['float', [8], DoubleColumnSchema::class, ColumnType::FLOAT, ['getSize' => 8]],
['float', [8, 2], DoubleColumnSchema::class, ColumnType::FLOAT, ['getSize' => 8, 'getScale' => 2]],
['double', [], DoubleColumnSchema::class, ColumnType::DOUBLE],
['double', [8], DoubleColumnSchema::class, ColumnType::DOUBLE, ['getSize' => 8]],
['double', [8, 2], DoubleColumnSchema::class, ColumnType::DOUBLE, ['getSize' => 8, 'getScale' => 2]],
['decimal', [], DoubleColumnSchema::class, ColumnType::DECIMAL, ['getSize' => 10, 'getScale' => 0]],
['decimal', [8], DoubleColumnSchema::class, ColumnType::DECIMAL, ['getSize' => 8, 'getScale' => 0]],
['decimal', [8, 2], DoubleColumnSchema::class, ColumnType::DECIMAL, ['getSize' => 8, 'getScale' => 2]],
['money', [], DoubleColumnSchema::class, ColumnType::MONEY, ['getSize' => 19, 'getScale' => 4]],
['money', [8], DoubleColumnSchema::class, ColumnType::MONEY, ['getSize' => 8, 'getScale' => 4]],
['money', [8, 2], DoubleColumnSchema::class, ColumnType::MONEY, ['getSize' => 8, 'getScale' => 2]],
['binary', [], BinaryColumnSchema::class, ColumnType::BINARY],
['binary', [8], BinaryColumnSchema::class, ColumnType::BINARY, ['getSize' => 8]],
['array', [], ArrayColumnSchema::class, ColumnType::ARRAY],
['array', [$column = new StringColumnSchema()], ArrayColumnSchema::class, ColumnType::ARRAY, ['getColumn' => $column]],
['structured', [], StructuredColumnSchema::class, ColumnType::STRUCTURED],
['structured', ['money_currency'], StructuredColumnSchema::class, ColumnType::STRUCTURED, ['getDbType' => 'money_currency']],
[
'structured',
[
'money_currency',
$columns = ['value' => ColumnBuilder::money(), 'currency' => ColumnBuilder::string(3)],
],
StructuredColumnSchema::class,
ColumnType::STRUCTURED,
['getDbType' => 'money_currency', 'getColumns' => $columns],
],
];
}
}
Loading

0 comments on commit 72da3f3

Please sign in to comment.