From e8d133d548de34ac7c017be3b543415f0d3434d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Casper=20K=C3=BCthe?= <43839798+Casper64@users.noreply.github.com> Date: Tue, 12 Sep 2023 13:50:13 +0200 Subject: [PATCH] orm: fix cgen inserting wrong array index (#19324) --- cmd/tools/vtest-self.v | 2 ++ vlib/orm/orm_fk_test.v | 57 ++++++++++++++++++++++++++++++++++++++++++ vlib/v/gen/c/orm.v | 8 ++++-- 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 vlib/orm/orm_fk_test.v diff --git a/cmd/tools/vtest-self.v b/cmd/tools/vtest-self.v index cfa223c827cade..093be48531774a 100644 --- a/cmd/tools/vtest-self.v +++ b/cmd/tools/vtest-self.v @@ -134,6 +134,7 @@ const ( 'vlib/orm/orm_mut_db_test.v', 'vlib/orm/orm_result_test.v', 'vlib/orm/orm_custom_operators_test.v', + 'vlib/orm/orm_fk_test.v', 'vlib/db/sqlite/sqlite_test.v', 'vlib/db/sqlite/sqlite_orm_test.v', 'vlib/db/sqlite/sqlite_vfs_lowlevel_test.v', @@ -213,6 +214,7 @@ const ( 'vlib/orm/orm_mut_db_test.v', 'vlib/orm/orm_result_test.v', 'vlib/orm/orm_custom_operators_test.v', + 'vlib/orm/orm_fk_test.v', 'vlib/v/tests/orm_sub_struct_test.v', 'vlib/v/tests/orm_sub_array_struct_test.v', 'vlib/v/tests/orm_joined_tables_select_test.v', diff --git a/vlib/orm/orm_fk_test.v b/vlib/orm/orm_fk_test.v new file mode 100644 index 00000000000000..643ad8d55e69a1 --- /dev/null +++ b/vlib/orm/orm_fk_test.v @@ -0,0 +1,57 @@ +import db.sqlite + +struct Person { + id int [primary; sql: serial] + age int + brothers []Brother [fkey: 'person_id'] + sisters []Sister [fkey: 'person_id'] + field_after_fkeys string +} + +struct Brother { + id int [primary; sql: serial] + person_id int + name string +} + +struct Sister { + id int [primary; sql: serial] + person_id int + name string +} + +fn test_field_after_fkeys() { + db := sqlite.connect(':memory:') or { panic(err) } + + sql db { + create table Brother + create table Sister + create table Person + }! + + person := Person{ + age: 21 + brothers: [Brother{ + name: 'aaa' + }, Brother{ + name: 'bbb' + }] + sisters: [Sister{ + name: 'ccc' + }, Sister{ + name: 'ddd' + }] + field_after_fkeys: 'eee' + } + + sql db { + insert person into Person + }! + + persons := sql db { + select from Person + }! + + assert persons[0].age == 21 + assert persons[0].field_after_fkeys == 'eee' +} diff --git a/vlib/v/gen/c/orm.v b/vlib/v/gen/c/orm.v index 991841c8834e44..c2a3609deb166a 100644 --- a/vlib/v/gen/c/orm.v +++ b/vlib/v/gen/c/orm.v @@ -876,8 +876,10 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, le g.writeln('if (${select_unwrapped_result_var_name}.len > 0) {') g.indent++ - for i, field in fields { - array_get_call_code := '(*(orm__Primitive*) array_get((*(Array_orm__Primitive*) array_get(${select_unwrapped_result_var_name}, ${idx})), ${i}))' + + mut selected_fields_idx := 0 + for field in fields { + array_get_call_code := '(*(orm__Primitive*) array_get((*(Array_orm__Primitive*) array_get(${select_unwrapped_result_var_name}, ${idx})), ${selected_fields_idx}))' sym := g.table.sym(field.typ) if sym.kind == .struct_ && sym.name != 'time.Time' { mut sub := node.sub_structs[int(field.typ)] @@ -897,6 +899,7 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, le g.write_orm_select(sub, connection_var_name, '${tmp}.${c_name(field.name)} = ', or_expr) + selected_fields_idx++ } else if sym.kind == .array { mut fkey := '' // TODO: move to the ORM checker @@ -956,6 +959,7 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, le } else { mut typ := sym.cname g.writeln('${tmp}.${c_name(field.name)} = *(${array_get_call_code}._${typ});') + selected_fields_idx++ } } g.indent--