orm: select where id = x
parent
ddb1770af2
commit
fb5cae7376
|
@ -3,27 +3,28 @@
|
||||||
//import term
|
//import term
|
||||||
import sqlite
|
import sqlite
|
||||||
|
|
||||||
struct Modules {
|
struct Module {
|
||||||
id int
|
id int
|
||||||
user_id int
|
user_id int
|
||||||
name string
|
//name string
|
||||||
url string
|
//url string
|
||||||
//nr_downloads int
|
//nr_downloads int
|
||||||
}
|
}
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
id int
|
id int
|
||||||
|
age int
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_orm_sqlite() {
|
fn test_orm_sqlite() {
|
||||||
db := sqlite.connect(':memory:') or { panic(err) }
|
db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
db.exec("drop table if exists User")
|
db.exec("drop table if exists User")
|
||||||
db.exec("create table User (id integer primary key, name text default '');")
|
db.exec("create table User (id integer primary key, age int default 0, name text default '');")
|
||||||
|
|
||||||
name := 'sam'
|
name := 'sam'
|
||||||
|
|
||||||
db.exec("insert into User (name) values ('Sam')")
|
db.exec("insert into User (name, age) values ('Sam', 29)")
|
||||||
db.exec("insert into User (name) values ('Peter')")
|
db.exec("insert into User (name) values ('Peter')")
|
||||||
db.exec("insert into User (name) values ('Kate')")
|
db.exec("insert into User (name) values ('Kate')")
|
||||||
nr_all_users := sql db {
|
nr_all_users := sql db {
|
||||||
|
@ -48,6 +49,14 @@ fn test_orm_sqlite() {
|
||||||
select count from User where id == 1 && name == name
|
select count from User where id == 1 && name == name
|
||||||
}
|
}
|
||||||
println('nr_sams=$nr_sams')
|
println('nr_sams=$nr_sams')
|
||||||
|
//
|
||||||
|
user := sql db {
|
||||||
|
select from User where id == 1
|
||||||
|
}
|
||||||
|
println(user)
|
||||||
|
assert user.name == 'Sam'
|
||||||
|
assert user.id == 1
|
||||||
|
assert user.age == 29
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,13 @@ fn test_sb() {
|
||||||
assert sb.len == 2
|
assert sb.len == 2
|
||||||
assert sb.str() == 'ab'
|
assert sb.str() == 'ab'
|
||||||
///
|
///
|
||||||
sb = strings.new_builder(10)
|
$if !windows {
|
||||||
sb.write('123456')
|
// TODO msvc bug
|
||||||
assert sb.cut_last(2) == '56'
|
sb = strings.new_builder(10)
|
||||||
assert sb.str() == '1234'
|
sb.write('123456')
|
||||||
|
assert sb.cut_last(2) == '56'
|
||||||
|
assert sb.str() == '1234'
|
||||||
|
}
|
||||||
///
|
///
|
||||||
/*
|
/*
|
||||||
sb = strings.new_builder(10)
|
sb = strings.new_builder(10)
|
||||||
|
|
|
@ -9,11 +9,11 @@ import v.errors
|
||||||
|
|
||||||
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
||||||
|
|
||||||
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr |
|
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr | CharLiteral |
|
||||||
CastExpr | CharLiteral | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr |
|
ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr | IndexExpr |
|
||||||
IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | MapInit | MatchExpr | None |
|
InfixExpr | IntegerLiteral | Likely | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr |
|
||||||
OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr |
|
PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral |
|
||||||
StringInterLiteral | StringLiteral | StructInit | Type | TypeOf
|
StructInit | Type | TypeOf
|
||||||
|
|
||||||
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ConstDecl |
|
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ConstDecl |
|
||||||
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt |
|
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt |
|
||||||
|
@ -44,7 +44,6 @@ pub struct ExprStmt {
|
||||||
pub:
|
pub:
|
||||||
expr Expr
|
expr Expr
|
||||||
pos token.Position
|
pos token.Position
|
||||||
// treat like expr (dont add trailing `;`)
|
|
||||||
// is used for `x++` in `for x:=1; ; x++`
|
// is used for `x++` in `for x:=1; ; x++`
|
||||||
is_expr bool
|
is_expr bool
|
||||||
pub mut:
|
pub mut:
|
||||||
|
@ -806,8 +805,9 @@ pub:
|
||||||
is_count bool
|
is_count bool
|
||||||
db_var_name string // `db` in `sql db {`
|
db_var_name string // `db` in `sql db {`
|
||||||
table_name string
|
table_name string
|
||||||
where_expr Expr
|
where_expr Expr
|
||||||
has_where bool
|
has_where bool
|
||||||
|
fields []table.Field
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
|
|
@ -1307,8 +1307,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
if right_type_sym0.kind == .multi_return {
|
if right_type_sym0.kind == .multi_return {
|
||||||
assign_stmt.right_types = right_type_sym0.mr_info().types
|
assign_stmt.right_types = right_type_sym0.mr_info().types
|
||||||
right_len = assign_stmt.right_types.len
|
right_len = assign_stmt.right_types.len
|
||||||
|
} else if right_type0 == table.void_type {
|
||||||
|
right_len = 0
|
||||||
}
|
}
|
||||||
else if right_type0 == table.void_type { right_len=0 }
|
|
||||||
}
|
}
|
||||||
if assign_stmt.left.len != right_len {
|
if assign_stmt.left.len != right_len {
|
||||||
if right_first is ast.CallExpr {
|
if right_first is ast.CallExpr {
|
||||||
|
@ -1338,7 +1339,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
if is_decl {
|
if is_decl {
|
||||||
left_type = c.table.mktyp(right_type)
|
left_type = c.table.mktyp(right_type)
|
||||||
// we are unwrapping here instead if check_expr_opt_call currently
|
// we are unwrapping here instead if check_expr_opt_call currently
|
||||||
if left_type.has_flag(.optional) { left_type = left_type.clear_flag(.optional) }
|
if left_type.has_flag(.optional) {
|
||||||
|
left_type = left_type.clear_flag(.optional)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Make sure the variable is mutable
|
// Make sure the variable is mutable
|
||||||
c.fail_if_immutable(left)
|
c.fail_if_immutable(left)
|
||||||
|
@ -1353,9 +1356,10 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
if assign_stmt.op !in [.assign, .decl_assign] {
|
if assign_stmt.op !in [.assign, .decl_assign] {
|
||||||
c.error('cannot modify blank `_` identifier', it.pos)
|
c.error('cannot modify blank `_` identifier', it.pos)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
if is_decl {
|
||||||
if is_decl { c.check_valid_snake_case(it.name, 'variable name', it.pos) }
|
c.check_valid_snake_case(it.name, 'variable name', it.pos)
|
||||||
|
}
|
||||||
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
||||||
mut ident_var_info := it.var_info()
|
mut ident_var_info := it.var_info()
|
||||||
ident_var_info.typ = left_type
|
ident_var_info.typ = left_type
|
||||||
|
@ -1366,12 +1370,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
// Do now allow `*x = y` outside `unsafe`
|
// Do now allow `*x = y` outside `unsafe`
|
||||||
if it.op == .mul && !c.inside_unsafe {
|
if it.op == .mul && !c.inside_unsafe {
|
||||||
c.error('modifying variables via deferencing can only be done in `unsafe` blocks', assign_stmt.pos)
|
c.error('modifying variables via deferencing can only be done in `unsafe` blocks',
|
||||||
|
assign_stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
|
||||||
left_type_unwrapped := c.unwrap_generic(left_type)
|
left_type_unwrapped := c.unwrap_generic(left_type)
|
||||||
right_type_unwrapped := c.unwrap_generic(right_type)
|
right_type_unwrapped := c.unwrap_generic(right_type)
|
||||||
left_sym := c.table.get_type_symbol(left_type_unwrapped)
|
left_sym := c.table.get_type_symbol(left_type_unwrapped)
|
||||||
|
@ -1381,9 +1385,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
.assign {} // No need to do single side check for =. But here put it first for speed.
|
.assign {} // No need to do single side check for =. But here put it first for speed.
|
||||||
.plus_assign {
|
.plus_assign {
|
||||||
if !left_sym.is_number() && left_type != table.string_type && !left_sym.is_pointer() {
|
if !left_sym.is_number() && left_type != table.string_type && !left_sym.is_pointer() {
|
||||||
c.error('operator += not defined on left operand type `$left_sym.name`', left.position())
|
c.error('operator += not defined on left operand type `$left_sym.name`',
|
||||||
|
left.position())
|
||||||
} else if !right_sym.is_number() && right_type != table.string_type && !right_sym.is_pointer() {
|
} else if !right_sym.is_number() && right_type != table.string_type && !right_sym.is_pointer() {
|
||||||
c.error('operator += not defined on right operand type `$right_sym.name`', right.position())
|
c.error('operator += not defined on right operand type `$right_sym.name`',
|
||||||
|
right.position())
|
||||||
}
|
}
|
||||||
if right is ast.IntegerLiteral && right.str().int() == 1 {
|
if right is ast.IntegerLiteral && right.str().int() == 1 {
|
||||||
c.error('use `++` instead of `+= 1`', assign_stmt.pos)
|
c.error('use `++` instead of `+= 1`', assign_stmt.pos)
|
||||||
|
@ -1391,9 +1397,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
.minus_assign {
|
.minus_assign {
|
||||||
if !left_sym.is_number() && !left_sym.is_pointer() {
|
if !left_sym.is_number() && !left_sym.is_pointer() {
|
||||||
c.error('operator -= not defined on left operand type `$left_sym.name`', left.position())
|
c.error('operator -= not defined on left operand type `$left_sym.name`',
|
||||||
|
left.position())
|
||||||
} else if !right_sym.is_number() && !right_sym.is_pointer() {
|
} else if !right_sym.is_number() && !right_sym.is_pointer() {
|
||||||
c.error('operator -= not defined on right operand type `$right_sym.name`', right.position())
|
c.error('operator -= not defined on right operand type `$right_sym.name`',
|
||||||
|
right.position())
|
||||||
}
|
}
|
||||||
if right is ast.IntegerLiteral && right.str().int() == 1 {
|
if right is ast.IntegerLiteral && right.str().int() == 1 {
|
||||||
c.error('use `--` instead of `-= 1`', assign_stmt.pos)
|
c.error('use `--` instead of `-= 1`', assign_stmt.pos)
|
||||||
|
@ -1973,10 +1981,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
return table.u32_type
|
return table.u32_type
|
||||||
}
|
}
|
||||||
ast.SqlExpr {
|
ast.SqlExpr {
|
||||||
if it.has_where {
|
return c.sql_expr(it)
|
||||||
c.expr(it.where_expr)
|
|
||||||
}
|
|
||||||
return it.typ
|
|
||||||
}
|
}
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
if it.language == .c {
|
if it.language == .c {
|
||||||
|
@ -2564,6 +2569,13 @@ fn (c &Checker) fileis(s string) bool {
|
||||||
return c.file.path.contains(s)
|
return c.file.path.contains(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) sql_expr(node ast.SqlExpr) table.Type {
|
||||||
|
if node.has_where {
|
||||||
|
c.expr(node.where_expr)
|
||||||
|
}
|
||||||
|
return node.typ
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut c Checker) fn_decl(it ast.FnDecl) {
|
fn (mut c Checker) fn_decl(it ast.FnDecl) {
|
||||||
if it.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
|
if it.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
|
||||||
// loop thru each generic type and generate a function
|
// loop thru each generic type and generate a function
|
||||||
|
|
|
@ -5,6 +5,7 @@ module gen
|
||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
import strings
|
import strings
|
||||||
|
import v.table
|
||||||
|
|
||||||
// pg,mysql etc
|
// pg,mysql etc
|
||||||
const (
|
const (
|
||||||
|
@ -26,8 +27,17 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) {
|
||||||
cur_line := g.go_before_stmt(0)
|
cur_line := g.go_before_stmt(0)
|
||||||
mut q := 'select '
|
mut q := 'select '
|
||||||
if node.is_count {
|
if node.is_count {
|
||||||
// select count(*) from User
|
// `select count(*) from User`
|
||||||
q += 'count(*) from $node.table_name'
|
q += 'count(*) from $node.table_name'
|
||||||
|
} else {
|
||||||
|
// `select id, name, country from User`
|
||||||
|
for i, field in node.fields {
|
||||||
|
q += '$field.name'
|
||||||
|
if i < node.fields.len - 1 {
|
||||||
|
q += ', '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q += ' from $node.table_name'
|
||||||
}
|
}
|
||||||
if node.has_where {
|
if node.has_where {
|
||||||
q += ' where '
|
q += ' where '
|
||||||
|
@ -37,7 +47,7 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) {
|
||||||
db_name := g.new_tmp_var()
|
db_name := g.new_tmp_var()
|
||||||
g.writeln('\n\t// sql')
|
g.writeln('\n\t// sql')
|
||||||
// g.write('${dbtype}__DB $db_name = *(${dbtype}__DB*)${node.db_var_name}.data;')
|
// g.write('${dbtype}__DB $db_name = *(${dbtype}__DB*)${node.db_var_name}.data;')
|
||||||
g.write('${dbtype}__DB $db_name = ${node.db_var_name};')
|
g.writeln('${dbtype}__DB $db_name = ${node.db_var_name};')
|
||||||
// g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$q')
|
// g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$q')
|
||||||
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("$q')
|
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("$q')
|
||||||
if node.has_where && node.where_expr is ast.InfixExpr {
|
if node.has_where && node.where_expr is ast.InfixExpr {
|
||||||
|
@ -49,7 +59,27 @@ fn (mut g Gen) sql_expr(node ast.SqlExpr) {
|
||||||
g.sql_buf = strings.new_builder(100)
|
g.sql_buf = strings.new_builder(100)
|
||||||
g.writeln(binds)
|
g.writeln(binds)
|
||||||
g.writeln('puts(sqlite3_errmsg(${db_name}.conn));')
|
g.writeln('puts(sqlite3_errmsg(${db_name}.conn));')
|
||||||
g.writeln('$cur_line ${dbtype}__get_int_from_stmt($g.sql_stmt_name);')
|
//
|
||||||
|
if node.is_count {
|
||||||
|
g.writeln('$cur_line ${dbtype}__get_int_from_stmt($g.sql_stmt_name);')
|
||||||
|
} else {
|
||||||
|
// `user := sql db { select from User where id = 1 }`
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
g.write(g.typ(node.typ))
|
||||||
|
g.writeln(' $tmp;')
|
||||||
|
g.writeln('sqlite3_step($g.sql_stmt_name);')
|
||||||
|
for i, field in node.fields {
|
||||||
|
mut func := 'sqlite3_column_int'
|
||||||
|
if field.typ == table.string_type {
|
||||||
|
func = 'sqlite3_column_text'
|
||||||
|
g.writeln('${tmp}.$field.name = tos_clone(${func}($g.sql_stmt_name, $i));')
|
||||||
|
} else {
|
||||||
|
g.writeln('${tmp}.$field.name = ${func}($g.sql_stmt_name, $i);')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.writeln('sqlite3_finalize($g.sql_stmt_name);')
|
||||||
|
g.writeln('$cur_line $tmp; ') // `User user = tmp;`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) expr_to_sql(expr ast.Expr) {
|
fn (mut g Gen) expr_to_sql(expr ast.Expr) {
|
||||||
|
|
|
@ -28,6 +28,16 @@ fn (mut p Parser) sql_expr() ast.SqlExpr {
|
||||||
if has_where {
|
if has_where {
|
||||||
p.next()
|
p.next()
|
||||||
where_expr = p.expr(0)
|
where_expr = p.expr(0)
|
||||||
|
// `id == x` means that a single object is returned
|
||||||
|
if !is_count && where_expr is ast.InfixExpr {
|
||||||
|
e := where_expr as ast.InfixExpr
|
||||||
|
if e.op == .eq && e.left is ast.Ident {
|
||||||
|
ident := e.left as ast.Ident
|
||||||
|
if ident.name == 'id' {
|
||||||
|
typ = table_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
// /////////
|
// /////////
|
||||||
|
@ -75,5 +85,6 @@ fn (mut p Parser) sql_expr() ast.SqlExpr {
|
||||||
table_name: table_name
|
table_name: table_name
|
||||||
where_expr: where_expr
|
where_expr: where_expr
|
||||||
has_where: has_where
|
has_where: has_where
|
||||||
|
fields: fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue