summary refs log tree commit diff stats
path: root/lib/impure
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-11-18 01:36:20 +0100
committerAraq <rumpf_a@web.de>2012-11-18 01:36:20 +0100
commit3c0a6a89629884b652bf351cb0cee5c94548effc (patch)
treef9053489e93a46e47701a8218d7cc9bd4b92b97f /lib/impure
parent7f6633a06feeac8d6bd1eb1e6d8e841591326618 (diff)
downloadNim-3c0a6a89629884b652bf351cb0cee5c94548effc.tar.gz
'assert' hides EAssertionFailsure; stdlib makes use of 'tags'
Diffstat (limited to 'lib/impure')
-rw-r--r--lib/impure/db_mongo.nim38
-rwxr-xr-xlib/impure/db_mysql.nim46
-rwxr-xr-xlib/impure/db_postgres.nim38
-rwxr-xr-xlib/impure/db_sqlite.nim42
-rwxr-xr-xlib/impure/rdstdin.nim12
-rwxr-xr-xlib/impure/web.nim2
6 files changed, 113 insertions, 65 deletions
diff --git a/lib/impure/db_mongo.nim b/lib/impure/db_mongo.nim
index 5195e2a09..b7fb325f9 100644
--- a/lib/impure/db_mongo.nim
+++ b/lib/impure/db_mongo.nim
@@ -33,6 +33,10 @@ type
   EDb* = object of EIO ## exception that is raised if a database error occurs
   TDbConn* = TMongo    ## a database connection; alias for ``TMongo``
 
+  FDb* = object of FIO ## effect that denotes a database operation
+  FReadDb* = object of FReadIO   ## effect that denotes a read operation
+  FWriteDb* = object of FWriteIO ## effect that denotes a write operation
+
 proc dbError*(db: TDbConn, msg: string) {.noreturn.} = 
   ## raises an EDb exception with message `msg`.
   var e: ref EDb
@@ -43,12 +47,13 @@ proc dbError*(db: TDbConn, msg: string) {.noreturn.} =
     e.msg = $db.err & " " & msg
   raise e
 
-proc Close*(db: var TDbConn) = 
+proc Close*(db: var TDbConn) {.tags: [FDB].} = 
   ## closes the database connection.
   disconnect(db)
   destroy(db)
 
