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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
- Enh #865: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov, @vjik)
- Enh #798: Allow `QueryInterface::one()` and `QueryInterface::all()` to return objects (@darkdef, @Tigrov)
- Enh #872: Use `#[\SensitiveParameter]` attribute to mark sensitive parameters (@heap-s)
- New #864, #897, #898: Realize column factory (@Tigrov)
- New #864, #897, #898, #950: Realize column factory (@Tigrov)
- Enh #875: Ignore "Packets out of order..." warnings in `AbstractPdoCommand::internalExecute()` method (@Tigrov)
- Enh #877: Separate column type constants (@Tigrov)
- New #878: Realize `ColumnBuilder` class (@Tigrov)
Expand Down
3 changes: 2 additions & 1 deletion src/Schema/Column/AbstractColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yiisoft\Db\Syntax\ColumnDefinitionParser;

use function array_diff_key;
use function array_key_exists;
use function array_merge;
use function is_numeric;
use function preg_match;
Expand Down Expand Up @@ -121,7 +122,7 @@ public function fromType(string $type, array $info = []): ColumnInterface

$column = new $columnClass($type, ...$info);

if (isset($info['defaultValueRaw'])) {
if (array_key_exists('defaultValueRaw', $info)) {
$column->defaultValue($this->normalizeDefaultValue($info['defaultValueRaw'], $column));
}

Expand Down
121 changes: 15 additions & 106 deletions tests/Common/CommonSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Schema\Column\ColumnBuilder;
use Yiisoft\Db\Schema\Column\ColumnInterface;
use Yiisoft\Db\Schema\TableSchemaInterface;
use Yiisoft\Db\Tests\AbstractSchemaTest;
use Yiisoft\Db\Tests\Support\AnyCaseValue;
use Yiisoft\Db\Tests\Support\AnyValue;
use Yiisoft\Db\Tests\Support\Assert;
use Yiisoft\Db\Tests\Support\DbHelper;

use function array_keys;
use function count;
use function gettype;
use function is_array;
use function is_object;
use function json_encode;
use function ksort;
use function mb_chr;
use function sort;
use function str_replace;
use function strtolower;

Expand Down Expand Up @@ -833,122 +833,31 @@ protected function assertMetadataEquals($expected, $actual): void
$this->assertEquals($expected, $actual);
}

