orm: add unique fields & add drop table stmt (#9684)
parent
b0b3c51658
commit
67d8639917
|
@ -10,15 +10,14 @@ struct Module {
|
|||
|
||||
struct User {
|
||||
id int [primary; sql: serial]
|
||||
age int
|
||||
name string [nonull]
|
||||
is_customer bool
|
||||
age int [unique: 'user']
|
||||
name string [unique]
|
||||
is_customer bool [unique: 'user']
|
||||
skipped_string string [skip]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
db := sqlite.connect(':memory:') or { panic(err) }
|
||||
db.exec('drop table if exists User')
|
||||
sql db {
|
||||
create table Module
|
||||
}
|
||||
|
@ -40,6 +39,10 @@ fn main() {
|
|||
select from Module where id == 1
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table Module
|
||||
}
|
||||
|
||||
eprintln(modul)
|
||||
|
||||
mysql()
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
### Fields
|
||||
|
||||
- `[primary]` set the field as the primary key
|
||||
- `[primary]` sets the field as the primary key
|
||||
- `[unique]` sets the field as unique
|
||||
- `[unique: 'foo']` adds the field to a unique group
|
||||
- `[nonull]` field will be `NOT NULL` in table creation
|
||||
- `[skip]` field will be skipped
|
||||
- `[sql: type]` sets the type which is used in sql (special type `serial`)
|
||||
|
@ -26,6 +28,14 @@ sql db {
|
|||
}
|
||||
```
|
||||
|
||||
### Drop
|
||||
|
||||
```v ignore
|
||||
sql db {
|
||||
drop table Foo
|
||||
}
|
||||
```
|
||||
|
||||
### Insert
|
||||
|
||||
```v ignore
|
||||
|
|
|
@ -1407,6 +1407,7 @@ pub enum SqlStmtKind {
|
|||
update
|
||||
delete
|
||||
create
|
||||
drop
|
||||
}
|
||||
|
||||
pub struct SqlStmt {
|
||||
|
|
|
@ -1237,6 +1237,9 @@ pub fn (mut f Fmt) sql_stmt(node ast.SqlStmt) {
|
|||
.create {
|
||||
f.writeln('create table $table_name')
|
||||
}
|
||||
.drop {
|
||||
f.writeln('drop table $table_name')
|
||||
}
|
||||
}
|
||||
f.writeln('}')
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
|||
if node.kind == .create {
|
||||
g.sql_create_table(node)
|
||||
return
|
||||
} else if node.kind == .drop {
|
||||
g.sql_drop_table(node)
|
||||
return
|
||||
}
|
||||
g.sql_table_name = g.table.get_type_symbol(node.table_expr.typ).name
|
||||
typ := g.parse_db_type(node.db_expr)
|
||||
|
@ -58,6 +61,21 @@ fn (mut g Gen) sql_create_table(node ast.SqlStmt) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) sql_drop_table(node ast.SqlStmt) {
|
||||
typ := g.parse_db_type(node.db_expr)
|
||||
match typ {
|
||||
.sqlite3 {
|
||||
g.sqlite3_drop_table(node, typ)
|
||||
}
|
||||
.mysql {
|
||||
g.mysql_drop_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) {
|
||||
g.sql_table_name = g.table.get_type_symbol(node.table_expr.typ).name
|
||||
typ := g.parse_db_type(node.db_expr)
|
||||
|
@ -300,6 +318,15 @@ fn (mut g Gen) sqlite3_create_table(node ast.SqlStmt, typ SqlType) {
|
|||
g.writeln(', _SLIT("$create_string"));')
|
||||
}
|
||||
|
||||
fn (mut g Gen) sqlite3_drop_table(node ast.SqlStmt, typ SqlType) {
|
||||
table_name := util.strip_mod_name(g.table.get_type_symbol(node.table_expr.typ).name)
|
||||
g.writeln('// sqlite3 table drop')
|
||||
create_string := 'DROP TABLE $table_name;'
|
||||
g.write('sqlite__DB_exec(')
|
||||
g.expr(node.db_expr)
|
||||
g.writeln(', _SLIT("$create_string"));')
|
||||
}
|
||||
|
||||
fn (mut g Gen) sqlite3_bind(val string, len string, typ ast.Type) {
|
||||
match g.sqlite3_type_from_v(typ) {
|
||||
'INTEGER' {
|
||||
|
@ -582,7 +609,18 @@ fn (mut g Gen) mysql_create_table(node ast.SqlStmt, typ SqlType) {
|
|||
g.write('Option_mysql__Result $tmp = mysql__Connection_query(&')
|
||||
g.expr(node.db_expr)
|
||||
g.writeln(', _SLIT("$create_string"));')
|
||||
g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; _STR("Something went wrong\\000%.*s", 2, IError_str(err)); }')
|
||||
g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; eprintln(_STR("Something went wrong\\000%.*s", 2, IError_str(err))); }')
|
||||
}
|
||||
|
||||
fn (mut g Gen) mysql_drop_table(node ast.SqlStmt, typ SqlType) {
|
||||
table_name := util.strip_mod_name(g.table.get_type_symbol(node.table_expr.typ).name)
|
||||
g.writeln('// mysql table drop')
|
||||
create_string := 'DROP TABLE $table_name;'
|
||||
tmp := g.new_tmp_var()
|
||||
g.write('Option_mysql__Result $tmp = mysql__Connection_query(&')
|
||||
g.expr(node.db_expr)
|
||||
g.writeln(', _SLIT("$create_string"));')
|
||||
g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; eprintln(_STR("Something went wrong\\000%.*s", 2, IError_str(err))); }')
|
||||
}
|
||||
|
||||
fn (mut g Gen) mysql_bind(val string, _ ast.Type) {
|
||||
|
@ -794,16 +832,25 @@ fn (mut g Gen) table_gen(node ast.SqlStmt, typ SqlType) string {
|
|||
mut fields := []string{}
|
||||
|
||||
mut primary := '' // for mysql
|
||||
mut unique := map[string][]string{}
|
||||
|
||||
for field in struct_data.fields {
|
||||
mut is_primary := false
|
||||
mut no_null := false
|
||||
mut is_unique := false
|
||||
for attr in field.attrs {
|
||||
match attr.name {
|
||||
'primary' {
|
||||
is_primary = true
|
||||
primary = field.name
|
||||
}
|
||||
'unique' {
|
||||
if attr.arg != '' {
|
||||
unique[attr.arg] << field.name
|
||||
} else {
|
||||
is_unique = true
|
||||
}
|
||||
}
|
||||
'nonull' {
|
||||
no_null = true
|
||||
}
|
||||
|
@ -840,11 +887,23 @@ fn (mut g Gen) table_gen(node ast.SqlStmt, typ SqlType) string {
|
|||
if no_null {
|
||||
stmt += ' NOT NULL'
|
||||
}
|
||||
if is_unique {
|
||||
stmt += ' UNIQUE'
|
||||
}
|
||||
if is_primary && typ == .sqlite3 {
|
||||
stmt += ' PRIMARY KEY'
|
||||
}
|
||||
fields << stmt
|
||||
}
|
||||
if unique.len > 0 {
|
||||
for k, v in unique {
|
||||
mut tmp := []string{}
|
||||
for f in v {
|
||||
tmp << '`$f`'
|
||||
}
|
||||
fields << '/* $k */UNIQUE(${tmp.join(', ')})'
|
||||
}
|
||||
}
|
||||
if typ == .mysql {
|
||||
fields << 'PRIMARY KEY(`$primary`)'
|
||||
}
|
||||
|
@ -903,7 +962,6 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr, typ SqlType) {
|
|||
// for left sides just add a string, for right sides, generate the bindings
|
||||
if g.sql_side == .left {
|
||||
// println("sql gen left $expr.name")
|
||||
eprintln(expr.name)
|
||||
g.sql_left_type = g.get_struct_field_typ(expr.name)
|
||||
g.write(expr.name)
|
||||
} else {
|
||||
|
|
|
@ -146,6 +146,25 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
|||
pos: typ_pos
|
||||
}
|
||||
}
|
||||
} else if n == 'drop' {
|
||||
kind = .drop
|
||||
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