orm: fix checking invalid recursive structs in sql stmts (fix #20278) (#20505)

This commit is contained in:
shove 2024-01-12 21:53:06 +08:00 committed by GitHub
parent 0c4611fa4c
commit fdd481b2c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 5 deletions

View File

@ -48,7 +48,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
field_typ, field_sym := c.get_non_array_type(field.typ) field_typ, field_sym := c.get_non_array_type(field.typ)
if field_sym.kind == .struct_ && (field_typ.idx() == node.table_expr.typ.idx() if field_sym.kind == .struct_ && (field_typ.idx() == node.table_expr.typ.idx()
|| c.check_recursive_structs(field_sym, table_sym.name)) { || c.check_recursive_structs(field_sym, table_sym.name)) {
c.error('invalid recursive struct `${field_sym.name}`', field.pos) c.orm_error('invalid recursive struct `${field_sym.name}`', field.pos)
return ast.void_type return ast.void_type
} }
@ -273,6 +273,13 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type {
non_primitive_fields := c.get_orm_non_primitive_fields(fields) non_primitive_fields := c.get_orm_non_primitive_fields(fields)
for field in non_primitive_fields { for field in non_primitive_fields {
field_typ, field_sym := c.get_non_array_type(field.typ)
if field_sym.kind == .struct_ && (field_typ.idx() == node.table_expr.typ.idx()
|| c.check_recursive_structs(field_sym, table_sym.name)) {
c.orm_error('invalid recursive struct `${field_sym.name}`', field.pos)
return ast.void_type
}
// Delete an uninitialized struct from fields and skip adding the current field // Delete an uninitialized struct from fields and skip adding the current field
// to sub structs to skip inserting an empty struct in the related table. // to sub structs to skip inserting an empty struct in the related table.
if c.check_field_of_inserting_struct_is_uninitialized(node, field.name) { if c.check_field_of_inserting_struct_is_uninitialized(node, field.name) {

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/orm_invalid_recursive_structs_err.vv:6:2: error: invalid recursive struct `Child` vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.vv:6:2: error: ORM: invalid recursive struct `Child`
4 | struct Parent { 4 | struct Parent {
5 | id int @[primary; sql: serial] 5 | id int @[primary; sql: serial]
6 | children []Child @[fkey: 'parent_id'] 6 | children []Child @[fkey: 'parent_id']

View File

@ -14,12 +14,12 @@ struct Child {
} }
fn main() { fn main() {
mut db := sqlite.connect('/dev/null') or { panic(err) } mut db := sqlite.connect(':memory:')!
defer { defer {
db.close() or { panic(err) } db.close() or { panic(err) }
} }
_ := sql db { _ = sql db {
select from Parent select from Parent
} or { panic(err) } }!
} }

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.vv:6:2: error: ORM: invalid recursive struct `Child`
4 | struct Parent {
5 | id int @[primary; sql: serial]
6 | children []Child @[fkey: 'parent_id']
| ~~~~~~~~~~~~~~~~
7 | }
8 |

View File

@ -0,0 +1,25 @@
import db.sqlite
@[table: 'parents']
struct Parent {
id int @[primary; sql: serial]
children []Child @[fkey: 'parent_id']
}
@[table: 'children']
struct Child {
id int @[primary; sql: serial]
parent_id int
parent Parent
}
fn main() {
mut db := sqlite.connect(':memory:')!
defer {
db.close() or { panic(err) }
}
sql db {
create table Parent
}!
}