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