-proc Open*(host: string = defaultHost, port: int = defaultPort): TDbConn =
+proc Open*(host: string = defaultHost, port: int = defaultPort): TDbConn {.
+  tags: [FDB].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established.
   init(result)
@@ -108,7 +113,8 @@ proc getId*(obj: var TBSon): TOid =
   else:
     raise newException(EInvalidIndex, "_id not in object")
 
-proc insertID*(db: var TDbConn, namespace: string, data: PJsonNode): TOid =
+proc insertID*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {.
+  tags: [FWriteDb].} =
   ## converts `data` to BSON format and inserts it in `namespace`. Returns
   ## the generated OID for the ``_id`` field.
   result = genOid()
@@ -116,11 +122,13 @@ proc insertID*(db: var TDbConn, namespace: string, data: PJsonNode): TOid =
   insert(db, namespace, x)
   destroy(x)
 
-proc insert*(db: var TDbConn, namespace: string, data: PJsonNode) =
+proc insert*(db: var TDbConn, namespace: string, data: PJsonNode) {.
+  tags: [FWriteDb].} =
   ## converts `data` to BSON format and inserts it in `namespace`.  
   discard InsertID(db, namespace, data)
 
-proc update*(db: var TDbConn, namespace: string, obj: var TBSon) =
+proc update*(db: var TDbConn, namespace: string, obj: var TBSon) {.
+  tags: [FReadDB, FWriteDb].} =
   ## updates `obj` in `namespace`.
   var cond: TBson
   init(cond)
@@ -129,13 +137,15 @@ proc update*(db: var TDbConn, namespace: string, obj: var TBSon) =
   update(db, namespace, cond, obj, ord(UPDATE_UPSERT))
   destroy(cond)
 
-proc update*(db: var TDbConn, namespace: string, oid: TOid, obj: PJsonNode) =
+proc update*(db: var TDbConn, namespace: string, oid: TOid, obj: PJsonNode) {.
+  tags: [FReadDB, FWriteDb].} =
   ## updates the data with `oid` to have the new data `obj`.
   var a = jsonToBSon(obj, oid)
   Update(db, namespace, a)
   destroy(a)
 
-proc delete*(db: var TDbConn, namespace: string, oid: TOid) =
+proc delete*(db: var TDbConn, namespace: string, oid: TOid) {.
+  tags: [FWriteDb].} =
   ## Deletes the object belonging to `oid`.
   var cond: TBson
   init(cond)
@@ -144,11 +154,13 @@ proc delete*(db: var TDbConn, namespace: string, oid: TOid) =
   discard remove(db, namespace, cond)
   destroy(cond)
 
-proc delete*(db: var TDbConn, namespace: string, obj: var TBSon) =
+proc delete*(db: var TDbConn, namespace: string, obj: var TBSon) {.
+  tags: [FWriteDb].} =
   ## Deletes the object `obj`.
   delete(db, namespace, getId(obj))
 
-iterator find*(db: var TDbConn, namespace: string): var TBSon =
+iterator find*(db: var TDbConn, namespace: string): var TBSon {.
+  tags: [FReadDB].} =
   ## iterates over any object in `namespace`.
   var cursor: TCursor
   init(cursor, db, namespace)
@@ -157,7 +169,7 @@ iterator find*(db: var TDbConn, namespace: string): var TBSon =
   destroy(cursor)
 
 iterator find*(db: var TDbConn, namespace: string, 
-               query, fields: var TBSon): var TBSon =
+               query, fields: var TBSon): var TBSon {.tags: [FReadDB].} =
   ## yields the `fields` of any document that suffices `query`.
   var cursor = find(db, namespace, query, fields, 0'i32, 0'i32, 0'i32)
   if cursor != nil:
@@ -171,7 +183,8 @@ proc setupFieldnames(fields: varargs[string]): TBSon =
   finish(result)
 
 iterator find*(db: var TDbConn, namespace: string, 
-               query: var TBSon, fields: varargs[string]): var TBSon =
+               query: var TBSon, fields: varargs[string]): var TBSon {.
+               tags: [FReadDB].} =
   ## yields the `fields` of any document that suffices `query`. If `fields` 
   ## is ``[]`` the whole document is yielded.
   var f = setupFieldnames(fields)
@@ -188,7 +201,8 @@ proc setupQuery(query: string): TBSon =
   finish(result)
 
 iterator find*(db: var TDbConn, namespace: string, 
-               query: string, fields: varargs[string]): var TBSon =
+               query: string, fields: varargs[string]): var TBSon {.
+               tags: [FReadDB].} =
   ## yields the `fields` of any document that suffices `query`. If `fields` 
   ## is ``[]`` the whole document is yielded.
   var f = setupFieldnames(fields)
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index 6284b7995..118ed39bb 100755
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -18,7 +18,11 @@ type
   EDb* = object of EIO ## exception that is raised if a database error occurs
 
   TSqlQuery* = distinct string ## an SQL query string
- 
+
+  FDb* = object of FIO ## effect that denotes a database operation
+  FReadDb* = object of FReadIO   ## effect that denotes a read operation
+  FWriteDb* = object of FWriteIO ## effect that denotes a write operation
+
 proc dbError(db: TDbConn) {.noreturn.} = 
   ## raises an EDb exception.
   var e: ref EDb
@@ -60,12 +64,18 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
     else: 
       add(result, c)
   
-proc TryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool =
+proc TryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.
+  tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
   return mysql.RealQuery(db, q, q.len) == 0'i32
 
-proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
+proc rawExec(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
+  var q = dbFormat(query, args)
+  if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db)
+
+proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
+  tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
   var q = dbFormat(query, args)
   if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db)
@@ -80,11 +90,11 @@ proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =
   mysql.FreeResult(sqlres)
   
 iterator FastRows*(db: TDbConn, query: TSqlQuery,
-                   args: varargs[string, `$`]): TRow =
+                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
   ## query, the results can be undefined. For MySQL this is the case!.
-  Exec(db, query, args)
+  rawExec(db, query, args)
   var sqlres = mysql.UseResult(db)
   if sqlres != nil:
     var L = int(mysql.NumFields(sqlres))
