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?


Reply via email to