static void TestName(int index, const char *expected_name) { char name[128]; char buf[256]; SQLSMALLINT len, type; #define NAME_TEST \ do { \ if (strcmp(name, expected_name) != 0) \ { \ sprintf(buf, "wrong name in column %d expected '%s' got '%s'", index, expected_name, name); \ ODBC_REPORT_ERROR(buf); \ } \ } while(0) /* retrieve with SQLDescribeCol */ CHKDescribeCol(index, (SQLCHAR *) name, sizeof(name), &len, &type, NULL, NULL, NULL, "S"); NAME_TEST; /* retrieve with SQLColAttribute */ CHKColAttribute(index, SQL_DESC_NAME, name, sizeof(name), &len, NULL, "S"); if (odbc_db_is_microsoft()) NAME_TEST; CHKColAttribute(index, SQL_DESC_LABEL, name, sizeof(name), &len, NULL, "S"); NAME_TEST; }
int main(int argc, char **argv) { odbc_use_version3 = 1; odbc_connect(); odbc_command("create table #test_output (id int, msg text)"); Test("?", SQL_INTEGER, "?", SQL_LONGVARCHAR); Test("123", SQL_INTEGER, "?", SQL_LONGVARCHAR); Test("?", SQL_INTEGER, "'foo'", SQL_LONGVARCHAR); Test("?", SQL_INTEGER, "?", SQL_VARCHAR); /* * Sybase cannot pass this test without complicated query parsing. * Query with blob columns cannot be prepared so prepared query must * be emulated loosing column informations from server and Sybase do * not convert implicitly VARCHAR to INT */ if (odbc_db_is_microsoft()) Test("?", SQL_VARCHAR, "?", SQL_LONGVARCHAR); else ++test_num; odbc_disconnect(); return 0; }
int main(void) { int i; char cmd[128 + 110*10]; printf("SQLWCHAR size is: %d\n", (int) sizeof(SQLWCHAR)); odbc_use_version3 = 1; odbc_connect(); /* this test do not work with Sybase */ if (!odbc_db_is_microsoft()) { odbc_disconnect(); return 0; } strcpy(cmd, "create procedure #proc_longerror as\nbegin\nraiserror('"); for (i = 0; i < 110; ++i) strcat(cmd, "reallylong"); strcat(cmd, " error', 16, 1)\nend\n"); odbc_command(cmd); CHKR2(SQLExecDirectW, (odbc_stmt, odbc_get_sqlwchar(&odbc_buf, "{CALL #proc_longerror}"), SQL_NTS), SQL_HANDLE_STMT, odbc_stmt, "E"); extract_error(odbc_stmt, SQL_HANDLE_STMT); odbc_disconnect(); return 0; }
static void Test(const char *query) { CHKPrepare(T(query), SQL_NTS, "S"); CHKExecute("S"); CHKFetch("SI"); CHKFetch("No"); /* * Microsoft SQL Server 2000 provides a diagnostic record * associated with the second SQLFetch (which returns * SQL_NO_DATA) saying "Warning: Null value is eliminated by * an aggregate or other SET operation." * We check for "NO DM" cause unixODBC till 2.2.11 do not read * errors on SQL_NO_DATA */ if (odbc_db_is_microsoft() && tds_no_dm) { SQLTCHAR output[256]; CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, NULL, NULL, output, ODBC_VECTOR_SIZE(output), NULL, "SI"); printf("Message: %s\n", C(output)); } odbc_reset_statement(); }
int main(int argc, char *argv[]) { SQLSMALLINT len; const char * const*p; SQLINTEGER n; if (odbc_read_login_info()) exit(1); /* connect string using DSN */ init_connect(); sprintf(tmp, "DSN=%s;UID=%s;PWD=%s;DATABASE=%s;ClientCharset=UTF-8;", odbc_server, odbc_user, odbc_password, odbc_database); CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); if (!odbc_driver_is_freetds()) { odbc_disconnect(); printf("Driver is not FreeTDS, exiting\n"); return 0; } if (!odbc_db_is_microsoft() || odbc_db_version_int() < 0x08000000u) { odbc_disconnect(); printf("Test for MSSQL only\n"); return 0; } CHKAllocStmt(&odbc_stmt, "S"); /* create test table */ sprintf(tmp, "IF OBJECT_ID(N'%s') IS NOT NULL DROP TABLE %s", table_name, table_name); odbc_command(tmp); sprintf(tmp, "CREATE TABLE %s (k int, c NCHAR(10), vc NVARCHAR(10))", table_name); odbc_command(tmp); /* insert with INSERT statements */ for (n = 1, p = strings; p[0] && p[1]; p += 2, ++n) { sprintf(tmp, "INSERT INTO %s VALUES (%d,N'%s',N'%s')", table_name, (int) n, p[0], p[1]); odbc_command(tmp); } /* check rows */ for (n = 1, p = strings_hex; p[0] && p[1]; p += 2, ++n) { sprintf(tmp, "IF NOT EXISTS(SELECT * FROM %s WHERE k = %d AND c = %s AND vc = %s) SELECT 1", table_name, (int) n, p[0], p[1]); CheckNoRow(tmp); } TestBinding(0); TestBinding(1); /* cleanup */ sprintf(tmp, "IF OBJECT_ID(N'%s') IS NOT NULL DROP TABLE %s", table_name, table_name); odbc_command(tmp); odbc_disconnect(); printf("Done.\n"); return 0; }
int main(int argc, char *argv[]) { odbc_use_version3 = 1; odbc_connect(); if (odbc_db_is_microsoft()) { /* all successes */ test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?, ?)"); multiply = 1; query_test(0, SQL_SUCCESS, "VVVVVVVVVV"); multiply = 1; query_test(1, SQL_SUCCESS, "VVVVVVVVVV"); /* all errors */ test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?, ?)"); multiply = 257; query_test(0, SQL_ERROR, "!!!!!!!!!!"); multiply = 257; query_test(1, SQL_SUCCESS_WITH_INFO, "!!!!!!!!!!"); test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?, ?)"); query_test(0, SQL_ERROR, "VV!!!!!!!!"); query_test(1, SQL_SUCCESS_WITH_INFO, "VV!!!!!!!!"); test_query = T("INSERT INTO #tmp1 (id, value) VALUES (900-?, ?)"); query_test(0, SQL_SUCCESS_WITH_INFO, "!!!!!!!VVV"); query_test(1, SQL_SUCCESS_WITH_INFO, "!!!!!!!VVV"); test_query = T("INSERT INTO #tmp1 (id) VALUES (?) UPDATE #tmp1 SET value = ?"); query_test(0, SQL_SUCCESS_WITH_INFO, "VVVV!V!V!V"); query_test(1, SQL_SUCCESS_WITH_INFO, "VV!!!!!!!!"); #ifdef ENABLE_DEVELOPING /* with result, see how SQLMoreResult work */ test_query = T("INSERT INTO #tmp1 (id) VALUES (?) SELECT * FROM #tmp1 UPDATE #tmp1 SET value = ?"); /* IMHO our driver is better here -- freddy77 */ query_test(0, SQL_SUCCESS, odbc_driver_is_freetds() ? "VVVVV!V!V!" : "VVVVVV!VVV"); query_test(1, SQL_SUCCESS, "VVVVVVVVVV"); #endif } else { /* Sybase test for conversions before executing */ test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?/8, ?)"); query_test(0, SQL_SUCCESS, "VVVVVVVVVV"); } /* TODO record binding, array fetch, sqlputdata */ odbc_disconnect(); printf(failure ? "Failed :(\n" : "Success!\n"); return failure; }
/** initialize booleans, call after connection */ void odbc_init_bools(void) { int big_endian = 1; if (((char *) &big_endian)[0] == 1) big_endian = 0; odbc_set_bool("bigendian", big_endian); odbc_set_bool("msdb", odbc_db_is_microsoft()); odbc_set_bool("freetds", odbc_driver_is_freetds()); }
/* stripped down version of TestInput for NULLs */ static void NullInput(SQLSMALLINT out_c_type, SQLSMALLINT out_sql_type, const char *param_type) { char sbuf[1024]; SQLLEN out_len = SQL_NULL_DATA; odbc_reset_statement(); /* create a table with a column of that type */ odbc_reset_statement(); sprintf(sbuf, "CREATE TABLE #tmp_insert (col %s NULL)", param_type); odbc_command(sbuf); if (use_cursors) { odbc_reset_statement(); CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0, "S"); CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S"); } /* insert data using prepared statements */ sprintf(sbuf, "INSERT INTO #tmp_insert VALUES(?)"); if (exec_direct) { CHKBindParameter(1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, NULL, 1, &out_len, "S"); CHKExecDirect(T(sbuf), SQL_NTS, "SNo"); } else { if (prepare_before) CHKPrepare(T(sbuf), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, NULL, 1, &out_len, "S"); if (!prepare_before) CHKPrepare(T(sbuf), SQL_NTS, "S"); CHKExecute("SNo"); } /* check if row is present */ odbc_reset_statement(); if (!odbc_db_is_microsoft() && strcmp(param_type, "TEXT") == 0) odbc_command("SELECT * FROM #tmp_insert WHERE col LIKE ''"); else odbc_command("SELECT * FROM #tmp_insert WHERE col IS NULL"); CHKFetch("S"); CHKFetch("No"); CHKMoreResults("No"); odbc_command("DROP TABLE #tmp_insert"); ODBC_FREE(); }
static void Test(int use_sql) { odbc_command_with_result(odbc_stmt, "DROP TABLE #a"); odbc_command("CREATE TABLE #a(x int)"); odbc_command("INSERT INTO #a VALUES(123)"); Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT x AS i, c FROM #test, #a"); Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c FROM #test"); if (odbc_db_is_microsoft()) { Test0(use_sql, "CREATE TABLE #test(i int identity(1,1), c varchar(6))", "INSERT INTO #test(c) VALUES('%s')", "SELECT i, c FROM #test"); Test0(use_sql, "CREATE TABLE #test(i int primary key, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c FROM #test"); } Test0(use_sql, "CREATE TABLE #test(i int, c varchar(6))", "INSERT INTO #test(c, i) VALUES('%s', %d)", "SELECT i, c, c + 'xxx' FROM #test"); }
int main(int argc, char *argv[]) { odbc_connect(); odbc_check_cursor(); if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u) mssql2005 = 1; Test(1); Test(0); odbc_disconnect(); return 0; }
static void Test2(int nocount, int second_select) { char sql[512]; g_nocount = nocount; g_second_select = second_select; /* this test do not work with Sybase */ if (!odbc_db_is_microsoft()) return; sprintf(sql, create_proc, nocount ? " SET NOCOUNT ON\n" : "", second_select ? " SELECT 'Here is the last row' AS LastResult\n" : ""); odbc_command(sql); Test(5); Test(11); odbc_command("DROP PROC #tmp1"); }
static void Test(int prebind) { ODBC_BUF *odbc_buf = NULL; SQLLEN ind; int i; char buf[100]; /* build a string longer than 80 character (80 it's the default) */ buf[0] = 0; for (i = 0; i < 21; ++i) strcat(buf, "miao"); odbc_command("DELETE FROM #tmp1"); CHKAllocStmt(&stmt, "S"); SWAP_STMT(stmt); if (prebind) CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 1, 0, buf, 1, &ind, "S"); CHKPrepare(T("INSERT INTO #tmp1(c) VALUES(?)"), SQL_NTS, "S"); /* try to insert an empty string, should not fail */ /* NOTE this is currently the only test for insert a empty string using rpc */ if (odbc_db_is_microsoft()) TestInsert(""); TestInsert("a"); TestInsert("bb"); TestInsert(buf); CHKFreeStmt(SQL_DROP, "S"); odbc_stmt = SQL_NULL_HSTMT; SWAP_STMT(stmt); ODBC_FREE(); }
int main(int argc, char *argv[]) { SQLINTEGER input, output; SQLLEN ind, ind2, ind3, ind4; SQLINTEGER out1; char out2[30]; odbc_connect(); odbc_command("IF OBJECT_ID('simpleresult') IS NOT NULL DROP PROC simpleresult"); odbc_command("create proc simpleresult @i int as begin return @i end"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S"); CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S"); CHKPrepare(T("{ \n?\t\r= call simpleresult(?)}"), SQL_NTS, "S"); input = 123; ind2 = sizeof(input); output = 0xdeadbeef; CHKExecute("S"); if (output != 123) { printf("Invalid result\n"); exit(1); } /* should return "Invalid cursor state" */ if (SQLFetch(odbc_stmt) != SQL_ERROR) { printf("Data not expected\n"); exit(1); } ODBC_CHECK_COLS(0); /* just to reset some possible buffers */ odbc_command("DECLARE @i INT"); /* same test but with SQLExecDirect and same bindings */ input = 567; ind2 = sizeof(input); output = 0xdeadbeef; CHKExecDirect(T("{?=call simpleresult(?)}"), SQL_NTS, "S"); if (output != 567) { fprintf(stderr, "Invalid result\n"); exit(1); } /* should return "Invalid cursor state" */ CHKFetch("E"); odbc_command("drop proc simpleresult"); odbc_command("IF OBJECT_ID('simpleresult2') IS NOT NULL DROP PROC simpleresult2"); /* force cursor close */ SQLCloseCursor(odbc_stmt); /* test output parameter */ odbc_command("create proc simpleresult2 @i int, @x int output, @y varchar(20) output as begin select @x = 6789 select @y = 'test foo' return @i end"); CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S"); CHKBindParameter(3, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &out1, 0, &ind3, "S"); CHKBindParameter(4, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 20, 0, out2, sizeof(out2), &ind4, "S"); CHKPrepare(T("{ \n?\t\r= call simpleresult2(?,?,?)}"), SQL_NTS, "S"); input = 987; ind2 = sizeof(input); out1 = 888; output = 0xdeadbeef; ind3 = SQL_DATA_AT_EXEC; ind4 = SQL_DEFAULT_PARAM; strcpy(out2, "bad!"); CHKExecute("S"); if (output != 987 || ind3 <= 0 || ind4 <= 0 || out1 != 6789 || strcmp(out2, "test foo") != 0) { printf("ouput = %d ind3 = %d ind4 = %d out1 = %d out2 = %s\n", (int) output, (int) ind3, (int) ind4, (int) out1, out2); printf("Invalid result\n"); exit(1); } /* should return "Invalid cursor state" */ CHKFetch("E"); ODBC_CHECK_COLS(0); odbc_command("drop proc simpleresult2"); /* * test from shiv kumar * Cfr ML 2006-11-21 "specifying a 0 for the StrLen_or_IndPtr in the * SQLBindParameter call is not working on AIX" */ odbc_command("IF OBJECT_ID('rpc_read') IS NOT NULL DROP PROC rpc_read"); odbc_reset_statement(); odbc_command("create proc rpc_read @i int, @x timestamp as begin select 1 return 1234 end"); SQLCloseCursor(odbc_stmt); CHKPrepare(T("{ ? = CALL rpc_read ( ?, ? ) }"), SQL_NTS, "S"); ind = 0; CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S"); ind2 = 0; CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S"); ind3 = 8; CHKBindParameter(3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, 8, 0, out2, 8, &ind3, "S"); CHKExecute("S"); CHKFetch("S"); CHKFetch("No"); odbc_reset_statement(); odbc_command("drop proc rpc_read"); /* * Test from Joao Amaral * This test SQLExecute where a store procedure returns no result * This seems similar to a previous one but use set instead of select * (with is supported only by mssql and do not return all stuff as * select does) */ if (odbc_db_is_microsoft()) { odbc_reset_statement(); odbc_command("IF OBJECT_ID('sp_test') IS NOT NULL DROP PROC sp_test"); odbc_command("create proc sp_test @res int output as set @res = 456"); odbc_reset_statement(); CHKPrepare(T("{ call sp_test(?)}"), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S"); output = 0xdeadbeef; CHKExecute("S"); if (output != 456) { fprintf(stderr, "Invalid result %d(%x)\n", (int) output, (int) output); return 1; } odbc_command("drop proc sp_test"); } odbc_disconnect(); if (odbc_db_is_microsoft()) test_with_conversions(); printf("Done.\n"); return 0; }
static void AllTests(void) { struct tm *ltime; char buf[80]; time_t curr_time; SQLINTEGER y, m, d; char date[128]; printf("use_cursors %d exec_direct %d prepare_before %d\n", use_cursors, exec_direct, prepare_before); /* test some NULLs */ NullInput(SQL_C_CHAR, SQL_VARCHAR, "VARCHAR(100)"); NullInput(SQL_C_CHAR, SQL_LONGVARCHAR, "TEXT"); NullInput(SQL_C_LONG, SQL_INTEGER, "INTEGER"); NullInput(SQL_C_LONG, SQL_LONGVARCHAR, "TEXT"); NullInput(SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, "DATETIME"); NullInput(SQL_C_FLOAT, SQL_REAL, "FLOAT"); NullInput(SQL_C_NUMERIC, SQL_LONGVARCHAR, "TEXT"); if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) NullInput(SQL_C_BIT, SQL_BIT, "BIT"); NullInput(SQL_C_DOUBLE, SQL_DOUBLE, "MONEY"); /* FIXME why should return 38 0 as precision and scale ?? correct ?? */ precision = 18; TestOutput("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "18 0 1 7B"); TestOutput("DECIMAL(18,2)", "123", SQL_C_NUMERIC, SQL_DECIMAL, "18 0 1 7B"); precision = 38; TestOutput("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "38 0 1 7B"); TestInput(SQL_C_LONG, "INTEGER", SQL_VARCHAR, "VARCHAR(20)", "12345"); TestInput(SQL_C_LONG, "INTEGER", SQL_LONGVARCHAR, "TEXT", "12345"); /* * MS driver behavior for output parameters is different * former returns "313233" while newer "333133323333" */ if (odbc_driver_is_freetds()) TestOutput("VARCHAR(20)", "313233", SQL_C_BINARY, SQL_VARCHAR, "333133323333"); only_test = 1; precision = 3; if (TestOutput("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ssssssl", 2004, 2, 24, 15, 16, 17, 0))) { /* FIXME our driver ignore precision for date */ precision = 3; /* Some MS driver incorrectly prepare with smalldatetime*/ if (!use_cursors || odbc_driver_is_freetds()) { TestOutput("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ll", 0x9497, 0xFBAA2C)); } TestOutput("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ll", 0x9497, 0xFB9640)); } else { TestOutput("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ssssssl", 2004, 2, 24, 15, 16, 0, 0)); } TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34"); /* test timestamp millisecond round off */ TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.001 -> 2005-07-22 09:51:34.000"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.002 -> 2005-07-22 09:51:34.003"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.003 -> 2005-07-22 09:51:34.003"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.004 -> 2005-07-22 09:51:34.003"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.005 -> 2005-07-22 09:51:34.007"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.006 -> 2005-07-22 09:51:34.007"); /* FIXME on ms driver first SQLFetch return SUCCESS_WITH_INFO for truncation error */ TestInput(SQL_C_TYPE_DATE, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 13:02:03 -> 2005-07-22 00:00:00"); /* replace date information with current date */ time(&curr_time); ltime = localtime(&curr_time); y = ltime->tm_year + 1900; m = ltime->tm_mon + 1; d = ltime->tm_mday; /* server concept of data can be different so try ask to server */ odbc_command("SELECT GETDATE()"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, date, sizeof(date), NULL); if (SQLFetch(odbc_stmt) == SQL_SUCCESS) { int a, b, c; if (sscanf(date, "%d-%d-%d", &a, &b, &c) == 3) { y = a; m = b; d = c; } } SQLFetch(odbc_stmt); SQLMoreResults(odbc_stmt); SQLFreeStmt(odbc_stmt, SQL_UNBIND); sprintf(buf, "2003-07-22 13:02:03 -> %04d-%02d-%02d 13:02:03", (int) y, (int) m, (int) d); TestInput(SQL_C_TYPE_TIME, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", buf); TestInput(SQL_C_FLOAT, "FLOAT", SQL_REAL, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "REAL", SQL_REAL, "FLOAT", "-1234.25"); TestInput(SQL_C_FLOAT, "REAL", SQL_REAL, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "FLOAT", SQL_REAL, "FLOAT", "-1234.25"); TestInput(SQL_C_FLOAT, "FLOAT", SQL_FLOAT, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "REAL", SQL_FLOAT, "FLOAT", "-1234.25"); TestInput(SQL_C_FLOAT, "FLOAT", SQL_DOUBLE, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "REAL", SQL_DOUBLE, "FLOAT", "-1234.25"); TestInput(SQL_C_UTINYINT, "TINYINT", SQL_TINYINT, "TINYINT", "231"); TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_NUMERIC, "NUMERIC(20,3)", "765432.2 -> 765432"); TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_VARCHAR, "VARCHAR(20)", "578246.234 -> 578246"); TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_LONGVARCHAR, "TEXT", "578246.234 -> 578246"); TestInput(SQL_C_CHAR, "VARCHAR(100)", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_CHAR, "TEXT", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_CHAR, "VARCHAR(100)", SQL_LONGVARBINARY, "IMAGE", "4145544F -> AETO"); TestInput(SQL_C_BINARY, "VARBINARY(100)", SQL_VARCHAR, "VARCHAR(20)", "0x4145544F -> AETO"); TestInput(SQL_C_BINARY, "IMAGE", SQL_VARCHAR, "VARCHAR(20)", "0x4145544F -> AETO"); TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "0"); TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "1"); TestInput(SQL_C_DOUBLE, "MONEY", SQL_DOUBLE, "MONEY", "123.34"); TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_VARCHAR, "VARCHAR(20)", "1EasyTest"); TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "TEXT", "1EasyTest"); TestInput(SQL_C_WCHAR, "VARCHAR(10)", SQL_VARCHAR, "VARCHAR(10)", "Test 12345"); TestInput(SQL_C_WCHAR, "VARCHAR(10)", SQL_LONGVARCHAR, "TEXT", "Test 12345"); /* TODO use collate in syntax if available */ TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_VARCHAR, "VARCHAR(20)", "me\xf4"); TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "TEXT", "me\xf4"); precision = 6; /* output from char with conversions */ TestOutput("VARCHAR(20)", "foo test", SQL_C_CHAR, SQL_VARCHAR, "6 foo te"); /* TODO use collate in sintax if available */ TestOutput("VARCHAR(20)", "0xf8f9", SQL_C_CHAR, SQL_VARCHAR, "2 \xf8\xf9"); if ((odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u && odbc_tds_version() > 0x700) || (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0)) { TestOutput("BIGINT", "-987654321065432", SQL_C_BINARY, SQL_BIGINT, big_endian ? "FFFC7DBBCF083228" : "283208CFBB7DFCFF"); TestInput(SQL_C_SBIGINT, "BIGINT", SQL_BIGINT, "BIGINT", "-12345678901234"); } if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) { TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "test"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "test"); /* test for invalid stream due to truncation*/ TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "01234567890"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "01234567890"); #ifdef ENABLE_DEVELOPING check_truncation = 1; TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "012345678901234567890"); check_truncation = 1; TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "012345678901234567890"); #endif TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "\xa3h\xf9 -> 0xA3006800f900"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "\xa3h\xf9 -> 0xA3006800f900"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "0xA3006800f900 -> \xa3h\xf9"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "0xA3006800f900 -> \xa3h\xf9"); TestInput(SQL_C_LONG, "INT", SQL_WVARCHAR, "NVARCHAR(100)", "45236"); TestInput(SQL_C_LONG, "INT", SQL_WLONGVARCHAR, "NTEXT", "45236"); precision = 6; TestOutput("NVARCHAR(20)", "foo test", SQL_C_CHAR, SQL_WVARCHAR, "6 foo te"); precision = 12; TestOutput("NVARCHAR(20)", "foo test", SQL_C_CHAR, SQL_WVARCHAR, "8 foo test"); /* TODO use collate in sintax if available */ TestOutput("NVARCHAR(20)", "0xf800f900", SQL_C_CHAR, SQL_WVARCHAR, "2 \xf8\xf9"); TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WVARCHAR, "NVARCHAR(10)", "1EasyTest2"); TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WLONGVARCHAR, "NTEXT", "1EasyTest2"); use_nts = 1; TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WVARCHAR, "NVARCHAR(10)", "1EasyTest3"); use_nts = 1; TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WLONGVARCHAR, "NTEXT", "1EasyTest3"); TestInput(SQL_C_WCHAR, "NVARCHAR(3)", SQL_WVARCHAR, "NVARCHAR(3)", "0xf800a300bc06"); TestInput(SQL_C_WCHAR, "NVARCHAR(3)", SQL_WLONGVARCHAR, "NTEXT", "0xf800a300bc06"); TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_INTEGER, "INT", " -423785 -> -423785"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_CHAR, "NTEXT", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_BINARY, "VARBINARY(100)", SQL_WVARCHAR, "NVARCHAR(20)", "0x4100450054004F00 -> AETO"); TestInput(SQL_C_BINARY, "IMAGE", SQL_WVARCHAR, "NVARCHAR(20)", "0x4100450054004F00 -> AETO"); } if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u) { TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "VARCHAR(MAX)", "1EasyTest"); TestInput(SQL_C_BINARY, "VARBINARY(20)", SQL_LONGVARBINARY, "VARBINARY(MAX)", "Anything will suite!"); } }
int main(int argc, char *argv[]) { int big_endian = 1; int test_2008_date_to_binary = 0; odbc_connect(); if (((char *) &big_endian)[0] == 1) big_endian = 0; Test("NUMERIC(18,2)", "123", SQL_C_NUMERIC, "38 0 1 7B"); /* all binary results */ /* cases (2) */ Test("CHAR(7)", "pippo", SQL_C_BINARY, "706970706F2020"); Test("TEXT", "mickey", SQL_C_BINARY, "6D69636B6579"); Test("VARCHAR(20)", "foo", SQL_C_BINARY, "666F6F"); Test("BINARY(5)", "qwer", SQL_C_BINARY, "7177657200"); Test("IMAGE", "cricetone", SQL_C_BINARY, "6372696365746F6E65"); Test("VARBINARY(20)", "teo", SQL_C_BINARY, "74656F"); /* TODO only MS ?? */ if (odbc_db_is_microsoft()) Test("TIMESTAMP", "abcdefghi", SQL_C_BINARY, "6162636465666768"); Test("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, big_endian ? "0000949700FBAA2C" : "979400002CAAFB00"); Test("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, big_endian ? "94970394" : "97949403"); Test("BIT", "1", SQL_C_BINARY, "01"); Test("BIT", "0", SQL_C_BINARY, "00"); Test("TINYINT", "231", SQL_C_BINARY, "E7"); Test("SMALLINT", "4321", SQL_C_BINARY, big_endian ? "10E1" : "E110"); Test("INT", "1234567", SQL_C_BINARY, big_endian ? "0012D687" : "87D61200"); if ((odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) || (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0)) { int old_result = result; Test("BIGINT", "123456789012345", SQL_C_BINARY, big_endian ? "00007048860DDF79" : "79DF0D8648700000"); if (result && strcmp(sbuf, "13000179DF0D86487000000000000000000000") == 0) { fprintf(stderr, "Ignore previous error. You should configure TDS 7.1 for this!!!\n"); if (!old_result) result = 0; } } Test("INT", "-123", SQL_C_CHAR, "4 -123"); Test("INT", "78654", SQL_C_WCHAR, "5 78654"); Test("VARCHAR(10)", " 51245 ", SQL_C_LONG, "51245"); Test("VARCHAR(20)", " 15.1245 ", SQL_C_NUMERIC, "38 0 1 0F"); Test("VARCHAR(20)", " 15 ", SQL_C_NUMERIC, "38 0 1 0F"); if (odbc_db_is_microsoft() && (strncmp(odbc_db_version(), "08.00.", 6) == 0 || strncmp(odbc_db_version(), "09.00.", 6) == 0)) { /* nvarchar without extended characters */ Test("NVARCHAR(20)", "test", SQL_C_CHAR, "4 test"); /* nvarchar with extended characters */ /* don't test with MS which usually have a not compatible encoding */ if (odbc_driver_is_freetds()) Test("NVARCHAR(20)", "0x830068006900f200", SQL_C_CHAR, "4 \x83hi\xf2"); Test("VARCHAR(20)", "test", SQL_C_WCHAR, "4 test"); /* nvarchar with extended characters */ Test("NVARCHAR(20)", "0x830068006900f200", SQL_C_WCHAR, "4 \x83hi\xf2"); Test("NVARCHAR(20)", "0xA406A5FB", SQL_C_WCHAR, "2 \\u06a4\\ufba5"); /* NVARCHAR -> SQL_C_LONG */ Test("NVARCHAR(20)", "-24785 ", SQL_C_LONG, "-24785"); } ignore_select_error = 1; Test("UNIVARCHAR(10)", "u&'\\06A4\\FBA5'", SQL_C_WCHAR, "2 \\u06a4\\ufba5"); /* case (1) */ Test("DECIMAL", "1234.5678", SQL_C_BINARY, "120001D3040000000000000000000000000000"); Test("NUMERIC", "8765.4321", SQL_C_BINARY, "1200013D220000000000000000000000000000"); Test("FLOAT", "1234.5678", SQL_C_BINARY, big_endian ? "40934A456D5CFAAD" : "ADFA5C6D454A9340"); Test("REAL", "8765.4321", SQL_C_BINARY, big_endian ? "4608F5BA" : "BAF50846"); Test("SMALLMONEY", "765.4321", SQL_C_BINARY, big_endian ? "0074CBB1" : "B1CB7400"); Test("MONEY", "4321234.5678", SQL_C_BINARY, big_endian ? "0000000A0FA8114E" : "0A0000004E11A80F"); /* behavior is different from MS ODBC */ if (odbc_db_is_microsoft()) { Test("NCHAR(7)", "donald", SQL_C_BINARY, "64006F006E0061006C0064002000"); Test("NTEXT", "duck", SQL_C_BINARY, "6400750063006B00"); Test("NVARCHAR(20)", "daffy", SQL_C_BINARY, "64006100660066007900"); } if (odbc_db_is_microsoft()) Test("UNIQUEIDENTIFIER", "0DDF3B64-E692-11D1-AB06-00AA00BDD685", SQL_C_BINARY, big_endian ? "0DDF3B64E69211D1AB0600AA00BDD685" : "643BDF0D92E6D111AB0600AA00BDD685"); /* case (4) */ Test("DATETIME", "2006-06-09 11:22:44", SQL_C_CHAR, "23 2006-06-09 11:22:44.000"); Test("SMALLDATETIME", "2006-06-12 22:37:21", SQL_C_CHAR, "19 2006-06-12 22:37:00"); Test("DATETIME", "2006-06-09 11:22:44", SQL_C_WCHAR, "23 2006-06-09 11:22:44.000"); Test("SMALLDATETIME", "2006-06-12 22:37:21", SQL_C_WCHAR, "19 2006-06-12 22:37:00"); if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) { Test("SQL_VARIANT", "CAST('123' AS INT)", SQL_C_CHAR, "3 123"); Test("SQL_VARIANT", "CAST('hello' AS CHAR(6))", SQL_C_CHAR, "6 hello "); Test("SQL_VARIANT", "CAST('ciao' AS VARCHAR(10))", SQL_C_CHAR, "4 ciao"); Test("SQL_VARIANT", "CAST('foo' AS NVARCHAR(10))", SQL_C_CHAR, "3 foo"); Test("SQL_VARIANT", "CAST('Super' AS NCHAR(8))", SQL_C_CHAR, "8 Super "); Test("SQL_VARIANT", "CAST('321' AS VARBINARY(10))", SQL_C_CHAR, "6 333231"); /* for some reasons MS ODBC seems to convert -123.4 to -123.40000000000001 */ Test("SQL_VARIANT", "CAST('-123.5' AS FLOAT)", SQL_C_CHAR, "6 -123.5"); Test("SQL_VARIANT", "CAST('-123.4' AS NUMERIC(10,2))", SQL_C_CHAR, "7 -123.40"); Test("SQL_VARIANT", "CAST('0DDF3B64-E692-11D1-AB06-00AA00BDD685' AS UNIQUEIDENTIFIER)", SQL_C_CHAR, "36 0DDF3B64-E692-11D1-AB06-00AA00BDD685"); } if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u) { Test("VARCHAR(MAX)", "goodbye!", SQL_C_CHAR, "8 goodbye!"); Test("NVARCHAR(MAX)", "Micio mao", SQL_C_CHAR, "9 Micio mao"); Test("VARBINARY(MAX)", "ciao", SQL_C_BINARY, "6369616F"); Test("XML", "<a b=\"aaa\"><b>ciao</b>hi</a>", SQL_C_CHAR, "28 <a b=\"aaa\"><b>ciao</b>hi</a>"); /* XML with schema */ odbc_command("IF EXISTS(SELECT * FROM sys.xml_schema_collections WHERE [name] = 'test_schema') DROP XML SCHEMA COLLECTION test_schema"); odbc_command("CREATE XML SCHEMA COLLECTION test_schema AS '<schema xmlns=\"http://www.w3.org/2001/XMLSchema\"><element name=\"test\" type=\"string\"/></schema>'"); Test("XML(test_schema)", "<test>ciao</test>", SQL_C_CHAR, "17 <test>ciao</test>"); odbc_command("DROP XML SCHEMA COLLECTION test_schema"); } /* MSSQL 2008*/ if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x0A000000u) { int save_result = result; /* check right protocol */ result = 0; test_2008_date_to_binary = 1; Test("DATE", "1923-12-02", SQL_C_BINARY, big_endian ? "0783000C0002" : "83070C000200"); if (result) { result = 0; Test("DATE", "1923-12-02", SQL_C_BINARY, "31003900320033002D00310032002D0030003200"); if (!result) { printf("previous error expected: wrong protocol used\n"); test_2008_date_to_binary = 0; } } if (save_result) result = 1; Test("DATE", "1923-12-02", SQL_C_CHAR, "10 1923-12-02"); Test("TIME", "12:23:45", SQL_C_CHAR, "16 12:23:45.0000000"); Test("TIME(4)", "12:23:45.765", SQL_C_CHAR, "13 12:23:45.7650"); Test("TIME(0)", "12:23:45.765", SQL_C_CHAR, "8 12:23:46"); Test("DATETIME2", "2011-08-10 12:23:45", SQL_C_CHAR, "27 2011-08-10 12:23:45.0000000"); Test("DATETIME2(4)", "12:23:45.345888", SQL_C_CHAR, "24 1900-01-01 12:23:45.3459"); Test("DATETIME2(0)", "2011-08-10 12:23:45.93", SQL_C_CHAR, "19 2011-08-10 12:23:46"); Test("DATETIMEOFFSET", "12:23:45 -02:30", SQL_C_CHAR, "34 1900-01-01 12:23:45.0000000 -02:30"); Test("DATETIMEOFFSET(4)", "12:23:45", SQL_C_CHAR, "31 1900-01-01 12:23:45.0000 +00:00"); } if (test_2008_date_to_binary) { Test("DATE", "1923-12-02", SQL_C_BINARY, big_endian ? "0783000C0002" : "83070C000200"); Test("TIME", "12:23:45", SQL_C_BINARY, big_endian ? "000C0017002D000000000000" : "0C0017002D00000000000000"); Test("TIME(4)", "12:23:45.765", SQL_C_BINARY, big_endian ? "000C0017002D00002D98F940" : "0C0017002D00000040F9982D"); Test("DATETIME2", "2011-08-10 12:23:45", SQL_C_BINARY, big_endian ? "07DB0008000A000C0017002D00000000" : "DB0708000A000C0017002D0000000000"); Test("DATETIME2(4)", "12:23:45", SQL_C_BINARY, big_endian ? "076C00010001000C0017002D00000000" : "6C07010001000C0017002D0000000000"); Test("DATETIMEOFFSET", "12:23:45 -08:30", SQL_C_BINARY, big_endian ? "076C00010001000C0017002D00000000FFF8FFE2" : "6C07010001000C0017002D0000000000F8FFE2FF"); Test("DATETIMEOFFSET(4)", "12:23:45", SQL_C_BINARY, big_endian ? "076C00010001000C0017002D0000000000000000" : "6C07010001000C0017002D000000000000000000"); } if (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0) { /* FIXME sure ?? with date and time always ?? */ Test("DATE", "1923-12-02", SQL_C_CHAR, "23 1923-12-02 00:00:00.000"); Test("TIME", "12:23:45", SQL_C_CHAR, "23 1900-01-01 12:23:45.000"); } odbc_disconnect(); if (!result) printf("Done successfully!\n"); return result; }
int main(int argc, char **argv) { SQLRETURN RetCode; SQLHSTMT old_odbc_stmt = SQL_NULL_HSTMT; int i; int key; SQLLEN vind0; int cnt = 2, wide; char sql[256]; test_info *t = NULL; odbc_use_version3 = 1; odbc_connect(); /* tests (W)CHAR/BINARY -> (W)CHAR/BINARY (9 cases) */ add_test(SQL_C_BINARY, SQL_LONGVARCHAR, "TEXT", 123, 1 ); add_test(SQL_C_BINARY, SQL_LONGVARBINARY, "IMAGE", 987, 25); add_test(SQL_C_CHAR, SQL_LONGVARBINARY, "IMAGE", 987, 25); add_test(SQL_C_CHAR, SQL_LONGVARCHAR, "TEXT", 343, 47); add_test(SQL_C_WCHAR, SQL_LONGVARBINARY, "IMAGE", 561, 29); add_test(SQL_C_WCHAR, SQL_LONGVARCHAR, "TEXT", 698, 24); if (odbc_db_is_microsoft()) { add_test(SQL_C_BINARY, SQL_WLONGVARCHAR, "NTEXT", 765, 12); add_test(SQL_C_CHAR, SQL_WLONGVARCHAR, "NTEXT", 237, 71); add_test(SQL_C_WCHAR, SQL_WLONGVARCHAR, "NTEXT", 687, 68); } strcpy(sql, "CREATE TABLE #tt(k INT"); for (t = test_infos; t < test_infos+num_tests; ++t) sprintf(strchr(sql, 0), ",f%u %s", t->num, t->db_type); strcat(sql, ",v INT)"); odbc_command(sql); old_odbc_stmt = odbc_stmt; odbc_stmt = SQL_NULL_HSTMT; /* Insert rows ... */ for (i = 0; i < cnt; i++) { /* MS do not save correctly char -> binary */ if (!odbc_driver_is_freetds() && i) continue; CHKAllocHandle(SQL_HANDLE_STMT, odbc_conn, &odbc_stmt, "S"); strcpy(sql, "INSERT INTO #tt VALUES(?"); for (t = test_infos; t < test_infos+num_tests; ++t) strcat(sql, ",?"); strcat(sql, ",?)"); CHKPrepare(T(sql), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0, "S"); for (t = test_infos; t < test_infos+num_tests; ++t) CHKBindParameter(t->num+1, SQL_PARAM_INPUT, t->c_type, t->sql_type, 0x10000000, 0, t->buf, 0, &t->vind, "S"); CHKBindParameter(num_tests+2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0, "S"); key = i; vind0 = 0; printf(">> insert... %d\n", i); RetCode = CHKExecute("SINe"); while (RetCode == SQL_NEED_DATA) { char *p; RetCode = CHKParamData((SQLPOINTER) & p, "SINe"); printf(">> SQLParamData: ptr = %p RetCode = %d\n", (void *) p, RetCode); if (RetCode == SQL_NEED_DATA) { for (t = test_infos; t < test_infos+num_tests && t->buf != p; ++t) ; assert(t < test_infos+num_tests); if (t->c_type == SQL_C_CHAR || t->c_type == SQL_C_WCHAR) { unsigned char_len = 1; fill_hex(p, NBYTES, t->gen1, t->gen2); if (t->c_type == SQL_C_WCHAR) { char_len = sizeof(SQLWCHAR); odbc_to_sqlwchar((SQLWCHAR*) p, p, NBYTES * 2); } CHKPutData(p, (NBYTES - (i&1)) * char_len, "S"); printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES - (i&1)); CHKPutData(p + (NBYTES - (i&1)) * char_len, (NBYTES + (i&1)) * char_len, "S"); printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES + (i&1)); } else { CHKPutData(p, NBYTES, "S"); printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES); } } } CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S"); odbc_stmt = SQL_NULL_HSTMT; } /* Now fetch rows ... */ for (wide = 0; wide < 2; ++wide) for (i = 0; i < cnt; i++) { /* MS do not save correctly char -> binary */ if (!odbc_driver_is_freetds() && i) continue; CHKAllocHandle(SQL_HANDLE_STMT, odbc_conn, &odbc_stmt, "S"); if (odbc_db_is_microsoft()) { CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_NONSCROLLABLE, SQL_IS_UINTEGER, "S"); CHKSetStmtAttr(SQL_ATTR_CURSOR_SENSITIVITY, (SQLPOINTER) SQL_SENSITIVE, SQL_IS_UINTEGER, "S"); } strcpy(sql, "SELECT "); for (t = test_infos; t < test_infos+num_tests; ++t) sprintf(strchr(sql, 0), "f%u,", t->num); strcat(sql, "v FROM #tt WHERE k = ?"); CHKPrepare(T(sql), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &i, 0, &vind0, "S"); for (t = test_infos; t < test_infos+num_tests; ++t) { t->vind = SQL_DATA_AT_EXEC; CHKBindCol(t->num, SQL_C_BINARY, NULL, 0, &t->vind, "S"); } CHKBindCol(num_tests+1, SQL_C_LONG, &key, 0, &vind0, "S"); vind0 = 0; CHKExecute("S"); CHKFetchScroll(SQL_FETCH_NEXT, 0, "S"); printf(">> fetch... %d\n", i); for (t = test_infos; t < test_infos+num_tests; ++t) { if (t->c_type == SQL_C_CHAR || t->c_type == SQL_C_WCHAR) readBlobAsChar(t, i, wide); else readBlob(t); } CHKCloseCursor("S"); CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S"); odbc_stmt = SQL_NULL_HSTMT; } odbc_stmt = old_odbc_stmt; free_tests(); odbc_disconnect(); if (!failed) printf("ok!\n"); return failed ? 1 : 0; }
int main(int argc, char *argv[]) { odbc_use_version3 = 1; odbc_connect(); /* Invalid argument value */ CHKSetConnectAttr(SQL_ATTR_TXN_ISOLATION, int2ptr(SQL_TXN_REPEATABLE_READ | SQL_TXN_READ_COMMITTED), 0, "E"); ReadErrorConn(); if (strcmp(odbc_sqlstate, "HY024") != 0) { odbc_disconnect(); fprintf(stderr, "Unexpected success\n"); return 1; } /* here we can't use temporary table cause we use two connection */ odbc_command("IF OBJECT_ID('test_transaction') IS NOT NULL DROP TABLE test_transaction"); odbc_command("CREATE TABLE test_transaction(n NUMERIC(18,0) PRIMARY KEY, t VARCHAR(30))"); CHKSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER) 2, 0, "S"); AutoCommit(SQL_AUTOCOMMIT_OFF); odbc_command("INSERT INTO test_transaction(n, t) VALUES(1, 'initial')"); #ifdef ENABLE_DEVELOPING /* test setting with active transaction "Operation invalid at this time" */ CHKSetConnectAttr(SQL_ATTR_TXN_ISOLATION, int2ptr(SQL_TXN_REPEATABLE_READ), 0, "E"); ReadErrorConn(); if (strcmp(odbc_sqlstate, "HY011") != 0) { odbc_disconnect(); fprintf(stderr, "Unexpected success\n"); return 1; } #endif EndTransaction(SQL_COMMIT); odbc_command("SELECT * FROM test_transaction"); /* test setting with pending data */ CHKSetConnectAttr(SQL_ATTR_TXN_ISOLATION, int2ptr(SQL_TXN_REPEATABLE_READ), 0, "E"); ReadErrorConn(); if (strcmp(odbc_sqlstate, "HY011") != 0) { odbc_disconnect(); fprintf(stderr, "Unexpected success\n"); return 1; } SQLMoreResults(odbc_stmt); EndTransaction(SQL_COMMIT); /* save this connection and do another */ SWAP_CONN(); odbc_connect(); CHKSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER) 2, 0, "S"); AutoCommit(SQL_AUTOCOMMIT_OFF); SWAP_CONN(); for (test_with_connect = 0; test_with_connect <= 1; ++test_with_connect) { Test(SQL_TXN_READ_UNCOMMITTED, "dirty 1 non repeatable 1 phantom 1"); Test(SQL_TXN_READ_COMMITTED, "dirty 0 non repeatable 1 phantom 1"); if (odbc_db_is_microsoft()) { Test(SQL_TXN_REPEATABLE_READ, "dirty 0 non repeatable 0 phantom 1"); } else { hide_error = 1; if (!Test(SQL_TXN_REPEATABLE_READ, "dirty 0 non repeatable 0 phantom 1")) Test(SQL_TXN_REPEATABLE_READ, "dirty 0 non repeatable 0 phantom 0"); } Test(SQL_TXN_SERIALIZABLE, "dirty 0 non repeatable 0 phantom 0"); } odbc_disconnect(); SWAP_CONN(); EndTransaction(SQL_COMMIT); /* Sybase do not accept DROP TABLE during a transaction */ AutoCommit(SQL_AUTOCOMMIT_ON); odbc_command("DROP TABLE test_transaction"); odbc_disconnect(); return 0; }
int main(int argc, char *argv[]) { odbc_connect(); /* MSSQL 2012+, compute not supported */ if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x0b000000u) { odbc_disconnect(); return 0; } odbc_command("create table #tmp1 (c varchar(20), i int)"); odbc_command("insert into #tmp1 values('pippo', 12)"); odbc_command("insert into #tmp1 values('pippo', 34)"); odbc_command("insert into #tmp1 values('pluto', 1)"); odbc_command("insert into #tmp1 values('pluto', 2)"); odbc_command("insert into #tmp1 values('pluto', 3)"); /* * TODO skip rows/column on compute (compute.c) * TODO check rows/column after moreresults after compute */ /* select * from #tmp1 compute sum(i) */ SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); odbc_command("select * from #tmp1 order by c, i compute sum(i)"); CheckFetch("c", "pippo", "12"); CheckFetch("c", "pippo", "34"); CheckFetch("c", "pluto", "1"); CheckFetch("c", "pluto", "2"); CheckFetch("c", "pluto", "3"); CHKFetch("No"); CHKMoreResults("S"); /* why I need to rebind ?? ms bug of feature ?? */ SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); col2[0] = '@'; CheckFetch("sum", "52", "@"); CHKFetch("No"); CHKMoreResults("No"); /* select * from #tmp1 order by c compute sum(i) by c */ SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); odbc_command("select c as mao, i from #tmp1 order by c, i compute sum(i) by c compute max(i)"); CheckFetch("mao", "pippo", "12"); CheckFetch("mao", "pippo", "34"); CHKFetch("No"); CHKMoreResults("S"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); strcpy(col2, "##"); CheckFetch("sum", "46", "##"); CHKFetch("No"); CHKMoreResults("S"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); CheckFetch("mao", "pluto", "1"); CheckFetch("mao", "pluto", "2"); CheckFetch("mao", "pluto", "3"); CHKFetch("No"); CHKMoreResults("S"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); strcpy(col2, "%"); CheckFetch("sum", "6", "%"); CHKFetch("No"); CHKMoreResults("S"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); strcpy(col2, "&"); CheckFetch("max", "34", "&"); CHKFetch("No"); CHKMoreResults("No"); /* test skip recordset with computed rows */ /* select * from #tmp1 where i = 2 compute min(i) */ SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); odbc_command("select * from #tmp1 where i = 2 or i = 34 order by c, i compute min(i) by c"); CheckFetch("c", "pippo", "34"); CHKFetch("No"); CHKMoreResults("S"); /* here just skip results, before a row */ CHKMoreResults("S"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, col1, sizeof(col1), &ind1); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, col2, sizeof(col2), &ind2); CheckFetch("c", "pluto", "2"); CHKFetch("No"); CHKMoreResults("S"); /* here just skip results, before done */ CHKMoreResults("No"); odbc_disconnect(); return 0; }
int main(int argc, char *argv[]) { SQLLEN ind; int len = strlen(test_text), n, i; const char *p; char *pp; SQLPOINTER ptr; unsigned char buf[256], *pb; SQLRETURN RetCode; int type, lc, sql_type; odbc_connect(); /* create table to hold data */ odbc_command("CREATE TABLE #putdata (c TEXT NULL, b IMAGE NULL)"); sql_type = SQL_LONGVARCHAR; type = SQL_C_CHAR; lc = 1; for (;;) { CHKBindParameter(1, SQL_PARAM_INPUT, type, sql_type, 0, 0, (SQLPOINTER) 123, 0, &ind, "S"); /* length required */ ind = SQL_LEN_DATA_AT_EXEC(len * lc); /* * test for char */ CHKPrepare(T("INSERT INTO #putdata(c) VALUES(?)"), SQL_NTS, "S"); CHKExecute("Ne"); p = test_text; n = 5; CHKParamData(&ptr, "Ne"); if (ptr != (SQLPOINTER) 123) ODBC_REPORT_ERROR("Wrong pointer from SQLParamData"); while (*p) { int l = strlen(p); if (l < n) n = l; if (type == SQL_C_CHAR) { CHKPutData((char *) p, n, "S"); } else { SQLWCHAR buf[256]; CHKPutData((char *) buf, to_sqlwchar(buf, p, n), "S"); } p += n; n *= 2; } CHKParamData(&ptr, "S"); CHKParamData(&ptr, "E"); /* check state and reset some possible buffers */ odbc_command("DECLARE @i INT"); /* use server ntext if available */ if (sql_type == SQL_LONGVARCHAR && odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) { sql_type = SQL_WLONGVARCHAR; continue; } if (type != SQL_C_CHAR) break; sql_type = SQL_LONGVARCHAR; type = SQL_C_WCHAR; lc = sizeof(SQLWCHAR); } /* update row setting binary field */ for (i = 0; i < 255; ++i) buf[i] = BYTE_AT(i); /* * test for binary */ CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 0, 0, (SQLPOINTER) 4567, 0, &ind, "S"); ind = SQL_LEN_DATA_AT_EXEC(254); CHKPrepare(T("UPDATE #putdata SET b = ?"), SQL_NTS, "S"); CHKExecute("Ne"); pb = buf; n = 7; CHKParamData(&ptr, "Ne"); if (ptr != (SQLPOINTER) 4567) ODBC_REPORT_ERROR("Wrong pointer from SQLParamData"); while (pb != (buf + 254)) { int l = buf + 254 - pb; if (l < n) n = l; CHKPutData((char *) pb, n, "S"); pb += n; n *= 2; } CHKParamData(&ptr, "S"); CHKParamData(&ptr, "E"); /* check state and reset some possible buffers */ odbc_command("DECLARE @i2 INT"); CHKFreeStmt(SQL_RESET_PARAMS, "S"); /* check inserts ... there should be all equal rows */ strcpy(sql, "IF EXISTS(SELECT * FROM #putdata WHERE CONVERT(VARBINARY(255),b) <> 0x"); /* append binary */ for (i = 0; i < 254; ++i) sprintf(strchr(sql, 0), "%02x", buf[i]); strcat(sql, " OR CONVERT(VARCHAR(255),c) <> '"); /* append string */ pp = strchr(sql, 0); p = test_text; do { *pp++ = *p; if (*p == '\'') *pp++ = *p; } while(*p++); strcat(sql, "') SELECT 1"); odbc_check_no_row(sql); odbc_command("DELETE FROM #putdata"); /* test len == 0 case from ML */ type = SQL_C_CHAR; for (;;) { CHKPrepare(T("INSERT INTO #putdata(c) VALUES(?)"), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, type, SQL_LONGVARCHAR, 0, 0, (PTR) 2, 0, &ind, "S"); ind = SQL_LEN_DATA_AT_EXEC(0); RetCode = CHKExecute("Ne"); while (RetCode == SQL_NEED_DATA) { RetCode = SQLParamData(odbc_stmt, &ptr); if (RetCode == SQL_NEED_DATA) { if (type == SQL_C_CHAR) { CHKPutData("abc", 3, "S"); } else { SQLWCHAR buf[10]; CHKPutData(buf, to_sqlwchar(buf, "abc", 3), "S"); } } } if (type != SQL_C_CHAR) break; type = SQL_C_WCHAR; odbc_reset_statement(); } /* check inserts ... */ odbc_check_no_row("IF EXISTS(SELECT * FROM #putdata WHERE c NOT LIKE 'abc') SELECT 1"); odbc_command("DELETE FROM #putdata"); /* test putting 0 bytes from Sebastien Flaesch */ if (odbc_db_is_microsoft()) { type = SQL_C_CHAR; for (;;) { CHKPrepare(T("INSERT INTO #putdata(c) VALUES(?)"), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, type, SQL_LONGVARCHAR, 10, 0, (PTR) 2, 10, &ind, "S"); ind = SQL_DATA_AT_EXEC; RetCode = CHKExecute("Ne"); while (RetCode == SQL_NEED_DATA) { RetCode = SQLParamData(odbc_stmt, &ptr); if (RetCode == SQL_NEED_DATA) CHKPutData("", 0, "S"); } if (type != SQL_C_CHAR) break; type = SQL_C_WCHAR; odbc_reset_statement(); } /* check inserts ... */ odbc_check_no_row("IF EXISTS(SELECT * FROM #putdata WHERE c NOT LIKE '') SELECT 1"); } /* TODO test cancel inside SQLExecute */ odbc_disconnect(); printf("Done.\n"); return 0; }
int main(int argc, char *argv[]) { char tmp[512]; char out[32]; SQLLEN n_len; SQLSMALLINT len; const char * const*p; int n; if (odbc_read_login_info()) exit(1); /* connect string using DSN */ init_connect(); sprintf(tmp, "DSN=%s;UID=%s;PWD=%s;DATABASE=%s;ClientCharset=UTF-8;", odbc_server, odbc_user, odbc_password, odbc_database); CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); if (!odbc_driver_is_freetds()) { odbc_disconnect(); printf("Driver is not FreeTDS, exiting\n"); odbc_test_skipped(); return 0; } if (!odbc_db_is_microsoft() || odbc_db_version_int() < 0x08000000u || odbc_tds_version() < 0x701) { odbc_disconnect(); /* protocol till 7.1 does not support telling encoding so we * cannot understand how the string is encoded */ printf("Test for MSSQL only using protocol 7.1\n"); odbc_test_skipped(); return 0; } CHKAllocStmt(&odbc_stmt, "S"); /* create test table */ odbc_command("CREATE TABLE #tmpHebrew (i INT, v VARCHAR(10) COLLATE Hebrew_CI_AI)"); /* insert with INSERT statements */ for (n = 0, p = strings_hex; p[n]; ++n) { sprintf(tmp, "INSERT INTO #tmpHebrew VALUES(%d, CAST(%s AS NVARCHAR(10)))", n+1, p[n]); odbc_command(tmp); } /* test conversions in libTDS */ odbc_command("SELECT v FROM #tmpHebrew"); /* insert with SQLPrepare/SQLBindParameter/SQLExecute */ CHKBindCol(1, SQL_C_CHAR, out, sizeof(out), &n_len, "S"); for (n = 0, p = strings; p[n]; ++n) { CHKFetch("S"); if (n_len != strlen(p[n]) || strcmp(p[n], out) != 0) { fprintf(stderr, "Wrong row %d %s\n", n, out); odbc_disconnect(); return 1; } } odbc_disconnect(); printf("Done.\n"); return 0; }
int main(int argc, char *argv[]) { char buf[32]; SQLINTEGER int_buf; SQLLEN len; SQLRETURN rc; odbc_connect(); lc = 1; type = SQL_C_CHAR; test_split(""); lc = sizeof(SQLWCHAR); type = SQL_C_WCHAR; test_split(""); if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x07000000u) { lc = 1; type = SQL_C_CHAR; test_split("N"); lc = sizeof(SQLWCHAR); type = SQL_C_WCHAR; test_split("N"); } /* test with fixed length */ odbc_command("SELECT CONVERT(INT, 12345)"); CHKFetch("S"); int_buf = 0xdeadbeef; CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "S"); if (int_buf != 12345) { printf("Wrong data result\n"); exit(1); } CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "No"); if (int_buf != 12345) { printf("Wrong data result 2 res = %d\n", (int) int_buf); exit(1); } odbc_reset_statement(); /* test with numeric */ odbc_command("SELECT CONVERT(NUMERIC(18,5), 1850000000000)"); CHKFetch("S"); memset(buf, 'x', sizeof(buf)); CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "S"); buf[sizeof(buf)-1] = 0; if (strcmp(buf, "1850000000000") != 0) { printf("Wrong data result: %s\n", buf); exit(1); } /* should give NO DATA */ CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "No"); buf[sizeof(buf)-1] = 0; if (strcmp(buf, "1850000000000") != 0) { printf("Wrong data result 3 res = %s\n", buf); exit(1); } odbc_reset_statement(); /* test int to truncated string */ odbc_command("SELECT CONVERT(INTEGER, 12345)"); CHKFetch("S"); /* error 22003 */ memset(buf, 'x', sizeof(buf)); CHKGetData(1, SQL_C_CHAR, buf, 4, NULL, "E"); #ifdef ENABLE_DEVELOPING buf[4] = 0; if (strcmp(buf, "xxxx") != 0) { fprintf(stderr, "Wrong buffer result buf = %s\n", buf); exit(1); } #endif odbc_read_error(); if (strcmp(odbc_sqlstate, "22003") != 0) { fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate); odbc_disconnect(); exit(1); } CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No"); odbc_reset_statement(); /* test unique identifier to truncated string */ rc = odbc_command2("SELECT CONVERT(UNIQUEIDENTIFIER, 'AA7DF450-F119-11CD-8465-00AA00425D90')", "SENo"); if (rc != SQL_ERROR) { CHKFetch("S"); /* error 22003 */ CHKGetData(1, SQL_C_CHAR, buf, 17, NULL, "E"); odbc_read_error(); if (strcmp(odbc_sqlstate, "22003") != 0) { fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate); odbc_disconnect(); exit(1); } CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No"); } odbc_reset_statement(); odbc_disconnect(); odbc_use_version3 = 1; odbc_connect(); /* test error from SQLGetData */ /* wrong constant, SQL_VARCHAR is invalid as C type */ test_err("prova 123", SQL_VARCHAR, "HY003"); /* use ARD but no ARD data column */ test_err("prova 123", SQL_ARD_TYPE, "07009"); /* wrong conversion, int */ test_err("prova 123", SQL_C_LONG, "22018"); /* wrong conversion, date */ test_err("prova 123", SQL_C_TIMESTAMP, "22018"); /* overflow */ test_err("1234567890123456789", SQL_C_LONG, "22003"); /* test for empty string from mssql */ if (odbc_db_is_microsoft()) { lc = 1; type = SQL_C_CHAR; for (;;) { void *buf = ODBC_GET(lc); odbc_command("SELECT CONVERT(TEXT,'')"); CHKFetch("S"); len = 1234; CHKGetData(1, type, buf, lc, &len, "S"); if (len != 0) { fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len); return 1; } CHKGetData(1, type, buf, lc, NULL, "No"); odbc_reset_statement(); ODBC_FREE(); buf = ODBC_GET(4096*lc); odbc_command("SELECT CONVERT(TEXT,'')"); CHKFetch("S"); len = 1234; CHKGetData(1, type, buf, lc*4096, &len, "S"); if (len != 0) { fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len); return 1; } CHKGetData(1, type, buf, lc*4096, NULL, "No"); odbc_reset_statement(); ODBC_FREE(); if (type != SQL_C_CHAR) break; lc = sizeof(SQLWCHAR); type = SQL_C_WCHAR; } odbc_command("SELECT CONVERT(TEXT,'')"); CHKFetch("S"); len = 1234; CHKGetData(1, SQL_C_BINARY, buf, 1, &len, "S"); if (len != 0) { fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len); return 1; } CHKGetData(1, SQL_C_BINARY, buf, 1, NULL, "No"); } odbc_disconnect(); printf("Done.\n"); return 0; }
static void DoTest(int version3) { char name[128], params[128]; SQLSMALLINT type, is_unsigned; SQLINTEGER col_size, min_scale; SQLLEN ind1, ind2, ind3, ind4, ind5, ind6; int date_time_supported = 0; int name_version3; odbc_use_version3 = version3; name_version3 = version3; odbc_connect(); printf("Using ODBC version %d\n", version3 ? 3 : 2); /* test column name */ /* MS ODBC use always ODBC 3 names even in ODBC 2 mode */ if (!odbc_driver_is_freetds()) name_version3 = 1; CHKGetTypeInfo(SQL_ALL_TYPES, "SI"); TestName(1, "TYPE_NAME"); TestName(2, "DATA_TYPE"); TestName(3, name_version3 ? "COLUMN_SIZE" : "PRECISION"); TestName(4, "LITERAL_PREFIX"); TestName(5, "LITERAL_SUFFIX"); TestName(6, "CREATE_PARAMS"); TestName(7, "NULLABLE"); TestName(8, "CASE_SENSITIVE"); TestName(9, "SEARCHABLE"); TestName(10, "UNSIGNED_ATTRIBUTE"); TestName(11, name_version3 ? "FIXED_PREC_SCALE" : "MONEY"); TestName(12, name_version3 ? "AUTO_UNIQUE_VALUE" : "AUTO_INCREMENT"); TestName(13, "LOCAL_TYPE_NAME"); TestName(14, "MINIMUM_SCALE"); TestName(15, "MAXIMUM_SCALE"); /* TODO test these column for ODBC 3 */ /* ODBC 3.0 SQL_DATA_TYPE SQL_DATETIME_SUB NUM_PREC_RADIX INTERVAL_PRECISION */ Flushodbc_stmt(); /* TODO test if SQL_ALL_TYPES returns right numeric type for timestamp */ /* numeric type for data */ /* test for date/time support */ if (odbc_command_with_result(odbc_stmt, "select cast(getdate() as date)") == SQL_SUCCESS) date_time_supported = 1; SQLCloseCursor(odbc_stmt); #define CHECK_TYPE(in,out) CheckType(in, out, #in, __LINE__) /* under Sybase this type require extra handling, check it */ CHECK_TYPE(SQL_VARCHAR, SQL_VARCHAR); CHECK_TYPE(SQL_DATE, date_time_supported && !version3 ? SQL_DATE : SQL_UNKNOWN_TYPE); CHECK_TYPE(SQL_TIME, date_time_supported && !version3 ? SQL_TIME : SQL_UNKNOWN_TYPE); /* MS ODBC returns S1004 (HY004), TODO support it */ if (odbc_driver_is_freetds() || version3) { CHECK_TYPE(SQL_TYPE_DATE, date_time_supported && version3 ? SQL_TYPE_DATE : SQL_UNKNOWN_TYPE); CHECK_TYPE(SQL_TYPE_TIME, date_time_supported && version3 ? SQL_TYPE_TIME : SQL_UNKNOWN_TYPE); } /* TODO MS ODBC handle SQL_TIMESTAMP even for ODBC 3 */ if (odbc_driver_is_freetds()) CHECK_TYPE(SQL_TIMESTAMP, version3 ? SQL_UNKNOWN_TYPE : SQL_TIMESTAMP); else CHECK_TYPE(SQL_TIMESTAMP, version3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP); /* MS ODBC returns S1004 (HY004), TODO support it */ if (odbc_driver_is_freetds() || version3) { CHECK_TYPE(SQL_TYPE_TIMESTAMP, version3 ? SQL_TYPE_TIMESTAMP : SQL_UNKNOWN_TYPE); } /* TODO implement this part of test */ /* varchar/nvarchar before sysname */ /* test binding (not all column, required for Oracle) */ CHKGetTypeInfo(SQL_ALL_TYPES, "SI"); CHKBindCol(1, SQL_C_CHAR, name, sizeof(name), &ind1, "SI"); CHKBindCol(2, SQL_C_SSHORT, &type, 0, &ind2, "SI"); CHKBindCol(3, SQL_C_SLONG, &col_size, 0, &ind3, "SI"); CHKBindCol(6, SQL_C_CHAR, params, sizeof(params), &ind4, "SI"); CHKBindCol(10, SQL_C_SSHORT, &is_unsigned, 0, &ind5, "SI"); CHKBindCol(14, SQL_C_SSHORT, &min_scale, 0, &ind6, "SI"); while (CHKFetch("SNo") == SQL_SUCCESS) ; SQLFreeStmt(odbc_stmt, SQL_UNBIND); Flushodbc_stmt(); /* check WVARCHAR for no pending data */ if (odbc_db_is_microsoft() || strncmp(odbc_db_version(), "15.00.", 6) >= 0) { CHKGetTypeInfo(SQL_WVARCHAR, "SI"); CHKFetch("S"); if (odbc_db_is_microsoft()) CHKFetch("S"); CHKFetch("No"); CHKGetTypeInfo(SQL_BINARY, "SI"); } odbc_disconnect(); }