Skip to content

Commit

Permalink
Improve column type (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Sep 2, 2023
1 parent 6bb534e commit 6888e26
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 33 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 1.1.1 under development

- no changes in this release.
- Enh #230: Improve column type #230 (@Tigrov)

## 1.1.0 July 24, 2023

Expand Down
12 changes: 6 additions & 6 deletions src/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ final class QueryBuilder extends AbstractQueryBuilder
SchemaInterface::TYPE_SMALLINT => 'NUMBER(5)',
SchemaInterface::TYPE_INTEGER => 'NUMBER(10)',
SchemaInterface::TYPE_BIGINT => 'NUMBER(20)',
SchemaInterface::TYPE_FLOAT => 'NUMBER',
SchemaInterface::TYPE_DOUBLE => 'NUMBER',
SchemaInterface::TYPE_DECIMAL => 'NUMBER',
SchemaInterface::TYPE_DATETIME => 'TIMESTAMP',
SchemaInterface::TYPE_TIMESTAMP => 'TIMESTAMP',
SchemaInterface::TYPE_TIME => 'TIMESTAMP',
SchemaInterface::TYPE_FLOAT => 'BINARY_FLOAT',
SchemaInterface::TYPE_DOUBLE => 'BINARY_DOUBLE',
SchemaInterface::TYPE_DECIMAL => 'NUMBER(10,0)',
SchemaInterface::TYPE_DATETIME => 'TIMESTAMP(0)',
SchemaInterface::TYPE_TIMESTAMP => 'TIMESTAMP(0)',
SchemaInterface::TYPE_TIME => 'INTERVAL DAY(0) TO SECOND(0)',
SchemaInterface::TYPE_DATE => 'DATE',
SchemaInterface::TYPE_BINARY => 'BLOB',
SchemaInterface::TYPE_BOOLEAN => 'NUMBER(1)',
Expand Down
63 changes: 51 additions & 12 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
use function is_array;
use function md5;
use function preg_match;
use function preg_replace;
use function serialize;
use function str_replace;
use function strtolower;
use function trim;

/**
Expand Down Expand Up @@ -64,6 +66,38 @@
*/
final class Schema extends AbstractPdoSchema
{
/**
* @var array The mapping from physical column types (keys) to abstract column types (values).
*
* @link https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Data-Types.html
*
* @psalm-var string[]
*/
private array $typeMap = [
'char' => self::TYPE_CHAR,
'nchar' => self::TYPE_CHAR,
'varchar2' => self::TYPE_STRING,
'nvarchar2' => self::TYPE_STRING,
'clob' => self::TYPE_TEXT,
'nclob' => self::TYPE_TEXT,
'blob' => self::TYPE_BINARY,
'bfile' => self::TYPE_BINARY,
'long raw' => self::TYPE_BINARY,
'raw' => self::TYPE_BINARY,
'number' => self::TYPE_DECIMAL,
'binary_float' => self::TYPE_FLOAT, // 32 bit
'binary_double' => self::TYPE_DOUBLE, // 64 bit
'float' => self::TYPE_DOUBLE, // 126 bit
'timestamp' => self::TYPE_TIMESTAMP,
'timestamp with time zone' => self::TYPE_TIMESTAMP,
'timestamp with local time zone' => self::TYPE_TIMESTAMP,
'date' => self::TYPE_DATE,
'interval day to second' => self::TYPE_TIME,

/** Deprecated */
'long' => self::TYPE_TEXT,
];

public function __construct(protected ConnectionInterface $db, SchemaCache $schemaCache, string $defaultSchema)
{
$this->defaultSchema = $defaultSchema;
Expand Down Expand Up @@ -614,18 +648,23 @@ public function findUniqueIndexes(TableSchemaInterface $table): array
*/
private function extractColumnType(ColumnSchemaInterface $column): string
{
$dbType = explode('(', (string) $column->getDbType(), 2)[0];

return match ($dbType) {
'FLOAT', 'DOUBLE' => self::TYPE_DOUBLE,
'NUMBER' => $column->getScale() === null || $column->getScale() > 0
? self::TYPE_DECIMAL
: self::TYPE_INTEGER,
'BLOB' => self::TYPE_BINARY,
'CLOB' => self::TYPE_TEXT,
'TIMESTAMP' => self::TYPE_TIMESTAMP,
default => self::TYPE_STRING,
};
$dbType = strtolower((string) $column->getDbType());

if ($dbType === 'number') {
return match ($column->getScale()) {
null => self::TYPE_DOUBLE,
0 => self::TYPE_INTEGER,
default => self::TYPE_DECIMAL,
};
}

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

if ($dbType === 'interval day to second' && $column->getPrecision() > 0) {
return self::TYPE_STRING;
}

return $this->typeMap[$dbType] ?? self::TYPE_STRING;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/ColumnSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function testPhpTypeCast(): void
$this->assertSame(1.234, $floatColPhpType);
$this->assertSame("\x10\x11\x12", stream_get_contents($blobColPhpType));
$this->assertEquals(false, $boolColPhpType);
$this->assertEquals(0b0110_0110, $bitColPhpType);
$this->assertSame(0b0110_0110, $bitColPhpType);

$db->close();
}
Expand Down
48 changes: 37 additions & 11 deletions tests/Provider/SchemaProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static function columns(): array
'defaultValue' => 1,
],
'char_col' => [
'type' => 'string',
'type' => 'char',
'dbType' => 'CHAR',
'phpType' => 'string',
'primaryKey' => false,
Expand Down Expand Up @@ -184,8 +184,34 @@ public static function columns(): array
'scale' => 6,
'defaultValue' => "to_timestamp('2002-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')",
],
'bool_col' => [
'time_col' => [
'type' => 'time',
'dbType' => 'INTERVAL DAY(0) TO SECOND(0)',
'phpType' => 'string',
'primaryKey' => false,
'allowNull' => true,
'autoIncrement' => false,
'enumValues' => null,
'size' => 11,
'precision' => 0,
'scale' => 0,
'defaultValue' => "INTERVAL '0 10:33:21' DAY(0) TO SECOND(0)",
],
'interval_day_col' => [
'type' => 'string',
'dbType' => 'INTERVAL DAY(1) TO SECOND(0)',
'phpType' => 'string',
'primaryKey' => false,
'allowNull' => true,
'autoIncrement' => false,
'enumValues' => null,
'size' => 11,
'precision' => 1,
'scale' => 0,
'defaultValue' => "INTERVAL '2 04:56:12' DAY(1) TO SECOND(0)",
],
'bool_col' => [
'type' => 'char',
'dbType' => 'CHAR',
'phpType' => 'string',
'primaryKey' => false,
Expand All @@ -198,7 +224,7 @@ public static function columns(): array
'defaultValue' => null,
],
'bool_col2' => [
'type' => 'string',
'type' => 'char',
'dbType' => 'CHAR',
'phpType' => 'string',
'primaryKey' => false,
Expand All @@ -224,17 +250,17 @@ public static function columns(): array
'defaultValue' => new Expression('CURRENT_TIMESTAMP'),
],
'bit_col' => [
'type' => 'string',
'dbType' => 'CHAR',
'phpType' => 'string',
'type' => 'integer',
'dbType' => 'NUMBER',
'phpType' => 'integer',
'primaryKey' => false,
'allowNull' => false,
'autoIncrement' => false,
'enumValues' => null,
'size' => 3,
'precision' => null,
'scale' => null,
'defaultValue' => '130', // b'10000010'
'size' => 22,
'precision' => 3,
'scale' => 0,
'defaultValue' => 130, // b'10000010'
],
],
'type',
Expand Down Expand Up @@ -276,7 +302,7 @@ public static function columns(): array
public static function columnsTypeChar(): array
{
return [
['char_col', 'string', 100, 'CHAR'],
['char_col', 'char', 100, 'CHAR'],
['char_col2', 'string', 100, 'VARCHAR2'],
['char_col3', 'string', 4000, 'VARCHAR2'],
];
Expand Down
2 changes: 1 addition & 1 deletion tests/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ public function testCreateTable(): void
\t"name" VARCHAR2(255) NOT NULL,
\t"email" VARCHAR2(255) NOT NULL,
\t"status" NUMBER(10) NOT NULL,
\t"created_at" TIMESTAMP NOT NULL
\t"created_at" TIMESTAMP(0) NOT NULL
)
SQL,
$qb->createTable(
Expand Down
4 changes: 3 additions & 1 deletion tests/Support/Fixture/oci.sql
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,12 @@ CREATE TABLE "type" (
"blob_col" blob DEFAULT NULL,
"numeric_col" decimal(5,2) DEFAULT 33.22,
"timestamp_col" timestamp DEFAULT to_timestamp('2002-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') NOT NULL,
"time_col" interval day (0) to second(0) DEFAULT INTERVAL '0 10:33:21' DAY(0) TO SECOND(0),
"interval_day_col" interval day (1) to second(0) DEFAULT INTERVAL '2 04:56:12' DAY(1) TO SECOND(0),
"bool_col" char NOT NULL check ("bool_col" in (0,1)),
"bool_col2" char DEFAULT 1 check("bool_col2" in (0,1)),
"ts_default" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
"bit_col" char(3) DEFAULT 130 NOT NULL
"bit_col" number(3) DEFAULT 130 NOT NULL
);

CREATE TABLE "bool_values" (
Expand Down

0 comments on commit 6888e26

Please sign in to comment.