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, 2006 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 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif /* HAVE_CONFIG_H */
24 :
25 : #if HAVE_STDLIB_H
26 : #include <stdlib.h>
27 : #endif /* HAVE_STDLIB_H */
28 :
29 : #if HAVE_STRING_H
30 : #include <string.h>
31 : #endif /* HAVE_STRING_H */
32 :
33 : #include <assert.h>
34 :
35 : #include "tdsodbc.h"
36 :
37 : #ifdef DMALLOC
38 : #include <dmalloc.h>
39 : #endif
40 :
41 : TDS_RCSID(var, "$Id: odbc_util.c,v 1.85.2.1 2007/12/21 11:19:02 freddy77 Exp $");
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 : static int
55 : odbc_set_stmt(TDS_STMT * stmt, char **dest, const char *sql, int sql_len)
56 800 : {
57 : char *p;
58 :
59 800 : assert(dest == &stmt->prepared_query || dest == &stmt->query);
60 :
61 800 : if (sql_len == SQL_NTS)
62 724 : sql_len = strlen(sql);
63 76 : else if (sql_len <= 0)
64 0 : return SQL_ERROR;
65 :
66 : /* TODO already NULL ?? */
67 800 : tds_free_param_results(stmt->params);
68 800 : stmt->params = NULL;
69 800 : stmt->param_num = 0;
70 800 : stmt->param_count = 0;
71 800 : stmt->prepared_query_is_func = 0;
72 800 : stmt->prepared_query_is_rpc = 0;
73 800 : stmt->prepared_pos = NULL;
74 800 : stmt->curr_param_row = 0;
75 :
76 800 : if (stmt->prepared_query)
77 71 : TDS_ZERO_FREE(stmt->prepared_query);
78 :
79 800 : if (stmt->query)
80 608 : TDS_ZERO_FREE(stmt->query);
81 :
82 800 : *dest = p = (char *) malloc(sql_len + 1);
83 800 : if (!p)
84 0 : return SQL_ERROR;
85 :
86 800 : if (sql) {
87 800 : memcpy(p, sql, sql_len);
88 800 : p[sql_len] = 0;
89 : } else {
90 0 : p[0] = 0;
91 : }
92 :
93 800 : return SQL_SUCCESS;
94 : }
95 :
96 : int
97 : odbc_set_stmt_query(TDS_STMT * stmt, const char *sql, int sql_len)
98 703 : {
99 703 : return odbc_set_stmt(stmt, &stmt->query, sql, sql_len);
100 : }
101 :
102 :
103 : int
104 : odbc_set_stmt_prepared_query(TDS_STMT * stmt, const char *sql, int sql_len)
105 97 : {
106 97 : return odbc_set_stmt(stmt, &stmt->prepared_query, sql, sql_len);
107 : }
108 :
109 :
110 : void
111 : odbc_set_return_status(struct _hstmt *stmt, unsigned int n_row)
112 98 : {
113 98 : TDSSOCKET *tds = stmt->dbc->tds_socket;
114 98 : TDSCONTEXT *context = stmt->dbc->env->tds_ctx;
115 :
116 : /* TODO handle different type results (functions) on mssql2k */
117 98 : if (stmt->prepared_query_is_func && tds->has_status) {
118 : struct _drecord *drec;
119 : int len;
120 16 : const TDS_DESC* axd = stmt->apd;
121 : TDS_INTPTR len_offset;
122 : char *data_ptr;
123 :
124 16 : if (axd->header.sql_desc_count < 1)
125 0 : return;
126 16 : drec = &axd->records[0];
127 16 : data_ptr = drec->sql_desc_data_ptr;
128 :
129 16 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
130 0 : len_offset = axd->header.sql_desc_bind_type * n_row;
131 0 : if (axd->header.sql_desc_bind_offset_ptr)
132 0 : len_offset += *axd->header.sql_desc_bind_offset_ptr;
133 0 : data_ptr += len_offset;
134 : } else {
135 16 : len_offset = sizeof(SQLLEN) * n_row;
136 16 : data_ptr += sizeof(SQLINTEGER) * n_row;
137 : }
138 : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
139 :
140 16 : len = convert_tds2sql(context, SYBINT4, (TDS_CHAR *) & tds->ret_status, sizeof(TDS_INT),
141 : drec->sql_desc_concise_type, (void *) data_ptr, drec->sql_desc_octet_length, NULL);
142 16 : if (TDS_FAIL == len)
143 0 : return /* SQL_ERROR */ ;
144 16 : if (drec->sql_desc_indicator_ptr)
145 16 : LEN(drec->sql_desc_indicator_ptr) = 0;
146 16 : if (drec->sql_desc_octet_length_ptr)
147 16 : LEN(drec->sql_desc_octet_length_ptr) = len;
148 : }
149 : #undef LEN
150 : }
151 :
152 : void
153 : odbc_set_return_params(struct _hstmt *stmt, unsigned int n_row)
154 24 : {
155 24 : TDSSOCKET *tds = stmt->dbc->tds_socket;
156 24 : TDSPARAMINFO *info = tds->current_results;
157 24 : TDSCONTEXT *context = stmt->dbc->env->tds_ctx;
158 :
159 24 : int i_begin = stmt->prepared_query_is_func ? 1 : 0;
160 : int i;
161 24 : int nparam = i_begin;
162 :
163 : /* I don't understand why but this happen -- freddy77 */
164 : /* TODO check why, put an assert ? */
165 24 : if (!info)
166 0 : return;
167 :
168 56 : for (i = 0; i < info->num_cols; ++i) {
169 32 : const TDS_DESC* axd = stmt->apd;
170 : const struct _drecord *drec_apd, *drec_ipd;
171 32 : TDSCOLUMN *colinfo = info->columns[i];
172 : TDS_CHAR *src;
173 : int srclen;
174 : SQLINTEGER len;
175 : int c_type;
176 : char *data_ptr;
177 : TDS_INTPTR len_offset;
178 :
179 : /* find next output parameter */
180 : for (;;) {
181 44 : drec_apd = NULL;
182 : /* TODO best way to stop */
183 44 : if (nparam >= axd->header.sql_desc_count || nparam >= stmt->ipd->header.sql_desc_count)
184 0 : return;
185 44 : drec_apd = &axd->records[nparam];
186 44 : drec_ipd = &stmt->ipd->records[nparam];
187 44 : if (stmt->ipd->records[nparam++].sql_desc_parameter_type != SQL_PARAM_INPUT)
188 32 : break;
189 12 : }
190 :
191 32 : data_ptr = drec_apd->sql_desc_data_ptr;
192 32 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
193 0 : len_offset = axd->header.sql_desc_bind_type * n_row;
194 0 : if (axd->header.sql_desc_bind_offset_ptr)
195 0 : len_offset += *axd->header.sql_desc_bind_offset_ptr;
196 0 : data_ptr += len_offset;
197 : } else {
198 32 : len_offset = sizeof(SQLLEN) * n_row;
199 32 : data_ptr += odbc_get_octet_len(drec_apd->sql_desc_concise_type, drec_apd) * n_row;
200 : }
201 : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
202 :
203 : /* null parameter ? */
204 32 : if (colinfo->column_cur_size < 0) {
205 : /* FIXME error if NULL */
206 0 : if (drec_apd->sql_desc_indicator_ptr)
207 0 : LEN(drec_apd->sql_desc_indicator_ptr) = SQL_NULL_DATA;
208 0 : continue;
209 : }
210 :
211 32 : src = (TDS_CHAR *) & info->current_row[colinfo->column_offset];
212 32 : if (is_blob_type(colinfo->column_type))
213 0 : src = ((TDSBLOB *) src)->textvalue;
214 32 : srclen = colinfo->column_cur_size;
215 32 : c_type = drec_apd->sql_desc_concise_type;
216 32 : if (c_type == SQL_C_DEFAULT)
217 0 : c_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
218 : /*
219 : * TODO why IPD ?? perhaps SQLBindParameter it's not correct ??
220 : * Or tests are wrong ??
221 : */
222 32 : len = convert_tds2sql(context, tds_get_conversion_type(colinfo->column_type, colinfo->column_size), src, srclen,
223 : c_type, (void *) data_ptr, drec_apd->sql_desc_octet_length, drec_ipd);
224 : /* TODO error handling */
225 32 : if (len < 0)
226 0 : return /* SQL_ERROR */ ;
227 32 : if (drec_apd->sql_desc_indicator_ptr)
228 32 : LEN(drec_apd->sql_desc_indicator_ptr) = 0;
229 32 : if (drec_apd->sql_desc_octet_length_ptr)
230 32 : LEN(drec_apd->sql_desc_octet_length_ptr) = len;
231 : #undef LEN
232 : }
233 : }
234 :
235 : int
236 : odbc_get_string_size(int size, SQLCHAR * str)
237 357 : {
238 357 : if (str) {
239 337 : if (size == SQL_NTS)
240 266 : return strlen((const char *) str);
241 71 : if (size >= 0)
242 71 : return size;
243 : }
244 : /* SQL_NULL_DATA or any other strange value */
245 20 : return 0;
246 : }
247 :
248 : /**
249 : * Convert type from database to ODBC
250 : */
251 : SQLSMALLINT
252 : odbc_server_to_sql_type(int col_type, int col_size)
253 1386 : {
254 : /* FIXME finish */
255 1386 : switch ((TDS_SERVER_TYPE) col_type) {
256 : case XSYBCHAR:
257 : case SYBCHAR:
258 15 : return SQL_CHAR;
259 : case XSYBVARCHAR:
260 : case SYBVARCHAR:
261 420 : return SQL_VARCHAR;
262 : case SYBTEXT:
263 14 : return SQL_LONGVARCHAR;
264 : case SYBBIT:
265 : case SYBBITN:
266 20 : return SQL_BIT;
267 : #if (ODBCVER >= 0x0300)
268 : case SYBINT8:
269 : /* TODO return numeric for odbc2 and convert bigint to numeric */
270 0 : return SQL_BIGINT;
271 : #endif
272 : case SYBINT4:
273 136 : return SQL_INTEGER;
274 : case SYBINT2:
275 142 : return SQL_SMALLINT;
276 : case SYBINT1:
277 4 : return SQL_TINYINT;
278 : case SYBINTN:
279 502 : switch (col_size) {
280 : case 1:
281 9 : return SQL_TINYINT;
282 : case 2:
283 352 : return SQL_SMALLINT;
284 : case 4:
285 141 : return SQL_INTEGER;
286 : #if (ODBCVER >= 0x0300)
287 : case 8:
288 0 : return SQL_BIGINT;
289 : #endif
290 : }
291 0 : break;
292 : case SYBREAL:
293 5 : return SQL_REAL;
294 : case SYBFLT8:
295 23 : return SQL_DOUBLE;
296 : case SYBFLTN:
297 18 : switch (col_size) {
298 : case 4:
299 5 : return SQL_REAL;
300 : case 8:
301 13 : return SQL_DOUBLE;
302 : }
303 0 : break;
304 : case SYBMONEY:
305 1 : return SQL_DOUBLE;
306 : case SYBMONEY4:
307 1 : return SQL_DOUBLE;
308 : case SYBMONEYN:
309 8 : return SQL_DOUBLE;
310 : case SYBDATETIME:
311 : case SYBDATETIME4:
312 : case SYBDATETIMN:
313 : #if (ODBCVER >= 0x0300)
314 38 : return SQL_TYPE_TIMESTAMP;
315 : #else
316 : return SQL_TIMESTAMP;
317 : #endif
318 : case XSYBBINARY:
319 : case SYBBINARY:
320 3 : return SQL_BINARY;
321 : case SYBLONGBINARY:
322 : case SYBIMAGE:
323 4 : return SQL_LONGVARBINARY;
324 : case XSYBVARBINARY:
325 : case SYBVARBINARY:
326 3 : return SQL_VARBINARY;
327 : case SYBNUMERIC:
328 : case SYBDECIMAL:
329 25 : return SQL_NUMERIC;
330 : /* TODO this is ODBC 3.5 */
331 : case SYBNTEXT:
332 : case SYBNVARCHAR:
333 : case XSYBNVARCHAR:
334 : case XSYBNCHAR:
335 0 : break;
336 : #if (ODBCVER >= 0x0300)
337 : case SYBUNIQUE:
338 : #ifdef SQL_GUID
339 4 : return SQL_GUID;
340 : #else
341 : return SQL_CHAR;
342 : #endif
343 : case SYBVARIANT:
344 : break;
345 : #endif
346 : /* TODO what should I do with these types ?? */
347 : case SYBVOID:
348 : case SYBSINT1:
349 : case SYBUINT2:
350 : case SYBUINT4:
351 : case SYBUINT8:
352 : break;
353 : }
354 0 : return SQL_UNKNOWN_TYPE;
355 : }
356 :
357 : /**
358 : * Pass this an SQL_C_* type and get a SYB* type which most closely corresponds
359 : * to the SQL_C_* type.
360 : */
361 : int
362 : odbc_c_to_server_type(int c_type)
363 1809 : {
364 1809 : switch (c_type) {
365 : /* FIXME this should be dependent on size of data !!! */
366 : case SQL_C_BINARY:
367 59 : return SYBBINARY;
368 : /* TODO what happen if varchar is more than 255 characters long */
369 : case SQL_C_CHAR:
370 924 : return SYBVARCHAR;
371 : case SQL_C_FLOAT:
372 16 : return SYBREAL;
373 : case SQL_C_DOUBLE:
374 16 : return SYBFLT8;
375 : case SQL_C_BIT:
376 8 : return SYBBIT;
377 : #if (ODBCVER >= 0x0300)
378 : case SQL_C_SBIGINT:
379 : case SQL_C_UBIGINT:
380 0 : return SYBINT8;
381 : #ifdef SQL_C_GUID
382 : case SQL_C_GUID:
383 6 : return SYBUNIQUE;
384 : #endif
385 : #endif
386 : case SQL_C_LONG:
387 : case SQL_C_SLONG:
388 : case SQL_C_ULONG:
389 486 : return SYBINT4;
390 : case SQL_C_SHORT:
391 : case SQL_C_SSHORT:
392 : case SQL_C_USHORT:
393 258 : return SYBINT2;
394 : case SQL_C_TINYINT:
395 : case SQL_C_STINYINT:
396 : case SQL_C_UTINYINT:
397 4 : return SYBINT1;
398 : /* ODBC date formats are completely differect from SQL one */
399 : case SQL_C_DATE:
400 : case SQL_C_TIME:
401 : case SQL_C_TIMESTAMP:
402 : case SQL_C_TYPE_DATE:
403 : case SQL_C_TYPE_TIME:
404 : case SQL_C_TYPE_TIMESTAMP:
405 14 : return SYBDATETIME;
406 : /* ODBC numeric/decimal formats are completely differect from tds one */
407 : case SQL_C_NUMERIC:
408 18 : return SYBNUMERIC;
409 : /* not supported */
410 : case SQL_C_INTERVAL_YEAR:
411 : case SQL_C_INTERVAL_MONTH:
412 : case SQL_C_INTERVAL_DAY:
413 : case SQL_C_INTERVAL_HOUR:
414 : case SQL_C_INTERVAL_MINUTE:
415 : case SQL_C_INTERVAL_SECOND:
416 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
417 : case SQL_C_INTERVAL_DAY_TO_HOUR:
418 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
419 : case SQL_C_INTERVAL_DAY_TO_SECOND:
420 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
421 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
422 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
423 : #ifdef SQL_C_WCHAR
424 : case SQL_C_WCHAR:
425 : #endif
426 : break;
427 : }
428 0 : return TDS_FAIL;
429 : }
430 :
431 : void
432 : odbc_set_sql_type_info(TDSCOLUMN * col, struct _drecord *drec)
433 1386 : {
434 : #define SET_INFO(type, prefix, suffix) \
435 : drec->sql_desc_literal_prefix = prefix; \
436 : drec->sql_desc_literal_suffix = suffix; \
437 : drec->sql_desc_type_name = type; \
438 : return;
439 :
440 : /* FIXME finish, support for N type (nvarchar) */
441 1386 : switch (tds_get_conversion_type(col->column_type, col->column_size)) {
442 : case XSYBCHAR:
443 : case SYBCHAR:
444 15 : SET_INFO("char", "'", "'");
445 : case XSYBVARCHAR:
446 : case SYBVARCHAR:
447 420 : SET_INFO("varchar", "'", "'");
448 : case SYBTEXT:
449 14 : SET_INFO("text", "'", "'");
450 : case SYBBIT:
451 : case SYBBITN:
452 20 : SET_INFO("bit", "", "");
453 : #if (ODBCVER >= 0x0300)
454 : case SYBINT8:
455 : /* TODO return numeric for odbc2 and convert bigint to numeric */
456 0 : SET_INFO("bigint", "", "");
457 : #endif
458 : case SYBINT4:
459 277 : SET_INFO("int", "", "");
460 : case SYBINT2:
461 494 : SET_INFO("smallint", "", "");
462 : case SYBINT1:
463 13 : SET_INFO("tinyint", "", "");
464 : case SYBREAL:
465 10 : SET_INFO("real", "", "");
466 : case SYBFLT8:
467 36 : SET_INFO("float", "", "");
468 : case SYBMONEY:
469 : case SYBMONEY4:
470 10 : SET_INFO("money", "$", "");
471 : case SYBDATETIME:
472 : case SYBDATETIME4:
473 38 : SET_INFO("datetime", "'", "'");
474 : case SYBBINARY:
475 : /* handle TIMESTAMP using usertype */
476 3 : if (col->column_usertype == 80)
477 1 : SET_INFO("timestamp", "0x", "");
478 : SET_INFO("binary", "0x", "");
479 : case SYBIMAGE:
480 4 : SET_INFO("image", "0x", "");
481 : case SYBVARBINARY:
482 3 : SET_INFO("varbinary", "0x", "");
483 : case SYBNUMERIC:
484 21 : SET_INFO("numeric", "", "");
485 : case SYBDECIMAL:
486 4 : SET_INFO("decimal", "", "");
487 : case SYBINTN:
488 : case SYBDATETIMN:
489 : case SYBFLTN:
490 : case SYBMONEYN:
491 0 : assert(0);
492 : case SYBVOID:
493 : case SYBNTEXT:
494 : case SYBNVARCHAR:
495 : case XSYBNVARCHAR:
496 : case XSYBNCHAR:
497 0 : break;
498 : #if (ODBCVER >= 0x0300)
499 : case SYBUNIQUE:
500 : /* FIXME for Sybase ?? */
501 4 : SET_INFO("uniqueidentifier", "'", "'");
502 : case SYBVARIANT:
503 : /* SET_INFO("sql_variant", "", ""); */
504 : break;
505 : #endif
506 : }
507 0 : SET_INFO("", "", "");
508 : #undef SET_INFO
509 : }
510 :
511 : SQLINTEGER
512 : odbc_sql_to_displaysize(int sqltype, int column_size, int column_prec)
513 1386 : {
514 1386 : SQLINTEGER size = 0;
515 :
516 1386 : switch (sqltype) {
517 : case SQL_CHAR:
518 : case SQL_VARCHAR:
519 : case SQL_LONGVARCHAR:
520 449 : size = column_size;
521 449 : break;
522 : case SQL_BIGINT:
523 0 : size = 20;
524 0 : break;
525 : case SQL_INTEGER:
526 277 : size = 11; /* -1000000000 */
527 277 : break;
528 : case SQL_SMALLINT:
529 494 : size = 6; /* -10000 */
530 494 : break;
531 : case SQL_TINYINT:
532 13 : size = 3; /* 255 */
533 13 : break;
534 : case SQL_DECIMAL:
535 : case SQL_NUMERIC:
536 25 : size = column_prec + 2;
537 25 : break;
538 : case SQL_DATE:
539 : /* FIXME check always yyyy-mm-dd ?? */
540 0 : size = 19;
541 0 : break;
542 : case SQL_TIME:
543 : /* FIXME check always hh:mm:ss[.fff] */
544 0 : size = 19;
545 0 : break;
546 : case SQL_TYPE_TIMESTAMP:
547 : case SQL_TIMESTAMP:
548 : /* TODO dependent on precision (decimal second digits) */
549 : /* FIXME check, always format yyyy-mm-dd hh:mm:ss[.fff] ?? */
550 38 : size = 24;
551 : /* spinellia@acm.org: int token.c it is 30 should we comply? */
552 38 : break;
553 : case SQL_FLOAT:
554 : case SQL_REAL:
555 : case SQL_DOUBLE:
556 56 : size = 24; /* FIXME -- what should the correct size be? */
557 56 : break;
558 : #ifdef SQL_GUID
559 : case SQL_GUID:
560 4 : size = 36;
561 4 : break;
562 : #endif
563 : default:
564 : /* FIXME TODO finish, should support ALL types (interval, binary) */
565 30 : size = 40;
566 30 : tdsdump_log(TDS_DBG_INFO1, "odbc_sql_to_displaysize: unknown sql type %d\n", (int) sqltype);
567 : break;
568 : }
569 1386 : return size;
570 : }
571 :
572 : int
573 : odbc_sql_to_c_type_default(int sql_type)
574 0 : {
575 :
576 0 : switch (sql_type) {
577 :
578 : case SQL_CHAR:
579 : case SQL_VARCHAR:
580 : case SQL_LONGVARCHAR:
581 0 : return SQL_C_CHAR;
582 : /* for compatibility numeric are converted to CHAR, not to structure */
583 : case SQL_DECIMAL:
584 : case SQL_NUMERIC:
585 0 : return SQL_C_CHAR;
586 : #ifdef SQL_GUID
587 : case SQL_GUID:
588 : /* TODO return SQL_C_CHAR for Sybase ?? */
589 0 : return SQL_C_GUID;
590 : #endif
591 : case SQL_BIT:
592 0 : return SQL_C_BIT;
593 : case SQL_TINYINT:
594 0 : return SQL_C_UTINYINT;
595 : case SQL_SMALLINT:
596 0 : return SQL_C_SSHORT;
597 : case SQL_INTEGER:
598 0 : return SQL_C_SLONG;
599 : case SQL_BIGINT:
600 0 : return SQL_C_SBIGINT;
601 : case SQL_REAL:
602 0 : return SQL_C_FLOAT;
603 : case SQL_FLOAT:
604 : case SQL_DOUBLE:
605 0 : return SQL_C_DOUBLE;
606 : case SQL_DATE:
607 : case SQL_TYPE_DATE:
608 0 : return SQL_C_TYPE_DATE;
609 : case SQL_TIME:
610 : case SQL_TYPE_TIME:
611 0 : return SQL_C_TYPE_TIME;
612 : case SQL_TIMESTAMP:
613 : case SQL_TYPE_TIMESTAMP:
614 0 : return SQL_C_TYPE_TIMESTAMP;
615 : case SQL_BINARY:
616 : case SQL_VARBINARY:
617 : case SQL_LONGVARBINARY:
618 0 : return SQL_C_BINARY;
619 : /* TODO interval types */
620 : default:
621 0 : return 0;
622 : }
623 : }
624 :
625 : int
626 : odbc_sql_to_server_type(TDSSOCKET * tds, int sql_type)
627 432 : {
628 :
629 432 : switch (sql_type) {
630 :
631 : case SQL_CHAR:
632 1 : return SYBCHAR;
633 : case SQL_VARCHAR:
634 186 : return SYBVARCHAR;
635 : case SQL_LONGVARCHAR:
636 10 : return SYBTEXT;
637 : case SQL_DECIMAL:
638 2 : return SYBDECIMAL;
639 : case SQL_NUMERIC:
640 6 : return SYBNUMERIC;
641 : #ifdef SQL_GUID
642 : case SQL_GUID:
643 3 : if (IS_TDS7_PLUS(tds))
644 3 : return SYBUNIQUE;
645 0 : return 0;
646 : #endif
647 : case SQL_BIT:
648 4 : if (IS_TDS7_PLUS(tds))
649 2 : return SYBBITN;
650 2 : return SYBBIT;
651 : case SQL_TINYINT:
652 2 : return SYBINT1;
653 : case SQL_SMALLINT:
654 0 : return SYBINT2;
655 : case SQL_INTEGER:
656 187 : return SYBINT4;
657 : case SQL_BIGINT:
658 0 : return SYBINT8;
659 : case SQL_REAL:
660 8 : return SYBREAL;
661 : case SQL_FLOAT:
662 : case SQL_DOUBLE:
663 8 : return SYBFLT8;
664 : /* ODBC version 2 */
665 : case SQL_DATE:
666 : case SQL_TIME:
667 : case SQL_TIMESTAMP:
668 : /* ODBC version 3 */
669 : case SQL_TYPE_DATE:
670 : case SQL_TYPE_TIME:
671 : case SQL_TYPE_TIMESTAMP:
672 10 : return SYBDATETIME;
673 : case SQL_BINARY:
674 0 : return SYBBINARY;
675 : case SQL_VARBINARY:
676 0 : return SYBVARBINARY;
677 : case SQL_LONGVARBINARY:
678 5 : return SYBIMAGE;
679 : /* TODO interval types */
680 : default:
681 0 : return 0;
682 : }
683 : }
684 :
685 : /**
686 : * Copy a string to client setting size according to ODBC convenction
687 : * @param buffer client buffer
688 : * @param cbBuffer client buffer size (in bytes)
689 : * @param pcbBuffer pointer to SQLSMALLINT to hold string size
690 : * @param s string to copy
691 : * @param len len of string to copy. <0 null terminated
692 : */
693 : SQLRETURN
694 : odbc_set_string(SQLPOINTER buffer, SQLSMALLINT cbBuffer, SQLSMALLINT FAR * pcbBuffer, const char *s, int len)
695 739 : {
696 739 : SQLRETURN result = SQL_SUCCESS;
697 :
698 739 : if (len < 0)
699 731 : len = strlen(s);
700 :
701 739 : if (pcbBuffer)
702 699 : *pcbBuffer = len;
703 739 : if (len >= cbBuffer) {
704 0 : len = cbBuffer - 1;
705 0 : result = SQL_SUCCESS_WITH_INFO;
706 : }
707 739 : if (buffer && len >= 0) {
708 : /* buffer can overlap, use memmove, thanks to Valgrind */
709 739 : memmove((char *) buffer, s, len);
710 739 : ((char *) buffer)[len] = 0;
711 : }
712 739 : return result;
713 : }
714 :
715 : SQLRETURN
716 : odbc_set_string_i(SQLPOINTER buffer, SQLINTEGER cbBuffer, SQLINTEGER FAR * pcbBuffer, const char *s, int len)
717 0 : {
718 0 : SQLRETURN result = SQL_SUCCESS;
719 :
720 0 : if (len < 0)
721 0 : len = strlen(s);
722 :
723 0 : if (pcbBuffer)
724 0 : *pcbBuffer = len;
725 0 : if (len >= cbBuffer) {
726 0 : len = cbBuffer - 1;
727 0 : result = SQL_SUCCESS_WITH_INFO;
728 : }
729 0 : if (buffer && len >= 0) {
730 : /* buffer can overlap, use memmove, thanks to Valgrind */
731 0 : memmove((char *) buffer, s, len);
732 0 : ((char *) buffer)[len] = 0;
733 : }
734 0 : return result;
735 : }
736 :
737 : /** Returns the version of the RDBMS in the ODBC format */
738 : void
739 : odbc_rdbms_version(TDSSOCKET * tds, char *pversion_string)
740 4 : {
741 4 : sprintf(pversion_string, "%.02d.%.02d.%.04d", (int) ((tds->product_version & 0x7F000000) >> 24),
742 : (int) ((tds->product_version & 0x00FF0000) >> 16), (int) (tds->product_version & 0x0000FFFF));
743 4 : }
744 :
745 : /** Return length of parameter from parameter information */
746 : SQLINTEGER
747 : odbc_get_param_len(const struct _drecord *drec_axd, const struct _drecord *drec_ixd, const TDS_DESC* axd, unsigned int n_row)
748 385 : {
749 : SQLINTEGER len;
750 : int size;
751 : TDS_INTPTR len_offset;
752 :
753 385 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
754 0 : len_offset = axd->header.sql_desc_bind_type * n_row;
755 0 : if (axd->header.sql_desc_bind_offset_ptr)
756 0 : len_offset += *axd->header.sql_desc_bind_offset_ptr;
757 : } else {
758 385 : len_offset = sizeof(SQLLEN) * n_row;
759 : }
760 : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
761 :
762 385 : if (drec_axd->sql_desc_indicator_ptr && LEN(drec_axd->sql_desc_indicator_ptr) == SQL_NULL_DATA)
763 0 : len = SQL_NULL_DATA;
764 385 : else if (drec_axd->sql_desc_octet_length_ptr)
765 379 : len = LEN(drec_axd->sql_desc_octet_length_ptr);
766 : else {
767 6 : len = 0;
768 : /* TODO add XML if defined */
769 : /* FIXME, other types available */
770 10 : if (drec_axd->sql_desc_concise_type == SQL_C_CHAR || drec_axd->sql_desc_concise_type == SQL_C_BINARY) {
771 4 : len = SQL_NTS;
772 : } else {
773 2 : int type = drec_axd->sql_desc_concise_type;
774 :
775 2 : if (type == SQL_C_DEFAULT)
776 0 : type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type);
777 2 : type = odbc_c_to_server_type(type);
778 :
779 : /* FIXME check what happen to DATE/TIME types */
780 2 : size = tds_get_size_by_type(type);
781 2 : if (size > 0)
782 2 : len = size;
783 : }
784 : }
785 385 : return len;
786 : #undef LEN
787 : }
788 :
789 : #ifdef SQL_GUID
790 : # define TYPE_NORMAL_SQL_GUID TYPE_NORMAL(SQL_GUID)
791 : #else
792 : # define TYPE_NORMAL_SQL_GUID
793 : #endif
794 : #define SQL_TYPES \
795 : TYPE_NORMAL(SQL_BIT) \
796 : TYPE_NORMAL(SQL_SMALLINT) \
797 : TYPE_NORMAL(SQL_TINYINT) \
798 : TYPE_NORMAL(SQL_INTEGER) \
799 : TYPE_NORMAL(SQL_BIGINT) \
800 : \
801 : TYPE_NORMAL_SQL_GUID \
802 : \
803 : TYPE_NORMAL(SQL_BINARY) \
804 : TYPE_NORMAL(SQL_VARBINARY) \
805 : TYPE_NORMAL(SQL_LONGVARBINARY) \
806 : \
807 : TYPE_NORMAL(SQL_CHAR) \
808 : TYPE_NORMAL(SQL_VARCHAR) \
809 : TYPE_NORMAL(SQL_LONGVARCHAR) \
810 : \
811 : TYPE_NORMAL(SQL_DECIMAL) \
812 : TYPE_NORMAL(SQL_NUMERIC) \
813 : \
814 : TYPE_NORMAL(SQL_FLOAT) \
815 : TYPE_NORMAL(SQL_REAL) \
816 : TYPE_NORMAL(SQL_DOUBLE)\
817 : \
818 : TYPE_VERBOSE_START(SQL_DATETIME) \
819 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_TYPE_TIMESTAMP, SQL_TIMESTAMP) \
820 : TYPE_VERBOSE_END(SQL_DATETIME)
821 :
822 : SQLSMALLINT
823 : odbc_get_concise_sql_type(SQLSMALLINT type, SQLSMALLINT interval)
824 50910 : {
825 : #define TYPE_NORMAL(t) case t: return type;
826 : #define TYPE_VERBOSE_START(t) \
827 : case t: switch (interval) {
828 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
829 : case interval: return concise;
830 : #define TYPE_VERBOSE_END(t) \
831 : }
832 :
833 50910 : switch (type) {
834 232 : SQL_TYPES;
835 : }
836 0 : return 0;
837 : #undef TYPE_NORMAL
838 : #undef TYPE_VERBOSE_START
839 : #undef TYPE_VERBOSE_DATE
840 : #undef TYPE_VERBOSE_END
841 : }
842 :
843 : /**
844 : * Set concise type and all cascading field.
845 : * @param concise_type concise type to set
846 : * @param drec record to set. NULL to test error without setting
847 : * @param check_only it <>0 (true) check only, do not set type
848 : */
849 : SQLRETURN
850 : odbc_set_concise_sql_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only)
851 1719 : {
852 1719 : SQLSMALLINT type = concise_type, interval_code = 0;
853 :
854 : #define TYPE_NORMAL(t) case t: break;
855 : #define TYPE_VERBOSE_START(t)
856 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
857 : case old: concise_type = concise; \
858 : case concise: type = t; interval_code = interval; break;
859 : #define TYPE_VERBOSE_END(t)
860 :
861 1719 : switch (type) {
862 26 : SQL_TYPES;
863 : default:
864 52 : return SQL_ERROR;
865 : }
866 1667 : if (!check_only) {
867 1667 : drec->sql_desc_concise_type = concise_type;
868 1667 : drec->sql_desc_type = type;
869 1667 : drec->sql_desc_datetime_interval_code = interval_code;
870 :
871 1667 : switch (drec->sql_desc_type) {
872 : case SQL_NUMERIC:
873 : case SQL_DECIMAL:
874 37 : drec->sql_desc_precision = 38;
875 37 : drec->sql_desc_scale = 0;
876 : break;
877 : /* TODO finish */
878 : }
879 : }
880 1667 : return SQL_SUCCESS;
881 : #undef TYPE_NORMAL
882 : #undef TYPE_VERBOSE_START
883 : #undef TYPE_VERBOSE_DATE
884 : #undef TYPE_VERBOSE_END
885 : }
886 :
887 : #ifdef SQL_C_GUID
888 : # define TYPE_NORMAL_SQL_C_GUID TYPE_NORMAL(SQL_C_GUID)
889 : #else
890 : # define TYPE_NORMAL_SQL_C_GUID
891 : #endif
892 : #define C_TYPES \
893 : TYPE_NORMAL(SQL_C_BIT) \
894 : TYPE_NORMAL(SQL_C_SHORT) \
895 : TYPE_NORMAL(SQL_C_TINYINT) \
896 : TYPE_NORMAL(SQL_C_UTINYINT) \
897 : TYPE_NORMAL(SQL_C_STINYINT) \
898 : TYPE_NORMAL(SQL_C_LONG) \
899 : TYPE_NORMAL(SQL_C_SBIGINT) \
900 : TYPE_NORMAL(SQL_C_UBIGINT) \
901 : TYPE_NORMAL(SQL_C_SSHORT) \
902 : TYPE_NORMAL(SQL_C_SLONG) \
903 : TYPE_NORMAL(SQL_C_USHORT) \
904 : TYPE_NORMAL(SQL_C_ULONG) \
905 : \
906 : TYPE_NORMAL_SQL_C_GUID \
907 : TYPE_NORMAL(SQL_C_DEFAULT) \
908 : \
909 : TYPE_NORMAL(SQL_C_BINARY) \
910 : \
911 : TYPE_NORMAL(SQL_C_CHAR) \
912 : \
913 : TYPE_NORMAL(SQL_C_NUMERIC) \
914 : \
915 : TYPE_NORMAL(SQL_C_FLOAT) \
916 : TYPE_NORMAL(SQL_C_DOUBLE)\
917 : \
918 : TYPE_VERBOSE_START(SQL_DATETIME) \
919 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_DATE, SQL_C_TYPE_DATE, SQL_C_DATE) \
920 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIME, SQL_C_TYPE_TIME, SQL_C_TIME) \
921 : TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_C_TYPE_TIMESTAMP, SQL_C_TIMESTAMP) \
922 : TYPE_VERBOSE_END(SQL_DATETIME) \
923 : \
924 : TYPE_VERBOSE_START(SQL_INTERVAL) \
925 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY, SQL_C_INTERVAL_DAY) \
926 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_HOUR, SQL_C_INTERVAL_DAY_TO_HOUR) \
927 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_MINUTE, SQL_C_INTERVAL_DAY_TO_MINUTE) \
928 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_SECOND, SQL_C_INTERVAL_DAY_TO_SECOND) \
929 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR, SQL_C_INTERVAL_HOUR) \
930 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_MINUTE, SQL_C_INTERVAL_HOUR_TO_MINUTE) \
931 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_SECOND, SQL_C_INTERVAL_HOUR_TO_SECOND) \
932 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE, SQL_C_INTERVAL_MINUTE) \
933 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE_TO_SECOND, SQL_C_INTERVAL_MINUTE_TO_SECOND) \
934 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MONTH, SQL_C_INTERVAL_MONTH) \
935 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_SECOND, SQL_C_INTERVAL_SECOND) \
936 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR, SQL_C_INTERVAL_YEAR) \
937 : TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR_TO_MONTH, SQL_C_INTERVAL_YEAR_TO_MONTH) \
938 : TYPE_VERBOSE_END(SQL_INTERVAL)
939 :
940 : SQLSMALLINT
941 : odbc_get_concise_c_type(SQLSMALLINT type, SQLSMALLINT interval)
942 11180 : {
943 : #define TYPE_NORMAL(t) case t: return type;
944 : #define TYPE_VERBOSE_START(t) \
945 : case t: switch (interval) {
946 : #define TYPE_VERBOSE(t, interval, concise) \
947 : case interval: return concise;
948 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
949 : case interval: return concise;
950 : #define TYPE_VERBOSE_END(t) \
951 : }
952 :
953 11180 : switch (type) {
954 84 : C_TYPES;
955 : }
956 0 : return 0;
957 : #undef TYPE_NORMAL
958 : #undef TYPE_VERBOSE_START
959 : #undef TYPE_VERBOSE
960 : #undef TYPE_VERBOSE_DATE
961 : #undef TYPE_VERBOSE_END
962 : }
963 :
964 : /**
965 : * Set concise type and all cascading field.
966 : * @param concise_type concise type to set
967 : * @param drec record to set. NULL to test error without setting
968 : * @param check_only it <>0 (true) check only, do not set type
969 : */
970 : SQLRETURN
971 : odbc_set_concise_c_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only)
972 459 : {
973 459 : SQLSMALLINT type = concise_type, interval_code = 0;
974 :
975 : #define TYPE_NORMAL(t) case t: break;
976 : #define TYPE_VERBOSE_START(t)
977 : #define TYPE_VERBOSE(t, interval, concise) \
978 : case concise: type = t; interval_code = interval; break;
979 : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
980 : case concise: type = t; interval_code = interval; break; \
981 : case old: concise_type = concise; type = t; interval_code = interval; break;
982 : #define TYPE_VERBOSE_END(t)
983 :
984 459 : switch (type) {
985 10 : C_TYPES;
986 : default:
987 28 : return SQL_ERROR;
988 : }
989 431 : if (!check_only) {
990 431 : drec->sql_desc_concise_type = concise_type;
991 431 : drec->sql_desc_type = type;
992 431 : drec->sql_desc_datetime_interval_code = interval_code;
993 :
994 431 : switch (drec->sql_desc_type) {
995 : case SQL_C_NUMERIC:
996 14 : drec->sql_desc_precision = 38;
997 14 : drec->sql_desc_scale = 0;
998 : break;
999 : /* TODO finish */
1000 : }
1001 : }
1002 431 : return SQL_SUCCESS;
1003 : #undef TYPE_NORMAL
1004 : #undef TYPE_VERBOSE_START
1005 : #undef TYPE_VERBOSE
1006 : #undef TYPE_VERBOSE_DATE
1007 : #undef TYPE_VERBOSE_END
1008 : }
1009 :
1010 : SQLLEN
1011 : odbc_get_octet_len(int c_type, const struct _drecord *drec)
1012 196 : {
1013 : SQLLEN len;
1014 :
1015 : /* this shit is mine -- freddy77 */
1016 196 : switch (c_type) {
1017 : case SQL_C_CHAR:
1018 : case SQL_C_BINARY:
1019 96 : len = drec->sql_desc_octet_length;
1020 96 : break;
1021 : case SQL_C_DATE:
1022 : case SQL_C_TYPE_DATE:
1023 0 : len = sizeof(DATE_STRUCT);
1024 0 : break;
1025 : case SQL_C_TIME:
1026 : case SQL_C_TYPE_TIME:
1027 0 : len = sizeof(TIME_STRUCT);
1028 0 : break;
1029 : case SQL_C_TIMESTAMP:
1030 : case SQL_C_TYPE_TIMESTAMP:
1031 0 : len = sizeof(TIMESTAMP_STRUCT);
1032 0 : break;
1033 : case SQL_C_NUMERIC:
1034 6 : len = sizeof(SQL_NUMERIC_STRUCT);
1035 6 : break;
1036 : default:
1037 94 : len = tds_get_size_by_type(odbc_c_to_server_type(c_type));
1038 : break;
1039 : }
1040 196 : return len;
1041 : }
1042 :
1043 : /** \@} */
|