Skip to content

Commit c9ba8a2

Browse files
authored
Merge pull request #134 from kitloong/feature/enhancement
Generate SQL Server user defined types
2 parents 2cec022 + 24dafdb commit c9ba8a2

32 files changed

+218
-208
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ The generator first generates all tables and then adds foreign keys to existing
142142
However, SQLite only supports foreign keys upon creation of the table and not when tables are altered.
143143
*_add_foreign_keys_* migrations will still be generated, however will get omitted if migrate to SQLite type database.
144144

145-
## PostgreSQL Custom Column Type
145+
## User Defined Custom Column Type
146146

147-
The generator will register custom data type from `pg_type`, then generate migration as
147+
The generator will register custom data type from the schema, then generate migration as
148148

149149
```php
150150
public function up()
@@ -158,6 +158,11 @@ public function up()
158158

159159
Note that the new `column` is always added at the end of the created `table` which means the ordering of the column generated in migration will differ from what we have from the schema.
160160

161+
Supported DB:
162+
163+
- [x] PostgreSQL
164+
- [x] SQL Server
165+
161166
## Thank You
162167

163168
Thanks to Bernhard Breytenbach for his great work. This package is cloned from https://github.com/Xethron/migrations-generator.

src/DBAL/Models/DBALColumn.php

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace KitLoong\MigrationsGenerator\DBAL\Models;
44

55
use Doctrine\DBAL\Schema\Column as DoctrineDBALColumn;
6-
use KitLoong\MigrationsGenerator\DBAL\Types\Types;
76
use KitLoong\MigrationsGenerator\Enum\Migrations\ColumnName;
87
use KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType;
98
use KitLoong\MigrationsGenerator\Schema\Models\Column;
@@ -105,7 +104,7 @@ public function __construct(string $table, DoctrineDBALColumn $column)
105104
{
106105
$this->tableName = $table;
107106
$this->name = $column->getName();
108-
$this->type = $this->mapToColumnType($column->getType()->getName());
107+
$this->type = ColumnType::fromDBALType($column->getType());
109108
$this->length = $column->getLength();
110109
$this->scale = $column->getScale();
111110
$this->precision = $column->getPrecision();
@@ -272,33 +271,6 @@ public function isRawDefault(): bool
272271
return $this->rawDefault;
273272
}
274273

275-
/**
276-
* Converts built-in DBALTypes to ColumnType (Laravel column).
277-
*
278-
* @param string $dbalType
279-
* @return \KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType
280-
*/
281-
private function mapToColumnType(string $dbalType): ColumnType
282-
{
283-
$map = [
284-
Types::BIGINT => ColumnType::BIG_INTEGER(),
285-
Types::BLOB => ColumnType::BINARY(),
286-
Types::DATE_MUTABLE => ColumnType::DATE(),
287-
Types::DATE_IMMUTABLE => ColumnType::DATE(),
288-
Types::DATETIME_MUTABLE => ColumnType::DATETIME(),
289-
Types::DATETIME_IMMUTABLE => ColumnType::DATETIME(),
290-
Types::DATETIMETZ_MUTABLE => ColumnType::DATETIME_TZ(),
291-
Types::DATETIMETZ_IMMUTABLE => ColumnType::DATETIME_TZ(),
292-
Types::SMALLINT => ColumnType::SMALL_INTEGER(),
293-
Types::GUID => ColumnType::UUID(),
294-
Types::TIME_MUTABLE => ColumnType::TIME(),
295-
Types::TIME_IMMUTABLE => ColumnType::TIME(),
296-
];
297-
298-
// $dbalType outside from the map has the same name with ColumnType.
299-
return $map[$dbalType] ?? ColumnType::from($dbalType);
300-
}
301-
302274
/**
303275
* Set the column type to "increments" or "*Increments" if the column is auto increment.
304276
* If the DB supports unsigned, should check if the column is unsigned.

src/DBAL/Models/DBALCustomColumn.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ public function __construct(string $table, DoctrineDBALColumn $column)
3131
{
3232
$this->name = $column->getName();
3333
$this->tableName = $table;
34-
$this->sqls = DB::getDoctrineConnection()->getDatabasePlatform()->getAlterTableSQL(new TableDiff($this->tableName, [$column]));
34+
35+
// COLLATE clause cannot be used on user-defined data types.
36+
// Unset collation here.
37+
$platformOptions = $column->getPlatformOptions();
38+
unset($platformOptions['collation']);
39+
$column->setPlatformOptions($platformOptions);
40+
41+
$this->sqls = DB::getDoctrineConnection()->getDatabasePlatform()->getAlterTableSQL(new TableDiff($this->tableName, [$column]));
3542
}
3643

3744
/**

src/DBAL/RegisterColumnType.php

Lines changed: 50 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,25 @@
44

55
use Doctrine\DBAL\Platforms\AbstractPlatform;
66
use Doctrine\DBAL\Types\Type;
7+
use Doctrine\DBAL\Types\Types as DoctrineDBALTypes;
78
use Illuminate\Support\Collection;
89
use Illuminate\Support\Facades\DB;
910
use KitLoong\MigrationsGenerator\DBAL\Types\CustomType;
10-
use KitLoong\MigrationsGenerator\DBAL\Types\DoubleType;
11-
use KitLoong\MigrationsGenerator\DBAL\Types\EnumType;
12-
use KitLoong\MigrationsGenerator\DBAL\Types\GeometryCollectionType;
13-
use KitLoong\MigrationsGenerator\DBAL\Types\GeometryType;
14-
use KitLoong\MigrationsGenerator\DBAL\Types\IpAddressType;
15-
use KitLoong\MigrationsGenerator\DBAL\Types\JsonbType;
16-
use KitLoong\MigrationsGenerator\DBAL\Types\LineStringType;
17-
use KitLoong\MigrationsGenerator\DBAL\Types\LongTextType;
18-
use KitLoong\MigrationsGenerator\DBAL\Types\MacAddressType;
19-
use KitLoong\MigrationsGenerator\DBAL\Types\MediumIntegerType;
20-
use KitLoong\MigrationsGenerator\DBAL\Types\MediumTextType;
21-
use KitLoong\MigrationsGenerator\DBAL\Types\MultiLineStringType;
22-
use KitLoong\MigrationsGenerator\DBAL\Types\MultiPointType;
23-
use KitLoong\MigrationsGenerator\DBAL\Types\MultiPolygonType;
24-
use KitLoong\MigrationsGenerator\DBAL\Types\PointType;
25-
use KitLoong\MigrationsGenerator\DBAL\Types\PolygonType;
26-
use KitLoong\MigrationsGenerator\DBAL\Types\SetType;
27-
use KitLoong\MigrationsGenerator\DBAL\Types\TimestampType;
28-
use KitLoong\MigrationsGenerator\DBAL\Types\TimestampTzType;
29-
use KitLoong\MigrationsGenerator\DBAL\Types\TimeTzType;
30-
use KitLoong\MigrationsGenerator\DBAL\Types\TinyIntegerType;
3111
use KitLoong\MigrationsGenerator\DBAL\Types\Types;
32-
use KitLoong\MigrationsGenerator\DBAL\Types\UUIDType;
33-
use KitLoong\MigrationsGenerator\DBAL\Types\YearType;
3412
use KitLoong\MigrationsGenerator\Enum\Driver;
13+
use KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType;
3514
use KitLoong\MigrationsGenerator\Repositories\PgSQLRepository;
15+
use KitLoong\MigrationsGenerator\Repositories\SQLSrvRepository;
3616

3717
class RegisterColumnType
3818
{
3919
private $pgSQLRepository;
20+
private $sqlSrvRepository;
4021

41-
public function __construct(PgSQLRepository $pgSQLRepository)
22+
public function __construct(PgSQLRepository $pgSQLRepository, SQLSrvRepository $sqlSrvRepository)
4223
{
43-
$this->pgSQLRepository = $pgSQLRepository;
24+
$this->pgSQLRepository = $pgSQLRepository;
25+
$this->sqlSrvRepository = $sqlSrvRepository;
4426
}
4527

4628
/**
@@ -53,30 +35,29 @@ public function handle(): void
5335

5436
$doctrineTypes = [
5537
Driver::MYSQL()->getValue() => [
56-
'bit' => Types::BOOLEAN,
57-
'geomcollection' => Types::GEOMETRY_COLLECTION,
58-
'json' => Types::JSON,
59-
'mediumint' => Types::MEDIUM_INTEGER,
60-
'tinyint' => Types::TINY_INTEGER,
38+
'bit' => DoctrineDBALTypes::BOOLEAN,
39+
'geomcollection' => ColumnType::GEOMETRY_COLLECTION,
40+
'mediumint' => ColumnType::MEDIUM_INTEGER,
41+
'tinyint' => ColumnType::TINY_INTEGER,
6142
],
6243
Driver::PGSQL()->getValue() => [
63-
'_int4' => Types::TEXT,
64-
'_int8' => Types::TEXT,
65-
'_numeric' => Types::FLOAT,
66-
'_text' => Types::TEXT,
67-
'cidr' => Types::STRING,
68-
'geography' => Types::GEOMETRY,
69-
'inet' => Types::IP_ADDRESS,
70-
'macaddr' => Types::MAC_ADDRESS,
71-
'oid' => Types::STRING,
44+
'_int4' => DoctrineDBALTypes::TEXT,
45+
'_int8' => DoctrineDBALTypes::TEXT,
46+
'_numeric' => DoctrineDBALTypes::FLOAT,
47+
'_text' => DoctrineDBALTypes::TEXT,
48+
'cidr' => DoctrineDBALTypes::STRING,
49+
'geography' => ColumnType::GEOMETRY,
50+
'inet' => ColumnType::IP_ADDRESS,
51+
'macaddr' => ColumnType::MAC_ADDRESS,
52+
'oid' => DoctrineDBALTypes::STRING,
7253
],
7354
Driver::SQLITE()->getValue() => [],
7455
Driver::SQLSRV()->getValue() => [
75-
'geography' => Types::GEOMETRY,
76-
'money' => Types::DECIMAL,
77-
'smallmoney' => Types::DECIMAL,
78-
'tinyint' => Types::TINY_INTEGER,
79-
'xml' => Types::TEXT,
56+
'geography' => ColumnType::GEOMETRY,
57+
'money' => DoctrineDBALTypes::DECIMAL,
58+
'smallmoney' => DoctrineDBALTypes::DECIMAL,
59+
'tinyint' => ColumnType::TINY_INTEGER,
60+
'xml' => DoctrineDBALTypes::TEXT,
8061
],
8162
];
8263

@@ -93,38 +74,18 @@ public function handle(): void
9374
*/
9475
private function registerLaravelColumnType(): void
9576
{
96-
/**
97-
* The map of supported doctrine mapping types.
98-
*/
99-
$typeMap = [
100-
// [$name => $className]
101-
Types::DOUBLE => DoubleType::class,
102-
Types::ENUM => EnumType::class,
103-
Types::GEOMETRY => GeometryType::class,
104-
Types::GEOMETRY_COLLECTION => GeometryCollectionType::class,
105-
Types::IP_ADDRESS => IpAddressType::class,
106-
Types::JSONB => JsonbType::class,
107-
Types::LINE_STRING => LineStringType::class,
108-
Types::LONG_TEXT => LongTextType::class,
109-
Types::MAC_ADDRESS => MacAddressType::class,
110-
Types::MEDIUM_INTEGER => MediumIntegerType::class,
111-
Types::MEDIUM_TEXT => MediumTextType::class,
112-
Types::MULTI_LINE_STRING => MultiLineStringType::class,
113-
Types::MULTI_POINT => MultiPointType::class,
114-
Types::MULTI_POLYGON => MultiPolygonType::class,
115-
Types::POINT => PointType::class,
116-
Types::POLYGON => PolygonType::class,
117-
Types::SET => SetType::class,
118-
Types::TIMESTAMP => TimestampType::class,
119-
Types::TIMESTAMP_TZ => TimestampTzType::class,
120-
Types::TIME_TZ => TimeTzType::class,
121-
Types::TINY_INTEGER => TinyIntegerType::class,
122-
Types::UUID => UUIDType::class,
123-
Types::YEAR => YearType::class,
124-
];
77+
/** @var array<string, string> $typesMap */
78+
$typesMap = array_flip(Types::ADDITIONAL_TYPES_MAP);
79+
80+
foreach ($typesMap as $type => $doctrineTypeClassName) {
81+
// Add a new type by providing a `type` name and a `\Doctrine\DBAL\Types\Type` class name.
82+
// eg: `$type = double`, `$doctrineTypeClassName = \KitLoong\MigrationsGenerator\DBAL\Types\DoubleType`
83+
$this->addOrOverrideType($type, $doctrineTypeClassName);
12584

126-
foreach ($typeMap as $dbType => $class) {
127-
$this->overrideDoctrineType($dbType, $class);
85+
// Register type mapping so that Doctrine DBAL can recognize the DB column type.
86+
// eg: `$type = double`
87+
// Now Doctrine DBAL can recognize `column double NOT NULL` and create a column instance with type `\KitLoong\MigrationsGenerator\DBAL\Types\DoubleType`.
88+
$this->registerDoctrineTypeMapping($type, $type);
12889
}
12990
}
13091

@@ -170,41 +131,33 @@ public function getName()
170131
*/
171132
private function getCustomTypes(): Collection
172133
{
173-
if (DB::getDriverName() === Driver::PGSQL()->getValue()) {
174-
return $this->pgSQLRepository->getCustomDataTypes();
175-
}
134+
switch (DB::getDriverName()) {
135+
case Driver::PGSQL():
136+
return $this->pgSQLRepository->getCustomDataTypes();
176137

177-
return new Collection();
178-
}
138+
case Driver::SQLSRV():
139+
return $this->sqlSrvRepository->getCustomDataTypes();
179140

180-
/**
181-
* Register custom doctrine type, override if exists.
182-
*
183-
* @param string $dbType
184-
* @param string $class The class name of the custom type.
185-
* @throws \Doctrine\DBAL\Exception
186-
*/
187-
private function overrideDoctrineType(string $dbType, string $class): void
188-
{
189-
$this->addOrOverrideType($dbType, $class);
190-
$this->registerDoctrineTypeMapping($dbType, $dbType);
141+
default:
142+
return new Collection();
143+
}
191144
}
192145

193146
/**
194147
* Add or override doctrine type.
195148
*
196-
* @param string $dbType
197-
* @param string $class The class name of the custom type.
149+
* @param string $type
150+
* @param string $class The class name which is extends {@see \Doctrine\DBAL\Types\Type}.
198151
* @throws \Doctrine\DBAL\Exception
199152
*/
200-
private function addOrOverrideType(string $dbType, string $class): void
153+
private function addOrOverrideType(string $type, string $class): void
201154
{
202-
if (!Type::hasType($dbType)) {
203-
Type::addType($dbType, $class);
155+
if (!Type::hasType($type)) {
156+
Type::addType($type, $class);
204157
return;
205158
}
206159

207-
Type::overrideType($dbType, $class);
160+
Type::overrideType($type, $class);
208161
}
209162

210163
/**

src/DBAL/Types/DoubleType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::DOUBLE;
27+
return '';
2828
}
2929
}

src/DBAL/Types/EnumType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::ENUM;
27+
return '';
2828
}
2929
}

src/DBAL/Types/GeometryCollectionType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::GEOMETRY_COLLECTION;
27+
return '';
2828
}
2929
}

src/DBAL/Types/GeometryType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::GEOMETRY;
27+
return '';
2828
}
2929
}

src/DBAL/Types/IpAddressType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::IP_ADDRESS;
27+
return '';
2828
}
2929
}

src/DBAL/Types/JsonbType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::JSONB;
27+
return '';
2828
}
2929
}

src/DBAL/Types/LineStringType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::LINE_STRING;
27+
return '';
2828
}
2929
}

src/DBAL/Types/LongTextType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::LONG_TEXT;
27+
return '';
2828
}
2929
}

src/DBAL/Types/MacAddressType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::MAC_ADDRESS;
27+
return '';
2828
}
2929
}

src/DBAL/Types/MediumIntegerType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::MEDIUM_INTEGER;
27+
return '';
2828
}
2929
}

src/DBAL/Types/MediumTextType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::MEDIUM_TEXT;
27+
return '';
2828
}
2929
}

src/DBAL/Types/MultiLineStringType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
2424
*/
2525
public function getName()
2626
{
27-
return Types::MULTI_LINE_STRING;
27+
return '';
2828
}
2929
}

0 commit comments

Comments
 (0)