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
convert_datetime2server(int bindtype,const void * src,TDS_DATETIMEALL * dta)41 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 	const DATE_STRUCT *src_date = (const DATE_STRUCT *) src;
50 	const TIME_STRUCT *src_time = (const TIME_STRUCT *) src;
51 	const TIMESTAMP_STRUCT *src_timestamp = (const TIMESTAMP_STRUCT *) src;
52 
53 	memset(dta, 0, sizeof(*dta));
54 
55 	switch (bindtype) {
56 	case SQL_C_DATE:
57 	case SQL_C_TYPE_DATE:
58 		src_tm.tm_year = src_date->year - 1900;
59 		src_tm.tm_mon = src_date->month - 1;
60 		src_tm.tm_mday = src_date->day;
61 		src_tm.tm_hour = 0;
62 		src_tm.tm_min = 0;
63 		src_tm.tm_sec = 0;
64 		tm_dms = 0;
65 		dta->has_date = 1;
66 		break;
67 	case SQL_C_TIME:
68 	case SQL_C_TYPE_TIME:
69 #if HAVE_GETTIMEOFDAY
70 		{
71 			struct timeval tv;
72 		        gettimeofday(&tv, NULL);
73 		        curr_time = tv.tv_sec;
74 		}
75 #else
76 		curr_time = time(NULL);
77 #endif
78 		tds_localtime_r(&curr_time, &src_tm);
79 		src_tm.tm_hour = src_time->hour;
80 		src_tm.tm_min = src_time->minute;
81 		src_tm.tm_sec = src_time->second;
82 		tm_dms = 0;
83 		dta->has_time = 1;
84 		break;
85 	case SQL_C_TIMESTAMP:
86 	case SQL_C_TYPE_TIMESTAMP:
87 		src_tm.tm_year = src_timestamp->year - 1900;
88 		src_tm.tm_mon = src_timestamp->month - 1;
89 		src_tm.tm_mday = src_timestamp->day;
90 		src_tm.tm_hour = src_timestamp->hour;
91 		src_tm.tm_min = src_timestamp->minute;
92 		src_tm.tm_sec = src_timestamp->second;
93 		tm_dms = src_timestamp->fraction / 100lu;
94 		dta->has_date = 1;
95 		dta->has_time = 1;
96 		break;
97 	default:
98 		return TDS_CONVERT_FAIL;
99 	}
100 
101 	/* TODO code copied from convert.c, function */
102 	i = (src_tm.tm_mon - 13) / 12;
103 	dta->has_date = 1;
104 	dta->date = 1461 * (src_tm.tm_year + 300 + i) / 4 +
105 		(367 * (src_tm.tm_mon - 1 - 12 * i)) / 12 - (3 * ((src_tm.tm_year + 400 + i) / 100)) / 4 +
106 		src_tm.tm_mday - 109544;
107 
108 	dta->has_time = 1;
109 	dt_time = (src_tm.tm_hour * 60 + src_tm.tm_min) * 60 + src_tm.tm_sec;
110 	dta->time = dt_time * ((TDS_UINT8) 10000000u) + tm_dms;
111 	return sizeof(TDS_DATETIMEALL);
112 }
113 
114 static char*
odbc_wstr2str(TDS_STMT * stmt,const char * src,int * len)115 odbc_wstr2str(TDS_STMT * stmt, const char *src, int* len)
116 {
117 	int srclen = (*len) / sizeof(SQLWCHAR);
118 	char *out = tds_new(char, srclen + 1), *p;
119 	const SQLWCHAR *wp = (const SQLWCHAR *) src;
120 
121 	if (!out) {
122 		odbc_errs_add(&stmt->errs, "HY001", NULL);
123 		return NULL;
124 	}
125 
126         /* convert */
127         p = out;
128 	for (; srclen && *wp < 256; --srclen)
129 		*p++ = (char) *wp++;
130 
131 	/* still characters, wrong format */
132 	if (srclen) {
133 		free(out);
134 		/* TODO correct error ?? */
135 		odbc_errs_add(&stmt->errs, "07006", NULL);
136 		return NULL;
137 	}
138 
139 	*len = p - out;
140 	return out;
141 }
142 
143 static void
_odbc_blob_free(TDSCOLUMN * col)144 _odbc_blob_free(TDSCOLUMN *col)
145 {
146         if (!col->column_data)
147                 return;
148 
149         TDS_ZERO_FREE(col->column_data);
150 }
151 
152 /**
153  * Convert parameters to libtds format
154  * @param stmt        ODBC statement
155  * @param drec_ixd    IRD or IPD record of destination
156  * @param drec_ard    ARD or APD record of source
157  * @param curcol      destination column
158  * @param compute_row true if data needs to be written to column
159  * @param axd         ARD or APD of source
160  * @param n_row       number of the row to write
161  * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
162  */
163 SQLRETURN
odbc_sql2tds(TDS_STMT * stmt,const struct _drecord * drec_ixd,const struct _drecord * drec_axd,TDSCOLUMN * curcol,bool compute_row,const TDS_DESC * axd,unsigned int n_row)164 odbc_sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ixd, const struct _drecord *drec_axd, TDSCOLUMN *curcol,
165 	bool compute_row, const TDS_DESC* axd, unsigned int n_row)
166 {
167 	TDS_DBC * dbc = stmt->dbc;
168 	TDSCONNECTION * conn = dbc->tds_socket->conn;
169 	TDS_SERVER_TYPE dest_type;
170 	int src_type, sql_src_type, res;
171 	CONV_RESULT ores;
172 	TDSBLOB *blob;
173 	char *src, *converted_src;
174 	unsigned char *dest;
175 	int len;
176 	TDS_DATETIMEALL dta;
177 	TDS_NUMERIC num;
178 	SQL_NUMERIC_STRUCT *sql_num;
179 	SQLINTEGER sql_len;
180 	bool need_data = false;
181 	int i;
182 
183 	/* TODO handle bindings of char like "{d '2002-11-12'}" */
184 	tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ixd->sql_desc_concise_type);
185 
186 	/* what type to convert ? */
187 	dest_type = odbc_sql_to_server_type(conn, drec_ixd->sql_desc_concise_type, drec_ixd->sql_desc_unsigned);
188 	if (dest_type == TDS_INVALID_TYPE) {
189 		odbc_errs_add(&stmt->errs, "07006", NULL);	/* Restricted data type attribute violation */
190 		return SQL_ERROR;
191 	}
192 	tdsdump_log(TDS_DBG_INFO2, "trace\n");
193 
194 	/* get C type */
195 	sql_src_type = drec_axd->sql_desc_concise_type;
196 	if (sql_src_type == SQL_C_DEFAULT)
197 		sql_src_type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type);
198 
199 	tds_set_param_type(conn, curcol, dest_type);
200 
201 	/* TODO what happen for unicode types ?? */
202 	if (is_char_type(dest_type)) {
203 		TDSICONV *conv = conn->char_convs[is_unicode_type(dest_type) ? client2ucs2 : client2server_chardata];
204 
205 		/* use binary format for binary to char */
206 		if (sql_src_type == SQL_C_BINARY) {
207 			curcol->char_conv = NULL;
208 		} else if (sql_src_type == SQL_C_WCHAR) {
209 			curcol->char_conv = tds_iconv_get_info(conn, odbc_get_wide_canonic(conn), conv->to.charset.canonic);
210 			memcpy(curcol->column_collation, conn->collation, sizeof(conn->collation));
211 		} else {
212 #ifdef ENABLE_ODBC_WIDE
213 			curcol->char_conv = tds_iconv_get_info(conn, dbc->original_charset_num, conv->to.charset.canonic);
214 #else
215 			curcol->char_conv = NULL;
216 #endif
217 		}
218 	}
219 	if (is_numeric_type(curcol->column_type)) {
220 		curcol->column_prec = drec_ixd->sql_desc_precision;
221 		curcol->column_scale = drec_ixd->sql_desc_scale;
222 	}
223 
224 	if (drec_ixd->sql_desc_parameter_type != SQL_PARAM_INPUT)
225 		curcol->column_output = 1;
226 
227 	/* compute destination length */
228 	if (curcol->column_varint_size != 0) {
229 		/* curcol->column_size = drec_axd->sql_desc_octet_length; */
230 		/*
231 		 * TODO destination length should come from sql_desc_length,
232 		 * however there is the encoding problem to take into account
233 		 * we should fill destination length after conversion keeping
234 		 * attention to fill correctly blob/fixed type/variable type
235 		 */
236 		/* TODO location of this test is correct here ?? */
237 		if (dest_type != SYBUNIQUE && !is_fixed_type(dest_type)) {
238 			curcol->column_cur_size = 0;
239 			curcol->column_size = drec_ixd->sql_desc_length;
240 			if (curcol->column_size < 0) {
241 				curcol->on_server.column_size = curcol->column_size = 0x7FFFFFFFl;
242 			} else {
243 				if (is_unicode_type(dest_type))
244 					curcol->on_server.column_size = curcol->column_size * 2;
245 				else
246 					curcol->on_server.column_size = curcol->column_size;
247 			}
248 		}
249 	} else if (dest_type != SYBBIT) {
250 		/* TODO only a trick... */
251 		tds_set_param_type(conn, curcol, tds_get_null_type(dest_type));
252 	}
253 
254 	/* test source type */
255 	/* TODO test intervals */
256 	src_type = odbc_c_to_server_type(sql_src_type);
257 	if (!src_type) {
258 		odbc_errs_add(&stmt->errs, "07006", NULL);	/* Restricted data type attribute violation */
259 		return SQL_ERROR;
260 	}
261 
262 	/* we have no data to convert, just return */
263 	if (!compute_row)
264 		return SQL_SUCCESS;
265 
266 	src = (char *) drec_axd->sql_desc_data_ptr;
267 	if (src && n_row) {
268 		SQLLEN len;
269 		if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
270 			len = axd->header.sql_desc_bind_type;
271 			if (axd->header.sql_desc_bind_offset_ptr)
272 				src += *axd->header.sql_desc_bind_offset_ptr;
273 		} else {
274 			len = odbc_get_octet_len(sql_src_type, drec_axd);
275 			if (len < 0)
276 				/* TODO sure ? what happen to upper layer ?? */
277 				/* TODO fill error */
278 				return SQL_ERROR;
279 		}
280 		src += len * n_row;
281 	}
282 
283 	/* if only output assume input is NULL */
284 	if (drec_ixd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
285 		sql_len = SQL_NULL_DATA;
286 	} else {
287 		sql_len = odbc_get_param_len(drec_axd, drec_ixd, axd, n_row);
288 
289 		/* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
290 		if (src_type == SYBVARCHAR && sql_len == 1 && drec_ixd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
291 		    && src && *src == 0) {
292 			sql_len = SQL_NULL_DATA;
293 		}
294 	}
295 
296 	/* compute source length */
297 	switch (sql_len) {
298 	case SQL_NULL_DATA:
299 		len = 0;
300 		break;
301 	case SQL_NTS:
302 		/* check that SQLBindParameter::ParameterValuePtr is not zero for input parameters */
303 		if (!src) {
304 			odbc_errs_add(&stmt->errs, "HY090", NULL);
305 			return SQL_ERROR;
306 		}
307 		if (sql_src_type == SQL_C_WCHAR)
308 			len = sqlwcslen((const SQLWCHAR *) src) * sizeof(SQLWCHAR);
309 		else
310 			len = strlen(src);
311 		break;
312 	case SQL_DEFAULT_PARAM:
313 		odbc_errs_add(&stmt->errs, "07S01", NULL);	/* Invalid use of default parameter */
314 		return SQL_ERROR;
315 		break;
316 	case SQL_DATA_AT_EXEC:
317 	default:
318 		len = sql_len;
319 		if (sql_len < 0) {
320 			/* test for SQL_C_CHAR/SQL_C_BINARY */
321 			switch (sql_src_type) {
322 			case SQL_C_CHAR:
323 			case SQL_C_WCHAR:
324 			case SQL_C_BINARY:
325 				break;
326 			default:
327 				odbc_errs_add(&stmt->errs, "HY090", NULL);
328 				return SQL_ERROR;
329 			}
330 			len = SQL_LEN_DATA_AT_EXEC(sql_len);
331 			need_data = true;
332 
333 			/* dynamic length allowed only for BLOB fields */
334 			switch (drec_ixd->sql_desc_concise_type) {
335 			case SQL_LONGVARCHAR:
336 			case SQL_WLONGVARCHAR:
337 			case SQL_LONGVARBINARY:
338 				break;
339 			default:
340 				odbc_errs_add(&stmt->errs, "HY090", NULL);
341 				return SQL_ERROR;
342 			}
343 		}
344 	}
345 
346 	/* set NULL. For NULLs we don't need to allocate row buffer so avoid it */
347 	if (!need_data) {
348 		assert(drec_ixd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
349 		if (sql_len == SQL_NULL_DATA) {
350 			curcol->column_cur_size = -1;
351 			return SQL_SUCCESS;
352 		}
353 	}
354 
355 	if (is_char_type(dest_type) && !need_data
356 	    && (sql_src_type == SQL_C_CHAR || sql_src_type == SQL_C_WCHAR || sql_src_type == SQL_C_BINARY)) {
357 		if (curcol->column_data && curcol->column_data_free)
358 			curcol->column_data_free(curcol);
359 		curcol->column_data_free = NULL;
360 		if (is_blob_col(curcol)) {
361 			/* trick to set blob without freeing it, _odbc_blob_free does not free TDSBLOB->textvalue */
362 			TDSBLOB *blob = tds_new0(TDSBLOB, 1);
363 			if (!blob) {
364 				odbc_errs_add(&stmt->errs, "HY001", NULL);
365 				return SQL_ERROR;
366 			}
367 			blob->textvalue = src;
368 			curcol->column_data = (TDS_UCHAR*) blob;
369 			curcol->column_data_free = _odbc_blob_free;
370 		} else {
371 			curcol->column_data = (TDS_UCHAR*) src;
372 		}
373 		curcol->column_size = len;
374 		curcol->column_cur_size = len;
375 		return SQL_SUCCESS;
376 	}
377 
378 	/* allocate given space */
379 	if (!tds_alloc_param_data(curcol)) {
380 		odbc_errs_add(&stmt->errs, "HY001", NULL);
381 		return SQL_ERROR;
382 	}
383 
384 	/* fill data with SQLPutData */
385 	if (need_data) {
386 		curcol->column_cur_size = 0;
387 		return SQL_NEED_DATA;
388 	}
389 
390 	if (!src) {
391 		odbc_errs_add(&stmt->errs, "HY090", NULL);
392 		return SQL_ERROR;
393 	}
394 
395 	/* convert special parameters (not libTDS compatible) */
396 	switch (src_type) {
397 	case SYBMSDATETIME2:
398 		convert_datetime2server(sql_src_type, src, &dta);
399 		src = (char *) &dta;
400 		break;
401 	case SYBDECIMAL:
402 	case SYBNUMERIC:
403 		sql_num = (SQL_NUMERIC_STRUCT *) src;
404 		num.precision = sql_num->precision;
405 		num.scale = sql_num->scale;
406 		num.array[0] = sql_num->sign ^ 1;
407 		/* test precision so client do not crash our library */
408 		if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
409 			/* TODO add proper error */
410 			return SQL_ERROR;
411 		i = tds_numeric_bytes_per_prec[num.precision];
412 		memcpy(num.array + 1, sql_num->val, i - 1);
413 		tds_swap_bytes(num.array + 1, i - 1);
414 		if (i < sizeof(num.array))
415 			memset(num.array + i, 0, sizeof(num.array) - i);
416 		src = (char *) &num;
417 		break;
418 		/* TODO intervals */
419 	}
420 
421 	converted_src = NULL;
422 	if (sql_src_type == SQL_C_WCHAR) {
423 		converted_src = src = odbc_wstr2str(stmt, src, &len);
424 		if (!src)
425 			return SQL_ERROR;
426 		src_type = SYBVARCHAR;
427 	}
428 
429 	dest = curcol->column_data;
430 	switch ((TDS_SERVER_TYPE) dest_type) {
431 	case SYBCHAR:
432 	case SYBVARCHAR:
433 	case XSYBCHAR:
434 	case XSYBVARCHAR:
435 	case XSYBNVARCHAR:
436 	case XSYBNCHAR:
437 	case SYBNVARCHAR:
438 		ores.cc.c = (TDS_CHAR*) dest;
439 		ores.cc.len = curcol->column_size;
440 		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_CHAR, &ores);
441 		if (res > curcol->column_size)
442 			res = curcol->column_size;
443 		break;
444 	case SYBBINARY:
445 	case SYBVARBINARY:
446 	case XSYBBINARY:
447 	case XSYBVARBINARY:
448 		ores.cb.ib = (TDS_CHAR*) dest;
449 		ores.cb.len = curcol->column_size;
450 		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_BINARY, &ores);
451 		if (res > curcol->column_size)
452 			res = curcol->column_size;
453 		break;
454 	case SYBNTEXT:
455 		dest_type = SYBTEXT;
456 	case SYBTEXT:
457 	case SYBLONGBINARY:
458 	case SYBIMAGE:
459 		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
460 		if (res >= 0) {
461 			blob = (TDSBLOB *) dest;
462 			free(blob->textvalue);
463 			blob->textvalue = ores.ib;
464 		}
465 		break;
466 	case SYBNUMERIC:
467 	case SYBDECIMAL:
468 		((TDS_NUMERIC *) dest)->precision = drec_ixd->sql_desc_precision;
469 		((TDS_NUMERIC *) dest)->scale = drec_ixd->sql_desc_scale;
470 	case SYBINTN:
471 	case SYBINT1:
472 	case SYBINT2:
473 	case SYBINT4:
474 	case SYBINT8:
475 	case SYBFLT8:
476 	case SYBDATETIME:
477 	case SYBBIT:
478 	case SYBMONEY4:
479 	case SYBMONEY:
480 	case SYBDATETIME4:
481 	case SYBREAL:
482 	case SYBBITN:
483 	case SYBFLTN:
484 	case SYBMONEYN:
485 	case SYBDATETIMN:
486 	case SYBSINT1:
487 	case SYBUINT2:
488 	case SYBUINT4:
489 	case SYBUINT8:
490 	case SYBUNIQUE:
491 	case SYBMSTIME:
492 	case SYBMSDATE:
493 	case SYBMSDATETIME2:
494 	case SYBMSDATETIMEOFFSET:
495 	case SYB5BIGTIME:
496 	case SYB5BIGDATETIME:
497 		res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, (CONV_RESULT*) dest);
498 		break;
499 	default:
500 	case SYBVOID:
501 	case SYBVARIANT:
502 		/* TODO ODBC 3.5 */
503 		assert(0);
504 		res = -1;
505 		break;
506 	}
507 
508 	free(converted_src);
509 	if (res < 0) {
510 		odbc_convert_err_set(&stmt->errs, res);
511 		return SQL_ERROR;
512 	}
513 
514 	curcol->column_cur_size = res;
515 
516 	return SQL_SUCCESS;
517 }
518