orm: fix cgen inserting wrong array index (#19324)

This commit is contained in:
Casper Küthe 2023-09-12 13:50:13 +02:00 committed by GitHub
parent 55ca8d8d8e
commit e8d133d548
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 2 deletions

View file

@ -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',

57
vlib/orm/orm_fk_test.v Normal file
View file

@ -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'
}

View file

@ -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--