@@ -100,9 +110,9 @@ iterator FastRows*(db: TDbConn, query: TSqlQuery,
     properFreeResult(sqlres, row)
 
 proc getRow*(db: TDbConn, query: TSqlQuery,
-             args: varargs[string, `$`]): TRow =
+             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## retrieves a single row.
-  Exec(db, query, args)
+  rawExec(db, query, args)
   var sqlres = mysql.UseResult(db)
   if sqlres != nil:
     var L = int(mysql.NumFields(sqlres))
@@ -115,10 +125,10 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
     properFreeResult(sqlres, row)
 
 proc GetAllRows*(db: TDbConn, query: TSqlQuery, 
-                 args: varargs[string, `$`]): seq[TRow] =
+                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
-  Exec(db, query, args)
+  rawExec(db, query, args)
   var sqlres = mysql.UseResult(db)
   if sqlres != nil:
     var L = int(mysql.NumFields(sqlres))
@@ -134,12 +144,12 @@ proc GetAllRows*(db: TDbConn, query: TSqlQuery,
     mysql.FreeResult(sqlres)
 
 iterator Rows*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): TRow =
+               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## same as `FastRows`, but slower and safe.
   for r in items(GetAllRows(db, query, args)): yield r
 
 proc GetValue*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): string = 
+               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
   ## executes the query and returns the result dataset's the first column 
   ## of the first row. Returns "" if the dataset contains no rows. This uses
   ## `FastRows`, so it inherits its fragile behaviour.
@@ -149,7 +159,7 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
     break
 
 proc TryInsertID*(db: TDbConn, query: TSqlQuery, 
-                  args: varargs[string, `$`]): int64 =
+                  args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## 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)
@@ -159,24 +169,26 @@ proc TryInsertID*(db: TDbConn, query: TSqlQuery,
     result = mysql.InsertId(db)
   
 proc InsertID*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): int64 = 
+               args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = 
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row.
   result = TryInsertID(db, query, args)
   if result < 0: dbError(db)
 
 proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, 
-                       args: varargs[string, `$`]): int64 = 
+                       args: varargs[string, `$`]): int64 {.
+                       tags: [FReadDB, FWriteDb].} = 
   ## runs the query (typically "UPDATE") and returns the
   ## number of affected rows
-  Exec(db, query, args)
+  rawExec(db, query, args)
   result = mysql.AffectedRows(db)
 
-proc Close*(db: TDbConn) = 
+proc Close*(db: TDbConn) {.tags: [FDb].} = 
   ## closes the database connection.
   if db != nil: mysql.Close(db)
 
-proc Open*(connection, user, password, database: string): TDbConn =
+proc Open*(connection, user, password, database: string): TDbConn {.
+  tags: [FDb].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established.
   result = mysql.Init(nil)
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index cb8da75b8..2e2b09bc2 100755
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -18,6 +18,10 @@ type
   EDb* = object of EIO ## exception that is raised if a database error occurs
   
   TSqlQuery* = distinct string ## an SQL query string
+
+  FDb* = object of FIO ## effect that denotes a database operation
+  FReadDb* = object of FReadIO   ## effect that denotes a read operation
+  FWriteDb* = object of FWriteIO ## effect that denotes a write operation
   
 proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
   ## constructs a TSqlQuery from the string `query`. This is supposed to be 
@@ -60,14 +64,15 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
       add(result, c)
   
 proc TryExec*(db: TDbConn, query: TSqlQuery, 
-              args: varargs[string, `$`]): bool =
+              args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
   var res = PQExec(db, q)
   result = PQresultStatus(res) == PGRES_COMMAND_OK
   PQclear(res)
 
-proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
+proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
+  tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
   var q = dbFormat(query, args)
   var res = PQExec(db, q)
@@ -91,7 +96,7 @@ proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
     add(r[col], x)
   
 iterator FastRows*(db: TDbConn, query: TSqlQuery,
-                   args: varargs[string, `$`]): TRow =
+                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
   ## query, the results can be undefined. For Postgres it is safe though.
@@ -104,7 +109,7 @@ iterator FastRows*(db: TDbConn, query: TSqlQuery,
   PQclear(res)
 
 proc getRow*(db: TDbConn, query: TSqlQuery,
-             args: varargs[string, `$`]): TRow =
+             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## retrieves a single row.
   var res = setupQuery(db, query, args)
   var L = PQnfields(res)
@@ -113,38 +118,39 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
   PQclear(res)
 
 proc GetAllRows*(db: TDbConn, query: TSqlQuery, 
-                 args: varargs[string, `$`]): seq[TRow] =
+                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   for r in FastRows(db, query, args):
     result.add(r)
 
 iterator Rows*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): TRow =
+               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## same as `FastRows`, but slower and safe.
   for r in items(GetAllRows(db, query, args)): yield r
 
 proc GetValue*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): string = 
