I'm experimenting with reflections on Nim, mostly to get a better grasp of the language, seeing if I can make a prepared SQL statement given any object with any number of fields. It works, but there are a few things I still didn't manage. Here's the code: import strutils proc createTable[Obj](): string = var tostr: Obj #The SQL should be compatible with PostgreSQL and MySQL/MariaDB var preparedSql = "CREATE OR REPLACE TABLE " preparedSql.add($Obj) preparedSql.add(" (") var vartype : string for name, field in fieldPairs(tostr): preparedSql.add(name) preparedSql.add(" ") if ($field.type=="string"): vartype = "varchar(3000)" else: vartype = $(field.type) preparedSql.add(vartype) preparedSql.add(", ") preparedSql.removeSuffix(", ") #This could be an if check in the for loop above, but this works fine right now. preparedSql.add(");") result = preparedSql #Might as well use result instead of preparedSql in the code above type Sample = object pid : int forkey : int name : string description : string var sam = Sample(pid: 1, forkey: 2, name: "Sample", description: "Plenty of words") echo createTable[sam]() #The result will print: CREATE OR REPLACE TABLE Sample (pid int, forkey int, name varchar(3000), description varchar(3000)); Run
I do think the code is much longer than needed, but I'm not entirely sure what could be trimmed/joined. Now, there are some questions I'd like to make: 1. Why does fieldPairs() only work when called for an iterator? Is there a way to treat its result as a variable or something that can be printed/echo'ed? 2. Why does the generic "accept any type of object" have to be declared in the brackets instead of parenthesis of a proc? I tried `proc createTable (obj: T)` and `(obj: object)`, none worked. 3. I am currently looking into custom annotations, which are done with pragmas defined as templates. Will the reflection recognize them? How do I check for their existence to properly treat each object field? 4. Other than annotations/pragmas, is it possible to give extra details to object's fields, such as defining a primary key, foreign keys, if it is nullable, etc? 5. What would be a decent alternative to the several `preparedSql.add()` that I call one after another?