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