Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns
3 : * Copyright (C) 2005-2010 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #if HAVE_STDLIB_H
24 : #include <stdlib.h>
25 : #endif /* HAVE_STDLIB_H */
26 :
27 : #if HAVE_STRING_H
28 : #include <string.h>
29 : #endif /* HAVE_STRING_H */
30 :
31 : #include <assert.h>
32 :
33 : #include <freetds/odbc.h>
34 : #include <freetds/iconv.h>
35 : #include <freetds/utils/string.h>
36 : #include <freetds/convert.h>
37 : #include <freetds/enum_cap.h>
38 : #include <freetds/utils/bjoern-utf8.h>
39 : #include <odbcss.h>
40 :
41 : /**
42 : * \ingroup odbc_api
43 : * \defgroup odbc_util ODBC utility
44 : * Functions called within \c ODBC driver.
45 : */
46 :
47 : /**
48 : * \addtogroup odbc_util
49 : * @{
50 : */
51 :
52 : #ifdef ENABLE_ODBC_WIDE
53 : static DSTR *odbc_iso2utf(DSTR *res, const char *s, unsigned int len);
54 : static DSTR *odbc_mb2utf(TDS_DBC *dbc, DSTR *res, const char *s, unsigned int len);
55 : static DSTR *odbc_wide2utf(DSTR *res, const SQLWCHAR *s, unsigned int len);
56 : #endif
57 :
58 : int
59 24436 : odbc_set_stmt_query(TDS_STMT * stmt, const ODBC_CHAR *sql, int sql_len _WIDE)
60 : {
61 24436 : if (sql_len == SQL_NTS)
62 : #ifdef ENABLE_ODBC_WIDE
63 24044 : sql_len = wide ? sqlwcslen(sql->wide) : strlen(sql->mb);
64 : #else
65 : sql_len = strlen((const char*) sql);
66 : #endif
67 392 : else if (sql_len <= 0)
68 : return SQL_ERROR;
69 :
70 : /* TODO already NULL ?? */
71 24436 : tds_free_param_results(stmt->params);
72 24436 : stmt->params = NULL;
73 24436 : stmt->param_num = 0;
74 24436 : stmt->param_count = 0;
75 24436 : stmt->is_prepared_query = 0;
76 24436 : stmt->prepared_query_is_func = 0;
77 24436 : stmt->prepared_query_is_rpc = 0;
78 24436 : stmt->prepared_pos = 0;
79 24436 : stmt->curr_param_row = 0;
80 24436 : stmt->num_param_rows = 1;
81 24436 : stmt->need_reprepare = 0;
82 :
83 24436 : if (!odbc_dstr_copy(stmt->dbc, &stmt->query, sql_len, sql))
84 : return SQL_ERROR;
85 :
86 24436 : return SQL_SUCCESS;
87 : }
88 :
89 : unsigned int
90 31502 : odbc_get_string_size(int size, const ODBC_CHAR * str _WIDE)
91 : {
92 31502 : if (str) {
93 31218 : if (size == SQL_NTS)
94 : #ifdef ENABLE_ODBC_WIDE
95 6224 : return wide ? sqlwcslen(str->wide) : strlen(str->mb);
96 : #else
97 : return strlen((const char*) str);
98 : #endif
99 24994 : if (size >= 0)
100 24994 : return (unsigned int) size;
101 : }
102 : /* SQL_NULL_DATA or any other strange value */
103 : return 0;
104 : }
105 :
106 : #ifdef ENABLE_ODBC_WIDE
107 : static DSTR*
108 1268 : odbc_iso2utf(DSTR *res, const char *s, unsigned int len)
109 : {
110 1268 : unsigned int i, o_len = len + 1;
111 : char *out, *p;
112 :
113 1268 : assert(s);
114 15068 : for (i = 0; i < len; ++i)
115 15068 : if ((s[i] & 0x80) != 0)
116 0 : ++o_len;
117 :
118 1268 : if (!tds_dstr_alloc(res, o_len))
119 : return NULL;
120 2536 : out = tds_dstr_buf(res);
121 :
122 16336 : for (p = out; len > 0; --len) {
123 15068 : unsigned char u = (unsigned char) *s++;
124 15068 : if ((u & 0x80) != 0) {
125 0 : *p++ = 0xc0 | (0x1f & (u >> 6));
126 0 : *p++ = 0x80 | (0x3f & u);
127 : } else {
128 15068 : *p++ = u;
129 : }
130 : }
131 1268 : assert(p + 1 <= out + o_len);
132 1268 : return tds_dstr_setlen(res, p - out);
133 : }
134 :
135 : static DSTR*
136 15808 : odbc_wide2utf(DSTR *res, const SQLWCHAR *s, unsigned int len)
137 : {
138 15808 : unsigned int i, o_len = len + 1;
139 : char *out, *p;
140 :
141 : #if SIZEOF_SQLWCHAR > 2
142 : # define MASK(n) ((0xffffffffu << (n)) & 0xffffffffu)
143 : #else
144 : # define MASK(n) ((0xffffu << (n)) & 0xffffu)
145 : #endif
146 :
147 15808 : assert(s || len == 0);
148 609905 : for (i = 0; i < len; ++i) {
149 609905 : if ((s[i] & MASK(7)) == 0)
150 609497 : continue;
151 408 : ++o_len;
152 408 : if ((s[i] & MASK(11)) == 0)
153 268 : continue;
154 140 : ++o_len;
155 : #if SIZEOF_SQLWCHAR > 2
156 : if ((s[i] & MASK(16)) == 0)
157 : continue;
158 : ++o_len;
159 : if ((s[i] & MASK(21)) == 0)
160 : continue;
161 : ++o_len;
162 : if ((s[i] & MASK(26)) == 0)
163 : continue;
164 : ++o_len;
165 : #endif
166 : }
167 :
168 15808 : if (!tds_dstr_alloc(res, o_len))
169 : return NULL;
170 31616 : out = tds_dstr_buf(res);
171 :
172 : #undef MASK
173 : #define MASK(n) ((0xffffffffu << (n)) & 0xffffffffu)
174 625673 : for (p = out; len > 0; --len) {
175 609865 : uint32_t u = *s++;
176 : /* easy case, ASCII */
177 609865 : if ((u & MASK(7)) == 0) {
178 609497 : *p++ = (char) u;
179 609497 : continue;
180 : }
181 : #if SIZEOF_SQLWCHAR == 2
182 368 : if ((u & 0xfc00) == 0xd800 && len > 1) {
183 40 : uint32_t c2 = *s;
184 40 : if ((c2 & 0xfc00) == 0xdc00) {
185 40 : u = (u << 10) + c2 - ((0xd800 << 10) + 0xdc00 - 0x10000);
186 40 : ++s;
187 40 : --len;
188 : }
189 : }
190 : #endif
191 368 : if ((u & MASK(11)) == 0) {
192 268 : *p++ = 0xc0 | (u >> 6);
193 : } else {
194 100 : if ((u & MASK(16)) == 0) {
195 60 : *p++ = 0xe0 | (u >> 12);
196 : } else {
197 : if ((SIZEOF_SQLWCHAR == 2) || (u & MASK(21)) == 0) {
198 40 : *p++ = 0xf0 | (u >> 18);
199 : } else {
200 : if ((u & MASK(26)) == 0) {
201 : *p++ = 0xf8 | (u >> 24);
202 : } else {
203 : *p++ = 0xfc | (0x01 & (u >> 30));
204 : *p++ = 0x80 | (0x3f & (u >> 24));
205 : }
206 : *p++ = 0x80 | (0x3f & (u >> 18));
207 : }
208 40 : *p++ = 0x80 | (0x3f & (u >> 12));
209 : }
210 100 : *p++ = 0x80 | (0x3f & (u >> 6));
211 : }
212 368 : *p++ = 0x80 | (0x3f & u);
213 : }
214 15808 : assert(p + 1 <= out + o_len);
215 15808 : return tds_dstr_setlen(res, p - out);
216 : }
217 :
218 : static DSTR*
219 14082 : odbc_mb2utf(TDS_DBC *dbc, DSTR *res, const char *s, unsigned int len)
220 : {
221 : char *buf;
222 :
223 : const char *ib;
224 : char *ob;
225 : size_t il, ol;
226 14082 : TDSICONV *char_conv = dbc->mb_conv;
227 :
228 14082 : if (!char_conv)
229 1268 : return odbc_iso2utf(res, s, len);
230 :
231 12814 : if (char_conv->flags == TDS_ENCODING_MEMCPY)
232 163 : return tds_dstr_copyn(res, s, len);
233 :
234 12651 : il = len;
235 :
236 : /* allocate needed buffer (+1 is to exclude 0 case) */
237 12651 : ol = il * char_conv->to.charset.max_bytes_per_char / char_conv->from.charset.min_bytes_per_char + 1;
238 : assert(ol > 0);
239 12651 : if (!tds_dstr_alloc(res, ol))
240 : return NULL;
241 25302 : buf = tds_dstr_buf(res);
242 :
243 12651 : ib = s;
244 12651 : ob = buf;
245 12651 : --ol; /* leave space for terminator */
246 :
247 : /* char_conv is only mostly const */
248 12651 : memset((TDS_ERRNO_MESSAGE_FLAGS*) &char_conv->suppress, 0, sizeof(char_conv->suppress));
249 12651 : if (tds_iconv(dbc->tds_socket, char_conv, to_server, &ib, &il, &ob, &ol) == (size_t)-1)
250 : return NULL;
251 :
252 12651 : return tds_dstr_setlen(res, ob - buf);
253 : }
254 : #endif
255 :
256 : #ifdef ENABLE_ODBC_WIDE
257 : /**
258 : * Copy a string from client setting according to ODBC convenction
259 : * @param dbc database connection. Can't be NULL
260 : * @param s output string
261 : * @param size size of str, Can be SQL_NTS
262 : * @param str string to convert
263 : * @param flag set of flags.
264 : * 0x01 wide string in buffer
265 : * 0x20 size is in bytes, not characters
266 : */
267 : DSTR*
268 29890 : odbc_dstr_copy_flag(TDS_DBC *dbc, DSTR *s, int size, const ODBC_CHAR * str, int flag)
269 : {
270 29890 : int wide = flag&1;
271 : unsigned int len;
272 :
273 29890 : len = odbc_get_string_size((flag&0x21) == 0x21 && size >= 0 ? size/SIZEOF_SQLWCHAR : size, str, wide);
274 29890 : if (wide)
275 15808 : return odbc_wide2utf(s, str->wide, len);
276 :
277 14082 : return odbc_mb2utf(dbc, s, str->mb, len);
278 : }
279 : #else
280 : DSTR*
281 : odbc_dstr_copy(TDS_DBC *dbc, DSTR *s, int size, const ODBC_CHAR * str)
282 : {
283 : return tds_dstr_copyn(s, (const char *) str, odbc_get_string_size(size, str));
284 : }
285 : #endif
286 :
287 : /**
288 : * Copy a string to client setting size according to ODBC convenction
289 : * @param dbc database connection. Can be NULL
290 : * @param buffer client buffer
291 : * @param cbBuffer client buffer size (in bytes)
292 : * @param pcbBuffer pointer to SQLSMALLINT to hold string size
293 : * @param s string to copy
294 : * @param len len of string to copy. <0 null terminated
295 : * @param flag set of flags.
296 : * 0x01 wide string in buffer
297 : * 0x10 pcbBuffer is SQLINTEGER otherwise SQLSMALLINT
298 : * 0x20 size is in bytes, not characters
299 : */
300 : SQLRETURN
301 7036 : odbc_set_string_flag(TDS_DBC *dbc, SQLPOINTER buffer, SQLINTEGER cbBuffer, void FAR * pcbBuffer, const char *s, int len, int flag)
302 : {
303 7036 : SQLRETURN result = SQL_SUCCESS;
304 7036 : int out_len = 0;
305 : #if !defined(NDEBUG) && defined(ENABLE_ODBC_WIDE)
306 : size_t initial_size;
307 : #endif
308 :
309 7036 : if (len < 0)
310 3188 : len = strlen(s);
311 :
312 7036 : if (cbBuffer < 0)
313 0 : cbBuffer = 0;
314 :
315 : #ifdef ENABLE_ODBC_WIDE
316 7036 : if ((flag & 1) != 0) {
317 : /* wide characters */
318 3570 : const unsigned char *p = (const unsigned char*) s;
319 3570 : const unsigned char *const p_end = p + len;
320 3570 : SQLWCHAR *dest = (SQLWCHAR*) buffer;
321 :
322 3570 : if (flag&0x20)
323 1206 : cbBuffer /= SIZEOF_SQLWCHAR;
324 : #ifndef NDEBUG
325 3570 : initial_size = cbBuffer;
326 : #endif
327 72986 : while (p < p_end) {
328 : uint32_t u, state = UTF8_ACCEPT;
329 :
330 132172 : while (decode_utf8(&state, &u, *p++) > UTF8_REJECT && p < p_end)
331 240 : continue;
332 65846 : if (state != UTF8_ACCEPT)
333 : break;
334 :
335 65846 : ++out_len;
336 65846 : if (SIZEOF_SQLWCHAR == 2 && u >= 0x10000 && u < 0x110000u)
337 40 : ++out_len;
338 65846 : if (!dest)
339 1258 : continue;
340 64588 : if (SIZEOF_SQLWCHAR == 2 && u >= 0x10000) {
341 40 : if (cbBuffer > 2 && u < 0x110000u) {
342 40 : *dest++ = (SQLWCHAR) (0xd7c0 + (u >> 10));
343 40 : *dest++ = (SQLWCHAR) (0xdc00 + (u & 0x3ffu));
344 40 : cbBuffer -= 2;
345 40 : continue;
346 : }
347 0 : if (cbBuffer > 1) {
348 0 : *dest++ = (SQLWCHAR) '?';
349 0 : --cbBuffer;
350 : }
351 64548 : } else if (cbBuffer > 1) {
352 62740 : *dest++ = (SQLWCHAR) u;
353 62740 : --cbBuffer;
354 62740 : continue;
355 : }
356 : result = SQL_SUCCESS_WITH_INFO;
357 : }
358 : /* terminate buffer */
359 3570 : assert(dest == NULL || dest-(SQLWCHAR*) buffer == out_len
360 : || (dest-(SQLWCHAR*) buffer <= out_len && cbBuffer <= 1));
361 3570 : if (dest && cbBuffer) {
362 3160 : *dest++ = 0;
363 3160 : assert(dest-(SQLWCHAR*) buffer <= initial_size);
364 : }
365 3570 : assert(dest == NULL || dest-(SQLWCHAR*) buffer <= initial_size);
366 3570 : if (flag&0x20)
367 1206 : out_len *= SIZEOF_SQLWCHAR;
368 3466 : } else if (!dbc || !dbc->mb_conv) {
369 : /* to ISO-8859-1 */
370 75 : const unsigned char *p = (const unsigned char*) s;
371 75 : const unsigned char *const p_end = p + len;
372 75 : unsigned char *dest = (unsigned char*) buffer;
373 :
374 : #ifndef NDEBUG
375 75 : initial_size = cbBuffer;
376 : #endif
377 5761 : while (p < p_end) {
378 : uint32_t u, state = UTF8_ACCEPT;
379 :
380 11222 : while (decode_utf8(&state, &u, *p++) > UTF8_REJECT && p < p_end)
381 0 : continue;
382 5611 : if (state != UTF8_ACCEPT)
383 : break;
384 :
385 5611 : ++out_len;
386 5611 : if (!dest)
387 0 : continue;
388 5611 : if (cbBuffer > 1) {
389 5611 : *dest++ = u > 0x100 ? '?' : u;
390 5611 : --cbBuffer;
391 5611 : continue;
392 : }
393 : result = SQL_SUCCESS_WITH_INFO;
394 : }
395 75 : assert(dest == NULL || dest-(unsigned char*) buffer == out_len
396 : || (dest-(unsigned char*) buffer <= out_len && cbBuffer <= 1));
397 : /* terminate buffer */
398 75 : if (dest && cbBuffer) {
399 75 : *dest++ = 0;
400 75 : assert(dest-(unsigned char*) buffer <= initial_size);
401 : }
402 75 : assert(dest == NULL || dest-(unsigned char*) buffer <= initial_size);
403 3391 : } else if (dbc->mb_conv->flags == TDS_ENCODING_MEMCPY) {
404 : /* to UTF-8 */
405 41 : out_len = len;
406 41 : if (len >= cbBuffer) {
407 0 : len = cbBuffer - 1;
408 0 : result = SQL_SUCCESS_WITH_INFO;
409 : }
410 41 : if (buffer && len >= 0) {
411 : /* buffer can overlap, use memmove, thanks to Valgrind */
412 41 : memmove((char *) buffer, s, len);
413 41 : ((char *) buffer)[len] = 0;
414 : }
415 : } else {
416 : const char *ib;
417 : char *ob;
418 : size_t il, ol;
419 3350 : TDSICONV *char_conv = dbc->mb_conv;
420 :
421 3350 : il = len;
422 3350 : ib = s;
423 3350 : ol = cbBuffer;
424 3350 : ob = (char *) buffer;
425 :
426 : /* char_conv is only mostly const */
427 3350 : memset((TDS_ERRNO_MESSAGE_FLAGS*) &char_conv->suppress, 0, sizeof(char_conv->suppress));
428 3350 : char_conv->suppress.e2big = 1;
429 3350 : if (cbBuffer && tds_iconv(dbc->tds_socket, char_conv, to_client, &ib, &il, &ob, &ol) == (size_t)-1 && errno != E2BIG)
430 0 : result = SQL_ERROR;
431 3350 : out_len = cbBuffer - ol;
432 7132 : while (result != SQL_ERROR && il) {
433 : char discard[128];
434 432 : ol = sizeof(discard);
435 432 : ob = discard;
436 432 : char_conv->suppress.e2big = 1;
437 432 : if (tds_iconv(dbc->tds_socket, char_conv, to_client, &ib, &il, &ob, &ol) == (size_t)-1 && errno != E2BIG)
438 0 : result = SQL_ERROR;
439 432 : ol = sizeof(discard) - ol;
440 : /* if there are still left space copy the partial conversion */
441 432 : if (out_len < cbBuffer) {
442 0 : size_t max_copy = cbBuffer - out_len;
443 0 : if (max_copy > ol)
444 0 : max_copy = ol;
445 0 : memcpy(((char *) buffer) + out_len, discard, max_copy);
446 : }
447 432 : out_len += ol;
448 : }
449 3350 : if (out_len >= cbBuffer && result != SQL_ERROR)
450 420 : result = SQL_SUCCESS_WITH_INFO;
451 3350 : if (buffer && cbBuffer > 0)
452 2940 : ((char *) buffer)[cbBuffer-1 < out_len ? cbBuffer-1:out_len] = 0;
453 : }
454 : #else
455 : out_len = len;
456 : if (len >= cbBuffer) {
457 : len = cbBuffer - 1;
458 : result = SQL_SUCCESS_WITH_INFO;
459 : }
460 : if (buffer && len >= 0) {
461 : /* buffer can overlap, use memmove, thanks to Valgrind */
462 : memmove((char *) buffer, s, len);
463 : ((char *) buffer)[len] = 0;
464 : }
465 : #endif
466 :
467 : /* set output length */
468 7036 : if (pcbBuffer) {
469 3894 : if (flag & 0x10)
470 190 : *((SQLINTEGER *) pcbBuffer) = out_len;
471 : else
472 3704 : *((SQLSMALLINT *) pcbBuffer) = out_len;
473 : }
474 7036 : return result;
475 : }
476 :
477 :
478 : void
479 954 : odbc_set_return_status(struct _hstmt *stmt, unsigned int n_row)
480 : {
481 954 : TDSSOCKET *tds = stmt->tds;
482 :
483 : /* TODO handle different type results (functions) on mssql2k */
484 954 : if (stmt->prepared_query_is_func && tds->has_status) {
485 : struct _drecord *drec;
486 : int len;
487 150 : const TDS_DESC* axd = stmt->apd;
488 : TDS_INTPTR len_offset;
489 : char *data_ptr;
490 :
491 150 : if (axd->header.sql_desc_count < 1)
492 : return;
493 150 : drec = &axd->records[0];
494 150 : data_ptr = (char*) drec->sql_desc_data_ptr;
495 :
496 150 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
497 0 : len_offset = axd->header.sql_desc_bind_type * n_row;
498 0 : if (axd->header.sql_desc_bind_offset_ptr)
499 0 : len_offset += *axd->header.sql_desc_bind_offset_ptr;
500 0 : data_ptr += len_offset;
501 : } else {
502 150 : len_offset = sizeof(SQLLEN) * n_row;
503 150 : data_ptr += sizeof(SQLINTEGER) * n_row;
504 : }
505 : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
506 :
507 150 : len = odbc_tds2sql_int4(stmt, &tds->ret_status, drec->sql_desc_concise_type,
508 150 : (TDS_CHAR *) data_ptr, drec->sql_desc_octet_length);
509 150 : if (len == SQL_NULL_DATA)
510 : return /* SQL_ERROR */ ;
511 150 : if (drec->sql_desc_indicator_ptr)
512 150 : LEN(drec->sql_desc_indicator_ptr) = 0;
513 150 : if (drec->sql_desc_octet_length_ptr)
514 150 : LEN(drec->sql_desc_octet_length_ptr) = len;
515 : }
516 : #undef LEN
517 : }
518 :
519 : void
520 648 : odbc_set_return_params(struct _hstmt *stmt, unsigned int n_row)
521 : {
522 648 : TDSSOCKET *tds = stmt->tds;
523 648 : TDSPARAMINFO *info = tds->current_results;
524 :
525 648 : int i_begin = stmt->prepared_query_is_func ? 1 : 0;
526 : int i;
527 648 : int nparam = i_begin;
528 :
529 : /* I don't understand why but this happen -- freddy77 */
530 : /* TODO check why, put an assert ? */
531 648 : if (!info)
532 : return;
533 :
534 768 : for (i = 0; i < info->num_cols; ++i) {
535 768 : const TDS_DESC* axd = stmt->apd;
536 : const struct _drecord *drec_apd, *drec_ipd;
537 768 : TDSCOLUMN *colinfo = info->columns[i];
538 : SQLINTEGER len;
539 : int c_type;
540 : char *data_ptr;
541 : TDS_INTPTR len_offset;
542 :
543 : /* find next output parameter */
544 : for (;;) {
545 886 : drec_apd = NULL;
546 : /* TODO best way to stop */
547 886 : if (nparam >= axd->header.sql_desc_count || nparam >= stmt->ipd->header.sql_desc_count)
548 : return;
549 886 : drec_apd = &axd->records[nparam];
550 886 : drec_ipd = &stmt->ipd->records[nparam];
551 886 : if (stmt->ipd->records[nparam++].sql_desc_parameter_type != SQL_PARAM_INPUT)
552 : break;
553 : }
554 :
555 768 : data_ptr = (char*) drec_apd->sql_desc_data_ptr;
556 768 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
557 0 : len_offset = axd->header.sql_desc_bind_type * n_row;
558 0 : if (axd->header.sql_desc_bind_offset_ptr)
559 0 : len_offset += *axd->header.sql_desc_bind_offset_ptr;
560 0 : data_ptr += len_offset;
561 : } else {
562 768 : len_offset = sizeof(SQLLEN) * n_row;
563 768 : data_ptr += odbc_get_octet_len(drec_apd->sql_desc_concise_type, drec_apd) * n_row;
564 : }
565 : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
566 :
567 : /* null parameter ? */
568 768 : if (colinfo->column_cur_size < 0) {
569 : /* FIXME error if NULL */
570 0 : if (drec_apd->sql_desc_indicator_ptr)
571 0 : LEN(drec_apd->sql_desc_indicator_ptr) = SQL_NULL_DATA;
572 0 : continue;
573 : }
574 :
575 768 : colinfo->column_text_sqlgetdatapos = 0;
576 768 : colinfo->column_iconv_left = 0;
577 768 : c_type = drec_apd->sql_desc_concise_type;
578 768 : if (c_type == SQL_C_DEFAULT)
579 0 : c_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
580 : /*
581 : * TODO why IPD ?? perhaps SQLBindParameter it's not correct ??
582 : * Or tests are wrong ??
583 : */
584 768 : len = odbc_tds2sql_col(stmt, colinfo, c_type, (TDS_CHAR*) data_ptr, drec_apd->sql_desc_octet_length, drec_ipd);
585 768 : if (len == SQL_NULL_DATA)
586 : return /* SQL_ERROR */ ;
587 768 : if (drec_apd->sql_desc_indicator_ptr)
588 768 : LEN(drec_apd->sql_desc_indicator_ptr) = 0;
589 768 : if (drec_apd->sql_desc_octet_length_ptr)
590 768 : LEN(drec_apd->sql_desc_octet_length_ptr) = len;
591 : #undef LEN
592 : }
593 : }
594 :
595 : /**
596 : * Pass this an SQL_C_* type and get a SYB* type which most closely corresponds
597 : * to the SQL_C_* type.
598 : * This function can return XSYBNVARCHAR or SYBUINTx even if server do not support it
599 : */
600 : TDS_SERVER_TYPE
601 58718 : odbc_c_to_server_type(int c_type)
602 : {
603 63028 : switch (c_type) {
604 : /* FIXME this should be dependent on size of data !!! */
605 : case SQL_C_BINARY:
606 : return SYBBINARY;
607 : #ifdef SQL_C_WCHAR
608 : case SQL_C_WCHAR:
609 : return XSYBNVARCHAR;
610 : #endif
611 : /* TODO what happen if varchar is more than 255 characters long */
612 : case SQL_C_CHAR:
613 : return SYBVARCHAR;
614 : case SQL_C_FLOAT:
615 : return SYBREAL;
616 : case SQL_C_DOUBLE:
617 : return SYBFLT8;
618 : case SQL_C_BIT:
619 : return SYBBIT;
620 : #if (ODBCVER >= 0x0300)
621 : case SQL_C_UBIGINT:
622 : return SYBUINT8;
623 : case SQL_C_SBIGINT:
624 : return SYBINT8;
625 : #ifdef SQL_C_GUID
626 : case SQL_C_GUID:
627 : return SYBUNIQUE;
628 : #endif
629 : #endif
630 : case SQL_C_ULONG:
631 : return SYBUINT4;
632 : case SQL_C_LONG:
633 : case SQL_C_SLONG:
634 : return SYBINT4;
635 : case SQL_C_USHORT:
636 : return SYBUINT2;
637 : case SQL_C_SHORT:
638 : case SQL_C_SSHORT:
639 : return SYBINT2;
640 : case SQL_C_STINYINT:
641 : case SQL_C_TINYINT:
642 : case SQL_C_UTINYINT:
643 : return SYBINT1;
644 : /* ODBC date formats are completely different from SQL one */
645 : case SQL_C_DATE:
646 : case SQL_C_TIME:
647 : case SQL_C_TIMESTAMP:
648 : case SQL_C_TYPE_DATE:
649 : case SQL_C_TYPE_TIME:
650 : case SQL_C_TYPE_TIMESTAMP:
651 : return SYBMSDATETIME2;
652 : /* ODBC numeric/decimal formats are completely differect from tds one */
653 : case SQL_C_NUMERIC:
654 : return SYBNUMERIC;
655 : /* not supported */
656 : case SQL_C_INTERVAL_YEAR:
657 : case SQL_C_INTERVAL_MONTH:
658 : case SQL_C_INTERVAL_DAY:
659 : case SQL_C_INTERVAL_HOUR:
660 : case SQL_C_INTERVAL_MINUTE:
661 : case SQL_C_INTERVAL_SECOND:
662 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
663 : case SQL_C_INTERVAL_DAY_TO_HOUR:
664 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
665 : case SQL_C_INTERVAL_DAY_TO_SECOND:
666 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
667 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
668 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
669 : break;
670 : }
671 : return TDS_INVALID_TYPE;
672 : }
673 :
674 : int
675 8 : odbc_sql_to_c_type_default(int sql_type)
676 : {
677 :
678 8 : switch (sql_type) {
679 :
680 : case SQL_CHAR:
681 : case SQL_VARCHAR:
682 : case SQL_LONGVARCHAR:
683 : /* these types map to SQL_C_CHAR for compatibility with old applications */
684 : #ifdef SQL_C_WCHAR
685 : case SQL_WCHAR:
686 : case SQL_WVARCHAR:
687 : case SQL_WLONGVARCHAR:
688 : #endif
689 : return SQL_C_CHAR;
690 : /* for compatibility numeric are converted to CHAR, not to structure */
691 : case SQL_DECIMAL:
692 : case SQL_NUMERIC:
693 : return SQL_C_CHAR;
694 : #ifdef SQL_GUID
695 0 : case SQL_GUID:
696 : /* TODO return SQL_C_CHAR for Sybase ?? */
697 0 : return SQL_C_GUID;
698 : #endif
699 0 : case SQL_BIT:
700 0 : return SQL_C_BIT;
701 0 : case SQL_TINYINT:
702 0 : return SQL_C_UTINYINT;
703 0 : case SQL_SMALLINT:
704 0 : return SQL_C_SSHORT;
705 0 : case SQL_INTEGER:
706 0 : return SQL_C_SLONG;
707 0 : case SQL_BIGINT:
708 0 : return SQL_C_SBIGINT;
709 0 : case SQL_REAL:
710 0 : return SQL_C_FLOAT;
711 0 : case SQL_FLOAT:
712 : case SQL_DOUBLE:
713 0 : return SQL_C_DOUBLE;
714 0 : case SQL_DATE:
715 : case SQL_TYPE_DATE:
716 0 : return SQL_C_TYPE_DATE;
717 0 : case SQL_TIME:
718 : case SQL_TYPE_TIME:
719 0 : return SQL_C_TYPE_TIME;
720 0 : case SQL_TIMESTAMP:
721 : case SQL_TYPE_TIMESTAMP:
722 0 : return SQL_C_TYPE_TIMESTAMP;
723 0 : case SQL_BINARY:
724 : case SQL_VARBINARY:
725 : case SQL_LONGVARBINARY:
726 0 : return SQL_C_BINARY;
727 0 : case SQL_SS_TABLE:
728 0 : return SQL_C_BINARY;
729 : /* TODO interval types */
730 0 : default:
731 0 : return 0;
732 : }
733 : }
734 :
735 : TDS_SERVER_TYPE
736 19080 : odbc_sql_to_server_type(TDSCONNECTION * conn, int sql_type, int sql_unsigned)
737 : {
738 :
739 19080 : switch (sql_type) {
740 1080 : case SQL_WCHAR:
741 1080 : if (IS_TDS7_PLUS(conn))
742 : return XSYBNCHAR;
743 : /* fall thought */
744 : case SQL_CHAR:
745 1136 : return SYBCHAR;
746 372 : case SQL_WVARCHAR:
747 372 : if (IS_TDS7_PLUS(conn))
748 : return XSYBNVARCHAR;
749 : /* fall thought */
750 : case SQL_VARCHAR:
751 1930 : return SYBVARCHAR;
752 0 : case SQL_SS_VARIANT:
753 0 : if (IS_TDS71_PLUS(conn))
754 : return SYBVARIANT;
755 0 : if (IS_TDS7_PLUS(conn))
756 : return XSYBNVARCHAR;
757 0 : return SYBVARCHAR;
758 0 : case SQL_SS_XML:
759 0 : if (IS_TDS72_PLUS(conn))
760 : return SYBMSXML;
761 : /* fall thought */
762 : case SQL_WLONGVARCHAR:
763 348 : if (IS_TDS7_PLUS(conn))
764 : return SYBNTEXT;
765 : /* fall thought */
766 : case SQL_LONGVARCHAR:
767 518 : return SYBTEXT;
768 : case SQL_DECIMAL:
769 : return SYBDECIMAL;
770 722 : case SQL_NUMERIC:
771 722 : return SYBNUMERIC;
772 : #ifdef SQL_GUID
773 34 : case SQL_GUID:
774 34 : if (IS_TDS7_PLUS(conn))
775 : return SYBUNIQUE;
776 0 : return TDS_INVALID_TYPE;
777 : #endif
778 704 : case SQL_BIT:
779 : /* NOTE: always return not nullable type */
780 704 : return SYBBIT;
781 418 : case SQL_TINYINT:
782 418 : return SYBINT1;
783 536 : case SQL_SMALLINT:
784 536 : if (sql_unsigned && tds_capability_has_req(conn, TDS_REQ_DATA_UINT2))
785 : return SYBUINT2;
786 : return SYBINT2;
787 2314 : case SQL_INTEGER:
788 2314 : if (sql_unsigned && tds_capability_has_req(conn, TDS_REQ_DATA_UINT4))
789 : return SYBUINT4;
790 : return SYBINT4;
791 84 : case SQL_BIGINT:
792 84 : if (sql_unsigned && tds_capability_has_req(conn, TDS_REQ_DATA_UINT8))
793 : return SYBUINT8;
794 : return SYBINT8;
795 874 : case SQL_REAL:
796 874 : return SYBREAL;
797 916 : case SQL_FLOAT:
798 : case SQL_DOUBLE:
799 916 : return SYBFLT8;
800 : /* ODBC version 2 */
801 1132 : case SQL_DATE:
802 : case SQL_TIME:
803 : case SQL_TIMESTAMP:
804 : /* ODBC version 3 */
805 : case SQL_TYPE_DATE:
806 1324 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
807 : return SYB5BIGDATETIME;
808 1324 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_DATE))
809 : return SYBDATE;
810 1132 : if (IS_TDS73_PLUS(conn))
811 : return SYBMSDATE;
812 : goto type_timestamp;
813 292 : case SQL_TYPE_TIME:
814 340 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGTIME))
815 : return SYB5BIGTIME;
816 340 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_TIME))
817 : return SYBTIME;
818 292 : if (IS_TDS73_PLUS(conn))
819 : return SYBMSTIME;
820 : /* fall thought */
821 48 : type_timestamp:
822 : case SQL_TYPE_TIMESTAMP:
823 1054 : if (IS_TDS73_PLUS(conn))
824 : return SYBMSDATETIME2;
825 1044 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
826 : return SYB5BIGDATETIME;
827 : return SYBDATETIME;
828 0 : case SQL_SS_TIME2:
829 0 : if (IS_TDS73_PLUS(conn))
830 : return SYBMSTIME;
831 0 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
832 : return SYB5BIGDATETIME;
833 : return SYBDATETIME;
834 0 : case SQL_SS_TIMESTAMPOFFSET:
835 0 : if (IS_TDS73_PLUS(conn))
836 : return SYBMSDATETIMEOFFSET;
837 0 : if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
838 : return SYB5BIGDATETIME;
839 : return SYBDATETIME;
840 980 : case SQL_BINARY:
841 980 : return SYBBINARY;
842 164 : case SQL_VARBINARY:
843 164 : return SYBVARBINARY;
844 138 : case SQL_LONGVARBINARY:
845 138 : return SYBIMAGE;
846 4 : case SQL_SS_TABLE:
847 4 : return SYBMSTABLE;
848 : /* TODO interval types */
849 3712 : default:
850 3712 : return TDS_INVALID_TYPE;
851 : }
852 : }
853 :
854 : /** Returns the version of the RDBMS in the ODBC format */
855 : void
856 62 : odbc_rdbms_version(TDSSOCKET * tds, char *pversion_string)
857 : {
858 62 : TDS_UINT version = tds->conn->product_version;
859 124 : sprintf(pversion_string, "%.02d.%.02d.%.04d", (int) ((version & 0x7F000000) >> 24),
860 124 : (int) ((version & 0x00FF0000) >> 16), (int) (version & 0x0000FFFF));
861 62 : }
862 :
863 : /** Return length of parameter from parameter information */
864 : SQLINTEGER
865 9654 : odbc_get_param_len(const struct _drecord *drec_axd, const struct _drecord *drec_ixd, const TDS_DESC* axd, unsigned int n_row)
866 : {
867 : SQLINTEGER len;
868 : int size;
869 : TDS_INTPTR len_offset;
870 :
871 9654 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
872 0 : len_offset = axd->header.sql_desc_bind_type * n_row;
873 0 : if (axd->header.sql_desc_bind_offset_ptr)
874 0 : len_offset += *axd->header.sql_desc_bind_offset_ptr;
875 : } else {
876 9654 : len_offset = sizeof(SQLLEN) * n_row;
877 : }
878 : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
879 :
880 9654 : if (drec_axd->sql_desc_indicator_ptr && LEN(drec_axd->sql_desc_indicator_ptr) == SQL_NULL_DATA)
881 : len = SQL_NULL_DATA;
882 9268 : else if (drec_axd->sql_desc_octet_length_ptr)
883 5728 : len = LEN(drec_axd->sql_desc_octet_length_ptr);
884 : else {
885 3540 : len = 0;
886 : /* TODO add XML if defined */
887 : /* FIXME, other types available */
888 3540 : if (drec_axd->sql_desc_concise_type == SQL_C_CHAR || drec_axd->sql_desc_concise_type == SQL_C_WCHAR
889 3208 : || drec_axd->sql_desc_concise_type == SQL_C_BINARY) {
890 : len = SQL_NTS;
891 : } else {
892 3080 : int type = drec_axd->sql_desc_concise_type;
893 : TDS_SERVER_TYPE server_type;
894 :
895 3080 : if (type == SQL_C_DEFAULT)
896 0 : type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type);
897 3080 : server_type = odbc_c_to_server_type(type);
898 :
899 : /* FIXME check what happen to DATE/TIME types */
900 3080 : size = tds_get_size_by_type(server_type);
901 3080 : if (size > 0)
902 2088 : len = size;
903 : }
904 : }
905 9654 : return len;
906 : #undef LEN
907 : }
908 :
909 : #ifdef SQL_GUID
910 : # define TYPE_NORMAL_SQL_GUID TYPE_NORMAL(SQL_GUID)
911 : #else
912 : # define TYPE_NORMAL_SQL_GUID
913 : #endif
914 : #define SQL_TYPES \
915 : TYPE_NORMAL(SQL_BIT) \
916 : TYPE_NORMAL(SQL_SMALLINT) \
917 : TYPE_NORMAL(SQL_TINYINT) \
918 : TYPE_NORMAL(SQL_INTEGER) \
919 : TYPE_NORMAL(SQL_BIGINT) \
920 : \
921 : TYPE_NORMAL_SQL_GUID \
922 : \
923 : TYPE_NORMAL(SQL_BINARY) \
924 : TYPE_NORMAL(SQL_VARBINARY) \
925 : TYPE_NORMAL(SQL_LONGVARBINARY) \
926 : \
927 : TYPE_NORMAL(SQL_CHAR) \
928 : TYPE_NORMAL(SQL_VARCHAR) \
929 : TYPE_NORMAL(SQL_LONGVARCHAR) \
930 : TYPE_NORMAL(SQL_WCHAR) \
931 : TYPE_NORMAL(SQL_WVARCHAR) \
932 : TYPE_NORMAL(SQL_WLONGVARCHAR) \
933 : \
934 : TYPE_NORMAL(SQL_DECIMAL) \
935 : TYPE_NORMAL(SQL_NUMERIC) \
936 : \
937 : TYPE_NORMAL(SQL_FLOAT) \
938 : TYPE_NORMAL(SQL_REAL) \
939 : TYPE_NORMAL(SQL_DOUBLE)\
940 : \
941 : TYPE_NORMAL(SQL_SS_TIMESTAMPOFFSET) \
942 : TYPE_NORMAL(SQL_SS_TIME2) \
943 : TYPE_NORMAL(SQL_SS_XML) \
944 : TYPE_NORMAL(SQL_SS_VARIANT) \
945 : TYPE_NORMAL(SQL_TYPE_DATE) \
946 : TYPE_NORMAL(SQL_TYPE_TIME) \
947 : \
948 : TYPE_NORMAL(SQL_SS_TABLE) \
949 : \
950 : TYPE_VERBOSE_START(SQL_DATETIME) \
951 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_TYPE_TIMESTAMP, SQL_TIMESTAMP) \
952 : TYPE_VERBOSE_END(SQL_DATETIME)
953 :
954 : SQLSMALLINT
955 487590 : odbc_get_concise_sql_type(SQLSMALLINT type, SQLSMALLINT interval)
956 : {
957 : #define TYPE_NORMAL(t) case t: return type;
958 : #define TYPE_VERBOSE_START(t) \
959 : case t: switch (interval) {
960 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
961 : case interval: return concise;
962 : #define TYPE_VERBOSE_END(t) \
963 : } \
964 : break;
965 :
966 487590 : switch (type) {
967 19254 : SQL_TYPES;
968 : }
969 0 : return 0;
970 : #undef TYPE_NORMAL
971 : #undef TYPE_VERBOSE_START
972 : #undef TYPE_VERBOSE_DATE
973 : #undef TYPE_VERBOSE_END
974 : }
975 :
976 : /**
977 : * Set concise type and all cascading field.
978 : * @param concise_type concise type to set
979 : * @param drec record to set. NULL to test error without setting
980 : * @param check_only it <>0 (true) check only, do not set type
981 : */
982 : SQLRETURN
983 9632 : odbc_set_concise_sql_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only)
984 : {
985 9632 : SQLSMALLINT type = concise_type, interval_code = 0;
986 :
987 : #define TYPE_NORMAL(t) case t: break;
988 : #define TYPE_VERBOSE_START(t)
989 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
990 : case old: concise_type = concise; \
991 : case concise: type = t; interval_code = interval; break;
992 : #define TYPE_VERBOSE_END(t)
993 :
994 9632 : switch (type) {
995 122 : SQL_TYPES;
996 : default:
997 : return SQL_ERROR;
998 : }
999 9440 : if (!check_only) {
1000 9440 : if (drec->sql_desc_concise_type == SQL_SS_TABLE)
1001 2048 : tvp_free((SQLTVP *) drec->sql_desc_data_ptr);
1002 :
1003 9440 : drec->sql_desc_concise_type = concise_type;
1004 9440 : drec->sql_desc_type = type;
1005 9440 : drec->sql_desc_datetime_interval_code = interval_code;
1006 9440 : drec->sql_desc_data_ptr = NULL;
1007 :
1008 9440 : switch (drec->sql_desc_type) {
1009 186 : case SQL_NUMERIC:
1010 : case SQL_DECIMAL:
1011 186 : drec->sql_desc_precision = 38;
1012 186 : drec->sql_desc_scale = 0;
1013 186 : break;
1014 : /* TODO finish */
1015 : }
1016 : }
1017 : return SQL_SUCCESS;
1018 : #undef TYPE_NORMAL
1019 : #undef TYPE_VERBOSE_START
1020 : #undef TYPE_VERBOSE_DATE
1021 : #undef TYPE_VERBOSE_END
1022 : }
1023 :
1024 : #ifdef SQL_C_GUID
1025 : # define TYPE_NORMAL_SQL_C_GUID TYPE_NORMAL(SQL_C_GUID)
1026 : #else
1027 : # define TYPE_NORMAL_SQL_C_GUID
1028 : #endif
1029 : #define C_TYPES \
1030 : TYPE_NORMAL(SQL_C_BIT) \
1031 : TYPE_NORMAL(SQL_C_SHORT) \
1032 : TYPE_NORMAL(SQL_C_TINYINT) \
1033 : TYPE_NORMAL(SQL_C_UTINYINT) \
1034 : TYPE_NORMAL(SQL_C_STINYINT) \
1035 : TYPE_NORMAL(SQL_C_LONG) \
1036 : TYPE_NORMAL(SQL_C_SBIGINT) \
1037 : TYPE_NORMAL(SQL_C_UBIGINT) \
1038 : TYPE_NORMAL(SQL_C_SSHORT) \
1039 : TYPE_NORMAL(SQL_C_SLONG) \
1040 : TYPE_NORMAL(SQL_C_USHORT) \
1041 : TYPE_NORMAL(SQL_C_ULONG) \
1042 : \
1043 : TYPE_NORMAL_SQL_C_GUID \
1044 : TYPE_NORMAL(SQL_C_DEFAULT) \
1045 : \
1046 : TYPE_NORMAL(SQL_C_BINARY) \
1047 : \
1048 : TYPE_NORMAL(SQL_C_CHAR) \
1049 : TYPE_NORMAL(SQL_C_WCHAR) \
1050 : \
1051 : TYPE_NORMAL(SQL_C_NUMERIC) \
1052 : \
1053 : TYPE_NORMAL(SQL_C_FLOAT) \
1054 : TYPE_NORMAL(SQL_C_DOUBLE)\
1055 : \
1056 : TYPE_VERBOSE_START(SQL_DATETIME) \
1057 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_DATE, SQL_C_TYPE_DATE, SQL_C_DATE) \
1058 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIME, SQL_C_TYPE_TIME, SQL_C_TIME) \
1059 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_C_TYPE_TIMESTAMP, SQL_C_TIMESTAMP) \
1060 : TYPE_VERBOSE_END(SQL_DATETIME) \
1061 : \
1062 : TYPE_VERBOSE_START(SQL_INTERVAL) \
1063 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY, SQL_C_INTERVAL_DAY) \
1064 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_HOUR, SQL_C_INTERVAL_DAY_TO_HOUR) \
1065 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_MINUTE, SQL_C_INTERVAL_DAY_TO_MINUTE) \
1066 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_SECOND, SQL_C_INTERVAL_DAY_TO_SECOND) \
1067 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR, SQL_C_INTERVAL_HOUR) \
1068 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_MINUTE, SQL_C_INTERVAL_HOUR_TO_MINUTE) \
1069 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_SECOND, SQL_C_INTERVAL_HOUR_TO_SECOND) \
1070 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE, SQL_C_INTERVAL_MINUTE) \
1071 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE_TO_SECOND, SQL_C_INTERVAL_MINUTE_TO_SECOND) \
1072 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MONTH, SQL_C_INTERVAL_MONTH) \
1073 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_SECOND, SQL_C_INTERVAL_SECOND) \
1074 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR, SQL_C_INTERVAL_YEAR) \
1075 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR_TO_MONTH, SQL_C_INTERVAL_YEAR_TO_MONTH) \
1076 : TYPE_VERBOSE_END(SQL_INTERVAL)
1077 :
1078 : SQLSMALLINT
1079 206212 : odbc_get_concise_c_type(SQLSMALLINT type, SQLSMALLINT interval)
1080 : {
1081 : #define TYPE_NORMAL(t) case t: return type;
1082 : #define TYPE_VERBOSE_START(t) \
1083 : case t: switch (interval) {
1084 : #define TYPE_VERBOSE(t, interval, concise) \
1085 : case interval: return concise;
1086 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
1087 : case interval: return concise;
1088 : #define TYPE_VERBOSE_END(t) \
1089 : } \
1090 : break;
1091 :
1092 206212 : switch (type) {
1093 7220 : C_TYPES;
1094 : }
1095 0 : return 0;
1096 : #undef TYPE_NORMAL
1097 : #undef TYPE_VERBOSE_START
1098 : #undef TYPE_VERBOSE
1099 : #undef TYPE_VERBOSE_DATE
1100 : #undef TYPE_VERBOSE_END
1101 : }
1102 :
1103 : /**
1104 : * Set concise type and all cascading field.
1105 : * @param concise_type concise type to set
1106 : * @param drec record to set. NULL to test error without setting
1107 : * @param check_only it <>0 (true) check only, do not set type
1108 : */
1109 : SQLRETURN
1110 14092 : odbc_set_concise_c_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only)
1111 : {
1112 14092 : SQLSMALLINT type = concise_type, interval_code = 0;
1113 :
1114 : #define TYPE_NORMAL(t) case t: break;
1115 : #define TYPE_VERBOSE_START(t)
1116 : #define TYPE_VERBOSE(t, interval, concise) \
1117 : case concise: type = t; interval_code = interval; break;
1118 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
1119 : case concise: type = t; interval_code = interval; break; \
1120 : case old: concise_type = concise; type = t; interval_code = interval; break;
1121 : #define TYPE_VERBOSE_END(t)
1122 :
1123 14092 : switch (type) {
1124 116 : C_TYPES;
1125 : default:
1126 : return SQL_ERROR;
1127 : }
1128 13980 : if (!check_only) {
1129 13980 : drec->sql_desc_concise_type = concise_type;
1130 13980 : drec->sql_desc_type = type;
1131 13980 : drec->sql_desc_datetime_interval_code = interval_code;
1132 13980 : drec->sql_desc_data_ptr = NULL;
1133 :
1134 13980 : switch (drec->sql_desc_type) {
1135 470 : case SQL_C_NUMERIC:
1136 470 : drec->sql_desc_length = 38;
1137 470 : drec->sql_desc_precision = 38;
1138 470 : drec->sql_desc_scale = 0;
1139 470 : break;
1140 : /* TODO finish */
1141 : }
1142 : }
1143 : return SQL_SUCCESS;
1144 : #undef TYPE_NORMAL
1145 : #undef TYPE_VERBOSE_START
1146 : #undef TYPE_VERBOSE
1147 : #undef TYPE_VERBOSE_DATE
1148 : #undef TYPE_VERBOSE_END
1149 : }
1150 :
1151 : SQLLEN
1152 2928 : odbc_get_octet_len(int c_type, const struct _drecord *drec)
1153 : {
1154 : SQLLEN len;
1155 :
1156 : /* this shit is mine -- freddy77 */
1157 2928 : switch (c_type) {
1158 1564 : case SQL_C_CHAR:
1159 : case SQL_C_WCHAR:
1160 : case SQL_C_BINARY:
1161 1564 : len = drec->sql_desc_octet_length;
1162 1564 : break;
1163 : case SQL_C_DATE:
1164 : case SQL_C_TYPE_DATE:
1165 : len = sizeof(DATE_STRUCT);
1166 : break;
1167 : case SQL_C_TIME:
1168 : case SQL_C_TYPE_TIME:
1169 : len = sizeof(TIME_STRUCT);
1170 : break;
1171 0 : case SQL_C_TIMESTAMP:
1172 : case SQL_C_TYPE_TIMESTAMP:
1173 0 : len = sizeof(TIMESTAMP_STRUCT);
1174 0 : break;
1175 134 : case SQL_C_NUMERIC:
1176 134 : len = sizeof(SQL_NUMERIC_STRUCT);
1177 134 : break;
1178 1230 : default:
1179 1230 : len = tds_get_size_by_type(odbc_c_to_server_type(c_type));
1180 1230 : break;
1181 : }
1182 2928 : return len;
1183 : }
1184 :
1185 : void
1186 12096 : odbc_convert_err_set(struct _sql_errors *errs, TDS_INT err)
1187 : {
1188 : /*
1189 : * TODO we really need a column offset in the _sql_error structure so that caller can
1190 : * invoke SQLGetDiagField to learn which column is failing
1191 : */
1192 12096 : switch (err) {
1193 9888 : case TDS_CONVERT_NOAVAIL:
1194 9888 : odbc_errs_add(errs, "HY003", NULL);
1195 9888 : break;
1196 664 : case TDS_CONVERT_SYNTAX:
1197 664 : odbc_errs_add(errs, "22018", NULL);
1198 664 : break;
1199 1544 : case TDS_CONVERT_OVERFLOW:
1200 1544 : odbc_errs_add(errs, "22003", NULL);
1201 1544 : break;
1202 0 : case TDS_CONVERT_FAIL:
1203 0 : odbc_errs_add(errs, "07006", NULL);
1204 0 : break;
1205 0 : case TDS_CONVERT_NOMEM:
1206 0 : odbc_errs_add(errs, "HY001", NULL);
1207 0 : break;
1208 : }
1209 12096 : }
1210 :
1211 : /** @} */
|