From 649d34ad89e2ac46f711b319a08af09db85b17fa Mon Sep 17 00:00:00 2001 From: ketmar Date: Thu, 9 Sep 2021 20:49:46 +0000 Subject: [PATCH] sq3: added way to explicitly bind texts, blobs and nulls; texts and blobs can be non-transient FossilOrigin-Name: 193d7464935705d31c94f254e35703dd0893f731cbcea9004aa7cd7b692f3eff --- sq3.d | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/sq3.d b/sq3.d index 2a95b89..bae0d72 100644 --- a/sq3.d +++ b/sq3.d @@ -288,11 +288,98 @@ public: fldname[0] = ':'; fldname[1..name.length+1] = name[]; } - auto idx = sqlite3_bind_parameter_index(data.st, fldname.ptr); + immutable idx = sqlite3_bind_parameter_index(data.st, fldname.ptr); if (idx < 1) throw new SQLiteException("invalid field name: '"~name.idup~"'"); return bind!T(idx, value); } + + ref DBStatement bindText (uint idx, const(void)[] text, bool transient=true) { + if (!valid) throw new SQLiteException("cannot bind in invalid statement"); + if (data.stepIndex != 0) throw new SQLiteException("can't bind on busy statement"); + if (idx < 1) { + import std.conv : to; + throw new SQLiteException("invalid field index: "~to!string(idx)); + } + immutable int rc = sqlite3_bind_text(data.st, idx, cast(const(char)*)text.ptr, cast(int)text.length, (transient ? SQLITE_TRANSIENT : SQLITE_STATIC)); + sqcheck(rc); + return this; + } + + ref DBStatement bindText (const(char)[] name, const(void)[] text, bool transient=true) { + if (!valid) throw new SQLiteException("cannot bind in invalid statement"); + if (data.stepIndex != 0) throw new SQLiteException("can't bind on busy statement"); + char[257] fldname = 0; + if (name.length > 255) throw new SQLiteException("field name too long"); + if (name[0] == ':' || name[0] == '?' || name[0] == '@') { + fldname[0..name.length] = name[]; + } else { + fldname[0] = ':'; + fldname[1..name.length+1] = name[]; + } + immutable idx = sqlite3_bind_parameter_index(data.st, fldname.ptr); + if (idx < 1) throw new SQLiteException("invalid field name: '"~name.idup~"'"); + return bindText(cast(uint)idx, text, transient); + } + + + ref DBStatement bindBlob (uint idx, const(void)[] blob, bool transient=true) { + if (!valid) throw new SQLiteException("cannot bind in invalid statement"); + if (data.stepIndex != 0) throw new SQLiteException("can't bind on busy statement"); + if (idx < 1) { + import std.conv : to; + throw new SQLiteException("invalid field index: "~to!string(idx)); + } + immutable int rc = sqlite3_bind_blob(data.st, idx, blob.ptr, cast(int)blob.length, (transient ? SQLITE_TRANSIENT : SQLITE_STATIC)); + sqcheck(rc); + return this; + } + + ref DBStatement bindBlob (const(char)[] name, const(void)[] blob, bool transient=true) { + if (!valid) throw new SQLiteException("cannot bind in invalid statement"); + if (data.stepIndex != 0) throw new SQLiteException("can't bind on busy statement"); + char[257] fldname = 0; + if (name.length > 255) throw new SQLiteException("field name too long"); + if (name[0] == ':' || name[0] == '?' || name[0] == '@') { + fldname[0..name.length] = name[]; + } else { + fldname[0] = ':'; + fldname[1..name.length+1] = name[]; + } + immutable idx = sqlite3_bind_parameter_index(data.st, fldname.ptr); + if (idx < 1) throw new SQLiteException("invalid field name: '"~name.idup~"'"); + return bindBlob(cast(uint)idx, blob, transient); + } + + + ref DBStatement bindNull (uint idx) { + if (!valid) throw new SQLiteException("cannot bind in invalid statement"); + if (data.stepIndex != 0) throw new SQLiteException("can't bind on busy statement"); + if (idx < 1) { + import std.conv : to; + throw new SQLiteException("invalid field index: "~to!string(idx)); + } + immutable int rc = sqlite3_bind_null(data.st, idx); + sqcheck(rc); + return this; + } + + ref DBStatement bindNull (const(char)[] name) { + if (!valid) throw new SQLiteException("cannot bind in invalid statement"); + if (data.stepIndex != 0) throw new SQLiteException("can't bind on busy statement"); + char[257] fldname = 0; + if (name.length > 255) throw new SQLiteException("field name too long"); + if (name[0] == ':' || name[0] == '?' || name[0] == '@') { + fldname[0..name.length] = name[]; + } else { + fldname[0] = ':'; + fldname[1..name.length+1] = name[]; + } + immutable idx = sqlite3_bind_parameter_index(data.st, fldname.ptr); + if (idx < 1) throw new SQLiteException("invalid field name: '"~name.idup~"'"); + return bindNull(cast(uint)idx); + } + private: struct DBRow { private this (DBStatement.Data* adata) { -- 2.11.4.GIT