From 1ddc9dc604737df0a9ec2bc21d6edaa4db1d4b9e Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 20 Aug 2019 18:05:56 +0300 Subject: [PATCH] orm: allow variables like q.nr_orders in queries too. --- compiler/parser.v | 7 +++++-- compiler/query.v | 23 ++++++++++++++++++----- examples/database/pg/customer.v | 3 ++- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/compiler/parser.v b/compiler/parser.v index f17df72e07..0e4ccaf0d8 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -85,6 +85,7 @@ mut: is_sql bool sql_i int // $1 $2 $3 sql_params []string // ("select * from users where id = $1", ***"100"***) + sql_types []string // int, string and so on; see sql_params } const ( @@ -1400,8 +1401,10 @@ fn (p mut Parser) bterm() string { p.gen('$' + p.sql_i.str()) p.cgen.start_cut() p.check_types(p.expression(), typ) - p.sql_params << p.cgen.cut() - //println('sql params = "$p.sql_params"') + sql_param := p.cgen.cut() + p.sql_params << sql_param + p.sql_types << typ + //println('*** sql type: $typ | param: $sql_param') } else { p.check_types(p.expression(), typ) } diff --git a/compiler/query.v b/compiler/query.v index f09a078e28..380b3c51c6 100644 --- a/compiler/query.v +++ b/compiler/query.v @@ -6,27 +6,40 @@ module main import strings -fn sql_params2params_gen(sql_params []string, qprefix string) string { +fn sql_params2params_gen(sql_params []string, sql_types []string, qprefix string) string { mut params_gen := '' for i, mparam in sql_params { param := mparam.trim(` `) + paramtype := sql_types[ i ] if param[0].is_digit() { params_gen += '${qprefix}params[$i] = int_str($param).str;\n' - }else{ + }else if param[0] == `\'` { sparam := param.trim(`\'`) params_gen += '${qprefix}params[$i] = "$sparam";\n' + } else { + // A variable like q.nr_orders + if paramtype == 'int' { + params_gen += '${qprefix}params[$i] = int_str( $param ).str;\n' + }else if paramtype == 'string' { + params_gen += '${qprefix}params[$i] = ${param}.str;\n' + }else{ + panic('orm: only int and string variable types are supported in queries') + } } } + //println('>>>>>>>> params_gen') + //println( params_gen ) 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, p.sql_i, p.sql_params SHOULD be reset for each query, + // NB: qprefix and { p.sql_i, p.sql_params, p.sql_types } SHOULD be reset for each query, // because we can have many queries in the _same_ scope. qprefix := p.get_tmp().replace('tmp','sql') + '_' p.sql_i = 0 p.sql_params = []string + p.sql_types = []string mut q := 'select ' p.check(.key_select) @@ -117,7 +130,7 @@ fn (p mut Parser) select_query(fn_ph int) string { } // One object if query_one { - mut params_gen := sql_params2params_gen( p.sql_params, qprefix ) + mut params_gen := sql_params2params_gen( p.sql_params, p.sql_types, qprefix ) p.cgen.insert_before(' char* ${qprefix}params[$p.sql_i]; @@ -142,7 +155,7 @@ ${obj_gen.str()} // Array else { q += ' order by id' - params_gen := sql_params2params_gen( p.sql_params, qprefix ) + params_gen := sql_params2params_gen( p.sql_params, p.sql_types, qprefix ) p.cgen.insert_before('char* ${qprefix}params[$p.sql_i]; $params_gen diff --git a/examples/database/pg/customer.v b/examples/database/pg/customer.v index 8c520f0a3d..d80d9755a2 100644 --- a/examples/database/pg/customer.v +++ b/examples/database/pg/customer.v @@ -38,7 +38,7 @@ fn main() { println('------------------------------------------------------------------------') q := Customer{} for { - anon := db.select from Customer where id = 12345 && nr_orders > q.nr_orders limit 1 or { eprintln('No such customer. Error: $err') break } + anon := db.select from Customer where id = 12345 && name = q.name && nr_orders > q.nr_orders limit 1 or { eprintln('No such customer. Error: $err') break } println('Non existing customer name: $anon.name') break } @@ -52,4 +52,5 @@ fn main() { db.insert(nc) */ + }