static void insert_test_man(void) { SQLLEN sql_nts = SQL_NTS; SQLINTEGER commit_off = SQL_AUTOCOMMIT_OFF; SQLINTEGER commit_on = SQL_AUTOCOMMIT_ON; SQLINTEGER id = 0; char string[64]; CHKSetConnectAttr(SQL_ATTR_AUTOCOMMIT, int2ptr(commit_off), SQL_IS_INTEGER, "SI"); odbc_reset_statement(); 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("insert into test values (?, ?)"), SQL_NTS, "SI"); for (id = 0; id < 20; id++) { sprintf(string, "This is a test (%d)", (int) id); CHKExecute("SI"); } SQLEndTran(SQL_HANDLE_DBC, odbc_conn, SQL_COMMIT); SQLSetConnectAttr(odbc_conn, SQL_ATTR_AUTOCOMMIT, int2ptr(commit_on), SQL_IS_INTEGER); odbc_reset_statement(); }
static int Test(int bind_before) { SQLSMALLINT ReturnCode = 0; SQLSMALLINT InParam = 5; SQLSMALLINT OutParam = 1; char OutString[OUTSTRING_LEN]; SQLLEN cbReturnCode = 0, cbInParam = 0, cbOutParam = 0; SQLLEN cbOutString = SQL_NTS; odbc_connect(); /* drop proc */ odbc_command("IF OBJECT_ID('spTestProc') IS NOT NULL DROP PROC spTestProc"); /* create proc */ odbc_command(sp_define); if (!bind_before) CHKPrepare(T(SP_TEXT), strlen(SP_TEXT), "S"); CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &ReturnCode, 0, &cbReturnCode, "S"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &InParam, 0, &cbInParam, "S"); CHKBindParameter(3, SQL_PARAM_OUTPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &OutParam, 0, &cbOutParam, "S"); OutString[0] = '\0'; strcpy(OutString, "Test"); /* Comment this line and we get an error! Why? */ CHKBindParameter(4, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, OUTSTRING_LEN, 0, OutString, OUTSTRING_LEN, &cbOutString, "S"); if (bind_before) CHKPrepare(T(SP_TEXT), strlen(SP_TEXT), "S"); CHKExecute("S"); odbc_command("DROP PROC spTestProc"); printf("Output:\n"); printf(" Return Code = %d\n", (int) ReturnCode); printf(" InParam = %d\n", (int) InParam); printf(" OutParam = %d\n", (int) OutParam); printf(" OutString = %s\n", OutString); if (InParam != OutParam) { fprintf(stderr, "InParam != OutParam\n"); return 1; } if (strcmp(OutString, "This is cool!") != 0) { fprintf(stderr, "Bad string returned\n"); return 1; } odbc_disconnect(); ODBC_FREE(); 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[]) { SQLLEN cb = SQL_NTS; odbc_use_version3 = 1; odbc_connect(); odbc_command_with_result(odbc_stmt, "drop proc sp_paramcore_test"); odbc_command("create proc sp_paramcore_test @s varchar(100) output as select @s = '12345'"); /* here we pass a NULL buffer for input SQL_NTS */ CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, OUTSTRING_LEN, 0, NULL, OUTSTRING_LEN, &cb, "S"); cb = SQL_NTS; CHKExecDirect(T(SP_TEXT), SQL_NTS, "E"); odbc_reset_statement(); /* here we pass a NULL buffer for input */ CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_VARCHAR, 18, 0, NULL, OUTSTRING_LEN, &cb, "S"); cb = 1; CHKExecDirect(T(SP_TEXT), SQL_NTS, "E"); odbc_reset_statement(); odbc_command("drop proc sp_paramcore_test"); odbc_command("create proc sp_paramcore_test @s numeric(10,2) output as select @s = 12345.6"); odbc_reset_statement(); #if 0 /* this fails even on native platforms */ /* here we pass a NULL buffer for output */ cb = sizeof(SQL_NUMERIC_STRUCT); SQLBindParameter(odbc_stmt, 1, SQL_PARAM_OUTPUT, SQL_C_NUMERIC, SQL_NUMERIC, 18, 0, NULL, OUTSTRING_LEN, &cb); odbc_read_error(); cb = 1; odbc_command_with_result(odbc_stmt, SP_TEXT); odbc_read_error(); odbc_reset_statement(); #endif odbc_command("drop proc sp_paramcore_test"); odbc_disconnect(); printf("Done successfully!\n"); return 0; }
static int test_insert(void *buf, SQLLEN buflen) { SQLHSTMT odbc_stmt = SQL_NULL_HSTMT; SQLLEN strlen_or_ind; const char *qstr = "insert into " TEST_TABLE_NAME " values (?)"; assert(odbc_conn); assert(odbc_env); /* allocate new statement handle */ CHKAllocHandle(SQL_HANDLE_STMT, odbc_conn, &odbc_stmt, "SI"); /* execute query */ CHKPrepare(T(qstr), SQL_NTS, "SI"); strlen_or_ind = buflen; CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, (SQLUINTEGER) (-1), 0, buf, buflen, &strlen_or_ind, "SI"); CHKExecute("SI"); /* this command shouldn't fail */ odbc_command("DECLARE @i INT"); SQLFreeHandle(SQL_HANDLE_STMT, odbc_stmt); return 0; }
int main(int argc, char *argv[]) { SQLSMALLINT num_params, cols; SQLLEN count; SQLINTEGER id; odbc_use_version3 = 1; odbc_connect(); odbc_command("create table #tester (id int not null, name varchar(20) not null)"); odbc_command("insert into #tester(id, name) values(1, 'abc')"); odbc_command("insert into #tester(id, name) values(2, 'duck')"); CHKPrepare(T("SELECT * FROM #tester WHERE id = ?"), SQL_NTS, "S"); CHKR(SQLNumParams, (odbc_stmt, &num_params), "S"); assert(num_params == 1); id = 1; CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, sizeof(id), NULL, "S"); CHKExecute("S"); CHKR(SQLFreeStmt, (odbc_stmt, SQL_RESET_PARAMS), "S"); CHKRowCount(&count, "S"); CHKNumResultCols(&cols, "S"); assert(cols == 2); odbc_disconnect(); return 0; }
static void test_params(void) { #define ARRAY_SIZE 2 const rows_set_t *p; SQLULEN len; SQLUINTEGER *ids = MALLOC_N(SQLUINTEGER,ARRAY_SIZE); SQLLEN *id_lens = MALLOC_N(SQLLEN,ARRAY_SIZE); unsigned long int h, l; unsigned int n; for (n = 0; n < ARRAY_SIZE; ++n) { ids[n] = n; id_lens[n] = 0; } /* test setting just some test pointers */ set_ipd_params1(int2ptr(0x01020304)); check_ipd_params(); set_ipd_params2(int2ptr(0xabcdef12)); check_ipd_params(); set_ipd_params3(int2ptr(0x87654321)); check_ipd_params(); /* now see results */ for (p = param_set; *p != NULL; ++p) { odbc_reset_statement(); len = 0xdeadbeef; len <<= 16; len <<= 16; len |= 12345678; (*p)(&len); check_ipd_params(); CHKSetStmtAttr(SQL_ATTR_PARAMSET_SIZE, (void *) int2ptr(ARRAY_SIZE), 0, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0, ids, 0, id_lens, "S"); odbc_command("INSERT INTO #tmp1(i) VALUES(?)"); SQLMoreResults(odbc_stmt); for (n = 0; n < ARRAY_SIZE; ++n) SQLMoreResults(odbc_stmt); l = len; len >>= 16; h = len >> 16; l &= 0xfffffffflu; if (h != 0 || l != 2) { fprintf(stderr, "Wrong number returned in param rows high %lu low %lu\n", h, l); exit(1); } } free(ids); free(id_lens); }
static void TestBinding(int minimun) { const char * const*p; SQLINTEGER n; SQLLEN n_len; sprintf(tmp, "DELETE FROM %s", table_name); odbc_command(tmp); /* insert with SQLPrepare/SQLBindParameter/SQLExecute */ sprintf(tmp, "INSERT INTO %s VALUES(?,?,?)", table_name); CHKPrepare(T(tmp), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &n, 0, &n_len, "S"); n_len = sizeof(n); for (n = 1, p = strings; p[0] && p[1]; p += 2, ++n) { SQLLEN s1_len, s2_len; unsigned int len; len = minimun ? (strlen(strings_hex[p-strings]) - 2) /4 : 40; CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_WCHAR, len, 0, (void *) p[0], 0, &s1_len, "S"); len = minimun ? (strlen(strings_hex[p+1-strings]) - 2) /4 : 40; /* FIXME this with SQL_VARCHAR produce wrong protocol data */ CHKBindParameter(3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_WVARCHAR, len, 0, (void *) p[1], 0, &s2_len, "S"); s1_len = strlen(p[0]); s2_len = strlen(p[1]); printf("insert #%d\n", (int) n); CHKExecute("S"); } /* 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); } odbc_reset_statement(); }
static void insert_test_auto(void) { SQLLEN sql_nts = SQL_NTS; SQLINTEGER id = 0; char string[64]; odbc_reset_statement(); 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("insert into test values (?, ?)"), SQL_NTS, "SI"); for (id = 0; id < 20; id++) { sprintf(string, "This is a test (%d)", (int) id); CHKExecute("SI"); } odbc_reset_statement(); }
static void test_with_conversions(void) { SQLLEN ind, ind2, ind3; char out2[30]; /* * test from Bower, Wayne * Cfr ML 2012-03-02 "[freetds] [unixODBC][Driver Manager]Function sequence error (SQL-HY010)" */ odbc_use_version3 = 1; odbc_connect(); odbc_command("IF OBJECT_ID('TMP_SP_Test_ODBC') IS NOT NULL DROP PROC TMP_SP_Test_ODBC"); odbc_command("create proc TMP_SP_Test_ODBC @i int,\n@o int output\nas\nset nocount on\nselect @o = 55\nreturn 9\n"); odbc_reset_statement(); CHKPrepare(T("{ ? = call TMP_SP_Test_ODBC (?, ?) }"), SQL_NTS, "S"); ind2 = 2; CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 80, 0, "10", 2, &ind2, "S"); ind3 = SQL_NULL_DATA; strcpy(out2, " "); CHKBindParameter(3, SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 1, out2, 29, &ind3, "S"); ind = 1; CHKBindParameter(1, SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 1, out2, 29, &ind, "S"); /* mssql returns SUCCESS */ CHKExecute("No"); ODBC_CHECK_COLS(0); odbc_reset_statement(); odbc_command("drop proc TMP_SP_Test_ODBC"); odbc_disconnect(); }
static void Test(const char *bind1, SQLSMALLINT type1, const char *bind2, SQLSMALLINT type2) { char sql[512]; char *val = "test"; SQLLEN ind = 4; int id = 1; ODBC_BUF *odbc_buf = NULL; SQLFreeStmt(odbc_stmt, SQL_RESET_PARAMS); ++test_num; sprintf(sql, "insert into #test_output values (%s, %s)", bind1, bind2); CHKPrepare(T(sql), strlen(sql), "S"); if (bind1[0] == '?') CHKBindParameter(id++, SQL_PARAM_INPUT, SQL_C_LONG, type1, 3, 0, &test_num, 0, &ind, "S"); if (bind2[0] == '?') CHKBindParameter(id++, SQL_PARAM_INPUT, SQL_C_CHAR, type2, strlen(val) + 1, 0, (SQLCHAR *) val, 0, &ind, "S"); CHKExecute("S"); ODBC_FREE(); }
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 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[]) { 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; }
static void Test0(int use_sql, const char *create_sql, const char *insert_sql, const char *select_sql) { #define ROWS 4 #define C_LEN 10 SQLUINTEGER n[ROWS]; char c[ROWS][C_LEN]; SQLLEN c_len[ROWS], n_len[ROWS]; SQLUSMALLINT statuses[ROWS]; SQLUSMALLINT i; SQLULEN num_row; SQLHSTMT stmt2; /* create test table */ odbc_command("IF OBJECT_ID('tempdb..#test') IS NOT NULL DROP TABLE #test"); odbc_command(create_sql); for (i = 1; i <= 6; ++i) { char sql_buf[80], data[10]; memset(data, 'a' + (i - 1), sizeof(data)); data[i] = 0; sprintf(sql_buf, insert_sql, data, i); odbc_command(sql_buf); } /* set cursor options */ odbc_reset_statement(); CHKSetStmtAttr(SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0, "S"); CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S"); CHKSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0, "S"); CHKSetStmtAttr(SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) statuses, 0, "S"); CHKSetStmtAttr(SQL_ATTR_ROWS_FETCHED_PTR, &num_row, 0, "S"); CHKSetCursorName(T("C1"), SQL_NTS, "S"); /* */ CHKExecDirect(T(select_sql), SQL_NTS, "S"); /* bind some rows at a time */ CHKBindCol(1, SQL_C_ULONG, n, 0, n_len, "S"); CHKBindCol(2, SQL_C_CHAR, c, C_LEN, c_len, "S"); /* allocate an additional statement */ CHKAllocStmt(&stmt2, "S"); while (CHKFetchScroll(SQL_FETCH_NEXT, 0, "SNo") == SQL_SUCCESS) { /* print, just for debug */ for (i = 0; i < num_row; ++i) printf("row %d i %d c %s\n", (int) (i + 1), (int) n[i], c[i]); printf("---\n"); /* delete a row */ i = 1; if (i > 0 && i <= num_row) { if (mssql2005) CHKSetPos(i, use_sql ? SQL_POSITION : SQL_DELETE, SQL_LOCK_NO_CHANGE, "SI"); else CHKSetPos(i, use_sql ? SQL_POSITION : SQL_DELETE, SQL_LOCK_NO_CHANGE, "S"); if (use_sql) { SWAP_STMT(stmt2); CHKPrepare(T("DELETE FROM #test WHERE CURRENT OF C1"), SQL_NTS, "S"); CHKExecute("S"); SWAP_STMT(stmt2); } } /* update another row */ i = 2; if (i > 0 && i <= num_row) { strcpy(c[i - 1], "foo"); c_len[i - 1] = 3; if (strstr(select_sql, "#a") == NULL || use_sql) { CHKSetPos(i, use_sql ? SQL_POSITION : SQL_UPDATE, SQL_LOCK_NO_CHANGE, "S"); } else { SQLTCHAR sqlstate[6]; SQLTCHAR msg[256]; n[i - 1] = 321; CHKSetPos(i, use_sql ? SQL_POSITION : SQL_UPDATE, SQL_LOCK_NO_CHANGE, "E"); CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, msg, ODBC_VECTOR_SIZE(msg), NULL, "S"); if (strstr(C(msg), "Invalid column name 'c'") == NULL) { fprintf(stderr, "Expected message not found at line %d\n", __LINE__); exit(1); } } if (use_sql) { SWAP_STMT(stmt2); CHKPrepare(T("UPDATE #test SET c=? WHERE CURRENT OF C1"), SQL_NTS, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, C_LEN, 0, c[i - 1], 0, NULL, "S"); CHKExecute("S"); /* FIXME this is not necessary for mssql driver */ SQLMoreResults(odbc_stmt); SWAP_STMT(stmt2); } } } SWAP_STMT(stmt2); CHKFreeStmt(SQL_DROP, "S"); SWAP_STMT(stmt2); odbc_reset_statement(); /* test values */ CheckNoRow("IF (SELECT COUNT(*) FROM #test) <> 4 SELECT 1"); CheckNoRow("IF NOT EXISTS(SELECT * FROM #test WHERE i = 3 AND c = 'ccc') SELECT 1"); CheckNoRow("IF NOT EXISTS(SELECT * FROM #test WHERE i = 4 AND c = 'dddd') SELECT 1"); if (strstr(select_sql, "#a") == NULL || use_sql) { CheckNoRow("IF NOT EXISTS(SELECT * FROM #test WHERE i = 2 AND c = 'foo') SELECT 1"); CheckNoRow("IF NOT EXISTS(SELECT * FROM #test WHERE i = 6 AND c = 'foo') SELECT 1"); } }
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; }
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; }
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(); }
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_rows(void) { const rows_set_t *p; SQLULEN len; SQLUINTEGER *ids = MALLOC_N(SQLUINTEGER,ARRAY_SIZE); SQLLEN *id_lens = MALLOC_N(SQLLEN,ARRAY_SIZE); unsigned long int h, l; unsigned int n; for (n = 0; n < ARRAY_SIZE; ++n) { ids[n] = n; id_lens[n] = 0; } /* test setting just some test pointers */ set_ird_params1(int2ptr(0x01020304)); check_ird_params(); set_ird_params2(int2ptr(0xabcdef12)); check_ird_params(); /* now see results */ for (p = row_set; ; ++p) { const char *test_name = NULL; odbc_reset_statement(); len = 0xdeadbeef; len <<= 16; len <<= 16; len |= 12345678; if (*p) (*p)(&len); check_ird_params(); #if 0 CHKSetStmtAttr(SQL_ATTR_PARAMSET_SIZE, (void *) int2ptr(ARRAY_SIZE), 0, "S"); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0, ids, 0, id_lens, "S"); #endif CHKBindCol(1, SQL_C_ULONG, ids, 0, id_lens, "S"); if (*p) { CHKSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE, (void *) int2ptr(ARRAY_SIZE), 0, "S"); odbc_command("SELECT DISTINCT i FROM #tmp1"); SQLFetch(odbc_stmt); test_name = "SQLSetStmtAttr"; } else { CHKSetStmtAttr(SQL_ROWSET_SIZE, (void *) int2ptr(ARRAY_SIZE), 0, "S"); odbc_command("SELECT DISTINCT i FROM #tmp1"); CHKExtendedFetch(SQL_FETCH_NEXT, 0, &len, NULL, "S"); test_name = "SQLExtendedFetch"; } SQLMoreResults(odbc_stmt); l = len; len >>= 16; h = len >> 16; l &= 0xfffffffflu; if (h != 0 || l != 2) { fprintf(stderr, "Wrong number returned in rows high %lu(0x%lx) low %lu(0x%lx) test %s\n", h, h, l, l, test_name); exit(1); } if (!*p) break; } free(ids); free(id_lens); }
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; }