orm: add unique fields & add drop table stmt (#9684)
parent
b0b3c51658
commit
67d8639917
|
@ -10,15 +10,14 @@ struct Module {
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
id int [primary; sql: serial]
|
id int [primary; sql: serial]
|
||||||
age int
|
age int [unique: 'user']
|
||||||
name string [nonull]
|
name string [unique]
|
||||||
is_customer bool
|
is_customer bool [unique: 'user']
|
||||||
skipped_string string [skip]
|
skipped_string string [skip]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
db := sqlite.connect(':memory:') or { panic(err) }
|
db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
db.exec('drop table if exists User')
|
|
||||||
sql db {
|
sql db {
|
||||||
create table Module
|
create table Module
|
||||||
}
|
}
|
||||||
|
@ -40,6 +39,10 @@ fn main() {
|
||||||
select from Module where id == 1
|
select from Module where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sql db {
|
||||||
|
drop table Module
|
||||||
|
}
|
||||||
|
|
||||||
eprintln(modul)
|
eprintln(modul)
|
||||||
|
|
||||||
mysql()
|
mysql()
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
### Fields
|
### 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
|
- `[nonull]` field will be `NOT NULL` in table creation
|
||||||
- `[skip]` field will be skipped
|
- `[skip]` field will be skipped
|
||||||
- `[sql: type]` sets the type which is used in sql (special type `serial`)
|
- `[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
|
### Insert
|
||||||
|
|
||||||
```v ignore
|
```v ignore
|
||||||
|
|
|
@ -1407,6 +1407,7 @@ pub enum SqlStmtKind {
|
||||||
update
|
update
|
||||||
delete
|
delete
|
||||||
create
|
create
|
||||||
|
drop
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SqlStmt {
|
pub struct SqlStmt {
|
||||||
|
|
|
@ -1237,6 +1237,9 @@ pub fn (mut f Fmt) sql_stmt(node ast.SqlStmt) {
|
||||||
.create {
|
.create {
|
||||||
f.writeln('create table $table_name')
|
f.writeln('create table $table_name')
|
||||||
}
|
}
|
||||||
|
.drop {
|
||||||
|
f.writeln('drop table $table_name')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f.writeln('}')
|
f.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
||||||
if node.kind == .create {
|
if node.kind == .create {
|
||||||
g.sql_create_table(node)
|
g.sql_create_table(node)
|
||||||
return
|
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
|
g.sql_table_name = g.table.get_type_symbol(node.table_expr.typ).name
|
||||||
typ := g.parse_db_type(node.db_expr)
|
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) {
|
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
|
g.sql_table_name = g.table.get_type_symbol(node.table_expr.typ).name
|
||||||
typ := g.parse_db_type(node.db_expr)
|
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"));')
|
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) {
|
fn (mut g Gen) sqlite3_bind(val string, len string, typ ast.Type) {
|
||||||
match g.sqlite3_type_from_v(typ) {
|
match g.sqlite3_type_from_v(typ) {
|
||||||
'INTEGER' {
|
'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.write('Option_mysql__Result $tmp = mysql__Connection_query(&')
|
||||||
g.expr(node.db_expr)
|
g.expr(node.db_expr)
|
||||||
g.writeln(', _SLIT("$create_string"));')
|
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) {
|
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 fields := []string{}
|
||||||
|
|
||||||
mut primary := '' // for mysql
|
mut primary := '' // for mysql
|
||||||
|
mut unique := map[string][]string{}
|
||||||
|
|
||||||
for field in struct_data.fields {
|
for field in struct_data.fields {
|
||||||
mut is_primary := false
|
mut is_primary := false
|
||||||
mut no_null := false
|
mut no_null := false
|
||||||
|
mut is_unique := false
|
||||||
for attr in field.attrs {
|
for attr in field.attrs {
|
||||||
match attr.name {
|
match attr.name {
|
||||||
'primary' {
|
'primary' {
|
||||||
is_primary = true
|
is_primary = true
|
||||||
primary = field.name
|
primary = field.name
|
||||||
}
|
}
|
||||||
|
'unique' {
|
||||||
|
if attr.arg != '' {
|
||||||
|
unique[attr.arg] << field.name
|
||||||
|
} else {
|
||||||
|
is_unique = true
|
||||||
|
}
|
||||||
|
}
|
||||||
'nonull' {
|
'nonull' {
|
||||||
no_null = true
|
no_null = true
|
||||||
}
|
}
|
||||||
|
@ -840,11 +887,23 @@ fn (mut g Gen) table_gen(node ast.SqlStmt, typ SqlType) string {
|
||||||
if no_null {
|
if no_null {
|
||||||
stmt += ' NOT NULL'
|
stmt += ' NOT NULL'
|
||||||
}
|
}
|
||||||
|
if is_unique {
|
||||||
|
stmt += ' UNIQUE'
|
||||||
|
}
|
||||||
if is_primary && typ == .sqlite3 {
|
if is_primary && typ == .sqlite3 {
|
||||||
stmt += ' PRIMARY KEY'
|
stmt += ' PRIMARY KEY'
|
||||||
}
|
}
|
||||||
fields << stmt
|
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 {
|
if typ == .mysql {
|
||||||
fields << 'PRIMARY KEY(`$primary`)'
|
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
|
// for left sides just add a string, for right sides, generate the bindings
|
||||||
if g.sql_side == .left {
|
if g.sql_side == .left {
|
||||||
// println("sql gen left $expr.name")
|
// println("sql gen left $expr.name")
|
||||||
eprintln(expr.name)
|
|
||||||
g.sql_left_type = g.get_struct_field_typ(expr.name)
|
g.sql_left_type = g.get_struct_field_typ(expr.name)
|
||||||
g.write(expr.name)
|
g.write(expr.name)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -146,6 +146,25 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||||
pos: typ_pos
|
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 inserted_var_name := ''
|
||||||
mut table_type := ast.Type(0)
|
mut table_type := ast.Type(0)
|
||||||
|
|
Loading…
Reference in New Issue