orm: fix multi substructs (#9941)
parent
92a22e9ec5
commit
b8e070b2a1
|
@ -20,6 +20,7 @@ const (
|
||||||
'vlib/orm/orm_test.v',
|
'vlib/orm/orm_test.v',
|
||||||
'vlib/sqlite/sqlite_test.v',
|
'vlib/sqlite/sqlite_test.v',
|
||||||
'vlib/v/tests/orm_sub_struct_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/tests/vweb_test.v',
|
||||||
'vlib/vweb/request_test.v',
|
'vlib/vweb/request_test.v',
|
||||||
'vlib/vweb/route_test.v',
|
'vlib/vweb/route_test.v',
|
||||||
|
@ -56,6 +57,7 @@ const (
|
||||||
'vlib/sqlite/sqlite_test.v',
|
'vlib/sqlite/sqlite_test.v',
|
||||||
'vlib/orm/orm_test.v',
|
'vlib/orm/orm_test.v',
|
||||||
'vlib/v/tests/orm_sub_struct_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/clipboard/clipboard_test.v',
|
||||||
'vlib/vweb/tests/vweb_test.v',
|
'vlib/vweb/tests/vweb_test.v',
|
||||||
'vlib/vweb/request_test.v',
|
'vlib/vweb/request_test.v',
|
||||||
|
|
|
@ -19,9 +19,9 @@ struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Parent {
|
struct Parent {
|
||||||
id int [primary; sql: serial]
|
id int [primary; sql: serial]
|
||||||
name string
|
name string
|
||||||
chields []Chield [fkey: 'parent_id']
|
children []Chield [fkey: 'parent_id']
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Chield {
|
struct Chield {
|
||||||
|
@ -48,7 +48,7 @@ fn sqlite3_array() {
|
||||||
|
|
||||||
par := Parent{
|
par := Parent{
|
||||||
name: 'test'
|
name: 'test'
|
||||||
chields: [
|
children: [
|
||||||
Chield{
|
Chield{
|
||||||
name: 'abc'
|
name: 'abc'
|
||||||
},
|
},
|
||||||
|
@ -90,7 +90,7 @@ fn mysql_array() {
|
||||||
|
|
||||||
par := Parent{
|
par := Parent{
|
||||||
name: 'test'
|
name: 'test'
|
||||||
chields: [
|
children: [
|
||||||
Chield{
|
Chield{
|
||||||
name: 'abc'
|
name: 'abc'
|
||||||
},
|
},
|
||||||
|
@ -129,7 +129,7 @@ fn psql_array() {
|
||||||
|
|
||||||
par := Parent{
|
par := Parent{
|
||||||
name: 'test'
|
name: 'test'
|
||||||
chields: [
|
children: [
|
||||||
Chield{
|
Chield{
|
||||||
name: 'abc'
|
name: 'abc'
|
||||||
},
|
},
|
||||||
|
|
|
@ -6708,6 +6708,10 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type {
|
||||||
} else {
|
} else {
|
||||||
ast.Type(0)
|
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{
|
mut n := ast.SqlStmtLine{
|
||||||
pos: node.pos
|
pos: node.pos
|
||||||
kind: node.kind
|
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
|
pos: node.table_expr.pos
|
||||||
typ: typ
|
typ: typ
|
||||||
}
|
}
|
||||||
object_var_name: '${node.object_var_name}.$f.name'
|
object_var_name: object_var_name
|
||||||
}
|
}
|
||||||
tmp_inside_sql := c.inside_sql
|
tmp_inside_sql := c.inside_sql
|
||||||
c.sql_stmt_line(mut n)
|
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(');')
|
g.writeln(');')
|
||||||
mut arr_stmt := []ast.SqlStmtLine{}
|
mut arr_stmt := []ast.SqlStmtLine{}
|
||||||
mut arr_fkeys := []string{}
|
mut arr_fkeys := []string{}
|
||||||
|
mut arr_field_name := []string{}
|
||||||
if node.kind == .insert {
|
if node.kind == .insert {
|
||||||
// build the object now (`x.name = ... x.id == ...`)
|
// build the object now (`x.name = ... x.id == ...`)
|
||||||
for i, field in node.fields {
|
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_stmt << node.sub_structs[int(t)]
|
||||||
arr_fkeys << fkey
|
arr_fkeys << fkey
|
||||||
|
arr_field_name << field.name
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.writeln('sqlite3_bind_int($g.sql_stmt_name, ${i + 0} , $x); // stmt')
|
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()
|
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.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);')
|
g.writeln('memset($bind, 0, sizeof(MYSQL_BIND)*$g.sql_i);')
|
||||||
mut arr_stmt := []ast.SqlStmtLine{}
|
mut arr_stmt := []ast.SqlStmtLine{}
|
||||||
mut arr_fkeys := []string{}
|
mut arr_fkeys := []string{}
|
||||||
|
mut arr_field_name := []string{}
|
||||||
if node.kind == .insert {
|
if node.kind == .insert {
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
if g.get_sql_field_type(field) == ast.Type(-1) {
|
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_stmt << node.sub_structs[int(t)]
|
||||||
arr_fkeys << fkey
|
arr_fkeys << fkey
|
||||||
|
arr_field_name << field.name
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
t, sym := g.mysql_buffer_typ_from_field(field)
|
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('int $id_name = string_int(tos_clone(${rs}_row[0]));')
|
||||||
g.writeln('mysql_free_result($rs);')
|
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_stmt := []ast.SqlStmtLine{}
|
||||||
mut arr_fkeys := []string{}
|
mut arr_fkeys := []string{}
|
||||||
|
mut arr_field_name := []string{}
|
||||||
if node.kind == .insert {
|
if node.kind == .insert {
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
if g.get_sql_field_type(field) == ast.Type(-1) {
|
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_stmt << node.sub_structs[int(t)]
|
||||||
arr_fkeys << fkey
|
arr_fkeys << fkey
|
||||||
|
arr_field_name << field.name
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.sql_buf = strings.new_builder(100)
|
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))); }')
|
g.writeln('if (${res}.state != 0) { IError err = ${res}.err; eprintln(_STR("\\000%.*s", 2, IError_str(err))); }')
|
||||||
id_name := g.new_tmp_var()
|
id_name := g.new_tmp_var()
|
||||||
g.writeln('int $id_name = string_int((*(string*)array_get((*(pg__Row*)${res}.data).vals, 0)));')
|
g.writeln('int $id_name = string_int((*(string*)array_get((*(pg__Row*)${res}.data).vals, 0)));')
|
||||||
|
g.sql_arr_stmt(arr_stmt, arr_fkeys, arr_field_name, id_name, db_expr)
|
||||||
g.sql_arr_stmt(arr_stmt, arr_fkeys, 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 {
|
for i, s in arr_stmt {
|
||||||
cnt := g.new_tmp_var()
|
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
|
name := g.table.get_type_symbol(s.table_expr.typ).cname
|
||||||
tmp_var := g.new_tmp_var()
|
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{
|
stmt := ast.SqlStmtLine{
|
||||||
pos: s.pos
|
pos: s.pos
|
||||||
kind: s.kind
|
kind: s.kind
|
||||||
table_expr: s.table_expr
|
table_expr: s.table_expr
|
||||||
object_var_name: tmp_var
|
object_var_name: tmp_var
|
||||||
fields: s.fields
|
fields: s.fields
|
||||||
sub_structs: s.sub_structs
|
sub_structs: sub_structs
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_fkey := g.sql_fkey
|
tmp_fkey := g.sql_fkey
|
||||||
tmp_parent_id := g.sql_parent_id
|
tmp_parent_id := g.sql_parent_id
|
||||||
g.sql_fkey = arr_fkeys[i]
|
g.sql_fkey = arr_fkeys[i]
|
||||||
|
|
|
@ -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