build the documentation of official packages (#20986)

* remove db stuffs

* remove punycode

* remove

* fixes script

* add cloner

* patches

* disable

* patch

* fixes external packages

* disable two packages

* preview documentation build

* try again

* fixes URL

* fixes a bug

* simplify

* fixes documentaion

* fixes

* Apply suggestions from code review
This commit is contained in:
ringabout
2022-12-06 22:37:16 +08:00
committed by GitHub
parent 4ca2dcb404
commit 9ba07edb2e
31 changed files with 92 additions and 6358 deletions

View File

@@ -119,6 +119,16 @@
- Using an unnamed break in a block is deprecated. This warning will become an error in future versions! Use a named block with a named break instead.
- Several Standard libraries are moved to nimble packages, use `nimble` to install them:
- `std/punycode` => `punycode`
- `std/asyncftpclient` => `asyncftpclient`
- `std/smtp` => `smtp`
- `std/db_common` => `db_connector/db_common`
- `std/db_sqlite` => `db_connector/db_sqlite`
- `std/db_mysql` => `db_connector/db_mysql`
- `std/db_postgres` => `db_connector/db_postgres`
- `std/db_odbc` => `db_connector/db_odbc`
- Previously, calls like `foo(a, b): ...` or `foo(a, b) do: ...` where the final argument of
`foo` had type `proc ()` were assumed by the compiler to mean `foo(a, b, proc () = ...)`.
This behavior is now deprecated. Use `foo(a, b) do (): ...` or `foo(a, b, proc () = ...)` instead.

View File

@@ -370,9 +370,13 @@ Internet Protocols and Support
This module implements a selector API with backends specific to each OS.
Currently, epoll on Linux and select on other operating systems.
* [smtp](smtp.html)
This module implements a simple SMTP client.
* [socketstreams](socketstreams.html)
This module provides an implementation of the streams interface for sockets.
* [uri](uri.html)
This module provides functions for working with URIs.

View File

@@ -1,418 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## A higher level `mySQL`:idx: database wrapper. The same interface is
## implemented for other databases too.
##
## See also: `db_odbc <db_odbc.html>`_, `db_sqlite <db_sqlite.html>`_,
## `db_postgres <db_postgres.html>`_.
##
## Parameter substitution
## ======================
##
## All `db_*` modules support the same form of parameter substitution.
## That is, using the `?` (question mark) to signify the place where a
## value should be placed. For example:
## ```
## sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)"
## ```
##
## Examples
## ========
##
## Opening a connection to a database
## ----------------------------------
##
## ```
## import std/db_mysql
## let db = open("localhost", "user", "password", "dbname")
## db.close()
## ```
##
## Creating a table
## ----------------
##
## ```
## db.exec(sql"DROP TABLE IF EXISTS myTable")
## db.exec(sql("""CREATE TABLE myTable (
## id integer,
## name varchar(50) not null)"""))
## ```
##
## Inserting data
## --------------
##
## ```
## db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
## "Dominik")
## ```
##
## Larger example
## --------------
##
## ```
## import std/[db_mysql, math]
##
## let theDb = open("localhost", "nim", "nim", "test")
##
## theDb.exec(sql"Drop table if exists myTestTbl")
## theDb.exec(sql("create table myTestTbl (" &
## " Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, " &
## " Name VARCHAR(50) NOT NULL, " &
## " i INT(11), " &
## " f DECIMAL(18,10))"))
##
## theDb.exec(sql"START TRANSACTION")
## for i in 1..1000:
## theDb.exec(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
## "Item#" & $i, i, sqrt(i.float))
## theDb.exec(sql"COMMIT")
##
## for x in theDb.fastRows(sql"select * from myTestTbl"):
## echo x
##
## let id = theDb.tryInsertId(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
## "Item#1001", 1001, sqrt(1001.0))
## echo "Inserted item: ", theDb.getValue(sql"SELECT name FROM myTestTbl WHERE id=?", id)
##
## theDb.close()
## ```
import strutils, mysql
import db_common
export db_common
import std/private/[since, dbutils]
type
DbConn* = distinct PMySQL ## encapsulates a database connection
Row* = seq[string] ## a row of a dataset. NULL database values will be
## converted to nil.
InstantRow* = object ## a handle that can be used to get a row's
## column text on demand
row: cstringArray
len: int
proc dbError*(db: DbConn) {.noreturn.} =
## raises a DbError exception.
var e: ref DbError
new(e)
e.msg = $mysql.error(PMySQL db)
raise e
when false:
proc dbQueryOpt*(db: DbConn, query: string, args: varargs[string, `$`]) =
var stmt = mysql_stmt_init(db)
if stmt == nil: dbError(db)
if mysql_stmt_prepare(stmt, query, len(query)) != 0:
dbError(db)
var
binding: seq[MYSQL_BIND]
discard mysql_stmt_close(stmt)
proc dbQuote*(s: string): string =
## DB quotes the string. Note that this doesn't escape `%` and `_`.
result = newStringOfCap(s.len + 2)
result.add "'"
for c in items(s):
# see https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html#mysql-escaping
case c
of '\0': result.add "\\0"
of '\b': result.add "\\b"
of '\t': result.add "\\t"
of '\l': result.add "\\n"
of '\r': result.add "\\r"
of '\x1a': result.add "\\Z"
of '"': result.add "\\\""
of '\'': result.add "\\'"
of '\\': result.add "\\\\"
else: result.add c
add(result, '\'')
proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
dbFormatImpl(formatstr, dbQuote, args)
proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.
tags: [ReadDbEffect, WriteDbEffect].} =
## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args)
return mysql.real_query(PMySQL db, q.cstring, q.len) == 0'i32
proc rawExec(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) =
var q = dbFormat(query, args)
if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: dbError(db)
proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect].} =
## executes the query and raises EDB if not successful.
var q = dbFormat(query, args)
if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: dbError(db)
proc newRow(L: int): Row =
newSeq(result, L)
for i in 0..L-1: result[i] = ""
proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =
if row != nil:
while mysql.fetch_row(sqlres) != nil: discard
mysql.freeResult(sqlres)
iterator fastRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## executes the query and iterates over the result dataset.
##
## This is very fast, but potentially dangerous. Use this iterator only
## if you require **ALL** the rows.
##
## Breaking the fastRows() iterator during a loop will cause the next
## database query to raise an `EDb` exception `Commands out of sync`.
rawExec(db, query, args)
var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil:
var
L = int(mysql.numFields(sqlres))
row: cstringArray
result: Row
backup: Row
newSeq(result, L)
while true:
row = mysql.fetch_row(sqlres)
if row == nil: break
for i in 0..L-1:
setLen(result[i], 0)
result[i].add row[i]
yield result
properFreeResult(sqlres, row)
iterator instantRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
## Same as fastRows but returns a handle that can be used to get column text
## on demand using `[]`. Returned handle is valid only within the iterator body.
rawExec(db, query, args)
var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil:
let L = int(mysql.numFields(sqlres))
var row: cstringArray
while true:
row = mysql.fetch_row(sqlres)
if row == nil: break
yield InstantRow(row: row, len: L)
properFreeResult(sqlres, row)
proc setTypeName(t: var DbType; f: PFIELD) =
t.name = $f.name
t.maxReprLen = Natural(f.max_length)
if (NOT_NULL_FLAG and f.flags) != 0: t.notNull = true
case f.ftype
of TYPE_DECIMAL:
t.kind = dbDecimal
of TYPE_TINY:
t.kind = dbInt
t.size = 1
of TYPE_SHORT:
t.kind = dbInt
t.size = 2
of TYPE_LONG:
t.kind = dbInt
t.size = 4
of TYPE_FLOAT:
t.kind = dbFloat
t.size = 4
of TYPE_DOUBLE:
t.kind = dbFloat
t.size = 8
of TYPE_NULL:
t.kind = dbNull
of TYPE_TIMESTAMP:
t.kind = dbTimestamp
of TYPE_LONGLONG:
t.kind = dbInt
t.size = 8
of TYPE_INT24:
t.kind = dbInt
t.size = 3
of TYPE_DATE:
t.kind = dbDate
of TYPE_TIME:
t.kind = dbTime
of TYPE_DATETIME:
t.kind = dbDatetime
of TYPE_YEAR:
t.kind = dbDate
of TYPE_NEWDATE:
t.kind = dbDate
of TYPE_VARCHAR, TYPE_VAR_STRING, TYPE_STRING:
t.kind = dbVarchar
of TYPE_BIT:
t.kind = dbBit
of TYPE_NEWDECIMAL:
t.kind = dbDecimal
of TYPE_ENUM: t.kind = dbEnum
of TYPE_SET: t.kind = dbSet
of TYPE_TINY_BLOB, TYPE_MEDIUM_BLOB, TYPE_LONG_BLOB,
TYPE_BLOB: t.kind = dbBlob
of TYPE_GEOMETRY:
t.kind = dbGeometry
proc setColumnInfo(columns: var DbColumns; res: PRES; L: int) =
setLen(columns, L)
for i in 0..<L:
let fp = mysql.fetch_field_direct(res, cint(i))
setTypeName(columns[i].typ, fp)
columns[i].name = $fp.name
columns[i].tableName = $fp.table
columns[i].primaryKey = (fp.flags and PRI_KEY_FLAG) != 0
#columns[i].foreignKey = there is no such thing in mysql
iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
args: varargs[string, `$`]): InstantRow =
## Same as fastRows but returns a handle that can be used to get column text
## on demand using `[]`. Returned handle is valid only within the iterator body.
rawExec(db, query, args)
var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil:
let L = int(mysql.numFields(sqlres))
setColumnInfo(columns, sqlres, L)
var row: cstringArray
while true:
row = mysql.fetch_row(sqlres)
if row == nil: break
yield InstantRow(row: row, len: L)
properFreeResult(sqlres, row)
proc `[]`*(row: InstantRow, col: int): string {.inline.} =
## Returns text for given column of the row.
$row.row[col]
proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} =
## Return cstring of given column of the row
row.row[index]
proc len*(row: InstantRow): int {.inline.} =
## Returns number of columns in the row.
row.len
proc getRow*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## Retrieves a single row. If the query doesn't return any rows, this proc
## will return a Row with empty strings for each column.
rawExec(db, query, args)
var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil:
var L = int(mysql.numFields(sqlres))
result = newRow(L)
var row = mysql.fetch_row(sqlres)
if row != nil:
for i in 0..L-1:
setLen(result[i], 0)
add(result[i], row[i])
properFreeResult(sqlres, row)
proc getAllRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): seq[Row] {.tags: [ReadDbEffect].} =
## executes the query and returns the whole result dataset.
result = @[]
rawExec(db, query, args)
var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil:
var L = int(mysql.numFields(sqlres))
var row: cstringArray
var j = 0
while true:
row = mysql.fetch_row(sqlres)
if row == nil: break
setLen(result, j+1)
newSeq(result[j], L)
for i in 0..L-1:
result[j][i] = $row[i]
inc(j)
mysql.freeResult(sqlres)
iterator rows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## same as `fastRows`, but slower and safe.
for r in items(getAllRows(db, query, args)): yield r
proc getValue*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): string {.tags: [ReadDbEffect].} =
## executes the query and returns the first column of the first row of the
## result dataset. Returns "" if the dataset contains no rows or the database
## value is NULL.
result = getRow(db, query, args)[0]
proc tryInsertId*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect], raises: [DbError].} =
## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error.
var q = dbFormat(query, args)
if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32:
result = -1'i64
else:
result = mysql.insertId(PMySQL db)
proc insertId*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect].} =
## executes the query (typically "INSERT") and returns the
## generated ID for the row.
result = tryInsertID(db, query, args)
if result < 0: dbError(db)
proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], raises: [DbError], since: (1, 3).} =
## same as tryInsertID
tryInsertID(db, query, args)
proc insert*(db: DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], since: (1, 3).} =
## same as insertId
result = tryInsert(db, query,pkName, args)
if result < 0: dbError(db)
proc execAffectedRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [ReadDbEffect, WriteDbEffect].} =
## runs the query (typically "UPDATE") and returns the
## number of affected rows
rawExec(db, query, args)
result = mysql.affectedRows(PMySQL db)
proc close*(db: DbConn) {.tags: [DbEffect].} =
## closes the database connection.
if PMySQL(db) != nil: mysql.close(PMySQL db)
proc open*(connection, user, password, database: string): DbConn {.
tags: [DbEffect].} =
## opens a database connection. Raises `EDb` if the connection could not
## be established.
var res = mysql.init(nil)
if res == nil: dbError("could not open database connection")
let
colonPos = connection.find(':')
host = if colonPos < 0: connection
else: substr(connection, 0, colonPos-1)
port: int32 = if colonPos < 0: 0'i32
else: substr(connection, colonPos+1).parseInt.int32
if mysql.realConnect(res, host.cstring, user, password, database,
port, nil, 0) == nil:
var errmsg = $mysql.error(res)
mysql.close(res)
dbError(errmsg)
result = DbConn(res)
proc setEncoding*(connection: DbConn, encoding: string): bool {.
tags: [DbEffect].} =
## sets the encoding of a database connection, returns true for
## success, false for failure.
result = mysql.set_character_set(PMySQL connection, encoding) == 0

View File

