mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
orm: fix multi substructs (#9941)
This commit is contained in:
parent
92a22e9ec5
commit
b8e070b2a1
@ -20,6 +20,7 @@ const (
|
||||
'vlib/orm/orm_test.v',
|
||||
'vlib/sqlite/sqlite_test.v',
|
||||
'vlib/v/tests/orm_sub_struct_test.v',
|
||||
'vlib/v/tests/orm_sub_array_struct_test.v',
|
||||
'vlib/vweb/tests/vweb_test.v',
|
||||
'vlib/vweb/request_test.v',
|
||||
'vlib/vweb/route_test.v',
|
||||
@ -56,6 +57,7 @@ const (
|
||||
'vlib/sqlite/sqlite_test.v',
|
||||
'vlib/orm/orm_test.v',
|
||||
'vlib/v/tests/orm_sub_struct_test.v',
|
||||
'vlib/v/tests/orm_sub_array_struct_test.v',
|
||||
'vlib/clipboard/clipboard_test.v',
|
||||
'vlib/vweb/tests/vweb_test.v',
|
||||
'vlib/vweb/request_test.v',
|
||||
|
@ -19,9 +19,9 @@ struct User {
|
||||
}
|
||||
|
||||
struct Parent {
|
||||
id int [primary; sql: serial]
|
||||
name string
|
||||
chields []Chield [fkey: 'parent_id']
|
||||
id int [primary; sql: serial]
|
||||
name string
|
||||
children []Chield [fkey: 'parent_id']
|
||||
}
|
||||
|
||||
struct Chield {
|
||||
@ -48,7 +48,7 @@ fn sqlite3_array() {
|
||||
|
||||
par := Parent{
|
||||
name: 'test'
|
||||
chields: [
|
||||
children: [
|
||||
Chield{
|
||||
name: 'abc'
|
||||
},
|
||||
@ -90,7 +90,7 @@ fn mysql_array() {
|
||||
|
||||
par := Parent{
|
||||
name: 'test'
|
||||
chields: [
|
||||
children: [
|
||||
Chield{
|
||||
name: 'abc'
|
||||
},
|
||||
@ -129,7 +129,7 @@ fn psql_array() {
|
||||
|
||||
par := Parent{
|
||||
name: 'test'
|
||||
chields: [
|
||||
children: [
|
||||
Chield{
|
||||
name: 'abc'
|
||||
},
|
||||
|
@ -6708,6 +6708,10 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type {
|
||||
} else {
|
||||
ast.Type(0)
|
||||
}
|
||||
mut object_var_name := '${node.object_var_name}.$f.name'
|
||||
if typ != f.typ {
|
||||
object_var_name = node.object_var_name
|
||||
}
|
||||
mut n := ast.SqlStmtLine{
|
||||
pos: node.pos
|
||||
kind: node.kind
|
||||
@ -6715,7 +6719,7 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type {
|
||||
pos: node.table_expr.pos
|
||||
typ: typ
|
||||
}
|
||||
object_var_name: '${node.object_var_name}.$f.name'
|
||||
object_var_name: object_var_name
|
||||
}
|
||||
tmp_inside_sql := c.inside_sql
|
||||
c.sql_stmt_line(mut n)
|
||||
|
@ -159,6 +159,7 @@ fn (mut g Gen) sqlite3_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr)
|
||||
g.writeln(');')
|
||||
mut arr_stmt := []ast.SqlStmtLine{}
|
||||
mut arr_fkeys := []string{}
|
||||
mut arr_field_name := []string{}
|
||||
if node.kind == .insert {
|
||||
// build the object now (`x.name = ... x.id == ...`)
|
||||
for i, field in node.fields {
|
||||
@ -203,6 +204,7 @@ fn (mut g Gen) sqlite3_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr)
|
||||
|
||||
arr_stmt << node.sub_structs[int(t)]
|
||||
arr_fkeys << fkey
|
||||
arr_field_name << field.name
|
||||
}
|
||||
} else {
|
||||
g.writeln('sqlite3_bind_int($g.sql_stmt_name, ${i + 0} , $x); // stmt')
|
||||
@ -224,7 +226,7 @@ fn (mut g Gen) sqlite3_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr)
|
||||
id_name := g.new_tmp_var()
|
||||
g.writeln('int $id_name = string_int((*(string*)array_get((*(sqlite__Row*)array_get($res, 0)).vals, 0)));')
|
||||
|
||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, id_name, db_expr)
|
||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, arr_field_name, id_name, db_expr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,6 +451,7 @@ fn (mut g Gen) mysql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||
g.writeln('memset($bind, 0, sizeof(MYSQL_BIND)*$g.sql_i);')
|
||||
mut arr_stmt := []ast.SqlStmtLine{}
|
||||
mut arr_fkeys := []string{}
|
||||
mut arr_field_name := []string{}
|
||||
if node.kind == .insert {
|
||||
for i, field in node.fields {
|
||||
if g.get_sql_field_type(field) == ast.Type(-1) {
|
||||
@ -510,6 +513,7 @@ fn (mut g Gen) mysql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||
|
||||
arr_stmt << node.sub_structs[int(t)]
|
||||
arr_fkeys << fkey
|
||||
arr_field_name << field.name
|
||||
}
|
||||
} else {
|
||||
t, sym := g.mysql_buffer_typ_from_field(field)
|
||||
@ -549,7 +553,7 @@ fn (mut g Gen) mysql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||
g.writeln('int $id_name = string_int(tos_clone(${rs}_row[0]));')
|
||||
g.writeln('mysql_free_result($rs);')
|
||||
|
||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, id_name, db_expr)
|
||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, arr_field_name, id_name, db_expr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -826,6 +830,7 @@ fn (mut g Gen) psql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||
|
||||
mut arr_stmt := []ast.SqlStmtLine{}
|
||||
mut arr_fkeys := []string{}
|
||||
mut arr_field_name := []string{}
|
||||
if node.kind == .insert {
|
||||
for i, field in node.fields {
|
||||
if g.get_sql_field_type(field) == ast.Type(-1) {
|
||||
@ -874,6 +879,7 @@ fn (mut g Gen) psql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||
|
||||
arr_stmt << node.sub_structs[int(t)]
|
||||
arr_fkeys << fkey
|
||||
arr_field_name << field.name
|
||||
}
|
||||
} else {
|
||||
g.sql_buf = strings.new_builder(100)
|
||||
@ -894,8 +900,7 @@ fn (mut g Gen) psql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||
g.writeln('if (${res}.state != 0) { IError err = ${res}.err; eprintln(_STR("\\000%.*s", 2, IError_str(err))); }')
|
||||
id_name := g.new_tmp_var()
|
||||
g.writeln('int $id_name = string_int((*(string*)array_get((*(pg__Row*)${res}.data).vals, 0)));')
|
||||
|
||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, id_name, db_expr)
|
||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, arr_field_name, id_name, db_expr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1162,23 +1167,34 @@ fn (mut g Gen) sql_select_arr(field ast.StructField, node ast.SqlExpr, primary s
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) sql_arr_stmt(arr_stmt []ast.SqlStmtLine, arr_fkeys []string, id_name string, db_expr ast.Expr) {
|
||||
fn (mut g Gen) sql_arr_stmt(arr_stmt []ast.SqlStmtLine, arr_fkeys []string, arr_field_name []string, id_name string, db_expr ast.Expr) {
|
||||
for i, s in arr_stmt {
|
||||
cnt := g.new_tmp_var()
|
||||
g.writeln('for (int $cnt = 0; $cnt < ${s.object_var_name}.len; $cnt++) {')
|
||||
g.writeln('for (int $cnt = 0; $cnt < ${s.object_var_name}.${arr_field_name[i]}.len; $cnt++) {')
|
||||
name := g.table.get_type_symbol(s.table_expr.typ).cname
|
||||
tmp_var := g.new_tmp_var()
|
||||
g.writeln('\t$name $tmp_var = (*($name*)array_get($s.object_var_name, $cnt));')
|
||||
g.writeln('\t$name $tmp_var = (*($name*)array_get(${s.object_var_name}.${arr_field_name[i]}, $cnt));')
|
||||
|
||||
mut sub_structs := map[int]ast.SqlStmtLine{}
|
||||
|
||||
for key, sub in s.sub_structs {
|
||||
sub_structs[key] = ast.SqlStmtLine{
|
||||
pos: sub.pos
|
||||
kind: sub.kind
|
||||
table_expr: sub.table_expr
|
||||
object_var_name: tmp_var
|
||||
fields: sub.fields
|
||||
sub_structs: sub.sub_structs
|
||||
}
|
||||
}
|
||||
stmt := ast.SqlStmtLine{
|
||||
pos: s.pos
|
||||
kind: s.kind
|
||||
table_expr: s.table_expr
|
||||
object_var_name: tmp_var
|
||||
fields: s.fields
|
||||
sub_structs: s.sub_structs
|
||||
sub_structs: sub_structs
|
||||
}
|
||||
|
||||
tmp_fkey := g.sql_fkey
|
||||
tmp_parent_id := g.sql_parent_id
|
||||
g.sql_fkey = arr_fkeys[i]
|
||||
|
50
vlib/v/tests/orm_sub_array_struct_test.v
Normal file
50
vlib/v/tests/orm_sub_array_struct_test.v
Normal file
@ -0,0 +1,50 @@
|
||||
import sqlite
|
||||
|
||||
struct Parent {
|
||||
id int [primary; sql: serial]
|
||||
name string
|
||||
chields []Chield [fkey: 'parent_id']
|
||||
}
|
||||
|
||||
struct Chield {
|
||||
id int [primary; sql: serial]
|
||||
parent_id int
|
||||
name string
|
||||
}
|
||||
|
||||
fn test_orm_array() {
|
||||
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||
sql db {
|
||||
create table Parent
|
||||
}
|
||||
|
||||
par := Parent{
|
||||
name: 'test'
|
||||
chields: [
|
||||
Chield{
|
||||
name: 'abc'
|
||||
},
|
||||
Chield{
|
||||
name: 'def'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
sql db {
|
||||
insert par into Parent
|
||||
}
|
||||
|
||||
parent := sql db {
|
||||
select from Parent where id == 1
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table Chield
|
||||
drop table Parent
|
||||
}
|
||||
|
||||
assert parent.name == par.name
|
||||
assert parent.chields.len == par.chields.len
|
||||
assert parent.chields[0].name == 'abc'
|
||||
assert parent.chields[1].name == 'def'
|
||||
}
|
Loading…
Reference in New Issue
Block a user