diff options
Diffstat (limited to 'v_windows/v/vlib/v/gen/c/sql.v')
-rw-r--r-- | v_windows/v/vlib/v/gen/c/sql.v | 836 |
1 files changed, 836 insertions, 0 deletions
diff --git a/v_windows/v/vlib/v/gen/c/sql.v b/v_windows/v/vlib/v/gen/c/sql.v new file mode 100644 index 0000000..001f68c --- /dev/null +++ b/v_windows/v/vlib/v/gen/c/sql.v @@ -0,0 +1,836 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license that can be found in the LICENSE file. +module c + +import v.ast +import v.util + +enum SqlExprSide { + left + right +} + +enum SqlType { + sqlite3 + mysql + psql + mssql + unknown +} + +fn (mut g Gen) sql_stmt(node ast.SqlStmt) { + conn := g.new_tmp_var() + g.writeln('') + g.writeln('// orm') + g.write('orm__Connection $conn = (orm__Connection){._') + mut fn_prefix := '' + typ := g.parse_db_type(node.db_expr) + match typ { + .sqlite3 { + fn_prefix = 'sqlite__DB' + } + .mysql { + fn_prefix = 'mysql__Connection' + } + .psql { + fn_prefix = 'pg__DB' + } + else { + verror('This database type `$typ` is not implemented yet in orm') // TODO add better error + } + } + g.write('$fn_prefix = &') + g.expr(node.db_expr) + g.writeln(', ._typ = _orm__Connection_${fn_prefix}_index};') + for line in node.lines { + g.sql_stmt_line(line, conn) + } +} + +fn (mut g Gen) sql_stmt_line(nd ast.SqlStmtLine, expr string) { + mut node := nd + table_name := g.get_table_name(node.table_expr) + g.sql_table_name = g.table.get_type_symbol(node.table_expr.typ).name + res := g.new_tmp_var() + mut subs := false + mut dcheck := false + + if node.kind != .create { + mut fields := []ast.StructField{} + for f in node.fields { + mut skip := false + mut primary := false + for attr in f.attrs { + if attr.name == 'primary' { + primary = true + } + if attr.name == 'skip' { + skip = true + } + } + if !skip && !primary { + fields << f + } + } + node.fields = fields.clone() + unsafe { fields.free() } + } + + if node.kind == .create { + g.write('Option_void $res = orm__Connection_name_table[${expr}._typ]._method_') + g.sql_create_table(node, expr, table_name) + subs = true + } else if node.kind == .drop { + g.write('Option_void $res = orm__Connection_name_table[${expr}._typ]._method_') + g.writeln('drop(${expr}._object, _SLIT("$table_name"));') + subs = true + } else if node.kind == .insert { + arr := g.new_tmp_var() + g.writeln('Array_orm__Primitive $arr = new_array_from_c_array(0, 0, sizeof(orm__Primitive), NULL);') + g.sql_insert(node, expr, table_name, arr, res, '', false, '') + dcheck = true + } else if node.kind == .update { + g.write('Option_void $res = orm__Connection_name_table[${expr}._typ]._method_') + g.sql_update(node, expr, table_name) + } else if node.kind == .delete { + g.write('Option_void $res = orm__Connection_name_table[${expr}._typ]._method_') + g.sql_delete(node, expr, table_name) + } + if !dcheck { + g.writeln('if (${res}.state != 0 && ${res}.err._typ != _IError_None___index) { _v_panic(IError_str(${res}.err)); }') + } + if subs { + for _, sub in node.sub_structs { + g.sql_stmt_line(sub, expr) + } + } +} + +fn (mut g Gen) sql_create_table(node ast.SqlStmtLine, expr string, table_name string) { + g.write('create(${expr}._object, _SLIT("$table_name"), new_array_from_c_array($node.fields.len, $node.fields.len, sizeof(orm__TableField),') + if node.fields.len > 0 { + g.write(' _MOV((orm__TableField[$node.fields.len]){') + for field in node.fields { + sym := g.table.get_type_symbol(field.typ) + g.write('(orm__TableField){') + g.write('.name = _SLIT("$field.name"),') + mut typ := int(field.typ) + if sym.name == 'time.Time' { + typ = -2 + } + g.write('.typ = $typ,') + g.write('.is_arr = ${sym.kind == .array}, ') + g.write('.is_time = ${int(g.table.get_type_name(field.typ) == 'time__Time')},') + g.write('.default_val = (string){.str = (byteptr) "$field.default_val", .is_lit = 1},') + g.write('.attrs = new_array_from_c_array($field.attrs.len, $field.attrs.len, sizeof(StructAttribute),') + if field.attrs.len > 0 { + g.write(' _MOV((StructAttribute[$field.attrs.len]){') + for attr in field.attrs { + g.write('(StructAttribute){') + g.write('.name = _SLIT("$attr.name"),') + g.write('.has_arg = ${int(attr.has_arg)},') + g.write('.arg = _SLIT("$attr.arg"),') + g.write('.kind = ${int(attr.kind)},') + g.write('},') + } + g.write('})') + } else { + g.write('NULL') + } + g.write(')') + g.write('},') + } + g.write('})') + } else { + g.write('NULL') + } + g.writeln('));') +} + +fn (mut g Gen) sql_insert(node ast.SqlStmtLine, expr string, table_name string, last_ids_arr string, res string, pid string, is_array bool, fkey string) { + mut subs := []ast.SqlStmtLine{} + mut arrs := []ast.SqlStmtLine{} + mut fkeys := []string{} + mut field_names := []string{} + + for f in node.fields { + sym := g.table.get_type_symbol(f.typ) + if sym.kind == .struct_ && sym.name != 'time.Time' { + subs << node.sub_structs[int(f.typ)] + } else if sym.kind == .array { + mut f_key := '' + for attr in f.attrs { + if attr.name == 'fkey' && attr.has_arg && attr.kind == .string { + f_key = attr.arg + } + } + if f_key == '' { + verror('An field which holds an array, needs a fkey defined') + } + fkeys << f_key + info := sym.array_info() + if info.nr_dims == 1 { + arrs << node.sub_structs[int(info.elem_type)] + field_names << f.name + } else { + verror('V ORM only supports 1 dimensional arrays') + } + } + } + + fields := node.fields.filter(g.table.get_type_symbol(it.typ).kind != .array) + + for sub in subs { + g.sql_stmt_line(sub, expr) + g.writeln('array_push(&$last_ids_arr, _MOV((orm__Primitive[]){orm__Connection_name_table[${expr}._typ]._method_last_id(${expr}._object)}));') + } + + g.write('Option_void $res = orm__Connection_name_table[${expr}._typ]._method_') + g.write('insert(${expr}._object, _SLIT("$table_name"), (orm__QueryData){') + + g.write('.fields = new_array_from_c_array($fields.len, $fields.len, sizeof(string),') + if fields.len > 0 { + g.write('_MOV((string[$fields.len]){') + for f in fields { + g.write('_SLIT("${g.get_field_name(f)}"),') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),') + + g.write('.data = new_array_from_c_array($fields.len, $fields.len, sizeof(orm__Primitive),') + if fields.len > 0 { + g.write(' _MOV((orm__Primitive[$fields.len]){') + mut structs := 0 + for f in fields { + if f.name == fkey { + g.write('$pid, ') + continue + } + mut sym := g.table.get_type_symbol(f.typ) + mut typ := sym.cname + if sym.kind == .struct_ && typ != 'time__Time' { + g.write('(*(orm__Primitive*) array_get($last_ids_arr, $structs)),') + structs++ + continue + } + if typ == 'time__Time' { + typ = 'time' + } + g.write('orm__${typ}_to_primitive(${node.object_var_name}.$f.name),') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),') + g.write('.types = new_array_from_c_array(0, 0, sizeof(int), NULL),') + g.write('.kinds = new_array_from_c_array(0, 0, sizeof(orm__OperationKind), NULL),') + g.write('.is_and = new_array_from_c_array(0, 0, sizeof(bool), NULL),') + g.writeln('});') + + g.writeln('if (${res}.state != 0 && ${res}.err._typ != _IError_None___index) { _v_panic(IError_str(${res}.err)); }') + if arrs.len > 0 { + mut id_name := g.new_tmp_var() + g.writeln('orm__Primitive $id_name = orm__Connection_name_table[${expr}._typ]._method_last_id(${expr}._object);') + for i, mut arr in arrs { + idx := g.new_tmp_var() + g.writeln('for (int $idx = 0; $idx < ${arr.object_var_name}.${field_names[i]}.len; $idx++) {') + last_ids := g.new_tmp_var() + res_ := g.new_tmp_var() + tmp_var := g.new_tmp_var() + ctyp := g.typ(arr.table_expr.typ) + g.writeln('$ctyp $tmp_var = (*($ctyp*)array_get(${arr.object_var_name}.${field_names[i]}, $idx));') + arr.object_var_name = tmp_var + mut fff := []ast.StructField{} + for f in arr.fields { + mut skip := false + mut primary := false + for attr in f.attrs { + if attr.name == 'primary' { + primary = true + } + if attr.name == 'skip' { + skip = true + } + } + if !skip && !primary { + fff << f + } + } + arr.fields = fff.clone() + unsafe { fff.free() } + g.sql_insert(arr, expr, g.get_table_name(arr.table_expr), last_ids, res_, + id_name, true, fkeys[i]) + g.writeln('}') + } + } +} + +fn (mut g Gen) sql_update(node ast.SqlStmtLine, expr string, table_name string) { + g.write('update(${expr}._object, _SLIT("$table_name"), (orm__QueryData){') + g.write('.kinds = new_array_from_c_array(0, 0, sizeof(orm__OperationKind), NULL),') + g.write('.is_and = new_array_from_c_array(0, 0, sizeof(bool), NULL),') + g.write('.types = new_array_from_c_array(0, 0, sizeof(int), NULL),') + g.write('.fields = new_array_from_c_array($node.updated_columns.len, $node.updated_columns.len, sizeof(string),') + if node.updated_columns.len > 0 { + g.write(' _MOV((string[$node.updated_columns.len]){') + for field in node.updated_columns { + g.write('_SLIT("$field"),') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),') + g.write('.data = new_array_from_c_array($node.update_exprs.len, $node.update_exprs.len, sizeof(orm__Primitive),') + if node.update_exprs.len > 0 { + g.write(' _MOV((orm__Primitive[$node.update_exprs.len]){') + for e in node.update_exprs { + g.sql_expr_to_orm_primitive(e) + } + g.write('})') + } + g.write('),},') + g.sql_gen_where_data(node.where_expr) + g.writeln(');') +} + +fn (mut g Gen) sql_delete(node ast.SqlStmtLine, expr string, table_name string) { + g.write('_v_delete(${expr}._object, _SLIT("$table_name"),') + g.sql_gen_where_data(node.where_expr) + g.writeln(');') +} + +fn (mut g Gen) sql_expr_to_orm_primitive(expr ast.Expr) { + match expr { + ast.InfixExpr { + g.sql_write_orm_primitive(g.table.find_type_idx('orm.InfixType'), expr) + } + ast.StringLiteral { + g.sql_write_orm_primitive(ast.string_type, expr) + } + ast.IntegerLiteral { + g.sql_write_orm_primitive(ast.int_type, expr) + } + ast.BoolLiteral { + g.sql_write_orm_primitive(ast.bool_type, expr) + } + ast.Ident { + info := expr.info as ast.IdentVar + g.sql_write_orm_primitive(info.typ, expr) + } + ast.SelectorExpr { + g.sql_write_orm_primitive(expr.typ, expr) + } + else { + eprintln(expr) + verror('Unknown expr') + } + } +} + +fn (mut g Gen) sql_write_orm_primitive(t ast.Type, expr ast.Expr) { + mut sym := g.table.get_type_symbol(t) + mut typ := sym.cname + if typ == 'orm__Primitive' { + g.expr(expr) + g.write(',') + return + } + if typ == 'time__Time' { + typ = 'time' + } + if typ == 'orm__InfixType' { + typ = 'infix' + } + g.write('orm__${typ}_to_primitive(') + if expr is ast.InfixExpr { + g.write('(orm__InfixType){') + g.write('.name = _SLIT("$expr.left"),') + mut kind := match expr.op { + .plus { + 'orm__MathOperationKind__add' + } + .minus { + 'orm__MathOperationKind__sub' + } + .div { + 'orm__MathOperationKind__div' + } + .mul { + 'orm__MathOperationKind__mul' + } + else { + '' + } + } + g.write('.operator = $kind,') + g.write('.right = ') + g.sql_expr_to_orm_primitive(expr.right) + g.write('}') + } else { + g.expr(expr) + } + g.write('),') +} + +fn (mut g Gen) sql_where_data(expr ast.Expr, mut fields []string, mut kinds []string, mut data []ast.Expr, mut is_and []bool) { + match expr { + ast.InfixExpr { + g.sql_side = .left + g.sql_where_data(expr.left, mut fields, mut kinds, mut data, mut is_and) + mut kind := match expr.op { + .ne { + 'orm__OperationKind__neq' + } + .eq { + 'orm__OperationKind__eq' + } + .lt { + 'orm__OperationKind__lt' + } + .gt { + 'orm__OperationKind__gt' + } + .ge { + 'orm__OperationKind__ge' + } + .le { + 'orm__OperationKind__le' + } + else { + '' + } + } + if kind == '' { + if expr.op == .logical_or { + is_and << false + } else if expr.op == .and { + is_and << true + } else { + kind = 'orm__OperationKind__eq' + } + } + if expr.left !is ast.InfixExpr && expr.right !is ast.InfixExpr { + kinds << kind + } + g.sql_side = .right + g.sql_where_data(expr.right, mut fields, mut kinds, mut data, mut is_and) + } + ast.Ident { + if g.sql_side == .left { + fields << g.get_field_name(g.get_struct_field(expr.name)) + } else { + data << expr + } + } + ast.StringLiteral { + data << expr + } + ast.IntegerLiteral { + data << expr + } + ast.SelectorExpr { + data << expr + } + ast.BoolLiteral { + data << expr + } + else {} + } +} + +fn (mut g Gen) sql_gen_where_data(where_expr ast.Expr) { + g.write('(orm__QueryData){') + mut fields := []string{} + mut kinds := []string{} + mut data := []ast.Expr{} + mut is_and := []bool{} + g.sql_where_data(where_expr, mut fields, mut kinds, mut data, mut is_and) + g.write('.types = new_array_from_c_array(0, 0, sizeof(int), NULL),') + g.write('.fields = new_array_from_c_array($fields.len, $fields.len, sizeof(string),') + if fields.len > 0 { + g.write(' _MOV((string[$fields.len]){') + for field in fields { + g.write('_SLIT("$field"),') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),') + + g.write('.data = new_array_from_c_array($data.len, $data.len, sizeof(orm__Primitive),') + if data.len > 0 { + g.write(' _MOV((orm__Primitive[$data.len]){') + for e in data { + g.sql_expr_to_orm_primitive(e) + } + g.write('})') + } + g.write('),') + + g.write('.kinds = new_array_from_c_array($kinds.len, $kinds.len, sizeof(orm__OperationKind),') + if kinds.len > 0 { + g.write(' _MOV((orm__OperationKind[$kinds.len]){') + for k in kinds { + g.write('$k,') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),') + + g.write('.is_and = new_array_from_c_array($is_and.len, $is_and.len, sizeof(bool),') + if is_and.len > 0 { + g.write(' _MOV((bool[$is_and.len]){') + for b in is_and { + g.write('$b, ') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),}') +} + +fn (mut g Gen) sql_select_expr(node ast.SqlExpr) { + left := g.go_before_stmt(0) + conn := g.new_tmp_var() + g.writeln('') + g.writeln('// orm') + g.write('orm__Connection $conn = (orm__Connection){._') + mut fn_prefix := '' + typ := g.parse_db_type(node.db_expr) + match typ { + .sqlite3 { + fn_prefix = 'sqlite__DB' + } + .mysql { + fn_prefix = 'mysql__Connection' + } + .psql { + fn_prefix = 'pg__DB' + } + else { + verror('This database type `$typ` is not implemented yet in orm') // TODO add better error + } + } + + g.write('$fn_prefix = &') + g.expr(node.db_expr) + g.writeln(', ._typ = _orm__Connection_${fn_prefix}_index};') + g.sql_select(node, conn, left) +} + +fn (mut g Gen) sql_select(node ast.SqlExpr, expr string, left string) { + mut fields := []ast.StructField{} + mut prim := '' + for f in node.fields { + mut skip := false + for attr in f.attrs { + if attr.name == 'primary' { + prim = f.name + } + if attr.name == 'skip' { + skip = true + } + } + if !skip { + fields << f + } + } + + res := g.new_tmp_var() + table_name := g.get_table_name(node.table_expr) + g.sql_table_name = g.table.get_type_symbol(node.table_expr.typ).name + g.write('Option_Array_Array_orm__Primitive _o$res = orm__Connection_name_table[${expr}._typ]._method_select(${expr}._object, ') + g.write('(orm__SelectConfig){') + g.write('.table = _SLIT("$table_name"),') + g.write('.is_count = $node.is_count,') + g.write('.has_where = $node.has_where,') + g.write('.has_order = $node.has_order,') + if node.has_order { + g.write('.order = _SLIT("') + g.expr(node.order_expr) + g.write('"),') + if node.has_desc { + g.write('.order_type = orm__OrderType__desc,') + } else { + g.write('.order_type = orm__OrderType__asc,') + } + } + g.write('.has_limit = $node.has_limit,') + g.write('.has_offset = $node.has_offset,') + if prim != '' { + g.write('.primary = _SLIT("$prim"),') + } + select_fields := fields.filter(g.table.get_type_symbol(it.typ).kind != .array) + g.write('.fields = new_array_from_c_array($select_fields.len, $select_fields.len, sizeof(string),') + mut types := []int{} + if select_fields.len > 0 { + g.write(' _MOV((string[$select_fields.len]){') + for field in select_fields { + g.write('_SLIT("${g.get_field_name(field)}"),') + sym := g.table.get_type_symbol(field.typ) + if sym.name == 'time.Time' { + types << -2 + continue + } + if sym.kind == .struct_ { + types << int(ast.int_type) + continue + } + types << int(field.typ) + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),') + g.write('.types = new_array_from_c_array($types.len, $types.len, sizeof(int),') + if types.len > 0 { + g.write(' _MOV((int[$types.len]){') + for typ in types { + g.write('$typ,') + } + g.write('})') + } else { + g.write('NULL') + } + g.write('),},') + + mut exprs := []ast.Expr{} + if node.has_limit { + exprs << node.limit_expr + } + if node.has_offset { + exprs << node.offset_expr + } + g.write('(orm__QueryData) {') + g.write('.types = new_array_from_c_array(0, 0, sizeof(int), NULL),') + g.write('.kinds = new_array_from_c_array(0, 0, sizeof(orm__OperationKind), NULL),') + g.write('.is_and = new_array_from_c_array(0, 0, sizeof(bool), NULL),') + g.write('.data = new_array_from_c_array($exprs.len, $exprs.len, sizeof(orm__Primitive),') + if exprs.len > 0 { + g.write(' _MOV((orm__Primitive[$exprs.len]){') + for e in exprs { + g.sql_expr_to_orm_primitive(e) + } + g.write('})') + } else { + g.write('NULL') + } + g.write(')},') + + if node.has_where { + g.sql_gen_where_data(node.where_expr) + } else { + g.write('(orm__QueryData) {}') + } + g.writeln(');') + g.writeln('if (_o${res}.state != 0 && _o${res}.err._typ != _IError_None___index) { _v_panic(IError_str(_o${res}.err)); }') + g.writeln('Array_Array_orm__Primitive $res = (*(Array_Array_orm__Primitive*)_o${res}.data);') + + if node.is_count { + g.writeln('$left *((*(orm__Primitive*) array_get((*(Array_orm__Primitive*)array_get($res, 0)), 0))._int);') + } else { + tmp := g.new_tmp_var() + styp := g.typ(node.typ) + idx := g.new_tmp_var() + g.writeln('int $idx = 0;') + mut typ_str := '' + if node.is_array { + info := g.table.get_type_symbol(node.typ).array_info() + typ_str = g.typ(info.elem_type) + g.writeln('$styp ${tmp}_array = __new_array(0, ${res}.len, sizeof($typ_str));') + g.writeln('for (; $idx < ${res}.len; $idx++) {') + g.write('\t$typ_str $tmp = ($typ_str) {') + inf := g.table.get_type_symbol(info.elem_type).struct_info() + for i, field in inf.fields { + g.zero_struct_field(field) + if i != inf.fields.len - 1 { + g.write(', ') + } + } + g.writeln('};') + } else { + g.write('$styp $tmp = ($styp){') + info := g.table.get_type_symbol(node.typ).struct_info() + for i, field in info.fields { + g.zero_struct_field(field) + if i != info.fields.len - 1 { + g.write(', ') + } + } + g.writeln('};') + } + + g.writeln('if (${res}.len > 0) {') + for i, field in fields { + sel := '(*(orm__Primitive*) array_get((*(Array_orm__Primitive*) array_get($res, $idx)), $i))' + sym := g.table.get_type_symbol(field.typ) + if sym.kind == .struct_ && sym.name != 'time.Time' { + mut sub := node.sub_structs[int(field.typ)] + mut where_expr := sub.where_expr as ast.InfixExpr + mut ident := where_expr.right as ast.Ident + name := sel + s := g.table.find_type_idx('orm.Primitive') + if s != 0 { + if ident.info is ast.IdentVar { + mut info := ident.info as ast.IdentVar + info.typ = s + ident.info = info + } + } + ident.name = name + where_expr.right = ident + sub.where_expr = where_expr + + g.sql_select(sub, expr, '${tmp}.$field.name = ') + } else if sym.kind == .array { + mut fkey := '' + for attr in field.attrs { + if attr.name == 'fkey' && attr.has_arg && attr.kind == .string { + fkey = attr.arg + } + } + if fkey == '' { + verror('An field which holds an array, needs a fkey defined') + } + info := sym.array_info() + arr_typ := info.elem_type + sub := node.sub_structs[int(arr_typ)] + mut where_expr := sub.where_expr as ast.InfixExpr + mut l := where_expr.left as ast.Ident + mut r := where_expr.right as ast.Ident + l.name = fkey + r.name = tmp + where_expr.left = l + where_expr.right = ast.SelectorExpr{ + pos: r.pos + field_name: prim + is_mut: false + expr: r + expr_type: (r.info as ast.IdentVar).typ + typ: ast.int_type + scope: 0 + } + mut arr := ast.SqlExpr{ + typ: field.typ + is_count: sub.is_count + db_expr: sub.db_expr + has_where: sub.has_where + has_offset: sub.has_offset + offset_expr: sub.offset_expr + has_order: sub.has_order + order_expr: sub.order_expr + has_desc: sub.has_desc + is_array: true + pos: sub.pos + has_limit: sub.has_limit + limit_expr: sub.limit_expr + table_expr: sub.table_expr + fields: sub.fields + where_expr: where_expr + } + + g.sql_select(arr, expr, '${tmp}.$field.name = ') + } else { + mut typ := sym.cname + g.writeln('${tmp}.$field.name = *(${sel}._$typ);') + } + } + g.writeln('}') + + if node.is_array { + g.writeln('array_push(&${tmp}_array, _MOV(($typ_str[]){ $tmp }));') + g.writeln('}') + } + + g.write('$left $tmp') + if node.is_array { + g.write('_array') + } + g.writeln(';') + } +} + +fn (mut g Gen) parse_db_type(expr ast.Expr) SqlType { + match expr { + ast.Ident { + if expr.info is ast.IdentVar { + return g.parse_db_from_type_string(g.table.get_type_name(expr.info.typ)) + } + } + ast.SelectorExpr { + return g.parse_db_from_type_string(g.table.get_type_name(expr.typ)) + } + else { + return .unknown + } + } + return .unknown +} + +fn (mut g Gen) parse_db_from_type_string(name string) SqlType { + match name { + 'sqlite.DB' { + return .sqlite3 + } + 'mysql.Connection' { + return .mysql + } + 'pg.DB' { + return .psql + } + 'mssql.Connection' { + return .mssql + } + else { + return .unknown + } + } +} + +fn (mut g Gen) get_table_name(table_expr ast.TypeNode) string { + info := g.table.get_type_symbol(table_expr.typ).struct_info() + mut tablename := util.strip_mod_name(g.table.get_type_symbol(table_expr.typ).name) + for attr in info.attrs { + if attr.kind == .string && attr.name == 'table' && attr.arg != '' { + tablename = attr.arg + break + } + } + return tablename +} + +fn (mut g Gen) get_struct_field(name string) ast.StructField { + info := g.table.get_type_symbol(g.table.type_idxs[g.sql_table_name]).struct_info() + mut f := ast.StructField{} + for field in info.fields { + if field.name == name { + f = field + } + } + return f +} + +fn (mut g Gen) get_field_name(field ast.StructField) string { + mut name := field.name + for attr in field.attrs { + if attr.kind == .string && attr.name == 'sql' && attr.arg != '' { + name = attr.arg + break + } + } + sym := g.table.get_type_symbol(field.typ) + if sym.kind == .struct_ && sym.name != 'time.Time' { + name = '${name}_id' + } + return name +} |