From 5d978d28a7dd71a5df7155bd65ddb239598314bc Mon Sep 17 00:00:00 2001 From: Jackson Mowry Date: Tue, 8 Aug 2023 06:45:35 -0400 Subject: [PATCH] Initial working example of changes needed and updating test files --- examples/database/sqlite.v | 15 ++++----- vlib/db/sqlite/orm.v | 2 +- vlib/db/sqlite/sqlite.v | 56 ++++++++++++++++++------------- vlib/db/sqlite/sqlite_orm_test.v | 12 +++---- vlib/db/sqlite/sqlite_test.v | 29 ++++++++-------- vlib/orm/orm_sql_or_blocks_test.v | 2 +- 6 files changed, 60 insertions(+), 56 deletions(-) diff --git a/examples/database/sqlite.v b/examples/database/sqlite.v index a97de551ff..2f549af375 100644 --- a/examples/database/sqlite.v +++ b/examples/database/sqlite.v @@ -2,20 +2,19 @@ import db.sqlite fn main() { db := sqlite.connect(':memory:')! - db.exec("create table users (id integer primary key, name text default '');") + db.exec("create table users (id integer primary key, name text default '');") or { panic(err) } - db.exec("insert into users (name) values ('Sam')") - db.exec("insert into users (name) values ('Peter')") - db.exec("insert into users (name) values ('Kate')") + db.exec("insert into users (name) values ('Sam')") or { panic(err) } + db.exec("insert into users (name) values ('Peter')") or { panic(err) } + db.exec("insert into users (name) values ('Kate')") or { panic(err) } - nr_users := db.q_int('select count(*) from users') + nr_users := db.q_int('select count(*) from users') or { panic(err) } println('nr users = ${nr_users}') - name := db.q_string('select name from users where id = 1') + name := db.q_string('select name from users where id = 1') or { panic(err) } assert name == 'Sam' - users, code := db.exec('select * from users') - println('SQL Result code: ${code}') + users := db.exec('select * from users') or { panic(err) } for row in users { println(row.vals) } diff --git a/vlib/db/sqlite/orm.v b/vlib/db/sqlite/orm.v index 52cc7eb46c..cda1703c24 100644 --- a/vlib/db/sqlite/orm.v +++ b/vlib/db/sqlite/orm.v @@ -75,7 +75,7 @@ pub fn (db DB) delete(table string, where orm.QueryData) ! { pub fn (db DB) last_id() int { query := 'SELECT last_insert_rowid();' - return db.q_int(query) + return db.q_int(query) or { 0 } } // DDL (table creation/destroying etc) diff --git a/vlib/db/sqlite/sqlite.v b/vlib/db/sqlite/sqlite.v index 89fd420b20..cc7f5a7e16 100644 --- a/vlib/db/sqlite/sqlite.v +++ b/vlib/db/sqlite/sqlite.v @@ -181,26 +181,32 @@ pub fn (db &DB) get_affected_rows_count() int { } // q_int returns a single integer value, from the first column of the result of executing `query` -pub fn (db &DB) q_int(query string) int { +pub fn (db &DB) q_int(query string) !int { stmt := &C.sqlite3_stmt(unsafe { nil }) defer { C.sqlite3_finalize(stmt) } C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - C.sqlite3_step(stmt) + code := C.sqlite3_step(stmt) + if code != sqlite.sqlite_row { + return db.error_message(code, query) + } res := C.sqlite3_column_int(stmt, 0) return res } // q_string returns a single string value, from the first column of the result of executing `query` -pub fn (db &DB) q_string(query string) string { +pub fn (db &DB) q_string(query string) !string { stmt := &C.sqlite3_stmt(unsafe { nil }) defer { C.sqlite3_finalize(stmt) } C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - C.sqlite3_step(stmt) + code := C.sqlite3_step(stmt) + if code != sqlite.sqlite_row { + return db.error_message(code, query) + } val := unsafe { &u8(C.sqlite3_column_text(stmt, 0)) } return if val != &u8(0) { unsafe { tos_clone(val) } } else { '' } @@ -209,12 +215,16 @@ pub fn (db &DB) q_string(query string) string { // exec executes the query on the given `db`, and returns an array of all the results, alongside any result code. // Result codes: https://www.sqlite.org/rescode.html [manualfree] -pub fn (db &DB) exec(query string) ([]Row, int) { +pub fn (db &DB) exec(query string) ![]Row { stmt := &C.sqlite3_stmt(unsafe { nil }) defer { C.sqlite3_finalize(stmt) } - C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) + mut code := C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) + if code != sqlite.sqlite_ok { + return db.error_message(code, query) + } + nr_cols := C.sqlite3_column_count(stmt) mut res := 0 mut rows := []Row{} @@ -236,24 +246,22 @@ pub fn (db &DB) exec(query string) ([]Row, int) { } rows << row } - return rows, res + return rows } // exec_one executes a query on the given `db`. // It returns either the first row from the result, if the query was successful, or an error. [manualfree] pub fn (db &DB) exec_one(query string) !Row { - rows, code := db.exec(query) + rows := db.exec(query)! defer { unsafe { rows.free() } } if rows.len == 0 { return &SQLError{ msg: 'No rows' - code: code + code: sqlite.sqlite_done } - } else if code != 101 { - return db.error_message(code, query) } res := rows[0] return res @@ -334,8 +342,8 @@ pub fn (db &DB) exec_param(query string, param string) ![]Row { // 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. // The default columns type will be TEXT. -pub fn (db &DB) create_table(table_name string, columns []string) { - db.exec('create table if not exists ${table_name} (' + columns.join(',\n') + ')') +pub fn (db &DB) create_table(table_name string, columns []string) ! { + db.exec('create table if not exists ${table_name} (' + columns.join(',\n') + ')')! } // busy_timeout sets a busy timeout in milliseconds. @@ -351,13 +359,13 @@ pub fn (db &DB) busy_timeout(ms int) int { // .off: No syncs at all. (fastest) // .normal: Sync after each sequence of critical disk operations. // .full: Sync after each critical disk operation (slowest). -pub fn (db &DB) synchronization_mode(sync_mode SyncMode) { +pub fn (db &DB) synchronization_mode(sync_mode SyncMode) ! { if sync_mode == .off { - db.exec('pragma synchronous = OFF;') + db.exec('pragma synchronous = OFF;')! } else if sync_mode == .full { - db.exec('pragma synchronous = FULL;') + db.exec('pragma synchronous = FULL;')! } else { - db.exec('pragma synchronous = NORMAL;') + db.exec('pragma synchronous = NORMAL;')! } } @@ -367,18 +375,18 @@ pub fn (db &DB) synchronization_mode(sync_mode SyncMode) { // .delete: At the conclusion of a transaction, journal file is deleted. // .truncate: Journal file is truncated to a length of zero bytes. // .persist: Journal file is left in place, but the header is overwritten to indicate journal is no longer valid. -pub fn (db &DB) journal_mode(journal_mode JournalMode) { +pub fn (db &DB) journal_mode(journal_mode JournalMode) ! { if journal_mode == .off { - db.exec('pragma journal_mode = OFF;') + db.exec('pragma journal_mode = OFF;')! } else if journal_mode == .delete { - db.exec('pragma journal_mode = DELETE;') + db.exec('pragma journal_mode = DELETE;')! } else if journal_mode == .truncate { - db.exec('pragma journal_mode = TRUNCATE;') + db.exec('pragma journal_mode = TRUNCATE;')! } else if journal_mode == .persist { - db.exec('pragma journal_mode = PERSIST;') + db.exec('pragma journal_mode = PERSIST;')! } else if journal_mode == .memory { - db.exec('pragma journal_mode = MEMORY;') + db.exec('pragma journal_mode = MEMORY;')! } else { - db.exec('pragma journal_mode = MEMORY;') + db.exec('pragma journal_mode = MEMORY;')! } } diff --git a/vlib/db/sqlite/sqlite_orm_test.v b/vlib/db/sqlite/sqlite_orm_test.v index dc31f62244..163a72dbb8 100644 --- a/vlib/db/sqlite/sqlite_orm_test.v +++ b/vlib/db/sqlite/sqlite_orm_test.v @@ -103,11 +103,10 @@ fn test_sqlite_orm() { create table TestCustomSqlType }! - mut result_custom_sql, mut exec_custom_code := db.exec(' + mut result_custom_sql := db.exec(' pragma table_info(TestCustomSqlType); - ') + ')! - assert exec_custom_code == 101 mut table_info_types_results := []string{} information_schema_custom_sql := ['INTEGER', 'INTEGER', 'TEXT', 'REAL', 'NUMERIC', 'TEXT', 'INTEGER', 'INTEGER'] @@ -128,11 +127,10 @@ fn test_sqlite_orm() { create table TestDefaultAtribute }! - mut result_default_sql, mut code := db.exec(' + mut result_default_sql := db.exec(' pragma table_info(TestDefaultAtribute); - ') + ')! - assert code == 101 mut information_schema_data_types_results := []string{} information_schema_default_sql := ['', '', 'CURRENT_TIME', 'CURRENT_DATE', 'CURRENT_TIMESTAMP'] @@ -176,7 +174,7 @@ fn test_get_affected_rows_count() { db.exec('create table EntityToTest( id integer not null constraint tbl_pk primary key, smth integer - );') + );')! fst := EntityToTest{ id: 1 diff --git a/vlib/db/sqlite/sqlite_test.v b/vlib/db/sqlite/sqlite_test.v index c9ac093845..a2f82054ef 100644 --- a/vlib/db/sqlite/sqlite_test.v +++ b/vlib/db/sqlite/sqlite_test.v @@ -35,49 +35,48 @@ fn test_sqlite() { } mut db := sqlite.connect(':memory:') or { panic(err) } assert db.is_open - db.exec('drop table if exists users') - db.exec("create table users (id integer primary key, name text default '');") - db.exec("insert into users (name) values ('Sam')") + db.exec('drop table if exists users')! + db.exec("create table users (id integer primary key, name text default '');")! + db.exec("insert into users (name) values ('Sam')")! assert db.last_insert_rowid() == 1 assert db.get_affected_rows_count() == 1 - db.exec("insert into users (name) values ('Peter')") + db.exec("insert into users (name) values ('Peter')")! assert db.last_insert_rowid() == 2 - db.exec("insert into users (name) values ('Kate')") + 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') + nr_users := db.q_int('select count(*) from users')! assert nr_users == 4 - name := db.q_string('select name from users where id = 1') + 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')") + 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') + users := db.exec('select * from users')! assert users.len == 4 - assert code == 101 - code = db.exec_none('vacuum') + code := db.exec_none('vacuum') assert code == 101 user := db.exec_one('select * from users where id = 3') or { panic(err) } println(user) assert user.vals.len == 2 - db.exec("update users set name='zzzz' where name='qqqq'") + db.exec("update users set name='zzzz' where name='qqqq'")! assert db.get_affected_rows_count() == 0 - db.exec("update users set name='Peter1' where name='Peter'") + 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'") + db.exec("delete from users where name='qqqq'")! assert db.get_affected_rows_count() == 0 - db.exec("delete from users where name='Sam'") + db.exec("delete from users where name='Sam'")! assert db.get_affected_rows_count() == 1 db.close() or { panic(err) } diff --git a/vlib/orm/orm_sql_or_blocks_test.v b/vlib/orm/orm_sql_or_blocks_test.v index 7d281e635a..4b6a000bb0 100644 --- a/vlib/orm/orm_sql_or_blocks_test.v +++ b/vlib/orm/orm_sql_or_blocks_test.v @@ -23,7 +23,7 @@ fn test_ensure_db_exists_and_user_table_is_ok() { assert true eprintln('> drop pre-existing User table...') - db.exec('drop table if exists User') + db.exec('drop table if exists User')! eprintln('> creating User table...') sql db {