static void ReadErrorConn(void) { ODBC_BUF *odbc_buf = NULL; SQLTCHAR *err = (SQLTCHAR *) ODBC_GET(sizeof(odbc_err)*sizeof(SQLTCHAR)); SQLTCHAR *state = (SQLTCHAR *) ODBC_GET(sizeof(odbc_sqlstate)*sizeof(SQLTCHAR)); memset(odbc_err, 0, sizeof(odbc_err)); memset(odbc_sqlstate, 0, sizeof(odbc_sqlstate)); CHKGetDiagRec(SQL_HANDLE_DBC, odbc_conn, 1, state, NULL, err, sizeof(odbc_err), NULL, "SI"); strcpy(odbc_err, C(err)); strcpy(odbc_sqlstate, C(state)); ODBC_FREE(); printf("Message: '%s' %s\n", odbc_sqlstate, odbc_err); }
void odbc_read_error(void) { ODBC_BUF *odbc_buf = NULL; SQLTCHAR *err = ODBC_GET(sizeof(odbc_err)*sizeof(SQLTCHAR)); SQLTCHAR *state = ODBC_GET(sizeof(odbc_sqlstate)*sizeof(SQLTCHAR)); memset(odbc_err, 0, sizeof(odbc_err)); memset(odbc_sqlstate, 0, sizeof(odbc_sqlstate)); CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, state, NULL, err, sizeof(odbc_err), NULL, "SI"); strcpy(odbc_err, C(err)); strcpy(odbc_sqlstate, C(state)); ODBC_FREE(); printf("Message: '%s' %s\n", odbc_sqlstate, odbc_err); }
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; }
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(); }
static void query_test(int prepare, SQLRETURN expected, const char *expected_status) { #define DESC_LEN 51 #define ARRAY_SIZE 10 SQLUINTEGER *ids = XMALLOC_N(SQLUINTEGER,ARRAY_SIZE); typedef SQLCHAR desc_t[DESC_LEN]; desc_t *descs = XMALLOC_N(desc_t, ARRAY_SIZE); SQLLEN *id_lens = XMALLOC_N(SQLLEN,ARRAY_SIZE), *desc_lens = XMALLOC_N(SQLLEN,ARRAY_SIZE); SQLUSMALLINT i, *statuses = XMALLOC_N(SQLUSMALLINT,ARRAY_SIZE); unsigned *num_errors = XMALLOC_N(unsigned, ARRAY_SIZE); SQLULEN processed; RETCODE ret; char status[20]; SQLTCHAR *err = ODBC_GET(sizeof(odbc_err)*sizeof(SQLTCHAR)); SQLTCHAR *state = ODBC_GET(sizeof(odbc_sqlstate)*sizeof(SQLTCHAR)); assert(odbc_stmt != SQL_NULL_HSTMT); odbc_reset_statement(); odbc_command_with_result(odbc_stmt, "drop table #tmp1"); odbc_command("create table #tmp1 (id tinyint, value char(20))"); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAMSET_SIZE, (void *) ARRAY_SIZE, 0); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAM_STATUS_PTR, statuses, 0); SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &processed, 0); SQLBindParameter(odbc_stmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0, ids, 0, id_lens); SQLBindParameter(odbc_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, DESC_LEN - 1, 0, descs, DESC_LEN, desc_lens); processed = ARRAY_SIZE + 1; for (i = 0; i < ARRAY_SIZE; i++) { statuses[i] = SQL_PARAM_DIAG_UNAVAILABLE; ids[i] = (i + 1) * multiply; sprintf((char *) descs[i], "data %d", i * 7); id_lens[i] = 0; desc_lens[i] = SQL_NTS; num_errors[i] = 0; } multiply = 90; if (!prepare) { ret = SQLExecDirect(odbc_stmt, test_query, SQL_NTS); } else { SQLPrepare(odbc_stmt, test_query, SQL_NTS); ret = SQLExecute(odbc_stmt); } if (processed > ARRAY_SIZE) { char buf[256]; sprintf(buf, "Invalid processed number: %d", (int) processed); ODBC_REPORT_ERROR(buf); } for (i = 1; CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, i, state, NULL, err, sizeof(odbc_err), NULL, "SINo") != SQL_NO_DATA; ++i) { SQLINTEGER row; strcpy(odbc_err, C(err)); strcpy(odbc_sqlstate, C(state)); CHKGetDiagField(SQL_HANDLE_STMT, odbc_stmt, i, SQL_DIAG_ROW_NUMBER, &row, sizeof(row), NULL, "S"); if (row == SQL_ROW_NUMBER_UNKNOWN) continue; if (row < 1 || row > ARRAY_SIZE) { fprintf(stderr, "invalid row %d returned reading error number %d\n", (int) row, i); exit(1); } ++num_errors[row-1]; printf("for row %2d returned '%s' %s\n", (int) row, odbc_sqlstate, odbc_err); } for (i = 0; i < processed; ++i) { int has_diag = 0; switch (statuses[i]) { case SQL_PARAM_SUCCESS_WITH_INFO: has_diag = 1; case SQL_PARAM_SUCCESS: status[i] = 'V'; break; case SQL_PARAM_ERROR: has_diag = 1; status[i] = '!'; break; case SQL_PARAM_UNUSED: status[i] = ' '; break; case SQL_PARAM_DIAG_UNAVAILABLE: status[i] = '?'; break; default: fprintf(stderr, "Invalid status returned %d\n", statuses[i]); exit(1); } if (has_diag) { if (!num_errors[i]) { fprintf(stderr, "Diagnostics not returned for status %d\n", i); failure = 1; } } else { if (num_errors[i]) { fprintf(stderr, "Diagnostics returned for status %d\n", i); failure = 1; } } } status[i] = 0; if (ret != expected || strcmp(expected_status, status) != 0) { fprintf(stderr, "Invalid result: got %d \"%s\" expected %d \"%s\" processed %d\n", ret, status, expected, expected_status, (int) processed); if (ret != SQL_SUCCESS) odbc_read_error(); failure = 1; odbc_reset_statement(); return; } odbc_reset_statement(); }