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