mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
orm: insert expressions returning id
This commit is contained in:
parent
b2df3264a7
commit
96aa23ff35
6 changed files with 86 additions and 8 deletions
|
@ -1960,6 +1960,11 @@ pub enum SqlStmtKind {
|
||||||
drop
|
drop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SqlExprKind {
|
||||||
|
insert
|
||||||
|
select_
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SqlStmt {
|
pub struct SqlStmt {
|
||||||
pub:
|
pub:
|
||||||
pos token.Pos
|
pos token.Pos
|
||||||
|
@ -1989,7 +1994,10 @@ pub mut:
|
||||||
|
|
||||||
pub struct SqlExpr {
|
pub struct SqlExpr {
|
||||||
pub:
|
pub:
|
||||||
is_count bool
|
is_count bool
|
||||||
|
is_insert bool // for insert expressions
|
||||||
|
inserted_var string
|
||||||
|
|
||||||
has_where bool
|
has_where bool
|
||||||
has_order bool
|
has_order bool
|
||||||
has_limit bool
|
has_limit bool
|
||||||
|
|
|
@ -190,9 +190,16 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
|
||||||
'offset')
|
'offset')
|
||||||
}
|
}
|
||||||
c.expr(mut node.db_expr)
|
c.expr(mut node.db_expr)
|
||||||
|
if node.is_insert {
|
||||||
|
node.typ = ast.int_type
|
||||||
|
}
|
||||||
|
|
||||||
c.check_orm_or_expr(mut node)
|
c.check_orm_or_expr(mut node)
|
||||||
|
|
||||||
|
if node.is_insert {
|
||||||
|
return ast.int_type
|
||||||
|
}
|
||||||
|
|
||||||
return node.typ.clear_flag(.result)
|
return node.typ.clear_flag(.result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2985,7 +2985,11 @@ pub fn (mut f Fmt) sql_expr(node ast.SqlExpr) {
|
||||||
f.write('sql ')
|
f.write('sql ')
|
||||||
f.expr(node.db_expr)
|
f.expr(node.db_expr)
|
||||||
f.writeln(' {')
|
f.writeln(' {')
|
||||||
f.write('\tselect ')
|
if node.is_insert {
|
||||||
|
f.write('\tinsert ')
|
||||||
|
} else {
|
||||||
|
f.write('\tselect ')
|
||||||
|
}
|
||||||
sym := f.table.sym(node.table_expr.typ)
|
sym := f.table.sym(node.table_expr.typ)
|
||||||
mut table_name := sym.name
|
mut table_name := sym.name
|
||||||
if !table_name.starts_with('C.') && !table_name.starts_with('JS.') {
|
if !table_name.starts_with('C.') && !table_name.starts_with('JS.') {
|
||||||
|
@ -3001,7 +3005,11 @@ pub fn (mut f Fmt) sql_expr(node ast.SqlExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.write('from ${table_name}')
|
if node.is_insert {
|
||||||
|
f.write('${node.inserted_var} into ${table_name}')
|
||||||
|
} else {
|
||||||
|
f.write('from ${table_name}')
|
||||||
|
}
|
||||||
if node.has_where {
|
if node.has_where {
|
||||||
f.write(' where ')
|
f.write(' where ')
|
||||||
f.expr(node.where_expr)
|
f.expr(node.where_expr)
|
||||||
|
|
|
@ -3527,7 +3527,11 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
||||||
g.size_of(node)
|
g.size_of(node)
|
||||||
}
|
}
|
||||||
ast.SqlExpr {
|
ast.SqlExpr {
|
||||||
g.sql_select_expr(node)
|
if node.is_insert {
|
||||||
|
g.sql_insert_expr(node)
|
||||||
|
} else {
|
||||||
|
g.sql_select_expr(node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
g.string_literal(node)
|
g.string_literal(node)
|
||||||
|
|
|
@ -42,6 +42,30 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) {
|
||||||
g.write('${left} *(${unwrapped_c_typ}*)${result_var}.data')
|
g.write('${left} *(${unwrapped_c_typ}*)${result_var}.data')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sql_insert_expr(node ast.SqlExpr) {
|
||||||
|
left := g.go_before_last_stmt()
|
||||||
|
g.writeln('')
|
||||||
|
connection_var_name := g.new_tmp_var()
|
||||||
|
g.write_orm_connection_init(connection_var_name, &node.db_expr)
|
||||||
|
table_name := g.get_table_name_by_struct_type(node.table_expr.typ)
|
||||||
|
result_var_name := g.new_tmp_var()
|
||||||
|
g.sql_table_name = g.table.sym(node.table_expr.typ).name
|
||||||
|
|
||||||
|
// orm_insert needs an SqlStmtLine, build it from SqlExpr (most nodes are the same)
|
||||||
|
hack_stmt_line := ast.SqlStmtLine{
|
||||||
|
object_var: node.inserted_var
|
||||||
|
fields: node.fields
|
||||||
|
// sub_structs: node.sub_structs
|
||||||
|
}
|
||||||
|
g.write_orm_insert(hack_stmt_line, table_name, connection_var_name, result_var_name,
|
||||||
|
node.or_expr)
|
||||||
|
|
||||||
|
g.write(left)
|
||||||
|
g.write('db__pg__DB_last_id(')
|
||||||
|
g.expr(node.db_expr)
|
||||||
|
g.write(');')
|
||||||
|
}
|
||||||
|
|
||||||
// sql_stmt writes C code that calls ORM functions for
|
// sql_stmt writes C code that calls ORM functions for
|
||||||
// performing various database operations such as creating and dropping tables,
|
// performing various database operations such as creating and dropping tables,
|
||||||
// as well as inserting and updating objects.
|
// as well as inserting and updating objects.
|
||||||
|
@ -272,6 +296,7 @@ fn (mut g Gen) write_orm_delete(node &ast.SqlStmtLine, table_name string, connec
|
||||||
// inserting a struct into a table, saving inserted `id` into a passed variable.
|
// inserting a struct into a table, saving inserted `id` into a passed variable.
|
||||||
fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_var_name string, table_name string, last_ids_arr string, res string, pid string, fkey string, or_expr ast.OrExpr) {
|
fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_var_name string, table_name string, last_ids_arr string, res string, pid string, fkey string, or_expr ast.OrExpr) {
|
||||||
mut subs := []ast.SqlStmtLine{}
|
mut subs := []ast.SqlStmtLine{}
|
||||||
|
|
||||||
mut subs_unwrapped_c_typ := []string{}
|
mut subs_unwrapped_c_typ := []string{}
|
||||||
mut arrs := []ast.SqlStmtLine{}
|
mut arrs := []ast.SqlStmtLine{}
|
||||||
mut fkeys := []string{}
|
mut fkeys := []string{}
|
||||||
|
@ -285,6 +310,7 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
|
||||||
unwrapped_c_typ := g.typ(field.typ.clear_flag(.option))
|
unwrapped_c_typ := g.typ(field.typ.clear_flag(.option))
|
||||||
subs_unwrapped_c_typ << if field.typ.has_flag(.option) { unwrapped_c_typ } else { '' }
|
subs_unwrapped_c_typ << if field.typ.has_flag(.option) { unwrapped_c_typ } else { '' }
|
||||||
} else if sym.kind == .array {
|
} else if sym.kind == .array {
|
||||||
|
// Handle foreign keys
|
||||||
if attr := field.attrs.find_first('fkey') {
|
if attr := field.attrs.find_first('fkey') {
|
||||||
fkeys << attr.arg
|
fkeys << attr.arg
|
||||||
} else {
|
} else {
|
||||||
|
@ -475,7 +501,7 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
|
||||||
unsafe { fff.free() }
|
unsafe { fff.free() }
|
||||||
g.write_orm_insert_with_last_ids(arr, connection_var_name, g.get_table_name_by_struct_type(arr.table_expr.typ),
|
g.write_orm_insert_with_last_ids(arr, connection_var_name, g.get_table_name_by_struct_type(arr.table_expr.typ),
|
||||||
last_ids, res_, id_name, fkeys[i], or_expr)
|
last_ids, res_, id_name, fkeys[i], or_expr)
|
||||||
// Validates sub insertion success otherwise, handled and propagated error.
|
// Validates sub insertion success otherwise, handled and propagated error.
|
||||||
g.or_block(res_, or_expr, ast.int_type.set_flag(.result))
|
g.or_block(res_, or_expr, ast.int_type.set_flag(.result))
|
||||||
g.indent--
|
g.indent--
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
|
|
@ -5,6 +5,8 @@ module parser
|
||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
|
|
||||||
|
// select from User
|
||||||
|
// insert user into User returning id
|
||||||
fn (mut p Parser) sql_expr() ast.Expr {
|
fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
tmp_inside_match := p.inside_match
|
tmp_inside_match := p.inside_match
|
||||||
p.inside_orm = true
|
p.inside_orm = true
|
||||||
|
@ -16,12 +18,32 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
p.unexpected(prepend_msg: 'invalid expression:', expecting: 'database')
|
p.unexpected(prepend_msg: 'invalid expression:', expecting: 'database')
|
||||||
}
|
}
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
p.check(.key_select)
|
// p.check(.key_select)
|
||||||
is_count := p.check_name() == 'count'
|
is_select := p.tok.kind == .key_select
|
||||||
|
is_insert := p.tok.lit == 'insert'
|
||||||
|
if !is_select && !is_insert {
|
||||||
|
p.error('expected "select" or "insert" in an ORM expression')
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
// kind := if is_select { ast.SqlExprKind.select_ } else { ast.SqlExprKind.insert }
|
||||||
|
mut inserted_var := ''
|
||||||
|
mut is_count := false
|
||||||
|
if is_insert {
|
||||||
|
inserted_var = p.check_name()
|
||||||
|
into := p.check_name()
|
||||||
|
if into != 'into' {
|
||||||
|
p.error('expecting `into`')
|
||||||
|
}
|
||||||
|
} else if is_select {
|
||||||
|
is_count = p.check_name() == 'count'
|
||||||
|
}
|
||||||
mut typ := ast.void_type
|
mut typ := ast.void_type
|
||||||
|
|
||||||
if is_count {
|
if is_count {
|
||||||
p.check_name() // from
|
n := p.check_name() // from
|
||||||
|
if n != 'from' {
|
||||||
|
p.error('expecting "from" in a "select count" ORM statement')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table_pos := p.tok.pos()
|
table_pos := p.tok.pos()
|
||||||
|
@ -90,6 +112,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
|
|
||||||
return ast.SqlExpr{
|
return ast.SqlExpr{
|
||||||
is_count: is_count
|
is_count: is_count
|
||||||
|
is_insert: is_insert
|
||||||
typ: typ.set_flag(.result)
|
typ: typ.set_flag(.result)
|
||||||
or_expr: or_expr
|
or_expr: or_expr
|
||||||
db_expr: db_expr
|
db_expr: db_expr
|
||||||
|
@ -104,6 +127,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
has_desc: has_desc
|
has_desc: has_desc
|
||||||
is_array: if is_count { false } else { true }
|
is_array: if is_count { false } else { true }
|
||||||
is_generated: false
|
is_generated: false
|
||||||
|
inserted_var: inserted_var
|
||||||
pos: pos.extend(p.prev_tok.pos())
|
pos: pos.extend(p.prev_tok.pos())
|
||||||
table_expr: ast.TypeNode{
|
table_expr: ast.TypeNode{
|
||||||
typ: table_type
|
typ: table_type
|
||||||
|
@ -114,6 +138,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
|
|
||||||
// insert user into User
|
// insert user into User
|
||||||
// update User set nr_oders=nr_orders+1 where id == user_id
|
// update User set nr_oders=nr_orders+1 where id == user_id
|
||||||
|
// delete
|
||||||
fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||||
mut pos := p.tok.pos()
|
mut pos := p.tok.pos()
|
||||||
p.inside_orm = true
|
p.inside_orm = true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue