From 499d0526fcbb7eba30e9bde31857d5d36aa3c258 Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Wed, 28 Jun 2023 16:10:36 +0530 Subject: [PATCH] checker,orm: add compile error for unsupported field data types like `field []int` etc (#18537) --- vlib/v/checker/orm.v | 41 +++++++++++++++++-- ...ere_clause_unsupported_field_types_err.out | 20 +++++++++ ...here_clause_unsupported_field_types_err.vv | 22 ++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.out create mode 100644 vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv diff --git a/vlib/v/checker/orm.v b/vlib/v/checker/orm.v index b704aea494..826c962fcd 100644 --- a/vlib/v/checker/orm.v +++ b/vlib/v/checker/orm.v @@ -40,7 +40,8 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type { } info := table_sym.info as ast.Struct - mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name) + mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name, + node) non_primitive_fields := c.get_orm_non_primitive_fields(fields) mut sub_structs := map[int]ast.SqlExpr{} @@ -215,7 +216,8 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type { } info := table_sym.info as ast.Struct - mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name) + mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, table_sym.name, + ast.SqlExpr{}) mut sub_structs := map[int]ast.SqlStmtLine{} non_primitive_fields := c.get_orm_non_primitive_fields(fields) @@ -327,7 +329,7 @@ fn (mut c Checker) check_orm_struct_field_attributes(field ast.StructField) { } } -fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Pos, table_name string) []ast.StructField { +fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Pos, table_name string, sql_expr ast.SqlExpr) []ast.StructField { fields := info.fields.filter(fn [mut c] (field ast.StructField) bool { is_primitive := field.typ.is_string() || field.typ.is_bool() || field.typ.is_number() 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 return []ast.StructField{} } + field_pos := c.orm_get_field_pos(sql_expr.where_expr) + for field in info.fields { + if c.table.sym(field.typ).kind == .array + && c.table.sym(c.table.sym(field.typ).array_info().elem_type).is_primitive() { + c.add_error_detail('') + c.add_error_detail(' field name: `${field.name}`') + c.add_error_detail(' data type: `${c.table.type_to_str(field.typ)}`') + c.orm_error('does not support array of primitive types', field_pos) + return []ast.StructField{} + } + } + return fields } @@ -610,3 +624,24 @@ fn (_ &Checker) check_field_of_inserting_struct_is_uninitialized(node &ast.SqlSt return false } + +fn (c &Checker) orm_get_field_pos(expr &ast.Expr) token.Pos { + mut pos := token.Pos{} + if expr is ast.InfixExpr { + if expr.left is ast.Ident { + pos = expr.left.pos + } else if expr.left is ast.InfixExpr || expr.left is ast.ParExpr + || expr.left is ast.PrefixExpr { + pos = c.orm_get_field_pos(expr.left) + } else { + pos = expr.left.pos() + } + } else if expr is ast.ParExpr { + pos = c.orm_get_field_pos(expr.expr) + } else if expr is ast.PrefixExpr { + pos = c.orm_get_field_pos(expr.right) + } else { + pos = expr.pos() + } + return pos +} diff --git a/vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.out b/vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.out new file mode 100644 index 0000000000..f1457596f0 --- /dev/null +++ b/vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.out @@ -0,0 +1,20 @@ +vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:15:29: error: V ORM: does not support array of primitive types + 13 | bytes := [u8(0)] + 14 | e := sql db { + 15 | select from Example where example == bytes + | ~~~~~~~ + 16 | }! + 17 | f := sql db { +Details: + field name: `example` + data type: `[]u8` +vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:18:34: error: V ORM: does not support array of primitive types + 16 | }! + 17 | f := sql db { + 18 | select from Example where (example == bytes) + | ~~~~~~~ + 19 | }! + 20 | print(e) +Details: + field name: `example` + data type: `[]u8` diff --git a/vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv b/vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv new file mode 100644 index 0000000000..2ed6d32589 --- /dev/null +++ b/vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv @@ -0,0 +1,22 @@ +module main + +import db.pg + +[table: 'example'] +pub struct Example { + id int [primary; sql: serial] + example []u8 [sql_type: 'bytea'; unique] +} + +fn main() { + db := pg.connect(pg.Config{}) or { exit(0) } + bytes := [u8(0)] + e := sql db { + select from Example where example == bytes + }! + f := sql db { + select from Example where (example == bytes) + }! + print(e) + print(f) +}