LCOV - code coverage report
Current view: top level - src/odbc/unittests - typeinfo.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 94 104 90.4 %
Date: 2024-04-18 20:40:06 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : static void
       4         240 : TestName(int index, const char *expected_name)
       5             : {
       6         240 :         ODBC_BUF *odbc_buf = NULL;
       7             :         SQLTCHAR name[128];
       8             :         char buf[256];
       9             :         SQLSMALLINT len, type;
      10             : 
      11             : #define NAME_TEST \
      12             :         do { \
      13             :                 if (strcmp(C(name), expected_name) != 0) \
      14             :                 { \
      15             :                         sprintf(buf, "wrong name in column %d expected '%s' got '%s'", index, expected_name, C(name)); \
      16             :                         ODBC_REPORT_ERROR(buf); \
      17             :                 } \
      18             :         } while(0)
      19             : 
      20             :         /* retrieve with SQLDescribeCol */
      21         240 :         CHKDescribeCol(index, name, TDS_VECTOR_SIZE(name), &len, &type, NULL, NULL, NULL, "S");
      22         240 :         NAME_TEST;
      23             : 
      24             :         /* retrieve with SQLColAttribute */
      25         240 :         CHKColAttribute(index, SQL_DESC_NAME, name, sizeof(name), &len, NULL, "S");
      26         240 :         if (odbc_db_is_microsoft())
      27         180 :                 NAME_TEST;
      28         240 :         CHKColAttribute(index, SQL_DESC_LABEL, name, sizeof(name), &len, NULL, "S");
      29         240 :         NAME_TEST;
      30         240 :         ODBC_FREE();
      31         240 : }
      32             : 
      33             : static void
      34          84 : Flushodbc_stmt(void)
      35             : {
      36          84 :         while (CHKFetch("SNo") == SQL_SUCCESS)
      37             :                 ;
      38             : 
      39             :         /* Sybase store procedure seems to return extra empty results */
      40          84 :         while (CHKMoreResults("SNo") == SQL_SUCCESS)
      41             :                 ;
      42          84 : }
      43             : 
      44             : static void
      45          52 : CheckType(SQLSMALLINT type, SQLSMALLINT expected, const char *string_type, int line)
      46             : {
      47             :         SQLSMALLINT out_type;
      48             :         SQLLEN ind;
      49             :         SQLRETURN RetCode;
      50             : 
      51          52 :         printf("CheckType %d\n", line);
      52          52 :         CHKBindCol(2, SQL_C_SSHORT, &out_type, 0, &ind, "SI");
      53          52 :         CHKGetTypeInfo(type, "SI");
      54          52 :         RetCode = CHKFetch("SNo");
      55          52 :         switch (RetCode) {
      56          44 :         case SQL_SUCCESS:
      57          44 :                 if (expected == SQL_UNKNOWN_TYPE) {
      58           0 :                         fprintf(stderr, "Data not expected (type %d - %s) line %d\n", type, string_type, line);
      59           0 :                         odbc_disconnect();
      60           0 :                         exit(1);
      61             :                 }
      62          44 :                 if (expected != out_type) {
      63           0 :                         fprintf(stderr, "Got type %d expected %d. Input type %d - %s line %d\n", out_type, expected, type, string_type, line);
      64           0 :                         odbc_disconnect();
      65           0 :                         exit(1);
      66             :                 }
      67             :                 break;
      68           8 :         case SQL_NO_DATA:
      69           8 :                 if (expected != SQL_UNKNOWN_TYPE) {
      70           0 :                         fprintf(stderr, "Data expected. Input type %d - %s line %d\n", type, string_type, line);
      71           0 :                         odbc_disconnect();
      72           0 :                         exit(1);
      73             :                 }
      74             :                 break;
      75             :         }
      76             : 
      77          52 :         SQLFreeStmt(odbc_stmt, SQL_UNBIND);
      78             : 
      79          52 :         Flushodbc_stmt();
      80          52 : }
      81             : 
      82             : static void
      83          16 : DoTest(int version3)
      84             : {
      85             :         char name[128], params[128];
      86             :         SQLSMALLINT type, is_unsigned;
      87             :         SQLINTEGER col_size, min_scale;
      88             :         SQLLEN ind1, ind2, ind3, ind4, ind5, ind6;
      89          16 :         int date_time_supported = 0;
      90             :         int name_version3;
      91             :         int tdsver;
      92             : 
      93          16 :         odbc_use_version3 = version3;
      94          16 :         name_version3 = version3;
      95             : 
      96          16 :         odbc_connect();
      97             : 
      98          16 :         printf("Using ODBC version %d\n", version3 ? 3 : 2);
      99             : 
     100          16 :         tdsver = odbc_tds_version();
     101             : 
     102             :         /* test column name */
     103             :         /* MS ODBC use always ODBC 3 names even in ODBC 2 mode */
     104          16 :         if (!odbc_driver_is_freetds())
     105           0 :                 name_version3 = 1;
     106          16 :         CHKGetTypeInfo(SQL_ALL_TYPES, "SI");
     107          16 :         TestName(1, "TYPE_NAME");
     108          16 :         TestName(2, "DATA_TYPE");
     109          16 :         TestName(3, name_version3 ? "COLUMN_SIZE" : "PRECISION");
     110          16 :         TestName(4, "LITERAL_PREFIX");
     111          16 :         TestName(5, "LITERAL_SUFFIX");
     112          16 :         TestName(6, "CREATE_PARAMS");
     113          16 :         TestName(7, "NULLABLE");
     114          16 :         TestName(8, "CASE_SENSITIVE");
     115          16 :         TestName(9, "SEARCHABLE");
     116          16 :         TestName(10, "UNSIGNED_ATTRIBUTE");
     117          16 :         TestName(11, name_version3 ? "FIXED_PREC_SCALE" : "MONEY");
     118          16 :         TestName(12, name_version3 ? "AUTO_UNIQUE_VALUE" : "AUTO_INCREMENT");
     119          16 :         TestName(13, "LOCAL_TYPE_NAME");
     120          16 :         TestName(14, "MINIMUM_SCALE");
     121          16 :         TestName(15, "MAXIMUM_SCALE");
     122             : 
     123             :         /* TODO test these column for ODBC 3 */
     124             :         /* ODBC 3.0 SQL_DATA_TYPE SQL_DATETIME_SUB NUM_PREC_RADIX INTERVAL_PRECISION */
     125             : 
     126          16 :         Flushodbc_stmt();
     127             : 
     128             :         /* TODO test if SQL_ALL_TYPES returns right numeric type for timestamp */
     129             : 
     130             :         /* numeric type for data */
     131             : 
     132             :         /* test for date/time support */
     133          16 :         if (odbc_command_with_result(odbc_stmt, "select cast(getdate() as date)") == SQL_SUCCESS)
     134           8 :                 date_time_supported = 1;
     135          16 :         if (odbc_db_is_microsoft() && tdsver < 0x703)
     136           8 :                 date_time_supported = 0;
     137          16 :         SQLCloseCursor(odbc_stmt);
     138             : 
     139             : #define CHECK_TYPE(in,out) CheckType(in, out, #in, __LINE__)
     140             : 
     141             :         /* under Sybase this type require extra handling, check it */
     142          16 :         CHECK_TYPE(SQL_VARCHAR, SQL_VARCHAR);
     143             : 
     144          16 :         if (version3) {
     145             :                 /* MS ODBC returns S1004 (HY004), TODO support it */
     146           8 :                 CHECK_TYPE(SQL_TYPE_DATE, date_time_supported ? SQL_TYPE_DATE : SQL_UNKNOWN_TYPE);
     147           8 :                 if (!odbc_db_is_microsoft())
     148           2 :                         CHECK_TYPE(SQL_TYPE_TIME, date_time_supported ? SQL_TYPE_TIME : SQL_UNKNOWN_TYPE);
     149             :                 /* MS ODBC returns S1004 (HY004), TODO support it */
     150           8 :                 CHECK_TYPE(SQL_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP);
     151             :         } else {
     152           8 :                 CHECK_TYPE(SQL_DATE, date_time_supported ? SQL_DATE : SQL_UNKNOWN_TYPE);
     153           8 :                 if (!odbc_db_is_microsoft())
     154           2 :                         CHECK_TYPE(SQL_TIME, date_time_supported ? SQL_TIME : SQL_UNKNOWN_TYPE);
     155             :                 /* TODO MS ODBC handle SQL_TIMESTAMP even for ODBC 3 */
     156           8 :                 CHECK_TYPE(SQL_TIMESTAMP, SQL_TIMESTAMP);
     157             :         }
     158             : 
     159             :         /* TODO implement this part of test */
     160             :         /* varchar/nvarchar before sysname */
     161             : 
     162             :         /* test binding (not all column, required for Oracle) */
     163          16 :         CHKGetTypeInfo(SQL_ALL_TYPES, "SI");
     164          16 :         CHKBindCol(1, SQL_C_CHAR, name, sizeof(name), &ind1, "SI");
     165          16 :         CHKBindCol(2, SQL_C_SSHORT, &type, 0, &ind2, "SI");
     166          16 :         CHKBindCol(3, SQL_C_SLONG, &col_size, 0, &ind3, "SI");
     167          16 :         CHKBindCol(6, SQL_C_CHAR, params, sizeof(params), &ind4, "SI");
     168          16 :         CHKBindCol(10, SQL_C_SSHORT, &is_unsigned, 0, &ind5, "SI");
     169          16 :         CHKBindCol(14, SQL_C_SSHORT, &min_scale, 0, &ind6, "SI");
     170          16 :         while (CHKFetch("SNo") == SQL_SUCCESS)
     171             :                 ;
     172          16 :         SQLFreeStmt(odbc_stmt, SQL_UNBIND);
     173          16 :         Flushodbc_stmt();
     174             : 
     175             :         /* check WVARCHAR for no pending data */
     176          16 :         if (odbc_db_is_microsoft() || strncmp(odbc_db_version(), "15.00.", 6) >= 0) {
     177          16 :                 CHKGetTypeInfo(SQL_WVARCHAR, "SI");
     178          16 :                 CHKFetch("S");
     179             :                 /* mssql returns SYSNAME as NVARCHAR */
     180          16 :                 if (odbc_db_is_microsoft())
     181          12 :                         CHKFetch("S");
     182             : 
     183             :                 /* mssql 2008 can return a lot of NVARCHAR as new type (ie DATE)
     184             :                  * are converted automatically to NVARCHAR with former protocol
     185             :                  */
     186          16 :                 if (!odbc_db_is_microsoft() || tdsver >= 0x703 || odbc_db_version_int() < 0x0a000000)
     187          16 :                         CHKFetch("No");
     188          16 :                 CHKMoreResults("No");
     189             : 
     190          16 :                 CHKGetTypeInfo(SQL_BINARY, "SI");
     191             :         }
     192             : 
     193          16 :         odbc_disconnect();
     194          16 : }
     195             : 
     196             : int
     197           8 : main(void)
     198             : {
     199           8 :         DoTest(0);
     200             : 
     201           8 :         DoTest(1);
     202             : 
     203           8 :         printf("Done.\n");
     204             :         return 0;
     205             : }

Generated by: LCOV version 1.13