protected function assertTableColumns(array $columns, string $table): void
/**
* @param ColumnInterface[] $columns
*/
protected function assertTableColumns(array $columns, string $tableName): void
{
$db = $this->getConnection(true);

$table = $db->getTableSchema($table, true);
$table = $db->getTableSchema($tableName, true);

$this->assertNotNull($table);

$expectedColNames = array_keys($columns);
sort($expectedColNames);
$colNames = $table->getColumnNames();
sort($colNames);

$this->assertSame($expectedColNames, $colNames);

foreach ($table->getColumns() as $name => $column) {
$expected = $columns[$name];

$this->assertSame(
$expected['dbType'],
$column->getDbType(),
"dbType of column $name does not match. type is {$column->getType()}, dbType is {$column->getDbType()}."
);
$this->assertSame(
$expected['phpType'],
$column->getPhpType(),
"phpType of column $name does not match. type is {$column->getType()}, dbType is {$column->getDbType()}."
);
$this->assertSame(
$expected['primaryKey'],
$column->isPrimaryKey(),
"primaryKey of column $name does not match."
);
$this->assertSame($expected['type'], $column->getType(), "type of column $name does not match.");
$this->assertSame(
$expected['notNull'],
$column->isNotNull(),
"notNull of column $name does not match."
);
$this->assertSame(
$expected['autoIncrement'],
$column->isAutoIncrement(),
"autoIncrement of column $name does not match."
);
$this->assertSame(
$expected['enumValues'],
$column->getEnumValues(),
"enumValues of column $name does not match."
);
$this->assertSame($expected['size'], $column->getSize(), "size of column $name does not match.");

$this->assertSame($expected['scale'], $column->getScale(), "scale of column $name does not match.");

if (is_object($expected['defaultValue'])) {
$this->assertIsObject(
$column->getDefaultValue(),
"defaultValue of column $name is expected to be an object but it is not."
);
$this->assertSame(
(string) $expected['defaultValue'],
(string) $column->getDefaultValue(),
"defaultValue of column $name does not match."
);
} else {
$this->assertSame(
$expected['defaultValue'],
$column->getDefaultValue(),
"defaultValue of column $name does not match."
);
}

if (isset($expected['unique'])) {
$this->assertSame(
$expected['unique'],
$column->isUnique(),
"unique of column $name does not match"
);
}

if (isset($expected['unsigned'])) {
$this->assertSame(
$expected['unsigned'],
$column->isUnsigned(),
"unsigned of column $name does not match"
);
}
foreach ($columns as $name => &$column) {
$column = $column->withName($name);

/* For array types */
if (isset($expected['dimension'])) {
/** @psalm-suppress UndefinedMethod */
$this->assertSame(
$expected['dimension'],
$column->getDimension(),
"dimension of column $name does not match"
);
if ($column->isNotNull() === null) {
$column->notNull(false);
}

if (isset($expected['column'])) {
/** @psalm-suppress UndefinedMethod */
$arrayColumn = $column->getColumn();

$this->assertSame(
$expected['column'],
[
'type' => $arrayColumn->getType(),
'dbType' => $arrayColumn->getDbType(),
'phpType' => $arrayColumn->getPhpType(),
'enumValues' => $arrayColumn->getEnumValues(),
'size' => $arrayColumn->getSize(),
'scale' => $arrayColumn->getScale(),
],
"array column of column $name does not match"
);
if ($column->getDefaultValue() === null) {
$column->defaultValue(null);
}
}

Assert::arraysEquals($columns, $table->getColumns(), "Columns of table '$tableName'.");

$db->close();
}

Expand Down
80 changes: 80 additions & 0 deletions tests/Support/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
use ReflectionClass;
use ReflectionException;
use ReflectionObject;
use ReflectionProperty;

use function is_array;
use function is_object;
use function ltrim;

/**
* @psalm-suppress PropertyNotSetInConstructor
Expand Down Expand Up @@ -97,4 +102,79 @@ public static function invokeMethod(object $object, string $method, array $args

return $method->invokeArgs($object, $args);
}

public static function arraysEquals(array $expected, mixed $actual, string $message = ''): void
{
self::assertIsArray($actual, $message);
self::assertCount(count($expected), $actual, $message);

foreach ($expected as $key => $value) {
self::assertArrayHasKey($key, $actual, $message);

$assertionMessage = ltrim($message . " Item by key '$key'.");

if (is_object($value)) {
self::objectsEquals($value, $actual[$key], $assertionMessage);
} elseif (is_array($value)) {
self::arraysEquals($value, $actual[$key], $assertionMessage);
} else {
self::assertSame($value, $actual[$key], $assertionMessage);
}
}
}

public static function objectsEquals(object $expected, mixed $actual, string $message = ''): void
{
self::assertIsObject($actual, $message);

self::assertSame(
$expected::class,
$actual::class,
'Expected ' . $expected::class . ' class name but ' . $actual::class . " provided. $message",
);

$properties = self::getProperties($expected);

foreach ($properties as $property) {
$assertionMessage = ltrim("$message " . $expected::class . "::{$property->getName()} property.");

if (!$property->isInitialized($expected)) {
self::assertFalse($property->isInitialized($actual), "$assertionMessage Property should not be initialized.");

continue;
}

self::assertTrue($property->isInitialized($actual), "$assertionMessage Property is not initialized.");

$expectedValue = $property->getValue($expected);
$actualValue = $property->getValue($actual);

if (is_object($expectedValue)) {
self::objectsEquals($expectedValue, $actualValue, $assertionMessage);
} elseif (is_array($expectedValue)) {
self::arraysEquals($expectedValue, $actualValue, $assertionMessage);
} else {
self::assertSame($expectedValue, $actualValue, $assertionMessage);
}
}
}

/**
* Returns all properties of the object, including inherited ones.
*
* @return ReflectionProperty[]
*/
private static function getProperties(object $object): array
{
$properties = [];
$reflectionClass = new ReflectionClass($object);

do {
foreach ($reflectionClass->getProperties() as $property) {
$properties[$property->getName()] ??= $property;
}
} while ($reflectionClass = $reflectionClass->getParentClass());

return $properties;
}
}