Prepared queries can be many times faster depending on use case. So, I think
they should have been part of stdlib but I guess its too late for v1.
Here is what I meant by "diving into sqlite3.nim"
import sqlite3, db_sqlite, strutils, strformat
let dbname = ":memory:"
let db = open(dbName, "", "", "")
db.exec(sql"DROP TABLE IF EXISTS test")
let createTableStr = sql"""CREATE TABLE test(
id INTEGER,
data BLOB
)
"""
db.exec(createTableStr)
var data : seq[float64]
data.add(0)
data.add(1)
data.add(2)
data.add(3.14)
echo "Data to write: ", data
var bufSize = int(sizeof(float64)/sizeof(byte))*(data.len)
# Insert prepared
let insert_query = "INSERT INTO test (id, data) VALUES (?, ?)"
var stmt : PStmt = nil
var tail : ptr cstring
var err =
prepare_v2(cast[PSqlite3](db),insert_query.cstring,insert_query.len.cint,stmt,tail)
if err != SQLITE_OK:
raise newException(CatchableError,"Query failed")
# repeat
if stmt.bind_int(1,1) != SQLITE_OK:
raise newException(CatchableError,"Bind error")
if stmt.bind_blob(2,unsafeAddr(data[0]),bufSize.int32,SQLITE_STATIC) !=
SQLITE_OK:
raise newException(CatchableError,"Bind error")
err = stmt.step()
if err != SQLITE_DONE:
raise newException(CatchableError,"Query couldnt be executed")
discard stmt.reset()
# until all inserted
discard stmt.finalize()
# Select prepared
var data_read : seq[float64]
let select_query = "SELECT id,data FROM test"
err =
prepare_v2(cast[PSqlite3](db),select_query.cstring,select_query.len.cint,stmt,tail)
if err != SQLITE_OK:
raise newException(CatchableError,"Query failed")
while true:
err = stmt.step()
if err == SQLITE_DONE:
discard stmt.finalize()
break
else:
if err == SQLITE_ROW:
var id = stmt.column_int64(0)
bufsize = stmt.column_bytes(1)
if bufsize mod sizeof(float64) != 0:
raise newException(CatchableError,"Incorrect data")
var cnt = bufsize div sizeof(float64)
data_read.setLen(cnt)
if cnt>0:
var buf = stmt.column_blob(1)
copyMem(unsafeAddr(data_read[0]),buf,bufsize)
echo fmt"Row-> id:{id}, data: {data_read}"
else:
raise newException(CatchableError,"Query step error")
db_sqlite.close(db)
Run