From ef2ab31e885c44aef64ac0ed3f77931f52bd1934 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 12 Aug 2019 18:54:28 +0300 Subject: [PATCH] sql: only accept strings and ints for now --- compiler/parser.v | 9 ++++---- compiler/query.v | 53 ++++++++++++++++++++++++++++++++++--------- vlib/builtin/option.v | 6 ++--- vlib/vweb/vweb.v | 5 +++- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/compiler/parser.v b/compiler/parser.v index 0c6a63a16e..c3b3cf8ade 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -1251,8 +1251,9 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { println('allowing option asss') expr := p.cgen.cur_line.right(pos) left := p.cgen.cur_line.left(pos) + typ := expr_type.replace('Option_', '') //p.cgen.cur_line = left + 'opt_ok($expr)' - p.cgen.resetln(left + 'opt_ok($expr, sizeof($expr_type))') + p.cgen.resetln(left + 'opt_ok($expr, sizeof($typ))') } else if !p.builtin_mod && !p.check_types_no_throw(expr_type, p.assigned_type) { p.scanner.line_nr-- @@ -3315,10 +3316,10 @@ fn (p mut Parser) return_st() { if p.cur_fn.typ.ends_with(expr_type) && p.cur_fn.typ.starts_with('Option_') { tmp := p.get_tmp() ret := p.cgen.cur_line.right(ph) - - p.cgen.cur_line = '$expr_type $tmp = OPTION_CAST($expr_type)($ret);' + typ := expr_type.replace('Option_', '') + p.cgen.cur_line = '$expr_type $tmp = OPTION_CAST($typ)($ret);' p.cgen.resetln('$expr_type $tmp = OPTION_CAST($expr_type)($ret);') - p.gen('return opt_ok(&$tmp, sizeof($expr_type))') + p.gen('return opt_ok(&$tmp, sizeof($typ))') } else { ret := p.cgen.cur_line.right(ph) diff --git a/compiler/query.v b/compiler/query.v index 9f666cb42a..9dd4da872b 100644 --- a/compiler/query.v +++ b/compiler/query.v @@ -21,18 +21,36 @@ fn (p mut Parser) select_query(fn_ph int) string { if typ.name == '' { p.error('unknown type `$table_name`') } + //fields := typ.fields.filter(typ == 'string' || typ == 'int') + // get only string and int fields + mut fields := []Var + for i, field in typ.fields { + if field.typ != 'string' && field.typ != 'int' { + continue + } + fields << field + } + if fields.len == 0 { + p.error('V orm: select: empty fields in `$table_name`') + } + if fields[0].name != 'id' { + p.error('V orm: `id int` must be the first field in `$table_name`') + } // 'select id, name, age from...' if n == 'from' { - for i, field in typ.fields { + for i, field in fields { q += field.name - if i < typ.fields.len - 1 { + if i < fields.len - 1 { q += ', ' } } q += ' from ' } - for field in typ.fields { + for field in fields { //println('registering sql field var $field.name') + if field.typ != 'string' && field.typ != 'int' { + continue + } p.cur_fn.register_var({ field | is_used:true }) } q += table_name @@ -60,7 +78,7 @@ fn (p mut Parser) select_query(fn_ph int) string { query_one = true } } - //println('sql query="$q"') + println('sql query="$q"') if n == 'count' { p.cgen.set_placeholder(fn_ph, 'pg__DB_q_int(') p.gen(', tos2("$q"))') @@ -68,7 +86,7 @@ fn (p mut Parser) select_query(fn_ph int) string { // Build an object, assign each field. tmp := p.get_tmp() mut obj_gen := strings.new_builder(100) - for i, field in typ.fields { + for i, field in fields { mut cast := '' if field.typ == 'int' { cast = 'string_int' @@ -123,16 +141,29 @@ fn (p mut Parser) insert_query(fn_ph int) { p.check(.rpar) var := p.cur_fn.find_var(var_name) typ := p.table.find_type(var.typ) + mut fields := []Var + for i, field in typ.fields { + if field.typ != 'string' && field.typ != 'int' { + continue + } + fields << field + } + if fields.len == 0 { + p.error('V orm: insert: empty fields in `$var.typ`') + } + if fields[0].name != 'id' { + p.error('V orm: `id int` must be the first field in `$var.typ`') + } table_name := var.typ - mut fields := '' // 'name, city, country' + mut sfields := '' // 'name, city, country' mut params := '' // params[0] = 'bob'; params[1] = 'Vienna'; mut vals := '' // $1, $2, $3... mut nr_vals := 0 - for i, field in typ.fields { + for i, field in fields { if field.name == 'id' { continue } - fields += field.name + sfields += field.name vals += '$' + i.str() nr_vals++ params += 'params[${i-1}] = ' @@ -143,14 +174,14 @@ fn (p mut Parser) insert_query(fn_ph int) { } else { p.error('V ORM: unsupported type `$field.typ`') } - if i < typ.fields.len - 1 { - fields += ', ' + if i < fields.len - 1 { + sfields += ', ' vals += ', ' } } p.cgen.insert_before('char* params[$nr_vals];' + params) p.cgen.set_placeholder(fn_ph, 'PQexecParams( ') - p.genln('.conn, "insert into $table_name ($fields) values ($vals)", $nr_vals, + p.genln('.conn, "insert into $table_name ($sfields) values ($vals)", $nr_vals, 0, params, 0, 0, 0)') } diff --git a/vlib/builtin/option.v b/vlib/builtin/option.v index a1db5124c7..42203813bf 100644 --- a/vlib/builtin/option.v +++ b/vlib/builtin/option.v @@ -5,15 +5,15 @@ module builtin struct Option { - data [500]byte + data [255]byte error string ok bool } // `fn foo() ?Foo { return foo }` => `fn foo() ?Foo { return opt_ok(foo); }` fn opt_ok(data voidptr, size int) Option { - if size >= 500 { - panic('option size too big: $size (max is 500), this is a temporary limit') + if size >= 255 { + panic('option size too big: $size (max is 255), this is a temporary limit') } res := Option { ok: true diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index a006e79592..7db2280735 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -5,6 +5,7 @@ import ( strings net http + net.urllib ) const ( @@ -172,7 +173,9 @@ fn (ctx mut Context) parse_form(s string) { keyval := word.trim_space().split('=') if keyval.len != 2 { continue } key := keyval[0] - val := http.unescape_url(keyval[1]) + val := urllib.query_unescape(keyval[1]) or { + continue + } println('http form "$key" => "$val"') ctx.form[key] = val }