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:
Araq 2014-10-04 19:40:23 +02:00
commit fc47c0edc7
10 changed files with 135 additions and 44 deletions

View file

@ -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)

View file

@ -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

View file

@ -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 &

View file

@ -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

View file

@ -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!

View file

@ -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)

View file

@ -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

View file

@ -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:

View file

@ -78,6 +78,19 @@ when defined(macosx):
else: else:
template SIGBUS: expr = SIGSEGV template SIGBUS: expr = SIGSEGV
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) {. 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 {.

View file

@ -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{.