nim-sqlcipher/sqlcipher.nim

170 lines
6.2 KiB
Nim

include sqlcipher/tiny_sqlite
#
# Custom.DbConn
#
proc all*[T](db: DbConn, _: typedesc[T], sql: string,
params: varargs[DbValue, toDbValue]): seq[T] =
## Executes ``statement`` and returns all result rows.
for row in db.iterate(sql, params):
var r = T()
row.unpack(r)
result.add r
proc one*[T](db: DbConn, _: typedesc[T], sql: string,
params: varargs[DbValue, toDbValue]): Option[T] =
## Executes `sql`, which must be a single SQL statement, and returns the first result row.
## Returns `none(seq[DbValue])` if the result was empty.
for row in db.iterate(sql, params):
var r = T()
row.unpack(r)
return some(r)
proc value*[T](db: DbConn, _: typedesc[T], sql: string,
params: varargs[DbValue, toDbValue]): Option[T] =
## Executes `sql`, which must be a single SQL statement, and returns the first column of the first result row.
## Returns `none(DbValue)` if the result was empty.
for row in db.iterate(sql, params):
return some(row.values[0].fromDbValue(T))
#
# Custom.SqlStatement
#
proc all*[T](_: typedesc[T], statement: SqlStatement, params: varargs[DbValue, toDbValue]): seq[T] =
## Executes ``statement`` and returns all result rows.
assertCanUseStatement statement
for row in statement.iterate(params):
var r = T()
row.unpack(r)
result.add r
proc one*[T](_: typedesc[T], statement: SqlStatement,
params: varargs[DbValue, toDbValue]): Option[T] =
## Executes `statement` and returns the first row found.
## Returns `none(seq[DbValue])` if no result was found.
assertCanUseStatement statement
for row in statement.iterate(params):
var r = T()
row.unpack(r)
return some(r)
proc value*[T](_: typedesc[T], statement: SqlStatement,
params: varargs[DbValue, toDbValue]): Option[T] =
## Executes `statement` and returns the first column of the first row found.
## Returns `none(DbValue)` if no result was found.
assertCanUseStatement statement
for row in statement.iterate(params):
return some(row.values[0].fromDbValue(T))
#
# Custom.ResultRow
#
proc `[]`*[T](row: ResultRow, columnName: string, _: typedesc[T]): T =
row[columnName].fromDbValue(T)
proc hasRows*(rows: seq[ResultRow]): bool = rows.len > 0
#
# Custom.ORM
# This section was not originally part of tiny_sqlite
#
# TODO: add primaryKey param to pragma, however there is an issue with multiple
# params in getCustomPragmaFixed: https://github.com/status-im/nim-stew/issues/62,
# and we need to wait on a fix or a workaround.
template dbColumnName*(name: string) {.pragma.}
## Specifies the database column name for the object property
template dbTableName*(name: string) {.pragma.}
## Specifies the database table name for the object
template dbForeignKey*(t: typedesc) {.pragma.}
## Specifies the table's foreign key type
template columnName*(obj: auto | typedesc): string =
when macros.hasCustomPragma(obj, dbColumnName):
macros.getCustomPragmaVal(obj, dbColumnName)
else:
typetraits.name(obj.type).toLower
template tableName*(obj: auto | typedesc): string =
when macros.hasCustomPragma(obj, dbTableName):
macros.getCustomPragmaVal(obj, dbTableName)
else:
typetraits.name(obj.type).toLower
template enumInstanceDbColumns*(obj: auto,
fieldNameVar, fieldVar,
body: untyped) =
## Expands a block over all serialized fields of an object.
##
## Inside the block body, the passed `fieldNameVar` identifier
## will refer to the name of each field as a string. `fieldVar`
## will refer to the field value.
##
## The order of visited fields matches the order of the fields in
## the object definition.
type ObjType {.used.} = type(obj)
for fieldName, fieldVar in fieldPairs(obj):
when hasCustomPragmaFixed(ObjType, fieldName, dbColumnName):
const fieldNameVar = getCustomPragmaFixed(ObjType, fieldName, dbColumnName)
else:
const fieldNameVar = fieldName
body
proc unpack*(row: ResultRow, obj: var object) =
obj.enumInstanceDbColumns(dbColName, property):
type ColType = type property
property = row[dbColName, ColType]
#
# Custom.sqlcipher
# The following are APIs from sqlcipher
#
proc key*(db: DbConn, password: string) =
## * Specify the key for an encrypted database. This routine should be
## * called right after sqlite3_open().
## *
## * The code to implement this API is not available in the public release
## * of SQLite.
let rc = sqlite.key(db.handle, password.cstring, int32(password.len))
db.checkRc(rc)
proc key_v2*(db: DbConn, zDbName, password: string) =
## * Specify the key for an encrypted database. This routine should be
## * called right after sqlite3_open().
## *
## * The code to implement this API is not available in the public release
## * of SQLite.
let rc = sqlite.key_v2(db.handle, zDbName.cstring, password.cstring, int32(password.len))
db.checkRc(rc)
proc rekey*(db: DbConn, password: string) =
let rc = sqlite.rekey(db.handle, password.cstring, int32(password.len))
db.checkRc(rc)
## * Change the key on an open database. If the current database is not
## * encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
## * database is decrypted.
## *
## * The code to implement this API is not available in the public release
## * of SQLite.
proc rekey_v2*(db: DbConn, zDbName, password: string) =
## * Change the key on an open database. If the current database is not
## * encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
## * database is decrypted.
## *
## * The code to implement this API is not available in the public release
## * of SQLite.
let rc = sqlite.rekey_v2(db.handle, zDbName.cstring, password.cstring, int32(password.len))
db.checkRc(rc)
#
# Custom.Deprecations
#
proc execQuery*[T](db: DbConn, sql: string, params: varargs[DbValue, toDbValue]): seq[T] {.deprecated: "Use all[T] instead".} =
## Executes the query and iterates over the result dataset.
all[T](db, sql, T.type, params)