77import std/ [macros, macrocache, strutils, options,
88 sequtils, tables, os, random, strformat]
99
10+ import pkg/ parsesql
1011import pkg/ db_connector/ postgres {.all .}
1112import pkg/ db_connector/ db_postgres {.all .}
1213import pkg/ db_connector/ db_common {.all .}
1314
14- import pkg/ parsesql
15-
1615import ./ model, ./ collection
1716import ./ private/ types
1817
18+ include ./ runtime_helpers
19+
1920export SqlQuery , mapIt
2021
2122type
@@ -454,6 +455,33 @@ macro whereNotIn*(sql: untyped, col: static string, vals: untyped): untyped =
454455#
455456# SQL Query Validator
456457#
458+ proc countSqlArgs (args: NimNode ): int {.compileTime .} =
459+ case args.kind
460+ of nnkEmpty:
461+ 0
462+ of nnkBracket:
463+ args.len
464+ of nnkHiddenStdConv:
465+ if args.len > 1 and args[1 ].kind == nnkBracket: args[1 ].len else : 1
466+ else :
467+ 1
468+
469+ proc appendSqlArgs (callNode: var NimNode , args: NimNode ) {.compileTime .} =
470+ case args.kind
471+ of nnkEmpty:
472+ discard
473+ of nnkBracket:
474+ for a in args:
475+ callNode.add (a)
476+ of nnkHiddenStdConv:
477+ if args.len > 1 and args[1 ].kind == nnkBracket:
478+ for a in args[1 ]:
479+ callNode.add (a)
480+ else :
481+ callNode.add (args)
482+ else :
483+ callNode.add (args)
484+
457485proc parseSqlQuery (sql: NimNode , getRowProcName: string ,
458486 args: NimNode = newEmptyNode ()): NimNode {.compileTime .} =
459487 # Compile-time procedure to validate the SQL query and
@@ -476,46 +504,82 @@ proc parseSqlQuery(sql: NimNode, getRowProcName: string,
476504
477505 # generate code to assign columns to model instance fields
478506 var idx = 0
479- var assigns: seq [ string ]
507+ var assigns = newStmtList ()
480508 for cn in colNames:
481509 if cn != " *" :
482- assigns.add (" inst." & cn & " = row[" & $ idx & " ]" )
510+ # assigns.add("inst." & cn & " = row[" & $idx & "]")
511+ assigns.add (
512+ nnkAsgn.newTree (
513+ nnkDotExpr.newTree (ident (" inst" ), ident (cn)),
514+ nnkBracketExpr.newTree (ident (" row" ), newLit (idx))
515+ )
516+ )
483517 else :
484518 # assign all columns to fields with matching names
485519 let modelFields = getTypeImpl (m)[0 ].getTypeImpl[1 ]
486520 for field in getImpl (m)[2 ][0 ][2 ]:
487- assigns.add (" inst." & $ (field [0 ][1 ]) & " = row[" & $ idx & " ]" )
521+ # assigns.add("inst." & $(field[0][1]) & " = row[" & $idx & "]")
522+ assigns.add (
523+ nnkAsgn.newTree (
524+ nnkDotExpr.newTree (ident (" inst" ), field[0 ][1 ]),
525+ nnkBracketExpr.newTree (ident (" row" ), newLit (idx))
526+ )
527+ )
488528 inc idx
489529
490- # Create the runtime code that fetches the row and
491- # applies the generated assignments
492- var runtimeCode: string
530+ # validate the number of SQL arguments and generate
531+ # the appropriate runtime code to execute the query and
532+ # map results to model instances.
533+ let nParams = countSqlArgs (args)
493534 if getRowProcName == " getRow" :
494- let randId = genSym (nskVar, " id" )
495- runtimeCode =
496- staticRead (" private" / " stubs" / " iteratorGetRow.nim" ) % [
497- $ parsedSql,
498- $ (m.getImpl[0 ][1 ]),
499- assigns.join (" \n " ),
500- getRowProcName,
501- (if args.len > 0 : " ," & args.mapIt (it.repr).join (" ," ) else : " " ),
502- (if args.len > 0 : $ args.len else : " 0" ),
503- randId.repr
504- ]
535+ result = newCall (
536+ nnkBracketExpr.newTree (
537+ bindSym " getRowToModel" ,
538+ ident ($ (m.getImpl[0 ][1 ]))
539+ ),
540+ ident " dbcon" ,
541+ newCall (bindSym " SqlQuery" , newLit ($ parsedSql)),
542+ newLit (nParams),
543+ )
544+ appendSqlArgs (result , args)
545+ result .add (
546+ nnkLambda.newTree (
547+ newEmptyNode (),
548+ newEmptyNode (),
549+ newEmptyNode (),
550+ nnkFormalParams.newTree (
551+ newEmptyNode (),
552+ nnkIdentDefs.newTree (
553+ ident (" inst" ),
554+ ident ($ (m.getImpl[0 ][1 ])),
555+ newEmptyNode ()
556+ ),
557+ nnkIdentDefs.newTree (
558+ ident (" row" ),
559+ nnkBracketExpr.newTree (
560+ ident (" seq" ),
561+ ident (" string" )
562+ ),
563+ newEmptyNode ()
564+ )
565+ ),
566+ newEmptyNode (),
567+ newEmptyNode (),
568+ assigns
569+ )
570+ )
505571 else :
506- let randId = genSym (nskVar, " id" )
507- runtimeCode =
508- staticRead (" private" / " stubs" / " iteratorInstantRows.nim" ) % [
509- $ parsedSql,
510- $ (m.getImpl[0 ][1 ]),
511- colNames.mapIt (" \" " & it & " \" " ).join (" ," ),
512- getRowProcName,
513- (if args.len > 0 : " ," & args.mapIt (it.repr).join (" ," ) else : " " ),
514- (if args.len > 0 : $ args.len else : " 0" ),
515- randId.repr
516- ]
517- result = macros.parseStmt (runtimeCode) # parse the generated code into a NimNode
518- result [0 ][0 ] = sql[0 ] # the original block identifier
572+ result = newCall (
573+ nnkBracketExpr.newTree (
574+ bindSym " instantRowsToModels" ,
575+ ident ($ (m.getImpl[0 ][1 ]))
576+ ),
577+ ident " dbcon" ,
578+ newCall (bindSym " SqlQuery" , newLit ($ parsedSql)),
579+ newLit (colNames),
580+ newLit (nParams)
581+ )
582+ appendSqlArgs (result , args)
519583 except SqlParseError as e:
520584 error (" SQL parsing error: " & e.msg, sql[1 ][^ 1 ][1 ])
521585
@@ -752,15 +816,6 @@ macro rawSQL*(models: ptr ModelsTable, sql: static string, values: varargs[untyp
752816 except SqlParseError as e:
753817 raise newException (OzarkModelDefect , " SQL Parsing Error: " & e.msg)
754818
755- type PreparedKey = tuple [conn: pointer , name: string ]
756- var preparedRtCache {.global .}: TableRef [PreparedKey , SqlPrepared ] = newTable [PreparedKey , SqlPrepared ]()
757-
758- proc ensurePrepared * (db: DbConn , name: string , sql: SqlQuery , nParams: int ): SqlPrepared =
759- let key: PreparedKey = (cast [pointer ](db), name)
760- if key notin preparedRtCache:
761- preparedRtCache[key] = prepare (db, name, sql, nParams)
762- result = preparedRtCache[key]
763-
764819macro exec * (sql: untyped ) =
765820 # # Finalize and execute an SQL statement that doesn't
766821 # # return results (e.g. INSERT, UPDATE, DELETE).
0 commit comments