diff --git a/examples/sqlite.v b/examples/sqlite.v index dd545479d2..311a0c064b 100644 --- a/examples/sqlite.v +++ b/examples/sqlite.v @@ -14,7 +14,8 @@ fn main() { name := db.q_string('select name from users where id = 1') assert name == 'Sam' - users := db.exec('select * from users') + users, code := db.exec('select * from users') + println("SQL Result code: $code") for row in users { println(row.vals) } diff --git a/vlib/sqlite/sqlite.v b/vlib/sqlite/sqlite.v index f01d5b5dcc..005193e125 100644 --- a/vlib/sqlite/sqlite.v +++ b/vlib/sqlite/sqlite.v @@ -5,8 +5,8 @@ module sqlite #flag freebsd -Wl -L/usr/local/lib -lsqlite3 #include "sqlite3.h" -struct C.sqlite3 -struct C.sqlite3_stmt +struct C.sqlite3 {} +struct C.sqlite3_stmt {} pub struct DB { mut: @@ -18,21 +18,6 @@ pub mut: vals []string } -pub fn connect(path string) DB { - db := &C.sqlite3(0) - C.sqlite3_open(path.str, &db) - return DB {conn: db} -} - -pub fn (db DB) q_int(query string) int { - stmt := &C.sqlite3_stmt(0) - C.sqlite3_prepare_v2(db.conn, query.str, - 1, &stmt, 0) - C.sqlite3_step(stmt) - res := C.sqlite3_column_int(stmt, 0) - C.sqlite3_finalize(stmt) - return res -} - fn C.sqlite3_column_text(voidptr, int) byteptr fn C.sqlite3_column_int(voidptr, int) int fn C.sqlite3_open() @@ -41,9 +26,29 @@ fn C.sqlite3_prepare_v2() fn C.sqlite3_finalize() fn C.sqlite3_column_count(voidptr) int +// Opens the connection with a database. +pub fn connect(path string) DB { + db := &C.sqlite3(0) + C.sqlite3_open(path.str, &db) + return DB{ + conn: db + } +} + +// Returns a single cell with value int. +pub fn (db DB) q_int(query string) int { + stmt := &C.sqlite3_stmt(0) + C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0) + C.sqlite3_step(stmt) + res := C.sqlite3_column_int(stmt, 0) + C.sqlite3_finalize(stmt) + return res +} + +// Returns a single cell with value string. pub fn (db DB) q_string(query string) string { stmt := &C.sqlite3_stmt(0) - C.sqlite3_prepare_v2(db.conn, query.str, - 1, &stmt, 0) + C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0) C.sqlite3_step(stmt) res := tos_clone(C.sqlite3_column_text(stmt, 0)) C.sqlite3_finalize(stmt) @@ -51,36 +56,48 @@ pub fn (db DB) q_string(query string) string { } -pub fn (db DB) exec(query string) []Row { +// Execute the query on db, return an array of all the results, alongside any result code. +// Result codes: https://www.sqlite.org/rescode.html +pub fn (db DB) exec(query string) ([]Row,int) { stmt := &C.sqlite3_stmt(0) - C.sqlite3_prepare_v2(db.conn, query.str, - 1, &stmt, 0) + C.sqlite3_prepare_v2(db.conn, query.str, -1, &stmt, 0) nr_cols := C.sqlite3_column_count(stmt) - //println('nr cols $nr_cols') + mut res := 0 mut rows := []Row for { - ret := C.sqlite3_step(stmt) - if ret != 0x64 { + res = C.sqlite3_step(stmt) + // Result Code SQLITE_ROW; Another row is available + if res != 100 { break } mut row := Row{} - for i in 0..nr_cols { + for i in 0 .. nr_cols { val := tos_clone(C.sqlite3_column_text(stmt, i)) row.vals << val - //println(val) } rows << row } - return rows + return rows,res } +// Execute a query, handle error code +// Return the first row from the resulting table pub fn (db DB) exec_one(query string) ?Row { - rows := db.exec(query) + rows,code := db.exec(query) + if rows.len == 0 || code != 101 { + return error('SQL Error: Rows #$rows.len Return code $code') + } return rows[0] } -/* +// In case you don't expect any result, but still want an error code +// e.g. INSERT INTO ... VALUES (...) +pub fn (db DB) exec_none(query string) int { + _,code := db.exec(query) + return code +} + +/* TODO pub fn (db DB) exec_param(query string, param string) []Row { } */ - - diff --git a/vlib/sqlite/sqlite_test.v b/vlib/sqlite/sqlite_test.v index 6771db8e72..d43c3b0456 100644 --- a/vlib/sqlite/sqlite_test.v +++ b/vlib/sqlite/sqlite_test.v @@ -10,14 +10,20 @@ fn test_sqlite() { db.exec("insert into users (name) values ('Kate')") nr_users := db.q_int('select count(*) from users') - println('nr users = $nr_users') + assert nr_users == 3 name := db.q_string('select name from users where id = 1') assert name == 'Sam' - users := db.exec('select * from users') + users, mut code := db.exec('select * from users') assert users.len == 3 - for row in users { - println(row.vals) - } -} + assert code == 101 + + code = db.exec_none('vacuum') + assert code == 101 + + user := db.exec_one('select * from users where id = 3') or { + panic(err) + } + assert user.vals.len == 2 +}