From fdd481b2c25ff08b5ca48ad50959b60830ea5e26 Mon Sep 17 00:00:00 2001 From: shove Date: Fri, 12 Jan 2024 21:53:06 +0800 Subject: [PATCH] orm: fix checking invalid recursive structs in sql stmts (fix #20278) (#20505) --- vlib/v/checker/orm.v | 9 ++++++- ...> orm_invalid_recursive_structs_err_1.out} | 2 +- ...=> orm_invalid_recursive_structs_err_1.vv} | 6 ++--- .../orm_invalid_recursive_structs_err_2.out | 7 ++++++ .../orm_invalid_recursive_structs_err_2.vv | 25 +++++++++++++++++++ 5 files changed, 44 insertions(+), 5 deletions(-) rename vlib/v/checker/tests/{orm_invalid_recursive_structs_err.out => orm_invalid_recursive_structs_err_1.out} (61%) rename vlib/v/checker/tests/{orm_invalid_recursive_structs_err.vv => orm_invalid_recursive_structs_err_1.vv} (78%) create mode 100644 vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.out create mode 100644 vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.vv diff --git a/vlib/v/checker/orm.v b/vlib/v/checker/orm.v index 99fe8d3f74..3ed8b472e5 100644 --- a/vlib/v/checker/orm.v +++ b/vlib/v/checker/orm.v @@ -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) if field_sym.kind == .struct_ && (field_typ.idx() == node.table_expr.typ.idx() || 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 } @@ -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) 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 // 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) { diff --git a/vlib/v/checker/tests/orm_invalid_recursive_structs_err.out b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.out similarity index 61% rename from vlib/v/checker/tests/orm_invalid_recursive_structs_err.out rename to vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.out index 2203366b71..705f0868a3 100644 --- a/vlib/v/checker/tests/orm_invalid_recursive_structs_err.out +++ b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.out @@ -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 { 5 | id int @[primary; sql: serial] 6 | children []Child @[fkey: 'parent_id'] diff --git a/vlib/v/checker/tests/orm_invalid_recursive_structs_err.vv b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.vv similarity index 78% rename from vlib/v/checker/tests/orm_invalid_recursive_structs_err.vv rename to vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.vv index f8a133d2e9..819471467a 100644 --- a/vlib/v/checker/tests/orm_invalid_recursive_structs_err.vv +++ b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_1.vv @@ -14,12 +14,12 @@ struct Child { } fn main() { - mut db := sqlite.connect('/dev/null') or { panic(err) } + mut db := sqlite.connect(':memory:')! defer { db.close() or { panic(err) } } - _ := sql db { + _ = sql db { select from Parent - } or { panic(err) } + }! } diff --git a/vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.out b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.out new file mode 100644 index 0000000000..07beb7eed7 --- /dev/null +++ b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.out @@ -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 | diff --git a/vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.vv b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.vv new file mode 100644 index 0000000000..d44a81acb6 --- /dev/null +++ b/vlib/v/checker/tests/orm_invalid_recursive_structs_err_2.vv @@ -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 + }! +}