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(); }
static int CheckDirtyRead(void) { SQLRETURN RetCode; /* transaction 1 try to change a row but not commit */ odbc_command("UPDATE test_transaction SET t = 'second' WHERE n = 1"); SWAP_CONN(); /* second transaction try to fetch uncommited row */ RetCode = odbc_command2("SELECT * FROM test_transaction WHERE t = 'second' AND n = 1", "SE"); if (RetCode == SQL_ERROR) { EndTransaction(SQL_ROLLBACK); SWAP_CONN(); EndTransaction(SQL_ROLLBACK); return 0; /* no dirty read */ } CHKFetch("S"); CHKFetch("No"); SQLMoreResults(odbc_stmt); EndTransaction(SQL_ROLLBACK); SWAP_CONN(); EndTransaction(SQL_ROLLBACK); return 1; }
static void DoTest(int n) { SQLCHAR output[256]; SQLSMALLINT colType; SQLULEN colSize; SQLSMALLINT colScale, colNullable; SQLLEN dataSize; TIMESTAMP_STRUCT ts; odbc_command("select convert(datetime, '2002-12-27 18:43:21')"); CHKFetch("SI"); CHKDescribeCol(1, (SQLTCHAR*)output, sizeof(output)/sizeof(SQLWCHAR), NULL, &colType, &colSize, &colScale, &colNullable, "S"); if (n == 0) { memset(&ts, 0, sizeof(ts)); CHKGetData(1, SQL_C_TIMESTAMP, &ts, sizeof(ts), &dataSize, "S"); sprintf((char *) output, "%04d-%02d-%02d %02d:%02d:%02d.000", ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second); } else { CHKGetData(1, SQL_C_CHAR, output, sizeof(output), &dataSize, "S"); } printf("Date returned: %s\n", output); if (strcmp((char *) output, "2002-12-27 18:43:21.000") != 0) { fprintf(stderr, "Invalid returned date\n"); exit(1); } CHKFetch("No"); CHKCloseCursor("SI"); }
static int test_select(void *buf, SQLINTEGER buflen, SQLLEN * bytes_returned) { SQLHSTMT odbc_stmt = SQL_NULL_HSTMT; SQLLEN strlen_or_ind = 0; const char *qstr = "select * from " TEST_TABLE_NAME; assert(odbc_conn); assert(odbc_env); /* allocate new statement handle */ CHKAllocHandle(SQL_HANDLE_STMT, odbc_conn, &odbc_stmt, "SI"); /* execute query */ CHKExecDirect(T(qstr), SQL_NTS, "SINo"); /* fetch first page of first result row of unbound column */ CHKFetch("S"); strlen_or_ind = 0; CHKGetData(1, SQL_C_BINARY, buf, buflen, &strlen_or_ind, "SINo"); *bytes_returned = ((strlen_or_ind > buflen || (strlen_or_ind == SQL_NO_TOTAL)) ? buflen : strlen_or_ind); /* ensure that this was the only row */ CHKFetch("No"); SQLFreeHandle(SQL_HANDLE_STMT, odbc_stmt); ODBC_FREE(); return 0; }
int main(int argc, char **argv) { #define ARRAY_SIZE 10 SQLCHAR v_dec[ARRAY_SIZE][21]; SQLLEN v_ind[ARRAY_SIZE]; SQLULEN nrows; odbc_use_version3 = 1; odbc_connect(); odbc_check_cursor(); odbc_command("IF OBJECT_ID('mytab1') IS NOT NULL DROP TABLE mytab1"); odbc_command("CREATE TABLE mytab1 ( k INT, d DECIMAL(10,2))"); odbc_command("INSERT INTO mytab1 VALUES ( 201, 111.11 )"); /*SQLExecDirect(m_hstmt, (SQLCHAR *) "insert into mytab1 values ( 202, 222.22 )", SQL_NTS); */ odbc_command("INSERT INTO mytab1 VALUES ( 202, null )"); odbc_reset_statement(); CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_NONSCROLLABLE, SQL_IS_UINTEGER, "S"); CHKSetStmtAttr(SQL_ATTR_CURSOR_SENSITIVITY, (SQLPOINTER) SQL_SENSITIVE, SQL_IS_UINTEGER, "S"); CHKSetStmtAttr(SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER) SQL_BIND_BY_COLUMN, SQL_IS_UINTEGER, "S"); CHKSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ARRAY_SIZE, SQL_IS_UINTEGER, "S"); CHKSetStmtAttr(SQL_ATTR_ROWS_FETCHED_PTR, (SQLPOINTER) & (nrows), SQL_IS_UINTEGER, "S"); CHKPrepare(T("SELECT SUM(d) FROM mytab1"), SQL_NTS, "S"); CHKExecute("I"); #if 0 CHKMoreResults("S"); /* skip warning*/ #endif CHKBindCol(1, SQL_C_CHAR, v_dec, 21, v_ind, "S"); CHKFetch("S"); printf("fetch 1: rows fetched = %d\n", (int) nrows); printf("fetch 1: value = [%s]\n", v_dec[0]); CHKFetch("No"); CHKMoreResults("No"); odbc_command("drop table mytab1"); odbc_disconnect(); return 0; }
int main(int argc, char **argv) { char buff[64]; SQLLEN ind; odbc_use_version3 = 1; odbc_connect(); odbc_check_cursor(); exec_direct("CREATE TABLE #t1 ( k INT, c VARCHAR(20))"); exec_direct("INSERT INTO #t1 VALUES (1, 'aaa')"); odbc_reset_statement(); CHKSetStmtAttr(SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_LOCK, SQL_IS_UINTEGER, "S"); CHKSetCursorName(T("c112"), SQL_NTS, "S"); CHKSetConnectAttr(SQL_ATTR_AUTOCOMMIT, int2ptr(SQL_AUTOCOMMIT_OFF), 0, "S"); CHKPrepare(T("SELECT * FROM #t1 FOR UPDATE"), SQL_NTS, "S"); CHKExecute("S"); CHKFetch("S"); exec_direct("UPDATE #t1 SET c = 'xxx' WHERE CURRENT OF c112"); CHKCloseCursor("SI"); CHKEndTran(SQL_HANDLE_DBC, odbc_conn, SQL_COMMIT, "S"); CHKSetConnectAttr(SQL_ATTR_AUTOCOMMIT, int2ptr(SQL_AUTOCOMMIT_ON), 0, "S"); CHKExecDirect(T("SELECT c FROM #t1 WHERE k = 1"), SQL_NTS, "S"); CHKFetch("S"); CHKGetData(1, SQL_C_CHAR, buff, sizeof(buff), &ind, "S"); printf(">> New value after update = [%s] (should be [xxx]) \n", buff); CHKFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) odbc_stmt, "S"); odbc_stmt = SQL_NULL_HSTMT; odbc_disconnect(); return 0; }
/* 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(); }
int main(int argc, char *argv[]) { int i; SQLLEN cnamesize; const char *command; SQLCHAR output[256]; odbc_connect(); odbc_command("if object_id('tempdb..#odbctestdata') is not null drop table #odbctestdata"); command = "create table #odbctestdata (" "col1 varchar(30) not null," "col2 int not null," "col3 float not null," "col4 numeric(18,6) not null," "col5 datetime not null," "col6 text not null)"; odbc_command(command); command = "insert #odbctestdata values (" "'ABCDEFGHIJKLMNOP'," "123456," "1234.56," "123456.78," "'Sep 11 2001 10:00AM'," "'just to check returned length...')"; odbc_command(command); odbc_command("select * from #odbctestdata"); CHKFetch("SI"); for (i = 1; i <= 6; i++) { CHKGetData(i, SQL_C_CHAR, output, sizeof(output), &cnamesize, "S"); printf("output data >%s< len_or_ind = %d\n", output, (int) cnamesize); if (cnamesize != strlen((char *) output)) return 1; } CHKFetch("No"); CHKCloseCursor("SI"); odbc_command("drop table #odbctestdata"); odbc_disconnect(); printf("Done.\n"); return 0; }
int main(int argc, char *argv[]) { char buf[102]; SQLLEN ind; int failed = 0; odbc_use_version3 = 1; odbc_connect(); CHKBindCol(1, SQL_C_DEFAULT, buf, 100, &ind, "S"); odbc_command("SELECT CONVERT(NCHAR(10), 'Pippo 123')"); /* get data */ memset(buf, 0, sizeof(buf)); CHKFetch("S"); SQLMoreResults(odbc_stmt); SQLMoreResults(odbc_stmt); odbc_disconnect(); if (strcmp(buf, "Pippo 123 ") != 0) { fprintf(stderr, "Wrong results '%s'\n", buf); failed = 1; } return failed ? 1 : 0; }
static void TestProc(const char *type, const char *expected) { char sql[256]; odbc_command("IF OBJECT_ID('stat_proc') IS NOT NULL DROP PROC stat_proc"); sprintf(sql, "CREATE PROC stat_proc(@t %s) AS RETURN 0", type); odbc_command(sql); column = "@t"; CHKProcedureColumns(T(catalog), LEN(catalog), T(schema), LEN(schema), T(proc), LEN(proc), T(column), LEN(column), "SI"); CHKFetch("SI"); ReadCol(6); if (strcmp(output, expected) != 0) { fprintf(stderr, "Got \"%s\" expected \"%s\"\n", output, expected); odbc_disconnect(); exit(1); } CHKCloseCursor("SI"); ODBC_FREE(); }
static void TestTable(const char *type, const char *expected) { char sql[256]; odbc_command("IF OBJECT_ID('stat_t') IS NOT NULL DROP TABLE stat_t"); sprintf(sql, "CREATE TABLE stat_t(t %s)", type); odbc_command(sql); column = "t"; table = "stat_t"; CHKColumns(T(catalog), LEN(catalog), T(schema), LEN(schema), T(table), LEN(table), T(column), LEN(column), "SI"); CHKFetch("SI"); ReadCol(5); if (strcmp(output, expected) != 0) { fprintf(stderr, "Got \"%s\" expected \"%s\"\n", output, expected); odbc_disconnect(); exit(1); } CHKCloseCursor("SI"); ODBC_FREE(); }
static void DoTest(int prepared) { odbc_command("create table #odbctestdata (i int)"); /* test that 2 empty result set are returned correctly */ if (!prepared) { odbc_command("select * from #odbctestdata select * from #odbctestdata"); } else { CHKPrepare(T("select * from #odbctestdata select * from #odbctestdata"), SQL_NTS, "S"); CHKExecute("S"); } CHKFetch("No"); CHKMoreResults("S"); printf("Getting next recordset\n"); CHKFetch("No"); CHKMoreResults("No"); /* test that skipping a no empty result go to other result set */ odbc_command("insert into #odbctestdata values(123)"); if (!prepared) { odbc_command("select * from #odbctestdata select * from #odbctestdata"); } else { CHKPrepare(T("select * from #odbctestdata select * from #odbctestdata"), SQL_NTS, "S"); CHKExecute("S"); } CHKMoreResults("S"); printf("Getting next recordset\n"); CHKFetch("S"); CHKFetch("No"); CHKMoreResults("No"); odbc_command("drop table #odbctestdata"); ODBC_FREE(); }
static void Test(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, const char *expected) { char sbuf[1024]; unsigned char out_buf[256]; SQLLEN out_len = 0; SQLFreeStmt(odbc_stmt, SQL_UNBIND); SQLFreeStmt(odbc_stmt, SQL_RESET_PARAMS); /* execute a select to get data as wire */ sprintf(sbuf, "SELECT CONVERT(%s, '%s') AS data", type, value_to_convert); if (strncmp(value_to_convert, "0x", 2) == 0) sprintf(sbuf, "SELECT CONVERT(%s, %s) COLLATE Latin1_General_CI_AS AS data", type, value_to_convert); else if (strcmp(type, "SQL_VARIANT") == 0) sprintf(sbuf, "SELECT CONVERT(SQL_VARIANT, %s) AS data", value_to_convert); else if (strncmp(value_to_convert, "u&'", 3) == 0) sprintf(sbuf, "SELECT CONVERT(%s, %s) AS data", type, value_to_convert); if (ignore_select_error) { if (odbc_command2(sbuf, "SENo") == SQL_ERROR) { odbc_reset_statement(); ignore_select_error = 0; ignore_result = 0; return; } } else { odbc_command(sbuf); } SQLBindCol(odbc_stmt, 1, out_c_type, out_buf, sizeof(out_buf), &out_len); CHKFetch("S"); CHKFetch("No"); CHKMoreResults("No"); /* test results */ odbc_c2string(sbuf, out_c_type, out_buf, out_len); if (!ignore_result && strcmp(sbuf, expected) != 0) { fprintf(stderr, "Wrong result\n Got: %s\n Expected: %s\n", sbuf, expected); result = 1; } ignore_select_error = 0; ignore_result = 0; }
static void Flushodbc_stmt(void) { while (CHKFetch("SNo") == SQL_SUCCESS) ; /* Sybase store procedure seems to return extra empty results */ while (CHKMoreResults("SNo") == SQL_SUCCESS) ; }
static void TestInsert(char *buf) { SQLLEN ind; int l = strlen(buf); char sql[200]; /* insert some data and test success */ CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, l, 0, buf, l, &ind, "S"); ind = l; CHKExecute("S"); SWAP_STMT(stmt); sprintf(sql, "SELECT 1 FROM #tmp1 WHERE c = '%s'", buf); odbc_command(sql); CHKFetch("S"); CHKFetch("No"); CHKMoreResults("No"); SWAP_STMT(stmt); }
static int CheckPhantom(void) { SQLRETURN RetCode; /* transaction 2 read a row */ SWAP_CONN(); odbc_command("SELECT * FROM test_transaction WHERE t = 'initial'"); SQLMoreResults(odbc_stmt); /* transaction 1 insert a row that match critera */ SWAP_CONN(); RetCode = odbc_command2("INSERT INTO test_transaction(n, t) VALUES(2, 'initial')", "SE"); if (RetCode == SQL_ERROR) { EndTransaction(SQL_ROLLBACK); SWAP_CONN(); EndTransaction(SQL_ROLLBACK); SWAP_CONN(); return 0; /* no dirty read */ } EndTransaction(SQL_COMMIT); SWAP_CONN(); /* second transaction try to fetch commited row */ odbc_command("SELECT * FROM test_transaction WHERE t = 'initial'"); CHKFetch("S"); CHKFetch("S"); CHKFetch("No"); SQLMoreResults(odbc_stmt); EndTransaction(SQL_ROLLBACK); SWAP_CONN(); odbc_command("DELETE test_transaction WHERE n = 2"); EndTransaction(SQL_COMMIT); return 1; }
static int CheckNonrepeatableRead(void) { SQLRETURN RetCode; /* transaction 2 read a row */ SWAP_CONN(); odbc_command("SELECT * FROM test_transaction WHERE t = 'initial' AND n = 1"); SQLMoreResults(odbc_stmt); /* transaction 1 change a row and commit */ SWAP_CONN(); RetCode = odbc_command2("UPDATE test_transaction SET t = 'second' WHERE n = 1", "SE"); if (RetCode == SQL_ERROR) { EndTransaction(SQL_ROLLBACK); SWAP_CONN(); EndTransaction(SQL_ROLLBACK); SWAP_CONN(); return 0; /* no dirty read */ } EndTransaction(SQL_COMMIT); SWAP_CONN(); /* second transaction try to fetch commited row */ odbc_command("SELECT * FROM test_transaction WHERE t = 'second' AND n = 1"); CHKFetch("S"); CHKFetch("No"); SQLMoreResults(odbc_stmt); EndTransaction(SQL_ROLLBACK); SWAP_CONN(); odbc_command("UPDATE test_transaction SET t = 'initial' WHERE n = 1"); EndTransaction(SQL_COMMIT); return 1; }
int main(int argc, char *argv[]) { char output[256]; SQLLEN dataSize; odbc_connect(); odbc_command_with_result(odbc_stmt, "drop proc sp_norowset_test"); odbc_command("create proc sp_norowset_test as begin declare @i int end"); odbc_command("exec sp_norowset_test"); /* note, mssql 2005 seems to not return row for tempdb, use always master */ odbc_command("select name from master..sysobjects where name = 'sysobjects'"); CHKFetch("S"); CHKGetData(1, SQL_C_CHAR, output, sizeof(output), &dataSize, "S"); if (strcmp(output, "sysobjects") != 0) { printf("Unexpected result\n"); exit(1); } CHKFetch("No"); CHKMoreResults("No"); odbc_command("drop proc sp_norowset_test"); odbc_disconnect(); printf("Done.\n"); return 0; }
int main(int argc, char *argv[]) { int i; odbc_connect(); odbc_command("create table #timeout(i int)"); odbc_command("insert into #timeout values(1)"); for (i = 0; i < 2; ++i) { printf("Loop %d\n", i); CHKSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER) 10, SQL_IS_UINTEGER, "S"); CHKPrepare(T("select * from #timeout"), SQL_NTS, "S"); CHKExecute("S"); do { while (CHKFetch("SNo") == SQL_SUCCESS) ; } while (CHKMoreResults("SNo") == SQL_SUCCESS); if (i == 0) { printf("Sleep 15 seconds to test if timeout occurs\n"); tds_sleep_s(15); } SQLFreeStmt(odbc_stmt, SQL_CLOSE); SQLFreeStmt(odbc_stmt, SQL_UNBIND); SQLFreeStmt(odbc_stmt, SQL_RESET_PARAMS); SQLCloseCursor(odbc_stmt); } odbc_disconnect(); ODBC_FREE(); return 0; }
static void CheckType(SQLSMALLINT type, SQLSMALLINT expected, const char *string_type, int line) { SQLSMALLINT out_type; SQLLEN ind; SQLRETURN RetCode; printf("CheckType %d\n", line); CHKBindCol(2, SQL_C_SSHORT, &out_type, 0, &ind, "SI"); CHKGetTypeInfo(type, "SI"); RetCode = CHKFetch("SNo"); switch (RetCode) { case SQL_SUCCESS: if (expected == SQL_UNKNOWN_TYPE) { fprintf(stderr, "Data not expected (type %d - %s) line %d\n", type, string_type, line); odbc_disconnect(); exit(1); } if (expected != out_type) { fprintf(stderr, "Got type %d expected %d. Input type %d - %s line %d\n", out_type, expected, type, string_type, line); odbc_disconnect(); exit(1); } break; case SQL_NO_DATA: if (expected != SQL_UNKNOWN_TYPE) { fprintf(stderr, "Data expected. Inpute type %d - %s line %d\n", type, string_type, line); odbc_disconnect(); exit(1); } break; } SQLFreeStmt(odbc_stmt, SQL_UNBIND); Flushodbc_stmt(); }
static void CheckFetch(const char *c1name, const char *c1, const char *c2) { int error = 0; TestName(1, c1name); CHKFetch("S"); if (strlen(c1) != ind1 || strcmp(c1, col1) != 0) { fprintf(stderr, "%s:%d: Column 1 error '%s' (%d) expected '%s' (%d)\n", __FILE__, main_line, col1, (int) ind1, c1, (int) strlen(c1)); error = 1; } if (strlen(c2) != ind2 || strcmp(c2, col2) != 0) { fprintf(stderr, "%s:%d: Column 2 error '%s' (%d) expected '%s' (%d)\n", __FILE__, main_line, col2, (int) ind2, c2, (int) strlen(c2)); error = 1; } if (error) exit(1); }
static void test_split(const char *n_flag) { #define CheckLen(x) do { \ if (len != (x)) { \ fprintf(stderr, "Wrong len %ld at line %d expected %d\n", (long int) len, __LINE__, (x)); \ exit(1); \ } \ } while(0) char sql[80]; char *buf = NULL; SQLLEN len; /* TODO test with VARCHAR too */ sprintf(sql, "SELECT CONVERT(%sTEXT,'Prova' + REPLICATE('x',500))", n_flag); odbc_command(sql); CHKFetch("S"); /* these 2 tests test an old severe BUG in FreeTDS */ buf = ODBC_GET(1); CHKGetData(1, type, buf, 0, &len, "I"); if (len != SQL_NO_TOTAL) CheckLen(505*lc); CHKGetData(1, type, buf, 0, &len, "I"); if (len != SQL_NO_TOTAL) CheckLen(505*lc); buf = ODBC_GET(3*lc); CHKGetData(1, type, buf, 3 * lc, &len, "I"); if (len != SQL_NO_TOTAL) CheckLen(505*lc); if (mycmp(buf, "Pr") != 0) { printf("Wrong data result 1\n"); exit(1); } buf = ODBC_GET(16*lc); CHKGetData(1, type, buf, 16 * lc, &len, "I"); if (len != SQL_NO_TOTAL) CheckLen(503*lc); if (mycmp(buf, "ovaxxxxxxxxxxxx") != 0) { printf("Wrong data result 2 res = '%s'\n", buf); exit(1); } buf = ODBC_GET(256*lc); CHKGetData(1, type, buf, 256 * lc, &len, "I"); if (len != SQL_NO_TOTAL) CheckLen(488*lc); CHKGetData(1, type, buf, 256 * lc, &len, "S"); CheckLen(233*lc); CHKGetData(1, type, buf, 256 * lc, &len, "No"); odbc_reset_statement(); /* test with varchar, not blob but variable */ sprintf(sql, "SELECT CONVERT(%sVARCHAR(100), 'Other test')", n_flag); odbc_command(sql); CHKFetch("S"); buf = ODBC_GET(7*lc); CHKGetData(1, type, buf, 7 * lc, NULL, "I"); if (mycmp(buf, "Other ") != 0) { printf("Wrong data result 1\n"); exit(1); } buf = ODBC_GET(5*lc); CHKGetData(1, type, buf, 20, NULL, "S"); if (mycmp(buf, "test") != 0) { printf("Wrong data result 2 res = '%s'\n", buf); exit(1); } ODBC_FREE(); odbc_reset_statement(); }
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; }
int main(int argc, char *argv[]) { #define TEST_FILE "describecol.in" const char *in_file = FREETDS_SRCDIR "/" TEST_FILE; FILE *f; char buf[256]; SQLINTEGER i; SQLLEN len; check_attr_t check_attr_p = check_attr_none; odbc_connect(); odbc_command("SET TEXTSIZE 4096"); SQLBindCol(odbc_stmt, 1, SQL_C_SLONG, &i, sizeof(i), &len); f = fopen(in_file, "r"); if (!f) fopen(TEST_FILE, "r"); if (!f) { fprintf(stderr, "error opening test file\n"); exit(1); } line_num = 0; while (fgets(buf, sizeof(buf), f)) { char *p = buf, *cmd; ++line_num; while (isspace((unsigned char) *p)) ++p; cmd = strtok(p, SEP); /* skip comments */ if (!cmd || cmd[0] == '#' || cmd[0] == 0 || cmd[0] == '\n') continue; if (strcmp(cmd, "odbc") == 0) { int odbc3 = get_int(strtok(NULL, SEP)) == 3 ? 1 : 0; if (odbc_use_version3 != odbc3) { odbc_use_version3 = odbc3; odbc_disconnect(); odbc_connect(); odbc_command("SET TEXTSIZE 4096"); SQLBindCol(odbc_stmt, 1, SQL_C_SLONG, &i, sizeof(i), &len); } } /* select type */ if (strcmp(cmd, "select") == 0) { const char *type = strtok(NULL, SEP); const char *value = strtok(NULL, SEP); char sql[sizeof(buf) + 40]; SQLMoreResults(odbc_stmt); odbc_reset_statement(); sprintf(sql, "SELECT CONVERT(%s, %s) AS col", type, value); /* ignore error, we only need precision of known types */ check_attr_p = check_attr_none; if (odbc_command_with_result(odbc_stmt, sql) != SQL_SUCCESS) { odbc_reset_statement(); SQLBindCol(odbc_stmt, 1, SQL_C_SLONG, &i, sizeof(i), &len); continue; } CHKFetch("SI"); SQLBindCol(odbc_stmt, 1, SQL_C_SLONG, &i, sizeof(i), &len); check_attr_p = check_attr_ird; } /* set attribute */ if (strcmp(cmd, "set") == 0) { const struct attribute *attr = lookup_attr(strtok(NULL, SEP)); char *value = strtok(NULL, SEP); SQLHDESC desc; SQLRETURN ret; SQLINTEGER ind; if (!value) fatal("Line %u: value not defined\n", line_num); /* get ARD */ SQLGetStmtAttr(odbc_stmt, SQL_ATTR_APP_ROW_DESC, &desc, sizeof(desc), &ind); ret = SQL_ERROR; switch (attr->type) { case type_INTEGER: ret = SQLSetDescField(desc, 1, attr->value, int2ptr(lookup(value, attr->lookup)), sizeof(SQLINTEGER)); break; case type_SMALLINT: ret = SQLSetDescField(desc, 1, attr->value, int2ptr(lookup(value, attr->lookup)), sizeof(SQLSMALLINT)); break; case type_LEN: ret = SQLSetDescField(desc, 1, attr->value, int2ptr(lookup(value, attr->lookup)), sizeof(SQLLEN)); break; case type_CHARP: ret = SQLSetDescField(desc, 1, attr->value, (SQLPOINTER) value, SQL_NTS); break; } if (!SQL_SUCCEEDED(ret)) fatal("Line %u: failure not expected setting ARD attribute\n", line_num); check_attr_p = check_attr_ard; } /* test attribute */ if (strcmp(cmd, "attr") == 0) { const struct attribute *attr = lookup_attr(strtok(NULL, SEP)); char *expected = strtok(NULL, SEP); if (!expected) fatal("Line %u: value not defined\n", line_num); check_attr_p(attr, expected); } } fclose(f); odbc_disconnect(); printf("Done.\n"); return g_result; }
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(); }
static void TestInput(SQLSMALLINT out_c_type, const char *type, SQLSMALLINT out_sql_type, const char *param_type, const char *value_to_convert) { char sbuf[1024]; unsigned char out_buf[256]; SQLLEN out_len = 0; const char *expected = value_to_convert; size_t value_len = strlen(value_to_convert); const char *p; const char *sep = "'"; odbc_reset_statement(); /* execute a select to get data as wire */ if ((p = strstr(value_to_convert, " -> ")) != NULL) { value_len = p - value_to_convert; expected = p + 4; } if (value_len >= 2 && strncmp(value_to_convert, "0x", 2) == 0) sep = ""; sprintf(sbuf, "SELECT CONVERT(%s, %s%.*s%s)", type, sep, (int) value_len, value_to_convert, sep); odbc_command(sbuf); SQLBindCol(odbc_stmt, 1, out_c_type, out_buf, sizeof(out_buf), &out_len); CHKFetch("SI"); CHKFetch("No"); CHKMoreResults("No"); if (use_nts) { out_len = SQL_NTS; use_nts = 0; } /* create a table with a column of that type */ odbc_reset_statement(); sprintf(sbuf, "CREATE TABLE #tmp_insert (col %s)", 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, out_buf, sizeof(out_buf), &out_len, "S"); if (check_truncation) CHKExecDirect(T(sbuf), SQL_NTS, "E"); else 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, out_buf, sizeof(out_buf), &out_len, "S"); if (!prepare_before) CHKPrepare(T(sbuf), SQL_NTS, "S"); if (check_truncation) CHKExecute("E"); else CHKExecute("SNo"); } /* check if row is present */ if (!check_truncation) { odbc_reset_statement(); sep = "'"; if (strncmp(expected, "0x", 2) == 0) sep = ""; if (strcmp(param_type, "TEXT") == 0) sprintf(sbuf, "SELECT * FROM #tmp_insert WHERE CONVERT(VARCHAR(255), col) = CONVERT(VARCHAR(255), %s%s%s)", sep, expected, sep); else if (strcmp(param_type, "NTEXT") == 0) sprintf(sbuf, "SELECT * FROM #tmp_insert WHERE CONVERT(NVARCHAR(2000), col) = CONVERT(NVARCHAR(2000), %s%s%s)", sep, expected, sep); else if (strcmp(param_type, "IMAGE") == 0) sprintf(sbuf, "SELECT * FROM #tmp_insert WHERE CONVERT(VARBINARY(255), col) = CONVERT(VARBINARY(255), %s%s%s)", sep, expected, sep); else sprintf(sbuf, "SELECT * FROM #tmp_insert WHERE col = CONVERT(%s, %s%s%s)", param_type, sep, expected, sep); odbc_command(sbuf); CHKFetch("S"); CHKFetch("No"); CHKMoreResults("No"); } check_truncation = 0; odbc_command("DROP TABLE #tmp_insert"); ODBC_FREE(); }
static int test(int odbc3) { SQLLEN cnamesize; const char *query; odbc_use_version3 = odbc3; odbc_connect(); /* issue print statement and test message returned */ output[0] = 0; query = "print 'START' select count(*) from sysobjects where name='sysobjects' print 'END'"; odbc_command2(query, "I"); odbc_read_error(); if (!strstr(odbc_err, "START")) { printf("Message invalid\n"); return 1; } odbc_err[0] = 0; if (odbc3) { ODBC_CHECK_COLS(0); ODBC_CHECK_ROWS(-1); CHKFetch("E"); CHKMoreResults("S"); } ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(-1); CHKFetch("S"); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(-1); /* check no data */ CHKFetch("No"); ODBC_CHECK_COLS(1); ODBC_CHECK_ROWS(1); /* SQLMoreResults return NO DATA or SUCCESS WITH INFO ... */ if (tds_no_dm && !odbc3) CHKMoreResults("No"); else if (odbc3) CHKMoreResults("I"); else CHKMoreResults("INo"); /* * ... but read error * (unixODBC till 2.2.11 do not read errors on NO DATA, skip test) */ if (tds_no_dm || odbc3) { odbc_read_error(); if (!strstr(odbc_err, "END")) { printf("Message invalid\n"); return 1; } odbc_err[0] = 0; } if (odbc3) { ODBC_CHECK_COLS(0); ODBC_CHECK_ROWS(-1); CHKMoreResults("No"); } /* issue invalid command and test error */ odbc_command2("SELECT donotexistsfield FROM donotexiststable", "E"); odbc_read_error(); /* test no data returned */ CHKFetch("E"); odbc_read_error(); CHKGetData(1, SQL_C_CHAR, output, sizeof(output), &cnamesize, "E"); odbc_read_error(); odbc_disconnect(); 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; }
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 query_test(const char* expected, const char *expected_status) { #define ARRAY_SIZE 10 ODBC_BUF *odbc_buf = NULL; SQLUINTEGER *ids; SQLCHAR *descs; SQLLEN *id_lens, *desc_lens; SQLULEN processed; SQLUSMALLINT i, statuses[ARRAY_SIZE]; int desc_len = trunc ? 4 : 51; int rec_size = 0; Record *rec = NULL; char status[20]; assert(odbc_stmt != SQL_NULL_HSTMT); odbc_reset_statement(); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_STATUS_PTR, statuses, 0); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_ARRAY_SIZE, (void *) ARRAY_SIZE, 0); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROWS_FETCHED_PTR, &processed, 0); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0); if (!record_bind) { ids = (SQLUINTEGER *) ODBC_GET(sizeof(SQLUINTEGER) * ARRAY_SIZE); descs = ODBC_GET(sizeof(SQLCHAR) * ARRAY_SIZE * desc_len); desc_lens = (SQLLEN *) ODBC_GET(sizeof(SQLLEN) * ARRAY_SIZE); id_lens = (SQLLEN *) ODBC_GET(sizeof(SQLLEN) * ARRAY_SIZE); assert(descs && ids && desc_lens && id_lens); } else { rec_size = (sizeof(Record) + (sizeof(SQLCHAR) * desc_len + sizeof(SQLLEN) - 1)) & ~(sizeof(SQLLEN) - 1); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_ROW_BIND_TYPE, int2ptr(rec_size), 0); rec = (Record *) ODBC_GET(rec_size * ARRAY_SIZE); ids = &rec->id; id_lens = &rec->id_len; desc_lens = &rec->desc_len; descs = (SQLCHAR *) (((char *) rec) + sizeof(Record)); } #define REC(f,n) (((char*)f)+rec_size*(n)) #define DESCS(n) (rec ? (SQLCHAR*)REC(descs,n): (descs+(n)*desc_len)) #define IDS(n) *(rec ? (SQLUINTEGER*)REC(ids,n) : &ids[n]) #define ID_LENS(n) *(rec ? (SQLLEN*)REC(id_lens,n) : &id_lens[n]) #define DESC_LENS(n) *(rec ? (SQLLEN*)REC(desc_lens,n) : &desc_lens[n]) processed = ARRAY_SIZE + 1; for (i = 0; i < ARRAY_SIZE; i++) { statuses[i] = SQL_ROW_UPDATED; IDS(i) = i * 132; sprintf((char *) DESCS(i), "aaa"); ID_LENS(i) = 0; DESC_LENS(i) = -i; } SQLBindCol(odbc_stmt, 1, SQL_C_ULONG, &IDS(0), 0, &ID_LENS(0)); SQLBindCol(odbc_stmt, 2, SQL_C_CHAR, DESCS(0), desc_len, &DESC_LENS(0)); CHKExecDirect(T(test_query), SQL_NTS, "S"); CHKFetch(expected); assert(processed <= ARRAY_SIZE); for (i = 0; i < processed; ++i) { char buf[128]; sprintf(buf, "%crow number %d", 'a' + i, i * 13); if (trunc) buf[3] = 0; if (IDS(i) != i + 1 || strcmp((char *) DESCS(i), buf) != 0) { fprintf(stderr, "Invalid result\n\tgot '%d|%s'\n\texpected '%d|%s'\n", (int) IDS(i), DESCS(i), i + 1, buf); exit(1); } switch (statuses[i]) { case SQL_ROW_SUCCESS: status[i] = 'V'; break; case SQL_ROW_SUCCESS_WITH_INFO: status[i] = 'v'; break; case SQL_ROW_ERROR: status[i] = '!'; break; case SQL_ROW_NOROW: status[i] = ' '; break; default: fprintf(stderr, "Invalid status returned\n"); exit(1); } } status[i] = 0; if (expected_status && strcmp(expected_status, status) != 0) { fprintf(stderr, "Invalid status\n\tgot '%s'\n\texpected '%s'\n", status, expected_status); exit(1); } ODBC_FREE(); }