1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

db, json, time, term: change optional to result (#16201)

This commit is contained in:
yuyi 2022-10-26 16:26:28 +08:00 committed by GitHub
parent 2a7420f572
commit 992b502198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 340 additions and 340 deletions

View File

@ -4112,7 +4112,7 @@ println(user.last_name)
println(user.age)
// You can also decode JSON arrays:
sfoos := '[{"x":123},{"x":456}]'
foos := json.decode([]Foo, sfoos)?
foos := json.decode([]Foo, sfoos)!
println(foos[0].x)
println(foos[1].x)
```

View File

@ -8,8 +8,8 @@ fn main() {
password: ''
dbname: 'mysql'
}
conn.connect()?
res := conn.query('show tables')?
conn.connect()!
res := conn.query('show tables')!
for row in res.rows() {
println(row.vals.join(', '))
}

View File

@ -1,7 +1,7 @@
import sqlite
fn main() {
db := sqlite.connect(':memory:')?
db := sqlite.connect(':memory:')!
db.exec("create table users (id integer primary key, name text default '');")
db.exec("insert into users (name) values ('Sam')")

View File

@ -79,7 +79,7 @@ Decode the info to `FrameworkBenchmarkResponse`
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
res := http.get(url) or { panic(err) }
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
return framework_benchmark_response
}
```
@ -91,7 +91,7 @@ Decode the info to `FrameworkBenchmarkResponse`
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
res := http.get(url) or { panic(err) }
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
return framework_benchmark_response
}
```
@ -106,4 +106,4 @@ with the new function
# ROADMAP
02/09/2022
- [ ] select bench (easy)
- [ ] vsql (easy)
- [ ] vsql (easy)

View File

@ -68,7 +68,7 @@ Decode the info to `FrameworkBenchmarkResponse`
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
res := http.get(url) or { panic(err) }
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
return framework_benchmark_response
}
```
@ -80,7 +80,7 @@ Decode the info to `FrameworkBenchmarkResponse`
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
res := http.get(url) or { panic(err) }
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
return framework_benchmark_response
}
```
@ -95,4 +95,4 @@ with the new function
# ROADMAP
02/09/2022
- [ ] select bench (easy)
- [ ] vsql (easy)
- [ ] vsql (easy)

View File

@ -145,24 +145,24 @@ fn update_framework_benchmark_times() !FrameworkPlatform {
return numbers
}
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
fn typescript_sqlite_memory() !FrameworkBenchmarkResponse {
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
res := http.get(url) or { panic(err) }
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
return framework_benchmark_response
}
fn v_sqlite_memory() ?FrameworkBenchmarkResponse {
fn v_sqlite_memory() !FrameworkBenchmarkResponse {
url := 'http://localhost:4000/sqlite-memory/$benchmark_loop_length'
res := http.get(url) or { panic(err) }
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
return framework_benchmark_response
}
fn v_sqlite_file() ?FrameworkBenchmarkResponse {
fn v_sqlite_file() !FrameworkBenchmarkResponse {
// url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
// res := http.get(url) or { panic(err) }
// framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
// framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
framework_benchmark_response := FrameworkBenchmarkResponse{
insert: []
@select: []

View File

@ -1,3 +1,3 @@
chdir('examples/password')?
chdir('examples/password')!
assert execute('./correct.expect').exit_code == 0
assert execute('./incorrect.expect').exit_code == 0

View File

@ -2,6 +2,6 @@ import rand
fn main() {
for _ in 0 .. 10 {
println('${rand.intn(255)?}.${rand.intn(255)?}.${rand.intn(255)?}.${rand.intn(255)?}')
println('${rand.intn(255)!}.${rand.intn(255)!}.${rand.intn(255)!}.${rand.intn(255)!}')
}
}

View File

@ -25,7 +25,7 @@ struct JwtPayload {
permissions string
}
fn (mut app App) service_auth(username string, password string) ?string {
fn (mut app App) service_auth(username string, password string) !string {
mut db := databases.create_db_connection() or {
eprintln(err)
panic(err)
@ -42,7 +42,7 @@ fn (mut app App) service_auth(username string, password string) ?string {
return error('user is not active')
}
db.close()?
db.close()!
bcrypt.compare_hash_and_password(password.bytes(), user.password.bytes()) or {
return error('Failed to auth user, $err')

View File

@ -2,7 +2,7 @@ module databases
import sqlite
pub fn create_db_connection() ?sqlite.DB {
mut db := sqlite.connect('database.db')?
pub fn create_db_connection() !sqlite.DB {
mut db := sqlite.connect('database.db')!
return db
}

View File

@ -28,7 +28,7 @@ fn main() {
println('Employee x: $s')
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2}'
//
y := json.decode(Employee, s)?
y := json.decode(Employee, s)!
//
println(y)
assert y == x

View File

@ -38,9 +38,9 @@ struct Mount {
size u64
}
fn test_decode_u64() ? {
fn test_decode_u64() {
data := '{"size": 10737418240}'
m := json.decode(Mount, data)?
m := json.decode(Mount, data)!
assert m.size == 10737418240
// println(m)
}
@ -62,9 +62,9 @@ mut:
comments []Comment [skip]
}
fn test_skip_fields_should_be_initialised_by_json_decode() ? {
fn test_skip_fields_should_be_initialised_by_json_decode() {
data := '{"total_comments": 55, "id": 123}'
mut task := json.decode(Task, data)?
mut task := json.decode(Task, data)!
assert task.id == 123
assert task.total_comments == 55
assert task.comments == []

View File

@ -4,9 +4,9 @@ struct TodoDto {
foo int
}
fn test_decode_with_encode_arg() ? {
fn test_decode_with_encode_arg() {
body := TodoDto{}
ret := json.decode(TodoDto, json.encode(body))?
ret := json.decode(TodoDto, json.encode(body))!
println(ret)
assert ret.foo == 0
}

View File

@ -10,14 +10,14 @@ struct User {
username string
}
fn func<T>() ?T {
fn func<T>() !T {
text := '{"ok": true, "result":{"id":37467243, "username": "ciao"}}'
a := json.decode(Result<T>, text)?
a := json.decode(Result<T>, text)!
return a.result
}
fn test_decode_with_generic_struct() ? {
ret := func<User>()?
fn test_decode_with_generic_struct() {
ret := func<User>()!
println(ret)
assert ret.id == 37467243
assert ret.username == 'ciao'

View File

@ -12,8 +12,8 @@ fn test_json_decode_with_optional_arg() {
assert true
}
fn print_info() ?string {
dbconf := json.decode(DbConfig, os.read_file('dbconf.json')?)?
fn print_info() !string {
dbconf := json.decode(DbConfig, os.read_file('dbconf.json')!)!
println(dbconf)
return '$dbconf'
}

View File

@ -6,16 +6,16 @@ struct Some {
t Test
}
fn test_json_decode_with_sumtype() ? {
v1 := json.decode(Some, '{"t": ["string", "string2"]}')?
fn test_json_decode_with_sumtype() {
v1 := json.decode(Some, '{"t": ["string", "string2"]}')!
println(v1)
assert v1.t == Test(['string', 'string2'])
v2 := json.decode(Some, '{"t": [11, 22]}')?
v2 := json.decode(Some, '{"t": [11, 22]}')!
println(v2)
assert v2.t == Test([11, 22])
v3 := json.decode(Some, '{"t": [true, false]}')?
v3 := json.decode(Some, '{"t": [true, false]}')!
println(v3)
assert v3.t == Test([true, false])
}

View File

@ -35,7 +35,7 @@ fn C.cJSON_free(voidptr)
// decode tries to decode the provided JSON string, into a V structure.
// If it can not do that, it returns an error describing the reason for
// the parsing failure.
pub fn decode(typ voidptr, s string) ?voidptr {
pub fn decode(typ voidptr, s string) !voidptr {
// compiler implementation
return 0
}

View File

@ -14,12 +14,12 @@ struct Employee {
title JobTitle
}
fn test_simple() ? {
fn test_simple() {
x := Employee{'Peter', 28, 95000.5, .worker}
s := json.encode(x)
// eprintln('Employee x: $s')
assert s == '{"name":"Peter","age":28,"salary":95000.5,"title":2}'
y := json.decode(Employee, s)?
y := json.decode(Employee, s)!
// eprintln('Employee y: $y')
assert y.name == 'Peter'
assert y.age == 28
@ -34,9 +34,9 @@ struct Price {
currency_id string [json: currencyId] = currency_id
}
fn test_field_with_default_expr() ? {
fn test_field_with_default_expr() {
data := '[{"net":1},{"net":2,"currencyId":"cjson"}]'
prices := json.decode([]Price, data)?
prices := json.decode([]Price, data)!
assert prices == [Price{
net: 1
currency_id: 'cconst'
@ -77,7 +77,7 @@ struct SomeGame {
other []Entity
}
fn test_encode_decode_sumtype() ? {
fn test_encode_decode_sumtype() {
t := time.now()
game := SomeGame{
title: 'Super Mega Game'
@ -97,7 +97,7 @@ fn test_encode_decode_sumtype() ? {
assert enc == '{"title":"Super Mega Game","player":{"name":"Monke","_type":"Human"},"other":[{"tag":"Pen","_type":"Item"},{"tag":"Cookie","_type":"Item"},1,"Stool",{"_type":"Time","value":$t.unix_time()}]}'
dec := json.decode(SomeGame, enc)?
dec := json.decode(SomeGame, enc)!
// eprintln('Decoded Game: $dec')
assert game.title == dec.title
@ -106,8 +106,8 @@ fn test_encode_decode_sumtype() ? {
assert (game.other[4] as time.Time).unix_time() == (dec.other[4] as time.Time).unix_time()
}
fn bar<T>(payload string) ?Bar { // ?T doesn't work currently
result := json.decode(T, payload)?
fn bar<T>(payload string) !Bar { // ?T doesn't work currently
result := json.decode(T, payload)!
return result
}
@ -135,11 +135,11 @@ struct User {
pets string [json: 'pet_animals'; raw]
}
fn test_parse_user() ? {
fn test_parse_user() {
s := '{"age": 10, "nums": [1,2,3], "type": 1, "lastName": "Johnson", "IsRegistered": true, "pet_animals": {"name": "Bob", "animal": "Dog"}}'
u2 := json.decode(User2, s)?
u2 := json.decode(User2, s)!
// println(u2)
u := json.decode(User, s)?
u := json.decode(User, s)!
// println(u)
assert u.age == 10
assert u.last_name == 'Johnson'
@ -152,7 +152,7 @@ fn test_parse_user() ? {
assert u.pets == '{"name":"Bob","animal":"Dog"}'
}
fn test_encode_decode_time() ? {
fn test_encode_decode_time() {
user := User2{
age: 25
reg_date: time.new_time(year: 2020, month: 12, day: 22, hour: 7, minute: 23)
@ -160,7 +160,7 @@ fn test_encode_decode_time() ? {
s := json.encode(user)
// println(s)
assert s.contains('"reg_date":1608621780')
user2 := json.decode(User2, s)?
user2 := json.decode(User2, s)!
assert user2.reg_date.str() == '2020-12-22 07:23:00'
// println(user2)
// println(user2.reg_date)
@ -219,8 +219,8 @@ struct Country {
name string
}
fn test_struct_in_struct() ? {
country := json.decode(Country, '{ "name": "UK", "cities": [{"name":"London"}, {"name":"Manchester"}]}')?
fn test_struct_in_struct() {
country := json.decode(Country, '{ "name": "UK", "cities": [{"name":"London"}, {"name":"Manchester"}]}')!
assert country.name == 'UK'
assert country.cities.len == 2
assert country.cities[0].name == 'London'
@ -241,14 +241,14 @@ fn test_encode_map() {
assert out == expected
}
fn test_parse_map() ? {
fn test_parse_map() {
expected := {
'one': 1
'two': 2
'three': 3
'four': 4
}
out := json.decode(map[string]int, '{"one":1,"two":2,"three":3,"four":4}')?
out := json.decode(map[string]int, '{"one":1,"two":2,"three":3,"four":4}')!
// println(out)
assert out == expected
}
@ -259,7 +259,7 @@ struct Data {
extra map[string]map[string]int
}
fn test_nested_type() ? {
fn test_nested_type() {
data_expected := '{"countries":[{"cities":[{"name":"London"},{"name":"Manchester"}],"name":"UK"},{"cities":[{"name":"Donlon"},{"name":"Termanches"}],"name":"KU"}],"users":{"Foo":{"age":10,"nums":[1,2,3],"lastName":"Johnson","IsRegistered":true,"type":0,"pet_animals":"little foo"},"Boo":{"age":20,"nums":[5,3,1],"lastName":"Smith","IsRegistered":false,"type":4,"pet_animals":"little boo"}},"extra":{"2":{"n1":2,"n2":4,"n3":8,"n4":16},"3":{"n1":3,"n2":9,"n3":27,"n4":81}}}'
data := Data{
countries: [
@ -308,7 +308,7 @@ fn test_nested_type() ? {
out := json.encode(data)
// println(out)
assert out == data_expected
data2 := json.decode(Data, data_expected)?
data2 := json.decode(Data, data_expected)!
assert data2.countries.len == data.countries.len
for i in 0 .. 1 {
assert data2.countries[i].name == data.countries[i].name
@ -338,11 +338,11 @@ pub:
data T
}
fn test_generic_struct() ? {
fn test_generic_struct() {
foo_int := Foo<int>{'bar', 12}
foo_enc := json.encode(foo_int)
assert foo_enc == '{"name":"bar","data":12}'
foo_dec := json.decode(Foo<int>, foo_enc)?
foo_dec := json.decode(Foo<int>, foo_enc)!
assert foo_dec.name == 'bar'
assert foo_dec.data == 12
}
@ -376,8 +376,8 @@ struct Message {
id ID
}
fn test_decode_alias_struct() ? {
msg := json.decode(Message, '{"id": "118499178790780929"}')?
fn test_decode_alias_struct() {
msg := json.decode(Message, '{"id": "118499178790780929"}')!
// hacky way of comparing aliased strings
assert msg.id.str() == '118499178790780929'
}
@ -394,20 +394,20 @@ struct List {
items []string
}
fn test_list() ? {
list := json.decode(List, '{"id": 1, "items": ["1", "2"]}')?
fn test_list() {
list := json.decode(List, '{"id": 1, "items": ["1", "2"]}')!
assert list.id == 1
assert list.items == ['1', '2']
}
fn test_list_no_id() ? {
list := json.decode(List, '{"items": ["1", "2"]}')?
fn test_list_no_id() {
list := json.decode(List, '{"items": ["1", "2"]}')!
assert list.id == 0
assert list.items == ['1', '2']
}
fn test_list_no_items() ? {
list := json.decode(List, '{"id": 1}')?
fn test_list_no_items() {
list := json.decode(List, '{"id": 1}')!
assert list.id == 1
assert list.items == []
}
@ -418,15 +418,15 @@ struct Info {
maps map[string]string
}
fn test_decode_null_object() ? {
info := json.decode(Info, '{"id": 22, "items": null, "maps": null}')?
fn test_decode_null_object() {
info := json.decode(Info, '{"id": 22, "items": null, "maps": null}')!
assert info.id == 22
assert '$info.items' == '[]'
assert '$info.maps' == '{}'
}
fn test_decode_missing_maps_field() ? {
info := json.decode(Info, '{"id": 22, "items": null}')?
fn test_decode_missing_maps_field() {
info := json.decode(Info, '{"id": 22, "items": null}')!
assert info.id == 22
assert '$info.items' == '[]'
assert '$info.maps' == '{}'

View File

@ -9,37 +9,37 @@ pub mut:
}
// connect to db
pub fn (mut conn Connection) connect(conn_str string) ?bool {
pub fn (mut conn Connection) connect(conn_str string) !bool {
conn_str_c := unsafe { &C.SQLCHAR(conn_str.str) }
mut retcode := C.SQLRETURN(C.SQL_SUCCESS)
// Allocate environment handle
retcode = C.SQLAllocHandle(C.SQLSMALLINT(C.SQL_HANDLE_ENV), C.SQLHANDLE(C.SQL_NULL_HANDLE),
unsafe { &C.SQLHANDLE(&conn.henv) })
check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_ENV)', C.SQLHANDLE(conn.henv), C.SQLSMALLINT(C.SQL_HANDLE_ENV))?
check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_ENV)', C.SQLHANDLE(conn.henv), C.SQLSMALLINT(C.SQL_HANDLE_ENV))!
// Set the ODBC version environment attribute
retcode = C.SQLSetEnvAttr(conn.henv, C.SQLINTEGER(C.SQL_ATTR_ODBC_VERSION), &C.SQLPOINTER(C.SQL_OV_ODBC3),
C.SQLINTEGER(0))
check_error(retcode, 'SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION)', C.SQLHANDLE(conn.henv),
C.SQLSMALLINT(C.SQL_HANDLE_ENV))?
C.SQLSMALLINT(C.SQL_HANDLE_ENV))!
// Allocate connection handle
retcode = C.SQLAllocHandle(C.SQLSMALLINT(C.SQL_HANDLE_DBC), C.SQLHANDLE(conn.henv),
unsafe { &C.SQLHANDLE(&conn.hdbc) })
check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_DBC)', C.SQLHANDLE(conn.hdbc), C.SQLSMALLINT(C.SQL_HANDLE_DBC))?
check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_DBC)', C.SQLHANDLE(conn.hdbc), C.SQLSMALLINT(C.SQL_HANDLE_DBC))!
// Set login timeout to 5 seconds
retcode = C.SQLSetConnectAttr(conn.hdbc, C.SQLINTEGER(C.SQL_LOGIN_TIMEOUT), C.SQLPOINTER(5),
C.SQLINTEGER(0))
check_error(retcode, 'SQLSetConnectAttr(SQL_LOGIN_TIMEOUT)', C.SQLHANDLE(conn.hdbc),
C.SQLSMALLINT(C.SQL_HANDLE_DBC))?
C.SQLSMALLINT(C.SQL_HANDLE_DBC))!
// Connect to data source
mut outstr := [1024]char{}
mut outstrlen := C.SQLSMALLINT(0)
retcode = C.SQLDriverConnect(conn.hdbc, C.SQLHWND(0), conn_str_c, C.SQLSMALLINT(C.SQL_NTS),
&C.SQLCHAR(&outstr[0]), C.SQLSMALLINT(sizeof(outstr)), &outstrlen, C.SQLUSMALLINT(C.SQL_DRIVER_NOPROMPT))
check_error(retcode, 'SQLDriverConnect()', C.SQLHANDLE(conn.hdbc), C.SQLSMALLINT(C.SQL_HANDLE_DBC))?
check_error(retcode, 'SQLDriverConnect()', C.SQLHANDLE(conn.hdbc), C.SQLSMALLINT(C.SQL_HANDLE_DBC))!
conn.conn_str = conn_str
return true
}
@ -60,18 +60,18 @@ pub fn (mut conn Connection) close() {
}
// query executes a sql query
pub fn (mut conn Connection) query(q string) ?Result {
mut hstmt := new_hstmt(conn.hdbc)?
pub fn (mut conn Connection) query(q string) !Result {
mut hstmt := new_hstmt(conn.hdbc)!
defer {
hstmt.close()
}
hstmt.exec(q)?
hstmt.exec(q)!
affected := hstmt.retrieve_affected_rows()?
affected := hstmt.retrieve_affected_rows()!
hstmt.prepare_read()?
raw_rows := hstmt.read_rows()?
hstmt.prepare_read()!
raw_rows := hstmt.read_rows()!
mut res := Result{
rows: []Row{}
@ -88,7 +88,7 @@ pub fn (mut conn Connection) query(q string) ?Result {
}
// check_error checks odbc return code and extract error string if available
fn check_error(e C.SQLRETURN, s string, h C.SQLHANDLE, t C.SQLSMALLINT) ? {
fn check_error(e C.SQLRETURN, s string, h C.SQLHANDLE, t C.SQLSMALLINT) ! {
if e != C.SQLRETURN(C.SQL_SUCCESS) && e != C.SQLRETURN(C.SQL_SUCCESS_WITH_INFO) {
err_str := extract_error(s, h, t)
return error(err_str)

View File

@ -16,12 +16,12 @@ mut:
}
// new_hstmt constructs a new statement handle
fn new_hstmt(hdbc C.SQLHDBC) ?HStmt {
fn new_hstmt(hdbc C.SQLHDBC) !HStmt {
mut retcode := C.SQLRETURN(C.SQL_SUCCESS)
mut hstmt := C.SQLHSTMT(C.SQL_NULL_HSTMT)
// Allocate statement handle
retcode = C.SQLAllocHandle(C.SQLSMALLINT(C.SQL_HANDLE_STMT), C.SQLHANDLE(hdbc), unsafe { &C.SQLHANDLE(&hstmt) })
check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_STMT)', C.SQLHANDLE(hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_STMT)', C.SQLHANDLE(hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
return HStmt{
hdbc: hdbc
@ -40,32 +40,32 @@ fn (mut h HStmt) close() {
}
// exec executes a Sql statement. Result is stored in odbc driver, and not yet read.
fn (h HStmt) exec(sql string) ? {
fn (h HStmt) exec(sql string) ! {
retcode := C.SQLExecDirect(h.hstmt, sql.str, C.SQLINTEGER(C.SQL_NTS))
check_error(retcode, 'SQLExecDirect()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLExecDirect()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
}
// retrieve_affected_rows returns number of rows affected/modified by the last operation. -1 if not applicable.
fn (h HStmt) retrieve_affected_rows() ?int {
fn (h HStmt) retrieve_affected_rows() !int {
count_ret := C.SQLLEN(0)
retcode := C.SQLRowCount(h.hstmt, &count_ret)
check_error(retcode, 'SQLRowCount()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLRowCount()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
return int(count_ret)
}
fn (h HStmt) retrieve_column_count() ?int {
fn (h HStmt) retrieve_column_count() !int {
mut retcode := C.SQLRETURN(C.SQL_SUCCESS)
col_count_buff := C.SQLSMALLINT(0)
retcode = C.SQLNumResultCols(h.hstmt, &col_count_buff)
check_error(retcode, 'SQLNumResultCols()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLNumResultCols()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
return int(col_count_buff)
}
// allocate buffers and bind them to drivers
fn (mut h HStmt) prepare_read() ? {
fn (mut h HStmt) prepare_read() ! {
mut retcode := C.SQLRETURN(C.SQL_SUCCESS)
column_count := h.retrieve_column_count()?
column_count := h.retrieve_column_count()!
h.column_count = column_count // remember the count because read will need it
h.buffers = [][]char{len: h.column_count}
@ -77,7 +77,7 @@ fn (mut h HStmt) prepare_read() ? {
// find out buffer size needed to read data in this column
retcode = C.SQLColAttribute(h.hstmt, i_col, C.SQLUSMALLINT(C.SQL_DESC_LENGTH),
C.SQLPOINTER(0), C.SQLSMALLINT(0), C.SQLSMALLINT(0), &size_ret)
check_error(retcode, 'SQLColAttribute()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLColAttribute()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
// buffer allocation is the size + 1 to include termination char, since SQL_DESC_LENGTH does not include it.
allocate_size := size_ret + C.SQLLEN(1)
@ -87,7 +87,7 @@ fn (mut h HStmt) prepare_read() ? {
// bind the buffer
retcode = C.SQLBindCol(h.hstmt, C.SQLUSMALLINT(i_col), C.SQLSMALLINT(C.SQL_C_CHAR),
C.SQLPOINTER(&buff[0]), allocate_size, &h.indicators[i])
check_error(retcode, 'SQLBindCol()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLBindCol()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
// record the buffer in HStmt
h.buffers[i] = buff
@ -95,7 +95,7 @@ fn (mut h HStmt) prepare_read() ? {
}
// fetch all rows
fn (h HStmt) read_rows() ?[][]string {
fn (h HStmt) read_rows() ![][]string {
mut retcode := C.SQLRETURN(C.SQL_SUCCESS)
mut res := [][]string{}
@ -116,7 +116,7 @@ fn (h HStmt) read_rows() ?[][]string {
}
} else {
if retcode != C.SQLRETURN(C.SQL_NO_DATA) {
check_error(retcode, 'SQLFetch()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))?
check_error(retcode, 'SQLFetch()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))!
} else {
break
}

View File

@ -37,7 +37,7 @@ pub mut:
}
// connect - create a new connection to the MySQL server.
pub fn (mut conn Connection) connect() ?bool {
pub fn (mut conn Connection) connect() !bool {
instance := C.mysql_init(conn.conn)
conn.conn = C.mysql_real_connect(instance, conn.host.str, conn.username.str, conn.password.str,
conn.dbname.str, conn.port, 0, conn.flag)
@ -50,7 +50,7 @@ pub fn (mut conn Connection) connect() ?bool {
// query - make an SQL query and receive the results.
// `query()` cannot be used for statements that contain binary data;
// Use `real_query()` instead.
pub fn (conn Connection) query(q string) ?Result {
pub fn (conn Connection) query(q string) !Result {
if C.mysql_query(conn.conn, q.str) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}
@ -75,7 +75,7 @@ pub fn (conn Connection) use_result() {
// (Binary data may contain the `\0` character, which `query()`
// interprets as the end of the statement string). In addition,
// `real_query()` is faster than `query()`.
pub fn (mut conn Connection) real_query(q string) ?Result {
pub fn (mut conn Connection) real_query(q string) !Result {
if C.mysql_real_query(conn.conn, q.str, q.len) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}
@ -84,7 +84,7 @@ pub fn (mut conn Connection) real_query(q string) ?Result {
}
// select_db - change the default database for database queries.
pub fn (mut conn Connection) select_db(dbname string) ?bool {
pub fn (mut conn Connection) select_db(dbname string) !bool {
if C.mysql_select_db(conn.conn, dbname.str) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}
@ -94,7 +94,7 @@ pub fn (mut conn Connection) select_db(dbname string) ?bool {
// change_user - change the mysql user for the connection.
// Passing an empty string for the `dbname` parameter, resultsg in only changing
// the user and not changing the default database for the connection.
pub fn (mut conn Connection) change_user(username string, password string, dbname string) ?bool {
pub fn (mut conn Connection) change_user(username string, password string, dbname string) !bool {
mut ret := true
if dbname != '' {
ret = C.mysql_change_user(conn.conn, username.str, password.str, dbname.str)
@ -124,7 +124,7 @@ pub fn (mut conn Connection) autocommit(mode bool) {
// The `wildcard` parameter may contain the wildcard characters `%` or `_`.
// If an empty string is passed, it will return all tables.
// Calling `tables()` is similar to executing query `SHOW TABLES [LIKE wildcard]`.
pub fn (conn &Connection) tables(wildcard string) ?[]string {
pub fn (conn &Connection) tables(wildcard string) ![]string {
cres := C.mysql_list_tables(conn.conn, wildcard.str)
if isnil(cres) {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
@ -157,7 +157,7 @@ pub fn (mut conn Connection) set_option(option_type int, val voidptr) {
// get_option - return the value of an option, settable by `set_option`.
// https://dev.mysql.com/doc/c-api/5.7/en/mysql-get-option.html
pub fn (conn &Connection) get_option(option_type int) ?voidptr {
pub fn (conn &Connection) get_option(option_type int) !voidptr {
ret := unsafe { nil }
if C.mysql_get_option(conn.conn, option_type, &ret) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
@ -167,7 +167,7 @@ pub fn (conn &Connection) get_option(option_type int) ?voidptr {
// refresh - flush the tables or caches, or resets replication server
// information. The connected user must have the `RELOAD` privilege.
pub fn (mut conn Connection) refresh(options u32) ?bool {
pub fn (mut conn Connection) refresh(options u32) !bool {
if C.mysql_refresh(conn.conn, options) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}
@ -175,7 +175,7 @@ pub fn (mut conn Connection) refresh(options u32) ?bool {
}
// reset - resets the connection, and clear the session state.
pub fn (mut conn Connection) reset() ?bool {
pub fn (mut conn Connection) reset() !bool {
if C.mysql_reset_connection(conn.conn) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}
@ -184,7 +184,7 @@ pub fn (mut conn Connection) reset() ?bool {
// ping - pings a server connection, or tries to reconnect if the connection
// has gone down.
pub fn (mut conn Connection) ping() ?bool {
pub fn (mut conn Connection) ping() !bool {
if C.mysql_ping(conn.conn) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}
@ -224,7 +224,7 @@ pub fn (conn &Connection) get_server_version() u64 {
// dump_debug_info - instructs the server to write debugging information
// to the error log. The connected user must have the `SUPER` privilege.
pub fn (mut conn Connection) dump_debug_info() ?bool {
pub fn (mut conn Connection) dump_debug_info() !bool {
if C.mysql_dump_debug_info(conn.conn) != 0 {
return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn))
}

View File

@ -7,20 +7,20 @@ type Prims = f32 | f64 | i16 | i64 | i8 | int | string | u16 | u32 | u64 | u8
// sql expr
pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ?[][]orm.Primitive {
pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive {
query := orm.orm_select_gen(config, '`', false, '?', 0, where)
mut ret := [][]orm.Primitive{}
mut stmt := db.init_stmt(query)
stmt.prepare()?
stmt.prepare()!
mysql_stmt_binder(mut stmt, where)?
mysql_stmt_binder(mut stmt, data)?
mysql_stmt_binder(mut stmt, where)!
mysql_stmt_binder(mut stmt, data)!
if data.data.len > 0 || where.data.len > 0 {
stmt.bind_params()?
stmt.bind_params()!
}
mut status := stmt.execute()?
mut status := stmt.execute()!
num_fields := stmt.get_field_count()
metadata := stmt.gen_metadata()
fields := stmt.fetch_fields(metadata)
@ -99,30 +99,30 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
}
}
stmt.bind_result_buffer()?
stmt.store_result()?
stmt.bind_result_buffer()!
stmt.store_result()!
for {
status = stmt.fetch_stmt()?
status = stmt.fetch_stmt()!
if status == 1 || status == 100 {
break
}
row++
data_list := buffer_to_primitive(dataptr, types, field_types)?
data_list := buffer_to_primitive(dataptr, types, field_types)!
ret << data_list
}
stmt.close()?
stmt.close()!
return ret
}
// sql stmt
pub fn (db Connection) insert(table string, data orm.QueryData) ? {
pub fn (db Connection) insert(table string, data orm.QueryData) ! {
mut converted_primitive_array := db.factory_orm_primitive_converted_from_sql(table,
data)?
data)!
converted_primitive_data := orm.QueryData{
fields: data.fields
@ -134,18 +134,18 @@ pub fn (db Connection) insert(table string, data orm.QueryData) ? {
query, converted_data := orm.orm_stmt_gen(table, '`', .insert, false, '?', 1, converted_primitive_data,
orm.QueryData{})
mysql_stmt_worker(db, query, converted_data, orm.QueryData{})?
mysql_stmt_worker(db, query, converted_data, orm.QueryData{})!
}
pub fn (db Connection) update(table string, data orm.QueryData, where orm.QueryData) ? {
pub fn (db Connection) update(table string, data orm.QueryData, where orm.QueryData) ! {
query, _ := orm.orm_stmt_gen(table, '`', .update, false, '?', 1, data, where)
mysql_stmt_worker(db, query, data, where)?
mysql_stmt_worker(db, query, data, where)!
}
pub fn (db Connection) delete(table string, where orm.QueryData) ? {
pub fn (db Connection) delete(table string, where orm.QueryData) ! {
query, _ := orm.orm_stmt_gen(table, '`', .delete, false, '?', 1, orm.QueryData{},
where)
mysql_stmt_worker(db, query, orm.QueryData{}, where)?
mysql_stmt_worker(db, query, orm.QueryData{}, where)!
}
pub fn (db Connection) last_id() orm.Primitive {
@ -159,31 +159,31 @@ pub fn (db Connection) last_id() orm.Primitive {
}
// table
pub fn (db Connection) create(table string, fields []orm.TableField) ? {
pub fn (db Connection) create(table string, fields []orm.TableField) ! {
query := orm.orm_table_gen(table, '`', true, 0, fields, mysql_type_from_v, false) or {
return err
}
mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})?
mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
}
pub fn (db Connection) drop(table string) ? {
pub fn (db Connection) drop(table string) ! {
query := 'DROP TABLE `$table`;'
mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})?
mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
}
fn mysql_stmt_worker(db Connection, query string, data orm.QueryData, where orm.QueryData) ? {
fn mysql_stmt_worker(db Connection, query string, data orm.QueryData, where orm.QueryData) ! {
mut stmt := db.init_stmt(query)
stmt.prepare()?
mysql_stmt_binder(mut stmt, data)?
mysql_stmt_binder(mut stmt, where)?
stmt.prepare()!
mysql_stmt_binder(mut stmt, data)!
mysql_stmt_binder(mut stmt, where)!
if data.data.len > 0 || where.data.len > 0 {
stmt.bind_params()?
stmt.bind_params()!
}
stmt.execute()?
stmt.close()?
stmt.execute()!
stmt.close()!
}
fn mysql_stmt_binder(mut stmt Stmt, d orm.QueryData) ? {
fn mysql_stmt_binder(mut stmt Stmt, d orm.QueryData) ! {
for data in d.data {
stmt_binder_match(mut stmt, data)
}
@ -237,7 +237,7 @@ fn stmt_binder_match(mut stmt Stmt, data orm.Primitive) {
}
}
fn buffer_to_primitive(data_list []&u8, types []int, field_types []FieldType) ?[]orm.Primitive {
fn buffer_to_primitive(data_list []&u8, types []int, field_types []FieldType) ![]orm.Primitive {
mut res := []orm.Primitive{}
for i, data in data_list {
@ -287,7 +287,7 @@ fn buffer_to_primitive(data_list []&u8, types []int, field_types []FieldType) ?[
}
.type_datetime {
string_time := unsafe { cstring_to_vstring(&char(data)) }
primitive = time.parse(string_time)?
primitive = time.parse(string_time)!
}
else {}
}
@ -302,7 +302,7 @@ fn buffer_to_primitive(data_list []&u8, types []int, field_types []FieldType) ?[
return res
}
fn mysql_type_from_v(typ int) ?string {
fn mysql_type_from_v(typ int) !string {
str := match typ {
orm.type_idx['i8'], orm.type_idx['u8'] {
'TINYINT'
@ -341,8 +341,8 @@ fn mysql_type_from_v(typ int) ?string {
return str
}
fn (db Connection) factory_orm_primitive_converted_from_sql(table string, data orm.QueryData) ?[]orm.Primitive {
mut map_val := db.get_table_data_type_map(table)?
fn (db Connection) factory_orm_primitive_converted_from_sql(table string, data orm.QueryData) ![]orm.Primitive {
mut map_val := db.get_table_data_type_map(table)!
// adapt v type to sql time
mut converted_data := []orm.Primitive{}
@ -363,11 +363,11 @@ fn (db Connection) factory_orm_primitive_converted_from_sql(table string, data o
return converted_data
}
fn (db Connection) get_table_data_type_map(table string) ?map[string]string {
fn (db Connection) get_table_data_type_map(table string) !map[string]string {
data_type_querys := "SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '$table'"
mut map_val := map[string]string{}
results := db.query(data_type_querys)?
results := db.query(data_type_querys)!
db.use_result()
for row in results.rows() {

View File

@ -78,21 +78,21 @@ pub fn (db Connection) init_stmt(query string) Stmt {
}
}
pub fn (stmt Stmt) prepare() ? {
pub fn (stmt Stmt) prepare() ! {
res := C.mysql_stmt_prepare(stmt.stmt, stmt.query.str, stmt.query.len)
if res != 0 && stmt.get_error_msg() != '' {
return stmt.error(res)
}
}
pub fn (stmt Stmt) bind_params() ? {
pub fn (stmt Stmt) bind_params() ! {
res := C.mysql_stmt_bind_param(stmt.stmt, &C.MYSQL_BIND(stmt.binds.data))
if res && stmt.get_error_msg() != '' {
return stmt.error(1)
}
}
pub fn (stmt Stmt) execute() ?int {
pub fn (stmt Stmt) execute() !int {
res := C.mysql_stmt_execute(stmt.stmt)
if res != 0 && stmt.get_error_msg() != '' {
return stmt.error(res)
@ -100,7 +100,7 @@ pub fn (stmt Stmt) execute() ?int {
return res
}
pub fn (stmt Stmt) next() ?int {
pub fn (stmt Stmt) next() !int {
res := C.mysql_stmt_next_result(stmt.stmt)
if res > 0 && stmt.get_error_msg() != '' {
return stmt.error(res)
@ -116,7 +116,7 @@ pub fn (stmt Stmt) fetch_fields(res &C.MYSQL_RES) &C.MYSQL_FIELD {
return C.mysql_fetch_fields(res)
}
pub fn (stmt Stmt) fetch_stmt() ?int {
pub fn (stmt Stmt) fetch_stmt() !int {
res := C.mysql_stmt_fetch(stmt.stmt)
if res !in [0, 100] && stmt.get_error_msg() != '' {
return stmt.error(res)
@ -124,7 +124,7 @@ pub fn (stmt Stmt) fetch_stmt() ?int {
return res
}
pub fn (stmt Stmt) close() ? {
pub fn (stmt Stmt) close() ! {
if !C.mysql_stmt_close(stmt.stmt) && stmt.get_error_msg() != '' {
return stmt.error(1)
}
@ -222,14 +222,14 @@ pub fn (mut stmt Stmt) bind_res(fields &C.MYSQL_FIELD, dataptr []&u8, lens []u32
}
}
pub fn (mut stmt Stmt) bind_result_buffer() ? {
pub fn (mut stmt Stmt) bind_result_buffer() ! {
res := C.mysql_stmt_bind_result(stmt.stmt, &C.MYSQL_BIND(stmt.res.data))
if res && stmt.get_error_msg() != '' {
return stmt.error(1)
}
}
pub fn (mut stmt Stmt) store_result() ? {
pub fn (mut stmt Stmt) store_result() ! {
res := C.mysql_stmt_store_result(stmt.stmt)
if res != 0 && stmt.get_error_msg() != '' {
return stmt.error(res)

View File

@ -25,7 +25,7 @@ fn http_fetch_mock(_methods []string, _config FetchConfig) ![]Response {
config.method = method_from_str(method)
res := fetch(FetchConfig{ ...config, url: url + lmethod })!
// TODO
// body := json.decode(HttpbinResponseBody,res.body)?
// body := json.decode(HttpbinResponseBody,res.body)!
result << res
}
return result

View File

@ -9,8 +9,8 @@ struct MimeType {
}
fn main() {
mt_json := http.get('https://raw.githubusercontent.com/jshttp/mime-db/master/db.json')?
mt_map := json.decode(map[string]MimeType, mt_json.text)?
mt_json := http.get('https://raw.githubusercontent.com/jshttp/mime-db/master/db.json')!
mt_map := json.decode(map[string]MimeType, mt_json.text)!
mut ext_to_mt_str := map[string]string{}
for mt_str, mt in mt_map {
@ -28,6 +28,6 @@ fn main() {
db = $mt_map
ext_to_mt_str = $ext_to_mt_str
)
')?
')!
execute('${@VEXE} fmt -w db.v')
}

View File

@ -170,12 +170,12 @@ pub:
// Every function without last_id() returns an optional, which returns an error if present
// last_id returns the last inserted id of the db
pub interface Connection {
@select(config SelectConfig, data QueryData, where QueryData) ?[][]Primitive
insert(table string, data QueryData) ?
update(table string, data QueryData, where QueryData) ?
delete(table string, where QueryData) ?
create(table string, fields []TableField) ?
drop(table string) ?
@select(config SelectConfig, data QueryData, where QueryData) ![][]Primitive
insert(table string, data QueryData) !
update(table string, data QueryData, where QueryData) !
delete(table string, where QueryData) !
create(table string, fields []TableField) !
drop(table string) !
last_id() Primitive
}
@ -392,7 +392,7 @@ pub fn orm_select_gen(orm SelectConfig, q string, num bool, qm string, start_pos
// fields - See TableField
// sql_from_v - Function which maps type indices to sql type names
// alternative - Needed for msdb
pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int, fields []TableField, sql_from_v fn (int) ?string, alternative bool) ?string {
pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int, fields []TableField, sql_from_v fn (int) !string, alternative bool) !string {
mut str := 'CREATE TABLE IF NOT EXISTS $q$table$q ('
if alternative {
@ -416,7 +416,7 @@ pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int,
mut field_name := sql_field_name(field)
mut ctyp := sql_from_v(sql_field_type(field)) or {
field_name = '${field_name}_id'
sql_from_v(7)?
sql_from_v(7)!
}
for attr in field.attrs {
match attr.name {

View File

@ -256,7 +256,7 @@ fn test_orm_table_gen() {
assert mult_unique_query == "CREATE TABLE IF NOT EXISTS 'test_table' ('id' SERIAL DEFAULT 10, 'test' TEXT, 'abc' INT64 DEFAULT 6754, /* test */UNIQUE('test', 'abc'), PRIMARY KEY('id'));"
}
fn sql_type_from_v(typ int) ?string {
fn sql_type_from_v(typ int) !string {
return if typ in orm.nums {
'INT'
} else if typ in orm.num64 {

View File

@ -19,7 +19,7 @@ fn testsuite_end() {
}
fn test_ensure_db_exists_and_user_table_is_ok() {
mut db := sqlite.connect(db_path)?
mut db := sqlite.connect(db_path)!
assert true
eprintln('> drop pre-existing User table...')
@ -30,11 +30,11 @@ fn test_ensure_db_exists_and_user_table_is_ok() {
create table User
} or { panic(err) }
assert true
db.close()?
db.close()!
}
fn test_sql_or_block_for_insert() {
mut db := sqlite.connect(db_path)?
mut db := sqlite.connect(db_path)!
user := User{1, 'bilbo'}
eprintln('> inserting user 1 (first try)...')
@ -53,11 +53,11 @@ fn test_sql_or_block_for_insert() {
println('user could not be inserted, err: $err')
}
eprintln('LINE: ${@LINE}')
db.close()?
db.close()!
}
fn test_sql_or_block_for_select() {
mut db := sqlite.connect(db_path)?
mut db := sqlite.connect(db_path)!
eprintln('> selecting user with id 1...')
single := sql db {
@ -93,7 +93,7 @@ fn test_sql_or_block_for_select() {
assert multiple.len == 1
eprintln('LINE: ${@LINE}')
db.close()?
db.close()!
}
fn test_finish() {

View File

@ -6,10 +6,10 @@ import net.conv
// sql expr
pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ?[][]orm.Primitive {
pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive {
query := orm.orm_select_gen(config, '"', true, '$', 1, where)
res := pg_stmt_worker(db, query, where, data)?
res := pg_stmt_worker(db, query, where, data)!
mut ret := [][]orm.Primitive{}
@ -19,7 +19,7 @@ pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.Qu
for row in res {
mut row_data := []orm.Primitive{}
for i, val in row.vals {
field := str_to_primitive(val, config.types[i])?
field := str_to_primitive(val, config.types[i])!
row_data << field
}
ret << row_data
@ -30,20 +30,20 @@ pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.Qu
// sql stmt
pub fn (db DB) insert(table string, data orm.QueryData) ? {
pub fn (db DB) insert(table string, data orm.QueryData) ! {
query, converted_data := orm.orm_stmt_gen(table, '"', .insert, true, '$', 1, data,
orm.QueryData{})
pg_stmt_worker(db, query, converted_data, orm.QueryData{})?
pg_stmt_worker(db, query, converted_data, orm.QueryData{})!
}
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ? {
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! {
query, _ := orm.orm_stmt_gen(table, '"', .update, true, '$', 1, data, where)
pg_stmt_worker(db, query, data, where)?
pg_stmt_worker(db, query, data, where)!
}
pub fn (db DB) delete(table string, where orm.QueryData) ? {
pub fn (db DB) delete(table string, where orm.QueryData) ! {
query, _ := orm.orm_stmt_gen(table, '"', .delete, true, '$', 1, orm.QueryData{}, where)
pg_stmt_worker(db, query, orm.QueryData{}, where)?
pg_stmt_worker(db, query, orm.QueryData{}, where)!
}
pub fn (db DB) last_id() orm.Primitive {
@ -54,19 +54,19 @@ pub fn (db DB) last_id() orm.Primitive {
// table
pub fn (db DB) create(table string, fields []orm.TableField) ? {
pub fn (db DB) create(table string, fields []orm.TableField) ! {
query := orm.orm_table_gen(table, '"', true, 0, fields, pg_type_from_v, false) or { return err }
pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})?
pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
}
pub fn (db DB) drop(table string) ? {
pub fn (db DB) drop(table string) ! {
query := 'DROP TABLE "$table";'
pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})?
pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
}
// utils
fn pg_stmt_worker(db DB, query string, data orm.QueryData, where orm.QueryData) ?[]Row {
fn pg_stmt_worker(db DB, query string, data orm.QueryData, where orm.QueryData) ![]Row {
mut param_types := []u32{}
mut param_vals := []&char{}
mut param_lens := []int{}
@ -185,7 +185,7 @@ fn pg_stmt_match(mut types []u32, mut vals []&char, mut lens []int, mut formats
}
}
fn pg_type_from_v(typ int) ?string {
fn pg_type_from_v(typ int) !string {
str := match typ {
orm.type_idx['i8'], orm.type_idx['i16'], orm.type_idx['u8'], orm.type_idx['u16'] {
'SMALLINT'
@ -224,7 +224,7 @@ fn pg_type_from_v(typ int) ?string {
return str
}
fn str_to_primitive(str string, typ int) ?orm.Primitive {
fn str_to_primitive(str string, typ int) !orm.Primitive {
match typ {
// bool
orm.type_idx['bool'] {
@ -279,7 +279,7 @@ fn str_to_primitive(str string, typ int) ?orm.Primitive {
}
orm.time {
if str.contains_any(' /:-') {
date_time_str := time.parse(str)?
date_time_str := time.parse(str)!
return orm.Primitive(date_time_str)
}

View File

@ -76,7 +76,7 @@ fn C.PQfinish(voidptr)
// connect makes a new connection to the database server using
// the parameters from the `Config` structure, returning
// a connection error when something goes wrong
pub fn connect(config Config) ?DB {
pub fn connect(config Config) !DB {
conninfo := 'host=$config.host port=$config.port user=$config.user dbname=$config.dbname password=$config.password'
conn := C.PQconnectdb(conninfo.str)
if conn == 0 {
@ -125,8 +125,8 @@ pub fn (db DB) close() {
// returns an the first field in the first tuple
// converted to an int. If no row is found or on
// command failure, an error is returned
pub fn (db DB) q_int(query string) ?int {
rows := db.exec(query)?
pub fn (db DB) q_int(query string) !int {
rows := db.exec(query)!
if rows.len == 0 {
return error('q_int "$query" not found')
}
@ -142,8 +142,8 @@ pub fn (db DB) q_int(query string) ?int {
// returns an the first field in the first tuple
// as a string. If no row is found or on
// command failure, an error is returned
pub fn (db DB) q_string(query string) ?string {
rows := db.exec(query)?
pub fn (db DB) q_string(query string) !string {
rows := db.exec(query)!
if rows.len == 0 {
return error('q_string "$query" not found')
}
@ -157,37 +157,37 @@ pub fn (db DB) q_string(query string) ?string {
// q_strings submit a command to the database server and
// returns the resulting row set. Alias of `exec`
pub fn (db DB) q_strings(query string) ?[]Row {
pub fn (db DB) q_strings(query string) ![]Row {
return db.exec(query)
}
// exec submit a command to the database server and wait
// for the result, returning an error on failure and a
// row set on success
pub fn (db DB) exec(query string) ?[]Row {
pub fn (db DB) exec(query string) ![]Row {
res := C.PQexec(db.conn, query.str)
return db.handle_error_or_result(res, 'exec')
}
fn rows_first_or_empty(rows []Row) ?Row {
fn rows_first_or_empty(rows []Row) !Row {
if rows.len == 0 {
return error('no row')
}
return rows[0]
}
pub fn (db DB) exec_one(query string) ?Row {
pub fn (db DB) exec_one(query string) !Row {
res := C.PQexec(db.conn, query.str)
e := unsafe { C.PQerrorMessage(db.conn).vstring() }
if e != '' {
return error('pg exec error: "$e"')
}
row := rows_first_or_empty(res_to_rows(res))?
row := rows_first_or_empty(res_to_rows(res))!
return row
}
// exec_param_many executes a query with the provided parameters
pub fn (db DB) exec_param_many(query string, params []string) ?[]Row {
pub fn (db DB) exec_param_many(query string, params []string) ![]Row {
unsafe {
mut param_vals := []&char{len: params.len}
for i in 0 .. params.len {
@ -200,15 +200,15 @@ pub fn (db DB) exec_param_many(query string, params []string) ?[]Row {
}
}
pub fn (db DB) exec_param2(query string, param string, param2 string) ?[]Row {
pub fn (db DB) exec_param2(query string, param string, param2 string) ![]Row {
return db.exec_param_many(query, [param, param2])
}
pub fn (db DB) exec_param(query string, param string) ?[]Row {
pub fn (db DB) exec_param(query string, param string) ![]Row {
return db.exec_param_many(query, [param])
}
fn (db DB) handle_error_or_result(res voidptr, elabel string) ?[]Row {
fn (db DB) handle_error_or_result(res voidptr, elabel string) ![]Row {
e := unsafe { C.PQerrorMessage(db.conn).vstring() }
if e != '' {
C.PQclear(res)
@ -219,7 +219,7 @@ fn (db DB) handle_error_or_result(res voidptr, elabel string) ?[]Row {
// copy_expert execute COPY commands
// https://www.postgresql.org/docs/9.5/libpq-copy.html
pub fn (db DB) copy_expert(query string, mut file io.ReaderWriter) ?int {
pub fn (db DB) copy_expert(query string, mut file io.ReaderWriter) !int {
res := C.PQexec(db.conn, query.str)
status := C.PQresultStatus(res)

View File

@ -5,19 +5,19 @@ import time
// sql expr
pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ?[][]orm.Primitive {
pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive {
// 1. Create query and bind necessary data
query := orm.orm_select_gen(config, '`', true, '?', 1, where)
$if trace_sqlite ? {
eprintln('> @select query: "$query"')
}
stmt := db.new_init_stmt(query)?
stmt := db.new_init_stmt(query)!
defer {
stmt.finalize()
}
mut c := 1
sqlite_stmt_binder(stmt, where, query, mut c)?
sqlite_stmt_binder(stmt, data, query, mut c)?
sqlite_stmt_binder(stmt, where, query, mut c)!
sqlite_stmt_binder(stmt, data, query, mut c)!
mut ret := [][]orm.Primitive{}
@ -27,7 +27,7 @@ pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.Qu
if step !in [sqlite_row, sqlite_ok, sqlite_done] {
return db.error_message(step, query)
}
count := stmt.sqlite_select_column(0, 8)?
count := stmt.sqlite_select_column(0, 8)!
ret << [count]
return ret
}
@ -42,7 +42,7 @@ pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.Qu
}
mut row := []orm.Primitive{}
for i, typ in config.types {
primitive := stmt.sqlite_select_column(i, typ)?
primitive := stmt.sqlite_select_column(i, typ)!
row << primitive
}
ret << row
@ -52,20 +52,20 @@ pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.Qu
// sql stmt
pub fn (db DB) insert(table string, data orm.QueryData) ? {
pub fn (db DB) insert(table string, data orm.QueryData) ! {
query, converted_data := orm.orm_stmt_gen(table, '`', .insert, true, '?', 1, data,
orm.QueryData{})
sqlite_stmt_worker(db, query, converted_data, orm.QueryData{})?
sqlite_stmt_worker(db, query, converted_data, orm.QueryData{})!
}
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ? {
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! {
query, _ := orm.orm_stmt_gen(table, '`', .update, true, '?', 1, data, where)
sqlite_stmt_worker(db, query, data, where)?
sqlite_stmt_worker(db, query, data, where)!
}
pub fn (db DB) delete(table string, where orm.QueryData) ? {
pub fn (db DB) delete(table string, where orm.QueryData) ! {
query, _ := orm.orm_stmt_gen(table, '`', .delete, true, '?', 1, orm.QueryData{}, where)
sqlite_stmt_worker(db, query, orm.QueryData{}, where)?
sqlite_stmt_worker(db, query, orm.QueryData{}, where)!
}
pub fn (db DB) last_id() orm.Primitive {
@ -75,37 +75,37 @@ pub fn (db DB) last_id() orm.Primitive {
}
// table
pub fn (db DB) create(table string, fields []orm.TableField) ? {
pub fn (db DB) create(table string, fields []orm.TableField) ! {
query := orm.orm_table_gen(table, '`', true, 0, fields, sqlite_type_from_v, false) or {
return err
}
sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})?
sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
}
pub fn (db DB) drop(table string) ? {
pub fn (db DB) drop(table string) ! {
query := 'DROP TABLE `$table`;'
sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})?
sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
}
// helper
// Executes query and bind prepared statement data directly
fn sqlite_stmt_worker(db DB, query string, data orm.QueryData, where orm.QueryData) ? {
fn sqlite_stmt_worker(db DB, query string, data orm.QueryData, where orm.QueryData) ! {
$if trace_sqlite ? {
eprintln('> sqlite_stmt_worker query: "$query"')
}
stmt := db.new_init_stmt(query)?
stmt := db.new_init_stmt(query)!
defer {
stmt.finalize()
}
mut c := 1
sqlite_stmt_binder(stmt, data, query, mut c)?
sqlite_stmt_binder(stmt, where, query, mut c)?
stmt.orm_step(query)?
sqlite_stmt_binder(stmt, data, query, mut c)!
sqlite_stmt_binder(stmt, where, query, mut c)!
stmt.orm_step(query)!
}
// Binds all values of d in the prepared statement
fn sqlite_stmt_binder(stmt Stmt, d orm.QueryData, query string, mut c &int) ? {
fn sqlite_stmt_binder(stmt Stmt, d orm.QueryData, query string, mut c &int) ! {
for data in d.data {
err := bind(stmt, c, data)
@ -143,7 +143,7 @@ fn bind(stmt Stmt, c &int, data orm.Primitive) int {
}
// Selects column in result and converts it to an orm.Primitive
fn (stmt Stmt) sqlite_select_column(idx int, typ int) ?orm.Primitive {
fn (stmt Stmt) sqlite_select_column(idx int, typ int) !orm.Primitive {
mut primitive := orm.Primitive(0)
if typ in orm.nums || typ == -1 {
@ -165,7 +165,7 @@ fn (stmt Stmt) sqlite_select_column(idx int, typ int) ?orm.Primitive {
}
// Convert type int to sql type string
fn sqlite_type_from_v(typ int) ?string {
fn sqlite_type_from_v(typ int) !string {
return if typ in orm.nums || typ < 0 || typ in orm.num64 || typ == orm.time {
'INTEGER'
} else if typ in orm.float {

View File

@ -106,7 +106,7 @@ fn C.sqlite3_errmsg(&C.sqlite3) &char
fn C.sqlite3_free(voidptr)
// connect Opens the connection with a database.
pub fn connect(path string) ?DB {
pub fn connect(path string) !DB {
db := &C.sqlite3(0)
code := C.sqlite3_open(&char(path.str), &db)
if code != 0 {
@ -124,7 +124,7 @@ pub fn connect(path string) ?DB {
// close Closes the DB.
// TODO: For all functions, determine whether the connection is
// closed first, and determine what to do if it is
pub fn (mut db DB) close() ?bool {
pub fn (mut db DB) close() !bool {
code := C.sqlite3_close(db.conn)
if code == 0 {
db.is_open = false
@ -217,7 +217,7 @@ pub fn (db &DB) exec(query string) ([]Row, int) {
// Execute a query, handle error code
// Return the first row from the resulting table
[manualfree]
pub fn (db &DB) exec_one(query string) ?Row {
pub fn (db &DB) exec_one(query string) !Row {
rows, code := db.exec(query)
defer {
unsafe { rows.free() }

View File

@ -13,7 +13,7 @@ fn (db &DB) init_stmt(query string) (&C.sqlite3_stmt, int) {
return stmt, err
}
fn (db &DB) new_init_stmt(query string) ?Stmt {
fn (db &DB) new_init_stmt(query string) !Stmt {
stmt, err := db.init_stmt(query)
if err != sqlite_ok {
return db.error_message(err, query)
@ -66,7 +66,7 @@ fn (stmt &Stmt) step() int {
return C.sqlite3_step(stmt.stmt)
}
fn (stmt &Stmt) orm_step(query string) ? {
fn (stmt &Stmt) orm_step(query string) ! {
res := stmt.step()
if res != sqlite_ok && res != sqlite_done && res != sqlite_row {
return stmt.db.error_message(res, query)

View File

@ -30,7 +30,7 @@ pub fn get_terminal_size() (int, int) {
}
// get_cursor_position returns a Coord containing the current cursor position
pub fn get_cursor_position() ?Coord {
pub fn get_cursor_position() !Coord {
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
return Coord{0, 0}
}

View File

@ -58,8 +58,8 @@ fn test_header() {
}
fn test_get_cursor_position() {
original_position := term.get_cursor_position()?
cursor_position_1 := term.get_cursor_position()?
original_position := term.get_cursor_position()!
cursor_position_1 := term.get_cursor_position()!
assert original_position.x == cursor_position_1.x
assert original_position.y == cursor_position_1.y
//
@ -67,13 +67,13 @@ fn test_get_cursor_position() {
x: 10
y: 11
)
cursor_position_2 := term.get_cursor_position()?
cursor_position_2 := term.get_cursor_position()!
//
term.set_cursor_position(
x: 5
y: 6
)
cursor_position_3 := term.get_cursor_position()?
cursor_position_3 := term.get_cursor_position()!
//
term.set_cursor_position(original_position)
eprintln('original_position: $original_position')

View File

@ -69,7 +69,7 @@ pub fn get_terminal_size() (int, int) {
}
// get_cursor_position returns a Coord containing the current cursor position
pub fn get_cursor_position() ?Coord {
pub fn get_cursor_position() !Coord {
mut res := Coord{}
if os.is_atty(1) > 0 && os.getenv('TERM') != 'dumb' {
info := C.CONSOLE_SCREEN_BUFFER_INFO{}

View File

@ -47,7 +47,7 @@ pub fn (mut ctx Context) run() ? {
ctx.fail('error: x11 backend not implemented yet')
exit(1)
} else {
ctx.termios_setup()?
ctx.termios_setup() or { panic(err) }
ctx.termios_loop()
}
}

View File

@ -51,7 +51,7 @@ fn restore_terminal_state() {
os.flush()
}
fn (mut ctx Context) termios_setup() ? {
fn (mut ctx Context) termios_setup() ! {
// store the current title, so restore_terminal_state can get it back
save_title()

View File

@ -6,7 +6,7 @@ module time
// parse_rfc3339 returns time from a date string in RFC 3339 datetime format.
// See also https://ijmacd.github.io/rfc3339-iso8601/ for a visual reference of
// the differences between ISO-8601 and RFC 3339.
pub fn parse_rfc3339(s string) ?Time {
pub fn parse_rfc3339(s string) !Time {
if s == '' {
return error_invalid_time(0)
}
@ -23,7 +23,7 @@ pub fn parse_rfc3339(s string) ?Time {
// Check if sn is date only
if !parts[0].contains_any(' Z') && parts[0].contains('-') {
year, month, day := parse_iso8601_date(sn)?
year, month, day := parse_iso8601_date(sn)!
t = new_time(Time{
year: year
month: month
@ -34,7 +34,7 @@ pub fn parse_rfc3339(s string) ?Time {
// Check if sn is time only
if !parts[0].contains('-') && parts[0].contains(':') {
mut hour_, mut minute_, mut second_, mut microsecond_, mut unix_offset, mut is_local_time := 0, 0, 0, 0, i64(0), true
hour_, minute_, second_, microsecond_, unix_offset, is_local_time = parse_iso8601_time(parts[0])?
hour_, minute_, second_, microsecond_, unix_offset, is_local_time = parse_iso8601_time(parts[0])!
t = new_time(Time{
hour: hour_
minute: minute_
@ -58,7 +58,7 @@ pub fn parse_rfc3339(s string) ?Time {
}
// parse returns time from a date string in "YYYY-MM-DD HH:mm:ss" format.
pub fn parse(s string) ?Time {
pub fn parse(s string) !Time {
if s == '' {
return error_invalid_time(0)
}
@ -115,7 +115,7 @@ pub fn parse(s string) ?Time {
// from UTC time and can be both +/- HH:mm
// remarks: not all iso8601 is supported
// also checks and support for leapseconds should be added in future PR
pub fn parse_iso8601(s string) ?Time {
pub fn parse_iso8601(s string) !Time {
if s == '' {
return error_invalid_time(0)
}
@ -124,10 +124,10 @@ pub fn parse_iso8601(s string) ?Time {
if !(parts.len == 1 || parts.len == 2) {
return error_invalid_time(12)
}
year, month, day := parse_iso8601_date(parts[0])?
year, month, day := parse_iso8601_date(parts[0])!
mut hour_, mut minute_, mut second_, mut microsecond_, mut unix_offset, mut is_local_time := 0, 0, 0, 0, i64(0), true
if parts.len == 2 {
hour_, minute_, second_, microsecond_, unix_offset, is_local_time = parse_iso8601_time(parts[1])?
hour_, minute_, second_, microsecond_, unix_offset, is_local_time = parse_iso8601_time(parts[1])!
}
mut t := new_time(
year: year
@ -152,7 +152,7 @@ pub fn parse_iso8601(s string) ?Time {
}
// parse_rfc2822 returns time from a date string in RFC 2822 datetime format.
pub fn parse_rfc2822(s string) ?Time {
pub fn parse_rfc2822(s string) !Time {
if s == '' {
return error_invalid_time(0)
}
@ -171,7 +171,7 @@ pub fn parse_rfc2822(s string) ?Time {
}
// ----- iso8601 -----
fn parse_iso8601_date(s string) ?(int, int, int) {
fn parse_iso8601_date(s string) !(int, int, int) {
year, month, day, dummy := 0, 0, 0, u8(0)
count := unsafe { C.sscanf(&char(s.str), c'%4d-%2d-%2d%c', &year, &month, &day, &dummy) }
if count != 3 {
@ -189,7 +189,7 @@ fn parse_iso8601_date(s string) ?(int, int, int) {
return year, month, day
}
fn parse_iso8601_time(s string) ?(int, int, int, int, i64, bool) {
fn parse_iso8601_time(s string) !(int, int, int, int, i64, bool) {
hour_ := 0
minute_ := 0
second_ := 0

View File

@ -19,6 +19,6 @@ pub fn parse(s string) Time {
return res
}
pub fn parse_iso8601(s string) ?Time {
pub fn parse_iso8601(s string) !Time {
return parse(s)
}

View File

@ -1,7 +1,7 @@
import time
fn test_add_to_day_in_the_previous_century() {
a := time.parse_iso8601('1900-01-01')?
a := time.parse_iso8601('1900-01-01')!
aa := a.add_days(180)
dump(a.debug())
dump(aa.debug())
@ -9,25 +9,25 @@ fn test_add_to_day_in_the_previous_century() {
}
fn test_add_to_day_in_the_past() {
a := time.parse_iso8601('1990-03-01')?
a := time.parse_iso8601('1990-03-01')!
aa := a.add_days(180)
assert aa.ymmdd() == '1990-08-28'
}
fn test_add_to_day_in_the_recent_past() {
a := time.parse_iso8601('2021-03-01')?
a := time.parse_iso8601('2021-03-01')!
aa := a.add_days(180)
assert aa.ymmdd() == '2021-08-28'
}
fn test_add_to_day_in_the_future_1() {
a := time.parse_iso8601('3000-11-01')?
a := time.parse_iso8601('3000-11-01')!
aa := a.add_days(180)
assert aa.ymmdd() == '3001-04-30'
}
fn test_add_to_day_in_the_future_2() {
a := time.parse_iso8601('3000-12-30')?
a := time.parse_iso8601('3000-12-30')!
aa := a.add_days(180)
assert aa.ymmdd() == '3001-06-28'
}

View File

@ -644,7 +644,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
c.error('json.decode: second argument needs to be a string', node.pos)
}
typ := expr as ast.TypeNode
ret_type := typ.typ.set_flag(.optional)
ret_type := typ.typ.set_flag(.result)
node.return_type = ret_type
return ret_type
} else if fn_name == '__addr' {

View File

@ -1,34 +1,34 @@
vlib/v/checker/tests/json_decode.vv:11:7: error: json.decode: unknown type `St2`
9 | fn main() {
10 | json.decode(St, '{a: ""}')? // OK
11 | json.decode(St2, '{a: ""}')? // BAD
10 | json.decode(St, '{a: ""}')! // OK
11 | json.decode(St2, '{a: ""}')! // BAD
| ~~~~~~~~~~~~~~~~~~~~~~
12 | json.decode(St)? // BAD
13 | json.decode(string, '""')? // BAD
12 | json.decode(St)! // BAD
13 | json.decode(string, '""')! // BAD
vlib/v/checker/tests/json_decode.vv:12:7: error: json.decode expects 2 arguments, a type and a string (e.g `json.decode(T, '')`)
10 | json.decode(St, '{a: ""}')? // OK
11 | json.decode(St2, '{a: ""}')? // BAD
12 | json.decode(St)? // BAD
10 | json.decode(St, '{a: ""}')! // OK
11 | json.decode(St2, '{a: ""}')! // BAD
12 | json.decode(St)! // BAD
| ~~~~~~~~~~
13 | json.decode(string, '""')? // BAD
14 | json.decode(Num, '5')? // BAD
13 | json.decode(string, '""')! // BAD
14 | json.decode(Num, '5')! // BAD
vlib/v/checker/tests/json_decode.vv:13:14: error: json.decode: expected sum type, struct, map or array, found string
11 | json.decode(St2, '{a: ""}')? // BAD
12 | json.decode(St)? // BAD
13 | json.decode(string, '""')? // BAD
11 | json.decode(St2, '{a: ""}')! // BAD
12 | json.decode(St)! // BAD
13 | json.decode(string, '""')! // BAD
| ~~~~~~
14 | json.decode(Num, '5')? // BAD
15 | json.decode(St, 6)? // BAD
14 | json.decode(Num, '5')! // BAD
15 | json.decode(St, 6)! // BAD
vlib/v/checker/tests/json_decode.vv:14:14: error: json.decode: expected sum type, struct, map or array, found u8
12 | json.decode(St)? // BAD
13 | json.decode(string, '""')? // BAD
14 | json.decode(Num, '5')? // BAD
12 | json.decode(St)! // BAD
13 | json.decode(string, '""')! // BAD
14 | json.decode(Num, '5')! // BAD
| ~~~
15 | json.decode(St, 6)? // BAD
15 | json.decode(St, 6)! // BAD
16 | }
vlib/v/checker/tests/json_decode.vv:15:7: error: json.decode: second argument needs to be a string
13 | json.decode(string, '""')? // BAD
14 | json.decode(Num, '5')? // BAD
15 | json.decode(St, 6)? // BAD
13 | json.decode(string, '""')! // BAD
14 | json.decode(Num, '5')! // BAD
15 | json.decode(St, 6)! // BAD
| ~~~~~~~~~~~~~
16 | }

View File

@ -7,10 +7,10 @@ struct St {
type Num = u8
fn main() {
json.decode(St, '{a: ""}')? // OK
json.decode(St2, '{a: ""}')? // BAD
json.decode(St)? // BAD
json.decode(string, '""')? // BAD
json.decode(Num, '5')? // BAD
json.decode(St, 6)? // BAD
json.decode(St, '{a: ""}')! // OK
json.decode(St2, '{a: ""}')! // BAD
json.decode(St)! // BAD
json.decode(string, '""')! // BAD
json.decode(Num, '5')! // BAD
json.decode(St, 6)! // BAD
}

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/orm_empty_struct.vv:9:15: error: V orm: select: empty fields in `Person`
7 | db := sqlite.connect(':memory:')?
7 | db := sqlite.connect(':memory:')!
8 | _ := sql db {
9 | select from Person
| ~~~~~~

View File

@ -4,7 +4,7 @@ struct Person {
}
fn main() {
db := sqlite.connect(':memory:')?
db := sqlite.connect(':memory:')!
_ := sql db {
select from Person
}

View File

@ -5,7 +5,7 @@ struct Person {
}
fn main() {
db := sqlite.connect(':memory:')?
db := sqlite.connect(':memory:')!
_ := sql db {
select from Person
} or {

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/orm_not_a_struct.vv:10:15: error: The table symbol `Person` has to be a struct
8 | db := sqlite.connect(':memory:')?
8 | db := sqlite.connect(':memory:')!
9 | _ := sql db {
10 | select from Person
| ~~~~~~

View File

@ -5,7 +5,7 @@ enum Person {
}
fn main() {
db := sqlite.connect(':memory:')?
db := sqlite.connect(':memory:')!
_ := sql db {
select from Person
}

View File

@ -11,7 +11,7 @@ struct User {
}
fn main() {
db := sqlite.connect(':memory:')?
db := sqlite.connect(':memory:')!
sql db {
create table User
}

View File

@ -4,16 +4,16 @@ struct Request {
a int
}
fn parse(s string) ?Request {
fn parse(s string) !Request {
return json.decode(Request, s)
}
fn parse2(s string) ?Request {
req := json.decode(Request, s)?
fn parse2(s string) !Request {
req := json.decode(Request, s)!
return req
}
fn main() {
println(parse('{"a": 22} ')?)
println(parse2('{"a": 22} ')?)
println(parse('{"a": 22} ')!)
println(parse2('{"a": 22} ')!)
}

View File

@ -1301,7 +1301,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
g.call_args(node)
g.writeln(');')
tmp2 = g.new_tmp_var()
g.writeln('${option_name}_$typ $tmp2 = ${fn_name}($json_obj);')
g.writeln('${result_name}_$typ $tmp2 = ${fn_name}($json_obj);')
}
if !g.is_autofree {
g.write('cJSON_Delete($json_obj); // del')

View File

@ -44,12 +44,12 @@ fn (mut g Gen) gen_jsons() {
mut enc := strings.new_builder(100)
sym := g.table.sym(utyp)
styp := g.typ(utyp)
g.register_optional(utyp)
g.register_result(utyp)
// decode_TYPE funcs receive an actual cJSON* object to decode
// cJSON_Parse(str) call is added by the compiler
// Codegen decoder
dec_fn_name := js_dec_name(styp)
dec_fn_dec := '${option_name}_$styp ${dec_fn_name}(cJSON* root)'
dec_fn_dec := '${result_name}_$styp ${dec_fn_name}(cJSON* root)'
mut init_styp := '$styp res'
if sym.kind == .struct_ {
@ -89,7 +89,7 @@ $dec_fn_dec {
int maxchars = vstrlen_char(prevline_ptr);
vmemcpy(buf, prevline_ptr, (maxchars < maxcontext_chars ? maxchars : maxcontext_chars));
}
return (${option_name}_$styp){.state = 2,.err = _v_error(tos2(buf)),.data = {0}};
return (${result_name}_$styp){.is_error = true,.err = _v_error(tos2(buf)),.data = {0}};
}
}
')
@ -153,8 +153,8 @@ $enc_fn_dec {
g.gen_struct_enc_dec(sym.info, styp, mut enc, mut dec)
}
// cJSON_delete
dec.writeln('\t${option_name}_$styp ret;')
dec.writeln('\t_option_ok(&res, ($option_name*)&ret, sizeof(res));')
dec.writeln('\t${result_name}_$styp ret;')
dec.writeln('\t_result_ok(&res, ($result_name*)&ret, sizeof(res));')
dec.writeln('\treturn ret;\n}')
enc.writeln('\treturn o;\n}')
g.gowrappers.writeln(dec.str())
@ -251,9 +251,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
dec.writeln('\t\t\t}')
} else if !is_js_prim(variant_typ) && variant_sym.kind != .enum_ {
dec.writeln('\t\t\tif (strcmp("$unmangled_variant_name", $type_var) == 0) {')
dec.writeln('\t\t\t\t${option_name}_$variant_typ $tmp = ${js_dec_name(variant_typ)}(root);')
dec.writeln('\t\t\t\tif (${tmp}.state != 0) {')
dec.writeln('\t\t\t\t\treturn (${option_name}_$sym.cname){ .state = ${tmp}.state, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t\t${result_name}_$variant_typ $tmp = ${js_dec_name(variant_typ)}(root);')
dec.writeln('\t\t\t\tif (${tmp}.is_error) {')
dec.writeln('\t\t\t\t\treturn (${result_name}_$sym.cname){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t\t}')
dec.writeln('\t\t\t\tres = ${variant_typ}_to_sumtype_${sym.cname}(($variant_typ*)${tmp}.data);')
dec.writeln('\t\t\t}')
@ -317,9 +317,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(sym ast.TypeSymbol, mut enc strings.Builder,
'cJSON_IsNumber(root->child)'
}
dec.writeln('\t\tif (cJSON_IsArray(root) && $judge_elem_typ) {')
dec.writeln('\t\t\t${option_name}_$var_t $tmp = ${js_dec_name(var_t)}(root);')
dec.writeln('\t\t\tif (${tmp}.state != 0) {')
dec.writeln('\t\t\t\treturn (${option_name}_$sym.cname){ .state = ${tmp}.state, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t${result_name}_$var_t $tmp = ${js_dec_name(var_t)}(root);')
dec.writeln('\t\t\tif (${tmp}.is_error) {')
dec.writeln('\t\t\t\treturn (${result_name}_$sym.cname){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t}')
dec.writeln('\t\t\tres = ${var_t}_to_sumtype_${sym.cname}(($var_t*)${tmp}.data);')
dec.writeln('\t\t}')
@ -499,7 +499,7 @@ fn gen_js_get(styp string, tmp string, name string, mut dec strings.Builder, is_
dec.writeln('\tcJSON *jsonroot_$tmp = js_get(root, "$name");')
if is_required {
dec.writeln('\tif (jsonroot_$tmp == 0) {')
dec.writeln('\t\treturn (${option_name}_$styp){ .state = 2, .err = _v_error(_SLIT("expected field \'$name\' is missing")), .data = {0} };')
dec.writeln('\t\treturn (${result_name}_$styp){ .is_error = true, .err = _v_error(_SLIT("expected field \'$name\' is missing")), .data = {0} };')
dec.writeln('\t}')
}
}
@ -507,11 +507,11 @@ fn gen_js_get(styp string, tmp string, name string, mut dec strings.Builder, is_
fn gen_js_get_opt(dec_name string, field_type string, styp string, tmp string, name string, mut dec strings.Builder, is_required bool) {
gen_js_get(styp, tmp, name, mut dec, is_required)
value_field_type := field_type.trim_right('*')
dec.writeln('\t${option_name}_$value_field_type $tmp;')
dec.writeln('\t${result_name}_$value_field_type $tmp;')
dec.writeln('\tif (jsonroot_$tmp) {')
dec.writeln('\t\t$tmp = ${dec_name}(jsonroot_$tmp);')
dec.writeln('\t\tif (${tmp}.state != 0) {')
dec.writeln('\t\t\treturn (${option_name}_$styp){ .state = ${tmp}.state, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\tif (${tmp}.is_error) {')
dec.writeln('\t\t\treturn (${result_name}_$styp){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t}')
dec.writeln('\t}')
}
@ -557,10 +557,10 @@ fn (mut g Gen) decode_array(value_type ast.Type, fixed_array_size int) string {
s = '$styp val = ${fn_name}((cJSON *)jsval); '
} else {
s = '
${option_name}_$styp val2 = $fn_name ((cJSON *)jsval);
if(val2.state != 0) {
${result_name}_$styp val2 = $fn_name ((cJSON *)jsval);
if(val2.is_error) {
$array_free_str
return *(${option_name}_Array_$fixed_array_str$styp$fixed_array_size_str*)&val2;
return *(${result_name}_Array_$fixed_array_str$styp$fixed_array_size_str*)&val2;
}
$styp val = *($styp*)val2.data;
'
@ -568,7 +568,7 @@ fn (mut g Gen) decode_array(value_type ast.Type, fixed_array_size int) string {
return '
if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) {
return (${option_name}_Array_$fixed_array_str$styp$fixed_array_size_str){.state = 2, .err = _v_error(string__plus(_SLIT("Json element is not an array: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
return (${result_name}_Array_$fixed_array_str$styp$fixed_array_size_str){.is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an array: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
}
$res_str
const cJSON *jsval = NULL;
@ -612,17 +612,17 @@ fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type) string {
s = '$styp_v val = $fn_name_v (js_get(root, jsval->string));'
} else {
s = '
${option_name}_$styp_v val2 = $fn_name_v (js_get(root, jsval->string));
if(val2.state != 0) {
${result_name}_$styp_v val2 = $fn_name_v (js_get(root, jsval->string));
if(val2.is_error) {
map_free(&res);
return *(${option_name}_Map_${styp}_$styp_v*)&val2;
return *(${result_name}_Map_${styp}_$styp_v*)&val2;
}
$styp_v val = *($styp_v*)val2.data;
'
}
return '
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
return (${option_name}_Map_${styp}_$styp_v){ .state = 2, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
return (${result_name}_Map_${styp}_$styp_v){ .is_error = true, .err = _v_error(string__plus(_SLIT("Json element is not an object: "), tos2((byteptr)cJSON_PrintUnformatted(root)))), .data = {0}};
}
res = new_map(sizeof($styp), sizeof($styp_v), $hash_fn, $key_eq_fn, $clone_fn, $free_fn);
cJSON *jsval = NULL;

View File

@ -75,11 +75,11 @@ fn (mut g Gen) sql_stmt_line(nd ast.SqlStmtLine, expr string, or_expr ast.OrExpr
unsafe { fields.free() }
}
if node.kind == .create {
g.write('${option_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.write('${result_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.sql_create_table(node, expr, table_name)
subs = true
} else if node.kind == .drop {
g.write('${option_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.write('${result_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.writeln('drop(${expr}._object, _SLIT("$table_name"));')
subs = true
} else if node.kind == .insert {
@ -87,14 +87,14 @@ fn (mut g Gen) sql_stmt_line(nd ast.SqlStmtLine, expr string, or_expr ast.OrExpr
g.writeln('Array_orm__Primitive $arr = __new_array_with_default_noscan(0, 0, sizeof(orm__Primitive), 0);')
g.sql_insert(node, expr, table_name, arr, res, '', false, '', or_expr)
} else if node.kind == .update {
g.write('${option_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.write('${result_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.sql_update(node, expr, table_name)
} else if node.kind == .delete {
g.write('${option_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.write('${result_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.sql_delete(node, expr, table_name)
}
if or_expr.kind == .block {
g.or_block(res, or_expr, ast.int_type)
g.or_block(res, or_expr, ast.int_type.set_flag(.result))
}
if subs {
for _, sub in node.sub_structs {
@ -186,7 +186,7 @@ fn (mut g Gen) sql_insert(node ast.SqlStmtLine, expr string, table_name string,
g.writeln('array_push(&$last_ids_arr, _MOV((orm__Primitive[]){orm__Connection_name_table[${expr}._typ]._method_last_id(${expr}._object)}));')
}
g.write('${option_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.write('${result_name}_void $res = orm__Connection_name_table[${expr}._typ]._method_')
g.write('insert(${expr}._object, _SLIT("$table_name"), (orm__QueryData){')
g.write('.fields = new_array_from_c_array($fields.len, $fields.len, sizeof(string),')
@ -583,7 +583,7 @@ fn (mut g Gen) sql_select(node ast.SqlExpr, expr string, left string, or_expr as
res := g.new_tmp_var()
table_name := g.get_table_name(node.table_expr)
g.sql_table_name = g.table.sym(node.table_expr.typ).name
g.write('${option_name}_Array_Array_orm__Primitive _o$res = orm__Connection_name_table[${expr}._typ]._method_select(${expr}._object, ')
g.write('${result_name}_Array_Array_orm__Primitive _o$res = orm__Connection_name_table[${expr}._typ]._method_select(${expr}._object, ')
g.write('(orm__SelectConfig){')
g.write('.table = _SLIT("$table_name"),')
g.write('.is_count = $node.is_count,')
@ -677,12 +677,12 @@ fn (mut g Gen) sql_select(node ast.SqlExpr, expr string, left string, or_expr as
g.writeln(');')
mut tmp_left := g.new_tmp_var()
g.writeln('${g.typ(node.typ.set_flag(.optional))} $tmp_left;')
g.writeln('${g.typ(node.typ.set_flag(.result))} $tmp_left;')
if node.or_expr.kind == .block {
g.writeln('${tmp_left}.state = _o${res}.state;')
g.writeln('${tmp_left}.is_error = _o${res}.is_error;')
g.writeln('${tmp_left}.err = _o${res}.err;')
g.or_block(tmp_left, node.or_expr, node.typ)
g.or_block(tmp_left, node.or_expr, node.typ.set_flag(.result))
g.writeln('else {')
g.indent++
}

View File

@ -8,23 +8,23 @@ pub:
struct Abc {}
pub fn (x &Abc) notification_at<T>() ?NotificationMessage<T> {
pub fn (x &Abc) notification_at<T>() !NotificationMessage<T> {
return json.decode(NotificationMessage<T>, '{}')
}
pub fn (x &Abc) generic_method<T>(method_name string) ?NotificationMessage<T> {
pub fn (x &Abc) generic_method<T>(method_name string) !NotificationMessage<T> {
return x.notification_at<T>()
}
struct Res {}
pub fn (mut x Abc) diagnostics() ?Res {
got := x.generic_method<Res>('xyz')?
pub fn (mut x Abc) diagnostics() !Res {
got := x.generic_method<Res>('xyz')!
return got.params
}
fn test_generic_method_returning_optional() {
mut a := Abc{}
a.diagnostics()?
a.diagnostics()!
assert true
}

View File

@ -40,7 +40,7 @@ fn test_json_serialisation_of_fixed_arrays() {
]!}
s := json.encode(a)
dump(s)
b := json.decode(Fixed_Array, s)?
b := json.decode(Fixed_Array, s)!
dump(b)
assert a == b
}

View File

@ -12,6 +12,6 @@ struct LinksData {
}
fn main() {
links_data := json.decode(LinksData, '{}')?
links_data := json.decode(LinksData, '{}')!
println(links_data.messages)
}