Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor column PHP type #862

Merged
merged 10 commits into from
Aug 9, 2024
6 changes: 3 additions & 3 deletions src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
use Throwable;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\SchemaInterface;

use function explode;
use function get_resource_type;
Expand Down Expand Up @@ -363,8 +363,8 @@ public function getRawSql(): string
$params[$name] = match ($param->getType()) {
DataType::INTEGER => (string) (int) $value,
DataType::STRING, DataType::LOB => match (gettype($value)) {
SchemaInterface::PHP_TYPE_RESOURCE => $name,
SchemaInterface::PHP_TYPE_DOUBLE => (string) $value,
GettypeResult::RESOURCE => $name,
GettypeResult::DOUBLE => (string) $value,
default => $value instanceof Expression
? (string) $value
: $quoter->quoteValue((string) $value),
Expand Down
50 changes: 50 additions & 0 deletions src/Constant/GettypeResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Constant;

/**
* The following constants are returned by {@see gettype()} function.
*
* @link https://www.php.net/manual/en/function.gettype.php
*/
class GettypeResult
Tigrov marked this conversation as resolved.
Show resolved Hide resolved
{
/**
* Define the php type as `array`.
*/
public const ARRAY = 'array';
/**
* Define the php type as `boolean`.
*/
public const BOOLEAN = 'boolean';
/**
* Define the php type as `double`.
*/
public const DOUBLE = 'double';
/**
* Define the php type as `integer`.
*/
public const INTEGER = 'integer';
/**
* Define the php type as `NULL`.
*/
public const NULL = 'NULL';
/**
* Define the php type as `object`.
*/
public const OBJECT = 'object';
/**
* Define the php type as `resource`.
*/
public const RESOURCE = 'resource';
/**
* Define the php type as `string`.
*/
public const STRING = 'string';
/**
* Define the php type as `unknown type`.
*/
public const UNKNOWN = 'unknown type';
}
50 changes: 50 additions & 0 deletions src/Constant/PhpType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Constant;

use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;

/**
* Defines the available PHP types.
* Used to generate properties of Active Record model or other user defined models.
*
* @see ColumnSchemaInterface::getPhpType()
* @see https://www.php.net/manual/en/language.types.type-system.php
*/
class PhpType
Tigrov marked this conversation as resolved.
Show resolved Hide resolved
{
/**
* Define the php type as `array`.
*/
public const ARRAY = 'array';
/**
* Define the php type as `bool`.
*/
public const BOOL = 'bool';
/**
* Define the php type as `float`.
*/
public const FLOAT = 'float';
/**
* Define the php type as `int`.
*/
public const INT = 'int';
/**
* Define the php type as `mixed`.
*/
public const MIXED = 'mixed';
/**
* Define the php type as `null`.
*/
public const NULL = 'null';
/**
* Define the php type as `object`.
*/
public const OBJECT = 'object';
/**
* Define the php type as `string`.
*/
public const STRING = 'string';
}
71 changes: 21 additions & 50 deletions src/Schema/AbstractSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yiisoft\Db\Constraint\Constraint;
use Yiisoft\Db\Constraint\IndexConstraint;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Schema\Column\BinaryColumnSchema;
use Yiisoft\Db\Schema\Column\BitColumnSchema;
use Yiisoft\Db\Schema\Column\BooleanColumnSchema;
Expand Down Expand Up @@ -139,10 +140,10 @@
{
return match (gettype($data)) {
// php type => SQL data type
SchemaInterface::PHP_TYPE_BOOLEAN => DataType::BOOLEAN,
SchemaInterface::PHP_TYPE_INTEGER => DataType::INTEGER,
SchemaInterface::PHP_TYPE_RESOURCE => DataType::LOB,
SchemaInterface::PHP_TYPE_NULL => DataType::NULL,
GettypeResult::BOOLEAN => DataType::BOOLEAN,
GettypeResult::INTEGER => DataType::INTEGER,
GettypeResult::RESOURCE => DataType::LOB,
GettypeResult::NULL => DataType::NULL,
default => DataType::STRING,
};
}
Expand Down Expand Up @@ -387,62 +388,32 @@
protected function createColumnSchema(string $type, mixed ...$info): ColumnSchemaInterface
{
$isUnsigned = !empty($info['unsigned']);
$phpType = $this->getColumnPhpType($type, $isUnsigned);

$column = $this->createColumnSchemaFromPhpType($phpType, $type);
$column = $this->createColumnSchemaFromType($type, $isUnsigned);
$column->unsigned($isUnsigned);

return $column;
}

/**
* Get the PHP type from an abstract database type.
*
* @param string $type The abstract database type.
*
* @return string The PHP type name.
*/
protected function getColumnPhpType(string $type, bool $isUnsigned = false): string
protected function createColumnSchemaFromType(string $type, bool $isUnsigned = false): ColumnSchemaInterface
{
return match ($type) {
// abstract type => php type
SchemaInterface::TYPE_TINYINT => SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_SMALLINT => SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_BOOLEAN => new BooleanColumnSchema($type),
SchemaInterface::TYPE_BIT => new BitColumnSchema($type),
SchemaInterface::TYPE_TINYINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_SMALLINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_INTEGER => PHP_INT_SIZE !== 8 && $isUnsigned
? SchemaInterface::PHP_TYPE_STRING
: SchemaInterface::PHP_TYPE_INTEGER,
? new BigIntColumnSchema($type)

Check warning on line 406 in src/Schema/AbstractSchema.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/AbstractSchema.php#L406

Added line #L406 was not covered by tests
: new IntegerColumnSchema($type),
SchemaInterface::TYPE_BIGINT => PHP_INT_SIZE !== 8 || $isUnsigned
? SchemaInterface::PHP_TYPE_STRING
: SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_BIT => SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_BOOLEAN => SchemaInterface::PHP_TYPE_BOOLEAN,
SchemaInterface::TYPE_DECIMAL => SchemaInterface::PHP_TYPE_DOUBLE,
SchemaInterface::TYPE_FLOAT => SchemaInterface::PHP_TYPE_DOUBLE,
SchemaInterface::TYPE_DOUBLE => SchemaInterface::PHP_TYPE_DOUBLE,
SchemaInterface::TYPE_BINARY => SchemaInterface::PHP_TYPE_RESOURCE,
SchemaInterface::TYPE_JSON => SchemaInterface::PHP_TYPE_ARRAY,
default => SchemaInterface::PHP_TYPE_STRING,
};
}

protected function createColumnSchemaFromPhpType(string $phpType, string $type): ColumnSchemaInterface
{
if ($type === SchemaInterface::TYPE_BIT) {
return new BitColumnSchema($type, $phpType);
}

return match ($phpType) {
SchemaInterface::PHP_TYPE_STRING => match ($type) {
SchemaInterface::TYPE_INTEGER => new BigIntColumnSchema($type, $phpType),
SchemaInterface::TYPE_BIGINT => new BigIntColumnSchema($type, $phpType),
default => new StringColumnSchema($type, $phpType),
},
SchemaInterface::PHP_TYPE_INTEGER => new IntegerColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_DOUBLE => new DoubleColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_BOOLEAN => new BooleanColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_RESOURCE => new BinaryColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_ARRAY => new JsonColumnSchema($type, $phpType),
default => new StringColumnSchema($type, $phpType),
? new BigIntColumnSchema($type)
: new IntegerColumnSchema($type),
SchemaInterface::TYPE_DECIMAL => new DoubleColumnSchema($type),
SchemaInterface::TYPE_FLOAT => new DoubleColumnSchema($type),
SchemaInterface::TYPE_DOUBLE => new DoubleColumnSchema($type),
SchemaInterface::TYPE_BINARY => new BinaryColumnSchema($type),
SchemaInterface::TYPE_JSON => new JsonColumnSchema($type),
default => new StringColumnSchema($type),
};
}

Expand Down
13 changes: 4 additions & 9 deletions src/Schema/Column/AbstractColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Yiisoft\Db\Schema\Column;

use Yiisoft\Db\Constant\PhpType;

/**
* Represents the metadata of a column in a database table.
*
Expand Down Expand Up @@ -49,7 +51,6 @@ abstract class AbstractColumnSchema implements ColumnSchemaInterface

public function __construct(
private string $type,
private string|null $phpType = null,
) {
}

Expand Down Expand Up @@ -136,9 +137,9 @@ public function getPrecision(): int|null
return $this->precision;
}

public function getPhpType(): string|null
public function getPhpType(): string
{
return $this->phpType;
return PhpType::MIXED;
}

public function getScale(): int|null
Expand Down Expand Up @@ -187,12 +188,6 @@ public function name(string|null $name): static
return $this;
}

public function phpType(string|null $phpType): static
{
$this->phpType = $phpType;
return $this;
}

public function precision(int|null $precision): static
{
$this->precision = $precision;
Expand Down
20 changes: 14 additions & 6 deletions src/Schema/Column/BigIntColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,34 @@
namespace Yiisoft\Db\Schema\Column;

use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Constant\PhpType;
use Yiisoft\Db\Schema\SchemaInterface;

use function gettype;

use const PHP_INT_MAX;
use const PHP_INT_MIN;

class BigIntColumnSchema extends AbstractColumnSchema
{
public function __construct(
string $type = SchemaInterface::TYPE_BIGINT,
string|null $phpType = SchemaInterface::PHP_TYPE_STRING,
) {
parent::__construct($type, $phpType);
parent::__construct($type);
}

public function dbTypecast(mixed $value): int|string|ExpressionInterface|null

Check failure on line 25 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

MixedInferredReturnType

src/Schema/Column/BigIntColumnSchema.php:25:47: MixedInferredReturnType: Could not verify return type 'Yiisoft\Db\Expression\ExpressionInterface|int|null|string' for Yiisoft\Db\Schema\Column\BigIntColumnSchema::dbTypecast (see https://psalm.dev/047)

Check failure on line 25 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

MixedInferredReturnType

src/Schema/Column/BigIntColumnSchema.php:25:47: MixedInferredReturnType: Could not verify return type 'Yiisoft\Db\Expression\ExpressionInterface|int|null|string' for Yiisoft\Db\Schema\Column\BigIntColumnSchema::dbTypecast (see https://psalm.dev/047)

Check failure on line 25 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm83 / PHP 8.3-ubuntu-latest

MixedInferredReturnType

src/Schema/Column/BigIntColumnSchema.php:25:47: MixedInferredReturnType: Could not verify return type 'Yiisoft\Db\Expression\ExpressionInterface|int|null|string' for Yiisoft\Db\Schema\Column\BigIntColumnSchema::dbTypecast (see https://psalm.dev/047)
{
return match (gettype($value)) {

Check failure on line 27 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

MixedReturnStatement

src/Schema/Column/BigIntColumnSchema.php:27:16: MixedReturnStatement: Possibly-mixed return value (see https://psalm.dev/138)

Check failure on line 27 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

MixedReturnStatement

src/Schema/Column/BigIntColumnSchema.php:27:16: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)

Check failure on line 27 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

MixedReturnStatement

src/Schema/Column/BigIntColumnSchema.php:27:16: MixedReturnStatement: Possibly-mixed return value (see https://psalm.dev/138)

Check failure on line 27 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

MixedReturnStatement

src/Schema/Column/BigIntColumnSchema.php:27:16: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)

Check failure on line 27 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm83 / PHP 8.3-ubuntu-latest

MixedReturnStatement

src/Schema/Column/BigIntColumnSchema.php:27:16: MixedReturnStatement: Possibly-mixed return value (see https://psalm.dev/138)

Check failure on line 27 in src/Schema/Column/BigIntColumnSchema.php

View workflow job for this annotation

GitHub Actions / psalm83 / PHP 8.3-ubuntu-latest

MixedReturnStatement

src/Schema/Column/BigIntColumnSchema.php:27:16: MixedReturnStatement: Could not infer a return type (see https://psalm.dev/138)
'string' => $value === '' ? null : (
GettypeResult::STRING => $value === '' ? null : (
$value <= PHP_INT_MAX && $value >= PHP_INT_MIN
? (int) $value
: $value
),
'NULL' => null,
'integer' => $value,
'boolean' => $value ? 1 : 0,
GettypeResult::NULL => null,
GettypeResult::INTEGER => $value,
GettypeResult::BOOLEAN => $value ? 1 : 0,
default => $value instanceof ExpressionInterface ? $value : (
($val = (string) $value) <= PHP_INT_MAX && $val >= PHP_INT_MIN
? (int) $val
Expand All @@ -38,6 +41,11 @@
};
}

public function getPhpType(): string
{
return PhpType::STRING;
}

public function phpTypecast(mixed $value): string|null
{
if ($value === null) {
Expand Down
12 changes: 6 additions & 6 deletions src/Schema/Column/BinaryColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PDO;
use Yiisoft\Db\Command\Param;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Schema\SchemaInterface;

use function gettype;
Expand All @@ -15,18 +16,17 @@ class BinaryColumnSchema extends AbstractColumnSchema
{
public function __construct(
string $type = SchemaInterface::TYPE_BINARY,
string|null $phpType = SchemaInterface::PHP_TYPE_RESOURCE,
) {
parent::__construct($type, $phpType);
parent::__construct($type);
}

public function dbTypecast(mixed $value): mixed
{
return match (gettype($value)) {
'string' => new Param($value, PDO::PARAM_LOB),
'resource' => $value,
'NULL' => null,
'boolean' => $value ? '1' : '0',
GettypeResult::STRING => new Param($value, PDO::PARAM_LOB),
GettypeResult::RESOURCE => $value,
GettypeResult::NULL => null,
GettypeResult::BOOLEAN => $value ? '1' : '0',
default => $value instanceof ExpressionInterface ? $value : (string) $value,
};
}
Expand Down
9 changes: 7 additions & 2 deletions src/Schema/Column/BitColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

namespace Yiisoft\Db\Schema\Column;

use Yiisoft\Db\Constant\PhpType;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Schema\SchemaInterface;

class BitColumnSchema extends AbstractColumnSchema
{
public function __construct(
string $type = SchemaInterface::TYPE_BIT,
string|null $phpType = SchemaInterface::PHP_TYPE_INTEGER,
) {
parent::__construct($type, $phpType);
parent::__construct($type);
}

public function dbTypecast(mixed $value): int|string|ExpressionInterface|null
Expand All @@ -28,6 +28,11 @@ public function dbTypecast(mixed $value): int|string|ExpressionInterface|null
};
}

public function getPhpType(): string
{
return PhpType::INT;
}

public function phpTypecast(mixed $value): int|null
{
if ($value === null) {
Expand Down
Loading
Loading