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 {
id int
id int [primary]
age int
name string
is_customer bool
@ -24,7 +24,9 @@ struct Foo {
fn test_orm_sqlite() {
db := sqlite.connect(':memory:') or { panic(err) }
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'
db.exec("insert into User (name, age) values ('Sam', 29)")
db.exec("insert into User (name, age) values ('Peter', 31)")

View File

@ -1410,6 +1410,7 @@ pub enum SqlStmtKind {
insert
update
delete
create
}
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.writeln('')
}
.create {
f.writeln('create table $table_name')
}
}
f.writeln('}')
}

View File

@ -24,6 +24,10 @@ enum SqlType {
}
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)
match typ {
.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) {
typ := g.parse_db_type(node.db_expr)
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
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) {
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);')
}
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
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
} else if n == '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 table_type := ast.Type(0)