From 6f49d4c1d27b74a45610ff03ff40e2b33d8ee4aa Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 9 Dec 2019 17:10:44 +0300 Subject: [PATCH] orm: bool support; vweb fixes --- examples/database/pg/customer.v | 3 ++- vlib/builtin/string.v | 3 +++ vlib/compiler/expression.v | 14 ++++++++------ vlib/compiler/main.v | 2 +- vlib/compiler/query.v | 17 ++++++++++++----- vlib/vweb/vweb.v | 12 ++++++++++-- 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/examples/database/pg/customer.v b/examples/database/pg/customer.v index 39b82ba4af..b7137670b9 100644 --- a/examples/database/pg/customer.v +++ b/examples/database/pg/customer.v @@ -25,7 +25,8 @@ fn main() { // V syntax can be used to build queries println('----------------------------------------------------------------') - bg_customers := db.select from Customer where country == 'Bulgaria' && id != 2 + country := 'Bulgaria' + bg_customers := db.select from Customer where country == country && id != 2 for customer in bg_customers { println('$customer.country | $customer.id - $customer.name') } diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 6239b751d7..e353bafa91 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -190,6 +190,9 @@ pub fn (s string) replace(rep, with string) string { return tos(b, new_len) } +pub fn (s string) bool() bool { + return s == 'true' || s == 't' // TODO t for pg, remove +} pub fn (s string) int() int { return int(strconv.common_parse_int(s,0,32, false, false)) diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index 7ff32b7838..5883e79b22 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -51,14 +51,19 @@ fn (p mut Parser) bterm() string { is_ustr := typ=='ustring' is_float := typ[0] == `f` && (typ in ['f64', 'f32']) && !(p.cur_fn.name in ['f64_abs', 'f32_abs']) && - !(p.cur_fn.name == 'eq') - is_array := typ.contains('array_') + p.cur_fn.name != 'eq' + is_array := typ.starts_with('array_') expr_type := typ tok := p.tok + /* + if tok == .assign { + p.error('no = ') + } + */ if tok in [.eq, .gt, .lt, .le, .ge, .ne] { //TODO: remove when array comparing is supported if is_array { - p.error('array comparing is not supported yet') + p.error('array comparison is not supported yet') } p.fspace() @@ -161,14 +166,11 @@ fn (p mut Parser) name_expr() string { } return temp_type } - mut name := p.lit - // generic type check if name in p.cur_fn.dispatch_of.inst.keys() { name = p.cur_fn.dispatch_of.inst[name] } - // Raw string (`s := r'hello \n ') if name == 'r' && p.peek() == .str && p.prev_tok != .str_dollar { p.string_expr() diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index 2c47a43d5b..9d750f6aa4 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -746,7 +746,7 @@ pub fn (v &V) get_user_files() []string { if v.pref.is_test && v.pref.is_stats { user_files << filepath.join(preludes_path,'tests_with_stats.v') } - + // v volt/slack_test.v: compile all .v files to get the environment // I need to implement user packages! TODO is_test_with_imports := dir.ends_with('_test.v') && diff --git a/vlib/compiler/query.v b/vlib/compiler/query.v index e9ba5387a8..690865bc58 100644 --- a/vlib/compiler/query.v +++ b/vlib/compiler/query.v @@ -32,6 +32,7 @@ fn sql_params2params_gen(sql_params []string, sql_types []string, qprefix string return params_gen } + // `db.select from User where id == 1 && nr_bookings > 0` fn (p mut Parser) select_query(fn_ph int) string { // NB: qprefix and { p.sql_i, p.sql_params, p.sql_types } SHOULD be reset for each query, @@ -49,7 +50,8 @@ fn (p mut Parser) select_query(fn_ph int) string { p.check_name() } table_name := p.check_name() - // Register this type's fields as variables so they can be used in where expressions + // Register this type's fields as variables so they can be used in `where` + // expressions typ := p.table.find_type(table_name) if typ.name == '' { p.error('unknown type `$table_name`') @@ -58,7 +60,8 @@ fn (p mut Parser) select_query(fn_ph int) string { // get only string and int fields mut fields := []Var for i, field in typ.fields { - if field.typ != 'string' && field.typ != 'int' { + if !(field.typ in ['string', 'int', 'bool']) { + println('orm: skipping $field.name') continue } fields << field @@ -81,12 +84,13 @@ fn (p mut Parser) select_query(fn_ph int) string { } for field in fields { //println('registering sql field var $field.name') - if field.typ != 'string' && field.typ != 'int' { + if !(field.typ in ['string', 'int', 'bool']) { + println('orm: skipping $field.name') continue } - p.register_var({ field | is_used:true }) + p.register_var({ field | is_mut: true, is_used:true, is_changed:true }) } - q += table_name + q += table_name + 's' // `where` statement if p.tok == .name && p.lit == 'where' { p.next() @@ -123,6 +127,9 @@ fn (p mut Parser) select_query(fn_ph int) string { if field.typ == 'int' { cast = 'v_string_int' } + else if field.typ == 'bool' { + cast = 'string_bool' + } obj_gen.writeln('${qprefix}${tmp}.$field.name = ' + '${cast}(*(string*)array_get(${qprefix}row.vals, $i));') } diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 200e20b1be..087b6730f2 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -41,26 +41,34 @@ pub: // TODO Response mut: headers string // response headers + done bool } pub fn (ctx Context) html(html string) { + if ctx.done { return } //println('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n$ctx.headers\r\n\r\n$html') ctx.conn.write('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n$ctx.headers\r\n\r\n$html') or { panic(err) } } -pub fn (ctx Context) text(s string) { - ctx.conn.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n$ctx.headers\r\n\r\n $s') or { panic(err) } +pub fn (ctx mut Context) text(s string) { + if ctx.done { return } + ctx.conn.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n' + + '$ctx.headers\r\n$s') or { panic(err) } + ctx.done = true } pub fn (ctx Context) json(s string) { + if ctx.done { return } ctx.conn.write('HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n$ctx.headers\r\n\r\n$s') or { panic(err) } } pub fn (ctx Context) redirect(url string) { + if ctx.done { return } ctx.conn.write('HTTP/1.1 302 Found\r\nLocation: $url\r\n$ctx.headers\r\n\r\n') or { panic(err) } } pub fn (ctx Context) not_found(s string) { + if ctx.done { return } ctx.conn.write(HTTP_404) or { panic(err) } }