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-2015 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 : #include <assert.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 <freetds/time.h>
34 : #include <freetds/odbc.h>
35 : #include <freetds/convert.h>
36 : #include <freetds/iconv.h>
37 : #include <freetds/utils/string.h>
38 : #include <freetds/utils.h>
39 :
40 : TDS_INT
41 404 : convert_datetime2server(int bindtype, const void *src, TDS_DATETIMEALL * dta)
42 : {
43 : struct tm src_tm;
44 : int tm_dms;
45 : unsigned int dt_time;
46 : int i;
47 : time_t curr_time;
48 :
49 404 : const DATE_STRUCT *src_date = (const DATE_STRUCT *) src;
50 404 : const TIME_STRUCT *src_time = (const TIME_STRUCT *) src;
51 404 : const TIMESTAMP_STRUCT *src_timestamp = (const TIMESTAMP_STRUCT *) src;
52 :
53 404 : memset(dta, 0, sizeof(*dta));
54 :
55 404 : switch (bindtype) {
56 54 : case SQL_C_DATE:
57 : case SQL_C_TYPE_DATE:
58 54 : src_tm.tm_year = src_date->year - 1900;
59 54 : src_tm.tm_mon = src_date->month - 1;
60 54 : src_tm.tm_mday = src_date->day;
61 54 : src_tm.tm_hour = 0;
62 54 : src_tm.tm_min = 0;
63 54 : src_tm.tm_sec = 0;
64 54 : tm_dms = 0;
65 : dta->has_date = 1;
66 54 : break;
67 54 : case SQL_C_TIME:
68 : case SQL_C_TYPE_TIME:
69 : #if HAVE_GETTIMEOFDAY
70 : {
71 : struct timeval tv;
72 54 : gettimeofday(&tv, NULL);
73 54 : curr_time = tv.tv_sec;
74 : }
75 : #else
76 : curr_time = time(NULL);
77 : #endif
78 54 : tds_localtime_r(&curr_time, &src_tm);
79 54 : src_tm.tm_hour = src_time->hour;
80 54 : src_tm.tm_min = src_time->minute;
81 54 : src_tm.tm_sec = src_time->second;
82 54 : tm_dms = 0;
83 : dta->has_time = 1;
84 54 : break;
85 296 : case SQL_C_TIMESTAMP:
86 : case SQL_C_TYPE_TIMESTAMP:
87 296 : src_tm.tm_year = src_timestamp->year - 1900;
88 296 : src_tm.tm_mon = src_timestamp->month - 1;
89 296 : src_tm.tm_mday = src_timestamp->day;
90 296 : src_tm.tm_hour = src_timestamp->hour;
91 296 : src_tm.tm_min = src_timestamp->minute;
92 296 : src_tm.tm_sec = src_timestamp->second;
93 296 : tm_dms = src_timestamp->fraction / 100lu;
94 : dta->has_date = 1;
95 : dta->has_time = 1;
96 296 : break;
97 : default:
98 : return TDS_CONVERT_FAIL;
99 : }
100 :
101 : /* TODO code copied from convert.c, function */
102 404 : i = (src_tm.tm_mon - 13) / 12;
103 404 : dta->has_date = 1;
104 1212 : dta->date = 1461 * (src_tm.tm_year + 300 + i) / 4 +
105 1212 : (367 * (src_tm.tm_mon - 1 - 12 * i)) / 12 - (3 * ((src_tm.tm_year + 400 + i) / 100)) / 4 +
106 808 : src_tm.tm_mday - 109544;
107 :
108 404 : dta->has_time = 1;
109 404 : dt_time = (src_tm.tm_hour * 60 + src_tm.tm_min) * 60 + src_tm.tm_sec;
110 404 : dta->time = dt_time * UINT64_C(10000000) + tm_dms;
111 404 : return sizeof(TDS_DATETIMEALL);
112 : }
113 :
114 : static char*
115 36 : odbc_wstr2str(TDS_STMT * stmt, const char *src, int* len)
116 : {
117 36 : int srclen = (*len) / sizeof(SQLWCHAR);
118 36 : char *out = tds_new(char, srclen + 1), *p;
119 36 : const SQLWCHAR *wp = (const SQLWCHAR *) src;
120 :
121 36 : if (!out) {
122 0 : odbc_errs_add(&stmt->errs, "HY001", NULL);
123 0 : return NULL;
124 : }
125 :
126 : /* convert */
127 : p = out;
128 324 : for (; srclen && *wp < 256; --srclen)
129 324 : *p++ = (char) *wp++;
130 :
131 : /* still characters, wrong format */
132 36 : if (srclen) {
133 0 : free(out);
134 : /* TODO correct error ?? */
135 0 : odbc_errs_add(&stmt->errs, "07006", NULL);
136 0 : return NULL;
137 : }
138 :
139 36 : *len = p - out;
140 36 : return out;
141 : }
142 :
143 : static void
144 424 : _odbc_blob_free(TDSCOLUMN *col)
145 : {
146 424 : if (!col->column_data)
147 : return;
148 :
149 424 : TDS_ZERO_FREE(col->column_data);
150 : }
151 :
152 : static SQLRETURN
153 4 : odbc_convert_table(TDS_STMT *stmt, SQLTVP *src, TDS_TVP *dest, SQLLEN num_rows)
154 : {
155 : SQLLEN i;
156 : int j;
157 : TDS_TVP_ROW *row;
158 : TDS_TVP_ROW **prow;
159 : TDSPARAMINFO *params, *new_params;
160 4 : TDS_DESC *apd = src->apd, *ipd = src->ipd;
161 : SQLRETURN ret;
162 : char *type_name, *pch;
163 :
164 : /* probably data at execution attempt, currently not supported for TVP */
165 4 : if (num_rows < 0) {
166 0 : odbc_errs_add(&stmt->errs, "HYC00", "Data at execution are not supported for TVP columns");
167 0 : return SQL_ERROR;
168 : }
169 :
170 4 : tds_deinit_tvp(dest);
171 :
172 8 : type_name = strdup(tds_dstr_cstr(&src->type_name));
173 4 : if (!type_name)
174 : goto Memory_Error;
175 :
176 : /* Tokenize and extract the schema & TVP typename from the TVP's full name */
177 4 : pch = strchr(type_name, '.');
178 4 : if (pch == NULL) {
179 4 : dest->schema = tds_strndup("", 0);
180 4 : dest->name = type_name;
181 : } else {
182 0 : *pch = 0;
183 0 : dest->schema = type_name;
184 0 : dest->name = strdup(++pch);
185 : }
186 8 : if (!dest->schema || !dest->name)
187 : goto Memory_Error;
188 :
189 : /* Ensure that the TVP typename does not contain any more '.' */
190 : /* Otherwise, report it as an invalid data type error */
191 4 : pch = strchr(dest->name, '.');
192 4 : if (pch != NULL) {
193 0 : odbc_errs_add(&stmt->errs, "HY004", NULL);
194 0 : return SQL_ERROR;
195 : }
196 :
197 : params = NULL;
198 8 : for (j = 0; j < ipd->header.sql_desc_count; j++) {
199 8 : if (!(new_params = tds_alloc_param_result(params))) {
200 0 : tds_free_param_results(params);
201 0 : goto Memory_Error;
202 : }
203 8 : params = new_params;
204 :
205 8 : ret = odbc_sql2tds(stmt, &ipd->records[j], &apd->records[j], new_params->columns[j], false, apd, 0);
206 8 : if (!SQL_SUCCEEDED(ret)) {
207 0 : tds_free_param_results(params);
208 0 : return ret;
209 : }
210 : }
211 4 : dest->metadata = params;
212 :
213 22 : for (i = 0, prow = &dest->row; i < num_rows; prow = &(*prow)->next, i++) {
214 18 : if ((row = tds_new0(TDS_TVP_ROW, 1)) == NULL)
215 : goto Memory_Error;
216 :
217 18 : *prow = row;
218 :
219 18 : params = NULL;
220 54 : for (j = 0; j < ipd->header.sql_desc_count; j++) {
221 36 : if (!(new_params = tds_alloc_param_result(params))) {
222 0 : tds_free_param_results(params);
223 0 : goto Memory_Error;
224 : }
225 36 : params = new_params;
226 :
227 36 : ret = odbc_sql2tds(stmt, &ipd->records[j], &apd->records[j], new_params->columns[j], true, apd, i);
228 36 : if (!SQL_SUCCEEDED(ret)) {
229 0 : tds_free_param_results(params);
230 0 : return ret;
231 : }
232 : }
233 18 : row->params = params;
234 : }
235 :
236 : return SQL_SUCCESS;
237 :
238 0 : Memory_Error:
239 0 : odbc_errs_add(&stmt->errs, "HY001", NULL);
240 0 : return SQL_ERROR;
241 : }
242 :
243 : /**
244 : * Convert parameters to libtds format
245 : * @param stmt ODBC statement
246 : * @param drec_ixd IRD or IPD record of destination
247 : * @param drec_ard ARD or APD record of source
248 : * @param curcol destination column
249 : * @param compute_row true if data needs to be written to column
250 : * @param axd ARD or APD of source
251 : * @param n_row number of the row to write
252 : * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
253 : */
254 : SQLRETURN
255 19080 : odbc_sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ixd, const struct _drecord *drec_axd, TDSCOLUMN *curcol,
256 : bool compute_row, const TDS_DESC* axd, unsigned int n_row)
257 : {
258 19080 : TDS_DBC * dbc = stmt->dbc;
259 19080 : TDSCONNECTION * conn = dbc->tds_socket->conn;
260 : TDS_SERVER_TYPE dest_type, src_type;
261 : int sql_src_type, res;
262 : CONV_RESULT ores;
263 : TDSBLOB *blob;
264 : char *src, *converted_src;
265 : unsigned char *dest;
266 : int len;
267 : TDS_DATETIMEALL dta;
268 : TDS_NUMERIC num;
269 : SQL_NUMERIC_STRUCT *sql_num;
270 : SQLINTEGER sql_len;
271 19080 : bool need_data = false;
272 : int i;
273 :
274 : /* TODO handle bindings of char like "{d '2002-11-12'}" */
275 19080 : tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ixd->sql_desc_concise_type);
276 :
277 : /* what type to convert ? */
278 19080 : dest_type = odbc_sql_to_server_type(conn, drec_ixd->sql_desc_concise_type, drec_ixd->sql_desc_unsigned);
279 19080 : if (dest_type == TDS_INVALID_TYPE) {
280 3712 : odbc_errs_add(&stmt->errs, "07006", NULL); /* Restricted data type attribute violation */
281 3712 : return SQL_ERROR;
282 : }
283 15368 : tdsdump_log(TDS_DBG_INFO2, "trace\n");
284 :
285 : /* get C type */
286 15368 : sql_src_type = drec_axd->sql_desc_concise_type;
287 15368 : if (sql_src_type == SQL_C_DEFAULT)
288 0 : sql_src_type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type);
289 :
290 15368 : tds_set_param_type(conn, curcol, dest_type);
291 :
292 : /* TODO what happen for unicode types ?? */
293 15368 : if (is_char_type(dest_type)) {
294 5200 : TDSICONV *conv = conn->char_convs[is_unicode_type(dest_type) ? client2ucs2 : client2server_chardata];
295 :
296 : /* use binary format for binary to char */
297 5200 : if (sql_src_type == SQL_C_BINARY) {
298 258 : curcol->char_conv = NULL;
299 4942 : } else if (sql_src_type == SQL_C_WCHAR) {
300 396 : curcol->char_conv = tds_iconv_get_info(conn, odbc_get_wide_canonic(conn), conv->to.charset.canonic);
301 396 : memcpy(curcol->column_collation, conn->collation, sizeof(conn->collation));
302 : } else {
303 : #ifdef ENABLE_ODBC_WIDE
304 4546 : curcol->char_conv = tds_iconv_get_info(conn, dbc->original_charset_num, conv->to.charset.canonic);
305 : #else
306 : curcol->char_conv = NULL;
307 : #endif
308 : }
309 : }
310 15368 : if (is_numeric_type(curcol->column_type)) {
311 764 : curcol->column_prec = drec_ixd->sql_desc_precision;
312 764 : curcol->column_scale = drec_ixd->sql_desc_scale;
313 : }
314 :
315 15368 : if (drec_ixd->sql_desc_parameter_type != SQL_PARAM_INPUT)
316 9184 : curcol->column_output = 1;
317 :
318 : /* compute destination length */
319 15368 : if (curcol->column_varint_size != 0) {
320 : /* curcol->column_size = drec_axd->sql_desc_octet_length; */
321 : /*
322 : * TODO destination length should come from sql_desc_length,
323 : * however there is the encoding problem to take into account
324 : * we should fill destination length after conversion keeping
325 : * attention to fill correctly blob/fixed type/variable type
326 : */
327 : /* TODO location of this test is correct here ?? */
328 15240 : if (dest_type != SYBUNIQUE && !is_fixed_type(dest_type)) {
329 7870 : curcol->column_cur_size = 0;
330 7870 : curcol->column_size = drec_ixd->sql_desc_length;
331 : /* Ensure that the column_cur_size and column_size are consistent, */
332 : /* since drec_ixd->sql_desc_length contains the number of rows for a TVP */
333 7870 : if (dest_type == SYBMSTABLE)
334 4 : curcol->column_size = sizeof(TDS_TVP);
335 7870 : if (curcol->column_size < 0) {
336 8 : curcol->on_server.column_size = curcol->column_size = 0x7FFFFFFFl;
337 : } else {
338 7862 : if (is_unicode_type(dest_type))
339 1616 : curcol->on_server.column_size = curcol->column_size * 2;
340 : else
341 6246 : curcol->on_server.column_size = curcol->column_size;
342 : }
343 : }
344 128 : } else if (dest_type != SYBBIT) {
345 : /* TODO only a trick... */
346 12 : tds_set_param_type(conn, curcol, tds_get_null_type(dest_type));
347 : }
348 :
349 : /* test source type */
350 : /* TODO test intervals */
351 15368 : src_type = odbc_c_to_server_type(sql_src_type);
352 15368 : if (!src_type) {
353 4976 : odbc_errs_add(&stmt->errs, "07006", NULL); /* Restricted data type attribute violation */
354 4976 : return SQL_ERROR;
355 : }
356 :
357 : /* we have no data to convert, just return */
358 10392 : if (!compute_row)
359 : return SQL_SUCCESS;
360 :
361 10384 : src = (char *) drec_axd->sql_desc_data_ptr;
362 10384 : if (src && n_row) {
363 : SQLLEN len;
364 1276 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
365 0 : len = axd->header.sql_desc_bind_type;
366 0 : if (axd->header.sql_desc_bind_offset_ptr)
367 0 : src += *axd->header.sql_desc_bind_offset_ptr;
368 : } else {
369 1276 : len = odbc_get_octet_len(sql_src_type, drec_axd);
370 1276 : if (len < 0)
371 : /* TODO sure ? what happen to upper layer ?? */
372 : /* TODO fill error */
373 : return SQL_ERROR;
374 : }
375 1276 : src += len * n_row;
376 : }
377 :
378 : /* if only output assume input is NULL */
379 10384 : if (drec_ixd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
380 : sql_len = SQL_NULL_DATA;
381 : } else {
382 9654 : sql_len = odbc_get_param_len(drec_axd, drec_ixd, axd, n_row);
383 :
384 : /* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
385 9654 : if (src_type == SYBVARCHAR && sql_len == 1 && drec_ixd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
386 0 : && src && *src == 0) {
387 : sql_len = SQL_NULL_DATA;
388 : }
389 : }
390 :
391 : /* compute source length */
392 9654 : switch (sql_len) {
393 1116 : case SQL_NULL_DATA:
394 1116 : len = 0;
395 : break;
396 2178 : case SQL_NTS:
397 : /* check that SQLBindParameter::ParameterValuePtr is not zero for input parameters */
398 2178 : if (!src) {
399 392 : odbc_errs_add(&stmt->errs, "HY090", NULL);
400 392 : return SQL_ERROR;
401 : }
402 1786 : if (sql_src_type == SQL_C_WCHAR)
403 72 : len = sqlwcslen((const SQLWCHAR *) src) * sizeof(SQLWCHAR);
404 : else
405 1714 : len = strlen(src);
406 : break;
407 0 : case SQL_DEFAULT_PARAM:
408 0 : odbc_errs_add(&stmt->errs, "07S01", NULL); /* Invalid use of default parameter */
409 0 : return SQL_ERROR;
410 : break;
411 7090 : case SQL_DATA_AT_EXEC:
412 : default:
413 7090 : len = sql_len;
414 7090 : if (sql_len < 0) {
415 : /* test for SQL_C_CHAR/SQL_C_BINARY */
416 : switch (sql_src_type) {
417 : case SQL_C_CHAR:
418 : case SQL_C_WCHAR:
419 : case SQL_C_BINARY:
420 : break;
421 0 : default:
422 0 : odbc_errs_add(&stmt->errs, "HY090", NULL);
423 0 : return SQL_ERROR;
424 : }
425 260 : len = SQL_LEN_DATA_AT_EXEC(sql_len);
426 260 : need_data = true;
427 :
428 : /* dynamic length allowed only for BLOB fields */
429 260 : switch (drec_ixd->sql_desc_concise_type) {
430 : case SQL_LONGVARCHAR:
431 : case SQL_WLONGVARCHAR:
432 : case SQL_LONGVARBINARY:
433 : break;
434 0 : default:
435 0 : odbc_errs_add(&stmt->errs, "HY090", NULL);
436 0 : return SQL_ERROR;
437 : }
438 6830 : }
439 : }
440 :
441 : /* set NULL. For NULLs we don't need to allocate row buffer so avoid it */
442 : if (!need_data) {
443 9732 : assert(drec_ixd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
444 9732 : if (sql_len == SQL_NULL_DATA) {
445 1116 : curcol->column_cur_size = -1;
446 1116 : return SQL_SUCCESS;
447 : }
448 : }
449 :
450 8876 : if (is_char_type(dest_type) && !need_data
451 3368 : && (sql_src_type == SQL_C_CHAR || sql_src_type == SQL_C_WCHAR || sql_src_type == SQL_C_BINARY)) {
452 2458 : if (curcol->column_data && curcol->column_data_free)
453 0 : curcol->column_data_free(curcol);
454 2458 : curcol->column_data_free = NULL;
455 2458 : if (is_blob_col(curcol)) {
456 : /* trick to set blob without freeing it, _odbc_blob_free does not free TDSBLOB->textvalue */
457 424 : TDSBLOB *blob = tds_new0(TDSBLOB, 1);
458 424 : if (!blob) {
459 0 : odbc_errs_add(&stmt->errs, "HY001", NULL);
460 0 : return SQL_ERROR;
461 : }
462 424 : blob->textvalue = src;
463 424 : curcol->column_data = (TDS_UCHAR*) blob;
464 424 : curcol->column_data_free = _odbc_blob_free;
465 : } else {
466 2034 : curcol->column_data = (TDS_UCHAR*) src;
467 : }
468 2458 : curcol->column_size = len;
469 2458 : curcol->column_cur_size = len;
470 2458 : return SQL_SUCCESS;
471 : }
472 :
473 : /* allocate given space */
474 6418 : if (!tds_alloc_param_data(curcol)) {
475 0 : odbc_errs_add(&stmt->errs, "HY001", NULL);
476 0 : return SQL_ERROR;
477 : }
478 :
479 : /* fill data with SQLPutData */
480 6418 : if (need_data) {
481 260 : curcol->column_cur_size = 0;
482 260 : return SQL_NEED_DATA;
483 : }
484 :
485 6158 : if (!src) {
486 3064 : odbc_errs_add(&stmt->errs, "HY090", NULL);
487 3064 : return SQL_ERROR;
488 : }
489 :
490 : /* convert special parameters (not libTDS compatible) */
491 3094 : switch (src_type) {
492 402 : case SYBMSDATETIME2:
493 402 : convert_datetime2server(sql_src_type, src, &dta);
494 402 : src = (char *) &dta;
495 402 : break;
496 136 : case SYBDECIMAL:
497 : case SYBNUMERIC:
498 136 : sql_num = (SQL_NUMERIC_STRUCT *) src;
499 136 : num.precision = sql_num->precision;
500 136 : num.scale = sql_num->scale;
501 136 : num.array[0] = sql_num->sign ^ 1;
502 : /* test precision so client do not crash our library */
503 136 : if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
504 : /* TODO add proper error */
505 : return SQL_ERROR;
506 136 : i = tds_numeric_bytes_per_prec[num.precision];
507 136 : memcpy(num.array + 1, sql_num->val, i - 1);
508 136 : tds_swap_bytes(num.array + 1, i - 1);
509 136 : if (i < sizeof(num.array))
510 136 : memset(num.array + i, 0, sizeof(num.array) - i);
511 : src = (char *) #
512 : break;
513 : /* TODO intervals */
514 : default:
515 : /* prevents some compiler warnings about missing cases */
516 : break;
517 : }
518 :
519 3094 : converted_src = NULL;
520 3094 : if (sql_src_type == SQL_C_WCHAR) {
521 36 : converted_src = src = odbc_wstr2str(stmt, src, &len);
522 36 : if (!src)
523 : /* TODO add proper error */
524 : return SQL_ERROR;
525 : src_type = SYBVARCHAR;
526 : }
527 :
528 3094 : dest = curcol->column_data;
529 3094 : switch ((TDS_SERVER_TYPE) dest_type) {
530 126 : case SYBCHAR:
531 : case SYBVARCHAR:
532 : case XSYBCHAR:
533 : case XSYBVARCHAR:
534 : case XSYBNVARCHAR:
535 : case XSYBNCHAR:
536 : case SYBNVARCHAR:
537 126 : ores.cc.c = (TDS_CHAR*) dest;
538 126 : ores.cc.len = curcol->column_size;
539 126 : res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_CHAR, &ores);
540 126 : if (res > curcol->column_size)
541 0 : res = curcol->column_size;
542 : break;
543 174 : case SYBBINARY:
544 : case SYBVARBINARY:
545 : case XSYBBINARY:
546 : case XSYBVARBINARY:
547 174 : ores.cb.ib = (TDS_CHAR*) dest;
548 174 : ores.cb.len = curcol->column_size;
549 174 : res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_BINARY, &ores);
550 174 : if (res > curcol->column_size)
551 0 : res = curcol->column_size;
552 : break;
553 36 : case SYBNTEXT:
554 36 : dest_type = SYBTEXT;
555 194 : case SYBTEXT:
556 : case SYBLONGBINARY:
557 : case SYBIMAGE:
558 194 : res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
559 194 : if (res >= 0) {
560 194 : blob = (TDSBLOB *) dest;
561 194 : free(blob->textvalue);
562 194 : blob->textvalue = ores.ib;
563 : }
564 : break;
565 52 : case SYBNUMERIC:
566 : case SYBDECIMAL:
567 52 : ((TDS_NUMERIC *) dest)->precision = drec_ixd->sql_desc_precision;
568 52 : ((TDS_NUMERIC *) dest)->scale = drec_ixd->sql_desc_scale;
569 2596 : case SYBINTN:
570 : case SYBINT1:
571 : case SYBINT2:
572 : case SYBINT4:
573 : case SYBINT8:
574 : case SYBFLT8:
575 : case SYBDATETIME:
576 : case SYBBIT:
577 : case SYBMONEY4:
578 : case SYBMONEY:
579 : case SYBDATETIME4:
580 : case SYBREAL:
581 : case SYBBITN:
582 : case SYBFLTN:
583 : case SYBMONEYN:
584 : case SYBDATETIMN:
585 : case SYBSINT1:
586 : case SYBUINT2:
587 : case SYBUINT4:
588 : case SYBUINT8:
589 : case SYBUNIQUE:
590 : case SYBMSTIME:
591 : case SYBMSDATE:
592 : case SYBMSDATETIME2:
593 : case SYBMSDATETIMEOFFSET:
594 : case SYB5BIGTIME:
595 : case SYB5BIGDATETIME:
596 2596 : res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, (CONV_RESULT*) dest);
597 2596 : break;
598 4 : case SYBMSTABLE:
599 4 : free(converted_src);
600 4 : src = drec_ixd->sql_desc_data_ptr;
601 4 : curcol->column_cur_size = sizeof(TDS_TVP);
602 4 : return odbc_convert_table(stmt, (SQLTVP *) src, (TDS_TVP *) dest,
603 4 : drec_axd->sql_desc_octet_length_ptr == NULL ? 1 : *drec_axd->sql_desc_octet_length_ptr);
604 : default:
605 : case SYBVOID:
606 : case SYBVARIANT:
607 : /* TODO ODBC 3.5 */
608 0 : assert(0);
609 : res = -1;
610 : break;
611 : }
612 :
613 3090 : free(converted_src);
614 3090 : if (res < 0) {
615 0 : odbc_convert_err_set(&stmt->errs, res);
616 0 : return SQL_ERROR;
617 : }
618 :
619 3090 : curcol->column_cur_size = res;
620 :
621 3090 : return SQL_SUCCESS;
622 : }
|