@@ -1,529 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Nim Contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## A higher level `ODBC` database wrapper.
##
## This is the same interface that is implemented for other databases.
##
## This has NOT yet been (extensively) tested against ODBC drivers for
## Teradata, Oracle, Sybase, MSSqlvSvr, et. al. databases.
##
## Currently all queries are ANSI calls, not Unicode.
##
## See also: `db_postgres <db_postgres.html>`_, `db_sqlite <db_sqlite.html>`_,
## `db_mysql <db_mysql.html>`_.
##
## Parameter substitution
## ======================
##
## All `db_*` modules support the same form of parameter substitution.
## That is, using the `?` (question mark) to signify the place where a
## value should be placed. For example:
##
## ```Nim
## sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)"
## ```
##
##
## Examples
## ========
##
## Opening a connection to a database
## ----------------------------------
##
## ```Nim
## import std/db_odbc
## var db = open("localhost", "user", "password", "dbname")
## db.close()
## ```
##
## Creating a table
## ----------------
##
## ```Nim
## db.exec(sql"DROP TABLE IF EXISTS myTable")
## db.exec(sql("""CREATE TABLE myTable (
## id integer,
## name varchar(50) not null)"""))
## ```
##
## Inserting data
## --------------
##
## ```Nim
## db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
## "Andreas")
## ```
##
## Large example
## -------------
##
## ```Nim
## import std/[db_odbc, math]
##
## var theDb = open("localhost", "nim", "nim", "test")
##
## theDb.exec(sql"Drop table if exists myTestTbl")
## theDb.exec(sql("create table myTestTbl (" &
## " Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, " &
## " Name VARCHAR(50) NOT NULL, " &
## " i INT(11), " &
## " f DECIMAL(18,10))"))
##
## theDb.exec(sql"START TRANSACTION")
## for i in 1..1000:
## theDb.exec(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
## "Item#" & $i, i, sqrt(i.float))
## theDb.exec(sql"COMMIT")
##
## for x in theDb.fastRows(sql"select * from myTestTbl"):
## echo x
##
## let id = theDb.tryInsertId(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
## "Item#1001", 1001, sqrt(1001.0))
## echo "Inserted item: ", theDb.getValue(sql"SELECT name FROM myTestTbl WHERE id=?", id)
##
## theDb.close()
## ```
import strutils, odbcsql
import db_common
export db_common
import std/private/[since, dbutils]
type
OdbcConnTyp = tuple[hDb: SqlHDBC, env: SqlHEnv, stmt: SqlHStmt]
DbConn* = OdbcConnTyp ## encapsulates a database connection
Row* = seq[string] ## a row of a dataset. NULL database values will be
## converted to nil.
InstantRow* = tuple[row: seq[string], len: int] ## a handle that can be
## used to get a row's
## column text on demand
var
buf: array[0..4096, char]
proc properFreeResult(hType: int, sqlres: var SqlHandle) {.
tags: [WriteDbEffect], raises: [].} =
try:
discard SQLFreeHandle(hType.TSqlSmallInt, sqlres)
sqlres = nil
except: discard
proc getErrInfo(db: var DbConn): tuple[res: int, ss, ne, msg: string] {.
tags: [ReadDbEffect], raises: [].} =
## Returns ODBC error information
var
sqlState: array[0..512, char]
nativeErr: array[0..512, char]
errMsg: array[0..512, char]
retSz: TSqlSmallInt = 0
res: TSqlSmallInt = 0
try:
sqlState[0] = '\0'
nativeErr[0] = '\0'
errMsg[0] = '\0'
res = SQLErr(db.env, db.hDb, db.stmt,
cast[PSQLCHAR](sqlState.addr),
cast[PSQLCHAR](nativeErr.addr),
cast[PSQLCHAR](errMsg.addr),
511.TSqlSmallInt, retSz.addr)
except:
discard
return (res.int, $(cast[cstring](addr sqlState)), $cast[cstring](addr nativeErr), $cast[cstring](addr errMsg))
proc dbError*(db: var DbConn) {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError] .} =
## Raises an `[DbError]` exception with ODBC error information
var
e: ref DbError
ss, ne, msg: string = ""
isAnError = false
res: int = 0
prevSs = ""
while true:
prevSs = ss
(res, ss, ne, msg) = db.getErrInfo()
if prevSs == ss:
break
# sqlState of 00000 is not an error
elif ss == "00000":
break
elif ss == "01000":
echo "\nWarning: ", ss, " ", msg
continue
else:
isAnError = true
echo "\nError: ", ss, " ", msg
if isAnError:
new(e)
e.msg = "ODBC Error"
if db.stmt != nil:
properFreeResult(SQL_HANDLE_STMT, db.stmt)
properFreeResult(SQL_HANDLE_DBC, db.hDb)
properFreeResult(SQL_HANDLE_ENV, db.env)
raise e
proc sqlCheck(db: var DbConn, resVal: TSqlSmallInt) {.raises: [DbError]} =
## Wrapper that raises `EDb` if `resVal` is neither SQL_SUCCESS or SQL_NO_DATA
if resVal notIn [SQL_SUCCESS, SQL_NO_DATA]: dbError(db)
proc sqlGetDBMS(db: var DbConn): string {.
tags: [ReadDbEffect, WriteDbEffect], raises: [] .} =
## Returns the ODBC SQL_DBMS_NAME string
const
SQL_DBMS_NAME = 17.SqlUSmallInt
var
sz: TSqlSmallInt = 0
buf[0] = '\0'
try:
db.sqlCheck(SQLGetInfo(db.hDb, SQL_DBMS_NAME, cast[SqlPointer](buf.addr),
4095.TSqlSmallInt, sz.addr))
except: discard
return $(cast[cstring](addr buf))
proc dbQuote*(s: string): string {.noSideEffect.} =
## DB quotes the string.
result = "'"
for c in items(s):
if c == '\'': add(result, "''")
else: add(result, c)
add(result, '\'')
proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string {.
noSideEffect.} =
## Replace any `?` placeholders with `args`,
## and quotes the arguments
dbFormatImpl(formatstr, dbQuote, args)
proc prepareFetch(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): TSqlSmallInt {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
# Prepare a statement, execute it and fetch the data to the driver
# ready for retrieval of the data
# Used internally by iterators and retrieval procs
# requires calling
# properFreeResult(SQL_HANDLE_STMT, db.stmt)
# when finished
db.sqlCheck(SQLAllocHandle(SQL_HANDLE_STMT, db.hDb, db.stmt))
var q = dbFormat(query, args)
db.sqlCheck(SQLPrepare(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
db.sqlCheck(SQLExecute(db.stmt))
result = SQLFetch(db.stmt)
db.sqlCheck(result)
proc prepareFetchDirect(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
# Prepare a statement, execute it and fetch the data to the driver
# ready for retrieval of the data
# Used internally by iterators and retrieval procs
# requires calling
# properFreeResult(SQL_HANDLE_STMT, db.stmt)
# when finished
db.sqlCheck(SQLAllocHandle(SQL_HANDLE_STMT, db.hDb, db.stmt))
var q = dbFormat(query, args)
db.sqlCheck(SQLExecDirect(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
db.sqlCheck(SQLFetch(db.stmt))
proc tryExec*(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.
tags: [ReadDbEffect, WriteDbEffect], raises: [].} =
## Tries to execute the query and returns true if successful, false otherwise.
var
res:TSqlSmallInt = -1
try:
db.prepareFetchDirect(query, args)
var
rCnt:TSqlLen = -1
res = SQLRowCount(db.stmt, rCnt)
properFreeResult(SQL_HANDLE_STMT, db.stmt)
if res != SQL_SUCCESS: dbError(db)
except: discard
return res == SQL_SUCCESS
proc rawExec(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
db.prepareFetchDirect(query, args)
proc exec*(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Executes the query and raises EDB if not successful.
db.prepareFetchDirect(query, args)
properFreeResult(SQL_HANDLE_STMT, db.stmt)
proc newRow(L: int): Row {.noSideEFfect.} =
newSeq(result, L)
for i in 0..L-1: result[i] = ""
iterator fastRows*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Executes the query and iterates over the result dataset.
##
## This is very fast, but potentially dangerous. Use this iterator only
## if you require **ALL** the rows.
##
## Breaking the fastRows() iterator during a loop may cause a driver error
## for subsequent queries
##
## Rows are retrieved from the server at each iteration.
var
rowRes: Row
sz: TSqlLen = 0
cCnt: TSqlSmallInt = 0
res: TSqlSmallInt = 0
res = db.prepareFetch(query, args)
if res == SQL_NO_DATA:
discard
elif res == SQL_SUCCESS:
res = SQLNumResultCols(db.stmt, cCnt)
rowRes = newRow(cCnt)
rowRes.setLen(max(cCnt,0))
while res == SQL_SUCCESS:
for colId in 1..cCnt:
buf[0] = '\0'
db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
cast[cstring](buf.addr), 4095, sz.addr))
rowRes[colId-1] = $cast[cstring]((addr buf))
yield rowRes
res = SQLFetch(db.stmt)
properFreeResult(SQL_HANDLE_STMT, db.stmt)
db.sqlCheck(res)
iterator instantRows*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect, WriteDbEffect].} =
## Same as fastRows but returns a handle that can be used to get column text
## on demand using `[]`. Returned handle is valid only within the iterator body.
var
rowRes: Row = @[]
sz: TSqlLen = 0
cCnt: TSqlSmallInt = 0
res: TSqlSmallInt = 0
res = db.prepareFetch(query, args)
if res == SQL_NO_DATA:
discard
elif res == SQL_SUCCESS:
res = SQLNumResultCols(db.stmt, cCnt)
rowRes = newRow(cCnt)
rowRes.setLen(max(cCnt,0))
while res == SQL_SUCCESS:
for colId in 1..cCnt:
buf[0] = '\0'
db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
cast[cstring](buf.addr), 4095, sz.addr))
rowRes[colId-1] = $cast[cstring](addr buf)
yield (row: rowRes, len: cCnt.int)
res = SQLFetch(db.stmt)
properFreeResult(SQL_HANDLE_STMT, db.stmt)
db.sqlCheck(res)
proc `[]`*(row: InstantRow, col: int): string {.inline.} =
## Returns text for given column of the row
$row.row[col]
proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} =
## Return cstring of given column of the row
row.row[index].cstring
proc len*(row: InstantRow): int {.inline.} =
## Returns number of columns in the row
row.len
proc getRow*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Retrieves a single row. If the query doesn't return any rows, this proc
## will return a Row with empty strings for each column.
var
rowRes: Row
sz: TSqlLen = 0
cCnt: TSqlSmallInt = 0
res: TSqlSmallInt = 0
res = db.prepareFetch(query, args)
if res == SQL_NO_DATA:
result = @[]
elif res == SQL_SUCCESS:
res = SQLNumResultCols(db.stmt, cCnt)
rowRes = newRow(cCnt)
rowRes.setLen(max(cCnt,0))
for colId in 1..cCnt:
buf[0] = '\0'
db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
cast[cstring](buf.addr), 4095, sz.addr))
rowRes[colId-1] = $cast[cstring](addr buf)
res = SQLFetch(db.stmt)
result = rowRes
properFreeResult(SQL_HANDLE_STMT, db.stmt)
db.sqlCheck(res)
proc getAllRows*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): seq[Row] {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError] .} =
## Executes the query and returns the whole result dataset.
var
rows: seq[Row] = @[]
rowRes: Row
sz: TSqlLen = 0
cCnt: TSqlSmallInt = 0
res: TSqlSmallInt = 0
res = db.prepareFetch(query, args)
if res == SQL_NO_DATA:
result = @[]
elif res == SQL_SUCCESS:
res = SQLNumResultCols(db.stmt, cCnt)
rowRes = newRow(cCnt)
rowRes.setLen(max(cCnt,0))
while res == SQL_SUCCESS:
for colId in 1..cCnt:
buf[0] = '\0'
db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
cast[cstring](buf.addr), 4095, sz.addr))
rowRes[colId-1] = $cast[cstring](addr buf)
rows.add(rowRes)
res = SQLFetch(db.stmt)
result = rows
properFreeResult(SQL_HANDLE_STMT, db.stmt)
db.sqlCheck(res)
iterator rows*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Same as `fastRows`, but slower and safe.
##
## This retrieves ALL rows into memory before
## iterating through the rows.
## Large dataset queries will impact on memory usage.
for r in items(getAllRows(db, query, args)): yield r
proc getValue*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): string {.
tags: [ReadDbEffect, WriteDbEffect], raises: [].} =
## Executes the query and returns the first column of the first row of the
## result dataset. Returns "" if the dataset contains no rows or the database
## value is NULL.
result = ""
try:
result = getRow(db, query, args)[0]
except: discard
proc tryInsertId*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [ReadDbEffect, WriteDbEffect], raises: [].} =
## Executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error.
if not tryExec(db, query, args):
result = -1'i64
else:
result = -1'i64
try:
case sqlGetDBMS(db).toLower():
of "postgresql":
result = getValue(db, sql"SELECT LASTVAL();", []).parseInt
of "mysql":
result = getValue(db, sql"SELECT LAST_INSERT_ID();", []).parseInt
of "sqlite":
result = getValue(db, sql"SELECT LAST_INSERT_ROWID();", []).parseInt
of "microsoft sql server":
result = getValue(db, sql"SELECT SCOPE_IDENTITY();", []).parseInt
of "oracle":
result = getValue(db, sql"SELECT id.currval FROM DUAL;", []).parseInt
else: result = -1'i64
except: discard
proc insertId*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Executes the query (typically "INSERT") and returns the
## generated ID for the row.
result = tryInsertID(db, query, args)
if result < 0: dbError(db)
proc tryInsert*(db: var DbConn, query: SqlQuery,pkName: string,
args: varargs[string, `$`]): int64
{.tags: [ReadDbEffect, WriteDbEffect], raises: [], since: (1, 3).} =
## same as tryInsertID
tryInsertID(db, query, args)
proc insert*(db: var DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64
{.tags: [ReadDbEffect, WriteDbEffect], since: (1, 3).} =
## same as insertId
result = tryInsert(db, query,pkName, args)
if result < 0: dbError(db)
proc execAffectedRows*(db: var DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Runs the query (typically "UPDATE") and returns the
## number of affected rows
result = -1
db.sqlCheck(SQLAllocHandle(SQL_HANDLE_STMT, db.hDb, db.stmt.SqlHandle))
var q = dbFormat(query, args)
db.sqlCheck(SQLPrepare(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
rawExec(db, query, args)
var rCnt:TSqlLen = -1
db.sqlCheck(SQLRowCount(db.hDb, rCnt))
properFreeResult(SQL_HANDLE_STMT, db.stmt)
result = rCnt.int64
proc close*(db: var DbConn) {.
tags: [WriteDbEffect], raises: [].} =
## Closes the database connection.
if db.hDb != nil:
try:
var res = SQLDisconnect(db.hDb)
if db.stmt != nil:
res = SQLFreeHandle(SQL_HANDLE_STMT, db.stmt)
res = SQLFreeHandle(SQL_HANDLE_DBC, db.hDb)
res = SQLFreeHandle(SQL_HANDLE_ENV, db.env)
db = (hDb: nil, env: nil, stmt: nil)
except:
discard
proc open*(connection, user, password, database: string): DbConn {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Opens a database connection.
##
## Raises `EDb` if the connection could not be established.
##
## Currently the database parameter is ignored,
## but included to match `open()` in the other db_xxxxx library modules.
var
val = SQL_OV_ODBC3
resLen = 0
result = (hDb: nil, env: nil, stmt: nil)
# allocate environment handle
var res = SQLAllocHandle(SQL_HANDLE_ENV, result.env, result.env)
if res != SQL_SUCCESS: dbError("Error: unable to initialise ODBC environment.")
res = SQLSetEnvAttr(result.env,
SQL_ATTR_ODBC_VERSION.TSqlInteger,
cast[SqlPointer](val), resLen.TSqlInteger)
if res != SQL_SUCCESS: dbError("Error: unable to set ODBC driver version.")
# allocate hDb handle
res = SQLAllocHandle(SQL_HANDLE_DBC, result.env, result.hDb)
if res != SQL_SUCCESS: dbError("Error: unable to allocate connection handle.")
# Connect: connection = dsn str,
res = SQLConnect(result.hDb,
connection.PSQLCHAR , connection.len.TSqlSmallInt,
user.PSQLCHAR, user.len.TSqlSmallInt,
password.PSQLCHAR, password.len.TSqlSmallInt)
if res != SQL_SUCCESS:
result.dbError()
proc setEncoding*(connection: DbConn, encoding: string): bool {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
## Currently not implemented for ODBC.
##
## Sets the encoding of a database connection, returns true for
## success, false for failure.
##result = set_character_set(connection, encoding) == 0
dbError("setEncoding() is currently not implemented by the db_odbc module")

View File

@@ -1,647 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## A higher level `PostgreSQL`:idx: database wrapper. This interface
## is implemented for other databases also.
##
## See also: `db_odbc <db_odbc.html>`_, `db_sqlite <db_sqlite.html>`_,
## `db_mysql <db_mysql.html>`_.
##
## Parameter substitution
## ======================
##
## All `db_*` modules support the same form of parameter substitution.
## That is, using the `?` (question mark) to signify the place where a
## value should be placed. For example:
##
## ```Nim
## sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)"
## ```
##
## **Note**: There are two approaches to parameter substitution support by
## this module.
##
## 1. `SqlQuery` using `?, ?, ?, ...` (same as all the `db_*` modules)
##
## 2. `SqlPrepared` using `$1, $2, $3, ...`
##
## ```Nim
## prepare(db, "myExampleInsert",
## sql"""INSERT INTO myTable
## (colA, colB, colC)
## VALUES ($1, $2, $3)""",
## 3)
## ```
##
##
## Unix Socket
## ===========
##
## Using Unix sockets instead of TCP connection can
## `improve performance up to 30% ~ 175% for some operations <https://momjian.us/main/blogs/pgblog/2012.html#June_6_2012>`_.
##
## To use Unix sockets with `db_postgres`, change the server address to the socket file path:
##
## ```Nim
## import std/db_postgres ## Change "localhost" or "127.0.0.1" to the socket file path
## let db = db_postgres.open("/run/postgresql", "user", "password", "database")
## echo db.getAllRows(sql"SELECT version();")
## db.close()
## ```
##
## The socket file path is operating system specific and distribution specific,
## additional configuration may or may not be needed on your `postgresql.conf`.
## The Postgres server must be on the same computer and only works for Unix-like operating systems.
##
##
## Examples
## ========
##
## Opening a connection to a database
## ----------------------------------
##
## ```Nim
## import std/db_postgres
## let db = open("localhost", "user", "password", "dbname")
## db.close()
## ```
##
## Creating a table
## ----------------
##
## ```Nim
## db.exec(sql"DROP TABLE IF EXISTS myTable")
## db.exec(sql("""CREATE TABLE myTable (
## id integer,
## name varchar(50) not null)"""))
## ```
##
## Inserting data
## --------------
##
## ```Nim
## db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
## "Dominik")
## ```
import strutils, postgres
import db_common
export db_common
import std/private/[since, dbutils]
type
DbConn* = PPGconn ## encapsulates a database connection
Row* = seq[string] ## a row of a dataset. NULL database values will be
## converted to nil.
InstantRow* = object ## a handle that can be
res: PPGresult ## used to get a row's
SqlPrepared* = distinct string ## a identifier for the prepared queries
proc dbError*(db: DbConn) {.noreturn.} =
## raises a DbError exception.
var e: ref DbError
new(e)
e.msg = $pqErrorMessage(db)
raise e
proc dbQuote*(s: string): string =
## DB quotes the string.
result = "'"
for c in items(s):
case c
of '\'': add(result, "''")
of '\0': add(result, "\\0")
else: add(result, c)
add(result, '\'')
proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
dbFormatImpl(formatstr, dbQuote, args)
proc tryExec*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): bool {.tags: [ReadDbEffect, WriteDbEffect].} =
## tries to execute the query and returns true if successful, false otherwise.
var res = pqexecParams(db, dbFormat(query, args).cstring, 0, nil, nil,
nil, nil, 0)
result = pqresultStatus(res) == PGRES_COMMAND_OK
pqclear(res)
proc tryExec*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): bool {.tags: [
ReadDbEffect, WriteDbEffect].} =
## tries to execute the query and returns true if successful, false otherwise.
var arr = allocCStringArray(args)
var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
nil, nil, 0)
deallocCStringArray(arr)
result = pqresultStatus(res) == PGRES_COMMAND_OK
pqclear(res)
proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect].} =
## executes the query and raises EDB if not successful.
var res = pqexecParams(db, dbFormat(query, args).cstring, 0, nil, nil,
nil, nil, 0)
if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
pqclear(res)
proc exec*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string]) {.tags: [ReadDbEffect, WriteDbEffect].} =
var arr = allocCStringArray(args)
var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
nil, nil, 0)
deallocCStringArray(arr)
if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
pqclear(res)
proc newRow(L: int): Row =
newSeq(result, L)
for i in 0..L-1: result[i] = ""
proc setupQuery(db: DbConn, query: SqlQuery,
args: varargs[string]): PPGresult =
result = pqexec(db, dbFormat(query, args).cstring)
if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
proc setupQuery(db: DbConn, stmtName: SqlPrepared,
args: varargs[string]): PPGresult =
var arr = allocCStringArray(args)
result = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
nil, nil, 0)
deallocCStringArray(arr)
if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
proc setupSingeRowQuery(db: DbConn, query: SqlQuery,
args: varargs[string]) =
if pqsendquery(db, dbFormat(query, args).cstring) != 1:
dbError(db)
if pqSetSingleRowMode(db) != 1:
dbError(db)
proc setupSingeRowQuery(db: DbConn, stmtName: SqlPrepared,
args: varargs[string]) =
var arr = allocCStringArray(args)
if pqsendqueryprepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) != 1:
dbError(db)
if pqSetSingleRowMode(db) != 1:
dbError(db)
deallocCStringArray(arr)
proc prepare*(db: DbConn; stmtName: string, query: SqlQuery;
nParams: int): SqlPrepared =
## Creates a new `SqlPrepared` statement. Parameter substitution is done
## via `$1`, `$2`, `$3`, etc.
if nParams > 0 and not string(query).contains("$1"):
dbError("parameter substitution expects \"$1\"")
var res = pqprepare(db, stmtName, query.cstring, int32(nParams), nil)
if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
result = SqlPrepared(stmtName)
pqclear(res)
proc setRow(res: PPGresult, r: var Row, line, cols: int32) =
for col in 0'i32..cols-1:
setLen(r[col], 0)
let x = pqgetvalue(res, line, col)
if x.isNil:
r[col] = ""
else:
add(r[col], x)
template fetchRows(db: DbConn): untyped =
var res: PPGresult = nil
while true:
res = pqgetresult(db)
if res == nil:
break
let status = pqresultStatus(res)
if status == PGRES_TUPLES_OK:
discard
elif status != PGRES_SINGLE_TUPLE:
dbError(db)
else:
let L = pqNfields(res)
var result = newRow(L)
setRow(res, result, 0, L)
yield result
pqclear(res)
iterator fastRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## executes the query and iterates over the result dataset. This is very
## fast, but potentially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Postgres it is safe though.
setupSingeRowQuery(db, query, args)
fetchRows(db)
iterator fastRows*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## executes the query and iterates over the result dataset. This is very
## fast, but potentially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Postgres it is safe though.
setupSingeRowQuery(db, stmtName, args)
fetchRows(db)
template fetchinstantRows(db: DbConn): untyped =
var res: PPGresult = nil
while true:
res = pqgetresult(db)
if res == nil:
break
let status = pqresultStatus(res)
if status == PGRES_TUPLES_OK:
discard
elif status != PGRES_SINGLE_TUPLE:
dbError(db)
else:
yield InstantRow(res: res)
pqclear(res)
iterator instantRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
## same as fastRows but returns a handle that can be used to get column text
## on demand using `[]`. Returned handle is valid only within iterator body.
setupSingeRowQuery(db, query, args)
fetchinstantRows(db)
iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
## same as fastRows but returns a handle that can be used to get column text
## on demand using `[]`. Returned handle is valid only within iterator body.
setupSingeRowQuery(db, stmtName, args)
fetchinstantRows(db)
proc getColumnType(res: PPGresult, col: int) : DbType =
## returns DbType for given column in the row
## defined in pg_type.h file in the postgres source code
## Wire representation for types: http://www.npgsql.org/dev/types.html
var oid = pqftype(res, int32(col))
## The integer returned is the internal OID number of the type
case oid
of 16: return DbType(kind: DbTypeKind.dbBool, name: "bool")
of 17: return DbType(kind: DbTypeKind.dbBlob, name: "bytea")
of 21: return DbType(kind: DbTypeKind.dbInt, name: "int2", size: 2)
of 23: return DbType(kind: DbTypeKind.dbInt, name: "int4", size: 4)
of 20: return DbType(kind: DbTypeKind.dbInt, name: "int8", size: 8)
of 1560: return DbType(kind: DbTypeKind.dbBit, name: "bit")
of 1562: return DbType(kind: DbTypeKind.dbInt, name: "varbit")
of 18: return DbType(kind: DbTypeKind.dbFixedChar, name: "char")
of 19: return DbType(kind: DbTypeKind.dbFixedChar, name: "name")
of 1042: return DbType(kind: DbTypeKind.dbFixedChar, name: "bpchar")
of 25: return DbType(kind: DbTypeKind.dbVarchar, name: "text")
of 1043: return DbType(kind: DbTypeKind.dbVarChar, name: "varchar")
of 2275: return DbType(kind: DbTypeKind.dbVarchar, name: "cstring")
of 700: return DbType(kind: DbTypeKind.dbFloat, name: "float4")
of 701: return DbType(kind: DbTypeKind.dbFloat, name: "float8")
of 790: return DbType(kind: DbTypeKind.dbDecimal, name: "money")
of 1700: return DbType(kind: DbTypeKind.dbDecimal, name: "numeric")
of 704: return DbType(kind: DbTypeKind.dbTimeInterval, name: "tinterval")
of 702: return DbType(kind: DbTypeKind.dbTimestamp, name: "abstime")
of 703: return DbType(kind: DbTypeKind.dbTimeInterval, name: "reltime")
of 1082: return DbType(kind: DbTypeKind.dbDate, name: "date")
of 1083: return DbType(kind: DbTypeKind.dbTime, name: "time")
of 1114: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamp")
of 1184: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamptz")
of 1186: return DbType(kind: DbTypeKind.dbTimeInterval, name: "interval")
of 1266: return DbType(kind: DbTypeKind.dbTime, name: "timetz")
of 114: return DbType(kind: DbTypeKind.dbJson, name: "json")
of 142: return DbType(kind: DbTypeKind.dbXml, name: "xml")
of 3802: return DbType(kind: DbTypeKind.dbJson, name: "jsonb")
of 600: return DbType(kind: DbTypeKind.dbPoint, name: "point")
of 601: return DbType(kind: DbTypeKind.dbLseg, name: "lseg")
of 602: return DbType(kind: DbTypeKind.dbPath, name: "path")
of 603: return DbType(kind: DbTypeKind.dbBox, name: "box")
of 604: return DbType(kind: DbTypeKind.dbPolygon, name: "polygon")
of 628: return DbType(kind: DbTypeKind.dbLine, name: "line")
of 718: return DbType(kind: DbTypeKind.dbCircle, name: "circle")
of 650: return DbType(kind: DbTypeKind.dbInet, name: "cidr")
of 829: return DbType(kind: DbTypeKind.dbMacAddress, name: "macaddr")
of 869: return DbType(kind: DbTypeKind.dbInet, name: "inet")
of 2950: return DbType(kind: DbTypeKind.dbVarchar, name: "uuid")
of 3614: return DbType(kind: DbTypeKind.dbVarchar, name: "tsvector")
of 3615: return DbType(kind: DbTypeKind.dbVarchar, name: "tsquery")
of 2970: return DbType(kind: DbTypeKind.dbVarchar, name: "txid_snapshot")
of 27: return DbType(kind: DbTypeKind.dbComposite, name: "tid")
of 1790: return DbType(kind: DbTypeKind.dbComposite, name: "refcursor")
of 2249: return DbType(kind: DbTypeKind.dbComposite, name: "record")
of 3904: return DbType(kind: DbTypeKind.dbComposite, name: "int4range")
of 3906: return DbType(kind: DbTypeKind.dbComposite, name: "numrange")
of 3908: return DbType(kind: DbTypeKind.dbComposite, name: "tsrange")
of 3910: return DbType(kind: DbTypeKind.dbComposite, name: "tstzrange")
of 3912: return DbType(kind: DbTypeKind.dbComposite, name: "daterange")
of 3926: return DbType(kind: DbTypeKind.dbComposite, name: "int8range")
of 22: return DbType(kind: DbTypeKind.dbArray, name: "int2vector")
of 30: return DbType(kind: DbTypeKind.dbArray, name: "oidvector")
of 143: return DbType(kind: DbTypeKind.dbArray, name: "xml[]")
of 199: return DbType(kind: DbTypeKind.dbArray, name: "json[]")
of 629: return DbType(kind: DbTypeKind.dbArray, name: "line[]")
of 651: return DbType(kind: DbTypeKind.dbArray, name: "cidr[]")
of 719: return DbType(kind: DbTypeKind.dbArray, name: "circle[]")
of 791: return DbType(kind: DbTypeKind.dbArray, name: "money[]")
of 1000: return DbType(kind: DbTypeKind.dbArray, name: "bool[]")
of 1001: return DbType(kind: DbTypeKind.dbArray, name: "bytea[]")
of 1002: return DbType(kind: DbTypeKind.dbArray, name: "char[]")
of 1003: return DbType(kind: DbTypeKind.dbArray, name: "name[]")
of 1005: return DbType(kind: DbTypeKind.dbArray, name: "int2[]")
of 1006: return DbType(kind: DbTypeKind.dbArray, name: "int2vector[]")
of 1007: return DbType(kind: DbTypeKind.dbArray, name: "int4[]")
of 1008: return DbType(kind: DbTypeKind.dbArray, name: "regproc[]")
of 1009: return DbType(kind: DbTypeKind.dbArray, name: "text[]")
of 1028: return DbType(kind: DbTypeKind.dbArray, name: "oid[]")
of 1010: return DbType(kind: DbTypeKind.dbArray, name: "tid[]")
of 1011: return DbType(kind: DbTypeKind.dbArray, name: "xid[]")
of 1012: return DbType(kind: DbTypeKind.dbArray, name: "cid[]")
of 1013: return DbType(kind: DbTypeKind.dbArray, name: "oidvector[]")
of 1014: return DbType(kind: DbTypeKind.dbArray, name: "bpchar[]")
of 1015: return DbType(kind: DbTypeKind.dbArray, name: "varchar[]")
of 1016: return DbType(kind: DbTypeKind.dbArray, name: "int8[]")
of 1017: return DbType(kind: DbTypeKind.dbArray, name: "point[]")
of 1018: return DbType(kind: DbTypeKind.dbArray, name: "lseg[]")
of 1019: return DbType(kind: DbTypeKind.dbArray, name: "path[]")
of 1020: return DbType(kind: DbTypeKind.dbArray, name: "box[]")
of 1021: return DbType(kind: DbTypeKind.dbArray, name: "float4[]")
of 1022: return DbType(kind: DbTypeKind.dbArray, name: "float8[]")
of 1023: return DbType(kind: DbTypeKind.dbArray, name: "abstime[]")
of 1024: return DbType(kind: DbTypeKind.dbArray, name: "reltime[]")
of 1025: return DbType(kind: DbTypeKind.dbArray, name: "tinterval[]")
of 1027: return DbType(kind: DbTypeKind.dbArray, name: "polygon[]")
of 1040: return DbType(kind: DbTypeKind.dbArray, name: "macaddr[]")
of 1041: return DbType(kind: DbTypeKind.dbArray, name: "inet[]")
of 1263: return DbType(kind: DbTypeKind.dbArray, name: "cstring[]")
of 1115: return DbType(kind: DbTypeKind.dbArray, name: "timestamp[]")
of 1182: return DbType(kind: DbTypeKind.dbArray, name: "date[]")
of 1183: return DbType(kind: DbTypeKind.dbArray, name: "time[]")
of 1185: return DbType(kind: DbTypeKind.dbArray, name: "timestamptz[]")
of 1187: return DbType(kind: DbTypeKind.dbArray, name: "interval[]")
of 1231: return DbType(kind: DbTypeKind.dbArray, name: "numeric[]")
of 1270: return DbType(kind: DbTypeKind.dbArray, name: "timetz[]")
of 1561: return DbType(kind: DbTypeKind.dbArray, name: "bit[]")
of 1563: return DbType(kind: DbTypeKind.dbArray, name: "varbit[]")
of 2201: return DbType(kind: DbTypeKind.dbArray, name: "refcursor[]")
of 2951: return DbType(kind: DbTypeKind.dbArray, name: "uuid[]")
of 3643: return DbType(kind: DbTypeKind.dbArray, name: "tsvector[]")
of 3645: return DbType(kind: DbTypeKind.dbArray, name: "tsquery[]")
of 3807: return DbType(kind: DbTypeKind.dbArray, name: "jsonb[]")
of 2949: return DbType(kind: DbTypeKind.dbArray, name: "txid_snapshot[]")
of 3905: return DbType(kind: DbTypeKind.dbArray, name: "int4range[]")
of 3907: return DbType(kind: DbTypeKind.dbArray, name: "numrange[]")
of 3909: return DbType(kind: DbTypeKind.dbArray, name: "tsrange[]")
of 3911: return DbType(kind: DbTypeKind.dbArray, name: "tstzrange[]")
of 3913: return DbType(kind: DbTypeKind.dbArray, name: "daterange[]")
of 3927: return DbType(kind: DbTypeKind.dbArray, name: "int8range[]")
of 2287: return DbType(kind: DbTypeKind.dbArray, name: "record[]")
of 705: return DbType(kind: DbTypeKind.dbUnknown, name: "unknown")
else: return DbType(kind: DbTypeKind.dbUnknown, name: $oid) ## Query the system table pg_type to determine exactly which type is referenced.
proc setColumnInfo(columns: var DbColumns; res: PPGresult, L: int32) =
setLen(columns, L)
for i in 0'i32..<L:
columns[i].name = $pqfname(res, i)
columns[i].typ = getColumnType(res, i)
columns[i].tableName = $(pqftable(res, i)) ## Returns the OID of the table from which the given column was fetched.
## Query the system table pg_class to determine exactly which table is referenced.
#columns[i].primaryKey = libpq does not have a function for that
#columns[i].foreignKey = libpq does not have a function for that
iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
setupSingeRowQuery(db, query, args)
var res: PPGresult = nil
var colsObtained = false
while true:
res = pqgetresult(db)
if not colsObtained:
setColumnInfo(columns, res, pqnfields(res))
colsObtained = true
if res == nil:
break
let status = pqresultStatus(res)
if status == PGRES_TUPLES_OK:
discard
elif status != PGRES_SINGLE_TUPLE:
dbError(db)
else:
yield InstantRow(res: res)
pqclear(res)
proc `[]`*(row: InstantRow; col: int): string {.inline.} =
## returns text for given column of the row
$pqgetvalue(row.res, int32(0), int32(col))
proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} =
## Return cstring of given column of the row
pqgetvalue(row.res, int32(0), int32(index))
proc len*(row: InstantRow): int {.inline.} =
## returns number of columns in the row
int(pqNfields(row.res))
proc getRow(res: PPGresult): Row =
let L = pqnfields(res)
result = newRow(L)
if pqntuples(res) > 0:
setRow(res, result, 0, L)
pqclear(res)
proc getRow*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## retrieves a single row. If the query doesn't return any rows, this proc
## will return a Row with empty strings for each column.
let res = setupQuery(db, query, args)
result = getRow(res)
proc getRow*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
let res = setupQuery(db, stmtName, args)
result = getRow(res)
proc getAllRows(res: PPGresult): seq[Row] =
let N = pqntuples(res)
let L = pqnfields(res)
result = newSeqOfCap[Row](N)
var row = newRow(L)
for i in 0'i32..N-1:
setRow(res, row, i, L)
result.add(row)
pqclear(res)
proc getAllRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): seq[Row] {.
tags: [ReadDbEffect].} =
## executes the query and returns the whole result dataset.
let res = setupQuery(db, query, args)
result = getAllRows(res)
proc getAllRows*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): seq[Row] {.tags:
[ReadDbEffect].} =
## executes the prepared query and returns the whole result dataset.
let res = setupQuery(db, stmtName, args)
result = getAllRows(res)
iterator rows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## same as `fastRows`, but slower and safe.
for r in items(getAllRows(db, query, args)): yield r
iterator rows*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## same as `fastRows`, but slower and safe.
for r in items(getAllRows(db, stmtName, args)): yield r
proc getValue(res: PPGresult): string =
if pqntuples(res) > 0:
var x = pqgetvalue(res, 0, 0)
result = if isNil(x): "" else: $x
else:
result = ""
proc getValue*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): string {.
tags: [ReadDbEffect].} =
## executes the query and returns the first column of the first row of the
## result dataset. Returns "" if the dataset contains no rows or the database
## value is NULL.
let res = setupQuery(db, query, args)
result = getValue(res)
pqclear(res)
proc getValue*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): string {.
tags: [ReadDbEffect].} =
## executes the query and returns the first column of the first row of the
## result dataset. Returns "" if the dataset contains no rows or the database
## value is NULL.
let res = setupQuery(db, stmtName, args)
result = getValue(res)
pqclear(res)
proc tryInsertID*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [WriteDbEffect].}=
## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error. For Postgre this adds
## `RETURNING id` to the query, so it only works if your primary key is
## named `id`.
let res = setupQuery(db, SqlQuery(string(query) & " RETURNING id"),
args)
var x = pqgetvalue(res, 0, 0)
if not isNil(x):
result = parseBiggestInt($x)
else:
result = -1
pqclear(res)
proc insertID*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [WriteDbEffect].} =
## executes the query (typically "INSERT") and returns the
## generated ID for the row. For Postgre this adds
## `RETURNING id` to the query, so it only works if your primary key is
## named `id`.
result = tryInsertID(db, query, args)
if result < 0: dbError(db)
proc tryInsert*(db: DbConn, query: SqlQuery,pkName: string,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], since: (1, 3).}=
## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error.
let res = setupQuery(db, SqlQuery(string(query) & " RETURNING " & pkName),
args)
var x = pqgetvalue(res, 0, 0)
if not isNil(x):
result = parseBiggestInt($x)
else:
result = -1
pqclear(res)
proc insert*(db: DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], since: (1, 3).} =
## executes the query (typically "INSERT") and returns the
## generated ID
result = tryInsert(db, query, pkName, args)
if result < 0: dbError(db)
proc execAffectedRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.tags: [
ReadDbEffect, WriteDbEffect].} =
## executes the query (typically "UPDATE") and returns the
## number of affected rows.
var q = dbFormat(query, args)
var res = pqExec(db, q.cstring)
if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
result = parseBiggestInt($pqcmdTuples(res))
pqclear(res)
proc execAffectedRows*(db: DbConn, stmtName: SqlPrepared,
args: varargs[string, `$`]): int64 {.tags: [
ReadDbEffect, WriteDbEffect].} =
## executes the query (typically "UPDATE") and returns the
## number of affected rows.
var arr = allocCStringArray(args)
var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
nil, nil, 0)
deallocCStringArray(arr)
if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
result = parseBiggestInt($pqcmdTuples(res))
pqclear(res)
proc close*(db: DbConn) {.tags: [DbEffect].} =
## closes the database connection.
if db != nil: pqfinish(db)
proc open*(connection, user, password, database: string): DbConn {.
tags: [DbEffect].} =
## opens a database connection. Raises `EDb` if the connection could not
## be established.
##
## Clients can also use Postgres keyword/value connection strings to
## connect.
##
## Example:
## ```nim
## con = open("", "", "", "host=localhost port=5432 dbname=mydb")
## ```
##
## See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
## for more information.
let
colonPos = connection.find(':')
host = if colonPos < 0: connection
else: substr(connection, 0, colonPos-1)
port = if colonPos < 0: ""
else: substr(connection, colonPos+1)
result = pqsetdbLogin(host.cstring, port.cstring, nil, nil, database, user, password)
if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil
proc setEncoding*(connection: DbConn, encoding: string): bool {.
tags: [DbEffect].} =
## sets the encoding of a database connection, returns true for
## success, false for failure.
return pqsetClientEncoding(connection, encoding) == 0
# Tests are in ../../tests/untestable/tpostgres.

