Skip to content

Commit

Permalink
Add the ability to set custom schema name for Postres.
Browse files Browse the repository at this point in the history
  • Loading branch information
moigagoo committed Jan 30, 2024
1 parent 0994e31 commit 85313e9
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 4 deletions.
26 changes: 23 additions & 3 deletions src/norm/model.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,33 @@ func model*[T](val: T): Option[Model] =

none Model

func schema*(T: typedesc[Model]): Option[string] =
##[ Get schema name for `Model <#Model>`_, which is the value of `schemaName <pragmas.html#schemaName.t,string>`_ pragma.
`none(string)` means default schema.
Ignored in SQLite.
]##

when T.hasCustomPragma(schemaName):
some '"' & T.getCustomPragmaVal(schemaName) & '"'
else:
none(string)

func table*(T: typedesc[Model]): string =
## Get table name for `Model <#Model>`_, which is the type name in single quotes.
##[ Get table name for `Model <#Model>`_,
which is the value of `tableName <pragmas.html#tableName.t,string>`_ pragma or the type name in double quotes.
If `schemaName`_ is set, it's prepended to the table name.
]##

if T.schema.isSome:
result &= get(T.schema) & '.'

when T.hasCustomPragma(tableName):
'"' & T.getCustomPragmaVal(tableName) & '"'
result &= '"' & T.getCustomPragmaVal(tableName) & '"'
else:
'"' & $T & '"'
result &= '"' & $T & '"'

func col*(T: typedesc[Model], fld: string): string =
## Get column name for a `Model`_ field, which is just the field name.
Expand Down
14 changes: 13 additions & 1 deletion src/norm/postgres.nim
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,18 @@ proc dropDb* =

# Table manipulation

proc createSchema*[T: Model](dbConn; obj: T) =
## Create schema for `Model <model.html#Model>`_.

if T.schema.isSome:
let qry = "CREATE SCHEMA IF NOT EXISTS $#" % get(T.schema)

log(qry)

dbConn.exec(sql qry)

proc createTables*[T: Model](dbConn; obj: T) =
## Create tables for `Model <model.html#Model>`_ and its `Model`_ fields.
## Create tables for `Model`_ and its `Model`_ fields.

for fld, val in obj[].fieldPairs:
if val.model.isSome:
Expand Down Expand Up @@ -138,6 +148,8 @@ proc createTables*[T: Model](dbConn; obj: T) =

colGroups.add colShmParts.join(" ")

dbConn.createSchema(obj)

let
uniqueGroups = if len(uniqueGroupCols) > 0: @["UNIQUE($#)" % uniqueGroupCols.join(", ")] else: @[]
qry = "CREATE TABLE IF NOT EXISTS $#($#)" % [T.table, (colGroups & fkGroups & uniqueGroups).join(", ")]
Expand Down
3 changes: 3 additions & 0 deletions src/norm/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ template fk*(val: typed) {.pragma.}
template onDelete*(val: string) {.pragma.}
## Add ``ON DELETE {val}`` constraint to the column.

template schemaName*(val: string) {.pragma.}
## Custom schema name for a model.

template tableName*(val: string) {.pragma.}
## Custom table name for a model.

Expand Down
5 changes: 5 additions & 0 deletions src/norm/sqlite.nim
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ proc dropDb* =

# Table manipulation

proc createSchema*[T: Model](dbConn; obj: T) =
## Dummy proc for API consistency.

discard

proc createTables*[T: Model](dbConn; obj: T) =
## Create tables for `Model <model.html#Model>`_ and its `Model`_ fields.

Expand Down
1 change: 1 addition & 0 deletions tests/common/tmodel.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ suite "Getting table and columns from Model":
test "Table":
check Person.table == """"Person""""
check Table.table == """"FurnitureTable""""
check FurnitureTable.table == """"Furniture"."FurnitureTable""""

test "Columns":
let
Expand Down
6 changes: 6 additions & 0 deletions tests/models.nim
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ type
Table* {.tableName: "FurnitureTable".} = ref object of Model
legCount*: Positive

FurnitureTable* {.schemaName: "Furniture", tableName: "FurnitureTable".} = ref object of Model
legCount*: Positive

SelfRef* = ref object of Model
parent* {.fk: SelfRef.}: Option[int64]

Expand Down Expand Up @@ -237,6 +240,9 @@ func `===`*(a, b: String): bool =
func newTable*(legCount: Positive = 4): Table =
Table(legCount: legCount)

func newFurnitureTable*(legCount: Positive = 4): FurnitureTable =
FurnitureTable(legCount: legCount)

func newPetSpecies*: PetSpecies = PetSpecies(species: "")

func newPersonName*: PersonName = PersonName(name: "")
Expand Down
17 changes: 17 additions & 0 deletions tests/postgres/ttables.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@ suite "Table creation":
@[?"legcount", ?dftDbInt]
]

test "Create table with custom schema":
let furnitureTable = newFurnitureTable()

dbConn.createTables(furnitureTable)

let
qry = sql """SELECT column_name::text, data_type::text
FROM information_schema.columns
WHERE table_schema = $1 AND table_name = $2
ORDER BY column_name"""
dftDbInt = if high(int) == high(int64): "bigint" else: "integer"

check dbConn.getAllRows(qry, "Furniture", "FurnitureTable") == @[
@[?"id", ?"bigint"],
@[?"legcount", ?dftDbInt]
]

test "Create tables":
let
toy = newToy(123.45)
Expand Down

0 comments on commit 85313e9

Please sign in to comment.