Skip to content

Commit

Permalink
Merge pull request #41 from kitloong/feature/collation
Browse files Browse the repository at this point in the history
Feature/collation
  • Loading branch information
kitloong authored Jul 6, 2021
2 parents 764a304 + dd5a468 commit b027a1d
Show file tree
Hide file tree
Showing 62 changed files with 2,457 additions and 1,879 deletions.
23 changes: 23 additions & 0 deletions .env.action
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
MYSQL57_HOST=127.0.0.1
MYSQL57_PORT=3306
MYSQL57_DATABASE=migration
MYSQL57_USERNAME=root
MYSQL57_PASSWORD=

MYSQL8_HOST=127.0.0.1
MYSQL8_PORT=33062
MYSQL8_DATABASE=migration
MYSQL8_USERNAME=root
MYSQL8_PASSWORD=

POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_DATABASE=migration
POSTGRES_USERNAME=root
POSTGRES_PASSWORD=!QAZ2wsx

SQLSRV_HOST=127.0.0.1
SQLSRV_PORT=1433
SQLSRV_DATABASE=migration
SQLSRV_USERNAME=sa
SQLSRV_PASSWORD=!QAZ2wsx
17 changes: 17 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
MYSQL57_HOST=mysql57
MYSQL57_PORT=3306
MYSQL57_DATABASE=migration
MYSQL57_USERNAME=
MYSQL57_PASSWORD=

MYSQL8_HOST=mysql8
MYSQL8_PORT=3306
MYSQL8_DATABASE=migration
MYSQL8_USERNAME=
MYSQL8_PASSWORD=

POSTGRES_HOST=pgsql
POSTGRES_PORT=5432
POSTGRES_DATABASE=migration
POSTGRES_USERNAME=
POSTGRES_PASSWORD=
4 changes: 3 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/phpunit.xml.dist export-ignore
/phpunit.xml export-ignore
/tests export-ignore
/.env.* export-ignore
/phpcs.xml export-ignore
62 changes: 58 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,60 @@ jobs:
image: mysql:5.7
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: forge
MYSQL_DATABASE: migration
ports:
- 33306:3306
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

mysql8:
image: mysql:8
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: migration
ports:
- 33062:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

postgres:
image: mdillon/postgis:11
env:
POSTGRES_DB: migration
POSTGRES_USER: root
POSTGRES_PASSWORD: "!QAZ2wsx"
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
sqlsrv:
image: mcr.microsoft.com/mssql/server:2019-latest
env:
SA_PASSWORD: "!QAZ2wsx"
ACCEPT_EULA: "Y"
ports:
- 1433:1433

strategy:
matrix:
php: [ 7.3, 7.4 ]
laravel: [ 8.*, 7.*, 6.*, 5.8.*, 5.7.*, 5.6.* ]
dbal: [ 2.* ]
stability: [ prefer-stable ]
include:
- laravel: 8.*
php: 8.0
dbal: 3.*
stability: prefer-stable
- laravel: 7.*
php: 8.0
dbal: 2.*
stability: prefer-stable
- laravel: 6.*
php: 8.0
dbal: 2.*
stability: prefer-stable

name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
Expand All @@ -39,18 +74,37 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2

- name: Alter MySQL 8 root plugin
run: |
mysql --version
mysql --host 127.0.0.1 --port ${{ job.services.mysql8.ports['3306'] }} -u root -e "ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY ''"
- name: SQL Server Create Database
run: |
sleep 5s
# Test connection
sqlcmd -S 127.0.0.1 -U sa -P '!QAZ2wsx' -Q 'SELECT 1' -b
# Create DB
sqlcmd -S 127.0.0.1 -U sa -P '!QAZ2wsx' -Q 'CREATE DATABASE migration' -b
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, redis, memcached
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, redis, memcached, pdo_sqlsrv
tools: composer:v2
coverage: none

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
php -m
composer require "laravel/framework:${{ matrix.laravel }}" "doctrine/dbal:${{ matrix.dbal }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress
- name: Setup .env
run: composer run action-env-setup

