unsigned int odbc_db_version_int(void) { unsigned int h, l; if (sscanf(odbc_db_version(), "%u.%u.", &h, &l) != 2) { fprintf(stderr, "Wrong db version: %s\n", odbc_db_version()); odbc_disconnect(); exit(1); } return (h << 24) | ((l & 0xFFu) << 16); }
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!"); } }
static void DoTest(int version3) { char name[128], params[128]; SQLSMALLINT type, is_unsigned; SQLINTEGER col_size, min_scale; SQLLEN ind1, ind2, ind3, ind4, ind5, ind6; int date_time_supported = 0; int name_version3; odbc_use_version3 = version3; name_version3 = version3; odbc_connect(); printf("Using ODBC version %d\n", version3 ? 3 : 2); /* test column name */ /* MS ODBC use always ODBC 3 names even in ODBC 2 mode */ if (!odbc_driver_is_freetds()) name_version3 = 1; CHKGetTypeInfo(SQL_ALL_TYPES, "SI"); TestName(1, "TYPE_NAME"); TestName(2, "DATA_TYPE"); TestName(3, name_version3 ? "COLUMN_SIZE" : "PRECISION"); TestName(4, "LITERAL_PREFIX"); TestName(5, "LITERAL_SUFFIX"); TestName(6, "CREATE_PARAMS"); TestName(7, "NULLABLE"); TestName(8, "CASE_SENSITIVE"); TestName(9, "SEARCHABLE"); TestName(10, "UNSIGNED_ATTRIBUTE"); TestName(11, name_version3 ? "FIXED_PREC_SCALE" : "MONEY"); TestName(12, name_version3 ? "AUTO_UNIQUE_VALUE" : "AUTO_INCREMENT"); TestName(13, "LOCAL_TYPE_NAME"); TestName(14, "MINIMUM_SCALE"); TestName(15, "MAXIMUM_SCALE"); /* TODO test these column for ODBC 3 */ /* ODBC 3.0 SQL_DATA_TYPE SQL_DATETIME_SUB NUM_PREC_RADIX INTERVAL_PRECISION */ Flushodbc_stmt(); /* TODO test if SQL_ALL_TYPES returns right numeric type for timestamp */ /* numeric type for data */ /* test for date/time support */ if (odbc_command_with_result(odbc_stmt, "select cast(getdate() as date)") == SQL_SUCCESS) date_time_supported = 1; SQLCloseCursor(odbc_stmt); #define CHECK_TYPE(in,out) CheckType(in, out, #in, __LINE__) /* under Sybase this type require extra handling, check it */ CHECK_TYPE(SQL_VARCHAR, SQL_VARCHAR); CHECK_TYPE(SQL_DATE, date_time_supported && !version3 ? SQL_DATE : SQL_UNKNOWN_TYPE); CHECK_TYPE(SQL_TIME, date_time_supported && !version3 ? SQL_TIME : SQL_UNKNOWN_TYPE); /* MS ODBC returns S1004 (HY004), TODO support it */ if (odbc_driver_is_freetds() || version3) { CHECK_TYPE(SQL_TYPE_DATE, date_time_supported && version3 ? SQL_TYPE_DATE : SQL_UNKNOWN_TYPE); CHECK_TYPE(SQL_TYPE_TIME, date_time_supported && version3 ? SQL_TYPE_TIME : SQL_UNKNOWN_TYPE); } /* TODO MS ODBC handle SQL_TIMESTAMP even for ODBC 3 */ if (odbc_driver_is_freetds()) CHECK_TYPE(SQL_TIMESTAMP, version3 ? SQL_UNKNOWN_TYPE : SQL_TIMESTAMP); else CHECK_TYPE(SQL_TIMESTAMP, version3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP); /* MS ODBC returns S1004 (HY004), TODO support it */ if (odbc_driver_is_freetds() || version3) { CHECK_TYPE(SQL_TYPE_TIMESTAMP, version3 ? SQL_TYPE_TIMESTAMP : SQL_UNKNOWN_TYPE); } /* TODO implement this part of test */ /* varchar/nvarchar before sysname */ /* test binding (not all column, required for Oracle) */ CHKGetTypeInfo(SQL_ALL_TYPES, "SI"); CHKBindCol(1, SQL_C_CHAR, name, sizeof(name), &ind1, "SI"); CHKBindCol(2, SQL_C_SSHORT, &type, 0, &ind2, "SI"); CHKBindCol(3, SQL_C_SLONG, &col_size, 0, &ind3, "SI"); CHKBindCol(6, SQL_C_CHAR, params, sizeof(params), &ind4, "SI"); CHKBindCol(10, SQL_C_SSHORT, &is_unsigned, 0, &ind5, "SI"); CHKBindCol(14, SQL_C_SSHORT, &min_scale, 0, &ind6, "SI"); while (CHKFetch("SNo") == SQL_SUCCESS) ; SQLFreeStmt(odbc_stmt, SQL_UNBIND); Flushodbc_stmt(); /* check WVARCHAR for no pending data */ if (odbc_db_is_microsoft() || strncmp(odbc_db_version(), "15.00.", 6) >= 0) { CHKGetTypeInfo(SQL_WVARCHAR, "SI"); CHKFetch("S"); if (odbc_db_is_microsoft()) CHKFetch("S"); CHKFetch("No"); CHKGetTypeInfo(SQL_BINARY, "SI"); } odbc_disconnect(); }
int main(int argc, char *argv[]) { int big_endian = 1; int test_2008_date_to_binary = 0; odbc_connect(); if (((char *) &big_endian)[0] == 1) big_endian = 0; Test("NUMERIC(18,2)", "123", SQL_C_NUMERIC, "38 0 1 7B"); /* all binary results */ /* cases (2) */ Test("CHAR(7)", "pippo", SQL_C_BINARY, "706970706F2020"); Test("TEXT", "mickey", SQL_C_BINARY, "6D69636B6579"); Test("VARCHAR(20)", "foo", SQL_C_BINARY, "666F6F"); Test("BINARY(5)", "qwer", SQL_C_BINARY, "7177657200"); Test("IMAGE", "cricetone", SQL_C_BINARY, "6372696365746F6E65"); Test("VARBINARY(20)", "teo", SQL_C_BINARY, "74656F"); /* TODO only MS ?? */ if (odbc_db_is_microsoft()) Test("TIMESTAMP", "abcdefghi", SQL_C_BINARY, "6162636465666768"); Test("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, big_endian ? "0000949700FBAA2C" : "979400002CAAFB00"); Test("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, big_endian ? "94970394" : "97949403"); Test("BIT", "1", SQL_C_BINARY, "01"); Test("BIT", "0", SQL_C_BINARY, "00"); Test("TINYINT", "231", SQL_C_BINARY, "E7"); Test("SMALLINT", "4321", SQL_C_BINARY, big_endian ? "10E1" : "E110"); Test("INT", "1234567", SQL_C_BINARY, big_endian ? "0012D687" : "87D61200"); if ((odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) || (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0)) { int old_result = result; Test("BIGINT", "123456789012345", SQL_C_BINARY, big_endian ? "00007048860DDF79" : "79DF0D8648700000"); if (result && strcmp(sbuf, "13000179DF0D86487000000000000000000000") == 0) { fprintf(stderr, "Ignore previous error. You should configure TDS 7.1 for this!!!\n"); if (!old_result) result = 0; } } Test("INT", "-123", SQL_C_CHAR, "4 -123"); Test("INT", "78654", SQL_C_WCHAR, "5 78654"); Test("VARCHAR(10)", " 51245 ", SQL_C_LONG, "51245"); Test("VARCHAR(20)", " 15.1245 ", SQL_C_NUMERIC, "38 0 1 0F"); Test("VARCHAR(20)", " 15 ", SQL_C_NUMERIC, "38 0 1 0F"); if (odbc_db_is_microsoft() && (strncmp(odbc_db_version(), "08.00.", 6) == 0 || strncmp(odbc_db_version(), "09.00.", 6) == 0)) { /* nvarchar without extended characters */ Test("NVARCHAR(20)", "test", SQL_C_CHAR, "4 test"); /* nvarchar with extended characters */ /* don't test with MS which usually have a not compatible encoding */ if (odbc_driver_is_freetds()) Test("NVARCHAR(20)", "0x830068006900f200", SQL_C_CHAR, "4 \x83hi\xf2"); Test("VARCHAR(20)", "test", SQL_C_WCHAR, "4 test"); /* nvarchar with extended characters */ Test("NVARCHAR(20)", "0x830068006900f200", SQL_C_WCHAR, "4 \x83hi\xf2"); Test("NVARCHAR(20)", "0xA406A5FB", SQL_C_WCHAR, "2 \\u06a4\\ufba5"); /* NVARCHAR -> SQL_C_LONG */ Test("NVARCHAR(20)", "-24785 ", SQL_C_LONG, "-24785"); } ignore_select_error = 1; Test("UNIVARCHAR(10)", "u&'\\06A4\\FBA5'", SQL_C_WCHAR, "2 \\u06a4\\ufba5"); /* case (1) */ Test("DECIMAL", "1234.5678", SQL_C_BINARY, "120001D3040000000000000000000000000000"); Test("NUMERIC", "8765.4321", SQL_C_BINARY, "1200013D220000000000000000000000000000"); Test("FLOAT", "1234.5678", SQL_C_BINARY, big_endian ? "40934A456D5CFAAD" : "ADFA5C6D454A9340"); Test("REAL", "8765.4321", SQL_C_BINARY, big_endian ? "4608F5BA" : "BAF50846"); Test("SMALLMONEY", "765.4321", SQL_C_BINARY, big_endian ? "0074CBB1" : "B1CB7400"); Test("MONEY", "4321234.5678", SQL_C_BINARY, big_endian ? "0000000A0FA8114E" : "0A0000004E11A80F"); /* behavior is different from MS ODBC */ if (odbc_db_is_microsoft()) { Test("NCHAR(7)", "donald", SQL_C_BINARY, "64006F006E0061006C0064002000"); Test("NTEXT", "duck", SQL_C_BINARY, "6400750063006B00"); Test("NVARCHAR(20)", "daffy", SQL_C_BINARY, "64006100660066007900"); } if (odbc_db_is_microsoft()) Test("UNIQUEIDENTIFIER", "0DDF3B64-E692-11D1-AB06-00AA00BDD685", SQL_C_BINARY, big_endian ? "0DDF3B64E69211D1AB0600AA00BDD685" : "643BDF0D92E6D111AB0600AA00BDD685"); /* case (4) */ Test("DATETIME", "2006-06-09 11:22:44", SQL_C_CHAR, "23 2006-06-09 11:22:44.000"); Test("SMALLDATETIME", "2006-06-12 22:37:21", SQL_C_CHAR, "19 2006-06-12 22:37:00"); Test("DATETIME", "2006-06-09 11:22:44", SQL_C_WCHAR, "23 2006-06-09 11:22:44.000"); Test("SMALLDATETIME", "2006-06-12 22:37:21", SQL_C_WCHAR, "19 2006-06-12 22:37:00"); if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) { Test("SQL_VARIANT", "CAST('123' AS INT)", SQL_C_CHAR, "3 123"); Test("SQL_VARIANT", "CAST('hello' AS CHAR(6))", SQL_C_CHAR, "6 hello "); Test("SQL_VARIANT", "CAST('ciao' AS VARCHAR(10))", SQL_C_CHAR, "4 ciao"); Test("SQL_VARIANT", "CAST('foo' AS NVARCHAR(10))", SQL_C_CHAR, "3 foo"); Test("SQL_VARIANT", "CAST('Super' AS NCHAR(8))", SQL_C_CHAR, "8 Super "); Test("SQL_VARIANT", "CAST('321' AS VARBINARY(10))", SQL_C_CHAR, "6 333231"); /* for some reasons MS ODBC seems to convert -123.4 to -123.40000000000001 */ Test("SQL_VARIANT", "CAST('-123.5' AS FLOAT)", SQL_C_CHAR, "6 -123.5"); Test("SQL_VARIANT", "CAST('-123.4' AS NUMERIC(10,2))", SQL_C_CHAR, "7 -123.40"); Test("SQL_VARIANT", "CAST('0DDF3B64-E692-11D1-AB06-00AA00BDD685' AS UNIQUEIDENTIFIER)", SQL_C_CHAR, "36 0DDF3B64-E692-11D1-AB06-00AA00BDD685"); } if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u) { Test("VARCHAR(MAX)", "goodbye!", SQL_C_CHAR, "8 goodbye!"); Test("NVARCHAR(MAX)", "Micio mao", SQL_C_CHAR, "9 Micio mao"); Test("VARBINARY(MAX)", "ciao", SQL_C_BINARY, "6369616F"); Test("XML", "<a b=\"aaa\"><b>ciao</b>hi</a>", SQL_C_CHAR, "28 <a b=\"aaa\"><b>ciao</b>hi</a>"); /* XML with schema */ odbc_command("IF EXISTS(SELECT * FROM sys.xml_schema_collections WHERE [name] = 'test_schema') DROP XML SCHEMA COLLECTION test_schema"); odbc_command("CREATE XML SCHEMA COLLECTION test_schema AS '<schema xmlns=\"http://www.w3.org/2001/XMLSchema\"><element name=\"test\" type=\"string\"/></schema>'"); Test("XML(test_schema)", "<test>ciao</test>", SQL_C_CHAR, "17 <test>ciao</test>"); odbc_command("DROP XML SCHEMA COLLECTION test_schema"); } /* MSSQL 2008*/ if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x0A000000u) { int save_result = result; /* check right protocol */ result = 0; test_2008_date_to_binary = 1; Test("DATE", "1923-12-02", SQL_C_BINARY, big_endian ? "0783000C0002" : "83070C000200"); if (result) { result = 0; Test("DATE", "1923-12-02", SQL_C_BINARY, "31003900320033002D00310032002D0030003200"); if (!result) { printf("previous error expected: wrong protocol used\n"); test_2008_date_to_binary = 0; } } if (save_result) result = 1; Test("DATE", "1923-12-02", SQL_C_CHAR, "10 1923-12-02"); Test("TIME", "12:23:45", SQL_C_CHAR, "16 12:23:45.0000000"); Test("TIME(4)", "12:23:45.765", SQL_C_CHAR, "13 12:23:45.7650"); Test("TIME(0)", "12:23:45.765", SQL_C_CHAR, "8 12:23:46"); Test("DATETIME2", "2011-08-10 12:23:45", SQL_C_CHAR, "27 2011-08-10 12:23:45.0000000"); Test("DATETIME2(4)", "12:23:45.345888", SQL_C_CHAR, "24 1900-01-01 12:23:45.3459"); Test("DATETIME2(0)", "2011-08-10 12:23:45.93", SQL_C_CHAR, "19 2011-08-10 12:23:46"); Test("DATETIMEOFFSET", "12:23:45 -02:30", SQL_C_CHAR, "34 1900-01-01 12:23:45.0000000 -02:30"); Test("DATETIMEOFFSET(4)", "12:23:45", SQL_C_CHAR, "31 1900-01-01 12:23:45.0000 +00:00"); } if (test_2008_date_to_binary) { Test("DATE", "1923-12-02", SQL_C_BINARY, big_endian ? "0783000C0002" : "83070C000200"); Test("TIME", "12:23:45", SQL_C_BINARY, big_endian ? "000C0017002D000000000000" : "0C0017002D00000000000000"); Test("TIME(4)", "12:23:45.765", SQL_C_BINARY, big_endian ? "000C0017002D00002D98F940" : "0C0017002D00000040F9982D"); Test("DATETIME2", "2011-08-10 12:23:45", SQL_C_BINARY, big_endian ? "07DB0008000A000C0017002D00000000" : "DB0708000A000C0017002D0000000000"); Test("DATETIME2(4)", "12:23:45", SQL_C_BINARY, big_endian ? "076C00010001000C0017002D00000000" : "6C07010001000C0017002D0000000000"); Test("DATETIMEOFFSET", "12:23:45 -08:30", SQL_C_BINARY, big_endian ? "076C00010001000C0017002D00000000FFF8FFE2" : "6C07010001000C0017002D0000000000F8FFE2FF"); Test("DATETIMEOFFSET(4)", "12:23:45", SQL_C_BINARY, big_endian ? "076C00010001000C0017002D0000000000000000" : "6C07010001000C0017002D000000000000000000"); } if (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0) { /* FIXME sure ?? with date and time always ?? */ Test("DATE", "1923-12-02", SQL_C_CHAR, "23 1923-12-02 00:00:00.000"); Test("TIME", "12:23:45", SQL_C_CHAR, "23 1900-01-01 12:23:45.000"); } odbc_disconnect(); if (!result) printf("Done successfully!\n"); return result; }