+               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
   ## executes the query and returns the result dataset's the first column 
   ## of the first row. Returns "" if the dataset contains no rows.
   var x = PQgetvalue(setupQuery(db, query, args), 0, 0)
   result = if isNil(x): "" else: $x
   
 proc TryInsertID*(db: TDbConn, query: TSqlQuery, 
-                  args: varargs[string, `$`]): int64 =
+                  args: varargs[string, `$`]): int64  {.tags: [FWriteDb].}=
   ## 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``. 
-  var val = GetValue(db, TSqlQuery(string(query) & " RETURNING id"), args)
-  if val.len > 0:
-    result = ParseBiggestInt(val)
+  var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), 
+    args), 0, 0)
+  if not isNil(x):
+    result = ParseBiggestInt($x)
   else:
     result = -1
 
 proc InsertID*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): int64 = 
+               args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## 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
@@ -153,7 +159,8 @@ proc InsertID*(db: TDbConn, query: TSqlQuery,
   if result < 0: dbError(db)
   
 proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, 
-                       args: varargs[string, `$`]): int64 = 
+                       args: varargs[string, `$`]): int64 {.tags: [
+                       FReadDB, FWriteDb].} = 
   ## executes the query (typically "UPDATE") and returns the
   ## number of affected rows.
   var q = dbFormat(query, args)
@@ -162,11 +169,12 @@ proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
   result = parseBiggestInt($PQcmdTuples(res))
   PQclear(res)
 
-proc Close*(db: TDbConn) = 
+proc Close*(db: TDbConn) {.tags: [FDb].} = 
   ## closes the database connection.
   if db != nil: PQfinish(db)
 
