| 1 | // vtest build: started_mssql? |
| 2 | module main |
| 3 | |
| 4 | import db.mssql |
| 5 | import os |
| 6 | import time |
| 7 | |
| 8 | const default_mssql_conn_str = 'Driver={FreeTDS};Server=127.0.0.1;Port=1433;UID=sa;PWD=Vlang12345678!;Database=master;TDS_Version=7.4;ClientCharset=UTF-8' |
| 9 | |
| 10 | fn test_config_get_conn_str() { |
| 11 | assert mssql.Config{ |
| 12 | driver: 'ODBC Driver 18 for SQL Server' |
| 13 | server: 'tcp:localhost' |
| 14 | uid: 'sa' |
| 15 | pwd: 'secret' |
| 16 | dbname: 'master' |
| 17 | }.get_conn_str() == 'Driver={ODBC Driver 18 for SQL Server};Server=tcp:localhost;UID=sa;PWD=secret;Database=master' |
| 18 | assert mssql.Config{ |
| 19 | driver: 'FreeTDS' |
| 20 | server: '127.0.0.1' |
| 21 | port: 1433 |
| 22 | user: 'sa' |
| 23 | password: 'secret' |
| 24 | options: { |
| 25 | 'ClientCharset': 'UTF-8' |
| 26 | 'TDS_Version': '7.4' |
| 27 | } |
| 28 | }.get_conn_str() == 'Driver=FreeTDS;Server=127.0.0.1;Port=1433;UID=sa;PWD=secret;ClientCharset=UTF-8;TDS_Version=7.4' |
| 29 | assert mssql.Config{ |
| 30 | dsn: 'Reporting DB' |
| 31 | user: 'sa' |
| 32 | password: 'secret' |
| 33 | dbname: 'master' |
| 34 | options: { |
| 35 | 'Encrypt': 'yes' |
| 36 | 'TrustServerCertificate': 'yes' |
| 37 | } |
| 38 | }.get_conn_str() == 'DSN={Reporting DB};UID=sa;PWD=secret;Database=master;Encrypt=yes;TrustServerCertificate=yes' |
| 39 | assert mssql.Config{ |
| 40 | conn_str: 'DSN=Accounting;Trusted_Connection=Yes' |
| 41 | driver: 'ignored' |
| 42 | }.get_conn_str() == 'DSN=Accounting;Trusted_Connection=Yes' |
| 43 | } |
| 44 | |
| 45 | fn test_row_helpers() { |
| 46 | row := mssql.Row{ |
| 47 | vals: ['1', 'alice'] |
| 48 | } |
| 49 | assert row.val(0) == '1' |
| 50 | assert row.val(1) == 'alice' |
| 51 | assert row.values() == ['1', 'alice'] |
| 52 | } |
| 53 | |
| 54 | fn test_connection_and_query() { |
| 55 | $if !network ? { |
| 56 | eprintln('> Skipping test ${@FN}, since `-d network` is not passed.') |
| 57 | eprintln('> This test requires a working sql server running on localhost.') |
| 58 | return |
| 59 | } |
| 60 | |
| 61 | mut conn := connect_with_retry()! |
| 62 | defer { |
| 63 | conn.close() |
| 64 | } |
| 65 | |
| 66 | conn.query("if object_id('vlang_mssql_test', 'U') is not null drop table vlang_mssql_test") or {} |
| 67 | defer { |
| 68 | conn.query("if object_id('vlang_mssql_test', 'U') is not null drop table vlang_mssql_test") or {} |
| 69 | } |
| 70 | |
| 71 | create_result := conn.query('create table vlang_mssql_test ( |
| 72 | id int identity(1,1) primary key, |
| 73 | name varchar(32) not null |
| 74 | )')! |
| 75 | assert create_result.rows == []mssql.Row{} |
| 76 | |
| 77 | first_insert := conn.query("insert into vlang_mssql_test (name) values ('alice')")! |
| 78 | assert first_insert.rows == []mssql.Row{} |
| 79 | assert first_insert.num_rows_affected == 1 |
| 80 | |
| 81 | second_insert := conn.query("insert into vlang_mssql_test (name) values ('bob')")! |
| 82 | assert second_insert.rows == []mssql.Row{} |
| 83 | assert second_insert.num_rows_affected == 1 |
| 84 | |
| 85 | result := conn.query('select id, name from vlang_mssql_test order by id')! |
| 86 | assert result.rows == [ |
| 87 | mssql.Row{ |
| 88 | vals: ['1', 'alice'] |
| 89 | }, |
| 90 | mssql.Row{ |
| 91 | vals: ['2', 'bob'] |
| 92 | }, |
| 93 | ] |
| 94 | } |
| 95 | |
| 96 | fn connect_with_retry() !mssql.Connection { |
| 97 | conn_str := os.getenv_opt('VMSSQL_CONN_STR') or { default_mssql_conn_str } |
| 98 | mut last_err := 'could not connect to sql server' |
| 99 | for _ in 0 .. 30 { |
| 100 | mut conn := mssql.Connection{} |
| 101 | if _ := conn.connect(conn_str) { |
| 102 | // SQL Server can accept a connection before it is ready to execute statements. |
| 103 | if _ := conn.query('select 1') { |
| 104 | return conn |
| 105 | } else { |
| 106 | last_err = err.msg() |
| 107 | conn.close() |
| 108 | } |
| 109 | } else { |
| 110 | last_err = err.msg() |
| 111 | } |
| 112 | time.sleep(2 * time.second) |
| 113 | } |
| 114 | return error(last_err) |
| 115 | } |
| 116 | |