LCOV - code coverage report
Current view: top level - src/odbc/unittests - type.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 36 43 83.7 %
Date: 2025-04-26 20:22:58 Functions: 1 1 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : #include <assert.h>
       3             : 
       4             : struct type
       5             : {
       6             :         SQLSMALLINT type;
       7             :         const char *name;
       8             :         unsigned flags;
       9             : };
      10             : 
      11             : #define FLAG_C  1
      12             : #define FLAG_SQL  2
      13             : 
      14             : #define TYPE_C(s) {s, #s, FLAG_C }
      15             : #define TYPE_SQL(s) {s, #s, FLAG_SQL }
      16             : #define TYPE_BOTH(s,s2) {s, #s, FLAG_SQL|FLAG_C }
      17             : /* 
      18             :  * Same define with test for constants
      19             :  *  #define TYPE_BOTH(s,s2) {s, #s, (FLAG_SQL|FLAG_C)+((1/!(s-s2))-1) }
      20             :  */
      21             : static const struct type types[] = {
      22             :         TYPE_BOTH(SQL_C_CHAR, SQL_CHAR),
      23             :         TYPE_BOTH(SQL_C_LONG, SQL_INTEGER),
      24             :         TYPE_BOTH(SQL_C_SHORT, SQL_SMALLINT),
      25             :         TYPE_BOTH(SQL_C_FLOAT, SQL_REAL),
      26             :         TYPE_BOTH(SQL_C_DOUBLE, SQL_DOUBLE),
      27             :         TYPE_BOTH(SQL_C_NUMERIC, SQL_NUMERIC),
      28             :         TYPE_C(SQL_C_DEFAULT),
      29             :         TYPE_C(SQL_C_DATE),
      30             :         TYPE_C(SQL_C_TIME),
      31             : /* MS ODBC do not support SQL_TIMESTAMP for IPD type while we support it */
      32             : /*      TYPE_C(SQL_C_TIMESTAMP), */
      33             :         TYPE_BOTH(SQL_C_TIMESTAMP, SQL_TIMESTAMP),
      34             :         TYPE_BOTH(SQL_C_TYPE_DATE, SQL_TYPE_DATE),
      35             :         TYPE_BOTH(SQL_C_TYPE_TIME, SQL_TYPE_TIME),
      36             :         TYPE_BOTH(SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP),
      37             :         TYPE_C(SQL_C_INTERVAL_YEAR),
      38             :         TYPE_C(SQL_C_INTERVAL_MONTH),
      39             :         TYPE_C(SQL_C_INTERVAL_DAY),
      40             :         TYPE_C(SQL_C_INTERVAL_HOUR),
      41             :         TYPE_C(SQL_C_INTERVAL_MINUTE),
      42             :         TYPE_C(SQL_C_INTERVAL_SECOND),
      43             :         TYPE_C(SQL_C_INTERVAL_YEAR_TO_MONTH),
      44             :         TYPE_C(SQL_C_INTERVAL_DAY_TO_HOUR),
      45             :         TYPE_C(SQL_C_INTERVAL_DAY_TO_MINUTE),
      46             :         TYPE_C(SQL_C_INTERVAL_DAY_TO_SECOND),
      47             :         TYPE_C(SQL_C_INTERVAL_HOUR_TO_MINUTE),
      48             :         TYPE_C(SQL_C_INTERVAL_HOUR_TO_SECOND),
      49             :         TYPE_C(SQL_C_INTERVAL_MINUTE_TO_SECOND),
      50             :         TYPE_BOTH(SQL_C_BINARY, SQL_BINARY),
      51             :         TYPE_BOTH(SQL_C_BIT, SQL_BIT),
      52             :         TYPE_C(SQL_C_SBIGINT),
      53             :         TYPE_C(SQL_C_UBIGINT),
      54             :         TYPE_BOTH(SQL_C_TINYINT, SQL_TINYINT),
      55             :         TYPE_C(SQL_C_SLONG),
      56             :         TYPE_C(SQL_C_SSHORT),
      57             :         TYPE_C(SQL_C_STINYINT),
      58             :         TYPE_C(SQL_C_ULONG),
      59             :         TYPE_C(SQL_C_USHORT),
      60             :         TYPE_C(SQL_C_UTINYINT),
      61             :         TYPE_BOTH(SQL_C_GUID, SQL_GUID),
      62             : 
      63             :         TYPE_SQL(SQL_BIGINT),
      64             :         TYPE_SQL(SQL_VARBINARY),
      65             :         TYPE_SQL(SQL_LONGVARBINARY),
      66             :         TYPE_SQL(SQL_VARCHAR),
      67             :         TYPE_SQL(SQL_LONGVARCHAR),
      68             :         TYPE_SQL(SQL_DECIMAL),
      69             :         TYPE_SQL(SQL_FLOAT),
      70             :         {0, NULL}
      71             : };
      72             : 
      73             : static const char *
      74             : get_type_name(SQLSMALLINT type)
      75             : {
      76         590 :         const struct type *p = types;
      77             : 
      78       21810 :         for (; p->name; ++p)
      79       22990 :                 if (p->type == type)
      80             :                         return p->name;
      81             :         return "(unknown)";
      82             : }
      83             : 
      84             : static int result = 0;
      85             : 
      86             : static void
      87             : check_msg(int check, const char *msg)
      88             : {
      89         900 :         if (check)
      90             :                 return;
      91           0 :         fprintf(stderr, "Check failed: %s\n", msg);
      92           0 :         result = 1;
      93             : }
      94             : 
      95          10 : TEST_MAIN()
      96             : {
      97             :         const struct type *p;
      98             :         char buf[16];
      99             :         SQLINTEGER ind;
     100             :         SQLLEN lind;
     101             :         SQLHDESC desc;
     102             : 
     103          10 :         odbc_connect();
     104             : 
     105             :         /*
     106             :          * test setting two time a descriptor
     107             :          * success all user allocated are ARD or APD so type cheching can be done
     108             :          * TODO freeing descriptor dissociate it from statements
     109             :          */
     110             : 
     111             :         /* test C types */
     112         460 :         for (p = types; p->name; ++p) {
     113         450 :                 if (SQL_SUCCEEDED
     114             :                     (SQLBindParameter(odbc_stmt, 1, SQL_PARAM_INPUT, p->type, SQL_VARCHAR, (SQLUINTEGER) (-1), 0, buf, 16, &lind))) {
     115             :                         SQLSMALLINT concise_type, type, code;
     116             :                         SQLHDESC desc;
     117             : 
     118         380 :                         concise_type = type = code = 0;
     119             : 
     120             :                         /* get APD */
     121         380 :                         SQLGetStmtAttr(odbc_stmt, SQL_ATTR_APP_PARAM_DESC, &desc, sizeof(desc), &ind);
     122             : 
     123         380 :                         CHKGetDescField(desc, 1, SQL_DESC_TYPE, &type, sizeof(SQLSMALLINT), &ind, "S");
     124         380 :                         CHKGetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, &concise_type, sizeof(SQLSMALLINT), &ind, "S");
     125         380 :                         CHKGetDescField(desc, 1, SQL_DESC_DATETIME_INTERVAL_CODE, &code, sizeof(SQLSMALLINT), &ind, "S");
     126        1140 :                         printf("Setted type %s -> [%d (%s), %d (%s), %d]\n",
     127             :                                p->name, (int) concise_type, get_type_name(concise_type), (int) type, get_type_name(type), code);
     128         760 :                         check_msg(p->flags & FLAG_C, "Type not C successed to be set in APD");
     129             :                 } else {
     130             :                         SQLSMALLINT concise_type, type, code;
     131             :                         SQLHDESC desc;
     132             : 
     133          70 :                         concise_type = type = code = 0;
     134             : 
     135          70 :                         fprintf(stderr, "Error setting type %d (%s)\n", (int) p->type, p->name);
     136             : 
     137          70 :                         concise_type = p->type;
     138          70 :                         SQLGetStmtAttr(odbc_stmt, SQL_ATTR_APP_PARAM_DESC, &desc, sizeof(desc), &ind);
     139          70 :                         if (SQL_SUCCEEDED
     140             :                             (SQLSetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, TDS_INT2PTR(concise_type), sizeof(SQLSMALLINT))))
     141             :                         {
     142           0 :                                 CHKGetDescField(desc, 1, SQL_DESC_TYPE, &type, sizeof(SQLSMALLINT), &ind, "S");
     143           0 :                                 CHKGetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, &concise_type, sizeof(SQLSMALLINT), &ind, "S");
     144           0 :                                 CHKGetDescField(desc, 1, SQL_DESC_DATETIME_INTERVAL_CODE, &code, sizeof(SQLSMALLINT), &ind, "S");
     145           0 :                                 printf("Setted type %s -> [%d (%s), %d (%s), %d]\n",
     146             :                                        p->name,
     147             :                                        (int) concise_type, get_type_name(concise_type), (int) type, get_type_name(type), code);
     148           0 :                                 check_msg(p->flags & FLAG_C, "Type not C successed to be set in APD");
     149             :                         } else {
     150          70 :                                 check_msg(!(p->flags & FLAG_C), "Type C failed to be set in APD");
     151             :                         }
     152             :                 }
     153             :         }
     154             : 
     155          10 :         printf("\n\n");
     156             : 
     157             :         /* test SQL types */
     158          10 :         SQLGetStmtAttr(odbc_stmt, SQL_ATTR_IMP_PARAM_DESC, &desc, sizeof(desc), &ind);
     159         460 :         for (p = types; p->name; ++p) {
     160         450 :                 SQLSMALLINT concise_type = p->type;
     161             : 
     162         450 :                 if (SQL_SUCCEEDED
     163             :                     (SQLSetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, TDS_INT2PTR(concise_type), sizeof(SQLSMALLINT)))) {
     164             :                         SQLSMALLINT concise_type, type, code;
     165             : 
     166         210 :                         concise_type = type = code = 0;
     167             : 
     168         210 :                         CHKGetDescField(desc, 1, SQL_DESC_TYPE, &type, sizeof(SQLSMALLINT), &ind, "S");
     169         210 :                         CHKGetDescField(desc, 1, SQL_DESC_CONCISE_TYPE, &concise_type, sizeof(SQLSMALLINT), &ind, "S");
     170         210 :                         CHKGetDescField(desc, 1, SQL_DESC_DATETIME_INTERVAL_CODE, &code, sizeof(SQLSMALLINT), &ind, "S");
     171         630 :                         printf("Setted type %s -> [%d (%s), %d (%s), %d]\n",
     172             :                                p->name, (int) concise_type, get_type_name(concise_type), (int) type, get_type_name(type), code);
     173         420 :                         check_msg(p->flags & FLAG_SQL, "Type not SQL successed to be set in IPD");
     174             :                 } else {
     175         240 :                         fprintf(stderr, "Error setting type %d (%s)\n", (int) p->type, p->name);
     176         240 :                         check_msg(!(p->flags & FLAG_SQL), "Type SQL failed to be set in IPD");
     177             :                 }
     178             :         }
     179             : 
     180          10 :         odbc_disconnect();
     181             : 
     182          10 :         return result;
     183             : }

Generated by: LCOV version 1.13