From f073ffa4adb41033ebe1b019734f1f66ef46b58d Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 27 Jun 2020 16:19:12 +0200 Subject: [PATCH] orm: limit --- vlib/orm/orm_test.v | 6 ++++++ vlib/v/ast/ast.v | 50 +++++++++++++++++++++++---------------------- vlib/v/gen/sql.v | 9 ++++++-- vlib/v/parser/sql.v | 8 +++++++- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/vlib/orm/orm_test.v b/vlib/orm/orm_test.v index b0078385ce..967ec397ac 100644 --- a/vlib/orm/orm_test.v +++ b/vlib/orm/orm_test.v @@ -168,6 +168,12 @@ fn test_orm_sqlite() { } assert no_user.name == '' // TODO optional assert no_user.age == 0 + // + two_users := sql db { + select from User limit 2 + } + assert two_users.len == 2 + assert two_users[0].id > 0 } struct User { diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 89b1f5a7a9..e4f531bf6b 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -106,7 +106,7 @@ pub: field_name string pub mut: expr_type table.Type // type of `Foo` in `Foo.bar` - typ table.Type // type of the entire thing (`Foo.bar`) + typ table.Type // type of the entire thing (`Foo.bar`) } // module declaration @@ -211,10 +211,10 @@ pub: pub struct AnonFn { pub: - decl FnDecl + decl FnDecl is_called bool pub mut: - typ table.Type + typ table.Type } pub struct FnDecl { @@ -809,7 +809,6 @@ pub enum SqlExprKind { update } */ - pub enum SqlStmtKind { insert update @@ -818,32 +817,36 @@ pub enum SqlStmtKind { pub struct SqlStmt { pub: - kind SqlStmtKind - db_expr Expr // `db` in `sql db {` + kind SqlStmtKind + db_expr Expr // `db` in `sql db {` object_var_name string // `user` table_type table.Type - pos token.Position - where_expr Expr - updated_columns []string //for `update set x=y` - update_exprs []Expr//for `update` + pos token.Position + where_expr Expr + updated_columns []string // for `update set x=y` + update_exprs []Expr // for `update` pub mut: - table_name string - fields []table.Field + table_name string + fields []table.Field } pub struct SqlExpr { pub: - typ table.Type - is_count bool - db_expr Expr // `db` in `sql db {` - where_expr Expr - has_where bool - is_array bool - table_type table.Type - pos token.Position + typ table.Type + is_count bool + db_expr Expr // `db` in `sql db {` + where_expr Expr + has_where bool + has_offset bool + offset_expr Expr + is_array bool + table_type table.Type + pos token.Position + has_limit bool + limit_expr Expr pub mut: - table_name string - fields []table.Field + table_name string + fields []table.Field } [inline] @@ -898,8 +901,7 @@ pub fn (expr Expr) position() token.Position { InfixExpr { left_pos := expr.left.position() right_pos := expr.right.position() - if left_pos.pos == 0 || - right_pos.pos == 0 { + if left_pos.pos == 0 || right_pos.pos == 0 { return expr.pos } return token.Position{ diff --git a/vlib/v/gen/sql.v b/vlib/v/gen/sql.v index c23f6c41cf..9bdce67866 100644 --- a/vlib/v/gen/sql.v +++ b/vlib/v/gen/sql.v @@ -131,7 +131,12 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { if node.has_where && node.where_expr is ast.InfixExpr { g.expr_to_sql(node.where_expr) } - g.writeln(' order by id"));') + g.write(' order by id ') + if node.has_limit { + g.write(' limit ') + g.expr_to_sql(node.limit_expr) + } + g.writeln('"));') // Dump all sql parameters generated by our custom expr handler binds := g.sql_buf.str() g.sql_buf = strings.new_builder(100) @@ -182,7 +187,7 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { g.writeln('\tif (_step_res$tmp == SQLITE_ROW) ;') // another row g.writeln('\telse if (_step_res$tmp != SQLITE_OK) break;') } else { - g.writeln('printf("RES: %d\\n", _step_res$tmp) ;') + // g.writeln('printf("RES: %d\\n", _step_res$tmp) ;') g.writeln('\tif (_step_res$tmp == SQLITE_OK || _step_res$tmp == SQLITE_ROW) {') } for i, field in node.fields { diff --git a/vlib/v/parser/sql.v b/vlib/v/parser/sql.v index 1db4d9e83b..48f70e6baf 100644 --- a/vlib/v/parser/sql.v +++ b/vlib/v/parser/sql.v @@ -38,13 +38,17 @@ fn (mut p Parser) sql_expr() ast.Expr { } } } + mut has_limit := false + mut limit_expr := ast.Expr{} if p.tok.kind == .name && p.tok.lit == 'limit' { // `limit 1` means that a single object is returned p.check_name() // `limit` if p.tok.kind == .number && p.tok.lit == '1' { query_one = true + } else { + has_limit = true } - p.next() + limit_expr = p.expr(0) } if !query_one && !is_count { // return an array @@ -63,6 +67,8 @@ fn (mut p Parser) sql_expr() ast.Expr { table_type: table_type where_expr: where_expr has_where: has_where + has_limit: has_limit + limit_expr: limit_expr is_array: !query_one pos: pos }