Merge branch 'devel' of https://github.com/Araq/Nimrod into bigbreak
Conflicts: lib/impure/db_postgres.nim lib/pure/os.nim lib/wrappers/postgres.nim
This commit is contained in:
commit
fc47c0edc7
10 changed files with 135 additions and 44 deletions
|
|
@ -170,6 +170,10 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||||
if sfCompileTime in v.flags: return
|
if sfCompileTime in v.flags: return
|
||||||
var targetProc = p
|
var targetProc = p
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
|
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
||||||
|
a.sons[2].kind == nkEmpty and
|
||||||
|
v.loc.flags * {lfHeader, lfNoDecl} != {}:
|
||||||
|
return
|
||||||
if sfPure in v.flags:
|
if sfPure in v.flags:
|
||||||
# v.owner.kind != skModule:
|
# v.owner.kind != skModule:
|
||||||
targetProc = p.module.preInitProc
|
targetProc = p.module.preInitProc
|
||||||
|
|
@ -834,6 +838,13 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
discard cgsym(p.module, "E_Base")
|
discard cgsym(p.module, "E_Base")
|
||||||
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
|
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
|
||||||
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
|
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
|
||||||
|
if isDefined("nimStdSetjmp"):
|
||||||
|
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||||
|
elif isDefined("nimSigSetjmp"):
|
||||||
|
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
|
||||||
|
elif isDefined("nimRawSetjmp"):
|
||||||
|
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
|
||||||
|
else:
|
||||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||||
var length = sonsLen(t)
|
var length = sonsLen(t)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import
|
||||||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
||||||
options, intsets,
|
options, intsets,
|
||||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms,
|
||||||
rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings,
|
rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings,
|
||||||
semparallel
|
semparallel
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) =
|
||||||
platform.OS[platform.hostOS].name,
|
platform.OS[platform.hostOS].name,
|
||||||
CPU[platform.hostCPU].name]))
|
CPU[platform.hostCPU].name]))
|
||||||
|
|
||||||
const gitHash = gorge("git log -n 1 --format=%H")
|
discard """const gitHash = gorge("git log -n 1 --format=%H")
|
||||||
if gitHash.strip.len == 40:
|
if gitHash.strip.len == 40:
|
||||||
msgWriteln("git hash: " & gitHash)
|
msgWriteln("git hash: " & gitHash)"""
|
||||||
|
|
||||||
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
|
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
|
||||||
usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
|
usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
|
||||||
|
|
|
||||||
|
|
@ -137,3 +137,7 @@ proc initDefines*() =
|
||||||
declareSymbol("emulatedthreadvars")
|
declareSymbol("emulatedthreadvars")
|
||||||
if platform.OS[targetOS].props.contains(ospLacksThreadVars):
|
if platform.OS[targetOS].props.contains(ospLacksThreadVars):
|
||||||
defineSymbol("emulatedthreadvars")
|
defineSymbol("emulatedthreadvars")
|
||||||
|
case targetOS
|
||||||
|
of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx:
|
||||||
|
defineSymbol("nimRawSetjmp")
|
||||||
|
else: discard
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ const
|
||||||
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
||||||
VersionMajor* = 0
|
VersionMajor* = 0
|
||||||
VersionMinor* = 9
|
VersionMinor* = 9
|
||||||
VersionPatch* = 5
|
VersionPatch* = 6
|
||||||
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
||||||
|
|
||||||
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||||
var it: TIdentIter
|
var it: TIdentIter
|
||||||
result = initIdentIter(it, scope.symbols, fn.name)
|
result = initIdentIter(it, scope.symbols, fn.name)
|
||||||
while result != nil:
|
while result != nil:
|
||||||
if result.kind in skProcKinds and
|
if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
|
||||||
sameType(result.typ, fn.typ, flags): return
|
case equalParams(result.typ.n, fn.typ.n)
|
||||||
|
of paramsEqual:
|
||||||
|
return
|
||||||
|
of paramsIncompatible:
|
||||||
|
localError(fn.info, errNotOverloadable, fn.name.s)
|
||||||
|
return
|
||||||
|
of paramsNotEqual:
|
||||||
|
discard
|
||||||
|
|
||||||
result = nextIdentIter(it, scope.symbols)
|
result = nextIdentIter(it, scope.symbols)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nim's Runtime Library
|
# Nim's Runtime Library
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2014 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -19,6 +19,7 @@ type
|
||||||
EDb* = object of IOError ## exception that is raised if a database error occurs
|
EDb* = object of IOError ## exception that is raised if a database error occurs
|
||||||
|
|
||||||
TSqlQuery* = distinct string ## an SQL query string
|
TSqlQuery* = distinct string ## an SQL query string
|
||||||
|
TSqlPrepared* = distinct string ## a identifier for the prepared queries
|
||||||
|
|
||||||
FDb* = object of IOEffect ## effect that denotes a database operation
|
FDb* = object of IOEffect ## effect that denotes a database operation
|
||||||
FReadDb* = object of FDb ## effect that denotes a read operation
|
FReadDb* = object of FDb ## effect that denotes a read operation
|
||||||
|
|
@ -33,7 +34,7 @@ proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
|
||||||
## on, later versions will check the string for valid syntax.
|
## on, later versions will check the string for valid syntax.
|
||||||
result = TSqlQuery(query)
|
result = TSqlQuery(query)
|
||||||
|
|
||||||
proc dbError(db: TDbConn) {.noreturn.} =
|
proc dbError*(db: TDbConn) {.noreturn.} =
|
||||||
## raises an EDb exception.
|
## raises an EDb exception.
|
||||||
var e: ref EDb
|
var e: ref EDb
|
||||||
new(e)
|
new(e)
|
||||||
|
|
@ -67,28 +68,57 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
|
||||||
proc tryExec*(db: TDbConn, query: TSqlQuery,
|
proc tryExec*(db: TDbConn, query: TSqlQuery,
|
||||||
args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
|
args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
|
||||||
## tries to execute the query and returns true if successful, false otherwise.
|
## tries to execute the query and returns true if successful, false otherwise.
|
||||||
var q = dbFormat(query, args)
|
var arr = allocCStringArray(args)
|
||||||
var res = pqExec(db, q)
|
var res = pqexecParams(db, query.string, int32(args.len), nil, arr,
|
||||||
|
nil, nil, 0)
|
||||||
|
deallocCStringArray(arr)
|
||||||
result = pqresultStatus(res) == PGRES_COMMAND_OK
|
result = pqresultStatus(res) == PGRES_COMMAND_OK
|
||||||
pqclear(res)
|
pqclear(res)
|
||||||
|
|
||||||
proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||||
tags: [FReadDB, FWriteDb].} =
|
tags: [FReadDB, FWriteDb].} =
|
||||||
## executes the query and raises EDB if not successful.
|
## executes the query and raises EDB if not successful.
|
||||||
var q = dbFormat(query, args)
|
var arr = allocCStringArray(args)
|
||||||
var res = pqExec(db, q)
|
var res = pqexecParams(db, query.string, int32(args.len), nil, arr,
|
||||||
|
nil, nil, 0)
|
||||||
|
deallocCStringArray(arr)
|
||||||
if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
|
if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
|
||||||
pqclear(res)
|
pqclear(res)
|
||||||
|
|
||||||
|
proc exec*(db: TDbConn, stmtName: TSqlPrepared,
|
||||||
|
args: varargs[string]) {.tags: [FReadDB, FWriteDb].} =
|
||||||
|
var arr = allocCStringArray(args)
|
||||||
|
var res = pqexecPrepared(db, stmtName.string, int32(args.len), arr,
|
||||||
|
nil, nil, 0)
|
||||||
|
deallocCStringArray(arr)
|
||||||
|
if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
|
||||||
|
pqclear(res)
|
||||||
|
|
||||||
proc newRow(L: int): TRow =
|
proc newRow(L: int): TRow =
|
||||||
newSeq(result, L)
|
newSeq(result, L)
|
||||||
for i in 0..L-1: result[i] = ""
|
for i in 0..L-1: result[i] = ""
|
||||||
|
|
||||||
proc setupQuery(db: TDbConn, query: TSqlQuery,
|
proc setupQuery(db: TDbConn, query: TSqlQuery,
|
||||||
args: varargs[string]): PPGresult =
|
args: varargs[string]): PPGresult =
|
||||||
var q = dbFormat(query, args)
|
var arr = allocCStringArray(args)
|
||||||
result = pqExec(db, q)
|
result = pqexecParams(db, query.string, int32(args.len), nil, arr,
|
||||||
if pqresultStatus(result) != PGRES_TUPLES_OK: dbError(db)
|
nil, nil, 0)
|
||||||
|
deallocCStringArray(arr)
|
||||||
|
if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
|
||||||
|
|
||||||
|
proc setupQuery(db: TDbConn, stmtName: TSqlPrepared,
|
||||||
|
args: varargs[string]): PPGresult =
|
||||||
|
var arr = allocCStringArray(args)
|
||||||
|
result = pqexecPrepared(db, stmtName.string, int32(args.len), arr,
|
||||||
|
nil, nil, 0)
|
||||||
|
deallocCStringArray(arr)
|
||||||
|
if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
|
||||||
|
|
||||||
|
proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery;
|
||||||
|
nParams: int): TSqlPrepared =
|
||||||
|
var res = pqprepare(db, stmtName, query.string, int32(nParams), nil)
|
||||||
|
if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
|
||||||
|
return TSqlPrepared(stmtName)
|
||||||
|
|
||||||
proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
|
proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
|
||||||
for col in 0..cols-1:
|
for col in 0..cols-1:
|
||||||
|
|
@ -109,6 +139,17 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
|
||||||
yield result
|
yield result
|
||||||
pqclear(res)
|
pqclear(res)
|
||||||
|
|
||||||
|
iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared,
|
||||||
|
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||||
|
## executes the prepared query and iterates over the result dataset.
|
||||||
|
var res = setupQuery(db, stmtName, args)
|
||||||
|
var L = PQnfields(res)
|
||||||
|
var result = newRow(L)
|
||||||
|
for i in 0..PQntuples(res)-1:
|
||||||
|
setRow(res, result, i, L)
|
||||||
|
yield result
|
||||||
|
PQclear(res)
|
||||||
|
|
||||||
proc getRow*(db: TDbConn, query: TSqlQuery,
|
proc getRow*(db: TDbConn, query: TSqlQuery,
|
||||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||||
## retrieves a single row. If the query doesn't return any rows, this proc
|
## retrieves a single row. If the query doesn't return any rows, this proc
|
||||||
|
|
@ -119,6 +160,14 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
|
||||||
setRow(res, result, 0, L)
|
setRow(res, result, 0, L)
|
||||||
pqclear(res)
|
pqclear(res)
|
||||||
|
|
||||||
|
proc getRow*(db: TDbConn, stmtName: TSqlPrepared,
|
||||||
|
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||||
|
var res = setupQuery(db, stmtName, args)
|
||||||
|
var L = PQnfields(res)
|
||||||
|
result = newRow(L)
|
||||||
|
setRow(res, result, 0, L)
|
||||||
|
PQclear(res)
|
||||||
|
|
||||||
proc getAllRows*(db: TDbConn, query: TSqlQuery,
|
proc getAllRows*(db: TDbConn, query: TSqlQuery,
|
||||||
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
|
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
|
||||||
## executes the query and returns the whole result dataset.
|
## executes the query and returns the whole result dataset.
|
||||||
|
|
@ -126,6 +175,13 @@ proc getAllRows*(db: TDbConn, query: TSqlQuery,
|
||||||
for r in fastRows(db, query, args):
|
for r in fastRows(db, query, args):
|
||||||
result.add(r)
|
result.add(r)
|
||||||
|
|
||||||
|
proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared,
|
||||||
|
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
|
||||||
|
## executes the prepared query and returns the whole result dataset.
|
||||||
|
result = @[]
|
||||||
|
for r in FastRows(db, stmtName, args):
|
||||||
|
result.add(r)
|
||||||
|
|
||||||
iterator rows*(db: TDbConn, query: TSqlQuery,
|
iterator rows*(db: TDbConn, query: TSqlQuery,
|
||||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||||
## same as `fastRows`, but slower and safe.
|
## same as `fastRows`, but slower and safe.
|
||||||
|
|
@ -188,7 +244,7 @@ proc open*(connection, user, password, database: string): TDbConn {.
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
##
|
##
|
||||||
## con = Open("", "", "", "host=localhost port=5432 dbname=mydb")
|
## con = open("", "", "", "host=localhost port=5432 dbname=mydb")
|
||||||
##
|
##
|
||||||
## See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
## See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
||||||
## for more information.
|
## for more information.
|
||||||
|
|
@ -197,5 +253,3 @@ proc open*(connection, user, password, database: string): TDbConn {.
|
||||||
## the nim db api.
|
## the nim db api.
|
||||||
result = pqsetdbLogin(nil, nil, nil, nil, database, user, password)
|
result = pqsetdbLogin(nil, nil, nil, nil, database, user, password)
|
||||||
if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil
|
if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1341,10 +1341,10 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
|
||||||
|
|
||||||
proc rawCreateDir(dir: string) =
|
proc rawCreateDir(dir: string) =
|
||||||
when defined(solaris):
|
when defined(solaris):
|
||||||
if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS:
|
if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
elif defined(unix):
|
elif defined(unix):
|
||||||
if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
|
if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
else:
|
else:
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,22 @@ when defined(macosx):
|
||||||
else:
|
else:
|
||||||
template SIGBUS: expr = SIGSEGV
|
template SIGBUS: expr = SIGSEGV
|
||||||
|
|
||||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
|
||||||
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
|
header: "<setjmp.h>", importc: "siglongjmp".}
|
||||||
|
template c_setjmp(jmpb: C_JmpBuf): cint =
|
||||||
|
proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
|
||||||
|
header: "<setjmp.h>", importc: "sigsetjmp".}
|
||||||
|
c_sigsetjmp(jmpb, 0)
|
||||||
|
elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
|
||||||
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
|
header: "<setjmp.h>", importc: "_longjmp".}
|
||||||
|
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||||
|
header: "<setjmp.h>", importc: "_setjmp".}
|
||||||
|
else:
|
||||||
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
header: "<setjmp.h>", importc: "longjmp".}
|
header: "<setjmp.h>", importc: "longjmp".}
|
||||||
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||||
header: "<setjmp.h>", importc: "setjmp".}
|
header: "<setjmp.h>", importc: "setjmp".}
|
||||||
|
|
||||||
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,8 @@ proc pqexecParams*(conn: PPGconn, command: cstring, nParams: int32,
|
||||||
paramTypes: POid, paramValues: cstringArray,
|
paramTypes: POid, paramValues: cstringArray,
|
||||||
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
|
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
|
||||||
cdecl, dynlib: dllName, importc: "PQexecParams".}
|
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,
|
proc pqexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
|
||||||
paramValues: cstringArray,
|
paramValues: cstringArray,
|
||||||
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
|
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue