orm: add table creation (#9621)

pull/9628/head
Louis Schmieder 2021-04-07 15:27:02 +02:00 committed by GitHub
parent 3a07fbc653
commit ab03357a6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 2 deletions

View File

@ -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)")

View File

@ -1410,6 +1410,7 @@ pub enum SqlStmtKind {
insert insert
update update
delete delete
create
} }
pub struct SqlStmt { pub struct SqlStmt {

View File

@ -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('}')
} }

View File

@ -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) {

View File

@ -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)