Skip to content

Commit

Permalink
Merge pull request #134 from kitloong/feature/enhancement
Browse files Browse the repository at this point in the history
Generate SQL Server user defined types
  • Loading branch information
kitloong authored Nov 2, 2022
2 parents 2cec022 + 24dafdb commit c9ba8a2
Show file tree
Hide file tree
Showing 32 changed files with 218 additions and 208 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ The generator first generates all tables and then adds foreign keys to existing
However, SQLite only supports foreign keys upon creation of the table and not when tables are altered.
*_add_foreign_keys_* migrations will still be generated, however will get omitted if migrate to SQLite type database.

## PostgreSQL Custom Column Type
## User Defined Custom Column Type

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

```php
public function up()
Expand All @@ -158,6 +158,11 @@ public function up()

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.

Supported DB:

- [x] PostgreSQL
- [x] SQL Server

## Thank You

Thanks to Bernhard Breytenbach for his great work. This package is cloned from https://github.com/Xethron/migrations-generator.
Expand Down
30 changes: 1 addition & 29 deletions src/DBAL/Models/DBALColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace KitLoong\MigrationsGenerator\DBAL\Models;

use Doctrine\DBAL\Schema\Column as DoctrineDBALColumn;
use KitLoong\MigrationsGenerator\DBAL\Types\Types;
use KitLoong\MigrationsGenerator\Enum\Migrations\ColumnName;
use KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType;
use KitLoong\MigrationsGenerator\Schema\Models\Column;
Expand Down Expand Up @@ -105,7 +104,7 @@ public function __construct(string $table, DoctrineDBALColumn $column)
{
$this->tableName = $table;
$this->name = $column->getName();
$this->type = $this->mapToColumnType($column->getType()->getName());
$this->type = ColumnType::fromDBALType($column->getType());
$this->length = $column->getLength();
$this->scale = $column->getScale();
$this->precision = $column->getPrecision();
Expand Down Expand Up @@ -272,33 +271,6 @@ public function isRawDefault(): bool
return $this->rawDefault;
}

/**
* Converts built-in DBALTypes to ColumnType (Laravel column).
*
* @param string $dbalType
* @return \KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType
*/
private function mapToColumnType(string $dbalType): ColumnType
{
$map = [
Types::BIGINT => ColumnType::BIG_INTEGER(),
Types::BLOB => ColumnType::BINARY(),
Types::DATE_MUTABLE => ColumnType::DATE(),
Types::DATE_IMMUTABLE => ColumnType::DATE(),
Types::DATETIME_MUTABLE => ColumnType::DATETIME(),
Types::DATETIME_IMMUTABLE => ColumnType::DATETIME(),
Types::DATETIMETZ_MUTABLE => ColumnType::DATETIME_TZ(),
Types::DATETIMETZ_IMMUTABLE => ColumnType::DATETIME_TZ(),
Types::SMALLINT => ColumnType::SMALL_INTEGER(),
Types::GUID => ColumnType::UUID(),
Types::TIME_MUTABLE => ColumnType::TIME(),
Types::TIME_IMMUTABLE => ColumnType::TIME(),
];

// $dbalType outside from the map has the same name with ColumnType.
return $map[$dbalType] ?? ColumnType::from($dbalType);
}

/**
* Set the column type to "increments" or "*Increments" if the column is auto increment.
* If the DB supports unsigned, should check if the column is unsigned.
Expand Down
9 changes: 8 additions & 1 deletion src/DBAL/Models/DBALCustomColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ public function __construct(string $table, DoctrineDBALColumn $column)
{
$this->name = $column->getName();
$this->tableName = $table;
$this->sqls = DB::getDoctrineConnection()->getDatabasePlatform()->getAlterTableSQL(new TableDiff($this->tableName, [$column]));

// COLLATE clause cannot be used on user-defined data types.
// Unset collation here.
$platformOptions = $column->getPlatformOptions();
unset($platformOptions['collation']);
$column->setPlatformOptions($platformOptions);

$this->sqls = DB::getDoctrineConnection()->getDatabasePlatform()->getAlterTableSQL(new TableDiff($this->tableName, [$column]));
}

/**
Expand Down
147 changes: 50 additions & 97 deletions src/DBAL/RegisterColumnType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,25 @@

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types as DoctrineDBALTypes;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use KitLoong\MigrationsGenerator\DBAL\Types\CustomType;
use KitLoong\MigrationsGenerator\DBAL\Types\DoubleType;
use KitLoong\MigrationsGenerator\DBAL\Types\EnumType;
use KitLoong\MigrationsGenerator\DBAL\Types\GeometryCollectionType;
use KitLoong\MigrationsGenerator\DBAL\Types\GeometryType;
use KitLoong\MigrationsGenerator\DBAL\Types\IpAddressType;
use KitLoong\MigrationsGenerator\DBAL\Types\JsonbType;
use KitLoong\MigrationsGenerator\DBAL\Types\LineStringType;
use KitLoong\MigrationsGenerator\DBAL\Types\LongTextType;
use KitLoong\MigrationsGenerator\DBAL\Types\MacAddressType;
use KitLoong\MigrationsGenerator\DBAL\Types\MediumIntegerType;
use KitLoong\MigrationsGenerator\DBAL\Types\MediumTextType;
use KitLoong\MigrationsGenerator\DBAL\Types\MultiLineStringType;
use KitLoong\MigrationsGenerator\DBAL\Types\MultiPointType;
use KitLoong\MigrationsGenerator\DBAL\Types\MultiPolygonType;
use KitLoong\MigrationsGenerator\DBAL\Types\PointType;
use KitLoong\MigrationsGenerator\DBAL\Types\PolygonType;
use KitLoong\MigrationsGenerator\DBAL\Types\SetType;
use KitLoong\MigrationsGenerator\DBAL\Types\TimestampType;
use KitLoong\MigrationsGenerator\DBAL\Types\TimestampTzType;
use KitLoong\MigrationsGenerator\DBAL\Types\TimeTzType;
use KitLoong\MigrationsGenerator\DBAL\Types\TinyIntegerType;
use KitLoong\MigrationsGenerator\DBAL\Types\Types;
use KitLoong\MigrationsGenerator\DBAL\Types\UUIDType;
use KitLoong\MigrationsGenerator\DBAL\Types\YearType;
use KitLoong\MigrationsGenerator\Enum\Driver;
use KitLoong\MigrationsGenerator\Enum\Migrations\Method\ColumnType;
use KitLoong\MigrationsGenerator\Repositories\PgSQLRepository;
use KitLoong\MigrationsGenerator\Repositories\SQLSrvRepository;

class RegisterColumnType
{
private $pgSQLRepository;
private $sqlSrvRepository;

public function __construct(PgSQLRepository $pgSQLRepository)
public function __construct(PgSQLRepository $pgSQLRepository, SQLSrvRepository $sqlSrvRepository)
{
$this->pgSQLRepository = $pgSQLRepository;
$this->pgSQLRepository = $pgSQLRepository;
$this->sqlSrvRepository = $sqlSrvRepository;
}

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

$doctrineTypes = [
Driver::MYSQL()->getValue() => [
'bit' => Types::BOOLEAN,
'geomcollection' => Types::GEOMETRY_COLLECTION,
'json' => Types::JSON,
'mediumint' => Types::MEDIUM_INTEGER,
'tinyint' => Types::TINY_INTEGER,
'bit' => DoctrineDBALTypes::BOOLEAN,
'geomcollection' => ColumnType::GEOMETRY_COLLECTION,
'mediumint' => ColumnType::MEDIUM_INTEGER,
'tinyint' => ColumnType::TINY_INTEGER,
],
Driver::PGSQL()->getValue() => [
'_int4' => Types::TEXT,
'_int8' => Types::TEXT,
'_numeric' => Types::FLOAT,
'_text' => Types::TEXT,
'cidr' => Types::STRING,
'geography' => Types::GEOMETRY,
'inet' => Types::IP_ADDRESS,
'macaddr' => Types::MAC_ADDRESS,
'oid' => Types::STRING,
'_int4' => DoctrineDBALTypes::TEXT,
'_int8' => DoctrineDBALTypes::TEXT,
'_numeric' => DoctrineDBALTypes::FLOAT,
'_text' => DoctrineDBALTypes::TEXT,
'cidr' => DoctrineDBALTypes::STRING,
'geography' => ColumnType::GEOMETRY,
'inet' => ColumnType::IP_ADDRESS,
'macaddr' => ColumnType::MAC_ADDRESS,
'oid' => DoctrineDBALTypes::STRING,
],
Driver::SQLITE()->getValue() => [],
Driver::SQLSRV()->getValue() => [
'geography' => Types::GEOMETRY,
'money' => Types::DECIMAL,
'smallmoney' => Types::DECIMAL,
'tinyint' => Types::TINY_INTEGER,
'xml' => Types::TEXT,
'geography' => ColumnType::GEOMETRY,
'money' => DoctrineDBALTypes::DECIMAL,
'smallmoney' => DoctrineDBALTypes::DECIMAL,
'tinyint' => ColumnType::TINY_INTEGER,
'xml' => DoctrineDBALTypes::TEXT,
],
];

Expand All @@ -93,38 +74,18 @@ public function handle(): void
*/
private function registerLaravelColumnType(): void
{
/**
* The map of supported doctrine mapping types.
*/
$typeMap = [
// [$name => $className]
Types::DOUBLE => DoubleType::class,
Types::ENUM => EnumType::class,
Types::GEOMETRY => GeometryType::class,
Types::GEOMETRY_COLLECTION => GeometryCollectionType::class,
Types::IP_ADDRESS => IpAddressType::class,
Types::JSONB => JsonbType::class,
Types::LINE_STRING => LineStringType::class,
Types::LONG_TEXT => LongTextType::class,
Types::MAC_ADDRESS => MacAddressType::class,
Types::MEDIUM_INTEGER => MediumIntegerType::class,
Types::MEDIUM_TEXT => MediumTextType::class,
Types::MULTI_LINE_STRING => MultiLineStringType::class,
Types::MULTI_POINT => MultiPointType::class,
Types::MULTI_POLYGON => MultiPolygonType::class,
Types::POINT => PointType::class,
Types::POLYGON => PolygonType::class,
Types::SET => SetType::class,
Types::TIMESTAMP => TimestampType::class,
Types::TIMESTAMP_TZ => TimestampTzType::class,
Types::TIME_TZ => TimeTzType::class,
Types::TINY_INTEGER => TinyIntegerType::class,
Types::UUID => UUIDType::class,
Types::YEAR => YearType::class,
];
/** @var array<string, string> $typesMap */
$typesMap = array_flip(Types::ADDITIONAL_TYPES_MAP);

foreach ($typesMap as $type => $doctrineTypeClassName) {
// Add a new type by providing a `type` name and a `\Doctrine\DBAL\Types\Type` class name.
// eg: `$type = double`, `$doctrineTypeClassName = \KitLoong\MigrationsGenerator\DBAL\Types\DoubleType`
$this->addOrOverrideType($type, $doctrineTypeClassName);

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

Expand Down Expand Up @@ -170,41 +131,33 @@ public function getName()
*/
private function getCustomTypes(): Collection
{
if (DB::getDriverName() === Driver::PGSQL()->getValue()) {
return $this->pgSQLRepository->getCustomDataTypes();
}
switch (DB::getDriverName()) {
case Driver::PGSQL():
return $this->pgSQLRepository->getCustomDataTypes();

return new Collection();
}
case Driver::SQLSRV():
return $this->sqlSrvRepository->getCustomDataTypes();

/**
* Register custom doctrine type, override if exists.
*
* @param string $dbType
* @param string $class The class name of the custom type.
* @throws \Doctrine\DBAL\Exception
*/
private function overrideDoctrineType(string $dbType, string $class): void
{
$this->addOrOverrideType($dbType, $class);
$this->registerDoctrineTypeMapping($dbType, $dbType);
default:
return new Collection();
}
}

/**
* Add or override doctrine type.
*
* @param string $dbType
* @param string $class The class name of the custom type.
* @param string $type
* @param string $class The class name which is extends {@see \Doctrine\DBAL\Types\Type}.
* @throws \Doctrine\DBAL\Exception
*/
private function addOrOverrideType(string $dbType, string $class): void
private function addOrOverrideType(string $type, string $class): void
{
if (!Type::hasType($dbType)) {
Type::addType($dbType, $class);
if (!Type::hasType($type)) {
Type::addType($type, $class);
return;
}

Type::overrideType($dbType, $class);
Type::overrideType($type, $class);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/DBAL/Types/DoubleType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::DOUBLE;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/EnumType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::ENUM;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/GeometryCollectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::GEOMETRY_COLLECTION;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/GeometryType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::GEOMETRY;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/IpAddressType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::IP_ADDRESS;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/JsonbType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::JSONB;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/LineStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::LINE_STRING;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/LongTextType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::LONG_TEXT;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/MacAddressType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::MAC_ADDRESS;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/MediumIntegerType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::MEDIUM_INTEGER;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/MediumTextType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::MEDIUM_TEXT;
return '';
}
}
2 changes: 1 addition & 1 deletion src/DBAL/Types/MultiLineStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform)
*/
public function getName()
{
return Types::MULTI_LINE_STRING;
return '';
}
}
Loading

0 comments on commit c9ba8a2

Please sign in to comment.