LCOV - code coverage report
Current view: top level - src/odbc - odbc_data.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 248 256 96.9 %
Date: 2026-07-19 14:02:14 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 2014  Frediano Ziglio
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : 
      22             : #include <stdarg.h>
      23             : #include <stdio.h>
      24             : 
      25             : #if HAVE_STDLIB_H
      26             : #include <stdlib.h>
      27             : #endif /* HAVE_STDLIB_H */
      28             : 
      29             : #if HAVE_STRING_H
      30             : #include <string.h>
      31             : #endif /* HAVE_STRING_H */
      32             : 
      33             : #include <assert.h>
      34             : #include <ctype.h>
      35             : 
      36             : #include <freetds/odbc.h>
      37             : #include <freetds/tds/iconv.h>
      38             : #include <freetds/tds/convert.h>
      39             : #include <odbcss.h>
      40             : 
      41             : #define SET_INFO(type, prefix, suffix) do { \
      42             :         drec->sql_desc_literal_prefix = prefix; \
      43             :         drec->sql_desc_literal_suffix = suffix; \
      44             :         drec->sql_desc_type_name = type; \
      45             :         return; \
      46             :         } while(0)
      47             : #define SET_INFO2(type, prefix, suffix, len) do { \
      48             :         drec->sql_desc_length = (len); \
      49             :         SET_INFO(type, prefix, suffix); \
      50             :         } while(0)
      51             : 
      52             : /* For date/time types - ODBC specification says that SQL_DESC_LENGTH
      53             :  * should be the character string representation size.
      54             :  * https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetdescfield-function
      55             :  */
      56             : #define SET_INFO_DT(type, prefix, suffix) SET_INFO2(type, prefix, suffix, drec->sql_desc_display_size)
      57             : 
      58             : static int
      59       18107 : odbc_datetime_display_size(const TDSCOLUMN *col, const TDS_DBC *dbc)
      60             : {
      61             :         /* This logic should match that of odbc_tds2sql() code block which
      62             :          * selects the format string and precision.
      63             :          *
      64             :          * "precision" here refers to the number of digits to be generated by the
      65             :          * TDS-specific %z format specifier, which represents fractions of a second.
      66             :          *
      67             :          * This value SHOULD be set in col->column_prec. It is so, for MS types.
      68             :          * However, the non-MS types sometimes do not actually set column_prec,
      69             :          * so odbc_tds2sql() hardcodes precisions for those types.
      70             :          */
      71             : 
      72             :         int prec;
      73             :         const char *fmt;
      74       18107 :         int extra = 0;
      75             : 
      76       18107 :         switch (tds_get_conversion_type(col->on_server.column_type, col->on_server.column_size)) {
      77          26 :         case SYBMSDATETIMEOFFSET:
      78             :                 /* Offset formatting hardcodes a " +HH:MM" suffix */
      79          26 :                 extra = 7;
      80          26 :                 prec = col->column_prec;
      81             :                 goto datetime;
      82          46 :         case SYBMSDATETIME2:
      83          46 :                 prec = col->column_prec;
      84             :                 goto datetime;
      85             :         case SYB5BIGDATETIME:
      86             :                 prec = 6;
      87             :                 goto datetime;
      88        1264 :         case SYBDATETIME:
      89        1264 :                 prec = 3;
      90             :                 goto datetime;
      91         130 :         case SYBDATETIME4:
      92         130 :                 prec = 0;
      93        1476 :         datetime:
      94        2952 :                 fmt = tds_dstr_cstr(&dbc->datetime_fmt);
      95             :                 break;
      96          82 :         case SYBMSTIME:
      97          82 :                 prec = col->column_prec;
      98             :                 goto time;
      99             :         case SYB5BIGTIME:
     100             :                 prec = 6;
     101             :                 goto time;
     102          36 :         case SYBTIME:
     103          36 :                 prec = 3;
     104         128 :         time:
     105         256 :                 fmt = tds_dstr_cstr(&dbc->time_fmt);
     106             :                 break;
     107         126 :         case SYBMSDATE:
     108             :         case SYBDATE:
     109         126 :                 prec = 0;
     110         252 :                 fmt = tds_dstr_cstr(&dbc->date_fmt);
     111             :                 break;
     112             :         default:
     113             :                 return 0;
     114             :         }
     115             : 
     116        1730 :         return tds_strftime_maxsize(fmt, prec) + extra;
     117             : }
     118             : 
     119             : static void
     120         240 : data_msdatetime_set_type_info(TDSCOLUMN *col, struct _drecord *drec, const TDS_DBC *dbc)
     121             : {
     122         240 :         drec->sql_desc_display_size = odbc_datetime_display_size(col, dbc);
     123             : 
     124         240 :         switch (col->on_server.column_type) {
     125          82 :         case SYBMSTIME:
     126          82 :                 drec->sql_desc_octet_length = sizeof(SQL_SS_TIME2_STRUCT);
     127          82 :                 drec->sql_desc_concise_type = SQL_SS_TIME2;
     128          82 :                 SET_INFO_DT("time", "'", "'");
     129          86 :         case SYBMSDATE:
     130          86 :                 drec->sql_desc_octet_length = sizeof(DATE_STRUCT);
     131          86 :                 drec->sql_desc_concise_type = SQL_TYPE_DATE;
     132          86 :                 SET_INFO_DT("date", "'", "'");
     133          26 :         case SYBMSDATETIMEOFFSET:
     134          26 :                 drec->sql_desc_octet_length = sizeof(SQL_SS_TIMESTAMPOFFSET_STRUCT);
     135          26 :                 drec->sql_desc_concise_type = SQL_SS_TIMESTAMPOFFSET;
     136          26 :                 SET_INFO_DT("datetimeoffset", "'", "'");
     137          46 :         case SYBMSDATETIME2:
     138          46 :                 drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
     139          46 :                 drec->sql_desc_concise_type = SQL_TYPE_TIMESTAMP;
     140          46 :                 drec->sql_desc_datetime_interval_code = SQL_CODE_TIMESTAMP;
     141          46 :                 SET_INFO_DT("datetime2", "'", "'");
     142             :         default:
     143             :                 break;
     144             :         }
     145             : }
     146             : 
     147             : static void
     148         606 : data_variant_set_type_info(TDSCOLUMN *col TDS_UNUSED, struct _drecord *drec, const TDS_DBC *dbc TDS_UNUSED)
     149             : {
     150         606 :         drec->sql_desc_concise_type = SQL_SS_VARIANT;
     151         606 :         drec->sql_desc_display_size = 8000;
     152         606 :         drec->sql_desc_octet_length = 0;
     153         606 :         SET_INFO2("sql_variant", "", "", 8000);
     154             : }
     155             : 
     156             : static void
     157         836 : data_numeric_set_type_info(TDSCOLUMN *col, struct _drecord *drec, const TDS_DBC *dbc TDS_UNUSED)
     158             : {
     159         836 :         const char *type_name = col->on_server.column_type == SYBNUMERIC ? "numeric" : "decimal";
     160             : 
     161         836 :         drec->sql_desc_concise_type = SQL_NUMERIC;
     162         836 :         drec->sql_desc_octet_length = col->column_prec + 2;
     163         836 :         drec->sql_desc_display_size = col->column_prec + 2;
     164         836 :         drec->sql_desc_num_prec_radix = 10;
     165         836 :         SET_INFO2(type_name, "", "", col->column_prec);
     166             : }
     167             : 
     168             : static void
     169           8 : data_clrudt_set_type_info(TDSCOLUMN *col, struct _drecord *drec, const TDS_DBC *dbc TDS_UNUSED)
     170             : {
     171           8 :         drec->sql_desc_concise_type = SQL_LONGVARBINARY;
     172             :         /* TODO ??? */
     173           8 :         drec->sql_desc_display_size = col->column_size * 2;
     174           8 : }
     175             : 
     176             : static void
     177          20 : data_sybbigtime_set_type_info(TDSCOLUMN *col, struct _drecord *drec, const TDS_DBC *dbc TDS_UNUSED)
     178             : {
     179          20 :         drec->sql_desc_display_size = odbc_datetime_display_size(col, dbc);
     180             : 
     181          20 :         if (col->on_server.column_type == SYB5BIGTIME) {
     182          10 :                 drec->sql_desc_concise_type = SQL_SS_TIME2;
     183          10 :                 drec->sql_desc_octet_length = sizeof(SQL_SS_TIME2_STRUCT);
     184          10 :                 drec->sql_desc_precision = 6;
     185          10 :                 drec->sql_desc_scale = 6;
     186          10 :                 drec->sql_desc_datetime_interval_code = SQL_CODE_TIMESTAMP;
     187          10 :                 SET_INFO_DT("bigtime", "'", "'");
     188             :         }
     189             : 
     190          10 :         assert(col->on_server.column_type == SYB5BIGDATETIME);
     191             : 
     192          10 :         drec->sql_desc_concise_type = SQL_TYPE_TIMESTAMP;
     193          10 :         drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
     194          10 :         drec->sql_desc_precision = 6;
     195          10 :         drec->sql_desc_scale = 6;
     196          10 :         drec->sql_desc_datetime_interval_code = SQL_CODE_TIMESTAMP;
     197          10 :         SET_INFO_DT("bigdatetime", "'", "'");
     198             : }
     199             : 
     200             : static void
     201           0 : data_mstabletype_set_type_info(TDSCOLUMN *col TDS_UNUSED, struct _drecord *drec, const TDS_DBC *dbc TDS_UNUSED)
     202             : {
     203           0 :         drec->sql_desc_concise_type = SQL_SS_TABLE;
     204           0 :         drec->sql_desc_octet_length = 0;
     205           0 : }
     206             : 
     207             : static void
     208       17847 : data_generic_set_type_info(TDSCOLUMN *col, struct _drecord *drec, const TDS_DBC *dbc)
     209             : {
     210       17847 :         TDS_SERVER_TYPE col_type = col->on_server.column_type;
     211       17847 :         int col_size = col->on_server.column_size;
     212       17847 :         const int datetime_display_size = odbc_datetime_display_size(col, dbc);
     213             : 
     214       17847 :         drec->sql_desc_display_size = 26;
     215             : 
     216       17847 :         switch (tds_get_conversion_type(col_type, col_size)) {
     217          40 :         case XSYBNCHAR:
     218          40 :                 drec->sql_desc_concise_type = SQL_WCHAR;
     219          40 :                 drec->sql_desc_display_size = col->on_server.column_size / 2;
     220          40 :                 SET_INFO2("nchar", "'", "'", col->on_server.column_size / 2);
     221             : 
     222         156 :         case XSYBCHAR:
     223             :         case SYBCHAR:
     224         156 :                 drec->sql_desc_concise_type = SQL_CHAR;
     225         156 :                 drec->sql_desc_display_size = col->on_server.column_size;
     226         156 :                 SET_INFO("char", "'", "'");
     227             : 
     228             :         /* TODO really sure ?? SYBNVARCHAR sybase only ?? */
     229        2383 :         case SYBNVARCHAR:
     230             :         case XSYBNVARCHAR:
     231        2383 :                 drec->sql_desc_concise_type = SQL_WVARCHAR;
     232        2383 :                 drec->sql_desc_display_size = col->on_server.column_size / 2;
     233        2383 :                 drec->sql_desc_length = col->on_server.column_size / 2u;
     234        2383 :                 if (col->char_conv) {
     235        2381 :                         unsigned char bytes_per_char = TDS_CLAMP(col->char_conv->to.charset.max_bytes_per_char, 2, 3);
     236        2381 :                         drec->sql_desc_octet_length = (col->on_server.column_size / 2u) * bytes_per_char;
     237             :                 }
     238        2383 :                 if (is_blob_col(col)) {
     239           8 :                         drec->sql_desc_display_size = SQL_SS_LENGTH_UNLIMITED;
     240           8 :                         drec->sql_desc_octet_length = drec->sql_desc_length =
     241             :                                 SQL_SS_LENGTH_UNLIMITED;
     242             :                 }
     243        2383 :                 SET_INFO("nvarchar", "'", "'");
     244             : 
     245        3824 :         case XSYBVARCHAR:
     246             :         case SYBVARCHAR:
     247        3824 :                 drec->sql_desc_concise_type = SQL_VARCHAR;
     248        3824 :                 drec->sql_desc_display_size = col->on_server.column_size;
     249        3824 :                 if (is_blob_col(col)) {
     250          36 :                         drec->sql_desc_display_size = SQL_SS_LENGTH_UNLIMITED;
     251          36 :                         drec->sql_desc_octet_length = drec->sql_desc_length =
     252             :                                 SQL_SS_LENGTH_UNLIMITED;
     253             :                 }
     254        3824 :                 SET_INFO("varchar", "'", "'");
     255             : 
     256         574 :         case SYBNTEXT:
     257         574 :                 drec->sql_desc_concise_type = SQL_WLONGVARCHAR;
     258         574 :                 drec->sql_desc_display_size = col->on_server.column_size / 2;
     259         574 :                 SET_INFO2("ntext", "'", "'", col->on_server.column_size / 2);
     260             : 
     261         796 :         case SYBTEXT:
     262         796 :                 drec->sql_desc_concise_type = SQL_LONGVARCHAR;
     263         796 :                 drec->sql_desc_display_size = col->on_server.column_size;
     264         796 :                 SET_INFO("text", "'", "'");
     265             : 
     266         370 :         case SYBBIT:
     267             :         case SYBBITN:
     268         370 :                 drec->sql_desc_concise_type = SQL_BIT;
     269         370 :                 drec->sql_desc_display_size = 1;
     270         370 :                 drec->sql_desc_unsigned = SQL_TRUE;
     271         370 :                 SET_INFO2("bit", "", "", 1);
     272             : 
     273             : #if (ODBCVER >= 0x0300)
     274         214 :         case SYB5INT8:
     275             :         case SYBINT8:
     276             :                 /* TODO return numeric for odbc2 and convert bigint to numeric */
     277         214 :                 drec->sql_desc_concise_type = SQL_BIGINT;
     278         214 :                 drec->sql_desc_display_size = 20;
     279         214 :                 SET_INFO2("bigint", "", "", 19);
     280             : #endif
     281             : 
     282        2455 :         case SYBINT4:
     283        2455 :                 drec->sql_desc_concise_type = SQL_INTEGER;
     284        2455 :                 drec->sql_desc_display_size = 11;    /* -1000000000 */
     285        2455 :                 SET_INFO2("int", "", "", 10);
     286             : 
     287        2541 :         case SYBINT2:
     288        2541 :                 drec->sql_desc_concise_type = SQL_SMALLINT;
     289        2541 :                 drec->sql_desc_display_size = 6;     /* -10000 */
     290        2541 :                 SET_INFO2("smallint", "", "", 5);
     291             : 
     292         314 :         case SYBUINT1:
     293             :         case SYBINT1:
     294         314 :                 drec->sql_desc_unsigned = SQL_TRUE;
     295         314 :         case SYBSINT1: /* TODO not another type_name ?? */
     296         314 :                 drec->sql_desc_concise_type = SQL_TINYINT;
     297         314 :                 drec->sql_desc_display_size = 3;     /* 255 */
     298         314 :                 SET_INFO2("tinyint", "", "", 3);
     299             : 
     300             : #if (ODBCVER >= 0x0300)
     301          36 :         case SYBUINT8:
     302          36 :                 drec->sql_desc_unsigned = SQL_TRUE;
     303          36 :                 drec->sql_desc_concise_type = SQL_BIGINT;
     304          36 :                 drec->sql_desc_display_size = 20;
     305             :                 /* TODO return numeric for odbc2 and convert bigint to numeric */
     306          36 :                 SET_INFO2("unsigned bigint", "", "", 20);
     307             : #endif
     308             : 
     309          36 :         case SYBUINT4:
     310          36 :                 drec->sql_desc_unsigned = SQL_TRUE;
     311          36 :                 drec->sql_desc_concise_type = SQL_INTEGER;
     312          36 :                 drec->sql_desc_display_size = 10;
     313          36 :                 SET_INFO2("unsigned int", "", "", 10);
     314             : 
     315          38 :         case SYBUINT2:
     316          38 :                 drec->sql_desc_unsigned = SQL_TRUE;
     317          38 :                 drec->sql_desc_concise_type = SQL_SMALLINT;
     318          38 :                 drec->sql_desc_display_size = 5;     /* 65535 */
     319          38 :                 SET_INFO2("unsigned smallint", "", "", 5);
     320             : 
     321         316 :         case SYBREAL:
     322         316 :                 drec->sql_desc_concise_type = SQL_REAL;
     323         316 :                 drec->sql_desc_display_size = 14;
     324         316 :                 SET_INFO2("real", "", "", dbc->env->attr.odbc_version == SQL_OV_ODBC3 ? 24 : 7);
     325             : 
     326         812 :         case SYBFLT8:
     327         812 :                 drec->sql_desc_concise_type = SQL_DOUBLE;
     328         812 :                 drec->sql_desc_display_size = 24;    /* FIXME -- what should the correct size be? */
     329         812 :                 SET_INFO2("float", "", "", dbc->env->attr.odbc_version == SQL_OV_ODBC3 ? 53 : 15);
     330             : 
     331         356 :         case SYBMONEY:
     332             :                 /* TODO check money format returned by proprietary ODBC, scale == 4 but we use 2 digits */
     333         356 :                 drec->sql_desc_concise_type = SQL_DECIMAL;
     334         356 :                 drec->sql_desc_octet_length = 21;
     335         356 :                 drec->sql_desc_display_size = 21;
     336         356 :                 drec->sql_desc_precision = 19;
     337         356 :                 drec->sql_desc_scale     = 4;
     338         356 :                 SET_INFO2("money", "$", "", 19);
     339             : 
     340         100 :         case SYBMONEY4:
     341         100 :                 drec->sql_desc_concise_type = SQL_DECIMAL;
     342         100 :                 drec->sql_desc_octet_length = 12;
     343         100 :                 drec->sql_desc_display_size = 12;
     344         100 :                 drec->sql_desc_precision = 10;
     345         100 :                 drec->sql_desc_scale     = 4;
     346         100 :                 SET_INFO2("money", "$", "", 10);
     347             : 
     348        1264 :         case SYBDATETIME:
     349        1264 :                 drec->sql_desc_concise_type = SQL_TYPE_TIMESTAMP;
     350        1264 :                 drec->sql_desc_display_size = datetime_display_size;
     351        1264 :                 drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
     352        1264 :                 drec->sql_desc_precision = 3;
     353        1264 :                 drec->sql_desc_scale = 3;
     354        1264 :                 drec->sql_desc_datetime_interval_code = SQL_CODE_TIMESTAMP;
     355        1264 :                 SET_INFO_DT("datetime", "'", "'");
     356             : 
     357         130 :         case SYBDATETIME4:
     358             :                 /* MS ODBC driver gives 19 for display_size and 16 for length,
     359             :                  * the default display string has length 19.
     360             :                  * This appears to be a MS bug that we don't need to replicate,
     361             :                  * the two length values should match. */
     362         130 :                 drec->sql_desc_concise_type = SQL_TYPE_TIMESTAMP;
     363         130 :                 drec->sql_desc_display_size = datetime_display_size;
     364         130 :                 drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
     365         130 :                 drec->sql_desc_datetime_interval_code = SQL_CODE_TIMESTAMP;
     366         130 :                 SET_INFO_DT("datetime", "'", "'");
     367             : 
     368             :         /* The following two types are just Sybase types but as mainly our ODBC
     369             :          * driver is much more compatible with Windows use attributes similar
     370             :          * to MS one. For instance Sybase ODBC returns TIME into a TIME_STRUCT
     371             :          * however this truncate the precision to 0 as TIME does not have
     372             :          * fraction of seconds. Also Sybase ODBC have different concepts for
     373             :          * PRECISION for many types and making these 2 types compatibles with
     374             :          * Sybase would break this driver compatibility.
     375             :          */
     376          36 :         case SYBTIME:
     377          36 :                 drec->sql_desc_concise_type = SQL_SS_TIME2;
     378          36 :                 drec->sql_desc_octet_length = sizeof(SQL_SS_TIME2_STRUCT);
     379          36 :                 drec->sql_desc_display_size = datetime_display_size;
     380          36 :                 drec->sql_desc_precision = 3;
     381          36 :                 drec->sql_desc_scale = 3;
     382          36 :                 SET_INFO_DT("time", "'", "'");
     383             : 
     384          40 :         case SYBDATE:
     385          40 :                 drec->sql_desc_octet_length = sizeof(DATE_STRUCT);
     386          40 :                 drec->sql_desc_concise_type = SQL_TYPE_DATE;
     387             :                 /* we always format using yyyy-mm-dd, see convert_tds2sql.c */
     388          40 :                 drec->sql_desc_display_size = datetime_display_size;
     389          40 :                 SET_INFO_DT("date", "'", "'");
     390             : 
     391          58 :         case XSYBBINARY:
     392             :         case SYBBINARY:
     393          58 :                 drec->sql_desc_concise_type = SQL_BINARY;
     394          58 :                 drec->sql_desc_display_size = col->column_size * 2;
     395             :                 /* handle TIMESTAMP using usertype */
     396          58 :                 if (col->column_usertype == 80)
     397           8 :                         SET_INFO("timestamp", "0x", "");
     398          50 :                 SET_INFO("binary", "0x", "");
     399             : 
     400          76 :         case SYBLONGBINARY:
     401          76 :                 if (col->column_usertype == USER_UNICHAR_TYPE) {
     402           4 :                         drec->sql_desc_concise_type = SQL_WCHAR;
     403           4 :                         drec->sql_desc_display_size = col->on_server.column_size / 2;
     404           4 :                         SET_INFO2("unichar", "'", "'", col->on_server.column_size / 2);
     405             :                 }
     406          72 :                 if (col->column_usertype == USER_UNIVARCHAR_TYPE) {
     407          62 :                         drec->sql_desc_concise_type = SQL_WVARCHAR;
     408          62 :                         drec->sql_desc_display_size = col->on_server.column_size / 2;
     409          62 :                         SET_INFO2("univarchar", "'", "'", col->on_server.column_size / 2);
     410             :                 }
     411             :         case SYBIMAGE:
     412         374 :                 drec->sql_desc_concise_type = SQL_LONGVARBINARY;
     413         374 :                 drec->sql_desc_display_size = col->column_size * 2;
     414         374 :                 SET_INFO("image", "0x", "");
     415             : 
     416         432 :         case XSYBVARBINARY:
     417             :         case SYBVARBINARY:
     418         432 :                 drec->sql_desc_concise_type = SQL_VARBINARY;
     419         432 :                 drec->sql_desc_display_size = col->column_size * 2;
     420         432 :                 if (is_blob_col(col)) {
     421          40 :                         drec->sql_desc_display_size = SQL_SS_LENGTH_UNLIMITED;
     422          40 :                         drec->sql_desc_octet_length = drec->sql_desc_length =
     423             :                                 SQL_SS_LENGTH_UNLIMITED;
     424             :                 }
     425         432 :                 SET_INFO("varbinary", "0x", "");
     426             : 
     427             :         case SYBINTN:
     428             :         case SYBDATETIMN:
     429             :         case SYBFLTN:
     430             :         case SYBMONEYN:
     431             :         case SYBUINTN:
     432             :         case SYBTIMEN:
     433             :         case SYBDATEN:
     434           0 :                 assert(0);
     435             : 
     436             :         case SYBVOID:
     437             :         case SYBINTERVAL:
     438             :         case SYBUNITEXT:
     439             :         case SYBXML:
     440             :         case SYBMSUDT:
     441             :                 break;
     442             : 
     443             : #if (ODBCVER >= 0x0300)
     444          74 :         case SYBUNIQUE:
     445             : #ifdef SQL_GUID
     446          74 :                 drec->sql_desc_concise_type = SQL_GUID;
     447             : #else
     448             :                 drec->sql_desc_concise_type = SQL_CHAR;
     449             : #endif
     450          74 :                 drec->sql_desc_display_size = 36;
     451             :                 /* FIXME for Sybase ?? */
     452          74 :                 SET_INFO2("uniqueidentifier", "'", "'", 36);
     453             : #endif
     454             : 
     455          12 :         case SYBMSXML:
     456          12 :                 drec->sql_desc_concise_type = SQL_SS_XML;
     457          12 :                 drec->sql_desc_display_size = SQL_SS_LENGTH_UNLIMITED;
     458          12 :                 drec->sql_desc_octet_length = drec->sql_desc_length =
     459             :                         SQL_SS_LENGTH_UNLIMITED;
     460          12 :                 SET_INFO("xml", "'", "'");
     461             :         /* types already handled in other types, just to silent warnings */
     462             :         case SYBNUMERIC:
     463             :         case SYBDECIMAL:
     464             :         case SYBVARIANT:
     465             :         case SYBMSDATE:
     466             :         case SYBMSTIME:
     467             :         case SYBMSDATETIME2:
     468             :         case SYBMSDATETIMEOFFSET:
     469             :         case SYB5BIGDATETIME:
     470             :         case SYB5BIGTIME:
     471             :         case SYBMSTABLE:
     472             :                 break;
     473             :         }
     474           0 :         SET_INFO("", "", "");
     475             : }
     476             : 
     477             : static void
     478           0 : data_invalid_set_type_info(TDSCOLUMN *col TDS_UNUSED, struct _drecord *drec TDS_UNUSED, const TDS_DBC *dbc TDS_UNUSED)
     479             : {
     480           0 : }
     481             : 
     482             : void
     483       19557 : odbc_set_sql_type_info(TDSCOLUMN *col, struct _drecord *drec, const TDS_DBC *dbc)
     484             : {
     485       19557 :         drec->sql_desc_precision = col->column_prec;
     486       19557 :         drec->sql_desc_scale = col->column_scale;
     487       19557 :         drec->sql_desc_unsigned = SQL_FALSE;
     488       19557 :         drec->sql_desc_octet_length = drec->sql_desc_length = col->on_server.column_size;
     489       19557 :         drec->sql_desc_num_prec_radix = 0;
     490       19557 :         drec->sql_desc_datetime_interval_code = 0;
     491             : 
     492       19557 :         ((TDS_FUNCS *) col->funcs)->set_type_info(col, drec, dbc);
     493             : 
     494       19557 :         drec->sql_desc_type = drec->sql_desc_concise_type;
     495       19557 :         if (drec->sql_desc_concise_type == SQL_TYPE_TIMESTAMP)
     496        1450 :                 drec->sql_desc_type = SQL_DATETIME;
     497       19557 : }
     498             : 
     499             : #  define TDS_DEFINE_FUNCS(name) \
     500             :         const TDS_FUNCS tds_ ## name ## _funcs = { \
     501             :                 TDS_COMMON_FUNCS(name), \
     502             :                 data_ ## name ## _set_type_info, \
     503             :         }
     504             : TDS_DEFINE_FUNCS(invalid);
     505             : TDS_DEFINE_FUNCS(generic);
     506             : TDS_DEFINE_FUNCS(numeric);
     507             : TDS_DEFINE_FUNCS(variant);
     508             : TDS_DEFINE_FUNCS(msdatetime);
     509             : TDS_DEFINE_FUNCS(clrudt);
     510             : TDS_DEFINE_FUNCS(sybbigtime);
     511             : TDS_DEFINE_FUNCS(mstabletype);

Generated by: LCOV version 1.13