orm: fix mysql substructs (#9930)
parent
ea0ac09297
commit
b15156d465
|
@ -19,7 +19,13 @@ struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
db := sqlite.connect(':memory:') or { panic(err) }
|
sqlite3()
|
||||||
|
mysql()
|
||||||
|
psql()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sqlite3() {
|
||||||
|
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
sql db {
|
sql db {
|
||||||
create table Module
|
create table Module
|
||||||
}
|
}
|
||||||
|
@ -46,9 +52,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln(modul)
|
eprintln(modul)
|
||||||
|
db.close() or { panic(err) }
|
||||||
// mysql()
|
|
||||||
psql()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mysql() {
|
fn mysql() {
|
||||||
|
@ -82,7 +86,9 @@ fn mysql() {
|
||||||
m := sql conn {
|
m := sql conn {
|
||||||
select from Module where id == 1
|
select from Module where id == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln(m)
|
eprintln(m)
|
||||||
|
conn.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn psql() {
|
fn psql() {
|
||||||
|
@ -117,4 +123,5 @@ fn psql() {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln(modul)
|
eprintln(modul)
|
||||||
|
db.close()
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub enum ConnectionFlag {
|
||||||
// TODO: Documentation
|
// TODO: Documentation
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
mut:
|
mut:
|
||||||
conn &C.MYSQL = C.mysql_init(0)
|
conn &C.MYSQL = C.mysql_init(0)
|
||||||
pub mut:
|
pub mut:
|
||||||
host string = '127.0.0.1'
|
host string = '127.0.0.1'
|
||||||
port u32 = 3306
|
port u32 = 3306
|
||||||
|
@ -35,7 +35,7 @@ pub mut:
|
||||||
// connect - create a new connection to the MySQL server.
|
// connect - create a new connection to the MySQL server.
|
||||||
pub fn (mut conn Connection) connect() ?bool {
|
pub fn (mut conn Connection) connect() ?bool {
|
||||||
instance := C.mysql_init(conn.conn)
|
instance := C.mysql_init(conn.conn)
|
||||||
conn.conn = C.mysql_real_connect(conn.conn, conn.host.str, conn.username.str, conn.password.str,
|
conn.conn = C.mysql_real_connect(instance, conn.host.str, conn.username.str, conn.password.str,
|
||||||
conn.dbname.str, conn.port, 0, conn.flag)
|
conn.dbname.str, conn.port, 0, conn.flag)
|
||||||
if isnil(conn.conn) {
|
if isnil(conn.conn) {
|
||||||
return error_with_code(get_error_msg(instance), get_errno(instance))
|
return error_with_code(get_error_msg(instance), get_errno(instance))
|
||||||
|
@ -56,8 +56,8 @@ pub fn (mut conn Connection) query(q string) ?Result {
|
||||||
|
|
||||||
// real_query - make an SQL query and receive the results.
|
// real_query - make an SQL query and receive the results.
|
||||||
// `real_query()` can be used for statements containing binary data.
|
// `real_query()` can be used for statements containing binary data.
|
||||||
// (Binary data may contain the `\0` character, which `query()`
|
// (Binary data may contain the `\0` character, which `query()`
|
||||||
// interprets as the end of the statement string). In addition,
|
// interprets as the end of the statement string). In addition,
|
||||||
// `real_query()` is faster than `query()`.
|
// `real_query()` is faster than `query()`.
|
||||||
pub fn (mut conn Connection) real_query(q string) ?Result {
|
pub fn (mut conn Connection) real_query(q string) ?Result {
|
||||||
if C.mysql_real_query(conn.conn, q.str, q.len) != 0 {
|
if C.mysql_real_query(conn.conn, q.str, q.len) != 0 {
|
||||||
|
@ -122,13 +122,13 @@ pub fn (conn &Connection) tables(wildcard string) ?[]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// escape_string - creates a legal SQL string for use in an SQL statement.
|
// escape_string - creates a legal SQL string for use in an SQL statement.
|
||||||
// The `s` argument is encoded to produce an escaped SQL string,
|
// The `s` argument is encoded to produce an escaped SQL string,
|
||||||
// taking into account the current character set of the connection.
|
// taking into account the current character set of the connection.
|
||||||
pub fn (conn &Connection) escape_string(s string) string {
|
pub fn (conn &Connection) escape_string(s string) string {
|
||||||
unsafe {
|
unsafe {
|
||||||
to := malloc(2 * s.len + 1)
|
to := malloc(2 * s.len + 1)
|
||||||
C.mysql_real_escape_string_quote(conn.conn, to, s.str, s.len, `\'`)
|
C.mysql_real_escape_string_quote(conn.conn, to, s.str, s.len, `\'`)
|
||||||
return to.vstring()
|
return to.vstring()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ pub fn (conn &Connection) get_option(option_type int) ?voidptr {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh - flush the tables or caches, or resets replication server
|
// refresh - flush the tables or caches, or resets replication server
|
||||||
// information. The connected user must have the `RELOAD` privilege.
|
// information. The connected user must have the `RELOAD` privilege.
|
||||||
pub fn (mut conn Connection) refresh(options u32) ?bool {
|
pub fn (mut conn Connection) refresh(options u32) ?bool {
|
||||||
if C.mysql_refresh(conn.conn, options) != 0 {
|
if C.mysql_refresh(conn.conn, options) != 0 {
|
||||||
|
@ -166,7 +166,7 @@ pub fn (mut conn Connection) reset() ?bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ping - pings a server connection, or tries to reconnect if the connection
|
// ping - pings a server connection, or tries to reconnect if the connection
|
||||||
// has gone down.
|
// has gone down.
|
||||||
pub fn (mut conn Connection) ping() ?bool {
|
pub fn (mut conn Connection) ping() ?bool {
|
||||||
if C.mysql_ping(conn.conn) != 0 {
|
if C.mysql_ping(conn.conn) != 0 {
|
||||||
|
|
|
@ -8,7 +8,8 @@ import v.util
|
||||||
|
|
||||||
// pg,mysql etc
|
// pg,mysql etc
|
||||||
const (
|
const (
|
||||||
dbtype = 'sqlite'
|
dbtype = 'sqlite'
|
||||||
|
default_unique_str_len = 256
|
||||||
)
|
)
|
||||||
|
|
||||||
enum SqlExprSide {
|
enum SqlExprSide {
|
||||||
|
@ -452,7 +453,6 @@ fn (mut g Gen) mysql_stmt(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) {
|
||||||
binds := g.sql_buf.str()
|
binds := g.sql_buf.str()
|
||||||
g.sql_buf = strings.new_builder(100)
|
g.sql_buf = strings.new_builder(100)
|
||||||
g.writeln(binds)
|
g.writeln(binds)
|
||||||
// g.writeln('mysql_stmt_attr_set($g.sql_stmt_name, STMT_ATTR_ARRAY_SIZE, 1);')
|
|
||||||
res := g.new_tmp_var()
|
res := g.new_tmp_var()
|
||||||
g.writeln('int $res = mysql_stmt_bind_param($g.sql_stmt_name, $bind);')
|
g.writeln('int $res = mysql_stmt_bind_param($g.sql_stmt_name, $bind);')
|
||||||
g.writeln('if ($res != 0) { puts(mysql_error(${db_name}.conn)); }')
|
g.writeln('if ($res != 0) { puts(mysql_error(${db_name}.conn)); }')
|
||||||
|
@ -476,56 +476,20 @@ fn (mut g Gen) mysql_select_expr(node ast.SqlExpr, sub bool, line string, typ Sq
|
||||||
g.expr(node.db_expr)
|
g.expr(node.db_expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
|
|
||||||
stmt_name := g.new_tmp_var()
|
g.write('string $g.sql_stmt_name = _SLIT("')
|
||||||
g.sql_idents = []string{}
|
|
||||||
g.sql_idents_types = []ast.Type{}
|
|
||||||
g.write('char* ${stmt_name}_raw = "')
|
|
||||||
g.write(g.get_base_sql_select_query(node, typ))
|
g.write(g.get_base_sql_select_query(node, typ))
|
||||||
g.sql_expr_defaults(node, typ)
|
g.sql_expr_defaults(node, typ)
|
||||||
g.writeln('";')
|
g.writeln('");')
|
||||||
g.writeln('string $stmt_name = tos_clone(${stmt_name}_raw);')
|
|
||||||
if g.sql_idents.len > 0 {
|
|
||||||
vals := g.new_tmp_var()
|
|
||||||
g.writeln('Array_string $vals = __new_array_with_default(0, 0, sizeof(string), 0);')
|
|
||||||
for i, ident in g.sql_idents {
|
|
||||||
g.writeln('array_push((array*)&$vals, _MOV((string[]){string_clone(_SLIT("%${i + 1}"))}));')
|
|
||||||
|
|
||||||
g.write('array_push((array*)&$vals, _MOV((string[]){string_clone(')
|
rplc := g.sql_buf.str()
|
||||||
if g.sql_idents_types[i] == ast.string_type {
|
|
||||||
g.write('_SLIT(')
|
|
||||||
} else {
|
|
||||||
sym := g.table.get_type_name(g.sql_idents_types[i])
|
|
||||||
g.write('${sym}_str(')
|
|
||||||
}
|
|
||||||
g.writeln('$ident))}));')
|
|
||||||
}
|
|
||||||
g.writeln('$stmt_name = string_replace_each($stmt_name, $vals);')
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
g.writeln('MYSQL_STMT* $g.sql_stmt_name = mysql_stmt_init(${db_name}.conn);')
|
|
||||||
g.writeln('mysql_stmt_prepare($g.sql_stmt_name, ${stmt_name}.str, ${stmt_name}.len);')
|
|
||||||
|
|
||||||
g.writeln('MYSQL_BIND $g.sql_bind_name[$g.sql_i];')
|
|
||||||
g.writeln('memset($g.sql_bind_name, 0, sizeof(MYSQL_BIND)*$g.sql_i);')
|
|
||||||
|
|
||||||
binds := g.sql_buf.str()
|
|
||||||
g.sql_buf = strings.new_builder(100)
|
g.sql_buf = strings.new_builder(100)
|
||||||
g.writeln(binds)
|
g.writeln(rplc)
|
||||||
|
|
||||||
res := g.new_tmp_var()
|
|
||||||
g.writeln('int $res = mysql_stmt_bind_param($g.sql_stmt_name, $g.sql_bind_name);')
|
|
||||||
g.writeln('if ($res != 0) { puts(mysql_error(${db_name}.conn)); }')
|
|
||||||
g.writeln('$res = mysql_stmt_execute($g.sql_stmt_name);')
|
|
||||||
g.writeln('if ($res != 0) { puts(mysql_error(${db_name}.conn)); puts(mysql_stmt_error($g.sql_stmt_name)); }')
|
|
||||||
*/
|
|
||||||
query := g.new_tmp_var()
|
query := g.new_tmp_var()
|
||||||
res := g.new_tmp_var()
|
res := g.new_tmp_var()
|
||||||
fields := g.new_tmp_var()
|
fields := g.new_tmp_var()
|
||||||
/*
|
|
||||||
g.writeln('Option_mysql__Result $res = mysql__Connection_real_query(&$db_name, $stmt_name);')
|
g.writeln('int $query = mysql_real_query(${db_name}.conn, ${g.sql_stmt_name}.str, ${g.sql_stmt_name}.len);')
|
||||||
g.writeln('if (${res}.state != 0) { IError err = ${res}.err; _STR("Something went wrong\\000%.*s", 2, IError_str(err)); }')
|
|
||||||
g.writeln('Array_mysql__Row ${res}_rows = mysql__Result_rows(*(mysql__Result*)${res}.data);')*/
|
|
||||||
g.writeln('int $query = mysql_real_query(${db_name}.conn, ${stmt_name}.str, ${stmt_name}.len);')
|
|
||||||
g.writeln('if ($query != 0) { puts(mysql_error(${db_name}.conn)); }')
|
g.writeln('if ($query != 0) { puts(mysql_error(${db_name}.conn)); }')
|
||||||
g.writeln('MYSQL_RES* $res = mysql_store_result(${db_name}.conn);')
|
g.writeln('MYSQL_RES* $res = mysql_store_result(${db_name}.conn);')
|
||||||
g.writeln('MYSQL_ROW $fields = mysql_fetch_row($res);')
|
g.writeln('MYSQL_ROW $fields = mysql_fetch_row($res);')
|
||||||
|
@ -577,10 +541,7 @@ fn (mut g Gen) mysql_select_expr(node ast.SqlExpr, sub bool, line string, typ Sq
|
||||||
g.writeln('if ($char_ptr == NULL) { $char_ptr = ""; }')
|
g.writeln('if ($char_ptr == NULL) { $char_ptr = ""; }')
|
||||||
name := g.table.get_type_symbol(field.typ).cname
|
name := g.table.get_type_symbol(field.typ).cname
|
||||||
if g.table.get_type_symbol(field.typ).kind == .struct_ {
|
if g.table.get_type_symbol(field.typ).kind == .struct_ {
|
||||||
/*
|
g.writeln('//parse struct start')
|
||||||
id_name := g.new_tmp_var()
|
|
||||||
g.writeln('//parse struct start') //
|
|
||||||
//g.writeln('int $id_name = string_int(tos_clone($fields[$i]));')
|
|
||||||
|
|
||||||
mut expr := node.sub_structs[int(field.typ)]
|
mut expr := node.sub_structs[int(field.typ)]
|
||||||
mut where_expr := expr.where_expr as ast.InfixExpr
|
mut where_expr := expr.where_expr as ast.InfixExpr
|
||||||
|
@ -601,8 +562,7 @@ fn (mut g Gen) mysql_select_expr(node ast.SqlExpr, sub bool, line string, typ Sq
|
||||||
g.sql_stmt_name = tmp_sql_stmt_name
|
g.sql_stmt_name = tmp_sql_stmt_name
|
||||||
g.sql_buf = tmp_sql_buf
|
g.sql_buf = tmp_sql_buf
|
||||||
g.sql_i = tmp_sql_i
|
g.sql_i = tmp_sql_i
|
||||||
g.sql_table_name := tmp_sql_table_name
|
g.sql_table_name = tmp_sql_table_name
|
||||||
*/
|
|
||||||
} else if field.typ == ast.string_type {
|
} else if field.typ == ast.string_type {
|
||||||
g.writeln('${tmp}.$field.name = tos_clone($char_ptr);')
|
g.writeln('${tmp}.$field.name = tos_clone($char_ptr);')
|
||||||
} else if field.typ == ast.byte_type {
|
} else if field.typ == ast.byte_type {
|
||||||
|
@ -618,7 +578,7 @@ fn (mut g Gen) mysql_select_expr(node ast.SqlExpr, sub bool, line string, typ Sq
|
||||||
g.writeln('\t $fields = mysql_fetch_row($res);')
|
g.writeln('\t $fields = mysql_fetch_row($res);')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
g.writeln('string_free(&$stmt_name);')
|
g.writeln('string_free(&$g.sql_stmt_name);')
|
||||||
g.writeln('mysql_free_result($res);')
|
g.writeln('mysql_free_result($res);')
|
||||||
if node.is_array {
|
if node.is_array {
|
||||||
g.writeln('$cur_line ${tmp}_array; ')
|
g.writeln('$cur_line ${tmp}_array; ')
|
||||||
|
@ -649,23 +609,29 @@ fn (mut g Gen) mysql_drop_table(node ast.SqlStmtLine, typ SqlType, db_expr ast.E
|
||||||
g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; eprintln(_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_bind(val string, _ ast.Type) {
|
fn (mut g Gen) mysql_bind(val string, typ ast.Type) {
|
||||||
/*
|
g.write('$g.sql_i')
|
||||||
t := g.mysql_buffer_typ_from_typ(typ)
|
|
||||||
mut sym := g.table.get_type_symbol(typ).cname
|
mut sym := g.table.get_type_symbol(typ).cname
|
||||||
if typ == ast.string_type {
|
g.sql_buf.write_string('$g.sql_stmt_name = string_replace($g.sql_stmt_name, _SLIT("?$g.sql_i"), ')
|
||||||
sym = 'char *'
|
if sym != 'string' {
|
||||||
|
mut num := false
|
||||||
|
if sym != 'bool' {
|
||||||
|
num = true
|
||||||
|
g.sql_buf.write_string('${sym}_str(')
|
||||||
|
}
|
||||||
|
g.sql_buf.write_string('(($sym) $val)')
|
||||||
|
|
||||||
|
if sym == 'bool' {
|
||||||
|
g.sql_buf.write_string('? _SLIT("1") : _SLIT("0")')
|
||||||
|
}
|
||||||
|
|
||||||
|
if num {
|
||||||
|
g.sql_buf.write_string(')')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.sql_buf.write_string('string_add(_SLIT("\'"), string_add(((string) $val), _SLIT("\'")))')
|
||||||
}
|
}
|
||||||
tmp := g.new_tmp_var()
|
g.sql_buf.writeln(');')
|
||||||
g.sql_buf.writeln('$sym $tmp = $val;')
|
|
||||||
g.sql_buf.writeln('$g.sql_bind_name[${g.sql_i - 1}].buffer_type = $t;')
|
|
||||||
g.sql_buf.writeln('$g.sql_bind_name[${g.sql_i - 1}].buffer = ($sym*) &$tmp;')
|
|
||||||
if sym == 'char *' {
|
|
||||||
g.sql_buf.writeln('$g.sql_bind_name[${g.sql_i - 1}].buffer_length = ${val}.len;')
|
|
||||||
}
|
|
||||||
g.sql_buf.writeln('$g.sql_bind_name[${g.sql_i - 1}].is_null = 0;')
|
|
||||||
g.sql_buf.writeln('$g.sql_bind_name[${g.sql_i - 1}].length = 0;')*/
|
|
||||||
g.write(val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) mysql_get_table_type(typ ast.Type) string {
|
fn (mut g Gen) mysql_get_table_type(typ ast.Type) string {
|
||||||
|
@ -1114,6 +1080,7 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin
|
||||||
mut create_string := 'CREATE TABLE IF NOT EXISTS $lit$table_name$lit ('
|
mut create_string := 'CREATE TABLE IF NOT EXISTS $lit$table_name$lit ('
|
||||||
|
|
||||||
mut fields := []string{}
|
mut fields := []string{}
|
||||||
|
mut unique_fields := []string{}
|
||||||
|
|
||||||
mut primary := '' // for mysql
|
mut primary := '' // for mysql
|
||||||
mut unique := map[string][]string{}
|
mut unique := map[string][]string{}
|
||||||
|
@ -1124,6 +1091,7 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin
|
||||||
mut no_null := false
|
mut no_null := false
|
||||||
mut is_unique := false
|
mut is_unique := false
|
||||||
mut is_skip := false
|
mut is_skip := false
|
||||||
|
mut unique_len := 0
|
||||||
for attr in field.attrs {
|
for attr in field.attrs {
|
||||||
match attr.name {
|
match attr.name {
|
||||||
'primary' {
|
'primary' {
|
||||||
|
@ -1132,10 +1100,16 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin
|
||||||
}
|
}
|
||||||
'unique' {
|
'unique' {
|
||||||
if attr.arg != '' {
|
if attr.arg != '' {
|
||||||
unique[attr.arg] << name
|
if attr.kind == .string {
|
||||||
} else {
|
unique[attr.arg] << name
|
||||||
is_unique = true
|
continue
|
||||||
|
} else if attr.kind == .number {
|
||||||
|
unique_len = attr.arg.int()
|
||||||
|
is_unique = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
is_unique = true
|
||||||
}
|
}
|
||||||
'nonull' {
|
'nonull' {
|
||||||
no_null = true
|
no_null = true
|
||||||
|
@ -1177,7 +1151,20 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin
|
||||||
stmt += ' NOT NULL'
|
stmt += ' NOT NULL'
|
||||||
}
|
}
|
||||||
if is_unique {
|
if is_unique {
|
||||||
stmt += ' UNIQUE'
|
if typ == .mysql {
|
||||||
|
mut f := 'UNIQUE KEY($lit$name$lit'
|
||||||
|
if converted_typ == 'TEXT' {
|
||||||
|
if unique_len > 0 {
|
||||||
|
f += '($unique_len)'
|
||||||
|
} else {
|
||||||
|
f += '($c.default_unique_str_len)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f += ')'
|
||||||
|
unique_fields << f
|
||||||
|
} else {
|
||||||
|
stmt += ' UNIQUE'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if is_primary && typ == .sqlite3 {
|
if is_primary && typ == .sqlite3 {
|
||||||
stmt += ' PRIMARY KEY'
|
stmt += ' PRIMARY KEY'
|
||||||
|
@ -1196,6 +1183,7 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin
|
||||||
if typ == .mysql || typ == .psql {
|
if typ == .mysql || typ == .psql {
|
||||||
fields << 'PRIMARY KEY($lit$primary$lit)'
|
fields << 'PRIMARY KEY($lit$primary$lit)'
|
||||||
}
|
}
|
||||||
|
fields << unique_fields
|
||||||
create_string += fields.join(', ')
|
create_string += fields.join(', ')
|
||||||
create_string += ');'
|
create_string += ');'
|
||||||
return create_string
|
return create_string
|
||||||
|
|
Loading…
Reference in New Issue