View File

@@ -1,940 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## A higher level `SQLite`:idx: database wrapper. This interface
## is implemented for other databases too.
##
## Basic usage
## ===========
##
## The basic flow of using this module is:
##
## 1. Open database connection
## 2. Execute SQL query
## 3. Close database connection
##
## Parameter substitution
## ----------------------
##
## All `db_*` modules support the same form of parameter substitution.
## That is, using the `?` (question mark) to signify the place where a
## value should be placed. For example:
##
## ```Nim
## sql"INSERT INTO my_table (colA, colB, colC) VALUES (?, ?, ?)"
## ```
##
## Opening a connection to a database
## ----------------------------------
##
## ```Nim
## import std/db_sqlite
##
## # user, password, database name can be empty.
## # These params are not used on db_sqlite module.
## let db = open("mytest.db", "", "", "")
## db.close()
## ```
##
## Creating a table
## ----------------
##
## ```Nim
## db.exec(sql"DROP TABLE IF EXISTS my_table")
## db.exec(sql"""CREATE TABLE my_table (
## id INTEGER,
## name VARCHAR(50) NOT NULL
## )""")
## ```
##
## Inserting data
## --------------
##
## ```Nim
## db.exec(sql"INSERT INTO my_table (id, name) VALUES (0, ?)",
## "Jack")
## ```
##
## Larger example
## --------------
##
## ```Nim
## import std/[db_sqlite, math]
##
## let db = open("mytest.db", "", "", "")
##
## db.exec(sql"DROP TABLE IF EXISTS my_table")
## db.exec(sql"""CREATE TABLE my_table (
## id INTEGER PRIMARY KEY,
## name VARCHAR(50) NOT NULL,
## i INT(11),
## f DECIMAL(18, 10)
## )""")
##
## db.exec(sql"BEGIN")
## for i in 1..1000:
## db.exec(sql"INSERT INTO my_table (name, i, f) VALUES (?, ?, ?)",
## "Item#" & $i, i, sqrt(i.float))
## db.exec(sql"COMMIT")
##
## for x in db.fastRows(sql"SELECT * FROM my_table"):
## echo x
##
## let id = db.tryInsertId(sql"""INSERT INTO my_table (name, i, f)
## VALUES (?, ?, ?)""",
## "Item#1001", 1001, sqrt(1001.0))
## echo "Inserted item: ", db.getValue(sql"SELECT name FROM my_table WHERE id=?", id)
##
## db.close()
## ```
##
## Storing binary data example
##----------------------------
##
## ```nim
## import std/random
##
## ## Generate random float datas
## var orig = newSeq[float64](150)
## randomize()
## for x in orig.mitems:
## x = rand(1.0)/10.0
##
## let db = open("mysqlite.db", "", "", "")
## block: ## Create database
## ## Binary datas needs to be of type BLOB in SQLite
## let createTableStr = sql"""CREATE TABLE test(
## id INTEGER NOT NULL PRIMARY KEY,
## data BLOB
## )
## """
## db.exec(createTableStr)
##
## block: ## Insert data
## var id = 1
## ## Data needs to be converted to seq[byte] to be interpreted as binary by bindParams
## var dbuf = newSeq[byte](orig.len*sizeof(float64))
## copyMem(unsafeAddr(dbuf[0]), unsafeAddr(orig[0]), dbuf.len)
##
## ## Use prepared statement to insert binary data into database
## var insertStmt = db.prepare("INSERT INTO test (id, data) VALUES (?, ?)")
## insertStmt.bindParams(id, dbuf)
## let bres = db.tryExec(insertStmt)
## ## Check insert
## doAssert(bres)
## # Destroy statement
## finalize(insertStmt)
##
## block: ## Use getValue to select data
## var dataTest = db.getValue(sql"SELECT data FROM test WHERE id = ?", 1)
## ## Calculate sequence size from buffer size
## let seqSize = int(dataTest.len*sizeof(byte)/sizeof(float64))
## ## Copy binary string data in dataTest into a seq
## var res: seq[float64] = newSeq[float64](seqSize)
## copyMem(unsafeAddr(res[0]), addr(dataTest[0]), dataTest.len)
##
## ## Check datas obtained is identical
## doAssert res == orig
##
## db.close()
## ```
##
##
## Note
## ====
## This module does not implement any ORM features such as mapping the types from the schema.
## Instead, a `seq[string]` is returned for each row.
##
## The reasoning is as follows:
## 1. it's close to what many DBs offer natively (`char**`:c:)
## 2. it hides the number of types that the DB supports
## (int? int64? decimal up to 10 places? geo coords?)
## 3. it's convenient when all you do is to forward the data to somewhere else (echo, log, put the data into a new query)
##
## See also
## ========
##
## * `db_odbc module <db_odbc.html>`_ for ODBC database wrapper
## * `db_mysql module <db_mysql.html>`_ for MySQL database wrapper
## * `db_postgres module <db_postgres.html>`_ for PostgreSQL database wrapper
{.experimental: "codeReordering".}
import sqlite3, macros
import db_common
export db_common
import std/private/[since, dbutils]
when defined(nimPreviewSlimSystem):
import std/assertions
type
DbConn* = PSqlite3 ## Encapsulates a database connection.
Row* = seq[string] ## A row of a dataset. `NULL` database values will be
## converted to an empty string.
InstantRow* = PStmt ## A handle that can be used to get a row's column
## text on demand.
SqlPrepared* = distinct PStmt ## a identifier for the prepared queries
proc dbError*(db: DbConn) {.noreturn.} =
## Raises a `DbError` exception.
##
## **Examples:**
## ```Nim
## let db = open("mytest.db", "", "", "")
## if not db.tryExec(sql"SELECT * FROM not_exist_table"):
## dbError(db)
## db.close()
## ```
var e: ref DbError
new(e)
e.msg = $sqlite3.errmsg(db)
raise e
proc dbQuote*(s: string): string =
## Escapes the `'` (single quote) char to `''`.
## Because single quote is used for defining `VARCHAR` in SQL.
runnableExamples:
doAssert dbQuote("'") == "''''"
doAssert dbQuote("A Foobar's pen.") == "'A Foobar''s pen.'"
result = "'"
for c in items(s):
if c == '\'': add(result, "''")
else: add(result, c)
add(result, '\'')
proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
dbFormatImpl(formatstr, dbQuote, args)
proc prepare*(db: DbConn; q: string): SqlPrepared {.since: (1, 3).} =
## Creates a new `SqlPrepared` statement.
if prepare_v2(db, q, q.len.cint,result.PStmt, nil) != SQLITE_OK:
discard finalize(result.PStmt)
dbError(db)
proc tryExec*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): bool {.
tags: [ReadDbEffect, WriteDbEffect].} =
## Tries to execute the query and returns `true` if successful, `false` otherwise.
##
## **Examples:**
## ```Nim
## let db = open("mytest.db", "", "", "")
## if not db.tryExec(sql"SELECT * FROM my_table"):
## dbError(db)
## db.close()
## ```
assert(not db.isNil, "Database not connected.")
var q = dbFormat(query, args)
var stmt: sqlite3.PStmt
if prepare_v2(db, q.cstring, q.len.cint, stmt, nil) == SQLITE_OK:
let x = step(stmt)
if x in {SQLITE_DONE, SQLITE_ROW}:
result = finalize(stmt) == SQLITE_OK
else:
discard finalize(stmt)
result = false
proc tryExec*(db: DbConn, stmtName: SqlPrepared): bool {.
tags: [ReadDbEffect, WriteDbEffect].} =
let x = step(stmtName.PStmt)
if x in {SQLITE_DONE, SQLITE_ROW}:
result = true
else:
discard finalize(stmtName.PStmt)
result = false
proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect].} =
## Executes the query and raises a `DbError` exception if not successful.
##
## **Examples:**
## ```Nim
## let db = open("mytest.db", "", "", "")
## try:
## db.exec(sql"INSERT INTO my_table (id, name) VALUES (?, ?)",
## 1, "item#1")
## except:
## stderr.writeLine(getCurrentExceptionMsg())
## finally:
## db.close()
## ```
if not tryExec(db, query, args): dbError(db)
proc newRow(L: int): Row =
newSeq(result, L)
for i in 0..L-1: result[i] = ""
proc setupQuery(db: DbConn, query: SqlQuery,
args: varargs[string]): PStmt =
assert(not db.isNil, "Database not connected.")
var q = dbFormat(query, args)
if prepare_v2(db, q.cstring, q.len.cint, result, nil) != SQLITE_OK: dbError(db)
proc setupQuery(db: DbConn, stmtName: SqlPrepared): SqlPrepared {.since: (1, 3).} =
assert(not db.isNil, "Database not connected.")
result = stmtName
proc setRow(stmt: PStmt, r: var Row, cols: cint) =
for col in 0'i32..cols-1:
let cb = column_bytes(stmt, col)
setLen(r[col], cb) # set capacity
if column_type(stmt, col) == SQLITE_BLOB:
copyMem(addr(r[col][0]), column_blob(stmt, col), cb)
else:
setLen(r[col], 0)
let x = column_text(stmt, col)
if not isNil(x): add(r[col], x)
iterator fastRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## Executes the query and iterates over the result dataset.
##
## This is very fast, but potentially dangerous. Use this iterator only
## if you require **ALL** the rows.
##
## **Note:** Breaking the `fastRows()` iterator during a loop will cause the
## next database query to raise a `DbError` exception `unable to close due
## to ...`.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## for row in db.fastRows(sql"SELECT id, name FROM my_table"):
## echo row
##
## # Output:
## # @["1", "item#1"]
## # @["2", "item#2"]
##
## db.close()
## ```
var stmt = setupQuery(db, query, args)
var L = (column_count(stmt))
var result = newRow(L)
try:
while step(stmt) == SQLITE_ROW:
setRow(stmt, result, L)
yield result
finally:
if finalize(stmt) != SQLITE_OK: dbError(db)
iterator fastRows*(db: DbConn, stmtName: SqlPrepared): Row
{.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
discard setupQuery(db, stmtName)
var L = (column_count(stmtName.PStmt))
var result = newRow(L)
try:
while step(stmtName.PStmt) == SQLITE_ROW:
setRow(stmtName.PStmt, result, L)
yield result
except:
dbError(db)
iterator instantRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
## Similar to `fastRows iterator <#fastRows.i,DbConn,SqlQuery,varargs[string,]>`_
## but returns a handle that can be used to get column text
## on demand using `[]`. Returned handle is valid only within the iterator body.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## for row in db.instantRows(sql"SELECT * FROM my_table"):
## echo "id:" & row[0]
## echo "name:" & row[1]
## echo "length:" & $len(row)
##
## # Output:
## # id:1
## # name:item#1
## # length:2
## # id:2
## # name:item#2
## # length:2
##
## db.close()
## ```
var stmt = setupQuery(db, query, args)
try:
while step(stmt) == SQLITE_ROW:
yield stmt
finally:
if finalize(stmt) != SQLITE_OK: dbError(db)
iterator instantRows*(db: DbConn, stmtName: SqlPrepared): InstantRow
{.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
var stmt = setupQuery(db, stmtName).PStmt
try:
while step(stmt) == SQLITE_ROW:
yield stmt
except:
dbError(db)
proc toTypeKind(t: var DbType; x: int32) =
case x
of SQLITE_INTEGER:
t.kind = dbInt
t.size = 8
of SQLITE_FLOAT:
t.kind = dbFloat
t.size = 8
of SQLITE_BLOB: t.kind = dbBlob
of SQLITE_NULL: t.kind = dbNull
of SQLITE_TEXT: t.kind = dbVarchar
else: t.kind = dbUnknown
proc setColumns(columns: var DbColumns; x: PStmt) =
let L = column_count(x)
setLen(columns, L)
for i in 0'i32 ..< L:
columns[i].name = $column_name(x, i)
columns[i].typ.name = $column_decltype(x, i)
toTypeKind(columns[i].typ, column_type(x, i))
columns[i].tableName = $column_table_name(x, i)
iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [ReadDbEffect].} =
## Similar to `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_,
## but sets information about columns to `columns`.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## var columns: DbColumns
## for row in db.instantRows(columns, sql"SELECT * FROM my_table"):
## discard
## echo columns[0]
##
## # Output:
## # (name: "id", tableName: "my_table", typ: (kind: dbNull,
## # notNull: false, name: "INTEGER", size: 0, maxReprLen: 0, precision: 0,
## # scale: 0, min: 0, max: 0, validValues: @[]), primaryKey: false,
## # foreignKey: false)
##
## db.close()
## ```
var stmt = setupQuery(db, query, args)
setColumns(columns, stmt)
try:
while step(stmt) == SQLITE_ROW:
yield stmt
finally:
if finalize(stmt) != SQLITE_OK: dbError(db)
proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
## Returns text for given column of the row.
##
## See also:
## * `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_
## example code
$column_text(row, col)
proc unsafeColumnAt*(row: InstantRow, index: int32): cstring {.inline.} =
## Returns cstring for given column of the row.
##
## See also:
## * `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_
## example code
column_text(row, index)
proc len*(row: InstantRow): int32 {.inline.} =
## Returns number of columns in a row.
##
## See also:
## * `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_
## example code
column_count(row)
proc getRow*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## Retrieves a single row. If the query doesn't return any rows, this proc
## will return a `Row` with empty strings for each column.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## doAssert db.getRow(sql"SELECT id, name FROM my_table"
## ) == Row(@["1", "item#1"])
## doAssert db.getRow(sql"SELECT id, name FROM my_table WHERE id = ?",
## 2) == Row(@["2", "item#2"])
##
## # Returns empty.
## doAssert db.getRow(sql"INSERT INTO my_table (id, name) VALUES (?, ?)",
## 3, "item#3") == @[]
## doAssert db.getRow(sql"DELETE FROM my_table WHERE id = ?", 3) == @[]
## doAssert db.getRow(sql"UPDATE my_table SET name = 'ITEM#1' WHERE id = ?",
## 1) == @[]
## db.close()
## ```
var stmt = setupQuery(db, query, args)
var L = (column_count(stmt))
result = newRow(L)
if step(stmt) == SQLITE_ROW:
setRow(stmt, result, L)
if finalize(stmt) != SQLITE_OK: dbError(db)
proc getAllRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): seq[Row] {.tags: [ReadDbEffect].} =
## Executes the query and returns the whole result dataset.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## doAssert db.getAllRows(sql"SELECT id, name FROM my_table") == @[Row(@["1", "item#1"]), Row(@["2", "item#2"])]
## db.close()
## ```
result = @[]
for r in fastRows(db, query, args):
result.add(r)
proc getAllRows*(db: DbConn, stmtName: SqlPrepared): seq[Row]
{.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
result = @[]
for r in fastRows(db, stmtName):
result.add(r)
iterator rows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
## Similar to `fastRows iterator <#fastRows.i,DbConn,SqlQuery,varargs[string,]>`_,
## but slower and safe.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## for row in db.rows(sql"SELECT id, name FROM my_table"):
## echo row
##
## ## Output:
## ## @["1", "item#1"]
## ## @["2", "item#2"]
##
## db.close()
## ```
for r in fastRows(db, query, args): yield r
iterator rows*(db: DbConn, stmtName: SqlPrepared): Row
{.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
for r in fastRows(db, stmtName): yield r
proc getValue*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): string {.tags: [ReadDbEffect].} =
## Executes the query and returns the first column of the first row of the
## result dataset. Returns `""` if the dataset contains no rows or the database
## value is `NULL`.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## doAssert db.getValue(sql"SELECT name FROM my_table WHERE id = ?",
## 2) == "item#2"
## doAssert db.getValue(sql"SELECT id, name FROM my_table") == "1"
## doAssert db.getValue(sql"SELECT name, id FROM my_table") == "item#1"
##
## db.close()
## ```
var stmt = setupQuery(db, query, args)
if step(stmt) == SQLITE_ROW:
let cb = column_bytes(stmt, 0)
if cb == 0:
result = ""
else:
if column_type(stmt, 0) == SQLITE_BLOB:
result.setLen(cb)
copyMem(addr(result[0]), column_blob(stmt, 0), cb)
else:
result = newStringOfCap(cb)
add(result, column_text(stmt, 0))
else:
result = ""
if finalize(stmt) != SQLITE_OK: dbError(db)
proc getValue*(db: DbConn, stmtName: SqlPrepared): string
{.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
var stmt = setupQuery(db, stmtName).PStmt
if step(stmt) == SQLITE_ROW:
let cb = column_bytes(stmt, 0)
if cb == 0:
result = ""
else:
if column_type(stmt, 0) == SQLITE_BLOB:
result.setLen(cb)
copyMem(addr(result[0]), column_blob(stmt, 0), cb)
else:
result = newStringOfCap(cb)
add(result, column_text(stmt, 0))
else:
result = ""
proc tryInsertID*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], raises: [DbError].} =
## Executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
## db.exec(sql"CREATE TABLE my_table (id INTEGER, name VARCHAR(50) NOT NULL)")
##
## doAssert db.tryInsertID(sql"INSERT INTO not_exist_table (id, name) VALUES (?, ?)",
## 1, "item#1") == -1
## db.close()
## ```
assert(not db.isNil, "Database not connected.")
var q = dbFormat(query, args)
var stmt: sqlite3.PStmt
result = -1
if prepare_v2(db, q.cstring, q.len.cint, stmt, nil) == SQLITE_OK:
if step(stmt) == SQLITE_DONE:
result = last_insert_rowid(db)
if finalize(stmt) != SQLITE_OK:
result = -1
else:
discard finalize(stmt)
proc insertID*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect].} =
## Executes the query (typically "INSERT") and returns the
## generated ID for the row.
##
## Raises a `DbError` exception when failed to insert row.
## For Postgre this adds `RETURNING id` to the query, so it only works
## if your primary key is named `id`.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
## db.exec(sql"CREATE TABLE my_table (id INTEGER, name VARCHAR(50) NOT NULL)")
##
## for i in 0..2:
## let id = db.insertID(sql"INSERT INTO my_table (id, name) VALUES (?, ?)", i, "item#" & $i)
## echo "LoopIndex = ", i, ", InsertID = ", id
##
## # Output:
## # LoopIndex = 0, InsertID = 1
## # LoopIndex = 1, InsertID = 2
## # LoopIndex = 2, InsertID = 3
##
## db.close()
## ```
result = tryInsertID(db, query, args)
if result < 0: dbError(db)
proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], raises: [DbError], since: (1, 3).} =
## same as tryInsertID
tryInsertID(db, query, args)
proc insert*(db: DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], since: (1, 3).} =
## same as insertId
result = tryInsert(db, query, pkName, args)
if result < 0: dbError(db)
proc execAffectedRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.
tags: [ReadDbEffect, WriteDbEffect].} =
## Executes the query (typically "UPDATE") and returns the
## number of affected rows.
##
## **Examples:**
##
## ```Nim
## let db = open("mytest.db", "", "", "")
##
## # Records of my_table:
## # | id | name |
## # |----|----------|
## # | 1 | item#1 |
## # | 2 | item#2 |
##
## doAssert db.execAffectedRows(sql"UPDATE my_table SET name = 'TEST'") == 2
##
## db.close()
## ```
exec(db, query, args)
result = changes(db)
proc execAffectedRows*(db: DbConn, stmtName: SqlPrepared): int64
{.tags: [ReadDbEffect, WriteDbEffect],since: (1, 3).} =
exec(db, stmtName)
result = changes(db)
proc close*(db: DbConn) {.tags: [DbEffect].} =
## Closes the database connection.
##
## **Examples:**
## ```Nim
## let db = open("mytest.db", "", "", "")
## db.close()
## ```
if sqlite3.close(db) != SQLITE_OK: dbError(db)
proc open*(connection, user, password, database: string): DbConn {.
tags: [DbEffect].} =
## Opens a database connection. Raises a `DbError` exception if the connection
## could not be established.
##
## **Note:** Only the `connection` parameter is used for `sqlite`.
##
## **Examples:**
## ```Nim
## try:
## let db = open("mytest.db", "", "", "")
## ## do something...
## ## db.getAllRows(sql"SELECT * FROM my_table")
## db.close()
## except:
## stderr.writeLine(getCurrentExceptionMsg())
## ```
var db: DbConn
if sqlite3.open(connection, db) == SQLITE_OK:
result = db
else:
dbError(db)
proc setEncoding*(connection: DbConn, encoding: string): bool {.
tags: [DbEffect].} =
## Sets the encoding of a database connection, returns `true` for
## success, `false` for failure.
##
## **Note:** The encoding cannot be changed once it's been set.
## According to SQLite3 documentation, any attempt to change
## the encoding after the database is created will be silently
## ignored.
exec(connection, sql"PRAGMA encoding = ?", [encoding])
result = connection.getValue(sql"PRAGMA encoding") == encoding
proc finalize*(sqlPrepared:SqlPrepared) {.discardable, since: (1, 3).} =
discard finalize(sqlPrepared.PStmt)
template dbBindParamError*(paramIdx: int, val: varargs[untyped]) =
## Raises a `DbError` exception.
var e: ref DbError
new(e)
e.msg = "error binding param in position " & $paramIdx
raise e
proc bindParam*(ps: SqlPrepared, paramIdx: int, val: int32) {.since: (1, 3).} =
## Binds a int32 to the specified paramIndex.
if bind_int(ps.PStmt, paramIdx.int32, val) != SQLITE_OK:
dbBindParamError(paramIdx, val)
proc bindParam*(ps: SqlPrepared, paramIdx: int, val: int64) {.since: (1, 3).} =
## Binds a int64 to the specified paramIndex.
if bind_int64(ps.PStmt, paramIdx.int32, val) != SQLITE_OK:
dbBindParamError(paramIdx, val)
proc bindParam*(ps: SqlPrepared, paramIdx: int, val: int) {.since: (1, 3).} =
## Binds a int to the specified paramIndex.
when sizeof(int) == 8:
bindParam(ps, paramIdx, val.int64)
else:
bindParam(ps, paramIdx, val.int32)
proc bindParam*(ps: SqlPrepared, paramIdx: int, val: float64) {.since: (1, 3).} =
## Binds a 64bit float to the specified paramIndex.
if bind_double(ps.PStmt, paramIdx.int32, val) != SQLITE_OK:
dbBindParamError(paramIdx, val)
proc bindNull*(ps: SqlPrepared, paramIdx: int) {.since: (1, 3).} =
## Sets the bindparam at the specified paramIndex to null
## (default behaviour by sqlite).
if bind_null(ps.PStmt, paramIdx.int32) != SQLITE_OK:
dbBindParamError(paramIdx)
proc bindParam*(ps: SqlPrepared, paramIdx: int, val: string, copy = true) {.since: (1, 3).} =
## Binds a string to the specified paramIndex.
## if copy is true then SQLite makes its own private copy of the data immediately
if bind_text(ps.PStmt, paramIdx.int32, val.cstring, val.len.int32, if copy: SQLITE_TRANSIENT else: SQLITE_STATIC) != SQLITE_OK:
dbBindParamError(paramIdx, val)
proc bindParam*(ps: SqlPrepared, paramIdx: int,val: openArray[byte], copy = true) {.since: (1, 3).} =
## binds a blob to the specified paramIndex.
## if copy is true then SQLite makes its own private copy of the data immediately
let len = val.len
if bind_blob(ps.PStmt, paramIdx.int32, val[0].unsafeAddr, len.int32, if copy: SQLITE_TRANSIENT else: SQLITE_STATIC) != SQLITE_OK:
dbBindParamError(paramIdx, val)
macro bindParams*(ps: SqlPrepared, params: varargs[untyped]): untyped {.since: (1, 3).} =
let bindParam = bindSym("bindParam", brOpen)
let bindNull = bindSym("bindNull")
let preparedStatement = genSym()
result = newStmtList()
# Store `ps` in a temporary variable. This prevents `ps` from being evaluated every call.
result.add newNimNode(nnkLetSection).add(newIdentDefs(preparedStatement, newEmptyNode(), ps))
for idx, param in params:
if param.kind != nnkNilLit:
result.add newCall(bindParam, preparedStatement, newIntLitNode idx + 1, param)
else:
result.add newCall(bindNull, preparedStatement, newIntLitNode idx + 1)
macro untypedLen(args: varargs[untyped]): int =
newLit(args.len)
template exec*(db: DbConn, stmtName: SqlPrepared,
args: varargs[typed]): untyped =
when untypedLen(args) > 0:
if reset(stmtName.PStmt) != SQLITE_OK:
dbError(db)
if clear_bindings(stmtName.PStmt) != SQLITE_OK:
dbError(db)
stmtName.bindParams(args)
if not tryExec(db, stmtName): dbError(db)
when not defined(testing) and isMainModule:
var db = open(":memory:", "", "", "")
exec(db, sql"create table tbl1(one varchar(10), two smallint)", [])
exec(db, sql"insert into tbl1 values('hello!',10)", [])
exec(db, sql"insert into tbl1 values('goodbye', 20)", [])
var p1 = db.prepare "create table tbl2(one varchar(10), two smallint)"
exec(db, p1)
finalize(p1)
var p2 = db.prepare "insert into tbl2 values('hello!',10)"
exec(db, p2)
finalize(p2)
var p3 = db.prepare "insert into tbl2 values('goodbye', 20)"
exec(db, p3)
finalize(p3)
#db.query("create table tbl1(one varchar(10), two smallint)")
#db.query("insert into tbl1 values('hello!',10)")
#db.query("insert into tbl1 values('goodbye', 20)")
for r in db.rows(sql"select * from tbl1", []):
echo(r[0], r[1])
for r in db.instantRows(sql"select * from tbl1", []):
echo(r[0], r[1])
var p4 = db.prepare "select * from tbl2"
for r in db.rows(p4):
echo(r[0], r[1])
finalize(p4)
var i5 = 0
var p5 = db.prepare "select * from tbl2"
for r in db.instantRows(p5):
inc i5
echo(r[0], r[1])
assert i5 == 2
finalize(p5)
for r in db.rows(sql"select * from tbl2", []):
echo(r[0], r[1])
for r in db.instantRows(sql"select * from tbl2", []):
echo(r[0], r[1])
var p6 = db.prepare "select * from tbl2 where one = ? "
p6.bindParams("goodbye")
var rowsP3 = 0
for r in db.rows(p6):
rowsP3 = 1
echo(r[0], r[1])
assert rowsP3 == 1
finalize(p6)
var p7 = db.prepare "select * from tbl2 where two=?"
p7.bindParams(20'i32)
when sizeof(int) == 4:
p7.bindParams(20)
var rowsP = 0
for r in db.rows(p7):
rowsP = 1
echo(r[0], r[1])
assert rowsP == 1
finalize(p7)
exec(db, sql"CREATE TABLE photos(ID INTEGER PRIMARY KEY AUTOINCREMENT, photo BLOB)")
var p8 = db.prepare "INSERT INTO photos (ID,PHOTO) VALUES (?,?)"
var d = "abcdefghijklmnopqrstuvwxyz"
p8.bindParams(1'i32, "abcdefghijklmnopqrstuvwxyz")
exec(db, p8)
finalize(p8)
var p10 = db.prepare "INSERT INTO photos (ID,PHOTO) VALUES (?,?)"
p10.bindParams(2'i32,nil)
exec(db, p10)
exec( db, p10, 3, nil)
finalize(p10)
for r in db.rows(sql"select * from photos where ID = 1", []):
assert r[1].len == d.len
assert r[1] == d
var i6 = 0
for r in db.rows(sql"select * from photos where ID = 3", []):
i6 = 1
assert i6 == 1
var p9 = db.prepare("select * from photos where PHOTO is ?")
p9.bindParams(nil)
var rowsP2 = 0
for r in db.rows(p9):
rowsP2 = 1
echo(r[0], repr r[1])
assert rowsP2 == 1
finalize(p9)
db_sqlite.close(db)

View File

@@ -1,100 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Common datatypes and definitions for all `db_*.nim` (
## `db_mysql <db_mysql.html>`_, `db_postgres <db_postgres.html>`_,
## and `db_sqlite <db_sqlite.html>`_) modules.
type
DbError* = object of IOError ## exception that is raised if a database error occurs
SqlQuery* = distinct string ## an SQL query string
DbEffect* = object of IOEffect ## effect that denotes a database operation
ReadDbEffect* = object of DbEffect ## effect that denotes a read operation
WriteDbEffect* = object of DbEffect ## effect that denotes a write operation
DbTypeKind* = enum ## a superset of datatypes that might be supported.
dbUnknown, ## unknown datatype
dbSerial, ## datatype used for primary auto-increment keys
dbNull, ## datatype used for the NULL value
dbBit, ## bit datatype
dbBool, ## boolean datatype
dbBlob, ## blob datatype
dbFixedChar, ## string of fixed length
dbVarchar, ## string datatype
dbJson, ## JSON datatype
dbXml, ## XML datatype
dbInt, ## some integer type
dbUInt, ## some unsigned integer type
dbDecimal, ## decimal numbers (fixed-point number)
dbFloat, ## some floating point type
dbDate, ## a year-month-day description
dbTime, ## HH:MM:SS information
dbDatetime, ## year-month-day and HH:MM:SS information,
## plus optional time or timezone information
dbTimestamp, ## Timestamp values are stored as the number of seconds
## since the epoch ('1970-01-01 00:00:00' UTC).
dbTimeInterval, ## an interval [a,b] of times
dbEnum, ## some enum
dbSet, ## set of enum values
dbArray, ## an array of values
dbComposite, ## composite type (record, struct, etc)
dbUrl, ## a URL
dbUuid, ## a UUID
dbInet, ## an IP address
dbMacAddress, ## a MAC address
dbGeometry, ## some geometric type
dbPoint, ## Point on a plane (x,y)
dbLine, ## Infinite line ((x1,y1),(x2,y2))
dbLseg, ## Finite line segment ((x1,y1),(x2,y2))
dbBox, ## Rectangular box ((x1,y1),(x2,y2))
dbPath, ## Closed or open path (similar to polygon) ((x1,y1),...)
dbPolygon, ## Polygon (similar to closed path) ((x1,y1),...)
dbCircle, ## Circle <(x,y),r> (center point and radius)
dbUser1, ## user definable datatype 1 (for unknown extensions)
dbUser2, ## user definable datatype 2 (for unknown extensions)
dbUser3, ## user definable datatype 3 (for unknown extensions)
dbUser4, ## user definable datatype 4 (for unknown extensions)
dbUser5 ## user definable datatype 5 (for unknown extensions)
DbType* = object ## describes a database type
kind*: DbTypeKind ## the kind of the described type
notNull*: bool ## does the type contain NULL?
name*: string ## the name of the type
size*: Natural ## the size of the datatype; 0 if of variable size
maxReprLen*: Natural ## maximal length required for the representation
precision*, scale*: Natural ## precision and scale of the number
min*, max*: BiggestInt ## the minimum and maximum of allowed values
validValues*: seq[string] ## valid values of an enum or a set
DbColumn* = object ## information about a database column
name*: string ## name of the column
tableName*: string ## name of the table the column belongs to (optional)
typ*: DbType ## type of the column
primaryKey*: bool ## is this a primary key?
foreignKey*: bool ## is this a foreign key?
DbColumns* = seq[DbColumn]
template sql*(query: string): SqlQuery =
## constructs a SqlQuery from the string `query`. This is supposed to be
## used as a raw-string-literal modifier:
## `sql"update user set counter = counter + 1"`
##
## If assertions are turned off, it does nothing. If assertions are turned
## on, later versions will check the string for valid syntax.
SqlQuery(query)
proc dbError*(msg: string) {.noreturn, noinline.} =
## raises an DbError exception with message `msg`.
var e: ref DbError
new(e)
e.msg = msg
raise e

View File

@@ -1,88 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2016 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Memory tracking support for Nim.
when not defined(memTracker) and not isMainModule:
{.error: "Memory tracking support is turned off!".}
{.push memtracker: off.}
# we import the low level wrapper and are careful not to use Nim's
# memory manager for anything here.
import sqlite3
var
dbHandle: PSqlite3
insertStmt {.threadvar.}: Pstmt
const insertQuery = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
template sbind(x: int; value) =
when value is cstring:
let ret = insertStmt.bindText(x, value, value.len.int32, SQLITE_TRANSIENT)
if ret != SQLITE_OK:
quit "could not bind value"
else:
let ret = insertStmt.bindInt64(x, value)
if ret != SQLITE_OK:
quit "could not bind value"
when defined(memTracker):
proc logEntries(log: TrackLog) {.nimcall, tags: [], gcsafe.} =
if insertStmt.isNil:
if prepare_v2(dbHandle, insertQuery,
insertQuery.len, insertStmt, nil) != SQLITE_OK:
quit "could not bind query to insertStmt " & $sqlite3.errmsg(dbHandle)
for i in 0..log.count-1:
var success = false
let e = log.data[i]
discard sqlite3.reset(insertStmt)
discard clearBindings(insertStmt)
sbind 1, e.op
sbind(2, cast[int](e.address))
sbind 3, e.size
sbind 4, e.file
sbind 5, e.line
if step(insertStmt) == SQLITE_DONE:
success = true
if not success:
quit "could not write to database! " & $sqlite3.errmsg(dbHandle)
proc execQuery(q: string) =
var s: Pstmt
if prepare_v2(dbHandle, q, q.len.int32, s, nil) == SQLITE_OK:
discard step(s)
if finalize(s) != SQLITE_OK:
quit "could not finalize " & $sqlite3.errmsg(dbHandle)
else:
quit "could not prepare statement " & $sqlite3.errmsg(dbHandle)
proc setupDb() =
execQuery """create table if not exists tracking(
id integer primary key,
op varchar not null,
address integer not null,
size integer not null,
file varchar not null,
line integer not null
)"""
execQuery "delete from tracking"
if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK:
setupDb()
const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
if prepare_v2(dbHandle, insertQuery,
insertQuery.len, insertStmt, nil) == SQLITE_OK:
when defined(memTracker):
setTrackLogger logEntries
else:
quit "could not prepare statement B " & $sqlite3.errmsg(dbHandle)
else:
quit "could not setup sqlite " & $sqlite3.errmsg(dbHandle)
{.pop.}

View File

@@ -1,209 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2016 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Implements a representation of Unicode with the limited
## ASCII character subset.
import strutils
import unicode
# issue #3045
const
Base = 36
TMin = 1
TMax = 26
Skew = 38
Damp = 700
InitialBias = 72
InitialN = 128
Delimiter = '-'
type
PunyError* = object of ValueError
func decodeDigit(x: char): int {.raises: [PunyError].} =
if '0' <= x and x <= '9':
result = ord(x) - (ord('0') - 26)
elif 'A' <= x and x <= 'Z':
result = ord(x) - ord('A')
elif 'a' <= x and x <= 'z':
result = ord(x) - ord('a')
else:
raise newException(PunyError, "Bad input")
func encodeDigit(digit: int): Rune {.raises: [PunyError].} =
if 0 <= digit and digit < 26:
result = Rune(digit + ord('a'))
elif 26 <= digit and digit < 36:
result = Rune(digit + (ord('0') - 26))
else:
raise newException(PunyError, "internal error in punycode encoding")
func isBasic(c: char): bool = ord(c) < 0x80
func isBasic(r: Rune): bool = int(r) < 0x80
func adapt(delta, numPoints: int, first: bool): int =
var d = if first: delta div Damp else: delta div 2
d += d div numPoints
var k = 0
while d > ((Base-TMin)*TMax) div 2:
d = d div (Base - TMin)
k += Base
result = k + (Base - TMin + 1) * d div (d + Skew)
func encode*(prefix, s: string): string {.raises: [PunyError].} =
## Encode a string that may contain Unicode.
## Prepend `prefix` to the result
result = prefix
var (d, n, bias) = (0, InitialN, InitialBias)
var (b, remaining) = (0, 0)
for r in s.runes:
if r.isBasic:
# basic Ascii character
inc b
result.add($r)
else:
# special character
inc remaining
var h = b
if b > 0:
result.add(Delimiter) # we have some Ascii chars
while remaining != 0:
var m: int = high(int32)
for r in s.runes:
if m > int(r) and int(r) >= n:
m = int(r)
d += (m - n) * (h + 1)
if d < 0:
raise newException(PunyError, "invalid label " & s)
n = m
for r in s.runes:
if int(r) < n:
inc d
if d < 0:
raise newException(PunyError, "invalid label " & s)
continue
if int(r) > n:
continue
var q = d
var k = Base
while true:
var t = k - bias
if t < TMin:
t = TMin
elif t > TMax:
t = TMax
if q < t:
break
result.add($encodeDigit(t + (q - t) mod (Base - t)))
q = (q - t) div (Base - t)
k += Base
result.add($encodeDigit(q))
bias = adapt(d, h + 1, h == b)
d = 0
inc h
dec remaining
inc d
inc n
func encode*(s: string): string {.raises: [PunyError].} =
## Encode a string that may contain Unicode. Prefix is empty.
result = encode("", s)
func decode*(encoded: string): string {.raises: [PunyError].} =
## Decode a Punycode-encoded string
var
n = InitialN
i = 0
bias = InitialBias
var d = rfind(encoded, Delimiter)
var output: seq[Rune]
if d > 0:
# found Delimiter
for j in 0..<d:
var c = encoded[j] # char
if not c.isBasic:
raise newException(PunyError, "Encoded contains a non-basic char")
output.add(Rune(c)) # add the character
inc d
else:
d = 0 # set to first index
while (d < len(encoded)):
var oldi = i
var w = 1
var k = Base
while true:
if d == len(encoded):
raise newException(PunyError, "Bad input: " & encoded)
var c = encoded[d]; inc d
var digit = int(decodeDigit(c))
if digit > (high(int32) - i) div w:
raise newException(PunyError, "Too large a value: " & $digit)
i += digit * w
var t: int
if k <= bias:
t = TMin
elif k >= bias + TMax:
t = TMax
else:
t = k - bias
if digit < t:
break
w *= Base - t
k += Base
bias = adapt(i - oldi, len(output) + 1, oldi == 0)
if i div (len(output) + 1) > high(int32) - n:
raise newException(PunyError, "Value too large")
n += i div (len(output) + 1)
i = i mod (len(output) + 1)
insert(output, Rune(n), i)
inc i
result = $output
runnableExamples:
static:
block:
doAssert encode("") == ""
doAssert encode("a") == "a-"
doAssert encode("A") == "A-"
doAssert encode("3") == "3-"
doAssert encode("-") == "--"
doAssert encode("--") == "---"
doAssert encode("abc") == "abc-"
doAssert encode("London") == "London-"
doAssert encode("Lloyd-Atkinson") == "Lloyd-Atkinson-"
doAssert encode("This has spaces") == "This has spaces-"
doAssert encode("ü") == "tda"
doAssert encode("München") == "Mnchen-3ya"
doAssert encode("Mnchen-3ya") == "Mnchen-3ya-"
doAssert encode("München-Ost") == "Mnchen-Ost-9db"
doAssert encode("Bahnhof München-Ost") == "Bahnhof Mnchen-Ost-u6b"
block:
doAssert decode("") == ""
doAssert decode("a-") == "a"
doAssert decode("A-") == "A"
doAssert decode("3-") == "3"
doAssert decode("--") == "-"
doAssert decode("---") == "--"
doAssert decode("abc-") == "abc"
doAssert decode("London-") == "London"
doAssert decode("Lloyd-Atkinson-") == "Lloyd-Atkinson"
doAssert decode("This has spaces-") == "This has spaces"
doAssert decode("tda") == "ü"
doAssert decode("Mnchen-3ya") == "München"
doAssert decode("Mnchen-3ya-") == "Mnchen-3ya"
doAssert decode("Mnchen-Ost-9db") == "München-Ost"
doAssert decode("Bahnhof Mnchen-Ost-u6b") == "Bahnhof München-Ost"

View File

@@ -1,15 +0,0 @@
import db_common
template dbFormatImpl*(formatstr: SqlQuery, dbQuote: proc (s: string): string, args: varargs[string]): string =
var res = ""
var a = 0
for c in items(string(formatstr)):
if c == '?':
if a == args.len:
dbError("""The number of "?" given exceeds the number of parameters present in the query.""")
add(res, dbQuote(args[a]))
inc(a)
else:
add(res, c)
res

File diff suppressed because it is too large Load Diff

View File

@@ -1,844 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
when defined(nimPreviewSlimSystem):
import std/widestrs
when not defined(ODBCVER):
const
ODBCVER = 0x0351 ## define ODBC version 3.51 by default
when defined(windows):
{.push callconv: stdcall.}
const odbclib = "odbc32.dll"
else:
{.push callconv: cdecl.}
const odbclib = "libodbc.so"
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
# DATA TYPES CORRESPONDENCE
# BDE fields ODBC types
# ---------- ------------------
# ftBlob SQL_BINARY
# ftBoolean SQL_BIT
# ftDate SQL_TYPE_DATE
# ftTime SQL_TYPE_TIME
# ftDateTime SQL_TYPE_TIMESTAMP
# ftInteger SQL_INTEGER
# ftSmallint SQL_SMALLINT
# ftFloat SQL_DOUBLE
# ftString SQL_CHAR
# ftMemo SQL_BINARY // SQL_VARCHAR
#
type
TSqlChar* = char
TSqlSmallInt* = int16
SqlUSmallInt* = int16
SqlHandle* = pointer
SqlHEnv* = SqlHandle
SqlHDBC* = SqlHandle
SqlHStmt* = SqlHandle
SqlHDesc* = SqlHandle
TSqlInteger* = int32
SqlUInteger* = int32
TSqlLen* = int
TSqlULen* = uint
SqlPointer* = pointer
TSqlReal* = cfloat
TSqlDouble* = cdouble
TSqlFloat* = cdouble
SqlHWND* = pointer
PSQLCHAR* = cstring
PSQLINTEGER* = ptr TSqlInteger
PSQLUINTEGER* = ptr SqlUInteger
PSQLSMALLINT* = ptr TSqlSmallInt
PSQLUSMALLINT* = ptr SqlUSmallInt
PSQLREAL* = ptr TSqlReal
PSQLDOUBLE* = ptr TSqlDouble
PSQLFLOAT* = ptr TSqlFloat
PSQLHANDLE* = ptr SqlHandle
const # SQL data type codes
SQL_UNKNOWN_TYPE* = 0
SQL_LONGVARCHAR* = (- 1)
SQL_BINARY* = (- 2)
SQL_VARBINARY* = (- 3)
SQL_LONGVARBINARY* = (- 4)
SQL_BIGINT* = (- 5)
SQL_TINYINT* = (- 6)
SQL_BIT* = (- 7)
SQL_WCHAR* = (- 8)
SQL_WVARCHAR* = (- 9)
SQL_WLONGVARCHAR* = (- 10)
SQL_CHAR* = 1
SQL_NUMERIC* = 2
SQL_DECIMAL* = 3
SQL_INTEGER* = 4
SQL_SMALLINT* = 5
SQL_FLOAT* = 6
SQL_REAL* = 7
SQL_DOUBLE* = 8
SQL_DATETIME* = 9
SQL_VARCHAR* = 12
SQL_TYPE_DATE* = 91
SQL_TYPE_TIME* = 92
SQL_TYPE_TIMESTAMP* = 93
SQL_DATE* = 9
SQL_TIME* = 10
SQL_TIMESTAMP* = 11
SQL_INTERVAL* = 10
SQL_GUID* = - 11 # interval codes
when ODBCVER >= 0x0300:
const
SQL_CODE_YEAR* = 1
SQL_CODE_MONTH* = 2
SQL_CODE_DAY* = 3
SQL_CODE_HOUR* = 4
SQL_CODE_MINUTE* = 5
SQL_CODE_SECOND* = 6
SQL_CODE_YEAR_TO_MONTH* = 7
SQL_CODE_DAY_TO_HOUR* = 8
SQL_CODE_DAY_TO_MINUTE* = 9
SQL_CODE_DAY_TO_SECOND* = 10
SQL_CODE_HOUR_TO_MINUTE* = 11
SQL_CODE_HOUR_TO_SECOND* = 12
SQL_CODE_MINUTE_TO_SECOND* = 13
SQL_INTERVAL_YEAR* = 100 + SQL_CODE_YEAR
SQL_INTERVAL_MONTH* = 100 + SQL_CODE_MONTH
SQL_INTERVAL_DAY* = 100 + SQL_CODE_DAY
SQL_INTERVAL_HOUR* = 100 + SQL_CODE_HOUR
SQL_INTERVAL_MINUTE* = 100 + SQL_CODE_MINUTE
SQL_INTERVAL_SECOND* = 100 + SQL_CODE_SECOND
SQL_INTERVAL_YEAR_TO_MONTH* = 100 + SQL_CODE_YEAR_TO_MONTH
SQL_INTERVAL_DAY_TO_HOUR* = 100 + SQL_CODE_DAY_TO_HOUR
SQL_INTERVAL_DAY_TO_MINUTE* = 100 + SQL_CODE_DAY_TO_MINUTE
SQL_INTERVAL_DAY_TO_SECOND* = 100 + SQL_CODE_DAY_TO_SECOND
SQL_INTERVAL_HOUR_TO_MINUTE* = 100 + SQL_CODE_HOUR_TO_MINUTE
SQL_INTERVAL_HOUR_TO_SECOND* = 100 + SQL_CODE_HOUR_TO_SECOND
SQL_INTERVAL_MINUTE_TO_SECOND* = 100 + SQL_CODE_MINUTE_TO_SECOND
else:
const
SQL_INTERVAL_YEAR* = - 80
SQL_INTERVAL_MONTH* = - 81
SQL_INTERVAL_YEAR_TO_MONTH* = - 82
SQL_INTERVAL_DAY* = - 83
SQL_INTERVAL_HOUR* = - 84
SQL_INTERVAL_MINUTE* = - 85
SQL_INTERVAL_SECOND* = - 86
SQL_INTERVAL_DAY_TO_HOUR* = - 87
SQL_INTERVAL_DAY_TO_MINUTE* = - 88
SQL_INTERVAL_DAY_TO_SECOND* = - 89
SQL_INTERVAL_HOUR_TO_MINUTE* = - 90
SQL_INTERVAL_HOUR_TO_SECOND* = - 91
SQL_INTERVAL_MINUTE_TO_SECOND* = - 92
when ODBCVER < 0x0300:
const
SQL_UNICODE* = - 95
SQL_UNICODE_VARCHAR* = - 96
SQL_UNICODE_LONGVARCHAR* = - 97
SQL_UNICODE_CHAR* = SQL_UNICODE
else:
# The previous definitions for SQL_UNICODE_ are historical and obsolete
const
SQL_UNICODE* = SQL_WCHAR
SQL_UNICODE_VARCHAR* = SQL_WVARCHAR
SQL_UNICODE_LONGVARCHAR* = SQL_WLONGVARCHAR
SQL_UNICODE_CHAR* = SQL_WCHAR
const # C datatype to SQL datatype mapping
SQL_C_CHAR* = SQL_CHAR
SQL_C_LONG* = SQL_INTEGER
SQL_C_SHORT* = SQL_SMALLINT
SQL_C_FLOAT* = SQL_REAL
SQL_C_DOUBLE* = SQL_DOUBLE
SQL_C_NUMERIC* = SQL_NUMERIC
SQL_C_DEFAULT* = 99
SQL_SIGNED_OFFSET* = - 20
SQL_UNSIGNED_OFFSET* = - 22
SQL_C_DATE* = SQL_DATE
SQL_C_TIME* = SQL_TIME
SQL_C_TIMESTAMP* = SQL_TIMESTAMP
SQL_C_TYPE_DATE* = SQL_TYPE_DATE
SQL_C_TYPE_TIME* = SQL_TYPE_TIME
SQL_C_TYPE_TIMESTAMP* = SQL_TYPE_TIMESTAMP
SQL_C_INTERVAL_YEAR* = SQL_INTERVAL_YEAR
SQL_C_INTERVAL_MONTH* = SQL_INTERVAL_MONTH
SQL_C_INTERVAL_DAY* = SQL_INTERVAL_DAY
SQL_C_INTERVAL_HOUR* = SQL_INTERVAL_HOUR
SQL_C_INTERVAL_MINUTE* = SQL_INTERVAL_MINUTE
SQL_C_INTERVAL_SECOND* = SQL_INTERVAL_SECOND
SQL_C_INTERVAL_YEAR_TO_MONTH* = SQL_INTERVAL_YEAR_TO_MONTH
SQL_C_INTERVAL_DAY_TO_HOUR* = SQL_INTERVAL_DAY_TO_HOUR
SQL_C_INTERVAL_DAY_TO_MINUTE* = SQL_INTERVAL_DAY_TO_MINUTE
SQL_C_INTERVAL_DAY_TO_SECOND* = SQL_INTERVAL_DAY_TO_SECOND
SQL_C_INTERVAL_HOUR_TO_MINUTE* = SQL_INTERVAL_HOUR_TO_MINUTE
SQL_C_INTERVAL_HOUR_TO_SECOND* = SQL_INTERVAL_HOUR_TO_SECOND
SQL_C_INTERVAL_MINUTE_TO_SECOND* = SQL_INTERVAL_MINUTE_TO_SECOND
SQL_C_BINARY* = SQL_BINARY
SQL_C_BIT* = SQL_BIT
SQL_C_SBIGINT* = SQL_BIGINT + SQL_SIGNED_OFFSET # SIGNED BIGINT
SQL_C_UBIGINT* = SQL_BIGINT + SQL_UNSIGNED_OFFSET # UNSIGNED BIGINT
SQL_C_TINYINT* = SQL_TINYINT
SQL_C_SLONG* = SQL_C_LONG + SQL_SIGNED_OFFSET # SIGNED INTEGER
SQL_C_SSHORT* = SQL_C_SHORT + SQL_SIGNED_OFFSET # SIGNED SMALLINT
SQL_C_STINYINT* = SQL_TINYINT + SQL_SIGNED_OFFSET # SIGNED TINYINT
SQL_C_ULONG* = SQL_C_LONG + SQL_UNSIGNED_OFFSET # UNSIGNED INTEGER
SQL_C_USHORT* = SQL_C_SHORT + SQL_UNSIGNED_OFFSET # UNSIGNED SMALLINT
SQL_C_UTINYINT* = SQL_TINYINT + SQL_UNSIGNED_OFFSET # UNSIGNED TINYINT
SQL_C_BOOKMARK* = SQL_C_ULONG # BOOKMARK
SQL_C_GUID* = SQL_GUID
SQL_TYPE_NULL* = 0
when ODBCVER < 0x0300:
const
SQL_TYPE_MIN* = SQL_BIT
SQL_TYPE_MAX* = SQL_VARCHAR
const
SQL_C_VARBOOKMARK* = SQL_C_BINARY
SQL_API_SQLDESCRIBEPARAM* = 58
SQL_NO_TOTAL* = - 4
type
SQL_DATE_STRUCT* {.final, pure.} = object
Year*: TSqlSmallInt
Month*: SqlUSmallInt
Day*: SqlUSmallInt
PSQL_DATE_STRUCT* = ptr SQL_DATE_STRUCT
SQL_TIME_STRUCT* {.final, pure.} = object
Hour*: SqlUSmallInt
Minute*: SqlUSmallInt
Second*: SqlUSmallInt
PSQL_TIME_STRUCT* = ptr SQL_TIME_STRUCT
SQL_TIMESTAMP_STRUCT* {.final, pure.} = object
Year*: SqlUSmallInt
Month*: SqlUSmallInt
Day*: SqlUSmallInt
Hour*: SqlUSmallInt
Minute*: SqlUSmallInt
Second*: SqlUSmallInt
Fraction*: SqlUInteger
PSQL_TIMESTAMP_STRUCT* = ptr SQL_TIMESTAMP_STRUCT
const
SQL_NAME_LEN* = 128
SQL_OV_ODBC3* = 3
SQL_OV_ODBC2* = 2
SQL_ATTR_ODBC_VERSION* = 200 # Options for SQLDriverConnect
SQL_DRIVER_NOPROMPT* = 0
SQL_DRIVER_COMPLETE* = 1
SQL_DRIVER_PROMPT* = 2
SQL_DRIVER_COMPLETE_REQUIRED* = 3
SQL_IS_POINTER* = (- 4) # whether an attribute is a pointer or not
SQL_IS_UINTEGER* = (- 5)
SQL_IS_INTEGER* = (- 6)
SQL_IS_USMALLINT* = (- 7)
SQL_IS_SMALLINT* = (- 8) # SQLExtendedFetch "fFetchType" values
SQL_FETCH_BOOKMARK* = 8
SQL_SCROLL_OPTIONS* = 44 # SQL_USE_BOOKMARKS options
SQL_UB_OFF* = 0
SQL_UB_ON* = 1
SQL_UB_DEFAULT* = SQL_UB_OFF
SQL_UB_FIXED* = SQL_UB_ON
SQL_UB_VARIABLE* = 2 # SQL_SCROLL_OPTIONS masks
SQL_SO_FORWARD_ONLY* = 0x00000001
SQL_SO_KEYSET_DRIVEN* = 0x00000002
SQL_SO_DYNAMIC* = 0x00000004
SQL_SO_MIXED* = 0x00000008
SQL_SO_STATIC* = 0x00000010
SQL_BOOKMARK_PERSISTENCE* = 82
SQL_STATIC_SENSITIVITY* = 83 # SQL_BOOKMARK_PERSISTENCE values
SQL_BP_CLOSE* = 0x00000001
SQL_BP_DELETE* = 0x00000002
SQL_BP_DROP* = 0x00000004
SQL_BP_TRANSACTION* = 0x00000008
SQL_BP_UPDATE* = 0x00000010
SQL_BP_OTHER_HSTMT* = 0x00000020
SQL_BP_SCROLL* = 0x00000040
SQL_DYNAMIC_CURSOR_ATTRIBUTES1* = 144
SQL_DYNAMIC_CURSOR_ATTRIBUTES2* = 145
SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1* = 146
SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2* = 147
SQL_INDEX_KEYWORDS* = 148
SQL_INFO_SCHEMA_VIEWS* = 149
SQL_KEYSET_CURSOR_ATTRIBUTES1* = 150
SQL_KEYSET_CURSOR_ATTRIBUTES2* = 151
SQL_STATIC_CURSOR_ATTRIBUTES1* = 167
SQL_STATIC_CURSOR_ATTRIBUTES2* = 168 # supported SQLFetchScroll FetchOrientation's
SQL_CA1_NEXT* = 1
SQL_CA1_ABSOLUTE* = 2
SQL_CA1_RELATIVE* = 4
SQL_CA1_BOOKMARK* = 8 # supported SQLSetPos LockType's
SQL_CA1_LOCK_NO_CHANGE* = 0x00000040
SQL_CA1_LOCK_EXCLUSIVE* = 0x00000080
SQL_CA1_LOCK_UNLOCK* = 0x00000100 # supported SQLSetPos Operations
SQL_CA1_POS_POSITION* = 0x00000200
SQL_CA1_POS_UPDATE* = 0x00000400
SQL_CA1_POS_DELETE* = 0x00000800
SQL_CA1_POS_REFRESH* = 0x00001000 # positioned updates and deletes
SQL_CA1_POSITIONED_UPDATE* = 0x00002000
SQL_CA1_POSITIONED_DELETE* = 0x00004000
SQL_CA1_SELECT_FOR_UPDATE* = 0x00008000 # supported SQLBulkOperations operations
SQL_CA1_BULK_ADD* = 0x00010000
SQL_CA1_BULK_UPDATE_BY_BOOKMARK* = 0x00020000
SQL_CA1_BULK_DELETE_BY_BOOKMARK* = 0x00040000
SQL_CA1_BULK_FETCH_BY_BOOKMARK* = 0x00080000 # supported values for SQL_ATTR_SCROLL_CONCURRENCY
SQL_CA2_READ_ONLY_CONCURRENCY* = 1
SQL_CA2_LOCK_CONCURRENCY* = 2
SQL_CA2_OPT_ROWVER_CONCURRENCY* = 4
SQL_CA2_OPT_VALUES_CONCURRENCY* = 8 # sensitivity of the cursor to its own inserts, deletes, and updates
SQL_CA2_SENSITIVITY_ADDITIONS* = 0x00000010
SQL_CA2_SENSITIVITY_DELETIONS* = 0x00000020
SQL_CA2_SENSITIVITY_UPDATES* = 0x00000040 # semantics of SQL_ATTR_MAX_ROWS
SQL_CA2_MAX_ROWS_SELECT* = 0x00000080
SQL_CA2_MAX_ROWS_INSERT* = 0x00000100
SQL_CA2_MAX_ROWS_DELETE* = 0x00000200
SQL_CA2_MAX_ROWS_UPDATE* = 0x00000400
SQL_CA2_MAX_ROWS_CATALOG* = 0x00000800
SQL_CA2_MAX_ROWS_AFFECTS_ALL* = (SQL_CA2_MAX_ROWS_SELECT or
SQL_CA2_MAX_ROWS_INSERT or SQL_CA2_MAX_ROWS_DELETE or
SQL_CA2_MAX_ROWS_UPDATE or SQL_CA2_MAX_ROWS_CATALOG) # semantics of
# SQL_DIAG_CURSOR_ROW_COUNT
SQL_CA2_CRC_EXACT* = 0x00001000
SQL_CA2_CRC_APPROXIMATE* = 0x00002000 # the kinds of positioned statements that can be simulated
SQL_CA2_SIMULATE_NON_UNIQUE* = 0x00004000
SQL_CA2_SIMULATE_TRY_UNIQUE* = 0x00008000
SQL_CA2_SIMULATE_UNIQUE* = 0x00010000 # Operations in SQLBulkOperations
SQL_ADD* = 4
SQL_SETPOS_MAX_OPTION_VALUE* = SQL_ADD
SQL_UPDATE_BY_BOOKMARK* = 5
SQL_DELETE_BY_BOOKMARK* = 6
SQL_FETCH_BY_BOOKMARK* = 7 # Operations in SQLSetPos
SQL_POSITION* = 0
SQL_REFRESH* = 1
SQL_UPDATE* = 2
SQL_DELETE* = 3 # Lock options in SQLSetPos
SQL_LOCK_NO_CHANGE* = 0
SQL_LOCK_EXCLUSIVE* = 1
SQL_LOCK_UNLOCK* = 2 # SQLExtendedFetch "rgfRowStatus" element values
SQL_ROW_SUCCESS* = 0
SQL_ROW_DELETED* = 1
SQL_ROW_UPDATED* = 2
SQL_ROW_NOROW* = 3
SQL_ROW_ADDED* = 4
SQL_ROW_ERROR* = 5
SQL_ROW_SUCCESS_WITH_INFO* = 6
SQL_ROW_PROCEED* = 0
SQL_ROW_IGNORE* = 1
SQL_MAX_DSN_LENGTH* = 32 # maximum data source name size
SQL_MAX_OPTION_STRING_LENGTH* = 256
SQL_ODBC_CURSORS* = 110
SQL_ATTR_ODBC_CURSORS* = SQL_ODBC_CURSORS # SQL_ODBC_CURSORS options
SQL_CUR_USE_IF_NEEDED* = 0
SQL_CUR_USE_ODBC* = 1
SQL_CUR_USE_DRIVER* = 2
SQL_CUR_DEFAULT* = SQL_CUR_USE_DRIVER
SQL_PARAM_TYPE_UNKNOWN* = 0
SQL_PARAM_INPUT* = 1
SQL_PARAM_INPUT_OUTPUT* = 2
SQL_RESULT_COL* = 3
SQL_PARAM_OUTPUT* = 4
SQL_RETURN_VALUE* = 5 # special length/indicator values
SQL_NULL_DATA* = (- 1)
SQL_DATA_AT_EXEC* = (- 2)
SQL_SUCCESS* = 0
SQL_SUCCESS_WITH_INFO* = 1
SQL_NO_DATA* = 100
SQL_ERROR* = (- 1)
SQL_INVALID_HANDLE* = (- 2)
SQL_STILL_EXECUTING* = 2
SQL_NEED_DATA* = 99 # flags for null-terminated string
SQL_NTS* = (- 3) # maximum message length
SQL_MAX_MESSAGE_LENGTH* = 512 # date/time length constants
SQL_DATE_LEN* = 10
SQL_TIME_LEN* = 8 # add P+1 if precision is nonzero
SQL_TIMESTAMP_LEN* = 19 # add P+1 if precision is nonzero
# handle type identifiers
SQL_HANDLE_ENV* = 1
SQL_HANDLE_DBC* = 2
SQL_HANDLE_STMT* = 3
SQL_HANDLE_DESC* = 4 # environment attribute
SQL_ATTR_OUTPUT_NTS* = 10001 # connection attributes
SQL_ATTR_AUTO_IPD* = 10001
SQL_ATTR_METADATA_ID* = 10014 # statement attributes
SQL_ATTR_APP_ROW_DESC* = 10010
SQL_ATTR_APP_PARAM_DESC* = 10011
SQL_ATTR_IMP_ROW_DESC* = 10012
SQL_ATTR_IMP_PARAM_DESC* = 10013
SQL_ATTR_CURSOR_SCROLLABLE* = (- 1)
SQL_ATTR_CURSOR_SENSITIVITY* = (- 2)
SQL_QUERY_TIMEOUT* = 0
SQL_MAX_ROWS* = 1
SQL_NOSCAN* = 2
SQL_MAX_LENGTH* = 3
SQL_ASYNC_ENABLE* = 4 # same as SQL_ATTR_ASYNC_ENABLE */
SQL_BIND_TYPE* = 5
SQL_CURSOR_TYPE* = 6
SQL_CONCURRENCY* = 7
SQL_KEYSET_SIZE* = 8
SQL_ROWSET_SIZE* = 9
SQL_SIMULATE_CURSOR* = 10
SQL_RETRIEVE_DATA* = 11
SQL_USE_BOOKMARKS* = 12
SQL_GET_BOOKMARK* = 13 # GetStmtOption Only */
SQL_ROW_NUMBER* = 14 # GetStmtOption Only */
SQL_ATTR_CURSOR_TYPE* = SQL_CURSOR_TYPE
SQL_ATTR_CONCURRENCY* = SQL_CONCURRENCY
SQL_ATTR_FETCH_BOOKMARK_PTR* = 16
SQL_ATTR_ROW_STATUS_PTR* = 25
SQL_ATTR_ROWS_FETCHED_PTR* = 26
SQL_AUTOCOMMIT* = 102
SQL_ATTR_AUTOCOMMIT* = SQL_AUTOCOMMIT
SQL_ATTR_ROW_NUMBER* = SQL_ROW_NUMBER
SQL_TXN_ISOLATION* = 108
SQL_ATTR_TXN_ISOLATION* = SQL_TXN_ISOLATION
SQL_ATTR_MAX_ROWS* = SQL_MAX_ROWS
SQL_ATTR_USE_BOOKMARKS* = SQL_USE_BOOKMARKS #* connection attributes */
SQL_ACCESS_MODE* = 101 # SQL_AUTOCOMMIT =102;
SQL_LOGIN_TIMEOUT* = 103
SQL_OPT_TRACE* = 104
SQL_OPT_TRACEFILE* = 105
SQL_TRANSLATE_DLL* = 106
SQL_TRANSLATE_OPTION* = 107 # SQL_TXN_ISOLATION =108;
SQL_CURRENT_QUALIFIER* = 109 # SQL_ODBC_CURSORS =110;
SQL_QUIET_MODE* = 111
SQL_PACKET_SIZE* = 112 #* connection attributes with new names */
SQL_ATTR_ACCESS_MODE* = SQL_ACCESS_MODE # SQL_ATTR_AUTOCOMMIT =SQL_AUTOCOMMIT;
SQL_ATTR_CONNECTION_DEAD* = 1209 #* GetConnectAttr only */
SQL_ATTR_CONNECTION_TIMEOUT* = 113
SQL_ATTR_CURRENT_CATALOG* = SQL_CURRENT_QUALIFIER
SQL_ATTR_DISCONNECT_BEHAVIOR* = 114
SQL_ATTR_ENLIST_IN_DTC* = 1207
SQL_ATTR_ENLIST_IN_XA* = 1208
SQL_ATTR_LOGIN_TIMEOUT* = SQL_LOGIN_TIMEOUT # SQL_ATTR_ODBC_CURSORS =SQL_ODBC_CURSORS;
SQL_ATTR_PACKET_SIZE* = SQL_PACKET_SIZE
SQL_ATTR_QUIET_MODE* = SQL_QUIET_MODE
SQL_ATTR_TRACE* = SQL_OPT_TRACE
SQL_ATTR_TRACEFILE* = SQL_OPT_TRACEFILE
SQL_ATTR_TRANSLATE_LIB* = SQL_TRANSLATE_DLL
SQL_ATTR_TRANSLATE_OPTION* = SQL_TRANSLATE_OPTION # SQL_ATTR_TXN_ISOLATION =SQL_TXN_ISOLATION;
#* SQL_ACCESS_MODE options */
SQL_MODE_READ_WRITE* = 0
SQL_MODE_READ_ONLY* = 1
SQL_MODE_DEFAULT* = SQL_MODE_READ_WRITE #* SQL_AUTOCOMMIT options */
SQL_AUTOCOMMIT_OFF* = 0
SQL_AUTOCOMMIT_ON* = 1
SQL_AUTOCOMMIT_DEFAULT* = SQL_AUTOCOMMIT_ON # SQL_ATTR_CURSOR_SCROLLABLE values
SQL_NONSCROLLABLE* = 0
SQL_SCROLLABLE* = 1 # SQL_CURSOR_TYPE options
SQL_CURSOR_FORWARD_ONLY* = 0
SQL_CURSOR_KEYSET_DRIVEN* = 1
SQL_CURSOR_DYNAMIC* = 2
SQL_CURSOR_STATIC* = 3
SQL_CURSOR_TYPE_DEFAULT* = SQL_CURSOR_FORWARD_ONLY # Default value
# SQL_CONCURRENCY options
SQL_CONCUR_READ_ONLY* = 1
SQL_CONCUR_LOCK* = 2
SQL_CONCUR_ROWVER* = 3
SQL_CONCUR_VALUES* = 4
SQL_CONCUR_DEFAULT* = SQL_CONCUR_READ_ONLY # Default value
# identifiers of fields in the SQL descriptor
SQL_DESC_COUNT* = 1001
SQL_DESC_TYPE* = 1002
SQL_DESC_LENGTH* = 1003
SQL_DESC_OCTET_LENGTH_PTR* = 1004
SQL_DESC_PRECISION* = 1005
SQL_DESC_SCALE* = 1006
SQL_DESC_DATETIME_INTERVAL_CODE* = 1007
SQL_DESC_NULLABLE* = 1008
SQL_DESC_INDICATOR_PTR* = 1009
SQL_DESC_DATA_PTR* = 1010
SQL_DESC_NAME* = 1011
SQL_DESC_UNNAMED* = 1012
SQL_DESC_OCTET_LENGTH* = 1013
SQL_DESC_ALLOC_TYPE* = 1099 # identifiers of fields in the diagnostics area
SQL_DIAG_RETURNCODE* = 1
SQL_DIAG_NUMBER* = 2
SQL_DIAG_ROW_COUNT* = 3
SQL_DIAG_SQLSTATE* = 4
SQL_DIAG_NATIVE* = 5
SQL_DIAG_MESSAGE_TEXT* = 6
SQL_DIAG_DYNAMIC_FUNCTION* = 7
SQL_DIAG_CLASS_ORIGIN* = 8
SQL_DIAG_SUBCLASS_ORIGIN* = 9
SQL_DIAG_CONNECTION_NAME* = 10
SQL_DIAG_SERVER_NAME* = 11
SQL_DIAG_DYNAMIC_FUNCTION_CODE* = 12 # dynamic function codes
SQL_DIAG_ALTER_TABLE* = 4
SQL_DIAG_CREATE_INDEX* = (- 1)
SQL_DIAG_CREATE_TABLE* = 77
SQL_DIAG_CREATE_VIEW* = 84
SQL_DIAG_DELETE_WHERE* = 19
SQL_DIAG_DROP_INDEX* = (- 2)
SQL_DIAG_DROP_TABLE* = 32
SQL_DIAG_DROP_VIEW* = 36
SQL_DIAG_DYNAMIC_DELETE_CURSOR* = 38
SQL_DIAG_DYNAMIC_UPDATE_CURSOR* = 81
SQL_DIAG_GRANT* = 48
SQL_DIAG_INSERT* = 50
SQL_DIAG_REVOKE* = 59
SQL_DIAG_SELECT_CURSOR* = 85
SQL_DIAG_UNKNOWN_STATEMENT* = 0
SQL_DIAG_UPDATE_WHERE* = 82 # Statement attribute values for cursor sensitivity
SQL_UNSPECIFIED* = 0
SQL_INSENSITIVE* = 1
SQL_SENSITIVE* = 2 # GetTypeInfo() request for all data types
SQL_ALL_TYPES* = 0 # Default conversion code for SQLBindCol(), SQLBindParam() and SQLGetData()
SQL_DEFAULT* = 99 # SQLGetData() code indicating that the application row descriptor
# specifies the data type
SQL_ARD_TYPE* = (- 99) # SQL date/time type subcodes
SQL_CODE_DATE* = 1
SQL_CODE_TIME* = 2
SQL_CODE_TIMESTAMP* = 3 # CLI option values
SQL_FALSE* = 0
SQL_TRUE* = 1 # values of NULLABLE field in descriptor
SQL_NO_NULLS* = 0
SQL_NULLABLE* = 1 # Value returned by SQLGetTypeInfo() to denote that it is
# not known whether or not a data type supports null values.
SQL_NULLABLE_UNKNOWN* = 2
SQL_CLOSE* = 0
SQL_DROP* = 1
SQL_UNBIND* = 2
SQL_RESET_PARAMS* = 3 # Codes used for FetchOrientation in SQLFetchScroll(),
# and in SQLDataSources()
SQL_FETCH_NEXT* = 1
SQL_FETCH_FIRST* = 2
SQL_FETCH_FIRST_USER* = 31
SQL_FETCH_FIRST_SYSTEM* = 32 # Other codes used for FetchOrientation in SQLFetchScroll()
SQL_FETCH_LAST* = 3
SQL_FETCH_PRIOR* = 4
SQL_FETCH_ABSOLUTE* = 5
SQL_FETCH_RELATIVE* = 6
SQL_NULL_HENV* = SqlHEnv(nil)
SQL_NULL_HDBC* = SqlHDBC(nil)
SQL_NULL_HSTMT* = SqlHStmt(nil)
SQL_NULL_HDESC* = SqlHDesc(nil) #* null handle used in place of parent handle when allocating HENV */
SQL_NULL_HANDLE* = SqlHandle(nil) #* Values that may appear in the result set of SQLSpecialColumns() */
SQL_SCOPE_CURROW* = 0
SQL_SCOPE_TRANSACTION* = 1
SQL_SCOPE_SESSION* = 2 #* Column types and scopes in SQLSpecialColumns. */
SQL_BEST_ROWID* = 1
SQL_ROWVER* = 2
SQL_ROW_IDENTIFIER* = 1 #* Reserved values for UNIQUE argument of SQLStatistics() */
SQL_INDEX_UNIQUE* = 0
SQL_INDEX_ALL* = 1 #* Reserved values for RESERVED argument of SQLStatistics() */
SQL_QUICK* = 0
SQL_ENSURE* = 1 #* Values that may appear in the result set of SQLStatistics() */
SQL_TABLE_STAT* = 0
SQL_INDEX_CLUSTERED* = 1
SQL_INDEX_HASHED* = 2
SQL_INDEX_OTHER* = 3
SQL_SCROLL_CONCURRENCY* = 43
SQL_TXN_CAPABLE* = 46
SQL_TRANSACTION_CAPABLE* = SQL_TXN_CAPABLE
SQL_USER_NAME* = 47
SQL_TXN_ISOLATION_OPTION* = 72
SQL_TRANSACTION_ISOLATION_OPTION* = SQL_TXN_ISOLATION_OPTION
SQL_OJ_CAPABILITIES* = 115
SQL_OUTER_JOIN_CAPABILITIES* = SQL_OJ_CAPABILITIES
SQL_XOPEN_CLI_YEAR* = 10000
SQL_CURSOR_SENSITIVITY* = 10001
SQL_DESCRIBE_PARAMETER* = 10002
SQL_CATALOG_NAME* = 10003
SQL_COLLATION_SEQ* = 10004
SQL_MAX_IDENTIFIER_LEN* = 10005
SQL_MAXIMUM_IDENTIFIER_LENGTH* = SQL_MAX_IDENTIFIER_LEN
SQL_SCCO_READ_ONLY* = 1
SQL_SCCO_LOCK* = 2
SQL_SCCO_OPT_ROWVER* = 4
SQL_SCCO_OPT_VALUES* = 8 #* SQL_TXN_CAPABLE values */
SQL_TC_NONE* = 0
SQL_TC_DML* = 1
SQL_TC_ALL* = 2
SQL_TC_DDL_COMMIT* = 3
SQL_TC_DDL_IGNORE* = 4 #* SQL_TXN_ISOLATION_OPTION bitmasks */
SQL_TXN_READ_UNCOMMITTED* = 1
SQL_TRANSACTION_READ_UNCOMMITTED* = SQL_TXN_READ_UNCOMMITTED
SQL_TXN_READ_COMMITTED* = 2
SQL_TRANSACTION_READ_COMMITTED* = SQL_TXN_READ_COMMITTED
SQL_TXN_REPEATABLE_READ* = 4
SQL_TRANSACTION_REPEATABLE_READ* = SQL_TXN_REPEATABLE_READ
SQL_TXN_SERIALIZABLE* = 8
SQL_TRANSACTION_SERIALIZABLE* = SQL_TXN_SERIALIZABLE
SQL_SS_ADDITIONS* = 1
SQL_SS_DELETIONS* = 2
SQL_SS_UPDATES* = 4 # SQLColAttributes defines
SQL_COLUMN_COUNT* = 0
SQL_COLUMN_NAME* = 1
SQL_COLUMN_TYPE* = 2
SQL_COLUMN_LENGTH* = 3
SQL_COLUMN_PRECISION* = 4
SQL_COLUMN_SCALE* = 5
SQL_COLUMN_DISPLAY_SIZE* = 6
SQL_COLUMN_NULLABLE* = 7
SQL_COLUMN_UNSIGNED* = 8
SQL_COLUMN_MONEY* = 9
SQL_COLUMN_UPDATABLE* = 10
SQL_COLUMN_AUTO_INCREMENT* = 11
SQL_COLUMN_CASE_SENSITIVE* = 12
SQL_COLUMN_SEARCHABLE* = 13
SQL_COLUMN_TYPE_NAME* = 14
SQL_COLUMN_TABLE_NAME* = 15
SQL_COLUMN_OWNER_NAME* = 16
SQL_COLUMN_QUALIFIER_NAME* = 17
SQL_COLUMN_LABEL* = 18
SQL_COLATT_OPT_MAX* = SQL_COLUMN_LABEL
SQL_COLUMN_DRIVER_START* = 1000
SQL_DESC_ARRAY_SIZE* = 20
SQL_DESC_ARRAY_STATUS_PTR* = 21
SQL_DESC_AUTO_UNIQUE_VALUE* = SQL_COLUMN_AUTO_INCREMENT
SQL_DESC_BASE_COLUMN_NAME* = 22
SQL_DESC_BASE_TABLE_NAME* = 23
SQL_DESC_BIND_OFFSET_PTR* = 24
SQL_DESC_BIND_TYPE* = 25
SQL_DESC_CASE_SENSITIVE* = SQL_COLUMN_CASE_SENSITIVE
SQL_DESC_CATALOG_NAME* = SQL_COLUMN_QUALIFIER_NAME
SQL_DESC_CONCISE_TYPE* = SQL_COLUMN_TYPE
SQL_DESC_DATETIME_INTERVAL_PRECISION* = 26
SQL_DESC_DISPLAY_SIZE* = SQL_COLUMN_DISPLAY_SIZE
SQL_DESC_FIXED_PREC_SCALE* = SQL_COLUMN_MONEY
SQL_DESC_LABEL* = SQL_COLUMN_LABEL
SQL_DESC_LITERAL_PREFIX* = 27
SQL_DESC_LITERAL_SUFFIX* = 28
SQL_DESC_LOCAL_TYPE_NAME* = 29
SQL_DESC_MAXIMUM_SCALE* = 30
SQL_DESC_MINIMUM_SCALE* = 31
SQL_DESC_NUM_PREC_RADIX* = 32
SQL_DESC_PARAMETER_TYPE* = 33
SQL_DESC_ROWS_PROCESSED_PTR* = 34
SQL_DESC_SCHEMA_NAME* = SQL_COLUMN_OWNER_NAME
SQL_DESC_SEARCHABLE* = SQL_COLUMN_SEARCHABLE
SQL_DESC_TYPE_NAME* = SQL_COLUMN_TYPE_NAME
SQL_DESC_TABLE_NAME* = SQL_COLUMN_TABLE_NAME
SQL_DESC_UNSIGNED* = SQL_COLUMN_UNSIGNED
SQL_DESC_UPDATABLE* = SQL_COLUMN_UPDATABLE #* SQLEndTran() options */
SQL_COMMIT* = 0
SQL_ROLLBACK* = 1
SQL_ATTR_ROW_ARRAY_SIZE* = 27 #* SQLConfigDataSource() options */
ODBC_ADD_DSN* = 1
ODBC_CONFIG_DSN* = 2
ODBC_REMOVE_DSN* = 3
ODBC_ADD_SYS_DSN* = 4
ODBC_CONFIG_SYS_DSN* = 5
ODBC_REMOVE_SYS_DSN* = 6
SQL_ACTIVE_CONNECTIONS* = 0 # SQLGetInfo
SQL_DATA_SOURCE_NAME* = 2
SQL_DATA_SOURCE_READ_ONLY* = 25
SQL_DATABASE_NAME* = 2
SQL_DBMS_NAME* = 17
SQL_DBMS_VERSION* = 18
SQL_DRIVER_HDBC* = 3
SQL_DRIVER_HENV* = 4
SQL_DRIVER_HSTMT* = 5
SQL_DRIVER_NAME* = 6
SQL_DRIVER_VER* = 7
SQL_FETCH_DIRECTION* = 8
SQL_ODBC_VER* = 10
SQL_DRIVER_ODBC_VER* = 77
SQL_SERVER_NAME* = 13
SQL_ACTIVE_ENVIRONMENTS* = 116
SQL_ACTIVE_STATEMENTS* = 1
SQL_SQL_CONFORMANCE* = 118
SQL_DATETIME_LITERALS* = 119
SQL_ASYNC_MODE* = 10021
SQL_BATCH_ROW_COUNT* = 120
SQL_BATCH_SUPPORT* = 121
SQL_CATALOG_LOCATION* = 114
#SQL_CATALOG_NAME* = 10003
SQL_CATALOG_NAME_SEPARATOR* = 41
SQL_CATALOG_TERM* = 42
SQL_CATALOG_USAGE* = 92
#SQL_COLLATION_SEQ* = 10004
SQL_COLUMN_ALIAS* = 87
#SQL_USER_NAME* = 47
proc SQLAllocHandle*(HandleType: TSqlSmallInt, InputHandle: SqlHandle,
OutputHandlePtr: var SqlHandle): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLSetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLGetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
Value: SqlPointer, BufferLength: TSqlInteger,
StringLength: PSQLINTEGER): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLFreeHandle*(HandleType: TSqlSmallInt, Handle: SqlHandle): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLGetDiagRec*(HandleType: TSqlSmallInt, Handle: SqlHandle,
RecNumber: TSqlSmallInt, Sqlstate: PSQLCHAR,
NativeError: var TSqlInteger, MessageText: PSQLCHAR,
BufferLength: TSqlSmallInt, TextLength: var TSqlSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLGetDiagField*(HandleType: TSqlSmallInt, Handle: SqlHandle,
RecNumber: TSqlSmallInt, DiagIdentifier: TSqlSmallInt,
DiagInfoPtr: SqlPointer, BufferLength: TSqlSmallInt,
StringLengthPtr: var TSqlSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLConnect*(ConnectionHandle: SqlHDBC, ServerName: PSQLCHAR,
NameLength1: TSqlSmallInt, UserName: PSQLCHAR,
NameLength2: TSqlSmallInt, Authentication: PSQLCHAR,
NameLength3: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLDisconnect*(ConnectionHandle: SqlHDBC): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLDriverConnect*(hdbc: SqlHDBC, hwnd: SqlHWND, szCsin: cstring,
szCLen: TSqlSmallInt, szCsout: cstring,
cbCSMax: TSqlSmallInt, cbCsOut: var TSqlSmallInt,
f: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLBrowseConnect*(hdbc: SqlHDBC, szConnStrIn: PSQLCHAR,
cbConnStrIn: TSqlSmallInt, szConnStrOut: PSQLCHAR,
cbConnStrOutMax: TSqlSmallInt,
cbConnStrOut: var TSqlSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLExecDirect*(StatementHandle: SqlHStmt, StatementText: PSQLCHAR,
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLExecDirectW*(StatementHandle: SqlHStmt, StatementText: WideCString,
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLPrepare*(StatementHandle: SqlHStmt, StatementText: PSQLCHAR,
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLPrepareW*(StatementHandle: SqlHStmt, StatementText: WideCString,
TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLCloseCursor*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLExecute*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLFetch*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLNumResultCols*(StatementHandle: SqlHStmt, ColumnCount: var TSqlSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLDescribeCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
ColumnName: PSQLCHAR, BufferLength: TSqlSmallInt,
NameLength: var TSqlSmallInt, DataType: var TSqlSmallInt,
ColumnSize: var TSqlULen,
DecimalDigits: var TSqlSmallInt, Nullable: var TSqlSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLFetchScroll*(StatementHandle: SqlHStmt, FetchOrientation: TSqlSmallInt,
FetchOffset: TSqlLen): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLExtendedFetch*(hstmt: SqlHStmt, fFetchType: SqlUSmallInt,
irow: TSqlLen, pcrow: var TSqlULen,
rgfRowStatus: PSQLUSMALLINT): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLGetData*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
TargetType: TSqlSmallInt, TargetValue: SqlPointer,
BufferLength: TSqlLen, StrLen_or_Ind: ptr TSqlLen): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLSetStmtAttr*(StatementHandle: SqlHStmt, Attribute: TSqlInteger,
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLGetStmtAttr*(StatementHandle: SqlHStmt, Attribute: TSqlInteger,
Value: SqlPointer, BufferLength: TSqlInteger,
StringLength: PSQLINTEGER): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLGetInfo*(ConnectionHandle: SqlHDBC, InfoType: SqlUSmallInt,
InfoValue: SqlPointer, BufferLength: TSqlSmallInt,
StringLength: PSQLSMALLINT): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLBulkOperations*(StatementHandle: SqlHStmt, Operation: SqlUSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLPutData*(StatementHandle: SqlHStmt, Data: SqlPointer,
StrLen_or_Ind: TSQLLEN): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLBindCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
TargetType: TSqlSmallInt, TargetValue: SqlPointer,
BufferLength: TSqlLEN, StrLen_or_Ind: PSQLINTEGER): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLSetPos*(hstmt: SqlHStmt, irow: SqlUSmallInt, fOption: SqlUSmallInt,
fLock: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLDataSources*(EnvironmentHandle: SqlHEnv, Direction: SqlUSmallInt,
ServerName: PSQLCHAR, BufferLength1: TSqlSmallInt,
NameLength1: PSQLSMALLINT, Description: PSQLCHAR,
BufferLength2: TSqlSmallInt, NameLength2: PSQLSMALLINT): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLDrivers*(EnvironmentHandle: SqlHEnv, Direction: SqlUSmallInt,
DriverDescription: PSQLCHAR, BufferLength1: TSqlSmallInt,
DescriptionLength1: PSQLSMALLINT, DriverAttributes: PSQLCHAR,
BufferLength2: TSqlSmallInt, AttributesLength2: PSQLSMALLINT): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLSetConnectAttr*(ConnectionHandle: SqlHDBC, Attribute: TSqlInteger,
Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLGetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
BufferLength: TSqlSmallInt, NameLength: PSQLSMALLINT): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLSetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
NameLength: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLRowCount*(StatementHandle: SqlHStmt, RowCount: var TSQLLEN): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLBindParameter*(hstmt: SqlHStmt, ipar: SqlUSmallInt,
fParamType: TSqlSmallInt, fCType: TSqlSmallInt,
fSqlType: TSqlSmallInt, cbColDef: TSQLULEN,
ibScale: TSqlSmallInt, rgbValue: SqlPointer,
cbValueMax: TSQLLEN, pcbValue: var TSQLLEN): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLFreeStmt*(StatementHandle: SqlHStmt, Option: SqlUSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLColAttribute*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
FieldIdentifier: SqlUSmallInt,
CharacterAttribute: PSQLCHAR, BufferLength: TSqlSmallInt,
StringLength: PSQLSMALLINT,
NumericAttribute: TSQLLEN): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLEndTran*(HandleType: TSqlSmallInt, Handle: SqlHandle,
CompletionType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLTables*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
cbTableName: TSqlSmallInt, szTableType: PSQLCHAR,
cbTableType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLColumns*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
cbTableName: TSqlSmallInt, szColumnName: PSQLCHAR,
cbColumnName: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
proc SQLSpecialColumns*(StatementHandle: SqlHStmt, IdentifierType: SqlUSmallInt,
CatalogName: PSQLCHAR, NameLength1: TSqlSmallInt,
SchemaName: PSQLCHAR, NameLength2: TSqlSmallInt,
TableName: PSQLCHAR, NameLength3: TSqlSmallInt,
Scope: SqlUSmallInt,
Nullable: SqlUSmallInt): TSqlSmallInt{.
dynlib: odbclib, importc.}
proc SQLProcedures*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
cbTableName: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLPrimaryKeys*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
NameLength2: TSqlSmallInt, TableName: PSQLCHAR,
NameLength3: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLProcedureColumns*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
NameLength2: TSqlSmallInt, ProcName: PSQLCHAR,
NameLength3: TSqlSmallInt, ColumnName: PSQLCHAR,
NameLength4: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
importc.}
proc SQLStatistics*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
NameLength2: TSqlSmallInt, TableName: PSQLCHAR,
NameLength3: TSqlSmallInt, Unique: SqlUSmallInt,
Reserved: SqlUSmallInt): TSqlSmallInt {.
dynlib: odbclib, importc.}
proc SQLErr*(henv: SqlHEnv, hdbc: SqlHDBC, hstmt: SqlHStmt,
szSqlState, pfNativeError, szErrorMsg: PSQLCHAR,
cbErrorMsgMax: TSqlSmallInt,
pcbErrorMsg: PSQLSMALLINT): TSqlSmallInt {.
dynlib: odbclib, importc: "SQLError".}
{.pop.}
when defined(nimHasStyleChecks):
{.pop.}

View File

@@ -1,378 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This module contains the definitions for structures and externs for
# functions used by frontend postgres applications. It is based on
# Postgresql's libpq-fe.h.
#
# It is for postgreSQL version 7.4 and higher with support for the v3.0
# connection-protocol.
#
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
when defined(windows):
const
dllName = "libpq.dll"
elif defined(macosx):
const
dllName = "libpq.dylib"
else:
const
dllName = "libpq.so(.5|)"
when defined(nimPreviewSlimSystem):
import std/syncio
type
POid* = ptr Oid
Oid* = int32
const
ERROR_MSG_LENGTH* = 4096
CMDSTATUS_LEN* = 40
type
SockAddr* = array[1..112, int8]
PGresAttDesc*{.pure, final.} = object
name*: cstring
adtid*: Oid
adtsize*: int
PPGresAttDesc* = ptr PGresAttDesc
PPPGresAttDesc* = ptr PPGresAttDesc
PGresAttValue*{.pure, final.} = object
length*: int32
value*: cstring
PPGresAttValue* = ptr PGresAttValue
PPPGresAttValue* = ptr PPGresAttValue
PExecStatusType* = ptr ExecStatusType
ExecStatusType* = enum
PGRES_EMPTY_QUERY = 0, PGRES_COMMAND_OK, PGRES_TUPLES_OK, PGRES_COPY_OUT,
PGRES_COPY_IN, PGRES_BAD_RESPONSE, PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR,
PGRES_COPY_BOTH, PGRES_SINGLE_TUPLE
PGlobjfuncs*{.pure, final.} = object
fn_lo_open*: Oid
fn_lo_close*: Oid
fn_lo_creat*: Oid
fn_lo_unlink*: Oid
fn_lo_lseek*: Oid
fn_lo_tell*: Oid
fn_lo_read*: Oid
fn_lo_write*: Oid
PPGlobjfuncs* = ptr PGlobjfuncs
PConnStatusType* = ptr ConnStatusType
ConnStatusType* = enum
CONNECTION_OK, CONNECTION_BAD, CONNECTION_STARTED, CONNECTION_MADE,
CONNECTION_AWAITING_RESPONSE, CONNECTION_AUTH_OK, CONNECTION_SETENV,
CONNECTION_SSL_STARTUP, CONNECTION_NEEDED, CONNECTION_CHECK_WRITABLE,
CONNECTION_CONSUME, CONNECTION_GSS_STARTUP, CONNECTION_CHECK_TARGET
PGconn*{.pure, final.} = object
pghost*: cstring
pgtty*: cstring
pgport*: cstring
pgoptions*: cstring
dbName*: cstring
status*: ConnStatusType
errorMessage*: array[0..(ERROR_MSG_LENGTH) - 1, char]
Pfin*: File
Pfout*: File
Pfdebug*: File
sock*: int32
laddr*: SockAddr
raddr*: SockAddr
salt*: array[0..(2) - 1, char]
asyncNotifyWaiting*: int32
notifyList*: pointer
pguser*: cstring
pgpass*: cstring
lobjfuncs*: PPGlobjfuncs
PPGconn* = ptr PGconn
PGresult*{.pure, final.} = object
ntups*: int32
numAttributes*: int32
attDescs*: PPGresAttDesc
tuples*: PPPGresAttValue
tupArrSize*: int32
resultStatus*: ExecStatusType
cmdStatus*: array[0..(CMDSTATUS_LEN) - 1, char]
binary*: int32
conn*: PPGconn
PPGresult* = ptr PGresult
PPostgresPollingStatusType* = ptr PostgresPollingStatusType
PostgresPollingStatusType* = enum
PGRES_POLLING_FAILED = 0, PGRES_POLLING_READING, PGRES_POLLING_WRITING,
PGRES_POLLING_OK, PGRES_POLLING_ACTIVE
PPGTransactionStatusType* = ptr PGTransactionStatusType
PGTransactionStatusType* = enum
PQTRANS_IDLE, PQTRANS_ACTIVE, PQTRANS_INTRANS, PQTRANS_INERROR,
PQTRANS_UNKNOWN
PPGVerbosity* = ptr PGVerbosity
PGVerbosity* = enum
PQERRORS_TERSE, PQERRORS_DEFAULT, PQERRORS_VERBOSE, PQERRORS_SQLSTATE
PPGNotify* = ptr pgNotify
pgNotify*{.pure, final.} = object
relname*: cstring
be_pid*: int32
extra*: cstring
PQnoticeReceiver* = proc (arg: pointer, res: PPGresult){.cdecl.}
PQnoticeProcessor* = proc (arg: pointer, message: cstring){.cdecl.}
Ppqbool* = ptr pqbool
pqbool* = char
PPQprintOpt* = ptr PQprintOpt
PQprintOpt*{.pure, final.} = object
header*: pqbool
align*: pqbool
standard*: pqbool
html3*: pqbool
expanded*: pqbool
pager*: pqbool
fieldSep*: cstring
tableOpt*: cstring
caption*: cstring
fieldName*: ptr cstring
PPQconninfoOption* = ptr PQconninfoOption
PQconninfoOption*{.pure, final.} = object
keyword*: cstring
envvar*: cstring
compiled*: cstring
val*: cstring
label*: cstring
dispchar*: cstring
dispsize*: int32
PPQArgBlock* = ptr PQArgBlock
PQArgBlock*{.pure, final.} = object
length*: int32
isint*: int32
p*: pointer
proc pqinitOpenSSL*(do_ssl: int32, do_crypto: int32) {.cdecl, dynlib: dllName,
importc: "PQinitOpenSSL".}
proc pqconnectStart*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName,
importc: "PQconnectStart".}
proc pqconnectPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl,
dynlib: dllName, importc: "PQconnectPoll".}
proc pqconnectdb*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName,
importc: "PQconnectdb".}
proc pqsetdbLogin*(pghost: cstring, pgport: cstring, pgoptions: cstring,
pgtty: cstring, dbName: cstring, login: cstring, pwd: cstring): PPGconn{.
cdecl, dynlib: dllName, importc: "PQsetdbLogin".}
proc pqsetdb*(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): PPGconn
proc pqfinish*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQfinish".}
proc pqconndefaults*(): PPQconninfoOption{.cdecl, dynlib: dllName,
importc: "PQconndefaults".}
proc pqconninfoFree*(connOptions: PPQconninfoOption){.cdecl, dynlib: dllName,
importc: "PQconninfoFree".}
proc pqresetStart*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQresetStart".}
proc pqresetPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl,
dynlib: dllName, importc: "PQresetPoll".}
proc pqreset*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQreset".}
proc pqrequestCancel*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQrequestCancel".}
proc pqdb*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQdb".}
proc pquser*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQuser".}
proc pqpass*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQpass".}
proc pqhost*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQhost".}
proc pqport*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQport".}
proc pqtty*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQtty".}
proc pqoptions*(conn: PPGconn): cstring{.cdecl, dynlib: dllName,
importc: "PQoptions".}
proc pqstatus*(conn: PPGconn): ConnStatusType{.cdecl, dynlib: dllName,
importc: "PQstatus".}
proc pqtransactionStatus*(conn: PPGconn): PGTransactionStatusType{.cdecl,
dynlib: dllName, importc: "PQtransactionStatus".}
proc pqparameterStatus*(conn: PPGconn, paramName: cstring): cstring{.cdecl,
dynlib: dllName, importc: "PQparameterStatus".}
proc pqserverVersion*(conn: PPGconn): int32{.cdecl,
dynlib: dllName, importc: "PQserverVersion".}
proc pqprotocolVersion*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQprotocolVersion".}
proc pqerrorMessage*(conn: PPGconn): cstring{.cdecl, dynlib: dllName,
importc: "PQerrorMessage".}
proc pqsocket*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQsocket".}
proc pqbackendPID*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQbackendPID".}
proc pqconnectionNeedsPassword*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQconnectionNeedsPassword".}
proc pqconnectionUsedPassword*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQconnectionUsedPassword".}
proc pqclientEncoding*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQclientEncoding".}
proc pqsetClientEncoding*(conn: PPGconn, encoding: cstring): int32{.cdecl,
dynlib: dllName, importc: "PQsetClientEncoding".}
proc pqsetErrorVerbosity*(conn: PPGconn, verbosity: PGVerbosity): PGVerbosity{.
cdecl, dynlib: dllName, importc: "PQsetErrorVerbosity".}
proc pqtrace*(conn: PPGconn, debug_port: File){.cdecl, dynlib: dllName,
importc: "PQtrace".}
proc pquntrace*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQuntrace".}
proc pqsetNoticeReceiver*(conn: PPGconn, theProc: PQnoticeReceiver, arg: pointer): PQnoticeReceiver{.
cdecl, dynlib: dllName, importc: "PQsetNoticeReceiver".}
proc pqsetNoticeProcessor*(conn: PPGconn, theProc: PQnoticeProcessor,
arg: pointer): PQnoticeProcessor{.cdecl,
dynlib: dllName, importc: "PQsetNoticeProcessor".}
proc pqexec*(conn: PPGconn, query: cstring): PPGresult{.cdecl, dynlib: dllName,
importc: "PQexec".}
proc pqexecParams*(conn: PPGconn, command: cstring, nParams: int32,
paramTypes: POid, paramValues: cstringArray,
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
cdecl, dynlib: dllName, importc: "PQexecParams".}
proc pqprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
proc pqexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
paramValues: cstringArray,
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
cdecl, dynlib: dllName, importc: "PQexecPrepared".}
proc pqsendQuery*(conn: PPGconn, query: cstring): int32{.cdecl, dynlib: dllName,
importc: "PQsendQuery".}
## See also https://www.postgresql.org/docs/current/libpq-async.html
proc pqsendQueryParams*(conn: PPGconn, command: cstring, nParams: int32,
paramTypes: POid, paramValues: cstringArray,
paramLengths, paramFormats: ptr int32,
resultFormat: int32): int32{.cdecl, dynlib: dllName,
importc: "PQsendQueryParams".}
proc pqsendQueryPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
paramValues: cstringArray,
paramLengths, paramFormats: ptr int32,
resultFormat: int32): int32{.cdecl, dynlib: dllName,
importc: "PQsendQueryPrepared".}
proc pqSetSingleRowMode*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQsetSingleRowMode".}
## See also https://www.postgresql.org/docs/current/libpq-single-row-mode.html
proc pqgetResult*(conn: PPGconn): PPGresult{.cdecl, dynlib: dllName,
importc: "PQgetResult".}
proc pqisBusy*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQisBusy".}
proc pqconsumeInput*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQconsumeInput".}
proc pqnotifies*(conn: PPGconn): PPGNotify{.cdecl, dynlib: dllName,
importc: "PQnotifies".}
proc pqputCopyData*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.
cdecl, dynlib: dllName, importc: "PQputCopyData".}
proc pqputCopyEnd*(conn: PPGconn, errormsg: cstring): int32{.cdecl,
dynlib: dllName, importc: "PQputCopyEnd".}
proc pqgetCopyData*(conn: PPGconn, buffer: cstringArray, async: int32): int32{.
cdecl, dynlib: dllName, importc: "PQgetCopyData".}
proc pqgetline*(conn: PPGconn, str: cstring, len: int32): int32{.cdecl,
dynlib: dllName, importc: "PQgetline".}
proc pqputline*(conn: PPGconn, str: cstring): int32{.cdecl, dynlib: dllName,
importc: "PQputline".}
proc pqgetlineAsync*(conn: PPGconn, buffer: cstring, bufsize: int32): int32{.
cdecl, dynlib: dllName, importc: "PQgetlineAsync".}
proc pqputnbytes*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.cdecl,
dynlib: dllName, importc: "PQputnbytes".}
proc pqendcopy*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQendcopy".}
proc pqsetnonblocking*(conn: PPGconn, arg: int32): int32{.cdecl,
dynlib: dllName, importc: "PQsetnonblocking".}
proc pqisnonblocking*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
importc: "PQisnonblocking".}
proc pqflush*(conn: PPGconn): int32{.cdecl, dynlib: dllName, importc: "PQflush".}
proc pqfn*(conn: PPGconn, fnid: int32, result_buf, result_len: ptr int32,
result_is_int: int32, args: PPQArgBlock, nargs: int32): PPGresult{.
cdecl, dynlib: dllName, importc: "PQfn".}
proc pqresultStatus*(res: PPGresult): ExecStatusType{.cdecl, dynlib: dllName,
importc: "PQresultStatus".}
proc pqresStatus*(status: ExecStatusType): cstring{.cdecl, dynlib: dllName,
importc: "PQresStatus".}
proc pqresultErrorMessage*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
importc: "PQresultErrorMessage".}
proc pqresultErrorField*(res: PPGresult, fieldcode: int32): cstring{.cdecl,
dynlib: dllName, importc: "PQresultErrorField".}
proc pqntuples*(res: PPGresult): int32{.cdecl, dynlib: dllName,
importc: "PQntuples".}
proc pqnfields*(res: PPGresult): int32{.cdecl, dynlib: dllName,
importc: "PQnfields".}
proc pqbinaryTuples*(res: PPGresult): int32{.cdecl, dynlib: dllName,
importc: "PQbinaryTuples".}
proc pqfname*(res: PPGresult, field_num: int32): cstring{.cdecl,
dynlib: dllName, importc: "PQfname".}
proc pqfnumber*(res: PPGresult, field_name: cstring): int32{.cdecl,
dynlib: dllName, importc: "PQfnumber".}
proc pqftable*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName,
importc: "PQftable".}
proc pqftablecol*(res: PPGresult, field_num: int32): int32{.cdecl,
dynlib: dllName, importc: "PQftablecol".}
proc pqfformat*(res: PPGresult, field_num: int32): int32{.cdecl,
dynlib: dllName, importc: "PQfformat".}
proc pqftype*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName,
importc: "PQftype".}
proc pqfsize*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName,
importc: "PQfsize".}
proc pqfmod*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName,
importc: "PQfmod".}
proc pqcmdStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
importc: "PQcmdStatus".}
proc pqoidStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
importc: "PQoidStatus".}
proc pqoidValue*(res: PPGresult): Oid{.cdecl, dynlib: dllName,
importc: "PQoidValue".}
proc pqcmdTuples*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
importc: "PQcmdTuples".}
proc pqgetvalue*(res: PPGresult, tup_num: int32, field_num: int32): cstring{.
cdecl, dynlib: dllName, importc: "PQgetvalue".}
proc pqgetlength*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
cdecl, dynlib: dllName, importc: "PQgetlength".}
proc pqgetisnull*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
cdecl, dynlib: dllName, importc: "PQgetisnull".}
proc pqclear*(res: PPGresult){.cdecl, dynlib: dllName, importc: "PQclear".}
proc pqfreemem*(p: pointer){.cdecl, dynlib: dllName, importc: "PQfreemem".}
proc pqmakeEmptyPGresult*(conn: PPGconn, status: ExecStatusType): PPGresult{.
cdecl, dynlib: dllName, importc: "PQmakeEmptyPGresult".}
proc pqescapeString*(till, `from`: cstring, len: int): int{.cdecl,
dynlib: dllName, importc: "PQescapeString".}
proc pqescapeBytea*(bintext: cstring, binlen: int, bytealen: var int): cstring{.
cdecl, dynlib: dllName, importc: "PQescapeBytea".}
proc pqunescapeBytea*(strtext: cstring, retbuflen: var int): cstring{.cdecl,
dynlib: dllName, importc: "PQunescapeBytea".}
proc pqprint*(fout: File, res: PPGresult, ps: PPQprintOpt){.cdecl,
dynlib: dllName, importc: "PQprint".}
proc pqdisplayTuples*(res: PPGresult, fp: File, fillAlign: int32,
fieldSep: cstring, printHeader: int32, quiet: int32){.
cdecl, dynlib: dllName, importc: "PQdisplayTuples".}
proc pqprintTuples*(res: PPGresult, fout: File, printAttName: int32,
terseOutput: int32, width: int32){.cdecl, dynlib: dllName,
importc: "PQprintTuples".}
proc lo_open*(conn: PPGconn, lobjId: Oid, mode: int32): int32{.cdecl,
dynlib: dllName, importc: "lo_open".}
proc lo_close*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName,
importc: "lo_close".}
proc lo_read*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
cdecl, dynlib: dllName, importc: "lo_read".}
proc lo_write*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
cdecl, dynlib: dllName, importc: "lo_write".}
proc lo_lseek*(conn: PPGconn, fd: int32, offset: int32, whence: int32): int32{.
cdecl, dynlib: dllName, importc: "lo_lseek".}
proc lo_creat*(conn: PPGconn, mode: int32): Oid{.cdecl, dynlib: dllName,
importc: "lo_creat".}
proc lo_tell*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName,
importc: "lo_tell".}
proc lo_unlink*(conn: PPGconn, lobjId: Oid): int32{.cdecl, dynlib: dllName,
importc: "lo_unlink".}
proc lo_import*(conn: PPGconn, filename: cstring): Oid{.cdecl, dynlib: dllName,
importc: "lo_import".}
proc lo_export*(conn: PPGconn, lobjId: Oid, filename: cstring): int32{.cdecl,
dynlib: dllName, importc: "lo_export".}
proc pqmblen*(s: cstring, encoding: int32): int32{.cdecl, dynlib: dllName,
importc: "PQmblen".}
proc pqenv2encoding*(): int32{.cdecl, dynlib: dllName, importc: "PQenv2encoding".}
proc pqsetdb(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): PPGconn =
result = pqsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, "", "")
when defined(nimHasStyleChecks):
{.pop.}

