void odbc_init_parser(FILE *f) { if (parse_file) odbc_fatal("parser file already setup\n"); parse_file = f; odbc_line_num = 0; odbc_tds_version(); }
static void AllTests(void) { struct tm *ltime; char buf[80]; time_t curr_time; SQLINTEGER y, m, d; char date[128]; printf("use_cursors %d exec_direct %d prepare_before %d\n", use_cursors, exec_direct, prepare_before); /* test some NULLs */ NullInput(SQL_C_CHAR, SQL_VARCHAR, "VARCHAR(100)"); NullInput(SQL_C_CHAR, SQL_LONGVARCHAR, "TEXT"); NullInput(SQL_C_LONG, SQL_INTEGER, "INTEGER"); NullInput(SQL_C_LONG, SQL_LONGVARCHAR, "TEXT"); NullInput(SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, "DATETIME"); NullInput(SQL_C_FLOAT, SQL_REAL, "FLOAT"); NullInput(SQL_C_NUMERIC, SQL_LONGVARCHAR, "TEXT"); if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) NullInput(SQL_C_BIT, SQL_BIT, "BIT"); NullInput(SQL_C_DOUBLE, SQL_DOUBLE, "MONEY"); /* FIXME why should return 38 0 as precision and scale ?? correct ?? */ precision = 18; TestOutput("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "18 0 1 7B"); TestOutput("DECIMAL(18,2)", "123", SQL_C_NUMERIC, SQL_DECIMAL, "18 0 1 7B"); precision = 38; TestOutput("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "38 0 1 7B"); TestInput(SQL_C_LONG, "INTEGER", SQL_VARCHAR, "VARCHAR(20)", "12345"); TestInput(SQL_C_LONG, "INTEGER", SQL_LONGVARCHAR, "TEXT", "12345"); /* * MS driver behavior for output parameters is different * former returns "313233" while newer "333133323333" */ if (odbc_driver_is_freetds()) TestOutput("VARCHAR(20)", "313233", SQL_C_BINARY, SQL_VARCHAR, "333133323333"); only_test = 1; precision = 3; if (TestOutput("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ssssssl", 2004, 2, 24, 15, 16, 17, 0))) { /* FIXME our driver ignore precision for date */ precision = 3; /* Some MS driver incorrectly prepare with smalldatetime*/ if (!use_cursors || odbc_driver_is_freetds()) { TestOutput("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ll", 0x9497, 0xFBAA2C)); } TestOutput("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ll", 0x9497, 0xFB9640)); } else { TestOutput("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ssssssl", 2004, 2, 24, 15, 16, 0, 0)); } TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34"); /* test timestamp millisecond round off */ TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.001 -> 2005-07-22 09:51:34.000"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.002 -> 2005-07-22 09:51:34.003"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.003 -> 2005-07-22 09:51:34.003"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.004 -> 2005-07-22 09:51:34.003"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.005 -> 2005-07-22 09:51:34.007"); TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.006 -> 2005-07-22 09:51:34.007"); /* FIXME on ms driver first SQLFetch return SUCCESS_WITH_INFO for truncation error */ TestInput(SQL_C_TYPE_DATE, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 13:02:03 -> 2005-07-22 00:00:00"); /* replace date information with current date */ time(&curr_time); ltime = localtime(&curr_time); y = ltime->tm_year + 1900; m = ltime->tm_mon + 1; d = ltime->tm_mday; /* server concept of data can be different so try ask to server */ odbc_command("SELECT GETDATE()"); SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, date, sizeof(date), NULL); if (SQLFetch(odbc_stmt) == SQL_SUCCESS) { int a, b, c; if (sscanf(date, "%d-%d-%d", &a, &b, &c) == 3) { y = a; m = b; d = c; } } SQLFetch(odbc_stmt); SQLMoreResults(odbc_stmt); SQLFreeStmt(odbc_stmt, SQL_UNBIND); sprintf(buf, "2003-07-22 13:02:03 -> %04d-%02d-%02d 13:02:03", (int) y, (int) m, (int) d); TestInput(SQL_C_TYPE_TIME, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", buf); TestInput(SQL_C_FLOAT, "FLOAT", SQL_REAL, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "REAL", SQL_REAL, "FLOAT", "-1234.25"); TestInput(SQL_C_FLOAT, "REAL", SQL_REAL, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "FLOAT", SQL_REAL, "FLOAT", "-1234.25"); TestInput(SQL_C_FLOAT, "FLOAT", SQL_FLOAT, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "REAL", SQL_FLOAT, "FLOAT", "-1234.25"); TestInput(SQL_C_FLOAT, "FLOAT", SQL_DOUBLE, "FLOAT", "1234.25"); TestInput(SQL_C_DOUBLE, "REAL", SQL_DOUBLE, "FLOAT", "-1234.25"); TestInput(SQL_C_UTINYINT, "TINYINT", SQL_TINYINT, "TINYINT", "231"); TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_NUMERIC, "NUMERIC(20,3)", "765432.2 -> 765432"); TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_VARCHAR, "VARCHAR(20)", "578246.234 -> 578246"); TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_LONGVARCHAR, "TEXT", "578246.234 -> 578246"); TestInput(SQL_C_CHAR, "VARCHAR(100)", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_CHAR, "TEXT", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_CHAR, "VARCHAR(100)", SQL_LONGVARBINARY, "IMAGE", "4145544F -> AETO"); TestInput(SQL_C_BINARY, "VARBINARY(100)", SQL_VARCHAR, "VARCHAR(20)", "0x4145544F -> AETO"); TestInput(SQL_C_BINARY, "IMAGE", SQL_VARCHAR, "VARCHAR(20)", "0x4145544F -> AETO"); TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "0"); TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "1"); TestInput(SQL_C_DOUBLE, "MONEY", SQL_DOUBLE, "MONEY", "123.34"); TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_VARCHAR, "VARCHAR(20)", "1EasyTest"); TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "TEXT", "1EasyTest"); TestInput(SQL_C_WCHAR, "VARCHAR(10)", SQL_VARCHAR, "VARCHAR(10)", "Test 12345"); TestInput(SQL_C_WCHAR, "VARCHAR(10)", SQL_LONGVARCHAR, "TEXT", "Test 12345"); /* TODO use collate in syntax if available */ TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_VARCHAR, "VARCHAR(20)", "me\xf4"); TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "TEXT", "me\xf4"); precision = 6; /* output from char with conversions */ TestOutput("VARCHAR(20)", "foo test", SQL_C_CHAR, SQL_VARCHAR, "6 foo te"); /* TODO use collate in sintax if available */ TestOutput("VARCHAR(20)", "0xf8f9", SQL_C_CHAR, SQL_VARCHAR, "2 \xf8\xf9"); if ((odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u && odbc_tds_version() > 0x700) || (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0)) { TestOutput("BIGINT", "-987654321065432", SQL_C_BINARY, SQL_BIGINT, big_endian ? "FFFC7DBBCF083228" : "283208CFBB7DFCFF"); TestInput(SQL_C_SBIGINT, "BIGINT", SQL_BIGINT, "BIGINT", "-12345678901234"); } if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) { TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "test"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "test"); /* test for invalid stream due to truncation*/ TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "01234567890"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "01234567890"); #ifdef ENABLE_DEVELOPING check_truncation = 1; TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "012345678901234567890"); check_truncation = 1; TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "012345678901234567890"); #endif TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "\xa3h\xf9 -> 0xA3006800f900"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "\xa3h\xf9 -> 0xA3006800f900"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "0xA3006800f900 -> \xa3h\xf9"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "0xA3006800f900 -> \xa3h\xf9"); TestInput(SQL_C_LONG, "INT", SQL_WVARCHAR, "NVARCHAR(100)", "45236"); TestInput(SQL_C_LONG, "INT", SQL_WLONGVARCHAR, "NTEXT", "45236"); precision = 6; TestOutput("NVARCHAR(20)", "foo test", SQL_C_CHAR, SQL_WVARCHAR, "6 foo te"); precision = 12; TestOutput("NVARCHAR(20)", "foo test", SQL_C_CHAR, SQL_WVARCHAR, "8 foo test"); /* TODO use collate in sintax if available */ TestOutput("NVARCHAR(20)", "0xf800f900", SQL_C_CHAR, SQL_WVARCHAR, "2 \xf8\xf9"); TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WVARCHAR, "NVARCHAR(10)", "1EasyTest2"); TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WLONGVARCHAR, "NTEXT", "1EasyTest2"); use_nts = 1; TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WVARCHAR, "NVARCHAR(10)", "1EasyTest3"); use_nts = 1; TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WLONGVARCHAR, "NTEXT", "1EasyTest3"); TestInput(SQL_C_WCHAR, "NVARCHAR(3)", SQL_WVARCHAR, "NVARCHAR(3)", "0xf800a300bc06"); TestInput(SQL_C_WCHAR, "NVARCHAR(3)", SQL_WLONGVARCHAR, "NTEXT", "0xf800a300bc06"); TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_INTEGER, "INT", " -423785 -> -423785"); TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_CHAR, "NTEXT", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO"); TestInput(SQL_C_BINARY, "VARBINARY(100)", SQL_WVARCHAR, "NVARCHAR(20)", "0x4100450054004F00 -> AETO"); TestInput(SQL_C_BINARY, "IMAGE", SQL_WVARCHAR, "NVARCHAR(20)", "0x4100450054004F00 -> AETO"); } if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u) { TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "VARCHAR(MAX)", "1EasyTest"); TestInput(SQL_C_BINARY, "VARBINARY(20)", SQL_LONGVARBINARY, "VARBINARY(MAX)", "Anything will suite!"); } }
const char * odbc_get_cmd_line(char **p_s, int *cond) { while (fgets(line_buf, sizeof(line_buf), parse_file)) { char *p = line_buf; const char *cmd; ++odbc_line_num; cmd = odbc_get_tok(&p); /* skip comments */ if (!cmd || cmd[0] == '#' || cmd[0] == 0 || cmd[0] == '\n') continue; /* conditional statement */ if (!strcmp(cmd, "else")) { int c = pop_condition(); push_condition(c); *cond = c && !*cond; continue; } if (!strcmp(cmd, "endif")) { *cond = pop_condition(); continue; } if (!strcmp(cmd, "if")) { push_condition(*cond); if (*cond) *cond = get_condition(&p); continue; } if (strcmp(cmd, "tds_version_cmp") == 0) { const char *bool_name = odbc_get_tok(&p); const char *cmp = odbc_get_tok(&p); const char *s_ver = odbc_get_tok(&p); int ver = odbc_tds_version(); int expected; int res; unsigned M, m; if (!cmp || !s_ver) odbc_fatal(": missing parameters\n"); if (sscanf(s_ver, "%u.%u", &M, &m) != 2) odbc_fatal(": invalid version %s\n", s_ver); expected = M * 0x100u + m; if (strcmp(cmp, ">") == 0) res = ver > expected; else if (strcmp(cmp, ">=") == 0) res = ver >= expected; else if (strcmp(cmp, "<") == 0) res = ver < expected; else if (strcmp(cmp, "<=") == 0) res = ver <= expected; else if (strcmp(cmp, "==") == 0) res = ver == expected; else if (strcmp(cmp, "!=") == 0) res = ver != expected; else odbc_fatal(": invalid operator %s\n", cmp); if (*cond) odbc_set_bool(bool_name, res); continue; } *p_s = p; return cmd; } return NULL; }
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; }