From 07b36d69f3c041f7a5f321a80ecee2feddb425f9 Mon Sep 17 00:00:00 2001 From: jacksonmowry <96317858+jacksonmowry@users.noreply.github.com> Date: Mon, 7 Aug 2023 06:00:03 +0000 Subject: [PATCH] db.sqlite: add exec_param_many and exec_param methods (#19071) --- vlib/db/sqlite/sqlite.v | 57 +++++++++++++++++++++++++++++++++++- vlib/db/sqlite/sqlite_test.v | 10 +++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/vlib/db/sqlite/sqlite.v b/vlib/db/sqlite/sqlite.v index ec6e254f55..86ec59aa2b 100644 --- a/vlib/db/sqlite/sqlite.v +++ b/vlib/db/sqlite/sqlite.v @@ -285,7 +285,62 @@ pub fn (db &DB) exec_none(query string) int { return code } -// TODO pub fn (db &DB) exec_param(query string, param string) []Row { +// exec_param_many executes a query with parameters provided as ?, +// and returns either an error on failure, or the full result set on success +pub fn (db &DB) exec_param_many(query string, params []string) ![]Row { + mut stmt := &C.sqlite3_stmt(unsafe { nil }) + defer { + C.sqlite3_finalize(stmt) + } + + mut code := C.sqlite3_prepare_v2(db.conn, &char(query.str), -1, &stmt, 0) + if code != 0 { + return &SQLError{ + msg: unsafe { + cstring_to_vstring(&char(C.sqlite3_errstr(code))) + } + code: code + } + } + + for i, param in params { + code = C.sqlite3_bind_text(stmt, i + 1, voidptr(param.str), param.len, 0) + if code != 0 { + return &SQLError{ + msg: unsafe { cstring_to_vstring(&char(C.sqlite3_errstr(code))) } + code: code + } + } + } + + nr_cols := C.sqlite3_column_count(stmt) + mut res := 0 + mut rows := []Row{} + for { + res = C.sqlite3_step(stmt) + if res != sqlite.sqlite_row { + break + } + mut row := Row{} + for i in 0 .. nr_cols { + val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) } + if val == &u8(0) { + row.vals << '' + } else { + row.vals << unsafe { tos_clone(val) } + } + } + rows << row + } + + return rows +} + +// exec_param executes a query with one parameter provided as a ?, +// and returns either an error on failure, or the full result set on success +pub fn (db &DB) exec_param(query string, param string) ![]Row { + return db.exec_param_many(query, [param]) +} // create_table issues a "create table if not exists" command to the db. // It creates the table named 'table_name', with columns generated from 'columns' array. diff --git a/vlib/db/sqlite/sqlite_test.v b/vlib/db/sqlite/sqlite_test.v index 21a4ebeb80..c9ac093845 100644 --- a/vlib/db/sqlite/sqlite_test.v +++ b/vlib/db/sqlite/sqlite_test.v @@ -44,17 +44,21 @@ fn test_sqlite() { assert db.last_insert_rowid() == 2 db.exec("insert into users (name) values ('Kate')") assert db.last_insert_rowid() == 3 + db.exec_param('insert into users (name) values (?)', 'Tom')! + assert db.last_insert_rowid() == 4 nr_users := db.q_int('select count(*) from users') - assert nr_users == 3 + assert nr_users == 4 name := db.q_string('select name from users where id = 1') assert name == 'Sam' + username := db.exec_param('select name from users where id = ?', '1')! + assert username[0].vals[0] == 'Sam' // this insert will be rejected due to duplicated id db.exec("insert into users (id,name) values (1,'Sam')") assert db.get_affected_rows_count() == 0 users, mut code := db.exec('select * from users') - assert users.len == 3 + assert users.len == 4 assert code == 101 code = db.exec_none('vacuum') assert code == 101 @@ -67,6 +71,8 @@ fn test_sqlite() { db.exec("update users set name='Peter1' where name='Peter'") assert db.get_affected_rows_count() == 1 + db.exec_param_many('update users set name=? where name=?', ['Peter', 'Peter1'])! + assert db.get_affected_rows_count() == 1 db.exec("delete from users where name='qqqq'") assert db.get_affected_rows_count() == 0