View File

@@ -1,392 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
when defined(windows):
when defined(nimOldDlls):
const Lib = "sqlite3.dll"
elif defined(cpu64):
const Lib = "sqlite3_64.dll"
else:
const Lib = "sqlite3_32.dll"
elif defined(macosx):
const
Lib = "libsqlite3(|.0).dylib"
else:
const
Lib = "libsqlite3.so(|.0)"
when defined(staticSqlite):
{.pragma: mylib.}
{.compile("sqlite3.c", "-O3").}
else:
{.pragma: mylib, dynlib: Lib.}
const
SQLITE_INTEGER* = 1
SQLITE_FLOAT* = 2
SQLITE_BLOB* = 4
SQLITE_NULL* = 5
SQLITE_TEXT* = 3
SQLITE_UTF8* = 1
SQLITE_UTF16LE* = 2
SQLITE_UTF16BE* = 3 # Use native byte order
SQLITE_UTF16* = 4 # sqlite3_create_function only
SQLITE_ANY* = 5 #sqlite_exec return values
SQLITE_OK* = 0
SQLITE_ERROR* = 1 # SQL error or missing database
SQLITE_INTERNAL* = 2 # An internal logic error in SQLite
SQLITE_PERM* = 3 # Access permission denied
SQLITE_ABORT* = 4 # Callback routine requested an abort
SQLITE_BUSY* = 5 # The database file is locked
SQLITE_LOCKED* = 6 # A table in the database is locked
SQLITE_NOMEM* = 7 # A malloc() failed
SQLITE_READONLY* = 8 # Attempt to write a readonly database
SQLITE_INTERRUPT* = 9 # Operation terminated by sqlite3_interrupt()
SQLITE_IOERR* = 10 # Some kind of disk I/O error occurred
SQLITE_CORRUPT* = 11 # The database disk image is malformed
SQLITE_NOTFOUND* = 12 # (Internal Only) Table or record not found
SQLITE_FULL* = 13 # Insertion failed because database is full
SQLITE_CANTOPEN* = 14 # Unable to open the database file
SQLITE_PROTOCOL* = 15 # Database lock protocol error
SQLITE_EMPTY* = 16 # Database is empty
SQLITE_SCHEMA* = 17 # The database schema changed
SQLITE_TOOBIG* = 18 # Too much data for one row of a table
SQLITE_CONSTRAINT* = 19 # Abort due to constraint violation
SQLITE_MISMATCH* = 20 # Data type mismatch
SQLITE_MISUSE* = 21 # Library used incorrectly
SQLITE_NOLFS* = 22 # Uses OS features not supported on host
SQLITE_AUTH* = 23 # Authorization denied
SQLITE_FORMAT* = 24 # Auxiliary database format error
SQLITE_RANGE* = 25 # 2nd parameter to sqlite3_bind out of range
SQLITE_NOTADB* = 26 # File opened that is not a database file
SQLITE_ROW* = 100 # sqlite3_step() has another row ready
SQLITE_DONE* = 101 # sqlite3_step() has finished executing
SQLITE_COPY* = 0
SQLITE_CREATE_INDEX* = 1
SQLITE_CREATE_TABLE* = 2
SQLITE_CREATE_TEMP_INDEX* = 3
SQLITE_CREATE_TEMP_TABLE* = 4
SQLITE_CREATE_TEMP_TRIGGER* = 5
SQLITE_CREATE_TEMP_VIEW* = 6
SQLITE_CREATE_TRIGGER* = 7
SQLITE_CREATE_VIEW* = 8
SQLITE_DELETE* = 9
SQLITE_DROP_INDEX* = 10
SQLITE_DROP_TABLE* = 11
SQLITE_DROP_TEMP_INDEX* = 12
SQLITE_DROP_TEMP_TABLE* = 13
SQLITE_DROP_TEMP_TRIGGER* = 14
SQLITE_DROP_TEMP_VIEW* = 15
SQLITE_DROP_TRIGGER* = 16
SQLITE_DROP_VIEW* = 17
SQLITE_INSERT* = 18
SQLITE_PRAGMA* = 19
SQLITE_READ* = 20
SQLITE_SELECT* = 21
SQLITE_TRANSACTION* = 22
SQLITE_UPDATE* = 23
SQLITE_ATTACH* = 24
SQLITE_DETACH* = 25
SQLITE_ALTER_TABLE* = 26
SQLITE_REINDEX* = 27
SQLITE_DENY* = 1
SQLITE_IGNORE* = 2 # Original from sqlite3.h:
#define SQLITE_STATIC ((void(*)(void *))0)
#define SQLITE_TRANSIENT ((void(*)(void *))-1)
SQLITE_DETERMINISTIC* = 0x800
type
Sqlite3 {.pure, final.} = object
PSqlite3* = ptr Sqlite3
PPSqlite3* = ptr PSqlite3
Sqlite3_Backup {.pure, final.} = object
PSqlite3_Backup* = ptr Sqlite3_Backup
PPSqlite3_Backup* = ptr PSqlite3_Backup
Context{.pure, final.} = object
Pcontext* = ptr Context
TStmt{.pure, final.} = object
PStmt* = ptr TStmt
Value{.pure, final.} = object
PValue* = ptr Value
PValueArg* = array[0..127, PValue]
Callback* = proc (para1: pointer, para2: int32, para3,
para4: cstringArray): int32{.cdecl.}
Tbind_destructor_func* = proc (para1: pointer){.cdecl, tags: [], gcsafe.}
Create_function_step_func* = proc (para1: Pcontext, para2: int32,
para3: PValueArg){.cdecl.}
Create_function_func_func* = proc (para1: Pcontext, para2: int32,
para3: PValueArg){.cdecl.}
Create_function_final_func* = proc (para1: Pcontext){.cdecl.}
Result_func* = proc (para1: pointer){.cdecl.}
Create_collation_func* = proc (para1: pointer, para2: int32, para3: pointer,
para4: int32, para5: pointer): int32{.cdecl.}
Collation_needed_func* = proc (para1: pointer, para2: PSqlite3, eTextRep: int32,
para4: cstring){.cdecl.}
const
SQLITE_STATIC* = nil
SQLITE_TRANSIENT* = cast[Tbind_destructor_func](-1)
proc close*(para1: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_close".}
proc exec*(para1: PSqlite3, sql: cstring, para3: Callback, para4: pointer,
errmsg: var cstring): int32{.cdecl, mylib,
importc: "sqlite3_exec".}
proc last_insert_rowid*(para1: PSqlite3): int64{.cdecl, mylib,
importc: "sqlite3_last_insert_rowid".}
proc changes*(para1: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_changes".}
proc total_changes*(para1: PSqlite3): int32{.cdecl, mylib,
importc: "sqlite3_total_changes".}
proc interrupt*(para1: PSqlite3){.cdecl, mylib, importc: "sqlite3_interrupt".}
proc complete*(sql: cstring): int32{.cdecl, mylib,
importc: "sqlite3_complete".}
proc complete16*(sql: pointer): int32{.cdecl, mylib,
importc: "sqlite3_complete16".}
proc busy_handler*(para1: PSqlite3,
para2: proc (para1: pointer, para2: int32): int32{.cdecl.},
para3: pointer): int32{.cdecl, mylib,
importc: "sqlite3_busy_handler".}
proc busy_timeout*(para1: PSqlite3, ms: int32): int32{.cdecl, mylib,
importc: "sqlite3_busy_timeout".}
proc get_table*(para1: PSqlite3, sql: cstring, resultp: var cstringArray,
nrow, ncolumn: var cint, errmsg: ptr cstring): int32{.cdecl,
mylib, importc: "sqlite3_get_table".}
proc free_table*(result: cstringArray){.cdecl, mylib,
importc: "sqlite3_free_table".}
# Todo: see how translate sqlite3_mprintf, sqlite3_vmprintf, sqlite3_snprintf
# function sqlite3_mprintf(_para1:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_mprintf';
proc mprintf*(para1: cstring): cstring{.cdecl, varargs, mylib,
importc: "sqlite3_mprintf".}
#function sqlite3_vmprintf(_para1:Pchar; _para2:va_list):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_vmprintf';
proc free*(z: cstring){.cdecl, mylib, importc: "sqlite3_free".}
#function sqlite3_snprintf(_para1:longint; _para2:Pchar; _para3:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_snprintf';
proc snprintf*(para1: int32, para2: cstring, para3: cstring): cstring{.cdecl,
mylib, varargs, importc: "sqlite3_snprintf".}
proc set_authorizer*(para1: PSqlite3, xAuth: proc (para1: pointer, para2: int32,
para3: cstring, para4: cstring, para5: cstring, para6: cstring): int32{.
cdecl.}, pUserData: pointer): int32{.cdecl, mylib,
importc: "sqlite3_set_authorizer".}
proc trace*(para1: PSqlite3, xTrace: proc (para1: pointer, para2: cstring){.cdecl.},
para3: pointer): pointer{.cdecl, mylib,
importc: "sqlite3_trace".}
proc progress_handler*(para1: PSqlite3, para2: int32,
para3: proc (para1: pointer): int32{.cdecl.},
para4: pointer){.cdecl, mylib,
importc: "sqlite3_progress_handler".}
proc commit_hook*(para1: PSqlite3, para2: proc (para1: pointer): int32{.cdecl.},
para3: pointer): pointer{.cdecl, mylib,
importc: "sqlite3_commit_hook".}
proc open*(filename: cstring, ppDb: var PSqlite3): int32{.cdecl, mylib,
importc: "sqlite3_open".}
proc open16*(filename: pointer, ppDb: var PSqlite3): int32{.cdecl, mylib,
importc: "sqlite3_open16".}
proc errcode*(db: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_errcode".}
proc errmsg*(para1: PSqlite3): cstring{.cdecl, mylib, importc: "sqlite3_errmsg".}
proc errmsg16*(para1: PSqlite3): pointer{.cdecl, mylib,
importc: "sqlite3_errmsg16".}
proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: var PStmt,
pzTail: ptr cstring): int32{.cdecl, mylib,
importc: "sqlite3_prepare".}
proc prepare_v2*(db: PSqlite3, zSql: cstring, nByte: cint, ppStmt: var PStmt,
pzTail: ptr cstring): cint {.
importc: "sqlite3_prepare_v2", cdecl, mylib.}
proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: var PStmt,
pzTail: var pointer): int32{.cdecl, mylib,
importc: "sqlite3_prepare16".}
proc bind_blob*(para1: PStmt, para2: int32, para3: pointer, n: int32,
para5: Tbind_destructor_func): int32{.cdecl, mylib,
importc: "sqlite3_bind_blob".}
proc bind_double*(para1: PStmt, para2: int32, para3: float64): int32{.cdecl,
mylib, importc: "sqlite3_bind_double".}
proc bind_int*(para1: PStmt, para2: int32, para3: int32): int32{.cdecl,
mylib, importc: "sqlite3_bind_int".}
proc bind_int64*(para1: PStmt, para2: int32, para3: int64): int32{.cdecl,
mylib, importc: "sqlite3_bind_int64".}
proc bind_null*(para1: PStmt, para2: int32): int32{.cdecl, mylib,
importc: "sqlite3_bind_null".}
proc bind_text*(para1: PStmt, para2: int32, para3: cstring, n: int32,
para5: Tbind_destructor_func): int32{.cdecl, mylib,
importc: "sqlite3_bind_text".}
proc bind_text16*(para1: PStmt, para2: int32, para3: pointer, para4: int32,
para5: Tbind_destructor_func): int32{.cdecl, mylib,
importc: "sqlite3_bind_text16".}
#function sqlite3_bind_value(_para1:Psqlite3_stmt; _para2:longint; _para3:Psqlite3_value):longint;cdecl; external Sqlite3Lib name 'sqlite3_bind_value';
#These overloaded functions were introduced to allow the use of SQLITE_STATIC and SQLITE_TRANSIENT
#It's the c world man ;-)
proc bind_blob*(para1: PStmt, para2: int32, para3: pointer, n: int32,
para5: int32): int32{.cdecl, mylib,
importc: "sqlite3_bind_blob".}
proc bind_text*(para1: PStmt, para2: int32, para3: cstring, n: int32,
para5: int32): int32{.cdecl, mylib,
importc: "sqlite3_bind_text".}
proc bind_text16*(para1: PStmt, para2: int32, para3: pointer, para4: int32,
para5: int32): int32{.cdecl, mylib,
importc: "sqlite3_bind_text16".}
proc bind_parameter_count*(para1: PStmt): int32{.cdecl, mylib,
importc: "sqlite3_bind_parameter_count".}
proc bind_parameter_name*(para1: PStmt, para2: int32): cstring{.cdecl,
mylib, importc: "sqlite3_bind_parameter_name".}
proc bind_parameter_index*(para1: PStmt, zName: cstring): int32{.cdecl,
mylib, importc: "sqlite3_bind_parameter_index".}
proc clear_bindings*(para1: PStmt): int32 {.cdecl,
mylib, importc: "sqlite3_clear_bindings".}
proc column_count*(PStmt: PStmt): int32{.cdecl, mylib,
importc: "sqlite3_column_count".}
proc column_name*(para1: PStmt, para2: int32): cstring{.cdecl, mylib,
importc: "sqlite3_column_name".}
proc column_table_name*(para1: PStmt; para2: int32): cstring{.cdecl, mylib,
importc: "sqlite3_column_table_name".}
proc column_name16*(para1: PStmt, para2: int32): pointer{.cdecl, mylib,
importc: "sqlite3_column_name16".}
proc column_decltype*(para1: PStmt, i: int32): cstring{.cdecl, mylib,
importc: "sqlite3_column_decltype".}
proc column_decltype16*(para1: PStmt, para2: int32): pointer{.cdecl,
mylib, importc: "sqlite3_column_decltype16".}
proc step*(para1: PStmt): int32{.cdecl, mylib, importc: "sqlite3_step".}
proc data_count*(PStmt: PStmt): int32{.cdecl, mylib,
importc: "sqlite3_data_count".}
proc column_blob*(para1: PStmt, iCol: int32): pointer{.cdecl, mylib,
importc: "sqlite3_column_blob".}
proc column_bytes*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
importc: "sqlite3_column_bytes".}
proc column_bytes16*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
importc: "sqlite3_column_bytes16".}
proc column_double*(para1: PStmt, iCol: int32): float64{.cdecl, mylib,
importc: "sqlite3_column_double".}
proc column_int*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
importc: "sqlite3_column_int".}
proc column_int64*(para1: PStmt, iCol: int32): int64{.cdecl, mylib,
importc: "sqlite3_column_int64".}
proc column_text*(para1: PStmt, iCol: int32): cstring{.cdecl, mylib,
importc: "sqlite3_column_text".}
proc column_text16*(para1: PStmt, iCol: int32): pointer{.cdecl, mylib,
importc: "sqlite3_column_text16".}
proc column_type*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
importc: "sqlite3_column_type".}
proc finalize*(PStmt: PStmt): int32{.cdecl, mylib,
importc: "sqlite3_finalize".}
proc reset*(PStmt: PStmt): int32{.cdecl, mylib, importc: "sqlite3_reset".}
proc create_function*(para1: PSqlite3, zFunctionName: cstring, nArg: int32,
eTextRep: int32, para5: pointer,
xFunc: Create_function_func_func,
xStep: Create_function_step_func,
xFinal: Create_function_final_func): int32{.cdecl,
mylib, importc: "sqlite3_create_function".}
proc create_function16*(para1: PSqlite3, zFunctionName: pointer, nArg: int32,
eTextRep: int32, para5: pointer,
xFunc: Create_function_func_func,
xStep: Create_function_step_func,
xFinal: Create_function_final_func): int32{.cdecl,
mylib, importc: "sqlite3_create_function16".}
proc aggregate_count*(para1: Pcontext): int32{.cdecl, mylib,
importc: "sqlite3_aggregate_count".}
proc value_blob*(para1: PValue): pointer{.cdecl, mylib,
importc: "sqlite3_value_blob".}
proc value_bytes*(para1: PValue): int32{.cdecl, mylib,
importc: "sqlite3_value_bytes".}
proc value_bytes16*(para1: PValue): int32{.cdecl, mylib,
importc: "sqlite3_value_bytes16".}
proc value_double*(para1: PValue): float64{.cdecl, mylib,
importc: "sqlite3_value_double".}
proc value_int*(para1: PValue): int32{.cdecl, mylib,
importc: "sqlite3_value_int".}
proc value_int64*(para1: PValue): int64{.cdecl, mylib,
importc: "sqlite3_value_int64".}
proc value_text*(para1: PValue): cstring{.cdecl, mylib,
importc: "sqlite3_value_text".}
proc value_text16*(para1: PValue): pointer{.cdecl, mylib,
importc: "sqlite3_value_text16".}
proc value_text16le*(para1: PValue): pointer{.cdecl, mylib,
importc: "sqlite3_value_text16le".}
proc value_text16be*(para1: PValue): pointer{.cdecl, mylib,
importc: "sqlite3_value_text16be".}
proc value_type*(para1: PValue): int32{.cdecl, mylib,
importc: "sqlite3_value_type".}
proc aggregate_context*(para1: Pcontext, nBytes: int32): pointer{.cdecl,
mylib, importc: "sqlite3_aggregate_context".}
proc user_data*(para1: Pcontext): pointer{.cdecl, mylib,
importc: "sqlite3_user_data".}
proc get_auxdata*(para1: Pcontext, para2: int32): pointer{.cdecl, mylib,
importc: "sqlite3_get_auxdata".}
proc set_auxdata*(para1: Pcontext, para2: int32, para3: pointer,
para4: proc (para1: pointer){.cdecl.}){.cdecl, mylib,
importc: "sqlite3_set_auxdata".}
proc result_blob*(para1: Pcontext, para2: pointer, para3: int32,
para4: Result_func){.cdecl, mylib,
importc: "sqlite3_result_blob".}
proc result_double*(para1: Pcontext, para2: float64){.cdecl, mylib,
importc: "sqlite3_result_double".}
proc result_error*(para1: Pcontext, para2: cstring, para3: int32){.cdecl,
mylib, importc: "sqlite3_result_error".}
proc result_error16*(para1: Pcontext, para2: pointer, para3: int32){.cdecl,
mylib, importc: "sqlite3_result_error16".}
proc result_int*(para1: Pcontext, para2: int32){.cdecl, mylib,
importc: "sqlite3_result_int".}
proc result_int64*(para1: Pcontext, para2: int64){.cdecl, mylib,
importc: "sqlite3_result_int64".}
proc result_null*(para1: Pcontext){.cdecl, mylib,
importc: "sqlite3_result_null".}
proc result_text*(para1: Pcontext, para2: cstring, para3: int32,
para4: Result_func){.cdecl, mylib,
importc: "sqlite3_result_text".}
proc result_text16*(para1: Pcontext, para2: pointer, para3: int32,
para4: Result_func){.cdecl, mylib,
importc: "sqlite3_result_text16".}
proc result_text16le*(para1: Pcontext, para2: pointer, para3: int32,
para4: Result_func){.cdecl, mylib,
importc: "sqlite3_result_text16le".}
proc result_text16be*(para1: Pcontext, para2: pointer, para3: int32,
para4: Result_func){.cdecl, mylib,
importc: "sqlite3_result_text16be".}
proc result_value*(para1: Pcontext, para2: PValue){.cdecl, mylib,
importc: "sqlite3_result_value".}
proc create_collation*(para1: PSqlite3, zName: cstring, eTextRep: int32,
para4: pointer, xCompare: Create_collation_func): int32{.
cdecl, mylib, importc: "sqlite3_create_collation".}
proc create_collation16*(para1: PSqlite3, zName: cstring, eTextRep: int32,
para4: pointer, xCompare: Create_collation_func): int32{.
cdecl, mylib, importc: "sqlite3_create_collation16".}
proc collation_needed*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{.
cdecl, mylib, importc: "sqlite3_collation_needed".}
proc collation_needed16*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{.
cdecl, mylib, importc: "sqlite3_collation_needed16".}
proc libversion*(): cstring{.cdecl, mylib, importc: "sqlite3_libversion".}
#Alias for allowing better code portability (win32 is not working with external variables)
proc version*(): cstring{.cdecl, mylib, importc: "sqlite3_libversion".}
# Not published functions
proc libversion_number*(): int32{.cdecl, mylib,
importc: "sqlite3_libversion_number".}
proc backup_init*(pDest: PSqlite3, zDestName: cstring, pSource: PSqlite3, zSourceName: cstring): PSqlite3_Backup {.
cdecl, mylib, importc: "sqlite3_backup_init".}
proc backup_step*(pBackup: PSqlite3_Backup, nPage: int32): int32 {.cdecl, mylib, importc: "sqlite3_backup_step".}
proc backup_finish*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_finish".}
proc backup_pagecount*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_pagecount".}
proc backup_remaining*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_remaining".}
proc sqlite3_sleep*(t: int64): int64 {.cdecl, mylib, importc: "sqlite3_sleep".}
#function sqlite3_key(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_key';
#function sqlite3_rekey(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_rekey';
#function sqlite3_sleep(_para1:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_sleep';
#function sqlite3_expired(_para1:Psqlite3_stmt):longint;cdecl; external Sqlite3Lib name 'sqlite3_expired';
#function sqlite3_global_recover:longint;cdecl; external Sqlite3Lib name 'sqlite3_global_recover';
# implementation
when defined(nimHasStyleChecks):
{.pop.}

