Skip to content

Commit

Permalink
checker,orm: skip compile-time error msg for fields tagged with `[ski…
Browse files Browse the repository at this point in the history
…p]` and `[sql: '-']` (#18700)
  • Loading branch information
dnkdev committed Jun 29, 2023
1 parent 499d052 commit f0fb86f
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 31 deletions.
14 changes: 10 additions & 4 deletions vlib/orm/orm_test.v
Expand Up @@ -18,12 +18,14 @@ struct Module {

[table: 'userlist']
struct User {
id int [primary; sql: serial]
id int [primary; sql: serial]
age int
name string [sql: 'username']
name string [sql: 'username']
is_customer bool
skipped_string string [skip]
skipped_string2 string [sql: '-']
skipped_string string [skip]
skipped_string2 string [sql: '-']
skipped_array []string [skip]
skipped_array2 []string [sql: '-']
}

struct Foo {
Expand All @@ -50,6 +52,8 @@ fn test_use_struct_field_as_limit() {
age: 29
name: 'Sam'
skipped_string2: 'this should be ignored'
skipped_array: ['ignored', 'array']
skipped_array2: ['another', 'ignored', 'array']
}

sql db {
Expand All @@ -65,6 +69,8 @@ fn test_use_struct_field_as_limit() {
assert users[0].age == 29
assert users[0].skipped_string == ''
assert users[0].skipped_string2 == ''
assert users[0].skipped_array == [], 'skipped because of the [skip] tag, used for both sql and json'
assert users[0].skipped_array2 == [], "should be skipped, because of the sql specific [sql: '-'] tag"
}

fn test_orm() {
Expand Down
4 changes: 4 additions & 0 deletions vlib/v/ast/attr.v
Expand Up @@ -54,6 +54,10 @@ pub fn (attrs []Attr) contains(str string) bool {
return attrs.any(it.name == str)
}

pub fn (attrs []Attr) contains_arg(str string, arg string) bool {
return attrs.any(it.has_arg && it.name == str && it.arg == arg)
}

[direct_array_access]
pub fn (attrs []Attr) find_first(aname string) ?Attr {
for a in attrs {
Expand Down
41 changes: 22 additions & 19 deletions vlib/v/checker/orm.v
Expand Up @@ -330,34 +330,37 @@ 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, 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_
is_array := c.table.sym(field.typ).kind == .array
is_array_with_struct_elements := is_array
&& c.table.sym(c.table.sym(field.typ).array_info().elem_type).kind == .struct_
has_no_skip_attr := !field.attrs.contains('skip')

return (is_primitive || is_struct || is_array_with_struct_elements) && has_no_skip_attr
})

if fields.len == 0 {
c.orm_error('select: empty fields in `${table_name}`', pos)
return []ast.StructField{}
}

field_pos := c.orm_get_field_pos(sql_expr.where_expr)
mut fields := []ast.StructField{}
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() {
is_primitive := field.typ.is_string() || field.typ.is_bool() || field.typ.is_number()
fsym := c.table.sym(field.typ)
is_struct := fsym.kind == .struct_
is_array := fsym.kind == .array
elem_sym := if is_array {
c.table.sym(fsym.array_info().elem_type)
} else {
ast.invalid_type_symbol
}
is_array_with_struct_elements := is_array && elem_sym.kind == .struct_
has_skip_attr := field.attrs.contains('skip') || field.attrs.contains_arg('sql', '-')
if has_skip_attr {
continue
}
if is_primitive || is_struct || is_array_with_struct_elements {
fields << field
}
if is_array && elem_sym.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{}
}
}

if fields.len == 0 {
c.orm_error('select: empty fields in `${table_name}`', pos)
}
return fields
}

Expand Down
Expand Up @@ -5,16 +5,16 @@ vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:15:29: erro
| ~~~~~~~
16 | }!
17 | f := sql db {
Details:
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
vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:18:30: error: V ORM: does not support array of primitive types
16 | }!
17 | f := sql db {
18 | select from Example where (example == bytes)
| ~~~~~~~
19 | }!
18 | select from Example where (example == bytes)
| ~~~~~~~
19 | }!
20 | print(e)
Details:
Details:
field name: `example`
data type: `[]u8`
Expand Up @@ -15,8 +15,8 @@ fn main() {
select from Example where example == bytes
}!
f := sql db {
select from Example where (example == bytes)
}!
select from Example where (example == bytes)
}!
print(e)
print(f)
}

0 comments on commit f0fb86f

Please sign in to comment.