Skip to content

Commit bfd36f8

Browse files
authored
orm: fix fkey insert as assigment expr (fix #25568) (#25575)
1 parent 88f589e commit bfd36f8

3 files changed

Lines changed: 63 additions & 7 deletions

File tree

‎vlib/orm/orm_fk_test.v‎

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,54 @@ fn test_field_after_fkeys() {
5252
persons := sql db {
5353
select from Person
5454
}!
55-
5655
assert persons[0].age == 21
5756
assert persons[0].field_after_fkeys == 'eee'
5857
}
58+
59+
@[table: 'foos']
60+
struct Foo {
61+
id int @[primary; sql: serial]
62+
name string
63+
children []Child @[fkey: 'parent_id']
64+
}
65+
66+
struct Child {
67+
id int @[primary; sql: serial]
68+
parent_id int
69+
name string
70+
}
71+
72+
fn test_fkey_insert_as_assignment_expr() {
73+
db := sqlite.connect(':memory:')!
74+
75+
sql db {
76+
create table Foo
77+
create table Child
78+
}!
79+
80+
foo := Foo{
81+
name: 'abc'
82+
children: [
83+
Child{
84+
name: 'abc'
85+
},
86+
Child{
87+
name: 'def'
88+
},
89+
]
90+
}
91+
// use insert as an assigment expr
92+
_ := sql db {
93+
insert foo into Foo
94+
}!
95+
96+
result := sql db {
97+
select from Foo where id == 1
98+
}!
99+
assert result[0].children.len == 2
100+
101+
res := sql db {
102+
select from Child
103+
}!
104+
assert res.len == 2
105+
}

‎vlib/v/checker/orm.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
7171
foreign_typ := c.get_field_foreign_table_type(field)
7272

7373
mut subquery_expr := ast.SqlExpr{
74+
inserted_var: field.name
7475
pos: node.pos
7576
has_where: true
7677
where_expr: ast.None{}

‎vlib/v/gen/c/orm.v‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,26 @@ fn (mut g Gen) sql_insert_expr(node ast.SqlExpr) {
5353
g.sql_table_name = g.table.sym(node.table_expr.typ).name
5454

5555
// orm_insert needs an SqlStmtLine, build it from SqlExpr (most nodes are the same)
56-
hack_stmt_line := ast.SqlStmtLine{
57-
object_var: node.inserted_var
58-
fields: node.fields
59-
table_expr: node.table_expr
60-
// sub_structs: node.sub_structs
61-
}
56+
hack_stmt_line := g.build_sql_stmt_line_from_sql_expr(node)
6257
g.write_orm_insert(hack_stmt_line, table_name, connection_var_name, result_var_name,
6358
node.or_expr, table_attrs)
6459

6560
g.write2(left, 'orm__Connection_name_table[${connection_var_name}._typ]._method_last_id(${connection_var_name}._object)')
6661
}
6762

63+
fn (mut g Gen) build_sql_stmt_line_from_sql_expr(node ast.SqlExpr) ast.SqlStmtLine {
64+
mut sub_structs := map[int]ast.SqlStmtLine{}
65+
for typ, sub in node.sub_structs {
66+
sub_structs[typ] = g.build_sql_stmt_line_from_sql_expr(sub)
67+
}
68+
return ast.SqlStmtLine{
69+
object_var: node.inserted_var
70+
fields: node.fields
71+
table_expr: node.table_expr
72+
sub_structs: sub_structs
73+
}
74+
}
75+
6876
// sql_stmt writes C code that calls ORM functions for
6977
// performing various database operations such as creating and dropping tables,
7078
// as well as inserting and updating objects.

0 commit comments

Comments
 (0)