View File

@@ -115,10 +115,10 @@ pkg "nimquery", url = "https://github.com/nim-lang/nimquery", useHead = true
pkg "nimsl"
pkg "nimsvg"
pkg "nimterop", "nimble minitest"
pkg "nimwc", "nim c nimwc.nim"
pkg "nimwc", "nim c nimwc.nim", allowFailure = true
pkg "nimx", "nim c --threads:on test/main.nim", allowFailure = true
pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
pkg "norm", "testament r tests/sqlite/trows.nim"
pkg "norm", "testament r tests/sqlite/trows.nim", allowFailure = true
pkg "npeg", "nimble testarc"
pkg "numericalnim", "nimble nimCI"
pkg "optionsutils"

View File

@@ -39,11 +39,6 @@ import
cpuload,
critbits,
cstrutils,
db_common,
db_mysql,
db_odbc,
db_postgres,
db_sqlite,
deques,
distros,
dynlib,
@@ -95,7 +90,6 @@ import
pegs,
posix_utils,
prelude,
punycode,
random,
rationals,
rdstdin,

View File

@@ -25,7 +25,7 @@ import std/[
# Strings:
cstrutils, editdistance, wordwrap, parseutils, ropes,
pegs, punycode, strformat, strmisc, strscans, strtabs,
pegs, strformat, strmisc, strscans, strtabs,
strutils, unicode, unidecode,
# fails due to FFI: encodings

View File

@@ -1,4 +1,5 @@
discard """
disabled: true
output: "Database created successfully!"
"""

View File

@@ -1,4 +1,5 @@
discard """
disabled: true
action: compile
matrix: "--threads:off"
"""

View File

@@ -1,4 +1,5 @@
discard """
disabled: true
outputsub: "All tests finished successfully!"
"""

View File

@@ -1,25 +0,0 @@
discard """
action: "compile"
"""
import db_mysql, db_odbc, db_postgres
import os
from stdtest/specialpaths import buildDir
block:
block:
const dbName = buildDir / "db.sqlite3"
var db = db_mysql.open(dbName, "", "", "")
discard tryInsertId(db, sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)", "t")
block:
const dbName = buildDir / "db.odbc"
var db = db_odbc.open(dbName, "", "", "")
discard tryInsertId(db, sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)", "t")
block:
const dbName = buildDir / "db.postgres"
var db = db_postgres.open(dbName, "", "", "")
discard tryInsertId(db, sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)", "t")

View File

@@ -1,5 +0,0 @@
import std/db_mysql
import std/assertions
doAssert dbQuote("SELECT * FROM foo WHERE col1 = 'bar_baz'") == "'SELECT * FROM foo WHERE col1 = \\'bar_baz\\''"
doAssert dbQuote("SELECT * FROM foo WHERE col1 LIKE '%bar_baz%'") == "'SELECT * FROM foo WHERE col1 LIKE \\'%bar_baz%\\''"

View File

@@ -1,206 +0,0 @@
import punycode, std/unicode
import std/assertions
doAssert(decode(encode("", "bücher")) == "bücher")
doAssert(decode(encode("münchen")) == "münchen")
doAssert encode("xn--", "münchen") == "xn--mnchen-3ya"
# source: https://datatracker.ietf.org/doc/html/rfc3492.html#section-7
let punycode_testcases = [
# (A) Arabic (Egyptian):
(
input:
"\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" &
"\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
output:
"egbpdaj6bu4bxfgehfvwxn"
),
# (B) Chinese (simplified):
(
input:
"\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
output:
"ihqwcrb4cv8a8dqg056pqjye"
),
# (C) Chinese (traditional):
(
input:
"\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
output:
"ihqwctvzc91f659drss3x8bo0yb"
),
# (D) Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky
(
input:
"\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" &
"\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" &
"\u0065\u0073\u006B\u0079",
output:
"Proprostnemluvesky-uyb24dma41a"
),
# (E) Hebrew:
(
input:
"\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" &
"\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" &
"\u05D1\u05E8\u05D9\u05EA",
output:
"4dbcagdahymbxekheh6e0a7fei0b"
),
# (F) Hindi (Devanagari):
(
input:
"\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" &
"\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" &
"\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" &
"\u0939\u0948\u0902",
output:
"i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd"
),
# (G) Japanese (kanji and hiragana):
(
input:
"\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" &
"\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
output:
"n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa"
),
# (H) Korean (Hangul syllables):
(
input:
"\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" &
"\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" &
"\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
output:
"989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c"
),
# (I) Russian (Cyrillic):
(
input:
"\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" &
"\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" &
"\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" &
"\u0438",
output:
"b1abfaaepdrnnbgefbaDotcwatmq2g4l"
),
# (J) Spanish: Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol
(
input:
"\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" &
"\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" &
"\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" &
"\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" &
"\u0061\u00F1\u006F\u006C",
output:
"PorqunopuedensimplementehablarenEspaol-fmd56a"
),
# (K) Vietnamese:
# T<adotbelow>isaoh<odotbelow>kh<ocirc>ngth<ecirchookabove>ch\
# <ihookabove>n<oacute>iti<ecircacute>ngVi<ecircdotbelow>t
(
input:
"\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" &
"\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" &
"\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" &
"\u0056\u0069\u1EC7\u0074",
output:
"TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g"
),
# (L) 3<nen>B<gumi><kinpachi><sensei>
(
input:
"\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
output:
"3B-ww4c5e180e575a65lsy2b"
),
# (M) <amuro><namie>-with-SUPER-MONKEYS
(
input:
"\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" &
"\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" &
"\u004F\u004E\u004B\u0045\u0059\u0053",
output:
"-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n"
),
# (N) Hello-Another-Way-<sorezore><no><basho>
(
input:
"\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" &
"\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" &
"\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
output:
"Hello-Another-Way--fc4qua05auwb3674vfr0b"
),
# (O) <hitotsu><yane><no><shita>2
(
input:
"\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
output:
"2-u9tlzr9756bt3uc0v"
),
# (P) Maji<de>Koi<suru>5<byou><mae>
(
input:
"\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" &
"\u308B\u0035\u79D2\u524D",
output:
"MajiKoi5-783gue6qz075azm5e"
),
# (Q) <pafii>de<runba>
(
input:
"\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
output:
"de-jg4avhby1noc0d"
),
# (R) <sono><supiido><de>
(
input:
"\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
output:
"d9juau41awczczp"
),
# (S) -> $1.00 <-
(
input:
"\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" &
"\u003C\u002D",
output:
"-> $1.00 <--"
)
]
block encodeTests:
for (uni, puny) in punycode_testcases:
# Need to convert both strings to lower case, since
# some of the extended encodings use upper case, but our
# code produces only lower case. Converting just puny to
# lower is also insufficient, since some of the input characters
# are upper case.
doAssert encode(uni).toLower() == puny.toLower()
block decodeTests:
for (uni, puny) in punycode_testcases:
doAssert decode(puny) == uni
block decodeInvalidTest:
doAssertRaises(PunyError): discard decode("xn--w&")

View File

@@ -1,79 +0,0 @@
discard """
action: "run"
exitcode: 0
"""
import db_sqlite
import random
import os
from stdtest/specialpaths import buildDir
import std/assertions
block tsqlitebindatas: ## db_sqlite binary data
const dbName = buildDir / "tsqlitebindatas.db"
let origName = "Bobby"
var orig = newSeq[float64](150)
randomize()
for x in orig.mitems:
x = rand(1.0)/10.0
discard tryRemoveFile(dbName)
let db = open(dbName, "", "", "")
let createTableStr = sql"""CREATE TABLE test(
id INTEGER NOT NULL PRIMARY KEY,
name TEXT,
data BLOB
)
"""
db.exec(createTableStr)
var dbuf = newSeq[byte](orig.len*sizeof(float64))
copyMem(addr(dbuf[0]), addr(orig[0]), dbuf.len)
var insertStmt = db.prepare("INSERT INTO test (id, name, data) VALUES (?, ?, ?)")
insertStmt.bindParams(1, origName, dbuf)
let bres = db.tryExec(insertStmt)
doAssert(bres)
finalize(insertStmt)
var nameTest = db.getValue(sql"SELECT name FROM test WHERE id = ?", 1)
doAssert nameTest == origName
var dataTest = db.getValue(sql"SELECT data FROM test WHERE id = ?", 1)
let seqSize = int(dataTest.len*sizeof(byte)/sizeof(float64))
var res: seq[float64] = newSeq[float64](seqSize)
copyMem(addr(res[0]), addr(dataTest[0]), dataTest.len)
doAssert res.len == orig.len
doAssert res == orig
db.close()
doAssert tryRemoveFile(dbName)
block:
block:
const dbName = buildDir / "db.sqlite3"
var db = db_sqlite.open(dbName, "", "", "")
var witness = false
try:
db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);"))
db.exec(sql("REPLACE INTO table (url, another_field) VALUES (?, '123');"))
except DbError as e:
witness = true
doAssert e.msg == "The number of \"?\" given exceeds the number of parameters present in the query."
finally:
db.close()
removeFile(dbName)
doAssert witness
block:
const dbName = buildDir / "db.sqlite3"
var db = db_sqlite.open(dbName, "", "", "")
try:
db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);"))
db.exec(sql("INSERT INTO table1 (url, other_field) VALUES (?, ?);"), "http://domain.com/test?param=1", 123)
finally:
db.close()
removeFile(dbName)

