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 <odbcss.h>
38 
39 #define SET_INFO(type, prefix, suffix) do { \
40  drec->sql_desc_literal_prefix = prefix; \
41  drec->sql_desc_literal_suffix = suffix; \
42  drec->sql_desc_type_name = type; \
43  return; \
44  } while(0)
45 #define SET_INFO2(type, prefix, suffix, len) do { \
46  drec->sql_desc_length = (len); \
47  SET_INFO(type, prefix, suffix); \
48  } while(0)
49 
50 static void
52 {
53  int decimals = col->column_prec ? col->column_prec + 1: 0;
54 
55  switch (col->on_server.column_type) {
56  case SYBMSTIME:
59  /* always hh:mm:ss[.fff] */
60  drec->sql_desc_display_size = 8 + decimals;
61  SET_INFO2("time", "'", "'", 8 + decimals);
62  case SYBMSDATE:
63  drec->sql_desc_octet_length = sizeof(DATE_STRUCT);
65  /* always yyyy-mm-dd ?? */
66  drec->sql_desc_display_size = 10;
67  SET_INFO2("date", "'", "'", 10);
71  /* we always format using yyyy-mm-dd hh:mm:ss[.fff] +HH:MM, see convert_tds2sql.c */
72  drec->sql_desc_display_size = 26 + decimals;
73  SET_INFO2("datetimeoffset", "'", "'", 26 + decimals);
74  case SYBMSDATETIME2:
78  /* we always format using yyyy-mm-dd hh:mm:ss[.fff], see convert_tds2sql.c */
79  drec->sql_desc_display_size = 19 + decimals;
80  SET_INFO2("datetime2", "'", "'", 19 + decimals);
81  default:
82  break;
83  }
84 }
85 
86 static void
88 {
90  drec->sql_desc_display_size = 8000;
91  drec->sql_desc_octet_length = 0;
92  SET_INFO2("sql_variant", "", "", 8000);
93 }
94 
95 static void
97 {
98  const char *type_name =
99  col->on_server.column_type == SYBNUMERIC ? "numeric" : "decimal";
100 
102  drec->sql_desc_octet_length = col->column_prec + 2;
103  drec->sql_desc_display_size = col->column_prec + 2;
104  drec->sql_desc_num_prec_radix = 10;
105  SET_INFO2(type_name, "", "", col->column_prec);
106 }
107 
108 static void
110 {
112  /* TODO ??? */
113  drec->sql_desc_display_size = col->column_size * 2;
114 }
115 
116 static void
118 {
119  if (col->on_server.column_type == SYB5BIGTIME) {
121  /* we always format using hh:mm:ss[.ffffff], see convert_tds2sql.c */
122  drec->sql_desc_display_size = 15;
124  drec->sql_desc_precision = 6;
125  drec->sql_desc_scale = 6;
127  SET_INFO2("bigtime", "'", "'", 15);
128  }
129 
131 
133  drec->sql_desc_display_size = 26;
134  drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
135  drec->sql_desc_precision = 6;
136  drec->sql_desc_scale = 6;
138  SET_INFO2("bigdatetime", "'", "'", 26);
139 }
140 
141 static void
143 {
144  TDS_SERVER_TYPE col_type = col->on_server.column_type;
145  int col_size = col->on_server.column_size;
146 
147  switch (tds_get_conversion_type(col_type, col_size)) {
148  case XSYBNCHAR:
151  SET_INFO2("nchar", "'", "'", col->on_server.column_size / 2);
152 
153  case XSYBCHAR:
154  case SYBCHAR:
157  SET_INFO("char", "'", "'");
158 
159  /* TODO really sure ?? SYBNVARCHAR sybase only ?? */
160  case SYBNVARCHAR:
161  case XSYBNVARCHAR:
164  drec->sql_desc_length = col->on_server.column_size / 2u;
165  if (is_blob_col(col)) {
167  drec->sql_desc_octet_length = drec->sql_desc_length =
169  }
170  SET_INFO("nvarchar", "'", "'");
171 
172  case XSYBVARCHAR:
173  case SYBVARCHAR:
176  if (is_blob_col(col)) {
178  drec->sql_desc_octet_length = drec->sql_desc_length =
180  }
181  SET_INFO("varchar", "'", "'");
182 
183  case SYBNTEXT:
186  SET_INFO2("ntext", "'", "'", col->on_server.column_size / 2);
187 
188  case SYBTEXT:
191  SET_INFO("text", "'", "'");
192 
193  case SYBBIT:
194  case SYBBITN:
196  drec->sql_desc_display_size = 1;
197  drec->sql_desc_unsigned = SQL_TRUE;
198  SET_INFO2("bit", "", "", 1);
199 
200 #if (ODBCVER >= 0x0300)
201  case SYB5INT8:
202  case SYBINT8:
203  /* TODO return numeric for odbc2 and convert bigint to numeric */
205  drec->sql_desc_display_size = 20;
206  SET_INFO2("bigint", "", "", 19);
207 #endif
208 
209  case SYBINT4:
211  drec->sql_desc_display_size = 11; /* -1000000000 */
212  SET_INFO2("int", "", "", 10);
213 
214  case SYBINT2:
216  drec->sql_desc_display_size = 6; /* -10000 */
217  SET_INFO2("smallint", "", "", 5);
218 
219  case SYBUINT1:
220  case SYBINT1:
221  drec->sql_desc_unsigned = SQL_TRUE;
222  case SYBSINT1: /* TODO not another type_name ?? */
224  drec->sql_desc_display_size = 3; /* 255 */
225  SET_INFO2("tinyint", "", "", 3);
226 
227 #if (ODBCVER >= 0x0300)
228  case SYBUINT8:
229  drec->sql_desc_unsigned = SQL_TRUE;
231  drec->sql_desc_display_size = 20;
232  /* TODO return numeric for odbc2 and convert bigint to numeric */
233  SET_INFO2("unsigned bigint", "", "", 20);
234 #endif
235 
236  case SYBUINT4:
237  drec->sql_desc_unsigned = SQL_TRUE;
239  drec->sql_desc_display_size = 10;
240  SET_INFO2("unsigned int", "", "", 10);
241 
242  case SYBUINT2:
243  drec->sql_desc_unsigned = SQL_TRUE;
245  drec->sql_desc_display_size = 5; /* 65535 */
246  SET_INFO2("unsigned smallint", "", "", 5);
247 
248  case SYBREAL:
250  drec->sql_desc_display_size = 14;
251  SET_INFO2("real", "", "", odbc_ver == SQL_OV_ODBC3 ? 24 : 7);
252 
253  case SYBFLT8:
255  drec->sql_desc_display_size = 24; /* FIXME -- what should the correct size be? */
256  SET_INFO2("float", "", "", odbc_ver == SQL_OV_ODBC3 ? 53 : 15);
257 
258  case SYBMONEY:
259  /* TODO check money format returned by propretary ODBC, scale == 4 but we use 2 digits */
261  drec->sql_desc_octet_length = 21;
262  drec->sql_desc_display_size = 21;
263  drec->sql_desc_precision = 19;
264  drec->sql_desc_scale = 4;
265  SET_INFO2("money", "$", "", 19);
266 
267  case SYBMONEY4:
269  drec->sql_desc_octet_length = 12;
270  drec->sql_desc_display_size = 12;
271  drec->sql_desc_precision = 10;
272  drec->sql_desc_scale = 4;
273  SET_INFO2("money", "$", "", 10);
274 
275  case SYBDATETIME:
277  drec->sql_desc_display_size = 23;
278  drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
279  drec->sql_desc_precision = 3;
280  drec->sql_desc_scale = 3;
282  SET_INFO2("datetime", "'", "'", 23);
283 
284  case SYBDATETIME4:
286  /* TODO dependent on precision (decimal second digits) */
287  /* we always format using yyyy-mm-dd hh:mm:ss[.fff], see convert_tds2sql.c */
288  drec->sql_desc_display_size = 19;
289  drec->sql_desc_octet_length = sizeof(TIMESTAMP_STRUCT);
291  SET_INFO2("datetime", "'", "'", 16);
292 
293  /* The following two types are just Sybase types but as mainly our ODBC
294  * driver is much more compatible with Windows use attributes similar
295  * to MS one. For instance Sybase ODBC returns TIME into a TIME_STRUCT
296  * however this truncate the precision to 0 as TIME does not have
297  * fraction of seconds. Also Sybase ODBC have different concepts for
298  * PRECISION for many types and making these 2 types compatibles with
299  * Sybase would break this driver compatibility.
300  */
301  case SYBTIME:
304  /* we always format using hh:mm:ss[.fff], see convert_tds2sql.c */
305  drec->sql_desc_display_size = 12;
306  drec->sql_desc_precision = 3;
307  drec->sql_desc_scale = 3;
308  SET_INFO2("time", "'", "'", 12);
309 
310  case SYBDATE:
311  drec->sql_desc_octet_length = sizeof(DATE_STRUCT);
313  /* we always format using yyyy-mm-dd, see convert_tds2sql.c */
314  drec->sql_desc_display_size = 10;
315  SET_INFO2("date", "'", "'", 10);
316 
317  case XSYBBINARY:
318  case SYBBINARY:
320  drec->sql_desc_display_size = col->column_size * 2;
321  /* handle TIMESTAMP using usertype */
322  if (col->column_usertype == 80)
323  SET_INFO("timestamp", "0x", "");
324  SET_INFO("binary", "0x", "");
325 
326  case SYBLONGBINARY:
327  case SYBIMAGE:
329  drec->sql_desc_display_size = col->column_size * 2;
330  SET_INFO("image", "0x", "");
331 
332  case XSYBVARBINARY:
333  case SYBVARBINARY:
335  drec->sql_desc_display_size = col->column_size * 2;
336  if (is_blob_col(col)) {
338  drec->sql_desc_octet_length = drec->sql_desc_length =
340  }
341  SET_INFO("varbinary", "0x", "");
342 
343  case SYBINTN:
344  case SYBDATETIMN:
345  case SYBFLTN:
346  case SYBMONEYN:
347  case SYBUINTN:
348  case SYBTIMEN:
349  case SYBDATEN:
350  assert(0);
351 
352  case SYBVOID:
353  case SYBINTERVAL:
354  case SYBUNITEXT:
355  case SYBXML:
356  case SYBMSUDT:
357  break;
358 
359 #if (ODBCVER >= 0x0300)
360  case SYBUNIQUE:
361 #ifdef SQL_GUID
363 #else
365 #endif
366  drec->sql_desc_display_size = 36;
367  /* FIXME for Sybase ?? */
368  SET_INFO2("uniqueidentifier", "'", "'", 36);
369 #endif
370 
371  case SYBMSXML:
374  drec->sql_desc_octet_length = drec->sql_desc_length =
376  SET_INFO("xml", "'", "'");
377 
378  default: /* SYBNUMERIC, etc. */
379  break;
380  }
381  SET_INFO("", "", "");
382 }
383 
384 static void
386 {
387 }
388 
389 void
390 odbc_set_sql_type_info(TDSCOLUMN * col, struct _drecord *drec, SQLINTEGER odbc_ver)
391 {
392  drec->sql_desc_precision = col->column_prec;
393  drec->sql_desc_scale = col->column_scale;
396  drec->sql_desc_num_prec_radix = 0;
398 
399  ((TDS_FUNCS *) col->funcs)->set_type_info(col, drec, odbc_ver);
400 
401  drec->sql_desc_type = drec->sql_desc_concise_type;
403  drec->sql_desc_type = SQL_DATETIME;
404 }
405 
406 # define TDS_DEFINE_FUNCS(name) \
407  const TDS_FUNCS tds_ ## name ## _funcs = { \
408  TDS_COMMON_FUNCS(name), \
409  data_ ## name ## _set_type_info, \
410  }
415 TDS_DEFINE_FUNCS(msdatetime);
417 TDS_DEFINE_FUNCS(sybbigtime);
TDS_SERVER_TYPE
Definition: proto.h:161
@ SYBTIMEN
Definition: proto.h:226
@ 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
#define is_blob_col(x)
Definition: tds.h:445
static void data_invalid_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:385
static void data_sybbigtime_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:117
static void data_clrudt_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:109
void odbc_set_sql_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:390
static void data_variant_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:87
#define SET_INFO(type, prefix, suffix)
Definition: odbc_data.c:39
#define SET_INFO2(type, prefix, suffix, len)
Definition: odbc_data.c:45
#define TDS_DEFINE_FUNCS(name)
Definition: odbc_data.c:406
static void data_generic_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:142
static void data_msdatetime_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:51
static void data_numeric_set_type_info(TDSCOLUMN *col, struct _drecord *drec, SQLINTEGER odbc_ver)
Definition: odbc_data.c:96
#define SQL_SS_TIME2
Definition: odbcss.h:81
#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 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 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
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:23:38 2024 by modify_doxy.py rev. 669887