orm: add table creation (#9621)
parent
3a07fbc653
commit
ab03357a6e
|
@ -10,7 +10,7 @@ struct Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
id int
|
id int [primary]
|
||||||
age int
|
age int
|
||||||
name string
|
name string
|
||||||
is_customer bool
|
is_customer bool
|
||||||
|
@ -24,7 +24,9 @@ struct Foo {
|
||||||
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, age int default 0, name text default '', is_customer int default 0);")
|
sql db {
|
||||||
|
create table User
|
||||||
|
}
|
||||||
name := 'Peter'
|
name := 'Peter'
|
||||||
db.exec("insert into User (name, age) values ('Sam', 29)")
|
db.exec("insert into User (name, age) values ('Sam', 29)")
|
||||||
db.exec("insert into User (name, age) values ('Peter', 31)")
|
db.exec("insert into User (name, age) values ('Peter', 31)")
|
||||||
|
|
|
@ -1410,6 +1410,7 @@ pub enum SqlStmtKind {
|
||||||
insert
|
insert
|
||||||
update
|
update
|
||||||
delete
|
delete
|
||||||
|
create
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SqlStmt {
|
pub struct SqlStmt {
|
||||||
|
|
|
@ -1232,6 +1232,9 @@ pub fn (mut f Fmt) sql_stmt(node ast.SqlStmt) {
|
||||||
f.expr(node.where_expr)
|
f.expr(node.where_expr)
|
||||||
f.writeln('')
|
f.writeln('')
|
||||||
}
|
}
|
||||||
|
.create {
|
||||||
|
f.writeln('create table $table_name')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f.writeln('}')
|
f.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,10 @@ enum SqlType {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
||||||
|
if node.kind == .create {
|
||||||
|
g.sql_create_table(node)
|
||||||
|
return
|
||||||
|
}
|
||||||
typ := g.parse_db_type(node.db_expr)
|
typ := g.parse_db_type(node.db_expr)
|
||||||
match typ {
|
match typ {
|
||||||
.sqlite3 {
|
.sqlite3 {
|
||||||
|
@ -35,6 +39,18 @@ fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sql_create_table(node ast.SqlStmt) {
|
||||||
|
typ := g.parse_db_type(node.db_expr)
|
||||||
|
match typ {
|
||||||
|
.sqlite3 {
|
||||||
|
g.sqlite3_create_table(node, typ)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
verror('This database type `$typ` is not implemented yet in orm') // TODO add better error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) sql_select_expr(node ast.SqlExpr, sub bool, line string) {
|
fn (mut g Gen) sql_select_expr(node ast.SqlExpr, sub bool, line string) {
|
||||||
typ := g.parse_db_type(node.db_expr)
|
typ := g.parse_db_type(node.db_expr)
|
||||||
match typ {
|
match typ {
|
||||||
|
@ -69,6 +85,18 @@ fn (mut g Gen) sql_bind_string(val string, len string, typ SqlType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sql_type_from_v(typ SqlType, v_typ ast.Type) string {
|
||||||
|
match typ {
|
||||||
|
.sqlite3 {
|
||||||
|
return g.sqlite3_type_from_v(typ, v_typ)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// add error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
// sqlite3
|
// sqlite3
|
||||||
|
|
||||||
fn (mut g Gen) sqlite3_stmt(node ast.SqlStmt, typ SqlType) {
|
fn (mut g Gen) sqlite3_stmt(node ast.SqlStmt, typ SqlType) {
|
||||||
|
@ -337,6 +365,70 @@ fn (mut g Gen) sqlite3_select_expr(node ast.SqlExpr, sub bool, line string, sql_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sqlite3_create_table(node ast.SqlStmt, typ SqlType) {
|
||||||
|
typ_sym := g.table.get_type_symbol(node.table_expr.typ)
|
||||||
|
if typ_sym.info !is ast.Struct {
|
||||||
|
verror('Type `$typ_sym.name` has to be a struct')
|
||||||
|
}
|
||||||
|
g.writeln('// sqlite3 table creator ($typ_sym.name)')
|
||||||
|
struct_data := typ_sym.info as ast.Struct
|
||||||
|
table_name := typ_sym.name.split('.').last()
|
||||||
|
mut create_string := 'CREATE TABLE IF NOT EXISTS `$table_name` ('
|
||||||
|
|
||||||
|
mut fields := []string{}
|
||||||
|
|
||||||
|
outer: for field in struct_data.fields {
|
||||||
|
mut is_primary := false
|
||||||
|
for attr in field.attrs {
|
||||||
|
match attr.name {
|
||||||
|
'skip' {
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
'primary' {
|
||||||
|
is_primary = true
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mut stmt := ''
|
||||||
|
mut converted_typ := g.sql_type_from_v(typ, field.typ)
|
||||||
|
mut name := field.name
|
||||||
|
if converted_typ == '' {
|
||||||
|
if g.table.get_type_symbol(field.typ).kind == .struct_ {
|
||||||
|
converted_typ = g.sql_type_from_v(typ, ast.int_type)
|
||||||
|
g.sql_create_table(ast.SqlStmt{
|
||||||
|
db_expr: node.db_expr
|
||||||
|
kind: node.kind
|
||||||
|
pos: node.pos
|
||||||
|
table_expr: ast.TypeNode{
|
||||||
|
typ: field.typ
|
||||||
|
pos: node.table_expr.pos
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
eprintln(g.table.get_type_symbol(field.typ).kind)
|
||||||
|
verror('unknown type ($field.typ)')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stmt = '`$name` $converted_typ'
|
||||||
|
|
||||||
|
if field.has_default_expr {
|
||||||
|
stmt += ' DEFAULT '
|
||||||
|
stmt += field.default_expr.str()
|
||||||
|
}
|
||||||
|
if is_primary {
|
||||||
|
stmt += ' PRIMARY KEY'
|
||||||
|
}
|
||||||
|
fields << stmt
|
||||||
|
}
|
||||||
|
create_string += fields.join(', ')
|
||||||
|
create_string += ');'
|
||||||
|
g.write('sqlite__DB_exec(')
|
||||||
|
g.expr(node.db_expr)
|
||||||
|
g.writeln(', _SLIT("$create_string"));')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) sqlite3_bind_int(val string) {
|
fn (mut g Gen) sqlite3_bind_int(val string) {
|
||||||
g.sql_buf.writeln('sqlite3_bind_int($g.sql_stmt_name, $g.sql_i, $val);')
|
g.sql_buf.writeln('sqlite3_bind_int($g.sql_stmt_name, $g.sql_i, $val);')
|
||||||
}
|
}
|
||||||
|
@ -345,6 +437,16 @@ fn (mut g Gen) sqlite3_bind_string(val string, len string) {
|
||||||
g.sql_buf.writeln('sqlite3_bind_text($g.sql_stmt_name, $g.sql_i, $val, $len, 0);')
|
g.sql_buf.writeln('sqlite3_bind_text($g.sql_stmt_name, $g.sql_i, $val, $len, 0);')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sqlite3_type_from_v(typ SqlType, v_typ ast.Type) string {
|
||||||
|
if v_typ.is_number() || v_typ == ast.bool_type {
|
||||||
|
return 'INTEGER'
|
||||||
|
}
|
||||||
|
if v_typ.is_string() {
|
||||||
|
return 'TEXT'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
// mysql
|
// mysql
|
||||||
|
|
||||||
fn (mut g Gen) mysql_stmt(node ast.SqlStmt) {
|
fn (mut g Gen) mysql_stmt(node ast.SqlStmt) {
|
||||||
|
|
|
@ -127,6 +127,25 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||||
kind = .delete
|
kind = .delete
|
||||||
} else if n == 'update' {
|
} else if n == 'update' {
|
||||||
kind = .update
|
kind = .update
|
||||||
|
} else if n == 'create' {
|
||||||
|
kind = .create
|
||||||
|
table := p.check_name()
|
||||||
|
if table != 'table' {
|
||||||
|
p.error('expected `table` got `$table`')
|
||||||
|
return ast.SqlStmt{}
|
||||||
|
}
|
||||||
|
typ := p.parse_type()
|
||||||
|
typ_pos := p.tok.position()
|
||||||
|
p.check(.rcbr)
|
||||||
|
return ast.SqlStmt{
|
||||||
|
db_expr: db_expr
|
||||||
|
kind: kind
|
||||||
|
pos: pos.extend(p.prev_tok.position())
|
||||||
|
table_expr: ast.TypeNode{
|
||||||
|
typ: typ
|
||||||
|
pos: typ_pos
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mut inserted_var_name := ''
|
mut inserted_var_name := ''
|
||||||
mut table_type := ast.Type(0)
|
mut table_type := ast.Type(0)
|
||||||
|
|
Loading…
Reference in New Issue