@@ -928,25 +928,46 @@ fn (mut g Gen) write_orm_insert(node &ast.SqlStmtLine, table_name string, connec
928928 result_var_name, '' , '' , or_expr)
929929}
930930
931+ // orm_object_var_c_name escapes a top-level ORM object variable (the `x` in
932+ // `insert x into T` / `upsert x into T`, or the array in a bulk `insert xs into T`)
933+ // so a variable named after a C/C++ reserved word matches its escaped C
934+ // declaration. Sub-struct and array object vars are already-built C expressions
935+ // (they contain `.`, `*`, `(`, ...), i.e. not bare identifiers, so they are
936+ // returned unchanged.
937+ fn orm_object_var_c_name (object_var string ) string {
938+ if object_var == '' {
939+ return object_var
940+ }
941+ for ch in object_var {
942+ if ! util.is_name_char (ch) {
943+ return object_var
944+ }
945+ }
946+ return c_name (object_var)
947+ }
948+
931949fn (mut g Gen) write_orm_bulk_insert (node & ast.SqlStmtLine, table_name string , connection_var_name string , result_var_name string , or_expr & ast.OrExpr) {
932950 fields := g.orm_non_array_fields (node.fields)
933951 auto_fields := get_auto_field_idxs (fields)
934952 row_type := g.styp (node.table_expr.typ)
935953 row_var := g.new_tmp_var ()
936954 idx_var := g.new_tmp_var ()
937955 data_var := g.new_tmp_var ()
956+ // Escape the top-level array variable so a variable named after a C/C++ reserved
957+ // word matches its escaped C declaration (see write_orm_insert_with_last_ids).
958+ object_var := orm_object_var_c_name (node.object_var)
938959 g.writeln ('${result_name }_void ${result_var_name };' )
939- g.writeln ('if (${node . object_var }.len == 0) {' )
960+ g.writeln ('if (${object_var }.len == 0) {' )
940961 g.indent++
941962 g.writeln ('${result_var_name } = (${result_name }_void){0};' )
942963 g.indent--
943964 g.writeln ('} else {' )
944965 g.indent++
945966 if auto_fields.len > 0 {
946967 g.writeln ('${result_var_name } = (${result_name }_void){0};' )
947- g.writeln ('for (${ast .int_type_name } ${idx_var } = 0; ${idx_var } < ${node . object_var }.len; ${idx_var }++) {' )
968+ g.writeln ('for (${ast .int_type_name } ${idx_var } = 0; ${idx_var } < ${object_var }.len; ${idx_var }++) {' )
948969 g.indent++
949- g.writeln ('${row_type } ${row_var } = (*(${row_type }*)builtin__array_get(${node . object_var }, ${idx_var }));' )
970+ g.writeln ('${row_type } ${row_var } = (*(${row_type }*)builtin__array_get(${object_var }, ${idx_var }));' )
950971 row_result_var := g.new_tmp_var ()
951972 mut row_node := * node
952973 row_node.object_var = row_var
@@ -962,9 +983,9 @@ fn (mut g Gen) write_orm_bulk_insert(node &ast.SqlStmtLine, table_name string, c
962983 return
963984 }
964985 g.writeln ('Array_orm__Primitive ${data_var } = builtin____new_array_with_default_noscan(0, 0, sizeof(orm__Primitive), 0);' )
965- g.writeln ('for (${ast .int_type_name } ${idx_var } = 0; ${idx_var } < ${node . object_var }.len; ${idx_var }++) {' )
986+ g.writeln ('for (${ast .int_type_name } ${idx_var } = 0; ${idx_var } < ${object_var }.len; ${idx_var }++) {' )
966987 g.indent++
967- g.writeln ('${row_type } ${row_var } = (*(${row_type }*)builtin__array_get(${node . object_var }, ${idx_var }));' )
988+ g.writeln ('${row_type } ${row_var } = (*(${row_type }*)builtin__array_get(${object_var }, ${idx_var }));' )
968989 for field in fields {
969990 g.write ('builtin__array_push(&${data_var }, _MOV((orm__Primitive[1]){' )
970991 g.write_orm_field_access_to_primitive (field, row_var, node.table_expr.typ,
@@ -1013,7 +1034,7 @@ fn (mut g Gen) write_orm_bulk_insert(node &ast.SqlStmtLine, table_name string, c
10131034 g.writeln ('.kinds = builtin____new_array_with_default_noscan(0, 0, sizeof(orm__OperationKind), 0),' )
10141035 g.writeln ('.is_and = builtin____new_array_with_default_noscan(0, 0, sizeof(bool), 0),' )
10151036 g.writeln ('.parentheses = builtin____new_array_with_default_noscan(0, 0, sizeof(Array_${ast .int_type_name }), 0),' )
1016- g.writeln ('.batch_rows = ${node . object_var }.len,' )
1037+ g.writeln ('.batch_rows = ${object_var }.len,' )
10171038 g.indent--
10181039 g.writeln ('}' )
10191040 g.indent--
@@ -1029,6 +1050,9 @@ fn (mut g Gen) write_orm_upsert(node &ast.SqlStmtLine, table_name string, connec
10291050 auto_fields := get_auto_field_idxs (fields)
10301051 mut inserting_object_type := ast.void_type
10311052 mut member_access_type := '.'
1053+ // See write_orm_insert_with_last_ids: escape the top-level object var so a
1054+ // variable named after a C/C++ reserved word matches its escaped C declaration.
1055+ object_var := orm_object_var_c_name (node.object_var)
10321056 if node.scope != unsafe { nil } {
10331057 if inserting_object := node.scope.find (node.object_var) {
10341058 if inserting_object.typ.is_ptr () {
@@ -1065,12 +1089,12 @@ fn (mut g Gen) write_orm_upsert(node &ast.SqlStmtLine, table_name string, connec
10651089 mut typ := g.orm_primitive_field_name (field.typ)
10661090 mut ctyp := sym.cname
10671091 typ = vint2int (typ)
1068- var := '${node . object_var }${member_access_type }${orm_field_access_name (field .name )}'
1092+ var := '${object_var }${member_access_type }${orm_field_access_name (field .name )}'
10691093 if final_field_typ.has_flag (.option) {
10701094 g.writeln ('${var }.state == 2 ? _const_orm__null_primitive : orm__${typ }_to_primitive(*(${ctyp }*)(${var }.data)),' )
10711095 } else if inserting_object_sym.kind == .sum_type {
10721096 table_sym := g.table.sym (node.table_expr.typ)
1073- sum_type_var := '(*${node . object_var }._${table_sym .cname })${member_access_type }${orm_field_access_name (field .name )}'
1097+ sum_type_var := '(*${object_var }._${table_sym .cname })${member_access_type }${orm_field_access_name (field .name )}'
10741098 g.writeln ('orm__${typ }_to_primitive(${sum_type_var }),' )
10751099 } else {
10761100 g.writeln ('orm__${typ }_to_primitive(${var }),' )
@@ -1501,6 +1525,12 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
15011525
15021526 mut inserting_object_type := ast.void_type
15031527 mut member_access_type := '.'
1528+ // The top-level insert variable (e.g. `insert explicit into T`) is a plain V
1529+ // identifier, so its C name must be escaped the same way its declaration is,
1530+ // otherwise a variable named after a C/C++ reserved word (`new`, `explicit`, ...)
1531+ // won't match. Sub-struct/array object vars are already-built C expressions, so
1532+ // orm_object_var_c_name leaves them untouched.
1533+ object_var := orm_object_var_c_name (node.object_var)
15041534 if node.scope != unsafe { nil } {
15051535 if inserting_object := node.scope.find (node.object_var) {
15061536 if inserting_object.typ.is_ptr () {
@@ -1514,13 +1544,16 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
15141544
15151545 inserting_object_sym := g.table.sym (inserting_object_type)
15161546 for i, mut sub in subs {
1547+ // The relation field name is stored verbatim, so escape it like any other
1548+ // struct member (a field named after a reserved word is declared __v_<name>).
1549+ sub_field := orm_field_access_name (sub.object_var)
15171550 if subs_unwrapped_c_typ[i].len > 0 {
1518- var := '${node . object_var }${member_access_type }${sub . object_var }'
1551+ var := '${object_var }${member_access_type }${sub_field }'
15191552 g.writeln ('if(${var }.state == 0) {' )
15201553 g.indent++
1521- sub.object_var = '(*(${subs_unwrapped_c_typ [i ]}*)${node . object_var }${member_access_type }${sub . object_var }.data)'
1554+ sub.object_var = '(*(${subs_unwrapped_c_typ [i ]}*)${object_var }${member_access_type }${sub_field }.data)'
15221555 } else {
1523- sub.object_var = '${node . object_var }${member_access_type }${sub . object_var }'
1556+ sub.object_var = '${object_var }${member_access_type }${sub_field }'
15241557 }
15251558 g.sql_stmt_line (sub, connection_var_name, or_expr)
15261559 g.writeln ('builtin__array_push(&${last_ids_arr }, _MOV((orm__Primitive[1]){' )
@@ -1581,12 +1614,12 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
15811614 }
15821615 // fields processed hereafter can be NULL...
15831616 typ = vint2int (typ)
1584- var := '${node . object_var }${member_access_type }${orm_field_access_name (field .name )}'
1617+ var := '${object_var }${member_access_type }${orm_field_access_name (field .name )}'
15851618 if final_field_typ.has_flag (.option) {
15861619 g.writeln ('${var }.state == 2? _const_orm__null_primitive : orm__${typ }_to_primitive(*(${ctyp }*)(${var }.data)),' )
15871620 } else if inserting_object_sym.kind == .sum_type {
15881621 table_sym := g.table.sym (node.table_expr.typ)
1589- sum_type_var := '(*${node . object_var }._${table_sym .cname })${member_access_type }${orm_field_access_name (field .name )}'
1622+ sum_type_var := '(*${object_var }._${table_sym .cname })${member_access_type }${orm_field_access_name (field .name )}'
15901623 g.writeln ('orm__${typ }_to_primitive(${sum_type_var }),' )
15911624 } else {
15921625 g.writeln ('orm__${typ }_to_primitive(${var }),' )
@@ -1630,26 +1663,30 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
16301663 // else use the primary key value
16311664 mut typ := g.orm_primitive_field_name (primary_field.typ)
16321665 typ = vint2int (typ)
1633- g.writeln ('orm__Primitive ${id_name } = orm__${typ }_to_primitive(${node . object_var }${member_access_type }${orm_field_access_name (primary_field .name )});' )
1666+ g.writeln ('orm__Primitive ${id_name } = orm__${typ }_to_primitive(${object_var }${member_access_type }${orm_field_access_name (primary_field .name )});' )
16341667 }
16351668 for i, mut arr in arrs {
16361669 idx := g.new_tmp_var ()
16371670 ctyp := g.styp (arr.table_expr.typ)
16381671 is_option := opt_fields.contains (i)
1672+ // The array relation field name is stored verbatim, so escape it like any
1673+ // other struct member (a field named after a reserved word is declared
1674+ // __v_<name>).
1675+ arr_field := orm_field_access_name (arr.object_var)
16391676 if is_option {
1640- g.writeln ('for (${ast .int_type_name } ${idx } = 0; ${node . object_var }${member_access_type }${arr . object_var }.state != 2 && ${idx } < (*(Array_${ctyp }*)${node . object_var }${member_access_type }${arr . object_var }.data).len; ${idx }++) {' )
1677+ g.writeln ('for (${ast .int_type_name } ${idx } = 0; ${object_var }${member_access_type }${arr_field }.state != 2 && ${idx } < (*(Array_${ctyp }*)${object_var }${member_access_type }${arr_field }.data).len; ${idx }++) {' )
16411678 } else {
1642- g.writeln ('for (${ast .int_type_name } ${idx } = 0; ${idx } < ${node . object_var }${member_access_type }${arr . object_var }.len; ${idx }++) {' )
1679+ g.writeln ('for (${ast .int_type_name } ${idx } = 0; ${idx } < ${object_var }${member_access_type }${arr_field }.len; ${idx }++) {' )
16431680 }
16441681 g.indent++
16451682 last_ids := g.new_tmp_var ()
16461683 res_ := g.new_tmp_var ()
16471684 tmp_var := g.new_tmp_var ()
16481685 g.writeln ('Array_orm__Primitive ${last_ids } = builtin____new_array_with_default_noscan(0, 0, sizeof(orm__Primitive), 0);' )
16491686 if is_option {
1650- g.writeln ('${ctyp } ${tmp_var } = (*(${ctyp }*)builtin__array_get(*(Array_${ctyp }*)${node . object_var }${member_access_type }${arr . object_var }.data, ${idx }));' )
1687+ g.writeln ('${ctyp } ${tmp_var } = (*(${ctyp }*)builtin__array_get(*(Array_${ctyp }*)${object_var }${member_access_type }${arr_field }.data, ${idx }));' )
16511688 } else {
1652- g.writeln ('${ctyp } ${tmp_var } = (*(${ctyp }*)builtin__array_get(${node . object_var }${member_access_type }${arr . object_var }, ${idx }));' )
1689+ g.writeln ('${ctyp } ${tmp_var } = (*(${ctyp }*)builtin__array_get(${object_var }${member_access_type }${arr_field }, ${idx }));' )
16531690 }
16541691 arr.object_var = tmp_var
16551692 mut fff := []ast.StructField{}
@@ -1820,7 +1857,7 @@ fn (mut g Gen) write_orm_primitive(t ast.Type, expr ast.Expr) {
18201857 }
18211858 }
18221859
1823- g.writeln (' .operator = ${kind },' )
1860+ g.writeln (' .${ c_name (' operator ')} = ${kind },' )
18241861 g.write (' .right = ' )
18251862 g.write_orm_expr_to_primitive (expr.right)
18261863 g.indent--
0 commit comments