NCBI C++ ToolKit
odbc_data.c
Go to the documentation of this file.

Go to the SVN repository for this file.

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/iconv.h>
38 #include <odbcss.h>
39 
40 #define SET_INFO(type, prefix, suffix) do { \
41  drec->sql_desc_literal_prefix = prefix; \
42  drec->sql_desc_literal_suffix = suffix; \
43  drec->sql_desc_type_name = type; \
44  return; \
45  } while(0)
46 #define SET_INFO2(type, prefix, suffix, len) do { \
47  drec->sql_desc_length = (len); \
48  SET_INFO(type, prefix, suffix); \
49  } while(0)
50 
51 static void
53 {
54  int decimals = col->column_prec ? col->column_prec + 1: 0;
55 
56  switch (col->on_server.column_type) {
57  case SYBMSTIME:
60  /* always hh:mm:ss[.fff] */
61  drec->sql_desc_display_size = 8 + decimals;
62  SET_INFO2("time", "'", "'", 8 + decimals);
63  case SYBMSDATE:
64  drec->sql_desc_octet_length = sizeof(DATE_STRUCT);
66  /* always yyyy-mm-dd ?? */
67  drec->sql_desc_display_size = 10;
68  SET_INFO2("date", "'", "'", 10);
72  /* we always format using yyyy-mm-dd hh:mm:ss[.fff] +HH:MM, see convert_tds2sql.c */
73  drec->sql_desc_display_size = 26 + decimals;
74  SET_INFO2("datetimeoffset", "'", "'", 26 + decimals);
75  case SYBMSDATETIME2:
79  /* we always format using yyyy-mm-dd hh:mm:ss[.fff], see convert_tds2sql.c */
80  drec->sql_desc_display_size = 19 + decimals;
81  SET_INFO2("datetime2", "'", "'", 19 + decimals);
82  default:
83  break;
84  }
85 }
86 
87 static void
89 {
91  drec->sql_desc_display_size = 8000;
92  drec->sql_desc_octet_length = 0;
93  SET_INFO2("sql_variant", "", "", 8000);
94 }
95 
96 static void
98 {
99  const char *type_name =
100  col->on_server.column_type == SYBNUMERIC ? "numeric" : "decimal";
101 
103  drec->sql_desc_octet_length = col->column_prec + 2;
104  drec->sql_desc_display_size = col->column_prec + 2;
105  drec->sql_desc_num_prec_radix = 10;
106  SET_INFO2(type_name, "", "", col->column_prec);
107 }
108 
109 static void
111 {
113  /* TODO ??? */
114  drec->sql_desc_display_size = col->column_size * 2;
115 }
116 
117 static void
119 {
120  if (col->on_server.column_type == SYB5BIGTIME) {
122  /* we always format using hh:mm:ss[.ffffff], see convert_tds2sql.c */
123  drec->sql_desc_display_size = 15;
125  drec->sql_desc_precision = 6;
126  drec->sql_desc_scale = 6;
128  SET_INFO2("bigtime", "'", "'", 15);
129  }
130 
132 
134  drec->sql_desc_display_size = 26;
135  drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
136  drec->sql_desc_precision = 6;
137  drec->sql_desc_scale = 6;
139  SET_INFO2("bigdatetime", "'", "'", 26);
140 }
141 
142 static void
144 {
146  drec->sql_desc_octet_length = 0;
147 }
148 
149 static void
151 {
152  TDS_SERVER_TYPE col_type = col->on_server.column_type;
153  int col_size = col->on_server.column_size;
154 
155  switch (tds_get_conversion_type(col_type, col_size)) {
156  case XSYBNCHAR:
159  SET_INFO2("nchar", "'", "'", col->on_server.column_size / 2);
160 
161  case XSYBCHAR:
162  case SYBCHAR:
165  SET_INFO("char", "'", "'");
166 
167  /* TODO really sure ?? SYBNVARCHAR sybase only ?? */
168  case SYBNVARCHAR:
169  case XSYBNVARCHAR:
172  drec->sql_desc_length = col->on_server.column_size / 2u;
173  if (col->char_conv) {
174  unsigned char bytes_per_char = ODBC_CLAMP(col->char_conv->to.charset.max_bytes_per_char, 2, 3);
175  drec->sql_desc_octet_length = (col->on_server.column_size / 2u) * bytes_per_char;
176  }
177  if (is_blob_col(col)) {
179  drec->sql_desc_octet_length = drec->sql_desc_length =
181  }
182  SET_INFO("nvarchar", "'", "'");
183 
184  case XSYBVARCHAR:
185  case SYBVARCHAR:
188  if (is_blob_col(col)) {
190  drec->sql_desc_octet_length = drec->sql_desc_length =
192  }
193  SET_INFO("varchar", "'", "'");
194 
195  case SYBNTEXT:
198  SET_INFO2("ntext", "'", "'", col->on_server.column_size / 2);
199 
200  case SYBTEXT:
203  SET_INFO("text", "'", "'");
204 
205  case SYBBIT:
206  case SYBBITN:
208  drec->sql_desc_display_size = 1;
209  drec->sql_desc_unsigned = SQL_TRUE;
210  SET_INFO2("bit", "", "", 1);
211 
212 #if (ODBCVER >= 0x0300)
213  case SYB5INT8:
214  case SYBINT8:
215  /* TODO return numeric for odbc2 and convert bigint to numeric */
217  drec->sql_desc_display_size = 20;
218  SET_INFO2("bigint", "", "", 19);
219 #endif
220 
221  case SYBINT4:
223  drec->sql_desc_display_size = 11; /* -1000000000 */
224  SET_INFO2("int", "", "", 10);
225 
226  case SYBINT2:
228  drec->sql_desc_display_size = 6; /* -10000 */
229  SET_INFO2("smallint", "", "", 5);
230 
231  case SYBUINT1:
232  case SYBINT1:
233  drec->sql_desc_unsigned = SQL_TRUE;
234  case SYBSINT1: /* TODO not another type_name ?? */
236  drec->sql_desc_display_size = 3; /* 255 */
237  SET_INFO2("tinyint", "", "", 3);
238 
239 #if (ODBCVER >= 0x0300)
240  case SYBUINT8:
241  drec->sql_desc_unsigned = SQL_TRUE;
243  drec->sql_desc_display_size = 20;
244  /* TODO return numeric for odbc2 and convert bigint to numeric */
245  SET_INFO2("unsigned bigint", "", "", 20);
246 #endif
247 
248  case SYBUINT4:
249  drec->sql_desc_unsigned = SQL_TRUE;
251  drec->sql_desc_display_size = 10;
252  SET_INFO2("unsigned int", "", "", 10);
253 
254  case SYBUINT2:
255  drec->sql_desc_unsigned = SQL_TRUE;
257  drec->sql_desc_display_size = 5; /* 65535 */
258  SET_INFO2("unsigned smallint", "", "", 5);
259 
260  case SYBREAL:
262  drec->sql_desc_display_size = 14;
263  SET_INFO2("real", "", "", odbc_ver == SQL_OV_ODBC3 ? 24 : 7);
264 
265  case SYBFLT8:
267  drec->sql_desc_display_size = 24; /* FIXME -- what should the correct size be? */
268  SET_INFO2("float", "", "", odbc_ver == SQL_OV_ODBC3 ? 53 : 15);
269 
270  case SYBMONEY:
271  /* TODO check money format returned by propretary ODBC, scale == 4 but we use 2 digits */
273  drec->sql_desc_octet_length = 21;
274  drec->sql_desc_display_size = 21;
275  drec->sql_desc_precision = 19;
276  drec->sql_desc_scale = 4;
277  SET_INFO2("money", "$", "", 19);
278 
279  case SYBMONEY4:
281  drec->sql_desc_octet_length = 12;
282  drec->sql_desc_display_size = 12;
283  drec->sql_desc_precision = 10;
284  drec->sql_desc_scale = 4;
285  SET_INFO2("money", "$", "", 10);
286 
287  case SYBDATETIME:
289  drec->sql_desc_display_size = 23;
290  drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
291  drec->sql_desc_precision = 3;
292  drec->sql_desc_scale = 3;
294  SET_INFO2("datetime", "'", "'", 23);
295 
296  case SYBDATETIME4:
298  /* TODO dependent on precision (decimal second digits) */
299  /* we always format using yyyy-mm-dd hh:mm:ss[.fff], see convert_tds2sql.c */
300  drec->sql_desc_display_size = 19;
301  drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
303  SET_INFO2("datetime", "'", "'", 16);
304 
305  /* The following two types are just Sybase types but as mainly our ODBC
306  * driver is much more compatible with Windows use attributes similar
307  * to MS one. For instance Sybase ODBC returns TIME into a TIME_STRUCT
308  * however this truncate the precision to 0 as TIME does not have
309  * fraction of seconds. Also Sybase ODBC have different concepts for
310  * PRECISION for many types and making these 2 types compatibles with
311  * Sybase would break this driver compatibility.
312  */
313  case SYBTIME:
316  /* we always format using hh:mm:ss[.fff], see convert_tds2sql.c */
317  drec->sql_desc_display_size = 12;
318  drec->sql_desc_precision = 3;
319  drec->sql_desc_scale = 3;
320  SET_INFO2("time", "'", "'", 12);
321 
322  case SYBDATE:
323  drec->sql_desc_octet_length = sizeof(DATE_STRUCT);
325  /* we always format using yyyy-mm-dd, see convert_tds2sql.c */
326  drec->sql_desc_display_size = 10;
327  SET_INFO2("date", "'", "'", 10);
328 
329  case XSYBBINARY:
330  case SYBBINARY:
332  drec->sql_desc_display_size = col->column_size * 2;
333  /* handle TIMESTAMP using usertype */
334  if (col->column_usertype == 80)
335  SET_INFO("timestamp", "0x", "");
336  SET_INFO("binary", "0x", "");
337 
338  case SYBLONGBINARY:
339  if (col->column_usertype == USER_UNICHAR_TYPE) {
342  SET_INFO2("unichar", "'", "'", col->on_server.column_size / 2);
343  }
347  SET_INFO2("univarchar", "'", "'", col->on_server.column_size / 2);
348  }
349  case SYBIMAGE:
351  drec->sql_desc_display_size = col->column_size * 2;
352  SET_INFO("image", "0x", "");
353 
354  case XSYBVARBINARY:
355  case SYBVARBINARY:
357  drec->sql_desc_display_size = col->column_size * 2;
358  if (is_blob_col(col)) {
360  drec->sql_desc_octet_length = drec->sql_desc_length =
362  }
363  SET_INFO("varbinary", "0x", "");
364 
365  case SYBINTN:
366  case SYBDATETIMN:
367  case SYBFLTN:
368  case SYBMONEYN:
369  case SYBUINTN:
370  case SYBTIMEN:
371  case SYBDATEN:
372  assert(0);
373 
374  case SYBVOID:
375  case SYBINTERVAL:
376  case SYBUNITEXT:
377  case SYBXML:
378  case SYBMSUDT:
379  break;
380 
381 #if (ODBCVER >= 0x0300)
382  case SYBUNIQUE:
383 #ifdef SQL_GUID
385 #else
387 #endif
388  drec->sql_desc_display_size = 36;
389  /* FIXME for Sybase ?? */
390  SET_INFO2("uniqueidentifier", "'", "'", 36);
391 #endif
392 
393  case SYBMSXML:
396  drec->sql_desc_octet_length = drec->sql_desc_length =
398  SET_INFO("xml", "'", "'");
399  /* types already handled in other types, just to silent warnings */
400  case SYBNUMERIC:
401  case SYBDECIMAL:
402  case SYBVARIANT:
403  case SYBMSDATE:
404  case SYBMSTIME:
405  case SYBMSDATETIME2:
406  case SYBMSDATETIMEOFFSET:
407  case SYB5BIGDATETIME:
408  case SYB5BIGTIME:
409  case SYBMSTABLE:
410  break;
411  }
412  SET_INFO("", "", "");
413 }
414 
415 static void
417 {
418 }
419 
420 void
421 odbc_set_sql_type_info(TDSCOLUMN * col, struct _drecord *drec, SQLINTEGER odbc_ver)
422 {
423  drec->sql_desc_precision = col->column_prec;
424  drec->sql_desc_scale = col->column_scale;
427  drec->sql_desc_num_prec_radix = 0;
429 
430  ((TDS_FUNCS *) col->funcs)->set_type_info(col, drec, odbc_ver);
431 
432  drec->sql_desc_type = drec->sql_desc_concise_type;
434  drec->sql_desc_type = SQL_DATETIME;
435 }
436 
437 # define TDS_DEFINE_FUNCS(name) \
438  const TDS_FUNCS tds_ ## name ## _funcs = { \
439  TDS_COMMON_FUNCS(name), \
440  data_ ## name ## _set_type_info, \
441  }
446 TDS_DEFINE_FUNCS(msdatetime);
448 TDS_DEFINE_FUNCS(sybbigtime);
449 TDS_DEFINE_FUNCS(mstabletype);
TDS_SERVER_TYPE
Definition: proto.h:161
@ SYBTIMEN
Definition: proto.h:226
@ SYBVARIANT
Definition: proto.h:200
@ SYB5INT8
Definition: proto.h:220
@ SYBINTERVAL
Definition: proto.h:221
@ SYBUINT8
Definition: proto.h:215
@ SYBLONGBINARY
Definition: proto.h:211
@ SYBUNIQUE
Definition: proto.h:199
@ SYBUINTN
Definition: proto.h:227
@ SYBXML
Definition: proto.h:229
@ XSYBNVARCHAR
Definition: proto.h:195
@ XSYBCHAR
Definition: proto.h:193
@ SYBUINT2
Definition: proto.h:213
@ SYBDATEN
Definition: proto.h:219
@ XSYBVARCHAR
Definition: proto.h:194
@ SYBUNITEXT
Definition: proto.h:228
@ SYBUINT4
Definition: proto.h:214
@ SYBSINT1
Definition: proto.h:224
@ XSYBVARBINARY
Definition: proto.h:197
@ XSYBNCHAR
Definition: proto.h:196
@ SYBMSUDT
Definition: proto.h:201
@ SYB5BIGTIME
Definition: proto.h:231
@ XSYBBINARY
Definition: proto.h:198
@ SYBMSXML
Definition: proto.h:202
@ SYB5BIGDATETIME
Definition: proto.h:230
@ SYBUINT1
Definition: proto.h:212
@ USER_UNICHAR_TYPE
Definition: proto.h:237
@ USER_UNIVARCHAR_TYPE
Definition: proto.h:238
#define is_blob_col(x)
Definition: tds.h:445
void odbc_set_sql_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:390
#define SQL_SS_TIME2
Definition: odbcss.h:81
#define SQL_SS_TABLE
Definition: odbcss.h:77
#define SQL_SS_TIMESTAMPOFFSET
Definition: odbcss.h:85
struct tagSS_TIME2_STRUCT SQL_SS_TIME2_STRUCT
#define SQL_SS_VARIANT
Definition: odbcss.h:65
#define SQL_SS_LENGTH_UNLIMITED
Definition: odbcss.h:39
struct tagSS_TIMESTAMPOFFSET_STRUCT SQL_SS_TIMESTAMPOFFSET_STRUCT
#define SQL_SS_XML
Definition: odbcss.h:73
#define SYBMSDATE
Definition: sybdb.h:222
#define SYBVOID
Definition: sybdb.h:198
#define SYBINT4
Definition: sybdb.h:170
#define SYBNUMERIC
Definition: sybdb.h:202
#define SYBVARCHAR
Definition: sybdb.h:162
#define SYBTEXT
Definition: sybdb.h:182
#define SYBNVARCHAR
Definition: sybdb.h:212
#define SYBDATE
Definition: sybdb.h:214
#define SYBINT8
Definition: sybdb.h:172
#define SYBMONEYN
Definition: sybdb.h:208
#define SYBMSDATETIME2
Definition: sybdb.h:226
#define SYBNTEXT
Definition: sybdb.h:184
#define SYBIMAGE
Definition: sybdb.h:186
#define SYBINTN
Definition: sybdb.h:164
#define SYBMSDATETIMEOFFSET
Definition: sybdb.h:228
#define SYBINT1
Definition: sybdb.h:166
#define SYBDATETIME4
Definition: sybdb.h:192
#define SYBDECIMAL
Definition: sybdb.h:204
#define SYBCHAR
Definition: sybdb.h:160
#define SYBREAL
Definition: sybdb.h:194
#define SYBDATETIMN
Definition: sybdb.h:210
#define SYBBITN
Definition: sybdb.h:180
#define SYBBINARY
Definition: sybdb.h:196
#define SYBTIME
Definition: sybdb.h:216
#define SYBMSTIME
Definition: sybdb.h:224
#define SYBDATETIME
Definition: sybdb.h:176
#define SYBVARBINARY
Definition: sybdb.h:200
#define SYBMONEY
Definition: sybdb.h:190
#define SYBMONEY4
Definition: sybdb.h:188
#define SYBFLT8
Definition: sybdb.h:174
#define SYBFLTN
Definition: sybdb.h:206
#define SYBINT2
Definition: sybdb.h:168
#define SYBBIT
Definition: sybdb.h:178
#define tds_get_conversion_type
#define ODBC_CLAMP(x, a, b)
Definition: odbc.h:93
@ SYBMSTABLE
Definition: proto.h:207
static void data_invalid_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:416
static void data_sybbigtime_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:118
static void data_clrudt_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:110
static void data_mstabletype_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:143
static void data_variant_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:88
#define SET_INFO(type, prefix, suffix)
Definition: odbc_data.c:40
#define SET_INFO2(type, prefix, suffix, len)
Definition: odbc_data.c:46
#define TDS_DEFINE_FUNCS(name)
Definition: odbc_data.c:437
static void data_generic_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:150
static void data_msdatetime_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:52
static void data_numeric_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:97
#define SQL_REAL
Definition: sql.h:173
#define SQL_TRUE
Definition: sql.h:219
#define SQL_CHAR
Definition: sql.h:167
#define SQL_TYPE_TIMESTAMP
Definition: sql.h:184
#define SQL_SMALLINT
Definition: sql.h:171
#define SQL_NUMERIC
Definition: sql.h:168
#define SQL_FALSE
Definition: sql.h:218
#define SQL_TYPE_DATE
Definition: sql.h:182
#define SQL_DECIMAL
Definition: sql.h:169
#define SQL_INTEGER
Definition: sql.h:170
#define SQL_DATETIME
Definition: sql.h:176
#define SQL_CODE_TIMESTAMP
Definition: sql.h:213
#define SQL_DOUBLE
Definition: sql.h:174
#define SQL_VARCHAR
Definition: sql.h:178
#define SQL_OV_ODBC3
Definition: sqlext.h:98
#define SQL_LONGVARBINARY
Definition: sqlext.h:435
#define SQL_LONGVARCHAR
Definition: sqlext.h:432
#define SQL_TINYINT
Definition: sqlext.h:437
#define SQL_BINARY
Definition: sqlext.h:433
#define SQL_VARBINARY
Definition: sqlext.h:434
#define SQL_BIT
Definition: sqlext.h:438
#define SQL_GUID
Definition: sqlext.h:440
#define SQL_BIGINT
Definition: sqlext.h:436
struct tagDATE_STRUCT DATE_STRUCT
long SQLINTEGER
Definition: sqltypes.h:176
struct tagTIMESTAMP_STRUCT TIMESTAMP_STRUCT
#define SQL_WCHAR
Definition: sqlucode.h:14
#define SQL_WVARCHAR
Definition: sqlucode.h:15
#define SQL_WLONGVARCHAR
Definition: sqlucode.h:16
#define assert(x)
Definition: srv_diag.hpp:58
Descriptor record.
Definition: odbc.h:164
SQLINTEGER sql_desc_num_prec_radix
Definition: odbc.h:186
SQLINTEGER sql_desc_display_size
Definition: odbc.h:174
SQLINTEGER sql_desc_octet_length
Definition: odbc.h:187
SQLSMALLINT sql_desc_unsigned
Definition: odbc.h:200
SQLUINTEGER sql_desc_length
Definition: odbc.h:178
SQLSMALLINT sql_desc_scale
Definition: odbc.h:192
SQLSMALLINT sql_desc_precision
Definition: odbc.h:190
SQLSMALLINT sql_desc_datetime_interval_code
Definition: odbc.h:172
SQLSMALLINT sql_desc_type
Definition: odbc.h:196
SQLSMALLINT sql_desc_concise_type
Definition: odbc.h:170
Metadata about columns in regular and compute rows.
Definition: tds.h:761
TDS_INT column_size
maximun size of data.
Definition: tds.h:766
const TDSCOLUMNFUNCS * funcs
Definition: tds.h:762
TDS_TINYINT column_prec
precision for decimal/numeric
Definition: tds.h:775
TDS_SERVER_TYPE column_type
This type can be different from wire type because conversion (e.g.
Definition: tds.h:768
TDSICONV * char_conv
refers to previously allocated iconv information
Definition: tds.h:784
TDS_TINYINT column_scale
scale for decimal/numeric
Definition: tds.h:776
struct tds_column::@124 on_server
TDS_INT column_usertype
Definition: tds.h:763
static const char * type_name(CS_INT value)
Definition: will_convert.c:122
Modified on Sat Jun 08 14:21:05 2024 by modify_doxy.py rev. 669887