1
0
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:
Louis Schmieder 2021-05-04 11:35:18 +02:00 committed by GitHub
parent 92a22e9ec5
commit b8e070b2a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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

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