View File

@@ -17,7 +17,7 @@ import std/[
# Strings:
editdistance, wordwrap, parseutils, ropes,
pegs, punycode, strformat, strmisc, strscans, strtabs,
pegs, strformat, strmisc, strscans, strtabs,
strutils, unicode, unidecode,
# Generic operator system services:

View File

@@ -17,7 +17,7 @@ import std/[
# Strings:
editdistance, wordwrap, parseutils, ropes,
pegs, punycode, strformat, strmisc, strscans, strtabs,
pegs, strformat, strmisc, strscans, strtabs,
strutils, unicode, unidecode,
# Generic operator system services:

View File

@@ -26,7 +26,7 @@ import std/[
# Strings:
editdistance, wordwrap, parseutils, ropes,
pegs, punycode, strformat, strmisc, strscans, strtabs,
pegs, strformat, strmisc, strscans, strtabs,
strutils, unicode, unidecode, cstrutils,
# works but uses FFI: encodings

View File

@@ -1,8 +0,0 @@
discard """
action: compile
"""
import db_sqlite
var db: DbConn
exec(db, sql"create table blabla()")

View File

@@ -1,332 +1 @@
import db_postgres, strutils
let db = open("localhost", "dom", "", "test")
db.exec(sql"DROP TABLE IF EXISTS myTable")
db.exec(sql("""CREATE TABLE myTable (
id integer PRIMARY KEY,
name varchar(50) not null)"""))
let name = "Dom"
db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
name)
doAssert db.getValue(sql"SELECT name FROM myTable") == name
# Check issue #3513
doAssert db.getValue(sql"SELECT name FROM myTable") == name
# issue #3560
proc addToDb(conn: DbConn, fileId: int, fileName: string): int64 =
result = conn.insertId(sql("INSERT into files (id, filename) VALUES (?, ?)"), fileId, fileName)
db.exec(sql"DROP TABLE IF EXISTS files")
db.exec(sql"DROP TABLE IF EXISTS fileobjects")
db.exec(sql("""CREATE TABLE FILEOBJECTS(
ID SERIAL PRIMARY KEY,
FILE_SIZE INT,
MD5 CHAR(32) NOT NULL UNIQUE
);"""))
db.exec(sql("""CREATE TABLE FILES(
ID SERIAL PRIMARY KEY,
OBJECT_ID INT,
FILENAME TEXT NOT NULL,
URI TEXT,
SCHEME CHAR(10),
PUBLIC BOOLEAN DEFAULT FALSE,
CONSTRAINT fk1_fileobjs FOREIGN KEY (object_id)
REFERENCES fileobjects (id) MATCH SIMPLE
ON DELETE CASCADE
);"""))
let f1 = db.addToDb(1, "hello.tmp")
doAssert f1 == 1
let f2 = db.addToDb(2, "hello2.tmp")
doAssert f2 == 2
# PreparedStmt vs. normal query
try:
echo db.getValue(sql("select * from files where id = $1"), 1)
doAssert false, "Exception expected"
except DbError:
let msg = getCurrentExceptionMsg().normalize
info "DbError",
msg = $msg
doAssert "no parameter" in msg
doAssert "$1" in msg
doAssert db.getValue(sql("select filename from files where id = ?"), 1) == "hello.tmp"
var first = prepare(db, "one", sql"select filename from files where id = $1", 1)
doAssert db.getValue(first, 1) == "hello.tmp"
try:
var second = prepare(db, "two", sql"select filename from files where id = ?", 1)
doAssert false, "Exception expected"
except:
let msg = getCurrentExceptionMsg().normalize
doAssert "expects" in msg
doAssert "$1" in msg
doAssert "parameter substitution" in msg
# issue #3569
db.exec(SqlQuery("DROP TABLE IF EXISTS tags"))
db.exec(SqlQuery("CREATE TABLE tags(id serial UNIQUE, name varchar(255))"))
for i in 1..10:
var name = "t" & $i
echo(name)
discard db.getRow(
SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name]))
# get column details
db.exec(SqlQuery("DROP TABLE IF EXISTS dbtypes;"))
db.exec(SqlQuery("DROP TYPE IF EXISTS custom_enum;"))
db.exec(SqlQuery("CREATE TYPE custom_enum AS ENUM ('1', '2', '3');"))
db.exec(SqlQuery("DROP TYPE IF EXISTS custom_composite;"))
db.exec(SqlQuery("CREATE TYPE custom_composite AS (r double precision, i double precision);"))
db.exec(SqlQuery("""CREATE TABLE dbtypes(
id serial UNIQUE,
bytea_col bytea,
smallint_col smallint,
integer_col integer,
bigint_col bigint,
decimal_col decimal,
numeric_col numeric,
real_col real,
double_precision_col double precision,
smallserial_col smallserial,
serial_col serial,
bigserial_col bigserial,
money_col money,
varchar_col varchar(10),
character_col character(1),
text_col text,
timestamp_col timestamp,
date_col date,
time_col time,
interval_col interval,
bool_col boolean,
custom_enum_col custom_enum,
point_col point,
line_col line,
lseg_col lseg,
box_col box,
path_col path,
polygon_col polygon,
circle_col circle,
cidr_col cidr,
inet_col inet,
macaddr_col macaddr,
bit_col bit,
varbit_col bit(3),
tsvector_col tsvector,
tsquery_col tsquery,
uuid_col uuid,
xml_col xml,
json_col json,
array_col integer[],
custom_composite_col custom_composite,
range_col int4range
);"""))
db.exec(SqlQuery("INSERT INTO dbtypes (id) VALUES(0);"))
var dbCols : DbColumns = @[]
for row in db.instantRows(dbCols, sql"SELECT * FROM dbtypes"):
doAssert len(dbCols) == 42
doAssert dbCols[0].name == "id"
doAssert dbCols[0].typ.kind == DbTypeKind.dbInt
doAssert dbCols[0].typ.name == "int4"
doAssert dbCols[0].typ.size == 4
doAssert dbCols[1].name == "bytea_col"
doAssert dbCols[1].typ.kind == DbTypeKind.dbBlob
doAssert dbCols[1].typ.name == "bytea"
doAssert dbCols[2].name == "smallint_col"
doAssert dbCols[2].typ.kind == DbTypeKind.dbInt
doAssert dbCols[2].typ.name == "int2"
doAssert dbCols[2].typ.size == 2
doAssert dbCols[3].name == "integer_col"
doAssert dbCols[3].typ.kind == DbTypeKind.dbInt
doAssert dbCols[3].typ.name == "int4"
doAssert dbCols[3].typ.size == 4
doAssert dbCols[4].name == "bigint_col"
doAssert dbCols[4].typ.kind == DbTypeKind.dbInt
doAssert dbCols[4].typ.name == "int8"
doAssert dbCols[4].typ.size == 8
doAssert dbCols[5].name == "decimal_col"
doAssert dbCols[5].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[5].typ.name == "numeric"
doAssert dbCols[6].name == "numeric_col"
doAssert dbCols[6].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[6].typ.name == "numeric"
doAssert dbCols[7].name == "real_col"
doAssert dbCols[7].typ.kind == DbTypeKind.dbFloat
doAssert dbCols[7].typ.name == "float4"
doAssert dbCols[8].name == "double_precision_col"
doAssert dbCols[8].typ.kind == DbTypeKind.dbFloat
doAssert dbCols[8].typ.name == "float8"
doAssert dbCols[9].name == "smallserial_col"
doAssert dbCols[9].typ.kind == DbTypeKind.dbInt
doAssert dbCols[9].typ.name == "int2"
doAssert dbCols[10].name == "serial_col"
doAssert dbCols[10].typ.kind == DbTypeKind.dbInt
doAssert dbCols[10].typ.name == "int4"
doAssert dbCols[11].name == "bigserial_col"
doAssert dbCols[11].typ.kind == DbTypeKind.dbInt
doAssert dbCols[11].typ.name == "int8"
doAssert dbCols[12].name == "money_col"
doAssert dbCols[12].typ.kind == DbTypeKind.dbDecimal
doAssert dbCols[12].typ.name == "money"
doAssert dbCols[13].name == "varchar_col"
doAssert dbCols[13].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[13].typ.name == "varchar"
doAssert dbCols[14].name == "character_col"
doAssert dbCols[14].typ.kind == DbTypeKind.dbFixedChar
doAssert dbCols[14].typ.name == "bpchar"
doAssert dbCols[15].name == "text_col"
doAssert dbCols[15].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[15].typ.name == "text"
doAssert dbCols[16].name == "timestamp_col"
doAssert dbCols[16].typ.kind == DbTypeKind.dbTimestamp
doAssert dbCols[16].typ.name == "timestamp"
doAssert dbCols[17].name == "date_col"
doAssert dbCols[17].typ.kind == DbTypeKind.dbDate
doAssert dbCols[17].typ.name == "date"
doAssert dbCols[18].name == "time_col"
doAssert dbCols[18].typ.kind == DbTypeKind.dbTime
doAssert dbCols[18].typ.name == "time"
doAssert dbCols[19].name == "interval_col"
doAssert dbCols[19].typ.kind == DbTypeKind.dbTimeInterval
doAssert dbCols[19].typ.name == "interval"
doAssert dbCols[20].name == "bool_col"
doAssert dbCols[20].typ.kind == DbTypeKind.dbBool
doAssert dbCols[20].typ.name == "bool"
doAssert dbCols[21].name == "custom_enum_col"
doAssert dbCols[21].typ.kind == DbTypeKind.dbUnknown
doAssert parseInt(dbCols[21].typ.name) > 0
doAssert dbCols[22].name == "point_col"
doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint
doAssert dbCols[22].typ.name == "point"
doAssert dbCols[23].name == "line_col"
doAssert dbCols[23].typ.kind == DbTypeKind.dbLine
doAssert dbCols[23].typ.name == "line"
doAssert dbCols[24].name == "lseg_col"
doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg
doAssert dbCols[24].typ.name == "lseg"
doAssert dbCols[25].name == "box_col"
doAssert dbCols[25].typ.kind == DbTypeKind.dbBox
doAssert dbCols[25].typ.name == "box"
doAssert dbCols[26].name == "path_col"
doAssert dbCols[26].typ.kind == DbTypeKind.dbPath
doAssert dbCols[26].typ.name == "path"
doAssert dbCols[27].name == "polygon_col"
doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon
doAssert dbCols[27].typ.name == "polygon"
doAssert dbCols[28].name == "circle_col"
doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle
doAssert dbCols[28].typ.name == "circle"
doAssert dbCols[29].name == "cidr_col"
doAssert dbCols[29].typ.kind == DbTypeKind.dbInet
doAssert dbCols[29].typ.name == "cidr"
doAssert dbCols[30].name == "inet_col"
doAssert dbCols[30].typ.kind == DbTypeKind.dbInet
doAssert dbCols[30].typ.name == "inet"
doAssert dbCols[31].name == "macaddr_col"
doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress
doAssert dbCols[31].typ.name == "macaddr"
doAssert dbCols[32].name == "bit_col"
doAssert dbCols[32].typ.kind == DbTypeKind.dbBit
doAssert dbCols[32].typ.name == "bit"
doAssert dbCols[33].name == "varbit_col"
doAssert dbCols[33].typ.kind == DbTypeKind.dbBit
doAssert dbCols[33].typ.name == "bit"
doAssert dbCols[34].name == "tsvector_col"
doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[34].typ.name == "tsvector"
doAssert dbCols[35].name == "tsquery_col"
doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[35].typ.name == "tsquery"
doAssert dbCols[36].name == "uuid_col"
doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar
doAssert dbCols[36].typ.name == "uuid"
doAssert dbCols[37].name == "xml_col"
doAssert dbCols[37].typ.kind == DbTypeKind.dbXml
doAssert dbCols[37].typ.name == "xml"
doAssert dbCols[38].name == "json_col"
doAssert dbCols[38].typ.kind == DbTypeKind.dbJson
doAssert dbCols[38].typ.name == "json"
doAssert dbCols[39].name == "array_col"
doAssert dbCols[39].typ.kind == DbTypeKind.dbArray
doAssert dbCols[39].typ.name == "int4[]"
doAssert dbCols[40].name == "custom_composite_col"
doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown
doAssert parseInt(dbCols[40].typ.name) > 0
doAssert dbCols[41].name == "range_col"
doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite
doAssert dbCols[41].typ.name == "int4range"
# issue 6571
db.exec(sql"DROP TABLE IF EXISTS DICTIONARY")
db.exec(sql("""CREATE TABLE DICTIONARY(
id SERIAL PRIMARY KEY,
entry VARCHAR(1000) NOT NULL,
definition VARCHAR(4000) NOT NULL
);"""))
var entry = "あっそ"
var definition = "(int) (See ああそうそう) oh, really (uninterested)/oh yeah?/hmmmmm"
discard db.getRow(
sql("INSERT INTO DICTIONARY(entry, definition) VALUES(?, ?) RETURNING id"), entry, definition)
doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition
entry = "Format string entry"
definition = "Format string definition"
db.exec(SqlQuery("INSERT INTO DICTIONARY(entry, definition) VALUES (?, ?)"), entry, definition)
doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition
echo("All tests succeeded!")
db.close()

