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