mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
orm: add table creation (#9621)
This commit is contained in:
parent
3a07fbc653
commit
ab03357a6e
@ -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)")
|
||||
|
@ -1410,6 +1410,7 @@ pub enum SqlStmtKind {
|
||||
insert
|
||||
update
|
||||
delete
|
||||
create
|
||||
}
|
||||
|
||||
pub struct SqlStmt {
|
||||
|
@ -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('}')
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user