v/vlib/orm/orm_null_test.v

317 lines
7.2 KiB
V

// vtest retry: 3
import orm
import db.sqlite
struct MockDBState {
mut:
last string
data []orm.Primitive
where []orm.Primitive
}
struct MockDB {
use_num bool
st &MockDBState = unsafe { nil }
db sqlite.DB
}
fn MockDB.new() &MockDB {
return &MockDB{
st: &MockDBState{}
db: sqlite.connect(':memory:') or { panic(err) }
}
}
fn (db MockDB) select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive {
mut st := db.st
st.last = orm.orm_select_gen(config, '`', false, '?', 5, where)
st.data = data.data
st.where = where.data
return db.db.select(config, data, where)
}
fn (db MockDB) insert(table orm.Table, data orm.QueryData) ! {
mut st := db.st
last, qdata := orm.orm_stmt_gen(.sqlite, table, '`', .insert, false, '?', 1, data,
orm.QueryData{})
st.last = last
st.data = qdata.data
st.where = []orm.Primitive{}
return db.db.insert(table, data)
}
fn (db MockDB) update(table orm.Table, data orm.QueryData, where orm.QueryData) ! {
mut st := db.st
st.last, _ = orm.orm_stmt_gen(.sqlite, table, '`', .update, false, '?', 1, data, where)
st.data = data.data
st.where = where.data
return db.db.update(table, data, where)
}
fn (db MockDB) delete(table orm.Table, where orm.QueryData) ! {
mut st := db.st
st.last, _ = orm.orm_stmt_gen(.sqlite, table, '`', .delete, false, '?', 1, orm.QueryData{},
where)
return db.db.delete(table, where)
}
const typ_to_typename = {
typeof[i8]().idx: 'i8'
typeof[i16]().idx: 'i16'
typeof[int]().idx: 'int'
typeof[i64]().idx: 'i64'
typeof[u8]().idx: 'u8'
typeof[u16]().idx: 'u16'
typeof[u32]().idx: 'u32'
typeof[u64]().idx: 'u64'
typeof[f32]().idx: 'f32'
typeof[f64]().idx: 'f64'
typeof[string]().idx: 'string'
typeof[bool]().idx: 'bool'
orm.serial: 'serial'
orm.time_: 'time'
orm.enum_: 'enum'
}
fn mock_type_from_v(typ int) !string {
return if typ in typ_to_typename {
'${typ_to_typename[typ]}-type'
} else {
error('unknown type ${typ}')
}
}
fn (db MockDB) create(table orm.Table, fields []orm.TableField) ! {
mut st := db.st
st.last = orm.orm_table_gen(.sqlite, table, '`', true, 0, fields, mock_type_from_v,
false)!
return db.db.create(table, fields)
}
fn (db MockDB) drop(table orm.Table) ! {
return db.db.drop(table)
}
fn (db MockDB) last_id() int {
return db.db.last_id()
}
// --
@[table: 'foo']
struct Foo {
mut:
id u64 @[primary; sql: serial]
a string
b string @[default: '"yes"']
c ?string
d ?string = 'hi'
e int
f int @[default: 33]
g ?int
h ?int = 55
}
fn test_option_struct_fields_and_none() {
db := MockDB.new()
sql db {
create table Foo
}!
assert db.st.last == 'CREATE TABLE IF NOT EXISTS `foo` (`id` serial-type NOT NULL, `a` string-type NOT NULL, `b` string-type DEFAULT "yes" NOT NULL, `c` string-type, `d` string-type, `e` int-type NOT NULL, `f` int-type DEFAULT 33 NOT NULL, `g` int-type, `h` int-type, PRIMARY KEY(`id`));'
_ := sql db {
select from Foo where e > 5 && c is none && c !is none && h == 2
}!
assert db.st.last == 'SELECT `id`, `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h` FROM `foo` WHERE `e` > ? AND `c` IS NULL AND `c` IS NOT NULL AND `h` = ?;'
assert db.st.data.len == 0
assert db.st.where.len == 2
assert db.st.where == [orm.Primitive(int(5)), orm.Primitive(int(2))]
foo := Foo{}
sql db {
insert foo into Foo
}!
assert db.st.last == 'INSERT INTO `foo` (`a`, `c`, `d`, `e`, `g`, `h`) VALUES (?, ?, ?, ?, ?, ?);'
assert db.st.data.len == 6
assert db.st.data == [orm.Primitive(string('')), orm.Null{}, orm.Primitive(string('hi')), int(0),
orm.Null{}, int(55)]
id := db.last_id()
res1 := sql db {
select from Foo where id == id
}!
assert db.st.last == 'SELECT `id`, `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h` FROM `foo` WHERE `id` = ?;'
assert db.st.data.len == 0
assert db.st.where.len == 1
assert db.st.where == [orm.Primitive(int(id))]
assert res1.len == 1
assert res1[0] == Foo{
id: 1
a: ''
b: 'yes'
c: none
d: 'hi'
e: 0
f: 33
g: none
h: 55
}
sql db {
update Foo set c = 'yo', d = none, g = 44, h = none where id == id
}!
assert db.st.last == 'UPDATE `foo` SET `c` = ?, `d` = ?, `g` = ?, `h` = ? WHERE `id` = ?;'
assert db.st.data.len == 4
assert db.st.data == [orm.Primitive(string('yo')), orm.Null{}, int(44), orm.Null{}]
assert db.st.where.len == 1
assert db.st.where == [orm.Primitive(int(id))]
res2 := sql db {
select from Foo where id == id
}!
assert db.st.last == 'SELECT `id`, `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h` FROM `foo` WHERE `id` = ?;'
assert db.st.data.len == 0
assert db.st.where.len == 1
assert db.st.where == [orm.Primitive(int(id))]
assert res2.len == 1
assert res2[0] == Foo{
id: 1
a: ''
b: 'yes'
c: 'yo'
d: none
e: 0
f: 33
g: 44
h: none
}
assert sql db {
select count from Foo where a == 'yo'
}! == 0
assert sql db {
select count from Foo where b == 'yes'
}! == 1
assert sql db {
select count from Foo where d == 'yo'
}! == 0
assert sql db {
select count from Foo where f == 33
}! == 1
assert sql db {
select count from Foo where c == 'yo'
}! == 1
assert sql db {
select count from Foo where a == ''
}! == 1
assert sql db {
select count from Foo where d == ''
}! == 0
assert sql db {
select count from Foo where c == ''
}! == 0
assert sql db {
select count from Foo where a is none
}! == 0
assert sql db {
select count from Foo where d is none
}! == 1
assert sql db {
select count from Foo where c is none
}! == 0
assert sql db {
select count from Foo where a !is none
}! == 1
assert sql db {
select count from Foo where d !is none
}! == 0
assert sql db {
select count from Foo where c !is none
}! == 1
}
struct Bar {
id u64 @[primary; sql: serial]
name ?string
age int
}
fn update_bar1(db MockDB, id u64, name ?string) ! {
foo := 66
sql db {
update Bar set name = name, age = age + 3 + foo where id == id
}!
}
fn update_bar2(db MockDB, name ?string, new_name ?string) ! {
sql db {
update Bar set name = new_name where name == name
}!
}
type NameFn = fn () ?string
fn update_bar3(db MockDB, name_fn NameFn, new_name string) ! {
sql db {
update Bar set name = new_name where name == name_fn()
}!
}
fn test_inserting_passed_optionals() {
db := MockDB.new()
entry1 := Bar{}
entry2 := Bar{
name: 'Alice'
age: 55
}
entry3 := Bar{
name: 'Bob'
age: 66
}
sql db {
create table Bar
insert entry1 into Bar
insert entry2 into Bar
insert entry3 into Bar
}!
update_bar1(db, 2, none)!
update_bar1(db, 1, 'hi')!
res1 := sql db {
select from Bar
}!
assert res1.len == 3
assert res1[0].name or { '' } == 'hi'
assert res1[1].name == none
assert res1[2].name or { '' } == 'Bob'
update_bar2(db, none, 'xxx')! // no effect (select using "is none", not "== none")
update_bar2(db, 'hi', none)!
res2 := sql db {
select from Bar
}!
assert res2.len == 3
assert res2[0].name == none
assert res2[1].name == none
assert res2[2].name or { '' } == 'Bob'
update_bar3(db, fn () ?string {
return none // no effect (select using "is none", not "== none")
}, 'yyy')!
update_bar3(db, fn () ?string {
return 'Bob'
}, 'www')!
res3 := sql db {
select from Bar
}!
assert res3.len == 3
assert res3[0].name == none
assert res3[1].name == none
assert res3[2].name or { '' } == 'www'
}