check for out-of-memory errors re: sqlite3_column_text/blob/bytes

closes #2
This commit is contained in:
Michael Bradley, Jr 2022-07-08 12:49:35 -05:00 committed by Michael Bradley
parent 1a1a1ac642
commit f634c2f5ae
2 changed files with 63 additions and 4 deletions

View File

@ -136,9 +136,26 @@ template journalModePragmaStmt*(env: SQLite): RawStmtPtr =
s.dispose
return failure $sqlite3_errstr(x)
if (let x = $sqlite3_column_text(s, 0).cstring; x != "memory" and x != "wal"):
let
x = sqlite3_column_text(s, 0).cstring
# detect out-of-memory error
# see the conversion table and final paragraph of:
# https://www.sqlite.org/c3ref/column_blob.html
# see also https://www.sqlite.org/rescode.html
# in order to detect an out-of-memory error check that the result is a null
# pointer and that the result code is an error code
if x.isNil:
let
code = sqlite3_errcode(sqlite3_db_handle(s))
if not (code in [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]):
raise (ref Defect)(msg: $sqlite3_errstr(code))
if not ($x in ["memory", "wal"]):
s.dispose
return failure "Invalid pragma result: " & $x
return failure "Invalid pragma result: \"" & $x & "\""
s

View File

@ -185,7 +185,22 @@ proc idCol*(
s: RawStmtPtr,
index = 0): string =
$sqlite3_column_text(s, index.cint).cstring
let
text = sqlite3_column_text(s, index.cint).cstring
# detect out-of-memory error
# see the conversion table and final paragraph of:
# https://www.sqlite.org/c3ref/column_blob.html
# the "id" column is NOT NULL PRIMARY KEY so an out-of-memory error can be
# inferred from a null pointer result
if text.isNil:
let
code = sqlite3_errcode(sqlite3_db_handle(s))
raise (ref Defect)(msg: $sqlite3_errstr(code))
$text
proc dataCol*(
s: RawStmtPtr,
@ -193,9 +208,36 @@ proc dataCol*(
let
i = index.cint
dataBytes = cast[ptr UncheckedArray[byte]](sqlite3_column_blob(s, i))
blob = sqlite3_column_blob(s, i)
# detect out-of-memory error
# see the conversion table and final paragraph of:
# https://www.sqlite.org/c3ref/column_blob.html
# see also https://www.sqlite.org/rescode.html
# the "data" column can be NULL so in order to detect an out-of-memory error
# it is necessary to check that the result is a null pointer and that the
# result code is an error code
if blob.isNil:
let
code = sqlite3_errcode(sqlite3_db_handle(s))
if not (code in [SQLITE_OK, SQLITE_ROW, SQLITE_DONE]):
raise (ref Defect)(msg: $sqlite3_errstr(code))
let
dataLen = sqlite3_column_bytes(s, i)
# an out-of-memory error can be inferred from a null pointer result
if (unsafeAddr dataLen).isNil:
let
code = sqlite3_errcode(sqlite3_db_handle(s))
raise (ref Defect)(msg: $sqlite3_errstr(code))
let
dataBytes = cast[ptr UncheckedArray[byte]](blob)
@(toOpenArray(dataBytes, 0, dataLen - 1))
proc timestampCol*(