Skip to content

Commit e7a9075

Browse files
authored
update parser to handle pragmas (#67)
* update parser to handle pragmas * qualify error and hint * Delete ormin/parsesql_tmp.nim
1 parent 8718cbd commit e7a9075

5 files changed

Lines changed: 1896 additions & 49 deletions

File tree

config.nims

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
switch("nimcache", ".nimcache")
12

23
task buildimporter, "Build ormin_importer":
34
exec "nim c -o:./tools/ormin_importer tools/ormin_importer"
@@ -7,9 +8,9 @@ task test, "Run all test suite":
78
rmFile("tests/forum_model_sqlite.nim")
89
rmFile("tests/model_sqlite.nim")
910

10-
exec "nim c --nimcache:.nimcache -f -r tests/tfeature"
11-
exec "nim c --nimcache:.nimcache -f -r tests/tcommon"
12-
exec "nim c --nimcache:.nimcache -f -r tests/tsqlite"
11+
exec "nim c -f -r tests/tfeature"
12+
exec "nim c -f -r tests/tcommon"
13+
exec "nim c -f -r tests/tsqlite"
1314

1415
task test_postgres, "Run PostgreSQL test suite":
1516
# Skip PostgreSQL tests as they require a running PostgreSQL server

ormin/queries.nim

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
when not declared(tableNames):
3-
{.error: "The query DSL requires a tableNames const.".}
3+
{.macros.error: "The query DSL requires a tableNames const.".}
44

55
when not declared(attributes):
6-
{.error: "The query DSL requires a attributes const.".}
6+
{.macros.error: "The query DSL requires a attributes const.".}
77

88
import macros, strutils
99
import db_connector/db_common
@@ -140,15 +140,15 @@ proc `$`(a: DbType): string = $a.kind
140140

141141
proc checkBool(a: DbType; n: NimNode) =
142142
if a.kind != dbBool:
143-
error "expected type 'bool', but got: " & $a, n
143+
macros.error "expected type 'bool', but got: " & $a, n
144144

145145
proc checkInt(a: DbType; n: NimNode) =
146146
if a.kind != dbInt:
147-
error "expected type 'int', but got: " & $a, n
147+
macros.error "expected type 'int', but got: " & $a, n
148148

149149
proc checkCompatible(a, b: DbType; n: NimNode) =
150150
if a.kind != b.kind:
151-
error "incompatible types: " & $a & " and " & $b, n
151+
macros.error "incompatible types: " & $a & " and " & $b, n
152152

153153
proc checkCompatibleSet(a, b: DbType; n: NimNode) =
154154
discard "too implement; might require a richer type system"
@@ -184,7 +184,7 @@ proc lookupColumnInEnv(n: NimNode; q: var string; params: var Params;
184184
var alias: string
185185
result = lookup("", name, qb.env, alias)
186186
if result.kind == dbUnknown:
187-
error "unknown column name: " & name, n
187+
macros.error "unknown column name: " & name, n
188188
elif qb.kind in {qkSelect, qkJoin}:
189189
doAssert alias.len >= 0
190190
q.add alias
@@ -214,7 +214,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
214214
result = cond(n[0], q, params, expected, qb)
215215
q.add ")"
216216
else:
217-
error "tuple construction not allowed here", n
217+
macros.error "tuple construction not allowed here", n
218218
of nnkCurly:
219219
q.add "("
220220
let a = cond(n[0], q, params, expected, qb)
@@ -227,7 +227,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
227227
of nnkStrLit, nnkRStrLit, nnkTripleStrLit:
228228
result = expected
229229
if result.kind == dbUnknown:
230-
# error "cannot infer the type of the literal", n
230+
# macros.error "cannot infer the type of the literal", n
231231
result.kind = dbVarchar
232232
if result.kind == dbBlob:
233233
# For SQL string literals, single quotes must be doubled.
@@ -323,7 +323,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
323323
q.add placeHolder(qb)
324324
result = expected
325325
if result.kind == dbUnknown:
326-
error "cannot infer the type of the placeholder", n
326+
macros.error "cannot infer the type of the placeholder", n
327327
else:
328328
params.add((ex: n[1], typ: toNimType(result), isJson: op == "%"))
329329
of "not":
@@ -334,7 +334,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
334334
of "!!":
335335
result = expected
336336
if result.kind == dbUnknown:
337-
error "cannot infer the type of the literal", n
337+
macros.error "cannot infer the type of the literal", n
338338
let arg = n[1]
339339
if arg.kind in {nnkStrLit..nnkTripleStrLit}: q.add arg.strVal
340340
else: q.add repr(n[1])
@@ -364,8 +364,8 @@ proc cond(n: NimNode; q: var string; params: var Params;
364364
q.add ")"
365365
return
366366
else:
367-
error "function " & op & " takes " & $f.arity & " arguments", n
368-
error "unknown function " & op
367+
macros.error "function " & op & " takes " & $f.arity & " arguments", n
368+
macros.error "unknown function " & op
369369
of nnkIfStmt, nnkIfExpr:
370370
q.add "\Lcase "
371371
result = DbType(kind: dbUnknown)
@@ -377,7 +377,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
377377
q.add " then"
378378
of nnkElse, nnkElseExpr:
379379
q.add "\L else"
380-
else: error "illformed if expression", n
380+
else: macros.error "illformed if expression", n
381381
q.add "\L "
382382
let t = cond(x[^1], q, params, result, qb)
383383
if result.kind == dbUnknown: result = t
@@ -390,7 +390,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
390390
let tab = $call[0]
391391
let tabIndex = tableNames.lookup(tab)
392392
if tabIndex < 0:
393-
error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n[1][0]
393+
macros.error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n[1][0]
394394
else:
395395
let alias = qb.getAlias(tabIndex)
396396
var subenv = @[(tabIndex, alias)]
@@ -414,7 +414,7 @@ proc cond(n: NimNode; q: var string; params: var Params;
414414
let tab = $call[0]
415415
let tabIndex = tableNames.lookup(tab)
416416
if tabIndex < 0:
417-
error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n[1][0]
417+
macros.error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n[1][0]
418418
else:
419419
let alias = qb.getAlias(tabIndex)
420420
qb.env = @[(tabindex, alias)]
@@ -438,15 +438,15 @@ proc cond(n: NimNode; q: var string; params: var Params;
438438
else:
439439
discard cond(hav, subselect, params, DbType(kind: dbBool), qb)
440440
else:
441-
error "construct not supported in condition: " & treeRepr cmd, cmd
441+
macros.error "construct not supported in condition: " & treeRepr cmd, cmd
442442
elif cmd.len >= 2:
443-
error "construct not supported in condition: " & treeRepr cmd, cmd
443+
macros.error "construct not supported in condition: " & treeRepr cmd, cmd
444444
qb.env = subenv
445445
q.add subselect
446446
else:
447-
error "construct not supported in condition: " & treeRepr n, n
447+
macros.error "construct not supported in condition: " & treeRepr n, n
448448
else:
449-
error "construct not supported in condition: " & treeRepr n, n
449+
macros.error "construct not supported in condition: " & treeRepr n, n
450450

451451
proc generateRoutine(name: NimNode, q: QueryBuilder;
452452
sql: string; k: NimNodeKind): NimNode =
@@ -531,13 +531,13 @@ proc getColumnName(n: NimNode): string =
531531
else:
532532
# this is a little hacky, if the column name starts with
533533
# a space, it means "could not extract the column name"
534-
# but we need to emit this error lazily:
534+
# but we need to emit this macros.error lazily:
535535
result = " " & repr(n)
536536

537537
proc retName(q: QueryBuilder; i: int; n: NimNode): string =
538538
result = q.retNames[i]
539539
if q.retTypeIsJson and result.startsWith(" "):
540-
error "cannot extract column name of:" & result, n
540+
macros.error "cannot extract column name of:" & result, n
541541
result = ""
542542

543543
proc selectAll(q: QueryBuilder; tabIndex: int; arg, lineInfo: NimNode) =
@@ -580,7 +580,7 @@ proc selectAll(q: QueryBuilder; tabIndex: int; arg, lineInfo: NimNode) =
580580
q.head.add " = "
581581
q.head.add placeholder(q)
582582
else:
583-
error "select '_' not supported for this construct", lineInfo
583+
macros.error "select '_' not supported for this construct", lineInfo
584584

585585

586586
proc tableSel(n: NimNode; q: QueryBuilder) =
@@ -589,7 +589,7 @@ proc tableSel(n: NimNode; q: QueryBuilder) =
589589
let tab = $call[0]
590590
let tabIndex = tableNames.lookup(tab)
591591
if tabIndex < 0:
592-
error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n
592+
macros.error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n
593593
return
594594
let alias = q.getAlias(tabIndex)
595595
if q.kind == qkSelect:
@@ -610,7 +610,7 @@ proc tableSel(n: NimNode; q: QueryBuilder) =
610610
else:
611611
let coltype = lookup("", colname, q.env)
612612
if coltype.kind == dbUnknown:
613-
error "unkown column name: " & colname, col
613+
macros.error "unkown column name: " & colname, col
614614
else:
615615
if q.coln > 0: q.head.add ", "
616616
escIdent(q.head, colname)
@@ -634,7 +634,7 @@ proc tableSel(n: NimNode; q: QueryBuilder) =
634634
let colname = $col[1]
635635
let coltype = lookup("", colname, q.env)
636636
if coltype.kind == dbUnknown:
637-
error "unkown column name: " & colname, col
637+
macros.error "unkown column name: " & colname, col
638638
else:
639639
if q.coln > 0: q.head.add ", "
640640
escIdent(q.head, colname)
@@ -655,20 +655,20 @@ proc tableSel(n: NimNode; q: QueryBuilder) =
655655
q.retType.add nnkIdentDefs.newTree(newIdentNode(getColumnName(col)), toNimType(t), newEmptyNode())
656656
q.retNames.add getColumnName(col)
657657
else:
658-
error "unknown selector: " & repr(n), n
658+
macros.error "unknown selector: " & repr(n), n
659659
if q.kind notin {qkUpdate, qkSelect, qkJoin}: q.head.add ")"
660660
elif n.kind in {nnkIdent, nnkAccQuoted, nnkSym} and q.kind == qkDelete:
661661
let tab = $n
662662
let tabIndex = tableNames.lookup(tab)
663663
if tabIndex < 0:
664-
error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n
664+
macros.error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n
665665
return
666666
escIdent(q.head, tab)
667667
q.env.add((tabindex, q.getAlias(tabIndex)))
668668
elif n.kind == nnkRStrLit:
669669
q.head.add n.strVal
670670
else:
671-
error "unknown selector: " & repr(n), n
671+
macros.error "unknown selector: " & repr(n), n
672672

673673

674674
proc queryh(n: NimNode; q: QueryBuilder) =
@@ -715,7 +715,7 @@ proc queryh(n: NimNode; q: QueryBuilder) =
715715
let tab = $cmd[0][0]
716716
let tabIndex = tableNames.lookup(tab)
717717
if tabIndex < 0:
718-
error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n
718+
macros.error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n
719719
else:
720720
escIdent(q.join, tab)
721721
let alias = q.getAlias(tabIndex)
@@ -737,20 +737,20 @@ proc queryh(n: NimNode; q: QueryBuilder) =
737737
let tab = $cmd[0]
738738
let tabIndex = tableNames.lookup(tab)
739739
if tabIndex < 0:
740-
error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n[1][0]
740+
macros.error "unknown table name: " & tab & " from: " & fmtTableList(tableNames), n[1][0]
741741
else:
742742
let alias = q.getAlias(tabIndex)
743743
escIdent(q.join, tab)
744744
q.join.add " as " & alias
745745
if not autoJoin(q.join, q.env[^1], tabIndex, alias):
746-
error "cannot compute auto join from: " & tableNames[q.env[^1][0]] & " to: " & tab, n
746+
macros.error "cannot compute auto join from: " & tableNames[q.env[^1][0]] & " to: " & tab, n
747747
var oldEnv = q.env
748748
q.env = @[(tabIndex, alias)]
749749
q.kind = qkJoin
750750
tableSel(n[1], q)
751751
swap q.env, oldEnv
752752
else:
753-
error "unknown query component " & repr(n), n
753+
macros.error "unknown query component " & repr(n), n
754754
of "groupby":
755755
for i in 1..<n.len:
756756
discard cond(n[i], q.groupby, q.params, DbType(kind: dbUnknown), q)
@@ -774,7 +774,7 @@ proc queryh(n: NimNode; q: QueryBuilder) =
774774
checkInt(t, n[1])
775775
of "returning":
776776
if q.kind != qkInsert:
777-
error "'returning' only possible within 'insert'"
777+
macros.error "'returning' only possible within 'insert'"
778778
q.kind = qkInsertReturning
779779
expectLen n, 2
780780
when dbBackend == DbBackend.sqlite:
@@ -809,9 +809,9 @@ proc queryh(n: NimNode; q: QueryBuilder) =
809809
elif eqIdent(n[1], "nim") or eqIdent(n[1], "tuple"):
810810
q.retTypeIsJson = false
811811
else:
812-
error "produce expects 'json' or 'nim', but got: " & repr(n[1]), n
812+
macros.error "produce expects 'json' or 'nim', but got: " & repr(n[1]), n
813813
else:
814-
error "unknown query component " & repr(n), n
814+
macros.error "unknown query component " & repr(n), n
815815

816816
proc queryAsString(q: QueryBuilder, n: NimNode): string =
817817
result = q.head
@@ -846,7 +846,7 @@ proc queryAsString(q: QueryBuilder, n: NimNode): string =
846846
if q.returning.len > 0:
847847
result.add q.returning
848848
when defined(debugOrminSql):
849-
hint("Ormin SQL:\n" & $result, n)
849+
macros.hint("Ormin SQL:\n" & $result, n)
850850

851851
proc newGlobalVar(name, typ: NimNode, value: NimNode): NimNode =
852852
result = newTree(nnkVarSection,
@@ -867,7 +867,7 @@ proc queryImpl(q: QueryBuilder; body: NimNode; attempt, produceJson: bool): NimN
867867
q.retTypeIsJson = produceJson
868868
for b in body:
869869
if b.kind == nnkCommand: queryh(b, q)
870-
else: error "illformed query", b
870+
else: macros.error "illformed query", b
871871
let sql = queryAsString(q, body)
872872
let prepStmt = genSym(nskVar)
873873
let res = genSym(nskVar)
@@ -998,13 +998,13 @@ macro query*(body: untyped): untyped =
998998
var q = newQueryBuilder()
999999
result = queryImpl(q, body, false, false)
10001000
when defined(debugOrminDsl):
1001-
hint("Ormin Query: " & repr(result), body)
1001+
macros.hint("Ormin Query: " & repr(result), body)
10021002

10031003
macro tryQuery*(body: untyped): untyped =
10041004
var q = newQueryBuilder()
10051005
result = queryImpl(q, body, true, false)
10061006
when defined(debugOrminDsl):
1007-
hint("Ormin Query: " & repr(result), body)
1007+
macros.hint("Ormin Query: " & repr(result), body)
10081008

10091009
proc createRoutine(name, query: NimNode; k: NimNodeKind): NimNode =
10101010
expectKind query, nnkStmtList
@@ -1013,13 +1013,13 @@ proc createRoutine(name, query: NimNode; k: NimNodeKind): NimNode =
10131013
var q = newQueryBuilder()
10141014
for b in query:
10151015
if b.kind == nnkCommand: queryh(b, q)
1016-
else: error "illformed query", b
1016+
else: macros.error "illformed query", b
10171017
if q.kind notin {qkSelect, qkJoin}:
1018-
error "query must be a 'select' or 'join'", query
1018+
macros.error "query must be a 'select' or 'join'", query
10191019
let sql = queryAsString(q, query)
10201020
result = generateRoutine(name, q, sql, k)
10211021
when defined(debugOrminDsl):
1022-
hint("Ormin Query: " & repr(result), query)
1022+
macros.hint("Ormin Query: " & repr(result), query)
10231023

10241024
macro createIter*(name, query: untyped): untyped =
10251025
## Creates an iterator of the given 'name' that iterates
@@ -1097,7 +1097,7 @@ proc transformClient(n: NimNode; b: ProtoBuilder): NimNode =
10971097
expectLen p, 2
10981098
expectKind p[1], nnkIdentDefs
10991099
if p[1].len != 3:
1100-
error "proc must have one or zero parameters", p
1100+
macros.error "proc must have one or zero parameters", p
11011101
n.body = getAst(sendReqImpl(p[1][0], b.msgId))
11021102
b.procs.add n
11031103
return newTree(nnkNone)
@@ -1167,7 +1167,7 @@ proc protoImpl(n: NimNode; b: ProtoBuilder): NimNode =
11671167
if n.len == 3:
11681168
expectKind(n[1], nnkStrLit)
11691169
if b.sectionName != n[1].strVal:
1170-
error "section names of client/server pair do not match", n[1]
1170+
macros.error "section names of client/server pair do not match", n[1]
11711171
var clientPart = transformClient(n[^1], b)
11721172
if clientPart.kind == nnkNone or (clientPart.kind == nnkStmtList and clientPart.len == 0):
11731173
clientPart = newStmtList(newTree(nnkDiscardStmt, newEmptyNode()))
@@ -1220,4 +1220,4 @@ macro protocol*(name: static[string]; body: untyped): untyped =
12201220
b.server.add getAst(serverProc(disp))
12211221
result = b.server
12221222
when defined(debugOrminDsl):
1223-
hint("Ormin Query: " & repr(result), body)
1223+
macros.hint("Ormin Query: " & repr(result), body)

tests/forum_model_sqlite.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
pragma foreign_keys = on;
2+
13
create table if not exists thread(
24
id integer primary key,
35
name varchar(100) not null,

tools/ormin_importer.nim

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
## (c) 2017 Andreas Rumpf
33
## MIT License.
44

5-
import parsesql, streams, strutils, os, parseopt, tables
5+
import streams, strutils, os, parseopt, tables
66
import db_connector/db_common
77

8+
import ./parsesql_tmp
9+
810
#import compiler / [ast, renderer]
911

1012
const

0 commit comments

Comments
 (0)