From 98505207c4d4de49af1d0bb1373cdd64e9487cac Mon Sep 17 00:00:00 2001 From: youyuanwu <48816116+youyuanwu@users.noreply.github.com> Date: Tue, 1 Jun 2021 01:10:27 -0700 Subject: [PATCH] mssql: support orm create and drop table (#10296) --- vlib/mssql/config.v | 9 ++++- vlib/mssql/mssql.v | 5 ++- vlib/v/gen/c/sql.v | 80 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/vlib/mssql/config.v b/vlib/mssql/config.v index e93da104c6..7f26d6f91d 100644 --- a/vlib/mssql/config.v +++ b/vlib/mssql/config.v @@ -6,8 +6,15 @@ pub: server string uid string pwd string + // if dbname empty, conn str will not contain Database info, + // and it is up to the server to choose which db to connect to. + dbname string } pub fn (cfg Config) get_conn_str() string { - return 'Driver=$cfg.driver;Server=$cfg.server;UID=$cfg.uid;PWD=$cfg.pwd' + mut str := 'Driver=$cfg.driver;Server=$cfg.server;UID=$cfg.uid;PWD=$cfg.pwd' + if cfg.dbname != '' { + str += ';Database=$cfg.dbname' + } + return str } diff --git a/vlib/mssql/mssql.v b/vlib/mssql/mssql.v index be8cab8a1d..a885e4b8da 100644 --- a/vlib/mssql/mssql.v +++ b/vlib/mssql/mssql.v @@ -114,7 +114,10 @@ fn extract_error(fnName string, handle C.SQLHANDLE, tp C.SQLSMALLINT) string { // add driver error string if ret == C.SQLRETURN(C.SQL_SUCCESS) || ret == C.SQLRETURN(C.SQL_SUCCESS_WITH_INFO) { unsafe { - err_str += ':odbc=$(&sql_state[0]).vstring():$i:${int(native_error)}:$(&message_text[0]).vstring()\n' + state_str := (&sql_state[0]).vstring() + native_error_code := int(native_error) + txt_str := (&message_text[0]).vstring() + err_str += '\n\todbc=$state_str:$i:$native_error_code:$txt_str' } } } diff --git a/vlib/v/gen/c/sql.v b/vlib/v/gen/c/sql.v index 353d57c889..bc168cdb25 100644 --- a/vlib/v/gen/c/sql.v +++ b/vlib/v/gen/c/sql.v @@ -21,6 +21,7 @@ enum SqlType { sqlite3 mysql psql + mssql unknown } @@ -68,6 +69,9 @@ fn (mut g Gen) sql_create_table(node ast.SqlStmtLine, expr ast.Expr) { .psql { g.psql_create_table(node, typ, expr) } + .mssql { + g.mssql_create_table(node, typ, expr) + } else { verror('This database type `$typ` is not implemented yet in orm') // TODO add better error } @@ -86,6 +90,9 @@ fn (mut g Gen) sql_drop_table(node ast.SqlStmtLine, expr ast.Expr) { .psql { g.psql_drop_table(node, typ, expr) } + .mssql { + g.mssql_drop_table(node, typ, expr) + } else { verror('This database type `$typ` is not implemented yet in orm') // TODO add better error } @@ -137,6 +144,9 @@ fn (mut g Gen) sql_type_from_v(typ SqlType, v_typ ast.Type) string { .psql { return g.psql_get_table_type(v_typ) } + .mssql { + return g.mssql_get_table_type(v_typ) + } else { // add error } @@ -1131,6 +1141,66 @@ fn (mut g Gen) psql_bind(val string, typ ast.Type) { g.sql_buf.writeln(');') } +// mssql + +fn (mut g Gen) mssql_create_table(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) { + g.writeln('// mssql table creator') + create_string := g.table_gen(node, typ, db_expr) + tmp := g.new_tmp_var() + g.write('Option_mssql__Result $tmp = mssql__Connection_query(&') + g.expr(db_expr) + g.writeln(', _SLIT("$create_string"));') + + tmp_str := 'str_intp(1, _MOV((StrIntpData[]){{_SLIT("Something went wrong: "), $si_s_code ,{.d_s=IError_str(err)}}}))' + g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; eprintln($tmp_str); }') +} + +fn (mut g Gen) mssql_drop_table(node ast.SqlStmtLine, typ SqlType, db_expr ast.Expr) { + table_name := g.get_table_name(node.table_expr) + g.writeln('// mssql table drop') + lit := '\\"' + drop_string := 'DROP TABLE $lit$table_name$lit;' + tmp := g.new_tmp_var() + g.write('Option_mssql__Result $tmp = mssql__Connection_query(&') + g.expr(db_expr) + g.writeln(', _SLIT("$drop_string"));') + + tmp_str := 'str_intp(1, _MOV((StrIntpData[]){{_SLIT("Something went wrong: "), $si_s_code ,{.d_s=IError_str(err)}}}))' + g.writeln('if (${tmp}.state != 0) { IError err = ${tmp}.err; eprintln($tmp_str); }') +} + +fn (mut g Gen) mssql_get_table_type(typ ast.Type) string { + mut table_typ := '' + match typ { + ast.i8_type, ast.byte_type, ast.bool_type { + table_typ = 'TINYINT' + } + ast.i16_type, ast.u16_type { + table_typ = 'SMALLINT' + } + ast.int_type, ast.u32_type { + table_typ = 'INT' + } + ast.i64_type, ast.u64_type { + table_typ = 'BIGINT' + } + ast.f32_type { + table_typ = 'FLOAT(24)' + } + ast.f64_type { + table_typ = 'FLOAT(53)' + } + ast.string_type { + table_typ = 'TEXT' + } + -1 { + table_typ = 'INT IDENTITY' + } + else {} + } + return table_typ +} + // utils fn (mut g Gen) sql_select_arr(field ast.StructField, node ast.SqlExpr, primary string, tmp string) { @@ -1336,10 +1406,15 @@ fn (mut g Gen) table_gen(node ast.SqlStmtLine, typ SqlType, expr ast.Expr) strin struct_data := typ_sym.struct_info() table_name := g.get_table_name(node.table_expr) mut lit := '`' - if typ == .psql { + if typ == .psql || typ == .mssql { lit = '\\"' } + mut create_string := 'CREATE TABLE IF NOT EXISTS $lit$table_name$lit (' + if typ == .mssql { + // mssql detecting create if not exist is awkward + create_string = 'IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=\'$table_name\' and xtype=\'U\') CREATE TABLE $lit$table_name$lit (' + } mut fields := []string{} mut unique_fields := []string{} @@ -1641,6 +1716,9 @@ fn (mut g Gen) parse_db_from_type_string(name string) SqlType { 'pg.DB' { return .psql } + 'mssql.Connection' { + return .mssql + } else { return .unknown }