I was playing around with making a SQLite extension in Nim the other day. 
Here's a simple example of how to do this. This example defines a _hello_ 
function in SQL that takes one parameter and returns "Hello <value>". With a 
bit more effort you can do things like create virtual tables, etc.
    
    
    ## Nim version of Hello World SQLite plugin
    ##
    ## compile as DLL/.so
    ##   nim c --app:lib helloworld.nim
    ##
    ## Test with something like the following:
    ##
    ## sqlite3
    ## sqlite> .load libhelloworld
    ## sqlite> CREATE TABLE testing(id INTEGER PRIMARY KEY, name STRING);
    ## sqlite> INSERT INTO testing VALUES (1, 'Alice'), (2, 'Bob');
    ## sqlite> SELECT id, hello(name) FROM testing;
    ## 1|Hello Alice
    ## 2|Hello Bob
    ## sqlite>
    
    import sqlite3
    
    {.emit:"""
    #include <sqlite3ext.h>
    SQLITE_EXTENSION_INIT1
    """
    .}
    
    # This is the logic for our 'hello()' function that will be available in 
SQLite
    proc helloFunc(context : Pcontext, argcount: int32, argv: PValueArg) 
{.cdecl.} =
      assert argcount == 1
      var
        output = "Hello " & $value_text(argv[0])
        length = output.len + 1
      
      result_text(context, output, length.int32, SQLITE_TRANSIENT)
    
    proc sqlite3_helloworld_init(sqlite3 : PSqlite3, pzErrMsg: ptr string, 
pApi: ptr int32) : cint {.exportc, dynlib.} =
      result = SQLITE_OK
      
      {.emit:"""
      SQLITE_EXTENSION_INIT2(pApi);
      """
      .}
      
      var
        # Can be pointer to any extra data you want available in your function
        # but it has to be scoped to survive the length of your
        # database connection and not just this proc
        userData = cast[pointer](0)
      
      let
        funcName = "hello"    # name that will be available in SQL.
        numOfArgs = 1.int32
        encoding = SQLITE_UTF8.int32
        # These must be null pointers for just a basic SQL function
        stepFunc = cast[Create_function_step_func](0)
        finalFunc = cast[Create_function_final_func](0)
      discard create_function(sqlite3, funcName, numOfArgs, encoding,
                              userData, helloFunc, stepFunc, finalFunc)
    
    
    Run

Reply via email to