- name: Execute tests
run: vendor/bin/phpunit
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ report
composer.lock
build
.idea
.phpunit.result.cache
.phpunit.result.cache
storage
.env
.phpstorm.meta.php
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Run `php artisan help migrate:generate` for a list of options.
|-t, --tables[=TABLES]|A list of Tables you wish to Generate Migrations for separated by a comma: users,posts,comments|
|-i, --ignore[=IGNORE]|A list of Tables you wish to ignore, separated by a comma: users,posts,comments|
|-p, --path[=PATH]|Where should the file be created?|
| --useDBCollation|Follow db collations for migrations|
| --defaultIndexNames|Don't use db index names for migrations|
| --defaultFKNames|Don't use db foreign key names for migrations|
|-tp, --templatePath[=TEMPLATEPATH]|The location of the template for this generator|
Expand Down
12 changes: 10 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"require-dev": {
"orchestra/testbench": "^3.6|^4.0|^5.0|^6.0",
"squizlabs/php_codesniffer": "^3.5",
"mockery/mockery": "^1.0"
"mockery/mockery": "^1.0",
"ext-pdo": "*"
},
"autoload": {
"psr-4": {
Expand All @@ -37,5 +38,12 @@
"KitLoong\\MigrationsGenerator\\MigrationsGeneratorServiceProvider"
]
}
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"action-env-setup": [
"@php -r \"file_exists('.env') || copy('.env.action', '.env');\""
]
}
}
1 change: 1 addition & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
<file>tests</file>

<exclude-pattern>features/bootstrap/FeatureContext.php</exclude-pattern>
<exclude-pattern>tests/KitLoong/resources/database/migrations/*.php</exclude-pattern>
</ruleset>
117 changes: 106 additions & 11 deletions src/KitLoong/MigrationsGenerator/Generators/DatetimeField.php
Original file line number Diff line number Diff line change
@@ -1,27 +1,51 @@
<?php
/**
* Created by PhpStorm.
* User: liow.kitloong
* Date: 2020/03/29
*/

namespace KitLoong\MigrationsGenerator\Generators;

use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Types\DateTimeImmutableType;
use Doctrine\DBAL\Types\DateTimeType;
use Doctrine\DBAL\Types\DateTimeTzImmutableType;
use Doctrine\DBAL\Types\DateTimeTzType;
use KitLoong\MigrationsGenerator\MigrationMethod\ColumnModifier;
use KitLoong\MigrationsGenerator\MigrationMethod\ColumnName;
use KitLoong\MigrationsGenerator\MigrationMethod\ColumnType;
use KitLoong\MigrationsGenerator\MigrationsGeneratorSetting;
use KitLoong\MigrationsGenerator\Repositories\MySQLRepository;
use KitLoong\MigrationsGenerator\Repositories\PgSQLRepository;
use KitLoong\MigrationsGenerator\Repositories\SQLSrvRepository;
use KitLoong\MigrationsGenerator\Support\Regex;
use KitLoong\MigrationsGenerator\Types\DBALTypes;

