mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
orm: detect type mismatching on inserting an object (#17157)
This commit is contained in:
parent
bb512f782e
commit
a489417484
@ -1751,6 +1751,10 @@ pub:
|
|||||||
pos token.Pos
|
pos token.Pos
|
||||||
where_expr Expr
|
where_expr Expr
|
||||||
update_exprs []Expr // for `update`
|
update_exprs []Expr // for `update`
|
||||||
|
// is_top_level indicates that a statement is parsed from code
|
||||||
|
// and is not inserted by ORM for inserting in related tables.
|
||||||
|
is_top_level bool
|
||||||
|
scope &Scope = unsafe { nil }
|
||||||
pub mut:
|
pub mut:
|
||||||
object_var_name string // `user`
|
object_var_name string // `user`
|
||||||
updated_columns []string // for `update set x=y`
|
updated_columns []string // for `update set x=y`
|
||||||
|
@ -28,6 +28,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
|
|||||||
info := sym.info as ast.Struct
|
info := sym.info as ast.Struct
|
||||||
mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name)
|
mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name)
|
||||||
mut sub_structs := map[int]ast.SqlExpr{}
|
mut sub_structs := map[int]ast.SqlExpr{}
|
||||||
|
|
||||||
for f in fields.filter((c.table.type_symbols[int(it.typ)].kind == .struct_
|
for f in fields.filter((c.table.type_symbols[int(it.typ)].kind == .struct_
|
||||||
|| (c.table.sym(it.typ).kind == .array
|
|| (c.table.sym(it.typ).kind == .array
|
||||||
&& c.table.sym(c.table.sym(it.typ).array_info().elem_type).kind == .struct_))
|
&& c.table.sym(c.table.sym(it.typ).array_info().elem_type).kind == .struct_))
|
||||||
@ -52,6 +53,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
|
|||||||
tmp_inside_sql := c.inside_sql
|
tmp_inside_sql := c.inside_sql
|
||||||
c.sql_expr(mut n)
|
c.sql_expr(mut n)
|
||||||
c.inside_sql = tmp_inside_sql
|
c.inside_sql = tmp_inside_sql
|
||||||
|
|
||||||
n.where_expr = ast.InfixExpr{
|
n.where_expr = ast.InfixExpr{
|
||||||
op: .eq
|
op: .eq
|
||||||
pos: n.pos
|
pos: n.pos
|
||||||
@ -85,6 +87,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
|
|||||||
|
|
||||||
sub_structs[int(typ)] = n
|
sub_structs[int(typ)] = n
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.is_count {
|
if node.is_count {
|
||||||
fields = [
|
fields = [
|
||||||
ast.StructField{
|
ast.StructField{
|
||||||
@ -92,8 +95,10 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
node.fields = fields
|
node.fields = fields
|
||||||
node.sub_structs = sub_structs.move()
|
node.sub_structs = sub_structs.move()
|
||||||
|
|
||||||
if node.has_where {
|
if node.has_where {
|
||||||
c.expr(node.where_expr)
|
c.expr(node.where_expr)
|
||||||
c.check_expr_has_no_fn_calls_with_non_orm_return_type(&node.where_expr)
|
c.check_expr_has_no_fn_calls_with_non_orm_return_type(&node.where_expr)
|
||||||
@ -150,6 +155,23 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type {
|
|||||||
defer {
|
defer {
|
||||||
c.cur_orm_ts = old_ts
|
c.cur_orm_ts = old_ts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if node.kind == .insert && node.is_top_level {
|
||||||
|
inserting_object_name := node.object_var_name
|
||||||
|
inserting_object_var := node.scope.find(inserting_object_name) or {
|
||||||
|
c.error('undefined ident: `${inserting_object_name}`', node.pos)
|
||||||
|
return ast.void_type
|
||||||
|
}
|
||||||
|
|
||||||
|
if inserting_object_var.typ != node.table_expr.typ {
|
||||||
|
table_name := table_sym.name
|
||||||
|
inserting_type_name := c.table.sym(inserting_object_var.typ).name
|
||||||
|
|
||||||
|
c.error('cannot use `${inserting_type_name}` as `${table_name}`', node.pos)
|
||||||
|
return ast.void_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if table_sym.info !is ast.Struct {
|
if table_sym.info !is ast.Struct {
|
||||||
c.error('unknown type `${table_sym.name}`', node.pos)
|
c.error('unknown type `${table_sym.name}`', node.pos)
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
vlib/v/checker/tests/orm_insert_object_with_mismatched_type_error.vv:19:10: error: cannot use `Tiddler` as `Tiddlers`
|
||||||
|
17 | sql db {
|
||||||
|
18 | create table Tiddlers
|
||||||
|
19 | insert tiddler into Tiddlers
|
||||||
|
| ~~~~~~~
|
||||||
|
20 | }
|
||||||
|
21 | }
|
@ -0,0 +1,21 @@
|
|||||||
|
import db.sqlite
|
||||||
|
import json
|
||||||
|
|
||||||
|
struct Tiddler {
|
||||||
|
id int
|
||||||
|
created int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Tiddlers {
|
||||||
|
id int [primary; sql: serial]
|
||||||
|
created string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
tiddler := json.decode(Tiddler, '{}') or { Tiddler{} }
|
||||||
|
db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
|
sql db {
|
||||||
|
create table Tiddlers
|
||||||
|
insert tiddler into Tiddlers
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
vlib/v/checker/tests/orm_using_undefined_object_in_insert_error.vv:13:10: error: undefined ident: `bug`
|
||||||
|
11 | sql db {
|
||||||
|
12 | create table Node
|
||||||
|
13 | insert bug into Node
|
||||||
|
| ~~~
|
||||||
|
14 | }
|
||||||
|
15 | }
|
@ -0,0 +1,15 @@
|
|||||||
|
import db.sqlite
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
id int [primary; sql: serial]
|
||||||
|
text string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
|
|
||||||
|
sql db {
|
||||||
|
create table Node
|
||||||
|
insert bug into Node
|
||||||
|
}
|
||||||
|
}
|
@ -203,6 +203,7 @@ fn (mut p Parser) parse_sql_stmt_line() ast.SqlStmtLine {
|
|||||||
typ: typ
|
typ: typ
|
||||||
pos: typ_pos
|
pos: typ_pos
|
||||||
}
|
}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
} else if n == 'drop' {
|
} else if n == 'drop' {
|
||||||
kind = .drop
|
kind = .drop
|
||||||
@ -220,6 +221,7 @@ fn (mut p Parser) parse_sql_stmt_line() ast.SqlStmtLine {
|
|||||||
typ: typ
|
typ: typ
|
||||||
pos: typ_pos
|
pos: typ_pos
|
||||||
}
|
}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut inserted_var_name := ''
|
mut inserted_var_name := ''
|
||||||
@ -289,6 +291,8 @@ fn (mut p Parser) parse_sql_stmt_line() ast.SqlStmtLine {
|
|||||||
update_exprs: update_exprs
|
update_exprs: update_exprs
|
||||||
kind: kind
|
kind: kind
|
||||||
where_expr: where_expr
|
where_expr: where_expr
|
||||||
|
is_top_level: true
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user