From cf7ac7be7f3831165632e87bd1885ca42c7f51b1 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 24 Jun 2020 12:53:36 +0200 Subject: [PATCH] cgen: zero_struct_field(); orm: zero un-inited fields --- vlib/orm/orm_test.v | 1 + vlib/v/gen/cgen.v | 39 ++++++++++++++++++++++++++------------- vlib/v/gen/sql.v | 26 +++++++++++++++++++++----- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/vlib/orm/orm_test.v b/vlib/orm/orm_test.v index 5fc481c58c..8bf3587a2f 100644 --- a/vlib/orm/orm_test.v +++ b/vlib/orm/orm_test.v @@ -16,6 +16,7 @@ struct User { age int name string is_customer bool + skipped_string string [skip] } fn test_orm_sqlite() { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 2e2ff78a13..56f96ccc3a 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2531,12 +2531,15 @@ fn (mut g Gen) go_back_out(n int) { g.out.go_back(n) } -fn (mut g Gen) struct_init(struct_init ast.StructInit) { - skip_init := ['strconv__ftoa__Uf32', 'strconv__ftoa__Uf64', 'strconv__Float64u', 'struct stat', +const ( + skip_struct_init = ['strconv__ftoa__Uf32', 'strconv__ftoa__Uf64', 'strconv__Float64u', 'struct stat', 'struct addrinfo' ] +) + +fn (mut g Gen) struct_init(struct_init ast.StructInit) { styp := g.typ(struct_init.typ) - if styp in skip_init { + if styp in skip_struct_init { g.go_back_out(3) return } @@ -2587,13 +2590,15 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { } } // The rest of the fields are zeroed. - mut nr_info_fields := 0 + // `inited_fields` is a list of fields that have been init'ed, they are skipped + //mut nr_fields := 0 if sym.kind == .struct_ { info := sym.info as table.Struct if info.is_union && struct_init.fields.len > 1 { verror('union must not have more than 1 initializer') } - nr_info_fields = info.fields.len + //g.zero_struct_fields(info, inited_fields) + //nr_fields = info.fields.len for field in info.fields { if field.name in inited_fields { sfield := struct_init.fields[inited_fields[field.name]] @@ -2625,16 +2630,10 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { // TODO handle/require optionals in inits continue } - field_name := c_name(field.name) - g.write('\t.$field_name = ') - if field.has_default_expr { - g.expr(ast.fe2ex(field.default_expr)) - } else { - g.write(g.type_default(field.typ)) - } - g.writeln(',') + g.zero_struct_field(field) initialized = true } + } // if struct_init.fields.len == 0 && info.fields.len == 0 { if !initialized { @@ -2646,6 +2645,20 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { } } +fn (mut g Gen) zero_struct_field(field table.Field) { + field_name := c_name(field.name) + g.write('\t.$field_name = ') + if field.has_default_expr { + g.expr(ast.fe2ex(field.default_expr)) + } else { + g.write(g.type_default(field.typ)) + } + g.writeln(',') +} + +//fn (mut g Gen) zero_struct_fields(info table.Struct, inited_fields map[string]int) { +//} + // { user | name: 'new name' } fn (mut g Gen) assoc(node ast.Assoc) { g.writeln('// assoc') diff --git a/vlib/v/gen/sql.v b/vlib/v/gen/sql.v index d7525d2865..cccf79b335 100644 --- a/vlib/v/gen/sql.v +++ b/vlib/v/gen/sql.v @@ -124,15 +124,31 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { if node.is_array { // array_User array_tmp; // for { User tmp; ... array_tmp << tmp; } - sym := g.table.get_type_symbol(node.typ) - info := sym.info as table.Array - elem_type_str = g.typ(info.elem_type) + array_sym := g.table.get_type_symbol(node.typ) + array_info := array_sym.info as table.Array + elem_type_str = g.typ(array_info.elem_type) g.writeln('$styp ${tmp}_array = __new_array(0, 10, sizeof($elem_type_str));') g.writeln('while (1) {') - g.writeln('\t$elem_type_str $tmp;') + g.writeln('\t$elem_type_str $tmp = ($elem_type_str) {') + // + sym := g.table.get_type_symbol(array_info.elem_type) + info := sym.info as table.Struct + for field in info.fields { + g.zero_struct_field(field) + } + g.writeln('};') } else { // `User tmp;` - g.writeln('$styp $tmp;') + g.writeln('$styp $tmp = ($styp){') + // Zero fields, (only the [skip] ones?) + // If we don't, string values are going to be nil etc for fields that are not returned + // by the db engine. + sym := g.table.get_type_symbol(node.typ) + info := sym.info as table.Struct + for field in info.fields { + g.zero_struct_field(field) + } + g.writeln('};') } // g.writeln('int _step_res$tmp = sqlite3_step($g.sql_stmt_name);')