checker: handle limit and offset

pull/5532/head
Alexander Medvednikov 2020-06-27 16:41:29 +02:00
parent 3672cfad0b
commit 190f970544
2 changed files with 27 additions and 15 deletions

View File

@ -180,6 +180,13 @@ fn test_orm_sqlite() {
} }
assert y.len == 2 assert y.len == 2
assert y[0].id == 2 assert y[0].id == 2
//
offset_const := 2
z := sql db {
select from User limit 2 offset offset_const
}
assert z.len == 2
assert z[0].id == 3
} }
struct User { struct User {

View File

@ -319,8 +319,8 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
if !c.check_types(field_expr_type, field.typ) { if !c.check_types(field_expr_type, field.typ) {
field_expr_type_sym := c.table.get_type_symbol(field_expr_type) field_expr_type_sym := c.table.get_type_symbol(field_expr_type)
field_type_sym := c.table.get_type_symbol(field.typ) field_type_sym := c.table.get_type_symbol(field.typ)
c.error('default expression for field `$field.name` ' + 'has type `$field_expr_type_sym.name`, but should be `$field_type_sym.name`', c.error('default expression for field `$field.name` ' +
field.default_expr.position()) 'has type `$field_expr_type_sym.name`, but should be `$field_type_sym.name`', field.default_expr.position())
} }
} }
} }
@ -560,7 +560,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
// []T << T // []T << T
return table.void_type return table.void_type
} }
if right.kind == .array && c.check_types(left_value_type, c.table.value_type(right_type)) { if right.kind == .array &&
c.check_types(left_value_type, c.table.value_type(right_type)) {
// []T << []T // []T << []T
return table.void_type return table.void_type
} }
@ -819,8 +820,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
} }
if method := c.table.type_find_method(left_type_sym, method_name) { if method := c.table.type_find_method(left_type_sym, method_name) {
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test &&
left_type_sym.mod != c.mod && left_type_sym.mod != c.mod && left_type_sym.mod != '' { // method.mod != c.mod {
left_type_sym.mod != '' { // method.mod != c.mod {
// If a private method is called outside of the module // If a private method is called outside of the module
// its receiver type is defined in, show an error. // its receiver type is defined in, show an error.
// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod') // println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
@ -831,8 +831,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
// call_expr.is_mut = true // call_expr.is_mut = true
} }
if method.return_type == table.void_type && if method.return_type == table.void_type &&
method.ctdefine.len > 0 && method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines {
method.ctdefine !in c.pref.compile_defines {
call_expr.should_be_skipped = true call_expr.should_be_skipped = true
} }
nr_args := if method.args.len == 0 { 0 } else { method.args.len - 1 } nr_args := if method.args.len == 0 { 0 } else { method.args.len - 1 }
@ -1016,8 +1015,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
} }
call_expr.return_type = f.return_type call_expr.return_type = f.return_type
if f.return_type == table.void_type && if f.return_type == table.void_type &&
f.ctdefine.len > 0 && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines {
f.ctdefine !in c.pref.compile_defines {
call_expr.should_be_skipped = true call_expr.should_be_skipped = true
} }
if f.language != .v || call_expr.language != .v { if f.language != .v || call_expr.language != .v {
@ -1828,15 +1826,16 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.expr(it.call_expr) c.expr(it.call_expr)
if it.call_expr is ast.CallExpr { if it.call_expr is ast.CallExpr {
call_expr := it.call_expr as ast.CallExpr call_expr := it.call_expr as ast.CallExpr
// Make sure there are no mutable arguments // Make sure there are no mutable arguments
for arg in call_expr.args { for arg in call_expr.args {
if arg.is_mut && !arg.typ.is_ptr() { if arg.is_mut && !arg.typ.is_ptr() {
c.error('function in `go` statement cannot contain mutable non-reference arguments', arg.expr.position()) c.error('function in `go` statement cannot contain mutable non-reference arguments',
arg.expr.position())
} }
} }
if call_expr.is_method && call_expr.receiver_type.is_ptr() && !call_expr.left_type.is_ptr() { if call_expr.is_method && call_expr.receiver_type.is_ptr() && !call_expr.left_type.is_ptr() {
c.error('method in `go` statement cannot have non-reference mutable receiver', call_expr.left.position()) c.error('method in `go` statement cannot have non-reference mutable receiver',
call_expr.left.position())
} }
} }
} }
@ -2723,6 +2722,12 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) table.Type {
if node.has_where { if node.has_where {
c.expr(node.where_expr) c.expr(node.where_expr)
} }
if node.has_offset {
c.expr(node.offset_expr)
}
if node.has_limit {
c.expr(node.limit_expr)
}
c.expr(node.db_expr) c.expr(node.db_expr)
return node.typ return node.typ
} }
@ -2746,7 +2751,7 @@ fn (mut c Checker) sql_stmt(mut node ast.SqlStmt) table.Type {
}) })
} }
c.expr(node.db_expr) c.expr(node.db_expr)
if node.kind== .update { if node.kind == .update {
for expr in node.update_exprs { for expr in node.update_exprs {
c.expr(expr) c.expr(expr)
} }
@ -2803,8 +2808,8 @@ fn (mut c Checker) fn_decl(it ast.FnDecl) {
} }
sym.methods.delete(idx) sym.methods.delete(idx)
// //
c.error('cannot define new methods on non-local `$sym.name` (' + 'current module is `$c.mod`, `$sym.name` is from `$sym.mod`)', c.error('cannot define new methods on non-local `$sym.name` (' +
it.pos) 'current module is `$c.mod`, `$sym.name` is from `$sym.mod`)', it.pos)
} }
} }
if it.language == .v { if it.language == .v {