checker: do not allow {} for aliases; orm: update stmt
parent
0ea2e687d1
commit
9df29d0dd2
|
@ -126,10 +126,9 @@ fn test_orm_sqlite() {
|
|||
//
|
||||
/*
|
||||
sql db {
|
||||
update User set age = 31 where name = 'Kate'
|
||||
update User set age = 31 where name == 'Kate'
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -343,6 +343,10 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
|||
if type_sym.kind == .interface_ {
|
||||
c.error('cannot instantiate interface `$type_sym.name`', struct_init.pos)
|
||||
}
|
||||
if type_sym.kind == .alias {
|
||||
c.error('cannot instantiate type alias `$type_sym.name`', struct_init.pos)
|
||||
return table.void_type
|
||||
}
|
||||
if !type_sym.is_public && type_sym.kind != .placeholder && type_sym.mod != c.mod {
|
||||
c.error('type `$type_sym.name` is private', struct_init.pos)
|
||||
}
|
||||
|
|
|
@ -501,7 +501,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
|||
.name, .key_mut, .key_static, .mul {
|
||||
if p.tok.kind == .name {
|
||||
if p.tok.lit == 'sql' {
|
||||
return p.sql_insert_expr()
|
||||
return p.sql_stmt()
|
||||
}
|
||||
if p.peek_tok.kind == .colon {
|
||||
// `label:`
|
||||
|
|
|
@ -31,7 +31,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||
sym := p.table.get_type_symbol(table_type)
|
||||
table_name := sym.name
|
||||
mut where_expr := ast.Expr{}
|
||||
has_where := p.tok.kind == .name && p.tok.lit == 'where'
|
||||
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()
|
||||
|
@ -47,7 +47,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||
}
|
||||
}
|
||||
}
|
||||
if p.tok.kind ==.name && p.tok.lit == 'limit' {
|
||||
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' {
|
||||
|
@ -73,7 +73,8 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||
// get only string and int fields
|
||||
// mut fields := []Var
|
||||
info := sym.info as table.Struct
|
||||
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type] && 'skip' !in it.attrs)
|
||||
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type] &&
|
||||
'skip' !in it.attrs)
|
||||
if fields.len == 0 {
|
||||
p.error('V orm: select: empty fields in `$table_name`')
|
||||
}
|
||||
|
@ -103,37 +104,79 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) sql_insert_expr() ast.SqlStmt{
|
||||
// insert user into User
|
||||
// update User set nr_oders=nr_orders+1 where id == user_id
|
||||
fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||
p.inside_match = true
|
||||
defer { p.inside_match = false }
|
||||
defer {
|
||||
p.inside_match = false
|
||||
}
|
||||
// `sql db {`
|
||||
p.check_name()
|
||||
db_expr := p.expr(0)
|
||||
//println(typeof(db_expr))
|
||||
// println(typeof(db_expr))
|
||||
p.check(.lcbr)
|
||||
// kind := ast.SqlExprKind.select_
|
||||
//
|
||||
p.check_name() // insert
|
||||
mut object_var_name := ''
|
||||
mut n := p.check_name() // insert
|
||||
mut kind := ast.SqlStmtKind.insert
|
||||
if n == 'delete' {
|
||||
kind = .delete
|
||||
} else if n == 'update' {
|
||||
kind = .update
|
||||
}
|
||||
mut inserted_var_name := ''
|
||||
mut table_name := ''
|
||||
expr := p.expr(0)
|
||||
match expr {
|
||||
ast.Ident { object_var_name = expr.name }
|
||||
else { p.error('can only insert variables') }
|
||||
ast.Ident {
|
||||
if kind == .insert {
|
||||
inserted_var_name = expr.name
|
||||
} else if kind == .update {
|
||||
table_name = expr.name
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.error('can only insert variables')
|
||||
}
|
||||
}
|
||||
n := p.check_name() // into
|
||||
if n != 'into' {
|
||||
n = p.check_name() // into
|
||||
mut updated_columns := []string{}
|
||||
if kind == .insert && n != 'into' {
|
||||
p.error('expecting `into`')
|
||||
} else if kind == .update {
|
||||
if n != 'set' {
|
||||
p.error('expecting `set`')
|
||||
}
|
||||
column := p.check_name()
|
||||
updated_columns << column
|
||||
p.check(.assign)
|
||||
p.expr(0)
|
||||
}
|
||||
mut table_type := table.Type(0)
|
||||
if kind == .insert {
|
||||
table_type = p.parse_type() // `User`
|
||||
sym := p.table.get_type_symbol(table_type)
|
||||
// info := sym.info as table.Struct
|
||||
// fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type])
|
||||
table_name = sym.name
|
||||
} else if kind == .update {
|
||||
idx := p.table.find_type_idx(table_name)
|
||||
table_type = table.new_type(idx)
|
||||
p.check_sql_keyword('where')
|
||||
p.expr(0)
|
||||
}
|
||||
table_type := p.parse_type() // `User`
|
||||
sym := p.table.get_type_symbol(table_type)
|
||||
// info := sym.info as table.Struct
|
||||
// fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type])
|
||||
table_name := sym.name
|
||||
p.check(.rcbr)
|
||||
return ast.SqlStmt{
|
||||
db_expr: db_expr
|
||||
table_name: table_name
|
||||
table_type: table_type
|
||||
object_var_name: object_var_name
|
||||
object_var_name: inserted_var_name
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) check_sql_keyword(name string) {
|
||||
if p.check_name() != name {
|
||||
p.error('orm: expecting `$name`')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
mut comments := []ast.Comment{}
|
||||
for p.tok.kind == .comment {
|
||||
comments << p.comment()
|
||||
if p.tok.kind == .rcbr {break}
|
||||
if p.tok.kind == .rcbr {
|
||||
break
|
||||
}
|
||||
}
|
||||
if p.tok.kind == .rcbr {
|
||||
end_comments = comments
|
||||
|
@ -112,17 +114,19 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
}
|
||||
for p.tok.kind == .comment {
|
||||
comments << p.comment()
|
||||
if p.tok.kind == .rcbr {break}
|
||||
if p.tok.kind == .rcbr {
|
||||
break
|
||||
}
|
||||
}
|
||||
field_start_pos := p.tok.position()
|
||||
field_name := p.check_name()
|
||||
// p.warn('field $field_name')
|
||||
|
||||
for p.tok.kind == .comment {
|
||||
comments << p.comment()
|
||||
if p.tok.kind == .rcbr {break}
|
||||
if p.tok.kind == .rcbr {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// println(p.tok.position())
|
||||
typ := p.parse_type()
|
||||
// field_pos := field_start_pos.extend(p.tok.position())
|
||||
|
@ -139,14 +143,15 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
*/
|
||||
// Comments after type (same line)
|
||||
line_pos := field_pos.line_nr
|
||||
for p.tok.kind == .comment && line_pos + 1 == p.tok.line_nr{
|
||||
for p.tok.kind == .comment && line_pos + 1 == p.tok.line_nr {
|
||||
if p.tok.lit.contains('\n') {
|
||||
break
|
||||
}
|
||||
comments << p.comment()
|
||||
if p.tok.kind == .rcbr {break}
|
||||
if p.tok.kind == .rcbr {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
mut attrs := []string{}
|
||||
if p.tok.kind == .lsbr {
|
||||
parsed_attrs := p.attributes(false)
|
||||
|
@ -163,7 +168,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
// p.expr(0)
|
||||
default_expr = p.expr(0)
|
||||
match default_expr {
|
||||
ast.EnumVal { it.typ = typ }
|
||||
ast.EnumVal { default_expr.typ = typ }
|
||||
// TODO: implement all types??
|
||||
else {}
|
||||
}
|
||||
|
@ -340,7 +345,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
|||
p.error('interface methods cannot contain uppercase letters, use snake_case instead')
|
||||
}
|
||||
// field_names << name
|
||||
args2, _ := p.fn_args()
|
||||
args2, _ := p.fn_args() // TODO merge table.Arg and ast.Arg to avoid this
|
||||
mut args := [table.Arg{
|
||||
name: 'x'
|
||||
typ: typ
|
||||
|
|
Loading…
Reference in New Issue