1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

orm: fix mysql substructs (#9930)

This commit is contained in:
Louis Schmieder 2021-04-29 20:00:17 +02:00 committed by GitHub
parent ea0ac09297
commit b15156d465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 83 deletions

View File

@ -19,7 +19,13 @@ struct User {
}
fn main() {
db := sqlite.connect(':memory:') or { panic(err) }
sqlite3()
mysql()
psql()
}
fn sqlite3() {
mut db := sqlite.connect(':memory:') or { panic(err) }
sql db {
create table Module
}
@ -46,9 +52,7 @@ fn main() {
}
eprintln(modul)
// mysql()
psql()
db.close() or { panic(err) }
}
fn mysql() {
@ -82,7 +86,9 @@ fn mysql() {
m := sql conn {
select from Module where id == 1
}
eprintln(m)
conn.close()
}
fn psql() {
@ -117,4 +123,5 @@ fn psql() {
}
eprintln(modul)
db.close()
}

View File

@ -22,7 +22,7 @@ pub enum ConnectionFlag {
// TODO: Documentation
pub struct Connection {
mut:
conn &C.MYSQL = C.mysql_init(0)
conn &C.MYSQL = C.mysql_init(0)
pub mut:
host string = '127.0.0.1'
port u32 = 3306
@ -35,7 +35,7 @@ pub mut:
// connect - create a new connection to the MySQL server.
pub fn (mut conn Connection) connect() ?bool {
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)
if isnil(conn.conn) {
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()` can be used for statements containing binary data.
// (Binary data may contain the `\0` character, which `query()`
// interprets as the end of the statement string). In addition,
// (Binary data may contain the `\0` character, which `query()`
// interprets as the end of the statement string). In addition,
// `real_query()` is faster than `query()`.
pub fn (mut conn Connection) real_query(q string) ?Result {
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.
// The `s` argument is encoded to produce an escaped SQL string,
// taking into account the current character set of the connection.
// The `s` argument is encoded to produce an escaped SQL string,
// taking into account the current character set of the connection.
pub fn (conn &Connection) escape_string(s string) string {
unsafe {
to := malloc(2 * s.len + 1)
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
}
// 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.
pub fn (mut conn Connection) refresh(options u32) ?bool {
if C.mysql_refresh(conn.conn, options) != 0 {
@ -166,7 +166,7 @@ pub fn (mut conn Connection) reset() ?bool {
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.
pub fn (mut conn Connection) ping() ?bool {
if C.mysql_ping(conn.conn) != 0 {

View File

@ -8,7 +8,8 @@ import v.util
// pg,mysql etc
const (
dbtype = 'sqlite'
dbtype = 'sqlite'
default_unique_str_len = 256
)
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()
g.sql_buf = strings.new_builder(100)
g.writeln(binds)
// g.writeln('mysql_stmt_attr_set($g.sql_stmt_name, STMT_ATTR_ARRAY_SIZE, 1);')
res := g.new_tmp_var()
g.writeln('int $res = mysql_stmt_bind_param($g.sql_stmt_name, $bind);')
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.writeln(';')
stmt_name := g.new_tmp_var()
g.sql_idents = []string{}
g.sql_idents_types = []ast.Type{}
g.write('char* ${stmt_name}_raw = "')
g.write('string $g.sql_stmt_name = _SLIT("')
g.write(g.get_base_sql_select_query(node, typ))
g.sql_expr_defaults(node, typ)
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.writeln('");')
g.write('array_push((array*)&$vals, _MOV((string[]){string_clone(')
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()
rplc := g.sql_buf.str()
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()
res := 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('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('int $query = mysql_real_query(${db_name}.conn, ${g.sql_stmt_name}.str, ${g.sql_stmt_name}.len);')
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_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 = ""; }')
name := g.table.get_type_symbol(field.typ).cname
if g.table.get_type_symbol(field.typ).kind == .struct_ {
/*
id_name := g.new_tmp_var()
g.writeln('//parse struct start') //
//g.writeln('int $id_name = string_int(tos_clone($fields[$i]));')
g.writeln('//parse struct start')
mut expr := node.sub_structs[int(field.typ)]
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_buf = tmp_sql_buf
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 {
g.writeln('${tmp}.$field.name = tos_clone($char_ptr);')
} 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('}')
}
g.writeln('string_free(&$stmt_name);')
g.writeln('string_free(&$g.sql_stmt_name);')
g.writeln('mysql_free_result($res);')
if node.is_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))); }')
}
fn (mut g Gen) mysql_bind(val string, _ ast.Type) {
/*
t := g.mysql_buffer_typ_from_typ(typ)
fn (mut g Gen) mysql_bind(val string, typ ast.Type) {
g.write('$g.sql_i')
mut sym := g.table.get_type_symbol(typ).cname
if typ == ast.string_type {
sym = 'char *'
g.sql_buf.write_string('$g.sql_stmt_name = string_replace($g.sql_stmt_name, _SLIT("?$g.sql_i"), ')
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('$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)
g.sql_buf.writeln(');')
}
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 fields := []string{}
mut unique_fields := []string{}
mut primary := '' // for mysql
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 is_unique := false
mut is_skip := false
mut unique_len := 0
for attr in field.attrs {
match attr.name {
'primary' {
@ -1132,10 +1100,16 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin
}
'unique' {
if attr.arg != '' {
unique[attr.arg] << name
} else {
is_unique = true
if attr.kind == .string {
unique[attr.arg] << name
continue
} else if attr.kind == .number {
unique_len = attr.arg.int()
is_unique = true
continue
}
}
is_unique = true
}
'nonull' {
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'
}
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 {
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 {
fields << 'PRIMARY KEY($lit$primary$lit)'
}
fields << unique_fields
create_string += fields.join(', ')
create_string += ');'
return create_string