diff --git a/vlib/orm/orm_test.v b/vlib/orm/orm_test.v index fd5c0584c3..787d707c03 100644 --- a/vlib/orm/orm_test.v +++ b/vlib/orm/orm_test.v @@ -197,6 +197,11 @@ fn test_orm_sqlite() { } assert z.len == 2 assert z[0].id == 3 + + oldest := sql db { + select from User order age desc limit 1 + } + assert oldest.age == 34 } fn test_orm_pg() { diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index be74141198..90659f2a5a 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -846,6 +846,9 @@ pub: has_where bool has_offset bool offset_expr Expr + has_order bool + order_expr Expr + has_desc bool is_array bool table_type table.Type pos token.Position @@ -934,6 +937,7 @@ pub fn (expr Expr) position() token.Position { } // ast.None { } PrefixExpr { + return expr.pos } // ast.ParExpr { } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 7958e01cba..ccd3c978d4 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2808,6 +2808,9 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) table.Type { if node.has_limit { c.expr(node.limit_expr) } + if node.has_order { + c.expr(node.order_expr) + } c.expr(node.db_expr) return node.typ } diff --git a/vlib/v/gen/sql.v b/vlib/v/gen/sql.v index b3e817d37d..415beb8677 100644 --- a/vlib/v/gen/sql.v +++ b/vlib/v/gen/sql.v @@ -133,7 +133,16 @@ 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.write(' ORDER BY id ') + if node.has_order { + g.write(' ORDER BY ') + g.sql_side = .left + g.expr_to_sql(node.order_expr) + if node.has_desc { + g.write(' DESC ') + } + } else { + g.write(' ORDER BY id ') + } if node.has_limit { g.write(' LIMIT ') g.expr_to_sql(node.limit_expr) diff --git a/vlib/v/parser/sql.v b/vlib/v/parser/sql.v index 25fe37d8c4..c71c258b9c 100644 --- a/vlib/v/parser/sql.v +++ b/vlib/v/parser/sql.v @@ -42,6 +42,18 @@ fn (mut p Parser) sql_expr() ast.Expr { mut limit_expr := ast.Expr{} mut has_offset := false mut offset_expr := ast.Expr{} + mut has_order := false + mut order_expr := ast.Expr{} + mut has_desc := false + if p.tok.kind == .name && p.tok.lit == 'order' { + p.check_name() // `order` + has_order = true + order_expr = p.expr(0) + if p.tok.kind == .name && p.tok.lit == 'desc' { + p.check_name() // `desc` + has_desc = true + } + } if p.tok.kind == .name && p.tok.lit == 'limit' { // `limit 1` means that a single object is returned p.check_name() // `limit` @@ -77,6 +89,9 @@ fn (mut p Parser) sql_expr() ast.Expr { limit_expr: limit_expr has_offset: has_offset offset_expr: offset_expr + has_order: has_order + order_expr: order_expr + has_desc: has_desc is_array: !query_one pos: pos }