int main(int argc, char *argv[]) { odbc_use_version3 = 1; odbc_connect(); if (((char *) &big_endian)[0] == 1) big_endian = 0; for (use_cursors = 0; use_cursors <= 1; ++use_cursors) { if (use_cursors) { if (!tds_no_dm || !odbc_driver_is_freetds()) odbc_reset_statement(); odbc_check_cursor(); } exec_direct = 1; AllTests(); exec_direct = 0; prepare_before = 1; AllTests(); prepare_before = 0; AllTests(); } odbc_disconnect(); printf("Done successfully!\n"); return 0; }
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; }
/** 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()); }
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; }
int odbc_tds_version(void) { static int tds_version = -1; ODBC_BUF *odbc_buf = NULL; SQLUINTEGER version; SQLSMALLINT len; if (odbc_driver_is_freetds() && tds_version < 0) { version = 0; len = 0; SQLGetInfo(odbc_conn, 1300 /* SQL_INFO_FREETDS_TDS_VERSION */, &version, sizeof(version), &len); if (len == sizeof(version)) tds_version = (version >> 16) << 8 | (version & 0xff); }
int odbc_tds_version(void) { static int tds_version = -1; ODBC_BUF *odbc_buf = NULL; SQLTCHAR buf[64]; SQLSMALLINT len; if (!odbc_driver_is_freetds()) return 0; if (tds_version < 0) { unsigned M, m; buf[0] = 0; SQLGetInfo(odbc_conn, 1300 /* SQL_INFO_FREETDS_TDS_VERSION */, buf, sizeof(buf), &len); if (sscanf(C(buf), "%u.%u", &M, &m) == 2) tds_version = M * 0x100u + m; } ODBC_FREE(); return tds_version < 0 ? 0: tds_version; }
static int TestOutput(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, SQLSMALLINT out_sql_type, const char *expected) { char sbuf[1024]; unsigned char out_buf[256]; SQLLEN out_len = 0; const char *sep; odbc_reset_statement(); /* build store procedure to test */ odbc_command("IF OBJECT_ID('spTestProc') IS NOT NULL DROP PROC spTestProc"); sep = "'"; if (strncmp(value_to_convert, "0x", 2) == 0) sep = ""; sprintf(sbuf, "CREATE PROC spTestProc @i %s OUTPUT AS SELECT @i = CONVERT(%s, %s%s%s)", type, type, sep, value_to_convert, sep); odbc_command(sbuf); memset(out_buf, 0, sizeof(out_buf)); 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"); } /* bind parameter */ if (exec_direct) { CHKBindParameter(1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, precision, 0, out_buf, sizeof(out_buf), &out_len, "S"); /* call store procedure */ CHKExecDirect(T("{call spTestProc(?)}"), SQL_NTS, "S"); } else { if (prepare_before) CHKPrepare(T("{call spTestProc(?)}"), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, precision, 0, out_buf, sizeof(out_buf), &out_len, "S"); if (!prepare_before) CHKPrepare(T("{call spTestProc(?)}"), SQL_NTS, "S"); CHKExecute("S"); } /* * MS OBDC requires it cause first recordset is a recordset with a * warning caused by the way it execute RPC (via EXEC statement) */ if (use_cursors && !odbc_driver_is_freetds()) SQLMoreResults(odbc_stmt); /* test results */ odbc_c2string(sbuf, out_c_type, out_buf, out_len); if (strcmp(sbuf, expected) != 0) { if (only_test) { odbc_command("drop proc spTestProc"); ODBC_FREE(); return 1; } fprintf(stderr, "Wrong result\n Got: %s\n Expected: %s\n", sbuf, expected); exit(1); } only_test = 0; odbc_command("drop proc spTestProc"); ODBC_FREE(); 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) { 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; }
static void Test(int level) { SQLRETURN result; SQLSMALLINT InParam = level; SQLSMALLINT OutParam = 1; SQLLEN cbReturnCode = 0, cbInParam = 0, cbOutParam = 0; SQLLEN cbOutString = SQL_NTS; char sql[80]; printf("ODBC %d nocount %s select %s level %d\n", odbc_use_version3 ? 3 : 2, g_nocount ? "yes" : "no", g_second_select ? "yes" : "no", level); ReturnCode = INVALID_RETURN; memset(&OutString, 0, sizeof(OutString)); /* test with SQLExecDirect */ sprintf(sql, "RAISERROR('An error occurred.', %d, 1)", level); result = odbc_command_with_result(odbc_stmt, sql); TestResult(result, level, "SQLExecDirect"); /* test with SQLPrepare/SQLExecute */ if (!SQL_SUCCEEDED(SQLPrepare(odbc_stmt, T(SP_TEXT), strlen(SP_TEXT)))) { fprintf(stderr, "SQLPrepare failure!\n"); exit(1); } SQLBindParameter(odbc_stmt, 1, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &ReturnCode, 0, &cbReturnCode); SQLBindParameter(odbc_stmt, 2, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &InParam, 0, &cbInParam); SQLBindParameter(odbc_stmt, 3, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &OutParam, 0, &cbOutParam); strcpy(OutString, "Invalid!"); SQLBindParameter(odbc_stmt, 4, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, OUTSTRING_LEN, 0, OutString, OUTSTRING_LEN, &cbOutString); CHKExecute("S"); /* first select, check data are returned. * SET statements before does not affect results */ CheckData(""); CHKFetch("S"); CheckData("Here is the first row"); result = SQLFetch(odbc_stmt); if (odbc_use_version3) { SQLTCHAR SqlState[6]; SQLINTEGER NativeError; SQLTCHAR MessageText[1000]; SQLSMALLINT TextLength; SQLRETURN expected; SQLLEN rows; if (result != SQL_NO_DATA) ODBC_REPORT_ERROR("SQLFetch should return NO DATA"); CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, SqlState, &NativeError, MessageText, ODBC_VECTOR_SIZE(MessageText), &TextLength, "No"); result = SQLMoreResults(odbc_stmt); expected = level > 10 ? SQL_ERROR : SQL_SUCCESS_WITH_INFO; if (result != expected) ODBC_REPORT_ERROR("SQLMoreResults returned unexpected result"); if (!g_second_select && g_nocount) { if (ReturnCode == INVALID_RETURN) { result = SQLMoreResults(odbc_stmt); } else { CheckReturnCode(result, 0); ReturnCode = INVALID_RETURN; TestResult(result, level, "SQLMoreResults"); ReturnCode = 0; } } else { TestResult(result, level, "SQLMoreResults"); } /* a recordset with only warnings/errors do not contains rows */ if (CHKRowCount(&rows, "SE") == SQL_SUCCESS && rows != -1) ODBC_REPORT_ERROR("SQLRowCount returned some rows"); } else { /* in ODBC 2 errors/warnings are not handled as different recordset */ TestResult(result, level, "SQLFetch"); } if (odbc_driver_is_freetds()) CheckData(""); if (!g_second_select) { SQLLEN rows; if (CHKRowCount(&rows, "SE") == SQL_SUCCESS && rows != -1) ODBC_REPORT_ERROR("SQLRowCount returned some rows"); CheckReturnCode(result, g_nocount ? 0 : INVALID_RETURN); result = SQLMoreResults(odbc_stmt); #ifdef ENABLE_DEVELOPING if (result != SQL_NO_DATA) ODBC_REPORT_ERROR("SQLMoreResults should return NO DATA"); ODBC_CHECK_ROWS(-2); #endif CheckReturnCode(result, 0); return; } if (!odbc_use_version3 || !g_nocount) { /* mssql 2008 return SUCCESS_WITH_INFO with previous error */ CHKMoreResults("S"); result = SQL_SUCCESS; } CheckReturnCode(result, INVALID_RETURN); CheckData(""); if (g_nocount && odbc_use_version3 && g_second_select && level >= 10) { if (CHKFetch("SE") == SQL_ERROR) { SQLMoreResults(odbc_stmt); CHKFetch("S"); } } else { CHKFetch("S"); } CheckData("Here is the last row"); CHKFetch("No"); CheckData(""); if (!odbc_use_version3 || g_nocount) CheckReturnCode(result, 0); #ifdef ENABLE_DEVELOPING else CheckReturnCode(result, INVALID_RETURN); #endif /* FIXME how to handle return in store procedure ?? */ result = SQLMoreResults(odbc_stmt); #ifdef ENABLE_DEVELOPING if (result != SQL_NO_DATA) ODBC_REPORT_ERROR("SQLMoreResults return other data"); #endif CheckReturnCode(result, 0); CheckData(""); ODBC_FREE(); }
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(); }
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; }
static void DoTest(int prepare) { int n = 0; static const char query[] = /* on prepared this recordset should be skipped */ "DECLARE @b INT SELECT @b = 25 " "SELECT * FROM #tmp1 WHERE i <= 3 " /* on prepare we cannot distinguish these recordset */ "INSERT INTO #tmp2 SELECT * FROM #tmp1 WHERE i = 1 " "INSERT INTO #tmp2 SELECT * FROM #tmp1 WHERE i <= 3 " "SELECT * FROM #tmp1 WHERE i = 1 " /* but FreeTDS can detect last recordset */ "UPDATE #tmp1 SET i=i+1 WHERE i >= 2"; if (prepare) { CHKPrepare(T(query), SQL_NTS, "S"); CHKExecute("S"); } else { /* execute a batch command select insert insert select and check rows */ CHKExecDirect(T(query), SQL_NTS, "S"); } if (!prepare) { printf("Result %d\n", ++n); ODBC_CHECK_COLS(0); ODBC_CHECK_ROWS(1); CHKMoreResults("S"); } printf("Result %d\n", ++n); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(-1); CHKFetch("S"); CHKFetch("S"); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(-1); CHKFetch("No"); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(2); CHKMoreResults("S"); if (!prepare) { printf("Result %d\n", ++n); ODBC_CHECK_COLS(0); ODBC_CHECK_ROWS(1); CHKMoreResults("S"); printf("Result %d\n", ++n); ODBC_CHECK_COLS(0); ODBC_CHECK_ROWS(2); CHKMoreResults("S"); } printf("Result %d\n", ++n); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(-1); CHKFetch("S"); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(-1); CHKFetch("No"); ODBC_CHECK_COLS(1); if (prepare) { /* collapse 2 recordset... after a lot of testing this is the behavior! */ if (odbc_driver_is_freetds()) ODBC_CHECK_ROWS(2); } else { ODBC_CHECK_ROWS(1); CHKMoreResults("S"); ODBC_CHECK_COLS(0); ODBC_CHECK_ROWS(2); } CHKMoreResults("No"); #ifndef TDS_NO_DM if (!prepare) ODBC_CHECK_COLS(-1); ODBC_CHECK_ROWS(-2); #endif ODBC_FREE(); }
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[]) { char tmp[2048]; SQLSMALLINT len; int succeeded = 0; int is_freetds = 1; SQLRETURN rc; if (odbc_read_login_info()) exit(1); /* * prepare our odbcinst.ini * is better to do it before connect cause uniODBC cache INIs * the name must be odbcinst.ini cause unixODBC accept only this name */ if (odbc_driver[0]) { FILE *f = fopen("odbcinst.ini", "w"); if (f) { fprintf(f, "[FreeTDS]\nDriver = %s\n", odbc_driver); fclose(f); /* force iODBC */ setenv("ODBCINSTINI", "./odbcinst.ini", 1); setenv("SYSODBCINSTINI", "./odbcinst.ini", 1); /* force unixODBC (only directory) */ setenv("ODBCSYSINI", ".", 1); } } printf("SQLConnect connect..\n"); odbc_connect(); if (!odbc_driver_is_freetds()) is_freetds = 0; odbc_disconnect(); ++succeeded; if (!is_freetds) { printf("Driver is not FreeTDS, exiting\n"); return 0; } /* try connect string with using DSN */ printf("connect string DSN connect..\n"); init_connect(); sprintf(tmp, "DSN=%s;UID=%s;PWD=%s;DATABASE=%s;", 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"); odbc_disconnect(); ++succeeded; /* try connect string using old SERVERNAME specification */ printf("connect string SERVERNAME connect..\n"); printf("odbcinst.ini must be configured with FreeTDS driver..\n"); /* this is expected to work with unixODBC */ init_connect(); sprintf(tmp, "DRIVER=FreeTDS;SERVERNAME=%s;UID=%s;PWD=%s;DATABASE=%s;", odbc_server, odbc_user, odbc_password, odbc_database); rc = CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SIE"); if (rc == SQL_ERROR) { printf("Unable to open data source (ret=%d)\n", rc); } else { ++succeeded; } odbc_disconnect(); /* this is expected to work with iODBC */ init_connect(); sprintf(tmp, "DRIVER=%s;SERVERNAME=%s;UID=%s;PWD=%s;DATABASE=%s;", odbc_driver, odbc_server, odbc_user, odbc_password, odbc_database); rc = CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SIE"); if (rc == SQL_ERROR) { printf("Unable to open data source (ret=%d)\n", rc); } else { ++succeeded; } odbc_disconnect(); #ifdef _WIN32 if (get_entry("SERVER")) { init_connect(); sprintf(tmp, "DRIVER=FreeTDS;SERVER=%s;UID=%s;PWD=%s;DATABASE=%s;", entry, odbc_user, odbc_password, odbc_database); if (get_entry("TDS_Version")) sprintf(strchr(tmp, 0), "TDS_Version=%s;", entry); rc = CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SIE"); if (rc == SQL_ERROR) { printf("Unable to open data source (ret=%d)\n", rc); } else { ++succeeded; } odbc_disconnect(); } #endif /* at least one should success.. */ if (succeeded < 3) { ODBC_REPORT_ERROR("Too few successes"); exit(1); } printf("Done.\n"); return 0; }
int main(int argc, char **argv) { SQLLEN sql_nts = SQL_NTS; const char *query; SQLINTEGER id = 0; char string[64]; TDS_SYS_SOCKET last_socket; int port; const int num_inserts = 20; int is_freetds; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); #endif if (tds_mutex_init(&mtx)) return 1; odbc_mark_sockets_opened(); odbc_connect(); /* * this does not work if server is not connected with socket * (ie ms driver connected locally) */ last_socket = odbc_find_last_socket(); if (TDS_IS_SOCKET_INVALID(last_socket)) { fprintf(stderr, "Error finding last socket opened\n"); return 1; } remote_addr_len = sizeof(remote_addr); if (tds_getpeername(last_socket, &remote_addr.sa, &remote_addr_len)) { fprintf(stderr, "Unable to get remote address\n"); return 1; } is_freetds = odbc_driver_is_freetds(); odbc_disconnect(); /* init fake server, behave like a proxy */ for (port = 12340; port < 12350; ++port) if (!init_fake_server(port)) break; if (port == 12350) { fprintf(stderr, "Cannot bind to a port\n"); return 1; } printf("Fake server bound at port %d\n", port); /* override connections */ if (is_freetds) { setenv("TDSHOST", "127.0.0.1", 1); sprintf(string, "%d", port); setenv("TDSPORT", string, 1); odbc_connect(); } else { char tmp[2048]; SQLSMALLINT len; CHKAllocEnv(&odbc_env, "S"); CHKAllocConnect(&odbc_conn, "S"); sprintf(tmp, "DRIVER={SQL Server};SERVER=127.0.0.1,%d;UID=%s;PWD=%s;DATABASE=%s;Network=DBMSSOCN;", port, odbc_user, odbc_password, odbc_database); printf("connection string: %s\n", tmp); CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); CHKAllocStmt(&odbc_stmt, "S"); } /* real test */ odbc_command("CREATE TABLE #test(i int, c varchar(40))"); odbc_reset_statement(); /* do not take into account connection statistics */ tds_mutex_lock(&mtx); round_trips = 0; inserts = 0; tds_mutex_unlock(&mtx); query = "insert into #test values (?, ?)"; CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(id), 0, &id, 0, &sql_nts, "SI"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(string), 0, string, 0, &sql_nts, "SI"); CHKPrepare(T(query), SQL_NTS, "SI"); tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); for (id = 0; id < num_inserts; id++) { sprintf(string, "This is a test (%d)", (int) id); CHKExecute("SI"); CHKFreeStmt(SQL_CLOSE, "S"); } tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); odbc_reset_statement(); tds_mutex_lock(&mtx); if (inserts > 1 || round_trips > (unsigned) (num_inserts * 2 + 6)) { fprintf(stderr, "Too much round trips (%u) or insert (%u) !!!\n", round_trips, inserts); tds_mutex_unlock(&mtx); return 1; } printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); #ifdef ENABLE_DEVELOPING /* check for SQL_RESET_PARAMS */ tds_mutex_lock(&mtx); round_trips = 0; inserts = 0; tds_mutex_unlock(&mtx); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(id), 0, &id, 0, &sql_nts, "SI"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(string), 0, string, 0, &sql_nts, "SI"); CHKPrepare((SQLCHAR *) query, SQL_NTS, "SI"); tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); for (id = 0; id < num_inserts; id++) { CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(id), 0, &id, 0, &sql_nts, "SI"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(string), 0, string, 0, &sql_nts, "SI"); sprintf(string, "This is a test (%d)", (int) id); CHKExecute("SI"); CHKFreeStmt(SQL_RESET_PARAMS, "S"); } tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); odbc_reset_statement(); tds_mutex_lock(&mtx); if (inserts > 1 || round_trips > num_inserts * 2 + 6) { fprintf(stderr, "Too much round trips (%u) or insert (%u) !!!\n", round_trips, inserts); tds_mutex_unlock(&mtx); return 1; } printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); #endif odbc_disconnect(); alarm(10); tds_thread_join(fake_thread, NULL); return 0; }