orm: add pg select expr (#9927)

pull/9930/head
Louis Schmieder 2021-04-29 12:38:36 +02:00 committed by GitHub
parent 8af6237e28
commit e9bbb7de3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 151 additions and 10 deletions

View File

@ -107,4 +107,14 @@ fn psql() {
sql db {
insert mod into Module
}
modul := sql db {
select from Module where id == 1
}
sql db {
drop table Module
}
eprintln(modul)
}

View File

@ -83,7 +83,7 @@ fn (mut g Gen) sql_drop_table(node ast.SqlStmtLine, expr ast.Expr) {
g.mysql_drop_table(node, typ, expr)
}
.psql {
g.psql_create_table(node, typ, expr)
g.psql_drop_table(node, typ, expr)
}
else {
verror('This database type `$typ` is not implemented yet in orm') // TODO add better error
@ -101,6 +101,9 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr, sub bool, line string) {
.mysql {
g.mysql_select_expr(node, sub, line, typ)
}
.psql {
g.psql_select_expr(node, sub, line, typ)
}
else {
verror('This database type `$typ` is not implemented yet in orm') // TODO add better error
}
@ -217,7 +220,7 @@ fn (mut g Gen) sqlite3_select_expr(node ast.SqlExpr, sub bool, line string, sql_
g.writeln(';')
stmt_name := g.new_tmp_var()
g.write('string $stmt_name = _SLIT("')
g.write(g.get_base_sql_select_query(node))
g.write(g.get_base_sql_select_query(node, sql_typ))
g.sql_expr_defaults(node, sql_typ)
g.writeln('");')
// g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, _SLIT("$sql_query')
@ -477,7 +480,7 @@ fn (mut g Gen) mysql_select_expr(node ast.SqlExpr, sub bool, line string, typ Sq
g.sql_idents = []string{}
g.sql_idents_types = []ast.Type{}
g.write('char* ${stmt_name}_raw = "')
g.write(g.get_base_sql_select_query(node))
g.write(g.get_base_sql_select_query(node, typ))
g.sql_expr_defaults(node, typ)
g.writeln('";')
g.writeln('string $stmt_name = tos_clone(${stmt_name}_raw);')
@ -612,6 +615,7 @@ fn (mut g Gen) mysql_select_expr(node ast.SqlExpr, sub bool, line string, typ Sq
}
if node.is_array {
g.writeln('\t array_push((array*)&${tmp}_array, _MOV(($elem_type_str[]) { $tmp }));')
g.writeln('\t $fields = mysql_fetch_row($res);')
g.writeln('}')
}
g.writeln('string_free(&$stmt_name);')
@ -793,6 +797,128 @@ fn (mut g Gen) psql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
g.writeln('pg__DB_exec($db_name, $g.sql_stmt_name);')
}
fn (mut g Gen) psql_select_expr(node ast.SqlExpr, sub bool, line string, typ SqlType) {
g.sql_i = 0
mut cur_line := line
if !sub {
cur_line = g.go_before_stmt(0)
}
g.sql_stmt_name = g.new_tmp_var()
db_name := g.new_tmp_var()
g.writeln('\n\t// psql select')
g.write('pg__DB $db_name = ')
g.expr(node.db_expr)
g.writeln(';')
g.write('string $g.sql_stmt_name = _SLIT("')
g.write(g.get_base_sql_select_query(node, typ))
g.sql_expr_defaults(node, typ)
g.writeln('");')
buf := g.sql_buf.str()
g.sql_buf = strings.new_builder(100)
g.writeln(buf)
res := g.new_tmp_var()
g.writeln('Option_Array_pg__Row $res = pg__DB_exec($db_name, $g.sql_stmt_name);')
g.writeln('if (${res}.state != 0) { IError err = ${res}.err; eprintln(_STR("Something went wrong\\000%.*s", 2, IError_str(err))); }')
rows := g.new_tmp_var()
g.writeln('Array_pg__Row $rows = *(Array_pg__Row*) ${res}.data;')
if node.is_count {
g.writeln('$cur_line string_int((*(string*)array_get(array_get($rows, 0).vals), 0)));')
} else {
tmp := g.new_tmp_var()
styp := g.typ(node.typ)
tmp_i := g.new_tmp_var()
mut elem_type_str := ''
g.writeln('int $tmp_i = 0;')
if node.is_array {
array_sym := g.table.get_type_symbol(node.typ)
array_info := array_sym.info as ast.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('for ($tmp_i = 0; $tmp_i < ${rows}.len; $tmp_i++) {')
g.writeln('\t$elem_type_str $tmp = ($elem_type_str) {')
//
sym := g.table.get_type_symbol(array_info.elem_type)
info := sym.info as ast.Struct
for i, field in info.fields {
g.zero_struct_field(field)
if i != info.fields.len - 1 {
g.write(', ')
}
}
g.writeln('};')
} else {
g.writeln('$styp $tmp = ($styp){')
sym := g.table.get_type_symbol(node.typ)
info := sym.info as ast.Struct
for i, field in info.fields {
g.zero_struct_field(field)
if i != info.fields.len - 1 {
g.write(', ')
}
}
g.writeln('};')
}
fields := g.new_tmp_var()
g.writeln('Array_string $fields = (*(pg__Row*) array_get($rows, $tmp_i)).vals;')
fld := g.new_tmp_var()
g.writeln('string $fld;')
for i, field in node.fields {
g.writeln('$fld = (*(string*)array_get($fields, $i));')
name := g.table.get_type_symbol(field.typ).cname
if g.table.get_type_symbol(field.typ).kind == .struct_ {
g.writeln('//parse struct start')
mut expr := node.sub_structs[int(field.typ)]
mut where_expr := expr.where_expr as ast.InfixExpr
mut ident := where_expr.right as ast.Ident
ident.name = '$fld'
where_expr.right = ident
expr.where_expr = where_expr
tmp_sql_i := g.sql_i
tmp_sql_stmt_name := g.sql_stmt_name
tmp_sql_buf := g.sql_buf
tmp_sql_table_name := g.sql_table_name
g.sql_select_expr(expr, true, '\t${tmp}.$field.name =')
g.writeln('//parse struct end')
g.sql_stmt_name = tmp_sql_stmt_name
g.sql_buf = tmp_sql_buf
g.sql_i = tmp_sql_i
g.sql_table_name = tmp_sql_table_name
} else if field.typ == ast.string_type {
g.writeln('${tmp}.$field.name = $fld;')
} else if field.typ == ast.byte_type {
g.writeln('${tmp}.$field.name = (byte) string_${name}($fld);')
} else if field.typ == ast.i8_type {
g.writeln('${tmp}.$field.name = (i8) string_${name}($fld);')
} else if field.typ == ast.bool_type {
g.writeln('${tmp}.$field.name = string_eq($fld, _SLIT("0")) ? false : true;')
} else {
g.writeln('${tmp}.$field.name = string_${name}($fld);')
}
}
if node.is_array {
g.writeln('\t array_push((array*)&${tmp}_array, _MOV(($elem_type_str[]) { $tmp }));')
g.writeln('}')
}
g.writeln('string_free(&$g.sql_stmt_name);')
if node.is_array {
g.writeln('$cur_line ${tmp}_array; ')
} else {
g.writeln('$cur_line $tmp; ')
}
}
}
fn (mut g Gen) psql_create_table(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
g.writeln('// psql table creator')
create_string := g.table_gen(node, typ, db_expr)
@ -806,9 +932,10 @@ fn (mut g Gen) psql_create_table(node ast.SqlStmtLine, typ SqlType, db_expr ast.
fn (mut g Gen) psql_drop_table(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
table_name := g.get_table_name(node.table_expr)
g.writeln('// psql table drop')
drop_string := 'DROP TABLE "$table_name";'
lit := '\\"'
drop_string := 'DROP TABLE $lit$table_name$lit;'
tmp := g.new_tmp_var()
g.write('Option_Array_pg__Row $tmp = pg__DB_exec(&')
g.write('Option_Array_pg__Row $tmp = pg__DB_exec(')
g.expr(db_expr)
g.writeln(', _SLIT("$drop_string"));')
g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; eprintln(_STR("Something went wrong\\000%.*s", 2, IError_str(err))); }')
@ -898,21 +1025,25 @@ fn (mut g Gen) sql_expr_defaults(node ast.SqlExpr, sql_typ SqlType) {
}
}
fn (mut g Gen) get_base_sql_select_query(node ast.SqlExpr) string {
fn (mut g Gen) get_base_sql_select_query(node ast.SqlExpr, typ SqlType) string {
mut lit := '`'
if typ == .psql {
lit = '\\"'
}
mut sql_query := 'SELECT '
table_name := g.get_table_name(node.table_expr)
if node.is_count {
// `select count(*) from User`
sql_query += 'COUNT(*) FROM `$table_name` '
sql_query += 'COUNT(*) FROM $lit$table_name$lit '
} else {
// `select id, name, country from User`
for i, field in node.fields {
sql_query += '`${g.get_field_name(field)}`'
sql_query += '$lit${g.get_field_name(field)}$lit'
if i < node.fields.len - 1 {
sql_query += ', '
}
}
sql_query += ' FROM `$table_name`'
sql_query += ' FROM $lit$table_name$lit'
}
if node.has_where {
sql_query += ' WHERE '
@ -1134,7 +1265,7 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr, typ SqlType) {
g.sql_bind(expr.name, '', g.sql_get_real_type(ityp), typ)
}
} else {
g.sql_bind('%$g.sql_i.str()', '', g.sql_get_real_type(ityp), typ)
g.sql_bind('$g.sql_i.str()', '', g.sql_get_real_type(ityp), typ)
g.sql_idents << expr.name
g.sql_idents_types << g.sql_get_real_type(ityp)
}