Skip to content

Commit 499d052

Browse files
authored
checker,orm: add compile error for unsupported field data types like field []int etc (#18537)
1 parent 2b2aca6 commit 499d052

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

vlib/v/checker/orm.v

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
4040
}
4141

4242
info := table_sym.info as ast.Struct
43-
mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name)
43+
mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name,
44+
node)
4445
non_primitive_fields := c.get_orm_non_primitive_fields(fields)
4546
mut sub_structs := map[int]ast.SqlExpr{}
4647

@@ -215,7 +216,8 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type {
215216
}
216217

217218
info := table_sym.info as ast.Struct
218-
mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name)
219+
mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name,
220+
ast.SqlExpr{})
219221
mut sub_structs := map[int]ast.SqlStmtLine{}
220222
non_primitive_fields := c.get_orm_non_primitive_fields(fields)
221223

@@ -327,7 +329,7 @@ fn (mut c Checker) check_orm_struct_field_attributes(field ast.StructField) {
327329
}
328330
}
329331

330-
fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Pos, table_name string) []ast.StructField {
332+
fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Pos, table_name string, sql_expr ast.SqlExpr) []ast.StructField {
331333
fields := info.fields.filter(fn [mut c] (field ast.StructField) bool {
332334
is_primitive := field.typ.is_string() || field.typ.is_bool() || field.typ.is_number()
333335
is_struct := c.table.type_symbols[int(field.typ)].kind == .struct_
@@ -344,6 +346,18 @@ fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Pos, t
344346
return []ast.StructField{}
345347
}
346348

349+
field_pos := c.orm_get_field_pos(sql_expr.where_expr)
350+
for field in info.fields {
351+
if c.table.sym(field.typ).kind == .array
352+
&& c.table.sym(c.table.sym(field.typ).array_info().elem_type).is_primitive() {
353+
c.add_error_detail('')
354+
c.add_error_detail(' field name: `${field.name}`')
355+
c.add_error_detail(' data type: `${c.table.type_to_str(field.typ)}`')
356+
c.orm_error('does not support array of primitive types', field_pos)
357+
return []ast.StructField{}
358+
}
359+
}
360+
347361
return fields
348362
}
349363

@@ -610,3 +624,24 @@ fn (_ &Checker) check_field_of_inserting_struct_is_uninitialized(node &ast.SqlSt
610624

611625
return false
612626
}
627+
628+
fn (c &Checker) orm_get_field_pos(expr &ast.Expr) token.Pos {
629+
mut pos := token.Pos{}
630+
if expr is ast.InfixExpr {
631+
if expr.left is ast.Ident {
632+
pos = expr.left.pos
633+
} else if expr.left is ast.InfixExpr || expr.left is ast.ParExpr
634+
|| expr.left is ast.PrefixExpr {
635+
pos = c.orm_get_field_pos(expr.left)
636+
} else {
637+
pos = expr.left.pos()
638+
}
639+
} else if expr is ast.ParExpr {
640+
pos = c.orm_get_field_pos(expr.expr)
641+
} else if expr is ast.PrefixExpr {
642+
pos = c.orm_get_field_pos(expr.right)
643+
} else {
644+
pos = expr.pos()
645+
}
646+
return pos
647+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:15:29: error: V ORM: does not support array of primitive types
2+
13 | bytes := [u8(0)]
3+
14 | e := sql db {
4+
15 | select from Example where example == bytes
5+
| ~~~~~~~
6+
16 | }!
7+
17 | f := sql db {
8+
Details:
9+
field name: `example`
10+
data type: `[]u8`
11+
vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:18:34: error: V ORM: does not support array of primitive types
12+
16 | }!
13+
17 | f := sql db {
14+
18 | select from Example where (example == bytes)
15+
| ~~~~~~~
16+
19 | }!
17+
20 | print(e)
18+
Details:
19+
field name: `example`
20+
data type: `[]u8`
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module main
2+
3+
import db.pg
4+
5+
[table: 'example']
6+
pub struct Example {
7+
id int [primary; sql: serial]
8+
example []u8 [sql_type: 'bytea'; unique]
9+
}
10+
11+
fn main() {
12+
db := pg.connect(pg.Config{}) or { exit(0) }
13+
bytes := [u8(0)]
14+
e := sql db {
15+
select from Example where example == bytes
16+
}!
17+
f := sql db {
18+
select from Example where (example == bytes)
19+
}!
20+
print(e)
21+
print(f)
22+
}

0 commit comments

Comments
 (0)