class DatetimeField
{
const SQLSRV_DATETIME_DEFAULT_SCALE = 3;
const SQLSRV_DATETIME_DEFAULT_LENGTH = 8;

const SQLSRV_DATETIME_TZ_DEFAULT_SCALE = 7;
const SQLSRV_DATETIME_TZ_DEFAULT_LENGTH = 10;

private $decorator;
private $mySQLRepository;
private $pgSQLRepository;
private $sqlSrvRepository;
private $regex;

public function __construct(Decorator $decorator)
{
public function __construct(
Decorator $decorator,
MySQLRepository $mySQLRepository,
PgSQLRepository $pgSQLRepository,
SQLSrvRepository $sqlSrvRepository,
Regex $regex
) {
$this->decorator = $decorator;
$this->mySQLRepository = $mySQLRepository;
$this->pgSQLRepository = $pgSQLRepository;
$this->sqlSrvRepository = $sqlSrvRepository;
$this->regex = $regex;
}

public function makeField(array $field, Column $column, bool $useTimestamps): array
public function makeField(string $table, array $field, Column $column, bool $useTimestamps): array
{
if ($useTimestamps) {
if ($field['field'] === ColumnName::CREATED_AT) {
Expand All @@ -41,19 +65,31 @@ public function makeField(array $field, Column $column, bool $useTimestamps): ar
$field['type'] = FieldGenerator::$fieldTypeMap[$field['type']];
}

if ($column->getLength() !== null && $column->getLength() > 0) {
$length = $this->getLength($table, $column);
if ($length !== null && $length > 0) {
if ($field['type'] === ColumnType::SOFT_DELETES) {
$field['field'] = ColumnName::DELETED_AT;
}
$field['args'][] = $column->getLength();
$field['args'][] = $length;
}

if (app(MigrationsGeneratorSetting::class)->getPlatform() === Platform::MYSQL) {
if ($column->getType()->getName() === DBALTypes::TIMESTAMP) {
if ($this->mySQLRepository->useOnUpdateCurrentTimestamp($table, $column->getName())) {
$field['decorators'][] = ColumnModifier::USE_CURRENT_ON_UPDATE;
}
}
}

return $field;
}

public function makeDefault(Column $column): string
{
if (in_array($column->getDefault(), ['CURRENT_TIMESTAMP'], true)) {
return ColumnModifier::USE_CURRENT;
} elseif ($column->getDefault() === 'now()') { // For PgSQL
return ColumnModifier::USE_CURRENT;
} else {
$default = $this->decorator->columnDefaultToString($column->getDefault());
return $this->decorator->decorate(ColumnModifier::DEFAULT, [$default]);
Expand All @@ -64,7 +100,7 @@ public function makeDefault(Column $column): string
* @param Column[] $columns
* @return bool
*/
public function isUseTimestamps($columns): bool
public function isUseTimestamps(array $columns): bool
{
/** @var Column[] $timestampsColumns */
$timestampsColumns = [];
Expand All @@ -86,4 +122,63 @@ public function isUseTimestamps($columns): bool
}
return $useTimestamps;
}

private function getLength(string $table, Column $column): ?int
{
switch (app(MigrationsGeneratorSetting::class)->getPlatform()) {
case Platform::POSTGRESQL:
return $this->getPgSQLLength($table, $column);
case Platform::SQLSERVER:
return $this->getSQLSrvLength($table, $column);
default:
return $column->getLength();
}
}

/**
* @param string $table
* @param \Doctrine\DBAL\Schema\Column $column
* @return int|null
*/
private function getPgSQLLength(string $table, Column $column): ?int
{
$rawType = ($this->pgSQLRepository->getTypeByColumnName($table, $column->getName()));
$length = $this->regex->getTextBetween($rawType);
if ($length !== null) {
return (int) $length;
} else {
return null;
}
}

/**
* @param string $table
* @param \Doctrine\DBAL\Schema\Column $column
* @return int|null
*/
private function getSQLSrvLength(string $table, Column $column): ?int
{
$colDef = $this->sqlSrvRepository->getColumnDefinition($table, $column->getName());

switch (get_class($column->getType())) {
case DateTimeType::class:
case DateTimeImmutableType::class:
if ($colDef->getScale() === self::SQLSRV_DATETIME_DEFAULT_SCALE &&
$colDef->getLength() === self::SQLSRV_DATETIME_DEFAULT_LENGTH) {
return null;
} else {
return $column->getScale();
}
case DateTimeTzType::class:
case DateTimeTzImmutableType::class:
if ($colDef->getScale() === self::SQLSRV_DATETIME_TZ_DEFAULT_SCALE &&
$colDef->getLength() === self::SQLSRV_DATETIME_TZ_DEFAULT_LENGTH) {
return null;
} else {
return $column->getScale();
}
default:
return $column->getScale();
}
}
}
Loading

0 comments on commit b027a1d

Please sign in to comment.