1313 name: string
1414 tabIndex: int
1515 typ: DbTypekind
16+ typeName: string
17+ validValues: seq[string]
1618 key: int # 0 nothing special,
1719 # +1 -- primary key
1820 # -N -- references attribute N
2830 DbColumns * = seq [DbColumn ]
2931
3032 KnownTables * = OrderedTable [string , DbColumns ]
33+ KnownEnums = Table [string , seq [string ]]
3134 ImportTarget * = enum
3235 postgre, sqlite, mysql
3336
@@ -40,13 +43,30 @@ proc hasRefs(colDesc: SqlNode): (string, string) =
4043 for i in 2 ..< colDesc.len:
4144 let c = colDesc[i]
4245 if c.kind == nkReferences:
43- if c[0 ].kind == nkCall:
44- return (c[0 ][0 ].strVal, c[0 ][1 ].strVal)
45- elif c[0 ].kind == nkIdent:
46- return ($ c[0 ], " id" )
46+ if c[0 ].kind == nkColumnReference:
47+ return (sqlIdentName (c[0 ][0 ]), sqlIdentBaseName (c[0 ][1 ]))
48+ elif c[0 ].kind == nkCall:
49+ return (sqlIdentName (c[0 ][0 ]), sqlIdentBaseName (c[0 ][1 ]))
50+ elif c[0 ].kind in {nkIdent, nkQuotedIdent, nkDot}:
51+ return (sqlIdentName (c[0 ]), " id" )
4752 (" " , " " )
4853
49- proc getType (n: SqlNode ): DbType =
54+ proc collectEnumTypes (schemaSql: string ): KnownEnums =
55+ result = initTable [string , seq [string ]]()
56+ let definitions = parseEnumTypeDefs (schemaSql)
57+ for i in 0 ..< definitions.len:
58+ let definition = definitions[i]
59+ let typeName = sqlIdentName (definition[0 ]).toLowerAscii ()
60+ var values: seq [string ] = @ []
61+ for value in definition[1 ].sons:
62+ values.add (value.strVal)
63+ result [typeName] = values
64+
65+ let dotPos = typeName.rfind ('.' )
66+ if dotPos >= 0 and dotPos + 1 < typeName.len:
67+ result [typeName[dotPos + 1 .. ^ 1 ]] = values
68+
69+ proc getType (n: SqlNode ; enums: KnownEnums ): DbType =
5070 var it = n
5171 if it.kind == nkCall:
5272 it = it[0 ]
@@ -56,21 +76,28 @@ proc getType(n: SqlNode): DbType =
5676 for i in 0 ..< it.len:
5777 assert it[i].kind == nkStringLit
5878 result .validValues.add it[i].strVal
59- elif it.kind in {nkIdent, nkStringLit}:
60- result .kind = dbTypFromName (it.strVal)
61- result .name = it.strVal
79+ elif it.kind in {nkIdent, nkQuotedIdent, nkStringLit, nkDot}:
80+ let typeName = sqlIdentName (it)
81+ let normalized = typeName.toLowerAscii
82+ if enums.hasKey (normalized):
83+ result .kind = dbEnum
84+ result .validValues = enums[normalized]
85+ else :
86+ let baseName = sqlIdentBaseName (it)
87+ result .kind = dbTypFromName (baseName)
88+ result .name = typeName
6289
63- proc collectTables * (n: SqlNode ; t: var KnownTables ) =
90+ proc collectTables * (n: SqlNode ; t: var KnownTables ; enums: KnownEnums ) =
6491 if n.isNil:
6592 return
6693 case n.kind
6794 of nkCreateTable, nkCreateTableIfNotExists:
68- let tableName = n[0 ].strVal
95+ let tableName = sqlIdentName ( n[0 ])
6996 var cols: DbColumns = @ []
7097 for i in 1 ..< n.len:
7198 let it = n[i]
7299 if it.kind == nkColumnDef:
73- var typ = getType (it[1 ])
100+ var typ = getType (it[1 ], enums )
74101 if hasAttribute (it, {nkNotNull}):
75102 typ.notNull = true
76103 cols.add DbColumn (
@@ -97,9 +124,9 @@ proc collectTables*(n: SqlNode; t: var KnownTables) =
97124 var refTable = " "
98125 var refCols: seq [string ] = @ []
99126 if r.kind == nkColumnReference or r.kind == nkCall:
100- refTable = r[0 ].strVal
127+ refTable = sqlIdentName ( r[0 ])
101128 for k in 1 ..< r.len:
102- refCols.add (r[k].strVal )
129+ refCols.add (sqlIdentBaseName ( r[k]) )
103130 let pairCount = min (localCols.len, refCols.len)
104131 for k in 0 ..< pairCount:
105132 let localName = localCols[k]
@@ -111,25 +138,54 @@ proc collectTables*(n: SqlNode; t: var KnownTables) =
111138 t[tableName] = cols
112139 else :
113140 for i in 0 ..< n.len:
114- collectTables (n[i], t)
141+ collectTables (n[i], t, enums )
115142
116143proc attrToKey (a: DbColumn ; t: KnownTables ): int =
117144 if a.primaryKey:
118145 return 1
119146 if a.refs[0 ].len > 0 :
147+ var referencedTable = " "
148+ for tableName in keys (t):
149+ if cmpIgnoreCase (tableName, a.refs[0 ]) == 0 :
150+ referencedTable = tableName
151+ break
152+
153+ if referencedTable.len == 0 and '.' notin a.refs[0 ]:
154+ for tableName in keys (t):
155+ let dotPos = tableName.rfind ('.' )
156+ let baseName =
157+ if dotPos >= 0 : tableName[dotPos + 1 .. ^ 1 ]
158+ else : tableName
159+ if cmpIgnoreCase (baseName, a.refs[0 ]) == 0 :
160+ if referencedTable.len > 0 :
161+ return 0
162+ referencedTable = tableName
163+
164+ if referencedTable.len == 0 :
165+ return 0
166+
120167 var i = 0
121168 for k, v in pairs (t):
122169 for b in v:
123- if cmpIgnoreCase (k, a.refs[ 0 ] ) == 0 and cmpIgnoreCase (b.name, a.refs[1 ]) == 0 :
170+ if cmpIgnoreCase (k, referencedTable ) == 0 and cmpIgnoreCase (b.name, a.refs[1 ]) == 0 :
124171 return - i - 1
125172 inc i
126173 0
127174
175+ proc addStringSeq (dest: var string ; values: openArray [string ]) =
176+ dest.add " @["
177+ for i, value in values:
178+ if i > 0 :
179+ dest.add " , "
180+ dest.add escape (value)
181+ dest.add " ]"
182+
128183proc renderModelCode (schemaSql, schemaPath: string ; target: ImportTarget ; includeStatic = false ): string =
129184 discard target
130185 let sql = parseSql (schemaSql, schemaPath)
186+ let enums = collectEnumTypes (schemaSql)
131187 var knownTables = initOrderedTable [string , DbColumns ]()
132- collectTables (sql, knownTables)
188+ collectTables (sql, knownTables, enums )
133189
134190 result .add FileHeader
135191 result .add " const tableNames = ["
@@ -158,6 +214,10 @@ proc renderModelCode(schemaSql, schemaPath: string; target: ImportTarget; includ
158214 result .add $ i
159215 result .add " , typ: "
160216 result .add $ a.typ.kind
217+ result .add " , typeName: "
218+ result .add escape (a.typ.name)
219+ result .add " , validValues: "
220+ result .addStringSeq (a.typ.validValues)
161221 result .add " , key: "
162222 result .add $ attrToKey (a, knownTables)
163223 result .add " )"
0 commit comments