orm: move type logic to checker, so that sql queries can be used before type def
parent
a1bad50b2f
commit
786be1d1c3
|
@ -3,6 +3,7 @@
|
|||
|
||||
- coroutines
|
||||
- bring back lock{}
|
||||
- thread safe arrays/maps
|
||||
- C2V translator
|
||||
- doom.v
|
||||
- rune type, replace ustring with []rune
|
||||
|
|
|
@ -11,14 +11,6 @@ struct Module {
|
|||
//nr_downloads int
|
||||
}
|
||||
|
||||
struct User {
|
||||
id int
|
||||
age int
|
||||
name string
|
||||
is_customer bool
|
||||
skipped_string string [skip]
|
||||
}
|
||||
|
||||
fn test_orm_sqlite() {
|
||||
db := sqlite.connect(':memory:') or { panic(err) }
|
||||
db.exec("drop table if exists User")
|
||||
|
@ -131,6 +123,15 @@ fn test_orm_sqlite() {
|
|||
*/
|
||||
}
|
||||
|
||||
struct User {
|
||||
id int
|
||||
age int
|
||||
name string
|
||||
is_customer bool
|
||||
skipped_string string [skip]
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn test_orm_pg() {
|
||||
/*
|
||||
|
|
|
@ -822,6 +822,7 @@ pub:
|
|||
table_name string
|
||||
object_var_name string // `user`
|
||||
table_type table.Type
|
||||
pos token.Position
|
||||
}
|
||||
|
||||
pub struct SqlExpr {
|
||||
|
@ -829,11 +830,14 @@ pub:
|
|||
typ table.Type
|
||||
is_count bool
|
||||
db_expr Expr // `db` in `sql db {`
|
||||
table_name string
|
||||
where_expr Expr
|
||||
has_where bool
|
||||
fields []table.Field
|
||||
is_array bool
|
||||
table_type table.Type
|
||||
pos token.Position
|
||||
pub mut:
|
||||
table_name string
|
||||
fields []table.Field
|
||||
}
|
||||
|
||||
[inline]
|
||||
|
|
|
@ -1841,7 +1841,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||
c.scope_returns = true
|
||||
}
|
||||
ast.SqlStmt {
|
||||
c.sql_insert_expr(node)
|
||||
c.sql_stmt(node)
|
||||
}
|
||||
ast.StructDecl {
|
||||
c.struct_decl(it)
|
||||
|
@ -2680,7 +2680,34 @@ fn (c &Checker) fileis(s string) bool {
|
|||
return c.file.path.contains(s)
|
||||
}
|
||||
|
||||
fn (mut c Checker) sql_expr(node ast.SqlExpr) table.Type {
|
||||
fn (mut c Checker) sql_expr(mut node ast.SqlExpr) table.Type {
|
||||
sym := c.table.get_type_symbol(node.table_type)
|
||||
info := sym.info as table.Struct
|
||||
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type] &&
|
||||
'skip' !in it.attrs)
|
||||
if fields.len == 0 {
|
||||
c.error('V orm: select: empty fields in `$node.table_name`', node.pos)
|
||||
}
|
||||
if fields[0].name != 'id' {
|
||||
c.error('V orm: `id int` must be the first field in `$node.table_name`', node.pos)
|
||||
}
|
||||
node.fields = fields
|
||||
node.table_name = sym.name
|
||||
if node.has_where {
|
||||
// Register this type's fields as variables so they can be used in `where`
|
||||
// expressions
|
||||
scope := c.file.scope.innermost(node.pos.pos)
|
||||
for field in fields {
|
||||
// println('registering sql field var $field.name')
|
||||
scope.register(field.name, ast.Var{
|
||||
name: field.name
|
||||
typ: field.typ
|
||||
is_mut: true
|
||||
is_used: true
|
||||
is_changed: true
|
||||
})
|
||||
}
|
||||
}
|
||||
if node.has_where {
|
||||
c.expr(node.where_expr)
|
||||
}
|
||||
|
@ -2688,7 +2715,7 @@ fn (mut c Checker) sql_expr(node ast.SqlExpr) table.Type {
|
|||
return node.typ
|
||||
}
|
||||
|
||||
fn (mut c Checker) sql_insert_expr(node ast.SqlStmt) table.Type {
|
||||
fn (mut c Checker) sql_stmt(node ast.SqlStmt) table.Type {
|
||||
c.expr(node.db_expr)
|
||||
return table.void_type
|
||||
}
|
||||
|
|
|
@ -8,17 +8,10 @@ import v.table
|
|||
|
||||
fn (mut p Parser) sql_expr() ast.Expr {
|
||||
// `sql db {`
|
||||
pos := p.tok.position()
|
||||
p.check_name()
|
||||
db_expr := p.expr(0)
|
||||
p.check(.lcbr)
|
||||
// kind := ast.SqlExprKind.select_
|
||||
//
|
||||
/*
|
||||
if p.tok.kind == .name && p.tok.lit == 'insert' {
|
||||
return p.sql_insert_expr(db_var_name)
|
||||
// kind = .insert
|
||||
}
|
||||
*/
|
||||
p.check(.key_select)
|
||||
n := p.check_name()
|
||||
is_count := n == 'count'
|
||||
|
@ -28,8 +21,6 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||
typ = table.int_type
|
||||
}
|
||||
table_type := p.parse_type() // `User`
|
||||
sym := p.table.get_type_symbol(table_type)
|
||||
table_name := sym.name
|
||||
mut where_expr := ast.Expr{}
|
||||
has_where := p.tok.kind == .name && p.tok.lit == 'where'
|
||||
mut query_one := false // one object is returned, not an array
|
||||
|
@ -65,48 +56,24 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
|||
typ = table_type
|
||||
}
|
||||
p.check(.rcbr)
|
||||
// /////////
|
||||
// Register this type's fields as variables so they can be used in `where`
|
||||
// expressions
|
||||
// fields := typ.fields.filter(typ == 'string' || typ == 'int')
|
||||
// fields := typ.fields
|
||||
// get only string and int fields
|
||||
// mut fields := []Var
|
||||
info := sym.info as table.Struct
|
||||
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type] &&
|
||||
'skip' !in it.attrs)
|
||||
if fields.len == 0 {
|
||||
p.error('V orm: select: empty fields in `$table_name`')
|
||||
}
|
||||
if fields[0].name != 'id' {
|
||||
p.error('V orm: `id int` must be the first field in `$table_name`')
|
||||
}
|
||||
for field in fields {
|
||||
// println('registering sql field var $field.name')
|
||||
p.scope.register(field.name, ast.Var{
|
||||
name: field.name
|
||||
typ: field.typ
|
||||
is_mut: true
|
||||
is_used: true
|
||||
is_changed: true
|
||||
})
|
||||
}
|
||||
// ////////////
|
||||
return ast.SqlExpr{
|
||||
is_count: is_count
|
||||
typ: typ
|
||||
db_expr: db_expr
|
||||
table_name: table_name
|
||||
//table_name: table_name
|
||||
table_type: table_type
|
||||
where_expr: where_expr
|
||||
has_where: has_where
|
||||
fields: fields
|
||||
//fields: fields
|
||||
is_array: !query_one
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
|
||||
// insert user into User
|
||||
// update User set nr_oders=nr_orders+1 where id == user_id
|
||||
fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||
pos := p.tok.position()
|
||||
p.inside_match = true
|
||||
defer {
|
||||
p.inside_match = false
|
||||
|
@ -172,6 +139,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
|||
table_name: table_name
|
||||
table_type: table_type
|
||||
object_var_name: inserted_var_name
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue