Skip to content

Commit

Permalink
Merge pull request #232 from bowphp/5.x-refactoring-for-perf
Browse files Browse the repository at this point in the history
[5.x] Refactoring migrations to create data type for enum
  • Loading branch information
papac authored May 20, 2023
2 parents 3799316 + 812f449 commit 0a4291c
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 106 deletions.
6 changes: 3 additions & 3 deletions src/Console/Command/MigrationCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ private function createMigrationTable()
'create'
);

$generator->addColumn('migration', 'string', ['unique' => true]);
$generator->addColumn('batch', 'int');
$generator->addColumn('created_at', 'datetime', [
$generator->addString('migration', ['unique' => true]);
$generator->addInteger('batch');
$generator->addDatetime('created_at', [
'default' => 'CURRENT_TIMESTAMP',
'nullable' => true
]);
Expand Down
6 changes: 6 additions & 0 deletions src/Database/Migration/Compose/MysqlCompose.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ private function composeAddMysqlColumn(string $name, array $description): string
$unsigned = $attribute['unsigned'] ?? false;
$after = $attribute['after'] ?? false;
$first = $attribute['first'] ?? false;
$custom = $attribute['custom'] ?? false;

// String to VARCHAR
if ($raw_type == 'STRING') {
Expand Down Expand Up @@ -100,6 +101,11 @@ private function composeAddMysqlColumn(string $name, array $description): string
$type = sprintf('%s FIRST', $type);
}

// Apply the custom definition
if ($custom) {
$type = sprintf('%s %s', $type, $custom);
}

return trim(
sprintf('%s `%s` %s', $description['command'], $name, $type)
);
Expand Down
53 changes: 45 additions & 8 deletions src/Database/Migration/Compose/PgsqlCompose.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@

trait PgsqlCompose
{
protected array $custom_types = [];

/**
* Generate the custom type for pgsql
*
* @return array
*/
public function generateCustomTypes(): array
{
return $this->custom_types;
}

/**
* Compose sql statement for pgsql
*
Expand Down Expand Up @@ -35,6 +47,7 @@ private function composeAddPgsqlColumn(string $name, array $description): string
$unsigned = $attribute['unsigned'] ?? false;
$after = $attribute['after'] ?? false;
$first = $attribute['first'] ?? false;
$custom = $attribute['custom'] ?? false;

if ($after || $first) {
throw new SQLGeneratorException("The key first and after only work on mysql");
Expand All @@ -45,21 +58,40 @@ private function composeAddPgsqlColumn(string $name, array $description): string
$type = 'VARCHAR';
}

// Redefine the size
if (!$size && in_array($raw_type, ['VARCHAR', 'STRING', 'LONG VARCHAR'])) {
$size = 255;
}

// Add column size
if ($size) {
if (in_array($raw_type, ['ENUM', 'CHECK'])) {
$size = (array) $size;
$size = "'" . implode("', '", $size) . "'";
}
if (in_array($raw_type, ['ENUM', 'CHECK', 'VARCHAR', 'LONG VARCHAR', 'STRING'])) {
$type = sprintf('%s(%s)', $type, $size);
if (in_array($raw_type, ['VARCHAR', 'STRING', 'LONG VARCHAR']) && $size) {
$type = sprintf('%s(%s)', $type, $size);
}

if (in_array($raw_type, ['ENUM', 'CHECK'])) {
$size = (array) $size;
$size = "'" . implode("', '", $size) . "'";
if ($raw_type == "ENUM") {
$table = preg_replace("/(ies)$/", "y", $this->table);
$table = preg_replace("/(s)$/", "", $table);

$this->custom_types[] = sprintf(
"CREATE TYPE %s_%s_enum AS ENUM(%s);",
$table,
$name,
$size
);
$type = sprintf('%s_%s_enum', $this->table, $name);
} else {
$type = sprintf('TEXT CHECK (%s IN CHECK(%s))', $name, $size);
}
}

// Bind precision
if ($raw_type == "DOUBLE") {
$type = sprintf('DOUBLE PRECISION', $type);
}

// Bind auto increment action
if ($increment) {
$type = 'SERIAL';
Expand Down Expand Up @@ -98,8 +130,13 @@ private function composeAddPgsqlColumn(string $name, array $description): string
$type = sprintf('UNSIGNED %s', $type);
}

// Apply the custom definition
if ($custom) {
$type = sprintf('%s %s', $type, $custom);
}

return trim(
sprintf('%s %s %s', $description['command'], $name, $type)
sprintf('%s "%s" %s', $description['command'], $name, $type)
);
}

Expand Down
10 changes: 6 additions & 4 deletions src/Database/Migration/Compose/SqliteCompose.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ private function composeAddSqliteColumn(string $name, array $description): strin
$increment = $attribute['increment'] ?? false;
$nullable = $attribute['nullable'] ?? false;
$unique = $attribute['unique'] ?? false;
$custom = $attribute['custom'] ?? false;

// String to VARCHAR
if ($raw_type == 'STRING') {
Expand All @@ -43,10 +44,6 @@ private function composeAddSqliteColumn(string $name, array $description): strin
$size = 255;
}

// Add column size
if ($size) {
}

// Set column as primary key
if ($primary) {
$type = sprintf('%s PRIMARY KEY', $type);
Expand Down Expand Up @@ -79,6 +76,11 @@ private function composeAddSqliteColumn(string $name, array $description): strin
$type = sprintf('%s DEFAULT %s', $type, $default);
}

// Apply the custom definition
if ($custom) {
$type = sprintf('%s %s', $type, $custom);
}

return trim(
sprintf('%s `%s` %s', $description['command'], $name, $type)
);
Expand Down
19 changes: 14 additions & 5 deletions src/Database/Migration/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,21 @@ final public function create(string $table, callable $cb): Migration
$engine = null;
}

if ($this->adapter->getName() === 'pgsql') {
$sql = sprintf("CREATE TABLE %s (%s)%s;", $table, $generator->make(), $engine);
} else {
if ($this->adapter->getName() !== 'pgsql') {
$sql = sprintf("CREATE TABLE `%s` (%s)%s;", $table, $generator->make(), $engine);

return $this->executeSqlQuery($sql);
}

foreach ($generator->generateCustomTypes() as $sql) {
try {
$this->executeSqlQuery($sql);
} catch (\Exception $exception) {
echo sprintf("%s %s\n", Color::yellow("Warning"), $exception->getMessage());
}
}

$sql = sprintf("CREATE TABLE %s (%s)%s;", $table, $generator->make(), $engine);
return $this->executeSqlQuery($sql);
}

Expand Down Expand Up @@ -210,11 +219,11 @@ private function executeSqlQuery(string $sql): Migration
try {
Database::statement($sql);
} catch (\Exception $exception) {
echo sprintf("%s%s\n", Color::red(""), $sql);
echo sprintf("%s %s\n", Color::red(""), $sql);
throw new MigrationException($exception->getMessage(), (int) $exception->getCode());
}

echo sprintf("%s%s\n", Color::green(""), $sql);
echo sprintf("%s %s\n", Color::green(""), $sql);
return $this;
}
}
2 changes: 1 addition & 1 deletion src/Database/Migration/SQLGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public function renameColumn(string $name, string $new): SQLGenerator
}

if ($this->adapter === 'pgsql') {
$this->sqls[] = sprintf("RENAME COLUMN %s TO %s", $name, $new);
$this->sqls[] = sprintf('RENAME COLUMN "%s" TO %s', $name, $new);
} else {
$this->sqls[] = sprintf("RENAME COLUMN `%s` TO `%s`", $name, $new);
}
Expand Down
27 changes: 20 additions & 7 deletions src/Database/Migration/Shortcut/ConstraintColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,35 @@ public function addForeign(string $name, array $attributes = []): SQLGenerator

$on = '';
$references = '';
$target = sprintf("%s_%s_foreign", $this->getTable(), $name);

if ($this->adapter == "pgsql") {
$target = sprintf("\"%s_%s_foreign\"", $this->getTable(), $name);
} else {
$target = sprintf("%s_%s_foreign", $this->getTable(), $name);
}

if (isset($attributes['on'])) {
$on = strtoupper(' ON ' . $attributes['on']);
}

if (isset($attributes['references'], $attributes['table'])) {
$references = sprintf(
' REFERENCES %s(%s)',
$attributes['table'],
$attributes['references']
);
if ($this->adapter === 'pgsql') {
$references = sprintf(
' REFERENCES %s("%s")',
$attributes['table'],
$attributes['references']
);
} else {
$references = sprintf(
' REFERENCES %s(`%s`)',
$attributes['table'],
$attributes['references']
);
}
}

if ($this->adapter === 'pgsql') {
$replacement = '%s %s FOREIGN KEY (%s)%s%s';
$replacement = '%s %s FOREIGN KEY ("%s")%s%s';
} else {
$replacement = '%s %s FOREIGN KEY (`%s`)%s%s';
}
Expand Down
14 changes: 5 additions & 9 deletions src/Database/Migration/Shortcut/MixedColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ public function addUuid(string $column, array $attribute = []): SQLGenerator
return $this->addColumn($column, 'varchar', $attribute);
}

if (!isset($attribute['default']) && $this->adapter === 'pgsql') {
$attribute['default'] = 'uuid_generate_v4()';
}

return $this->addColumn($column, 'uuid', $attribute);
}

Expand Down Expand Up @@ -163,10 +159,14 @@ public function addEnum(string $column, array $attribute = []): SQLGenerator
throw new SQLGeneratorException("The enum values should be define!");
}

if (is_array($attribute['size'])) {
if (!is_array($attribute['size'])) {
throw new SQLGeneratorException("The enum values should be array");
}

if (count($attribute['size']) === 0) {
throw new SQLGeneratorException("The enum values cannot be empty.");
}

return $this->addColumn($column, 'enum', $attribute);
}

Expand Down Expand Up @@ -228,10 +228,6 @@ public function changeUuid(string $column, array $attribute = []): SQLGenerator
return $this->changeColumn($column, 'varchar', $attribute);
}

if (!isset($attribute['default']) && $this->adapter === 'pgsql') {
$attribute['default'] = 'uuid_generate_v4()';
}

return $this->changeColumn($column, 'uuid', $attribute);
}

Expand Down
24 changes: 12 additions & 12 deletions tests/Database/Migration/Pgsql/SQLGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@ public function test_add_column_sql_statement()
{
$this->generator->addColumn('name', 'int');
$sql = $this->generator->make();
$this->assertEquals($sql, 'name INT NOT NULL');
$this->assertEquals($sql, '"name" INT NOT NULL');

$this->generator->addColumn('name', 'string');
$sql = $this->generator->make();
$this->assertNotEquals($sql, 'name STRING NOT NULL');
$this->assertNotEquals($sql, '"name" STRING NOT NULL');

$this->generator->addColumn('name', 'string');
$sql = $this->generator->make();
$this->assertEquals($sql, 'name VARCHAR(255) NOT NULL');
$this->assertEquals($sql, '"name" VARCHAR(255) NOT NULL');

$this->generator->addColumn('name', 'string', ['default' => 'bow', 'size' => 100]);
$sql = $this->generator->make();
$this->assertEquals($sql, "name VARCHAR(100) NOT NULL DEFAULT 'bow'");
$this->assertEquals($sql, '"name" VARCHAR(100) NOT NULL DEFAULT \'bow\'');
}

/**
Expand All @@ -48,19 +48,19 @@ public function test_change_column_sql_statement()
{
$this->generator->changeColumn('name', 'int');
$sql = $this->generator->make();
$this->assertEquals($sql, 'MODIFY COLUMN name INT NOT NULL');
$this->assertEquals($sql, 'MODIFY COLUMN "name" INT NOT NULL');

$this->generator->changeColumn('name', 'string');
$sql = $this->generator->make();
$this->assertNotEquals($sql, 'MODIFY COLUMN name STRING NOT NULL');
$this->assertNotEquals($sql, 'MODIFY COLUMN "name" STRING NOT NULL');

$this->generator->changeColumn('name', 'string');
$sql = $this->generator->make();
$this->assertEquals($sql, 'MODIFY COLUMN name VARCHAR(255) NOT NULL');
$this->assertEquals($sql, 'MODIFY COLUMN "name" VARCHAR(255) NOT NULL');

$this->generator->changeColumn('name', 'string', ['default' => 'bow', 'size' => 100]);
$sql = $this->generator->make();
$this->assertEquals($sql, "MODIFY COLUMN name VARCHAR(100) NOT NULL DEFAULT 'bow'");
$this->assertEquals($sql, 'MODIFY COLUMN "name" VARCHAR(100) NOT NULL DEFAULT \'bow\'');
}

/**
Expand All @@ -70,7 +70,7 @@ public function test_rename_column_sql_statement_for_mysql()
{
$this->generator->renameColumn('name', 'fullname');
$sql = $this->generator->make();
$this->assertEquals($sql, 'RENAME COLUMN name TO fullname');
$this->assertEquals($sql, 'RENAME COLUMN "name" TO fullname');
}

/**
Expand Down Expand Up @@ -128,22 +128,22 @@ public function test_should_create_correct_datetime_sql_statement()
$this->generator->addDatetime('created_at', ['default' => 'CURRENT_TIMESTAMP']);
$sql = $this->generator->make();

$this->assertEquals($sql, 'created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
$this->assertEquals($sql, '"created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
}

public function test_should_create_not_correct_datetime_sql_statement()
{
$this->generator->addDatetime('created_at');
$sql = $this->generator->make();

$this->assertNotEquals($sql, 'created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
$this->assertNotEquals($sql, '"created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
}

public function test_should_create_correct_timestamps_sql_statement()
{
$this->generator->addTimestamps();
$sql = $this->generator->make();

$this->assertEquals($sql, 'created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
$this->assertEquals($sql, '"created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
}
}
Loading

0 comments on commit 0a4291c

Please sign in to comment.