Skip to content

Commit

Permalink
[Feature] Alter DataType Parameters (#47)
Browse files Browse the repository at this point in the history
Updated gitignore
Added support for altering datatype parameters
Updated testdata folder
Added tests for feature
  • Loading branch information
atedesch1 authored Jun 26, 2022
1 parent 16aa0cf commit 409a599
Show file tree
Hide file tree
Showing 20 changed files with 137 additions and 27 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ coverage.txt

dist
.release-env
unit_coverage.out
unit_coverage.out
.mgr8
19 changes: 19 additions & 0 deletions domain/column_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,22 @@ func (m *MakeColumnNullableDiff) Up(deparser Deparser) string {
func (m *MakeColumnNullableDiff) Down(deparser Deparser) string {
return deparser.MakeColumnNotNull(m.tableName, m.columnName, m.column)
}

type ChangeColumnDataTypeParameterDiff struct {
tableName string
columnName string
originalColumn *Column
column *Column
}

func NewChangeColumnParameterDiff(tableName string, columnName string, originalColumn *Column, column *Column) *ChangeColumnDataTypeParameterDiff {
return &ChangeColumnDataTypeParameterDiff{tableName: tableName, columnName: columnName, originalColumn: originalColumn, column: column}
}

func (m *ChangeColumnDataTypeParameterDiff) Up(deparser Deparser) string {
return deparser.ChangeDataTypeParameters(m.tableName, m.columnName, m.column)
}

func (m *ChangeColumnDataTypeParameterDiff) Down(deparser Deparser) string {
return deparser.ChangeDataTypeParameters(m.tableName, m.columnName, m.originalColumn)
}
8 changes: 8 additions & 0 deletions domain/diff.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package domain

import "reflect"

type Diff interface {
Up(driver Deparser) string
Down(driver Deparser) string
Expand Down Expand Up @@ -50,12 +52,18 @@ func (t *Table) Diff(originalTable *Table) DiffDeque {
func (c *Column) Diff(table *Table, columnName string, originalColumn *Column) DiffDeque {
diffsQueue := NewDiffDeque()
column := table.Columns[columnName]

if !reflect.DeepEqual(column.Parameters, originalColumn.Parameters) {
diffsQueue.Add(NewChangeColumnParameterDiff(table.Name, columnName, originalColumn, column))
}

if column.IsNotNull != originalColumn.IsNotNull {
if column.IsNotNull {
diffsQueue.Add(NewMakeColumnNotNullDiff(table.Name, columnName, column))
} else {
diffsQueue.Add(NewMakeColumnNullableDiff(table.Name, columnName, column))
}
}

return diffsQueue
}
2 changes: 2 additions & 0 deletions domain/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ type Deparser interface {
MakeColumnNotNull(tableName, columnName string, column *Column) string
MakeColumnNullable(tableName, columnName string, column *Column) string

ChangeDataTypeParameters(tableName, columnName string, column *Column) string

WriteScript(statements []string) string
}
10 changes: 10 additions & 0 deletions drivers/mysql/deparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ func (d *deparser) MakeColumnNullable(tableName, columnName string, column *doma
return fmt.Sprintf("ALTER TABLE %s MODIFY %s NULL", tableName, columnDatatype)
}

func (d *deparser) ChangeDataTypeParameters(tableName, columnName string, column *domain.Column) string {
_, hasSize := column.Parameters["size"]

if hasSize {
return fmt.Sprintf("ALTER TABLE %s MODIFY %s %s(%s)", tableName, columnName, column.Datatype, fmt.Sprint(column.Parameters["size"]))
} else {
return fmt.Sprintf("ALTER TABLE %s MODIFY %s %s(%s, %s)", tableName, columnName, column.Datatype, fmt.Sprint(column.Parameters["precision"]), fmt.Sprint(column.Parameters["scale"]))
}
}

func (d *deparser) WriteScript(statements []string) string {
var scriptContent string
for _, s := range statements {
Expand Down
17 changes: 14 additions & 3 deletions drivers/postgres/deparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ func (d *deparser) CreateTable(table *domain.Table) string {
}

if column.IsNotNull {
statement = statement + fmt.Sprintf(" NOT NULL")
statement = statement + " NOT NULL"
}

statement = statement + fmt.Sprintf(",\n")
statement = statement + ",\n"
}

statement = statement[0 : len(statement)-2]
statement = statement + fmt.Sprintf("\n)")
statement = statement + "\n)"
return statement
}

Expand All @@ -87,6 +87,7 @@ func (d *deparser) AddColumn(tableName, columnName string, column *domain.Column
func (d *deparser) DropColumn(tableName, columnName string) string {
return fmt.Sprintf("ALTER TABLE %s DROP COLUMN %s", tableName, columnName)
}

func (d *deparser) MakeColumnNotNull(tableName, columnName string, column *domain.Column) string {
return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET NOT NULL", tableName, columnName)
}
Expand All @@ -95,6 +96,16 @@ func (d *deparser) MakeColumnNullable(tableName, columnName string, column *doma
return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s DROP NOT NULL", tableName, columnName)
}

func (d *deparser) ChangeDataTypeParameters(tableName, columnName string, column *domain.Column) string {
_, hasSize := column.Parameters["size"]

if hasSize {
return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s TYPE %s(%s)", tableName, columnName, column.Datatype, fmt.Sprint(column.Parameters["size"]))
} else {
return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s TYPE %s(%s, %s)", tableName, columnName, column.Datatype, fmt.Sprint(column.Parameters["precision"]), fmt.Sprint(column.Parameters["scale"]))
}
}

func (d *deparser) WriteScript(statements []string) string {
var scriptContent string
for _, s := range statements {
Expand Down
7 changes: 6 additions & 1 deletion drivers/postgres/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,15 @@ func (d *postgresDriver) parseColumn(columnDefinition *pg_query.ColumnDef) *doma
datatype := columnDefinition.TypeName.Names[1].GetString_().GetStr()
parameters := make(map[string]interface{})

if datatype == "varchar" {
if hasSingleArg(datatype) {
parameters["size"] = columnDefinition.TypeName.Typmods[0].GetAConst().Val.GetInteger().Ival
}

if hasDoubleArg(datatype) {
parameters["precision"] = columnDefinition.TypeName.Typmods[0].GetAConst().Val.GetInteger().Ival
parameters["scale"] = columnDefinition.TypeName.Typmods[1].GetAConst().Val.GetInteger().Ival
}

isNotNull := false
for _, constraint := range columnDefinition.Constraints {
if constraint.GetConstraint().GetContype().String() == "CONSTR_NOTNULL" {
Expand Down
24 changes: 22 additions & 2 deletions drivers/postgres/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ var _ = Describe("Postgres Driver", func() {
CREATE TABLE users (
social_number VARCHAR(9) PRIMARY KEY,
phone VARCHAR(11),
name VARCHAR(15),
name VARCHAR(15) NOT NULL,
age INTEGER,
size INT,
height DECIMAL(2, 3),
ddi VARCHAR(3)
);
Expand All @@ -44,10 +45,11 @@ var _ = Describe("Postgres Driver", func() {
Columns: map[string]*domain.Column{
"social_number": {Datatype: "varchar", IsNotNull: false, Parameters: map[string]interface{}{"size": int32(9)}},
"phone": {Datatype: "varchar", IsNotNull: false, Parameters: map[string]interface{}{"size": int32(11)}},
"name": {Datatype: "varchar", IsNotNull: false, Parameters: map[string]interface{}{"size": int32(15)}},
"name": {Datatype: "varchar", IsNotNull: true, Parameters: map[string]interface{}{"size": int32(15)}},
"ddi": {Datatype: "varchar", IsNotNull: false, Parameters: map[string]interface{}{"size": int32(3)}},
"age": {Datatype: "int4", IsNotNull: false, Parameters: map[string]interface{}{}},
"size": {Datatype: "int4", IsNotNull: false, Parameters: map[string]interface{}{}},
"height": {Datatype: "numeric", IsNotNull: false, Parameters: map[string]interface{}{"precision": int32(2), "scale": int32(3)}},
},
},
},
Expand Down Expand Up @@ -128,6 +130,24 @@ var _ = Describe("Postgres Driver", func() {
})
})

When("A column's datatype parameters change", func() {
It("Changes single parameter datatype", func() {
columnName := "col"
tableName := "tbl"
column := &domain.Column{Datatype: "varchar", IsNotNull: false, Parameters: map[string]interface{}{"size": int32(10)}}
stmt := subject.ChangeDataTypeParameters(tableName, columnName, column)
Expect(strings.ToLower(stmt)).To(Equal("alter table tbl alter column col type varchar(10)"))
})

It("Changes double parameter datatype", func() {
columnName := "col"
tableName := "tbl"
column := &domain.Column{Datatype: "decimal", IsNotNull: false, Parameters: map[string]interface{}{"precision": int32(2), "scale": int32(3)}}
stmt := subject.ChangeDataTypeParameters(tableName, columnName, column)
Expect(strings.ToLower(stmt)).To(Equal("alter table tbl alter column col type decimal(2, 3)"))
})
})

When("New schema doesn't have a table", func() {
It("Drops the table", func() {
tableName := "tbl"
Expand Down
14 changes: 14 additions & 0 deletions mock/domain/driver_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file added testdata/0000_schema.sql
Empty file.
12 changes: 12 additions & 0 deletions testdata/0001_schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CREATE TABLE users (
social_number VARCHAR(9) PRIMARY KEY,
nombre VARCHAR(20) NOT NULL,
phone VARCHAR(20),
ddi VARCHAR(20),
num DECIMAL(20, 10)
);

CREATE TABLE products (
nombre VARCHAR(256),
qnt INTEGER
);
6 changes: 6 additions & 0 deletions testdata/0002_schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE users (
social_number VARCHAR(9) PRIMARY KEY,
nombre VARCHAR(15),
phone VARCHAR(11),
num DECIMAL(10, 5)
);
11 changes: 0 additions & 11 deletions testdata/new_schema.sql

This file was deleted.

5 changes: 0 additions & 5 deletions testdata/old_schema.sql

This file was deleted.

1 change: 1 addition & 0 deletions testdata/output/0001_1656197671.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS users;
6 changes: 6 additions & 0 deletions testdata/output/0001_1656197671.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE users (
nombre varchar(15),
num numeric(10,5),
phone varchar(11),
social_number varchar(9)
);
6 changes: 6 additions & 0 deletions testdata/output/0002_1656197676.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE users DROP COLUMN ddi;
ALTER TABLE users ALTER COLUMN num TYPE numeric(10, 5);
ALTER TABLE users ALTER COLUMN nombre TYPE varchar(15);
ALTER TABLE users ALTER COLUMN nombre DROP NOT NULL;
ALTER TABLE users ALTER COLUMN phone TYPE varchar(11);
DROP TABLE IF EXISTS products;
9 changes: 9 additions & 0 deletions testdata/output/0002_1656197676.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ALTER TABLE users ADD COLUMN ddi varchar(20);
ALTER TABLE users ALTER COLUMN num TYPE numeric(20, 10);
ALTER TABLE users ALTER COLUMN nombre TYPE varchar(20);
ALTER TABLE users ALTER COLUMN nombre SET NOT NULL;
ALTER TABLE users ALTER COLUMN phone TYPE varchar(20);
CREATE TABLE products (
nombre varchar(256),
qnt int4
);
2 changes: 0 additions & 2 deletions testdata/output/down_migration.sql

This file was deleted.

2 changes: 0 additions & 2 deletions testdata/output/up_migration.sql

This file was deleted.

0 comments on commit 409a599

Please sign in to comment.