View File

@@ -2,6 +2,9 @@
import std/[os, strutils, osproc, sets, pathnorm, sequtils]
import officialpackages
export exec
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -48,18 +51,6 @@ proc findNimImpl*(): tuple[path: string, ok: bool] =
proc findNim*(): string = findNimImpl().path
proc exec*(cmd: string, errorcode: int = QuitFailure, additionalPath = "") =
let prevPath = getEnv("PATH")
if additionalPath.len > 0:
var absolute = additionalPath
if not absolute.isAbsolute:
absolute = getCurrentDir() / absolute
echo("Adding to $PATH: ", absolute)
putEnv("PATH", (if prevPath.len > 0: prevPath & PathSep else: "") & absolute)
echo(cmd)
if execShellCmd(cmd) != 0: quit("FAILURE", errorcode)
putEnv("PATH", prevPath)
template inFold*(desc, body) =
if existsEnv("GITHUB_ACTIONS"):
echo "::group::" & desc
@@ -131,11 +122,7 @@ mm.md
""".splitWhitespace().mapIt("doc" / it)
withoutIndex = """
lib/wrappers/mysql.nim
lib/wrappers/sqlite3.nim
lib/wrappers/postgres.nim
lib/wrappers/tinyc.nim
lib/wrappers/odbcsql.nim
lib/wrappers/pcre.nim
lib/wrappers/openssl.nim
lib/posix/posix.nim
@@ -165,6 +152,35 @@ lib/posix/posix_openbsd_amd64.nim
lib/posix/posix_haiku.nim
""".splitWhitespace()
officialPackagesList = """
pkgs/asyncftpclient/src/asyncftpclient.nim
pkgs/smtp/src/smtp.nim
pkgs/punycode/src/punycode.nim
pkgs/db_connector/src/db_connector/db_common.nim
pkgs/db_connector/src/db_connector/db_mysql.nim
pkgs/db_connector/src/db_connector/db_odbc.nim
pkgs/db_connector/src/db_connector/db_postgres.nim
pkgs/db_connector/src/db_connector/db_sqlite.nim
""".splitWhitespace()
officialPackagesListWithoutIndex = """
pkgs/db_connector/src/db_connector/mysql.nim
pkgs/db_connector/src/db_connector/sqlite3.nim
pkgs/db_connector/src/db_connector/postgres.nim
pkgs/db_connector/src/db_connector/odbcsql.nim
pkgs/db_connector/src/db_connector/private/dbutils.nim
""".splitWhitespace()
proc findName(name: string): string =
doAssert name[0..4] == "pkgs/"
var i = 5
while i < name.len:
if name[i] != '/':
inc i
result.add name[i]
else:
break
when (NimMajor, NimMinor) < (1, 1) or not declared(isRelativeTo):
proc isRelativeTo(path, base: string): bool =
let path = path.normalizedPath
@@ -248,7 +264,8 @@ proc buildDoc(nimArgs, destPath: string) =
# call nim for the documentation:
let rst2html = getMd2html()
var
commands = newSeq[string](rst2html.len + len(doc) + withoutIndex.len)
commands = newSeq[string](rst2html.len + len(doc) + withoutIndex.len +
officialPackagesList.len + officialPackagesListWithoutIndex.len)
i = 0
let nim = findNim().quoteShell()
for d in items(rst2html):
@@ -269,6 +286,19 @@ proc buildDoc(nimArgs, destPath: string) =
destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc
for d in items(officialPackagesList):
var nimArgs2 = nimArgs
if d.isRelativeTo("compiler"): doAssert false
commands[i] = nim & " doc $# --outdir:$# --index:on $#" %
[nimArgs2, destPath, d]
i.inc
for d in items(officialPackagesListWithoutIndex):
commands[i] = nim & " doc $# -o:$# $#" %
[nimArgs,
destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc
mexec(commands)
exec(nim & " buildIndex -o:$1/theindex.html $1" % [destPath])
# caveat: this works so long it's called before `buildDocPackages` which
@@ -318,6 +348,7 @@ proc buildJS(): string =
proc buildDocsDir*(args: string, dir: string) =
let args = nimArgs & " " & args
let docHackJsSource = buildJS()
gitClonePackages(@["asyncftpclient", "punycode", "smtp", "db_connector"])
createDir(dir)
buildDocSamples(args, dir)
buildDoc(args, dir) # bottleneck

View File

@@ -0,0 +1,21 @@
import std/[strformat, paths, dirs, envvars]
from std/os import execShellCmd
proc exec*(cmd: string, errorcode: int = QuitFailure, additionalPath = "") =
let prevPath = getEnv("PATH")
if additionalPath.len > 0:
var absolute = Path(additionalPath)
if not absolute.isAbsolute:
absolute = getCurrentDir() / absolute
echo("Adding to $PATH: ", string(absolute))
putEnv("PATH", (if prevPath.len > 0: prevPath & PathSep else: "") & string(absolute))
echo(cmd)
if execShellCmd(cmd) != 0: quit("FAILURE", errorcode)
putEnv("PATH", prevPath)
proc gitClonePackages*(names: seq[string]) =
if not dirExists(Path"pkgs"):
createDir(Path"pkgs")
for name in names:
if not dirExists(Path"pkgs" / Path(name)):
exec fmt"git clone https://github.com/nim-lang/{name} pkgs/{name}"