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 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 : #include <assert.h>
26 :
27 : #if HAVE_STDLIB_H
28 : #include <stdlib.h>
29 : #endif /* HAVE_STDLIB_H */
30 :
31 : #if HAVE_STRING_H
32 : #include <string.h>
33 : #endif /* HAVE_STRING_H */
34 :
35 : #if TIME_WITH_SYS_TIME
36 : # if HAVE_SYS_TIME_H
37 : # include <sys/time.h>
38 : # endif
39 : # include <time.h>
40 : #else
41 : # if HAVE_SYS_TIME_H
42 : # include <sys/time.h>
43 : # else
44 : # include <time.h>
45 : # endif
46 : #endif
47 :
48 : #include "tdsodbc.h"
49 : #include "tdsconvert.h"
50 :
51 : #ifdef DMALLOC
52 : #include <dmalloc.h>
53 : #endif
54 :
55 : TDS_RCSID(var, "$Id: sql2tds.c,v 1.51.2.3 2007/12/21 11:19:05 freddy77 Exp $");
56 :
57 : static TDS_INT
58 : convert_datetime2server(int bindtype, const void *src, TDS_DATETIME * dt)
59 6 : {
60 : struct tds_time src_tm;
61 : unsigned int dt_time;
62 : TDS_INT dt_days;
63 : int i;
64 6 : int got_date = 1;
65 : time_t curr_time;
66 :
67 6 : const DATE_STRUCT *src_date = (const DATE_STRUCT *) src;
68 6 : const TIME_STRUCT *src_time = (const TIME_STRUCT *) src;
69 6 : const TIMESTAMP_STRUCT *src_timestamp = (const TIMESTAMP_STRUCT *) src;
70 :
71 6 : switch (bindtype) {
72 : case SQL_C_DATE:
73 : case SQL_C_TYPE_DATE:
74 2 : src_tm.tm_year = src_date->year - 1900;
75 2 : src_tm.tm_mon = src_date->month - 1;
76 2 : src_tm.tm_mday = src_date->day;
77 2 : src_tm.tm_hour = 0;
78 2 : src_tm.tm_min = 0;
79 2 : src_tm.tm_sec = 0;
80 2 : src_tm.tm_ms = 0;
81 2 : break;
82 : case SQL_C_TIME:
83 : case SQL_C_TYPE_TIME:
84 2 : got_date = 0;
85 : #if HAVE_GETTIMEOFDAY
86 : {
87 : struct timeval tv;
88 2 : gettimeofday(&tv, NULL);
89 2 : curr_time = tv.tv_sec;
90 : }
91 : #else
92 : curr_time = time(NULL);
93 : #endif
94 2 : dt_days = (curr_time / 86400u) + (70u * 365u + 17u);
95 2 : src_tm.tm_hour = src_time->hour;
96 2 : src_tm.tm_min = src_time->minute;
97 2 : src_tm.tm_sec = src_time->second;
98 2 : src_tm.tm_ms = 0;
99 2 : break;
100 : case SQL_C_TIMESTAMP:
101 : case SQL_C_TYPE_TIMESTAMP:
102 2 : src_tm.tm_year = src_timestamp->year - 1900;
103 2 : src_tm.tm_mon = src_timestamp->month - 1;
104 2 : src_tm.tm_mday = src_timestamp->day;
105 2 : src_tm.tm_hour = src_timestamp->hour;
106 2 : src_tm.tm_min = src_timestamp->minute;
107 2 : src_tm.tm_sec = src_timestamp->second;
108 2 : src_tm.tm_ms = src_timestamp->fraction / 1000000lu;
109 2 : break;
110 : default:
111 0 : return TDS_FAIL;
112 : }
113 :
114 : /* TODO code copied from convert.c, function */
115 6 : if (got_date) {
116 4 : i = (src_tm.tm_mon - 13) / 12;
117 4 : dt_days = 1461 * (src_tm.tm_year + 300 + i) / 4 +
118 : (367 * (src_tm.tm_mon - 1 - 12 * i)) / 12 - (3 * ((src_tm.tm_year + 400 + i) / 100)) / 4 +
119 : src_tm.tm_mday - 109544;
120 : }
121 :
122 6 : dt->dtdays = dt_days;
123 6 : dt_time = (src_tm.tm_hour * 60 + src_tm.tm_min) * 60 + src_tm.tm_sec;
124 6 : dt->dttime = dt_time * 300 + (src_tm.tm_ms * 300 / 1000);
125 6 : return sizeof(TDS_DATETIME);
126 : }
127 :
128 : /**
129 : * Convert parameters to libtds format
130 : * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
131 : */
132 : SQLRETURN
133 : sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ipd, const struct _drecord *drec_apd, TDSPARAMINFO * info, int nparam,
134 : int compute_row, const TDS_DESC* axd, unsigned int n_row)
135 432 : {
136 432 : TDS_DBC * dbc = stmt->dbc;
137 : int dest_type, src_type, sql_src_type, res;
138 : CONV_RESULT ores;
139 : TDSBLOB *blob;
140 : char *src;
141 : unsigned char *dest;
142 432 : TDSCOLUMN *curcol = info->columns[nparam];
143 : int len;
144 : TDS_DATETIME dt;
145 : TDS_NUMERIC num;
146 : SQL_NUMERIC_STRUCT *sql_num;
147 : SQLINTEGER sql_len;
148 432 : int need_data = 0, i;
149 :
150 : /* TODO handle bindings of char like "{d '2002-11-12'}" */
151 432 : tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ipd->sql_desc_concise_type);
152 :
153 : /* what type to convert ? */
154 432 : dest_type = odbc_sql_to_server_type(dbc->tds_socket, drec_ipd->sql_desc_concise_type);
155 432 : if (dest_type == TDS_FAIL)
156 0 : return SQL_ERROR;
157 432 : tdsdump_log(TDS_DBG_INFO2, "trace\n");
158 :
159 : /* TODO what happen for unicode types ?? */
160 432 : tds_set_param_type(dbc->tds_socket, curcol, dest_type);
161 432 : if (is_numeric_type(curcol->column_type)) {
162 8 : curcol->column_prec = drec_ipd->sql_desc_precision;
163 8 : curcol->column_scale = drec_ipd->sql_desc_scale;
164 8 : ores.n.precision = drec_ipd->sql_desc_precision;
165 8 : ores.n.scale = drec_ipd->sql_desc_scale;
166 : }
167 :
168 432 : if (drec_ipd->sql_desc_parameter_type != SQL_PARAM_INPUT)
169 32 : curcol->column_output = 1;
170 :
171 : /* compute destination length */
172 432 : if (curcol->column_varint_size != 0) {
173 : /* curcol->column_size = drec_apd->sql_desc_octet_length; */
174 : /*
175 : * TODO destination length should come from sql_desc_length,
176 : * however there is the encoding problem to take into account
177 : * we should fill destination length after conversion keeping
178 : * attention to fill correctly blob/fixed type/variable type
179 : */
180 : /* TODO location of this test is correct here ?? */
181 348 : if (dest_type != SYBUNIQUE && dest_type != SYBBITN && !is_fixed_type(dest_type)) {
182 210 : curcol->column_cur_size = 0;
183 210 : curcol->column_size = drec_ipd->sql_desc_length;
184 210 : if (curcol->column_size < 0)
185 2 : curcol->column_size = 0x7FFFFFFFl;
186 : }
187 84 : } else if (dest_type != SYBBIT) {
188 : /* TODO only a trick... */
189 82 : tds_set_param_type(dbc->tds_socket, curcol, tds_get_null_type(dest_type));
190 : }
191 :
192 : /* get C type */
193 432 : sql_src_type = drec_apd->sql_desc_concise_type;
194 432 : if (sql_src_type == SQL_C_DEFAULT)
195 0 : sql_src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
196 :
197 : /* test source type */
198 : /* TODO test intervals */
199 432 : src_type = odbc_c_to_server_type(sql_src_type);
200 432 : if (src_type == TDS_FAIL)
201 0 : return SQL_ERROR;
202 :
203 : /* we have no data to convert, just return */
204 432 : if (!compute_row)
205 15 : return TDS_SUCCEED;
206 :
207 417 : src = drec_apd->sql_desc_data_ptr;
208 417 : if (src && n_row) {
209 : SQLLEN len;
210 :
211 108 : if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
212 0 : len = axd->header.sql_desc_bind_type;
213 0 : if (axd->header.sql_desc_bind_offset_ptr)
214 0 : src += *axd->header.sql_desc_bind_offset_ptr;
215 : } else {
216 108 : len = odbc_get_octet_len(sql_src_type, drec_apd);
217 108 : if (len < 0)
218 : /* TODO sure ? what happen to upper layer ?? */
219 0 : return SQL_ERROR;
220 : }
221 108 : src += len * n_row;
222 : }
223 :
224 : /* if only output assume input is NULL */
225 417 : if (drec_ipd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
226 32 : sql_len = SQL_NULL_DATA;
227 : } else {
228 385 : sql_len = odbc_get_param_len(drec_apd, drec_ipd, axd, n_row);
229 :
230 : /* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
231 385 : if (src_type == SYBVARCHAR && sql_len == 1 && drec_ipd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
232 : && src && *src == 0) {
233 0 : sql_len = SQL_NULL_DATA;
234 : }
235 : }
236 :
237 : /* compute source length */
238 417 : switch (sql_len) {
239 : case SQL_NULL_DATA:
240 32 : len = 0;
241 32 : break;
242 : case SQL_NTS:
243 229 : len = strlen(src);
244 229 : break;
245 : case SQL_DEFAULT_PARAM:
246 : case SQL_DATA_AT_EXEC:
247 : /* TODO */
248 0 : return SQL_ERROR;
249 : break;
250 : default:
251 156 : len = sql_len;
252 156 : if (sql_len < 0) {
253 : /* test for SQL_C_CHAR/SQL_C_BINARY */
254 6 : switch (sql_src_type) {
255 : case SQL_C_CHAR:
256 : case SQL_C_BINARY:
257 : break;
258 : default:
259 0 : return SQL_ERROR;
260 : }
261 6 : len = SQL_LEN_DATA_AT_EXEC(sql_len);
262 6 : need_data = 1;
263 :
264 : /* dynamic length allowed only for BLOB fields */
265 6 : switch (drec_ipd->sql_desc_concise_type) {
266 : case SQL_LONGVARCHAR:
267 : case SQL_LONGVARBINARY:
268 6 : break;
269 : default:
270 0 : return SQL_ERROR;
271 : }
272 : }
273 : }
274 :
275 : /* allocate given space */
276 417 : if (!tds_alloc_param_row(info, curcol))
277 0 : return SQL_ERROR;
278 :
279 417 : if (need_data) {
280 6 : curcol->column_cur_size = 0;
281 6 : return SQL_NEED_DATA;
282 : }
283 :
284 : /* set null */
285 411 : assert(drec_ipd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
286 411 : if (sql_len == SQL_NULL_DATA) {
287 32 : curcol->column_cur_size = -1;
288 32 : return TDS_SUCCEED;
289 : }
290 :
291 : /* convert special parameters (not libTDS compatible) */
292 379 : switch (src_type) {
293 : case SYBDATETIME:
294 6 : convert_datetime2server(drec_apd->sql_desc_concise_type, src, &dt);
295 6 : src = (char *) &dt;
296 6 : break;
297 : case SYBDECIMAL:
298 : case SYBNUMERIC:
299 2 : sql_num = (SQL_NUMERIC_STRUCT *) src;
300 2 : num.precision = sql_num->precision;
301 2 : num.scale = sql_num->scale;
302 2 : num.array[0] = sql_num->sign ^ 1;
303 : /* test precision so client do not crash our library */
304 2 : if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
305 : /* TODO add proper error */
306 0 : return SQL_ERROR;
307 2 : i = tds_numeric_bytes_per_prec[num.precision];
308 2 : memcpy(num.array + 1, sql_num->val, i - 1);
309 2 : tds_swap_bytes(num.array + 1, i - 1);
310 2 : if (i < sizeof(num.array))
311 2 : memset(num.array + i, 0, sizeof(num.array) - i);
312 2 : src = (char *) #
313 : break;
314 : /* TODO intervals */
315 : }
316 :
317 379 : res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
318 379 : if (res < 0)
319 0 : return SQL_ERROR;
320 379 : tdsdump_log(TDS_DBG_INFO2, "trace\n");
321 :
322 : /* truncate ?? */
323 : /* TODO what happen for blobs ?? */
324 379 : if (res > curcol->column_size)
325 2 : res = curcol->column_size;
326 379 : curcol->column_cur_size = res;
327 :
328 : /* free allocated memory */
329 379 : dest = &info->current_row[curcol->column_offset];
330 379 : switch ((TDS_SERVER_TYPE) dest_type) {
331 : case SYBCHAR:
332 : case SYBVARCHAR:
333 : case XSYBCHAR:
334 : case XSYBVARCHAR:
335 170 : memcpy(&info->current_row[curcol->column_offset], ores.c, res);
336 170 : free(ores.c);
337 170 : break;
338 : case SYBTEXT:
339 5 : blob = (TDSBLOB *) dest;
340 5 : if (blob->textvalue)
341 0 : free(blob->textvalue);
342 5 : blob->textvalue = ores.c;
343 5 : break;
344 : case SYBBINARY:
345 : case SYBVARBINARY:
346 : case XSYBBINARY:
347 : case XSYBVARBINARY:
348 0 : memcpy(&info->current_row[curcol->column_offset], ores.ib, res);
349 0 : free(ores.ib);
350 0 : break;
351 : case SYBLONGBINARY:
352 : case SYBIMAGE:
353 2 : blob = (TDSBLOB *) dest;
354 2 : if (blob->textvalue)
355 0 : free(blob->textvalue);
356 2 : blob->textvalue = ores.ib;
357 2 : break;
358 : case SYBNUMERIC:
359 : case SYBDECIMAL:
360 : /*
361 : * for these types we ignore column_size so fix it in case
362 : * we overwrote it
363 : */
364 2 : res = sizeof(TDS_NUMERIC);
365 : case SYBINTN:
366 : case SYBINT1:
367 : case SYBINT2:
368 : case SYBINT4:
369 : case SYBINT8:
370 : case SYBFLT8:
371 : case SYBDATETIME:
372 : case SYBBIT:
373 : case SYBMONEY4:
374 : case SYBMONEY:
375 : case SYBDATETIME4:
376 : case SYBREAL:
377 : case SYBBITN:
378 : case SYBFLTN:
379 : case SYBMONEYN:
380 : case SYBDATETIMN:
381 : case SYBSINT1:
382 : case SYBUINT2:
383 : case SYBUINT4:
384 : case SYBUINT8:
385 : case SYBUNIQUE:
386 202 : memcpy(&info->current_row[curcol->column_offset], &ores, res);
387 202 : break;
388 : case XSYBNVARCHAR:
389 : case XSYBNCHAR:
390 : case SYBNVARCHAR:
391 : case SYBNTEXT:
392 : case SYBVOID:
393 : case SYBVARIANT:
394 : /* TODO ODBC 3.5 */
395 0 : assert(0);
396 : break;
397 : }
398 :
399 379 : return SQL_SUCCESS;
400 : }
|