1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker,orm: skip compile-time error msg for fields tagged with [skip] and [sql: '-'] (#18700)

This commit is contained in:
Daniel Daudysh 2023-06-29 06:43:24 +03:00 committed by GitHub
parent 499d0526fc
commit f0fb86f76e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 31 deletions

View File

@ -18,12 +18,14 @@ struct Module {
[table: 'userlist'] [table: 'userlist']
struct User { struct User {
id int [primary; sql: serial] id int [primary; sql: serial]
age int age int
name string [sql: 'username'] name string [sql: 'username']
is_customer bool is_customer bool
skipped_string string [skip] skipped_string string [skip]
skipped_string2 string [sql: '-'] skipped_string2 string [sql: '-']
skipped_array []string [skip]
skipped_array2 []string [sql: '-']
} }
struct Foo { struct Foo {
@ -50,6 +52,8 @@ fn test_use_struct_field_as_limit() {
age: 29 age: 29
name: 'Sam' name: 'Sam'
skipped_string2: 'this should be ignored' skipped_string2: 'this should be ignored'
skipped_array: ['ignored', 'array']
skipped_array2: ['another', 'ignored', 'array']
} }
sql db { sql db {
@ -65,6 +69,8 @@ fn test_use_struct_field_as_limit() {
assert users[0].age == 29 assert users[0].age == 29
assert users[0].skipped_string == '' assert users[0].skipped_string == ''
assert users[0].skipped_string2 == '' 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() { fn test_orm() {

View File

@ -54,6 +54,10 @@ pub fn (attrs []Attr) contains(str string) bool {
return attrs.any(it.name == str) 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] [direct_array_access]
pub fn (attrs []Attr) find_first(aname string) ?Attr { pub fn (attrs []Attr) find_first(aname string) ?Attr {
for a in attrs { for a in attrs {

View File

@ -330,26 +330,27 @@ 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 { 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) field_pos := c.orm_get_field_pos(sql_expr.where_expr)
mut fields := []ast.StructField{}
for field in info.fields { for field in info.fields {
if c.table.sym(field.typ).kind == .array is_primitive := field.typ.is_string() || field.typ.is_bool() || field.typ.is_number()
&& c.table.sym(c.table.sym(field.typ).array_info().elem_type).is_primitive() { 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('')
c.add_error_detail(' field name: `${field.name}`') c.add_error_detail(' field name: `${field.name}`')
c.add_error_detail(' data type: `${c.table.type_to_str(field.typ)}`') c.add_error_detail(' data type: `${c.table.type_to_str(field.typ)}`')
@ -357,7 +358,9 @@ fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Pos, t
return []ast.StructField{} return []ast.StructField{}
} }
} }
if fields.len == 0 {
c.orm_error('select: empty fields in `${table_name}`', pos)
}
return fields return fields
} }

View File

@ -5,16 +5,16 @@ vlib/v/checker/tests/orm_where_clause_unsupported_field_types_err.vv:15:29: erro
| ~~~~~~~ | ~~~~~~~
16 | }! 16 | }!
17 | f := sql db { 17 | f := sql db {
Details: Details:
field name: `example` field name: `example`
data type: `[]u8` 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 | }! 16 | }!
17 | f := sql db { 17 | f := sql db {
18 | select from Example where (example == bytes) 18 | select from Example where (example == bytes)
| ~~~~~~~ | ~~~~~~~
19 | }! 19 | }!
20 | print(e) 20 | print(e)
Details: Details:
field name: `example` field name: `example`
data type: `[]u8` data type: `[]u8`

View File

@ -15,8 +15,8 @@ fn main() {
select from Example where example == bytes select from Example where example == bytes
}! }!
f := sql db { f := sql db {
select from Example where (example == bytes) select from Example where (example == bytes)
}! }!
print(e) print(e)
print(f) print(f)
} }