1 /**
2     Copyright (C) 1995, 1996 by Ke Jin <kejin@visigenic.com>
3 	Enhanced for unixODBC (1999) by Peter Harvey <pharvey@codebydesign.com>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program 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
13     GNU General Public License for more details.
14 **/
15 #include <config.h>
16 #include "driver.h"
17 
18 /* It looks silly to use a MEM_ALLOC() in function char2str(), etc,
19  * for converting C data type into STRING SQL data type. Esspecially
20  * for char2str(), simply return the C data buffer address seems can
21  * do the same thing. However, all these 'to STRING' functions are
22  * assumed to be invoked in SQLExecute(), etc. According to ODBC, after
23  * that, user buffers are detached from the statement been executed.
24  * For example, for a statement:
25  *
26  *  "SELECT FROM comp.databases WHERE subject LIKE ?"
27  *
28  * You may bind a SQL_C_CHAR data to it as the pattern for the
29  * LIKE condition. After SQLExecute(), the user buffer should be
30  * detached from the statement. You can change the data in that
31  * buffer without worry about the SQLFetch() results will be
32  * affected. If we don't use a separate buffer to keep the user
33  * data at SQLExecute() time but only keep a pointer of user buffer,
34  * then when user changes data in user buffer after SQLExecute()
35  * but before or during SQLFetch()s, the SQLFetch()'s result will
36  * be affected as a result of the change of LIKE condition.
37  *
38  * These allocated memory will be released by SQL layer.
39  */
40 
41 typedef DATE_STRUCT	odbc_date_t;
42 
char2str(char * buf,int size)43 char*	char2str( char* buf, int size )
44 {
45 	char*	ptr;
46 	int	len;
47 
48 	if( size < 0 )
49 		size = STRLEN(buf);
50 
51 	ptr = (char*)MEM_ALLOC(size + 1);
52 
53 	if( ! ptr )
54 		return (char*)(-1);
55 
56 	STRNCPY(ptr, buf, size+1);
57 	ptr[size] = 0;
58 
59 	return ptr;
60 }
61 
char2num(char * buf,int size)62 char*	char2num( char* buf, int size)
63 {
64 	char	tbuf[16];
65 
66 	if( size < 0 )
67 		size = strlen(buf);
68 
69 	if( size>15 )
70 		size = 15;
71 
72 	STRNCPY(tbuf, buf, size);
73 
74 	tbuf[15] = 0;
75 
76 	return (char*)atol(tbuf);
77 }
78 
char2date(char * buf,int size,date_t * dt)79 char*	char2date( char* buf, int size, date_t* dt)
80 {
81 	char	tbuf[16];
82 
83 	if( size < 0 )
84 		size = strlen(buf);
85 
86 	if( size > 15 )
87 		size = 15;
88 
89 	STRNCPY( tbuf, buf, size);
90 
91 	tbuf[15] = 0;
92 
93 	if( nnsql_odbcdatestr2date(tbuf, dt) )
94 		return (char*)(-1);
95 
96 	return (char*)dt;
97 }
98 
date2str(odbc_date_t * dt)99 char*	date2str( odbc_date_t* dt )
100 {
101 	char*	ptr;
102 
103 	if( dt->year < 0 || dt->year > 9999
104 	 || dt->month< 1 || dt->month> 12
105 	 || dt->day  < 1 || dt->day  > 31
106 	 || !( ptr = (char*)MEM_ALLOC(12)) )
107 		return (char*)(-1);
108 
109 	sprintf(ptr, "%04d-%02d-%02d", dt->year, dt->month, dt->day);
110 
111 	return ptr;
112 }
113 
odate2date(odbc_date_t * odt,int size,date_t * dt)114 char*	odate2date( odbc_date_t* odt, int size, date_t* dt )
115 {
116 	if( dt->year < 0 || dt->year > 9999
117 	 || dt->month< 1 || dt->month> 12
118 	 || dt->day  < 1 || dt->day  > 31 )
119 		return (char*)(-1);
120 
121 	dt->year = odt->year;
122 	dt->month= odt->month;
123 	dt->day  = odt->day;
124 
125 	return (char*)dt;
126 }
127 
tint2num(char * d)128 char*	tint2num( char* d )
129 {
130 	long	num = *d;
131 
132 	return (char*)num;
133 }
134 
short2num(short * d)135 char*	short2num( short* d )
136 {
137 	long	num = *d;
138 
139 	return (char*)num;
140 }
141 
long2num(long * d)142 char*	long2num( long* d )
143 {
144 	return (char*)*d;
145 }
146 
tint2str(char * d)147 char*	tint2str( char* d )
148 {
149 	int	c = *d;
150 	char*	ptr;
151 
152 	if( ! (ptr = MEM_ALLOC(5)) )
153 		return (char*)(-1);
154 
155 	sprintf(ptr, "%d", c);
156 
157 	return ptr;
158 }
159 
short2str(short * d)160 char*	short2str( short* d )
161 {
162 	int	c = *d;
163 	char*	ptr;
164 
165 	if( ! (ptr = MEM_ALLOC(32)) )
166 		return (char*)(-1);
167 
168 	sprintf(ptr, "%d", c);
169 
170 	return ptr;
171 }
172 
long2str(long * d)173 char*	long2str( long* d )
174 {
175 	long	l = *d;
176 	char*	ptr;
177 
178 	if( ! (ptr = MEM_ALLOC(64)) )
179 		return (char*)(-1);
180 
181 	sprintf(ptr, "%ld", l);
182 
183 	return ptr;
184 }
185 
186 static fptr_t	c2sql_cvt_tab[5][3] =
187 {
188 	char2str,  char2num, char2date,
189 	tint2str,  tint2num, 0,
190 	short2str, short2num,0,
191 	long2str,  long2num, 0,
192 	date2str,  0,	     odate2date
193 };
194 
195 static	struct {
196 	int	ctype;
197 	int	idx;
198 } ctype_idx_tab[] =
199 {
200 	SQL_C_CHAR,	0,
201 
202 	SQL_C_TINYINT,	1,
203 	SQL_C_STINYINT, 1,
204 	SQL_C_UTINYINT, 1,
205 
206 	SQL_C_SHORT,	2,
207 	SQL_C_SSHORT,	2,
208 	SQL_C_USHORT,	2,
209 
210 	SQL_C_LONG,	3,
211 	SQL_C_SLONG,	3,
212 	SQL_C_ULONG,	3,
213 
214 	SQL_C_DATE,	4
215 };
216 
217 static	struct {
218 	int	sqltype;
219 	int	idx;
220 } sqltype_idx_tab[] =
221 {
222 	SQL_CHAR,	0,
223 	SQL_VARCHAR,	0,
224 	SQL_LONGVARCHAR,0,
225 
226 	SQL_TINYINT,	1,
227 	SQL_SMALLINT,	1,
228 	SQL_INTEGER,	1,
229 
230 	SQL_DATE,	2
231 };
232 
nnodbc_get_c2sql_cvt(int ctype,int sqltype)233 fptr_t	nnodbc_get_c2sql_cvt(int ctype, int sqltype)
234 {
235 	int	i, cidx = -1, sqlidx = -1;
236 
237 	for(i=0; i< sizeof(ctype_idx_tab) / sizeof(ctype_idx_tab[ 0 ]); i++ )
238 	{
239 		if( ctype_idx_tab[i].ctype == ctype )
240 		{
241 			cidx = ctype_idx_tab[i].idx;
242 			break;
243 		}
244 	}
245 
246 	if( cidx == -1 )
247 		return 0;
248 
249 	for(i=0; i< sizeof(sqltype_idx_tab) / sizeof(sqltype_idx_tab[ 0 ]); i++ )
250 	{
251 		if( sqltype_idx_tab[i].sqltype == sqltype )
252 		{
253 			sqlidx = sqltype_idx_tab[i].idx;
254 			break;
255 		}
256 	}
257 
258 	if( sqlidx == -1 )
259 		return 0;
260 
261 	return	c2sql_cvt_tab[cidx][sqlidx];
262 }
263 
str2char(char * ptr,char * buf,long size,long * psize)264 static char*	str2char( char* ptr, char* buf, long size, long* psize)
265 {
266 	long	len;
267 
268 	len = STRLEN(ptr) + 1;
269 
270 	if( len > size )
271 		len = size;
272 
273 	if( len )
274 	{
275 		STRNCPY( buf, ptr, len );
276 		buf[len - 1] = 0;
277 	}
278 
279 	*psize = len;
280 
281 	return 0;
282 }
283 
str2tint(char * ptr,char * buf,long size,long * psize)284 static char*	str2tint( char* ptr, char* buf, long size, long* psize )
285 {
286 	unsigned long	a, b = (unsigned char)(-1);
287 
288 	a = (unsigned long)atol(ptr);
289 
290 	if( a > b )
291 	{
292 		*psize = a;
293 		return (char*)(-1);
294 	}
295 
296 	*buf = (char)a;
297 
298 	return 0;
299 }
300 
str2short(char * ptr,short * buf,long size,long * psize)301 static char*	str2short( char* ptr, short* buf, long size, long* psize)
302 {
303 	unsigned long a, b = (unsigned short)(-1);
304 
305 	a = atoi(ptr);
306 
307 	if( a > b )
308 	{
309 		*psize = a;
310 		return (char*)(-1);
311 	}
312 
313 	*buf = (short)a;
314 
315 	return 0;
316 }
317 
str2long(char * ptr,long * buf)318 static char*	str2long( char* ptr, long* buf)
319 {
320 	*buf = atol(ptr);
321 	return 0;
322 }
323 
str2date(char * ptr,odbc_date_t * buf)324 static char*	str2date( char* ptr, odbc_date_t* buf )
325 {
326 	date_t	dt;
327 
328 	if( nnsql_nndatestr2date(ptr, &dt) )
329 		return (char*)(-1);
330 
331 	buf->year = dt.year;
332 	buf->month= dt.month;
333 	buf->day  = dt.day;
334 
335 	return 0;
336 }
337 
num2char(long x,char * buf,long size,long * psize)338 static char*	num2char( long x, char* buf, long size, long* psize)
339 {
340 	char	tbuf[48];
341 
342 	sprintf(tbuf, "%ld", x);
343 
344 	*psize = STRLEN(buf) + 1;
345 
346 	if(*psize > size )
347 		return (char*)(-1);
348 
349 	STRCPY(buf, tbuf);
350 
351 	return 0;
352 }
353 
num2tint(long x,char * buf,long size,long * psize)354 static char*	num2tint(long x, char* buf, long size, long* psize)
355 {
356 	unsigned long	a = x, b = (unsigned char)(-1);
357 
358 	if( a > b )
359 	{
360 		*psize = x;
361 		return (char*)(-1);
362 	}
363 
364 	*buf = (char)x;
365 
366 	return 0;
367 }
368 
num2short(long x,short * buf,long size,long * psize)369 static char*	num2short(long x, short* buf, long size, long* psize)
370 {
371 	unsigned long a = x, b = (unsigned short)(-1);
372 
373 	if( a > b)
374 	{
375 		*psize = x;
376 		return (char*)(-1);
377 	}
378 
379 	*buf = (short)x;
380 
381 	return 0;
382 }
383 
num2long(long x,long * buf)384 static char*	num2long(long x, long* buf )
385 {
386 	*buf = x;
387 
388 	return 0;
389 }
390 
date2char(date_t * dt,char * buf,long size,long * psize)391 static char*	date2char(date_t* dt, char* buf, long size, long* psize)
392 {
393 	*psize = 11;
394 
395 	if(size < 11)
396 		return (char*)(-1);
397 
398 	sprintf(buf, "%04d-%02d-%02d", dt->year, dt->month, dt->day);
399 
400 	return 0;
401 }
402 
date2odate(date_t * dt,odbc_date_t * buf)403 static char*	date2odate(date_t* dt, odbc_date_t* buf)
404 {
405 	buf->year = dt->year;
406 	buf->month= dt->month;
407 	buf->day  = dt->day;
408 
409 	return 0;
410 }
411 
412 static	fptr_t	sql2c_cvt_tab[3][5] =
413 {
414 	str2char,  str2tint, str2short, str2long, str2date,
415 	num2char,  num2tint, num2short, num2long, 0,
416 	date2char, 0,	     0, 	0,	  date2odate
417 };
418 
nnodbc_get_sql2c_cvt(int sqltype,int ctype)419 fptr_t	nnodbc_get_sql2c_cvt(int sqltype, int ctype)
420 {
421 	int	i, cidx = -1, sqlidx = -1;
422 
423 	for(i=0; i< sizeof(ctype_idx_tab) / sizeof(ctype_idx_tab[ 0 ]); i++ )
424 	{
425 		if( ctype_idx_tab[i].ctype == ctype )
426 		{
427 			cidx = ctype_idx_tab[i].idx;
428 			break;
429 		}
430 	}
431 
432 	if( cidx == -1 )
433 		return 0;
434 
435 	for(i=0; i< sizeof(sqltype_idx_tab) / sizeof(sqltype_idx_tab[ 0 ]); i++ )
436 	{
437 		if( sqltype_idx_tab[i].sqltype == sqltype )
438 		{
439 			sqlidx = sqltype_idx_tab[i].idx;
440 			break;
441 		}
442 	}
443 
444 	if( sqlidx == -1 )
445 		return 0;
446 
447 	return	sql2c_cvt_tab[sqlidx][cidx];
448 }
449