From 6066414afa422ff09ec01ec31b1b85da9d99bb05 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 17 Jun 2020 14:18:32 +0200 Subject: [PATCH] orm: select many --- vlib/orm/orm_test.v | 11 ++++++++++- vlib/v/ast/ast.v | 3 ++- vlib/v/gen/sql.v | 44 +++++++++++++++++++++++++++++++++++--------- vlib/v/parser/sql.v | 9 +++++++++ 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/vlib/orm/orm_test.v b/vlib/orm/orm_test.v index f800429e4b..126798736e 100644 --- a/vlib/orm/orm_test.v +++ b/vlib/orm/orm_test.v @@ -25,7 +25,7 @@ fn test_orm_sqlite() { name := 'sam' db.exec("insert into User (name, age) values ('Sam', 29)") - db.exec("insert into User (name) values ('Peter')") + db.exec("insert into User (name, age) values ('Peter', 31)") db.exec("insert into User (name) values ('Kate')") nr_all_users := sql db { select count from User @@ -57,6 +57,15 @@ fn test_orm_sqlite() { assert user.name == 'Sam' assert user.id == 1 assert user.age == 29 + // + users := sql db { + select from User where id > 0 + } + println(users) + assert users.len == 3 + assert users[0].name == 'Sam' + assert users[1].name == 'Peter' + assert users[1].age == 31 } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 36ed395e40..a8b43dcd2b 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -44,7 +44,6 @@ pub struct ExprStmt { pub: expr Expr pos token.Position - // is used for `x++` in `for x:=1; ; x++` is_expr bool pub mut: typ table.Type @@ -567,6 +566,7 @@ pub struct Attr { pub: name string } + pub fn (attrs []Attr) contains(attr Attr) bool { for a in attrs { if attr.name == a.name { @@ -816,6 +816,7 @@ pub: where_expr Expr has_where bool fields []table.Field + is_array bool } [inline] diff --git a/vlib/v/gen/sql.v b/vlib/v/gen/sql.v index 5cbb23c710..cc83258125 100644 --- a/vlib/v/gen/sql.v +++ b/vlib/v/gen/sql.v @@ -17,11 +17,11 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) { /* `nr_users := sql db { ... }` => ``` - sql_init_stmt() - sql_bind_int() - sql_bind_string() - ... - int nr_users = get_int(stmt) + sql_init_stmt() + sql_bind_int() + sql_bind_string() + ... + int nr_users = get_int(stmt) ``` */ cur_line := g.go_before_stmt(0) @@ -65,9 +65,26 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) { } else { // `user := sql db { select from User where id = 1 }` tmp := g.new_tmp_var() - g.write(g.typ(node.typ)) - g.writeln(' $tmp;') - g.writeln('sqlite3_step($g.sql_stmt_name);') + styp := g.typ(node.typ) + mut elem_type_str := '' + if node.is_array { + sym := g.table.get_type_symbol(node.typ) + info := sym.info as table.Array + elem_type_str = g.typ(info.elem_type) + // array_User array_tmp; + // for { User tmp; ... array_tmp << tmp; } + g.writeln('$styp ${tmp}_array = __new_array(0, 10, sizeof($elem_type_str));') + g.writeln('while (1) {') + g.writeln('\t$elem_type_str $tmp;') + } else { + // `User tmp;` + g.writeln('$styp $tmp;') + } + // + g.writeln('int _step_res$tmp = sqlite3_step($g.sql_stmt_name);') + if node.is_array { + g.writeln('\tif (_step_res$tmp == SQLITE_DONE) break;') + } for i, field in node.fields { mut func := 'sqlite3_column_int' if field.typ == table.string_type { @@ -77,8 +94,16 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) { g.writeln('${tmp}.$field.name = ${func}($g.sql_stmt_name, $i);') } } + if node.is_array { + g.writeln('\t array_push(&${tmp}_array, _MOV(($elem_type_str[]){ $tmp }));') + g.writeln('} // for') + } g.writeln('sqlite3_finalize($g.sql_stmt_name);') - g.writeln('$cur_line $tmp; ') // `User user = tmp;` + if node.is_array { + g.writeln('$cur_line ${tmp}_array; ') // `array_User users = tmp_array;` + } else { + g.writeln('$cur_line $tmp; ') // `User user = tmp;` + } } } @@ -93,6 +118,7 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr) { g.expr_to_sql(it.left) match it.op { .eq { g.write(' = ') } + .gt { g.write(' > ') } .and { g.write(' and ') } else {} } diff --git a/vlib/v/parser/sql.v b/vlib/v/parser/sql.v index f25116a0d5..a232c0516e 100644 --- a/vlib/v/parser/sql.v +++ b/vlib/v/parser/sql.v @@ -25,6 +25,7 @@ fn (mut p Parser) sql_expr() ast.SqlExpr { table_name := sym.name mut where_expr := ast.Expr{} has_where := p.tok.kind == .name && p.tok.lit == 'where' + mut query_one := false // one object is returned, not an array if has_where { p.next() where_expr = p.expr(0) @@ -34,11 +35,18 @@ fn (mut p Parser) sql_expr() ast.SqlExpr { if e.op == .eq && e.left is ast.Ident { ident := e.left as ast.Ident if ident.name == 'id' { + // TODO optional + query_one = true typ = table_type + // typ = table_type.set_flag(.optional) } } } } + if !query_one && !is_count { + // return an array + typ = table.new_type(p.table.find_or_register_array(table_type, 1, p.mod)) + } p.check(.rcbr) // ///////// // Register this type's fields as variables so they can be used in `where` @@ -86,5 +94,6 @@ fn (mut p Parser) sql_expr() ast.SqlExpr { where_expr: where_expr has_where: has_where fields: fields + is_array: !query_one } }