alex

/

v Public
0 Issues 1 Contributor 0 Releases 4 Branches
Additions: 80 Deletions: 0 View patch
1 pos token.Pos
2 where_expr Expr
3 update_exprs []Expr // for `update`
4+ // is_top_level indicates that a statement is parsed from code
5+ // and is not inserted by ORM for inserting in related tables.
6+ is_top_level bool
7+ scope &Scope = unsafe { nil }
8 pub mut:
9 object_var_name string // `user`
10 updated_columns []string // for `update set x=y`
11
1 info := sym.info as ast.Struct
2 mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name)
3 mut sub_structs := map[int]ast.SqlExpr{}
4+
5 for f in fields.filter((c.table.type_symbols[int(it.typ)].kind == .struct_
6 || (c.table.sym(it.typ).kind == .array
7 && c.table.sym(c.table.sym(it.typ).array_info().elem_type).kind == .struct_))
8 tmp_inside_sql := c.inside_sql
9 c.sql_expr(mut n)
10 c.inside_sql = tmp_inside_sql
11+
12 n.where_expr = ast.InfixExpr{
13 op: .eq
14 pos: n.pos
15
16 sub_structs[int(typ)] = n
17 }
18+
19 if node.is_count {
20 fields = [
21 ast.StructField{
22 },
23 ]
24 }
25+
26 node.fields = fields
27 node.sub_structs = sub_structs.move()
28+
29 if node.has_where {
30 c.expr(node.where_expr)
31 c.check_expr_has_no_fn_calls_with_non_orm_return_type(&node.where_expr)
32 defer {
33 c.cur_orm_ts = old_ts
34 }
35+
36+ if node.kind == .insert && node.is_top_level {
37+ inserting_object_name := node.object_var_name
38+ inserting_object_var := node.scope.find(inserting_object_name) or {
39+ c.error('undefined ident: `${inserting_object_name}`', node.pos)
40+ return ast.void_type
41+ }
42+
43+ if inserting_object_var.typ != node.table_expr.typ {
44+ table_name := table_sym.name
45+ inserting_type_name := c.table.sym(inserting_object_var.typ).name
46+
47+ c.error('cannot use `${inserting_type_name}` as `${table_name}`', node.pos)
48+ return ast.void_type
49+ }
50+ }
51+
52 if table_sym.info !is ast.Struct {
53 c.error('unknown type `${table_sym.name}`', node.pos)
54 return ast.void_type
55
1new file mode 100644
2+vlib/v/checker/tests/orm_insert_object_with_mismatched_type_error.vv:19:10: error: cannot use `Tiddler` as `Tiddlers`
3+ 17 | sql db {
4+ 18 | create table Tiddlers
5+ 19 | insert tiddler into Tiddlers
6+ | ~~~~~~~
7+ 20 | }
8+ 21 | }
9
1new file mode 100644
2+import db.sqlite
3+import json
4+
5+struct Tiddler {
6+ id int
7+ created int
8+}
9+
10+struct Tiddlers {
11+ id int [primary; sql: serial]
12+ created string
13+}
14+
15+fn main() {
16+ tiddler := json.decode(Tiddler, '{}') or { Tiddler{} }
17+ db := sqlite.connect(':memory:') or { panic(err) }
18+ sql db {
19+ create table Tiddlers
20+ insert tiddler into Tiddlers
21+ }
22+}
23
1new file mode 100644
2+vlib/v/checker/tests/orm_using_undefined_object_in_insert_error.vv:13:10: error: undefined ident: `bug`
3+ 11 | sql db {
4+ 12 | create table Node
5+ 13 | insert bug into Node
6+ | ~~~
7+ 14 | }
8+ 15 | }
9
1new file mode 100644
2+import db.sqlite
3+
4+struct Node {
5+ id int [primary; sql: serial]
6+ text string
7+}
8+
9+fn main() {
10+ db := sqlite.connect(':memory:') or { panic(err) }
11+
12+ sql db {
13+ create table Node
14+ insert bug into Node
15+ }
16+}
17
1 typ: typ
2 pos: typ_pos
3 }
4+ scope: p.scope
5 }
6 } else if n == 'drop' {
7 kind = .drop
8 typ: typ
9 pos: typ_pos
10 }
11+ scope: p.scope
12 }
13 }
14 mut inserted_var_name := ''
15 update_exprs: update_exprs
16 kind: kind
17 where_expr: where_expr
18+ is_top_level: true
19+ scope: p.scope
20 }
21 }
22