-proc Open*(connection, user, password, database: string): TDbConn =
+proc Open*(connection, user, password, database: string): TDbConn {.
+  tags: [FDb].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established.
   result = PQsetdbLogin(nil, nil, nil, nil, database, user, password)
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
index 4abc2ca97..e9864c599 100755
--- a/lib/impure/db_sqlite.nim
+++ b/lib/impure/db_sqlite.nim
@@ -19,6 +19,10 @@ type
   
   TSqlQuery* = distinct string ## an SQL query string
   
+  FDb* = object of FIO ## effect that denotes a database operation
+  FReadDb* = object of FReadIO   ## effect that denotes a read operation
+  FWriteDb* = object of FWriteIO ## effect that denotes a write operation
+  
 proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
   ## constructs a TSqlQuery from the string `query`. This is supposed to be 
   ## used as a raw-string-literal modifier:
@@ -60,7 +64,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
       add(result, c)
   
 proc TryExec*(db: TDbConn, query: TSqlQuery, 
-              args: varargs[string, `$`]): bool =
+              args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
   var stmt: sqlite3.PStmt
@@ -68,7 +72,8 @@ proc TryExec*(db: TDbConn, query: TSqlQuery,
     if step(stmt) == SQLITE_DONE:
       result = finalize(stmt) == SQLITE_OK
 
-proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
+proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`])  {.
+  tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
   if not TryExec(db, query, args): dbError(db)
   
@@ -89,7 +94,7 @@ proc setRow(stmt: PStmt, r: var TRow, cols: cint) =
     if not isNil(x): add(r[col], x)
   
 iterator FastRows*(db: TDbConn, query: TSqlQuery,
-                   args: varargs[string, `$`]): TRow =
+                   args: varargs[string, `$`]): TRow  {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
   ## query, the results can be undefined. For Sqlite it is safe though.
@@ -102,7 +107,7 @@ iterator FastRows*(db: TDbConn, query: TSqlQuery,
   if finalize(stmt) != SQLITE_OK: dbError(db)
 
 proc getRow*(db: TDbConn, query: TSqlQuery,
-             args: varargs[string, `$`]): TRow =
+             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## retrieves a single row.
   var stmt = setupQuery(db, query, args)
   var L = (columnCount(stmt))
@@ -112,19 +117,19 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
   if finalize(stmt) != SQLITE_OK: dbError(db)
 
 proc GetAllRows*(db: TDbConn, query: TSqlQuery, 
-                 args: varargs[string, `$`]): seq[TRow] =
+                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   for r in FastRows(db, query, args):
     result.add(r)
 
 iterator Rows*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): TRow =
+               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
   ## same as `FastRows`, but slower and safe.
   for r in FastRows(db, query, args): yield r
 
 proc GetValue*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): string = 
+               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
   ## executes the query and returns the result dataset's the first column 
   ## of the first row. Returns "" if the dataset contains no rows.
   var stmt = setupQuery(db, query, args)
@@ -140,16 +145,19 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
     result = ""
   
 proc TryInsertID*(db: TDbConn, query: TSqlQuery, 
-                  args: varargs[string, `$`]): int64 =
+                  args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error. 
-  if tryExec(db, query, args): 
-    result = last_insert_rowid(db)
-  else:
-    result = -1
+  var q = dbFormat(query, args)
+  var stmt: sqlite3.PStmt
+  if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK:
+    if step(stmt) == SQLITE_DONE:
+      if finalize(stmt) == SQLITE_OK:
+        return last_insert_rowid(db)
+  result = -1
 
 proc InsertID*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): int64 = 
+               args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = 
   ## 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
@@ -158,17 +166,19 @@ proc InsertID*(db: TDbConn, query: TSqlQuery,
   if result < 0: dbError(db)
   
 proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, 
-                       args: varargs[string, `$`]): int64 = 
+                       args: varargs[string, `$`]): int64 {.
+                       tags: [FReadDB, FWriteDb].} = 
   ## executes the query (typically "UPDATE") and returns the
   ## number of affected rows.
   Exec(db, query, args)
   result = changes(db)
 
-proc Close*(db: TDbConn) = 
+proc Close*(db: TDbConn) {.tags: [FDB].} = 
   ## closes the database connection.
   if sqlite3.close(db) != SQLITE_OK: dbError(db)
     
-proc Open*(connection, user, password, database: string): TDbConn =
+proc Open*(connection, user, password, database: string): TDbConn {.
+  tags: [FDB].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established. Only the ``connection`` parameter is used for ``sqlite``.
   var db: TDbConn
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index cd614fa98..cf076e929 100755
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -14,12 +14,14 @@
 ## wanted functionality.
 
 when defined(Windows):
-  proc ReadLineFromStdin*(prompt: string): TaintedString = 
+  proc ReadLineFromStdin*(prompt: string): TaintedString {.
+                          tags: [FReadIO, FWriteIO].} = 
     ## Reads a line from stdin.
     stdout.write(prompt)
     result = readLine(stdin)
 
-  proc ReadLineFromStdin*(prompt: string, line: var TaintedString): bool =
+  proc ReadLineFromStdin*(prompt: string, line: var TaintedString): bool {.
+                          tags: [FReadIO, FWriteIO].} =
     ## Reads a `line` from stdin. `line` must not be
     ## ``nil``! May throw an IO exception.
     ## A line of text may be delimited by ``CR``, ``LF`` or
@@ -32,7 +34,8 @@ when defined(Windows):
 else:
   import readline, history
     
-  proc ReadLineFromStdin*(prompt: string): TaintedString = 
+  proc ReadLineFromStdin*(prompt: string): TaintedString {.
+                          tags: [FReadIO, FWriteIO].} =
     var buffer = readline.readLine(prompt)
     if isNil(buffer): quit(0)
     result = TaintedString($buffer)
@@ -40,7 +43,8 @@ else:
       add_history(buffer)
     readline.free(buffer)
 
-  proc ReadLineFromStdin*(prompt: string, line: var TaintedString): bool =
+  proc ReadLineFromStdin*(prompt: string, line: var TaintedString): bool {.
+                          tags: [FReadIO, FWriteIO].} =
     var buffer = readline.readLine(prompt)
     if isNil(buffer): quit(0)
     line = TaintedString($buffer)
diff --git a/lib/impure/web.nim b/lib/impure/web.nim
index a0aea8421..417fe9746 100755
--- a/lib/impure/web.nim
+++ b/lib/impure/web.nim
@@ -58,5 +58,5 @@ proc URLretrieveString*(url: string): TaintedString =
   result = stream.data.TaintedString

 

 when isMainModule:

-  echo URLretrieveString("http://nimrod.ethexor.com/")

+  echo URLretrieveString("http://nimrod-code.org/")