Skip to content

Commit

Permalink
Feature/alter table add foreign key (#152)
Browse files Browse the repository at this point in the history
* sqlite alter table add foreign key

* postgre alter table add foreign key

* mysql alter table add foreign key

* sqlite alter table delete foreign

* mysql alter table delete foreign

* fix mysql alter table delete foreign

* postgre alter table delete foreign

* test seccess

* update doc

* fix run test

* success test

* success test

* fix regex
  • Loading branch information
itsumura-h authored Jul 10, 2021
1 parent d35eba6 commit 39999ae
Show file tree
Hide file tree
Showing 17 changed files with 501 additions and 263 deletions.
2 changes: 1 addition & 1 deletion allographer.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.17.5"
version = "0.18.0"
author = "Hidenobu Itsumura @dumblepytech1 as 'medy'"
description = "A Nim query builder library inspired by Laravel/PHP and Orator/Python"
license = "MIT"
Expand Down
14 changes: 10 additions & 4 deletions documents/schema_builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,14 @@ If you set `reset=true` in args of `Table().create`, `DROP TABLE` and `CREATE TA
### add column
```nim
alter(
table("users",
add().string("email").unique().default("")
)
table("auth", [
add.increments("id"),
add.string("name"),
]),
table("users",[
add().string("email").unique().default(""),
add().foreign("auth_id").reference("id").on("auth").onDelete(SET_NULL)
])
)
```
`>> ALTER TABLE "users" ADD COLUMN 'email' UNIQUE DEFAULT '' CHECK (length('email') <= 255)`
Expand All @@ -75,7 +80,8 @@ alter(
```nim
alter(
table("users",
delete("name")
delete().column("name")
delete().foreign("auth_id")
)
)
```
Expand Down
10 changes: 7 additions & 3 deletions src/allographer/schema_builder/alter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ proc add*():Column =
proc change*(name:string):Column =
return Column(alterTyp:Change, previousName:name)

proc delete*(name:string):Column =
return Column(alterTyp:Delete, previousName:name)

proc rename*(alterFrom, alterTo:string):Table =
return Table(name:alterFrom, alterTo:alterTo, typ:Rename)

proc drop*(name:string):Table =
return Table(name:name, typ:Drop)

proc delete*():Column =
return Column(alterTyp: Delete)

proc column*(self:Column, name:string):Column =
self.name = name
return self
35 changes: 26 additions & 9 deletions src/allographer/schema_builder/alters/mysql_alter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@ import ../../utils
import ../../connection

proc add(column:Column, table:string) =
let columnString = generateColumnString(column)
let query = &"ALTER TABLE {table} ADD {columnString}"
logger(query)
# let columnString = generateColumnString(column)
# let query = &"ALTER TABLE {table} ADD {columnString}"
let querySeq = generateAlterAddQueries(column, table)
block:
let db = db()
defer: db.close()
try:
db.exec(sql query)
for query in querySeq:
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)
echoWarningMsg(&"Safety skip alter table '{table}'")

proc getColumns(table:string, previousName:string):string =
proc getColumns(table:string, name:string):string =
let db = db()
defer: db.close()
var query = &"SHOW COLUMNS FROM {table}"
var columns:string
for i, row in db.getAllRows(sql query):
if row[0] != previousName:
if row[0] != name:
if i > 0: columns.add(", ")
columns.add(row[1])
return columns
Expand All @@ -42,17 +44,29 @@ proc change(column:Column, table:string) =
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

proc delete(column:Column, table:string) =
proc deleteColumn(table:string, column:Column) =
let db = db()
defer: db.close()
try:
let query = &"ALTER TABLE {table} DROP `{column.previousName}`"
let query = generateAlterDeleteQuery(table, column)
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

proc deleteForeign(table:string, column:Column) =
let querySeq = generateAlterDeleteForeignQueries(table, column)
let db = db()
defer: db.close()
try:
for query in querySeq:
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

proc rename(tableFrom, tableTo:string) =
let db = db()
defer: db.close()
Expand Down Expand Up @@ -84,7 +98,10 @@ proc exec*(table:Table) =
of Change:
change(column, table.name)
of Delete:
delete(column, table.name)
if column.typ == rdbForeign:
deleteForeign(table.name, column)
else:
deleteColumn(table.name, column)
elif table.typ == Rename:
rename(table.name, table.alterTo)
elif table.typ == Drop:
Expand Down
36 changes: 31 additions & 5 deletions src/allographer/schema_builder/alters/postgres_alter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import ../../utils
import ../../connection

proc add(column:Column, table:string) =
let columnString = generateColumnString(column)
let query = &"ALTER TABLE {table} ADD {columnString}"
logger(query)
let querySeq = migrateAlter(table, column)
block:
let db = db()
defer: db.close()
try:
db.exec(sql query)
for query in querySeq:
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)
Expand Down Expand Up @@ -79,6 +79,29 @@ proc delete(column:Column, table:string) =
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

proc deleteColumn(table:string, column:Column) =
let db = db()
defer: db.close()
try:
let query = generateAlterDeleteQuery(table, column)
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

proc deleteForeign(table:string, column:Column) =
let querySeq = generateAlterDeleteForeignQueries(table, column)
let db = db()
defer: db.close()
try:
for query in querySeq:
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

proc rename(tableFrom, tableTo:string) =
let db = db()
defer: db.close()
Expand Down Expand Up @@ -110,7 +133,10 @@ proc exec*(table:Table) =
of Change:
change(column, table.name)
of Delete:
delete(column, table.name)
if column.typ == rdbForeign:
deleteForeign(table.name, column)
else:
deleteColumn(table.name, column)
elif table.typ == Rename:
rename(table.name, table.alterTo)
elif table.typ == Drop:
Expand Down
25 changes: 17 additions & 8 deletions src/allographer/schema_builder/alters/sqlite_alter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import ../../utils
import ../../connection

proc add(column:Column, table:string) =
let columnString = generateColumnString(column)
let query = &"ALTER TABLE \"{table}\" ADD COLUMN {columnString}"
let query = migrateAlter(column, table)
logger(query)
block:
let db = db()
Expand Down Expand Up @@ -69,7 +68,7 @@ proc getColumns(table:string, previousName:string):string =
columns.add(row[1])
return columns

proc delete(column:Column, table:string) =
proc deleteColumn(column:Column, table:string) =
## rename existing table as tmp
##
## create new table with existing table name
Expand All @@ -79,23 +78,32 @@ proc delete(column:Column, table:string) =
## delete tmp table
let db = db()
defer: db.close()
try:
# delete tmp table
let query = &"DROP TABLE alter_table_tmp"
logger(query)
db.exec(sql query)
except:
let err = getCurrentExceptionMsg()
echoErrorMsg(err)

try:
# rename existing table as tmp
var query = &"ALTER TABLE {table} RENAME TO alter_table_tmp"
var query = &"ALTER TABLE \"{table}\" RENAME TO 'alter_table_tmp'"
logger(query)
db.exec(sql query)
# create new table with existing table name
let tableDifinitionSql = &"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'alter_table_tmp';"
var schema = db.getValue(sql tableDifinitionSql)
schema = replace(schema, re"\)$", ",)")
let columnRegex = &"'{column.previousName}'.*?,"
let columnRegex = &"'{column.name}'.*?,"
query = replace(schema, re(columnRegex))
query = replace(query, re",\)", ")")
query = replace(query, re"alter_table_tmp", table)
query = replace(query, re",\s*\)", ")")
logger(query)
db.exec(sql query)
# copy data from tmp table to new table
var columns = getColumns(table, column.previousName)
var columns = getColumns(table, column.name)
query = &"INSERT INTO {table}({columns}) SELECT {columns} FROM alter_table_tmp"
logger(query)
db.exec(sql query)
Expand Down Expand Up @@ -138,7 +146,8 @@ proc exec*(table:Table) =
of Change:
change(column, table.name)
of Delete:
delete(column, table.name)
deleteColumn(column, table.name)

elif table.typ == Rename:
rename(table.name, table.alterTo)
elif table.typ == Drop:
Expand Down
Loading

0 comments on commit 39999ae

Please sign in to comment.