1 /*--------
2  * Module:			pgtypes.c
3  *
4  * Description:		This module contains routines for getting information
5  *					about the supported Postgres data types.  Only the
6  *					function pgtype_to_sqltype() returns an unknown condition.
7  *					All other functions return a suitable default so that
8  *					even data types that are not directly supported can be
9  *					used (it is handled as char data).
10  *
11  * Classes:			n/a
12  *
13  * API functions:	none
14  *
15  * Comments:		See "readme.txt" for copyright and license information.
16  *--------
17  */
18 
19 #include "pgtypes.h"
20 
21 #include "dlg_specific.h"
22 #include "statement.h"
23 #include "connection.h"
24 #include "environ.h"
25 #include "qresult.h"
26 
27 #define	EXPERIMENTAL_CURRENTLY
28 
29 
ansi_to_wtype(const ConnectionClass * self,SQLSMALLINT ansitype)30 SQLSMALLINT ansi_to_wtype(const ConnectionClass *self, SQLSMALLINT ansitype)
31 {
32 #ifndef	UNICODE_SUPPORT
33 	return ansitype;
34 #else
35 	if (!ALLOW_WCHAR(self))
36 		return ansitype;
37 	switch (ansitype)
38 	{
39 		case SQL_CHAR:
40 			return SQL_WCHAR;
41 		case SQL_VARCHAR:
42 			return SQL_WVARCHAR;
43 		case SQL_LONGVARCHAR:
44 			return SQL_WLONGVARCHAR;
45 	}
46 	return ansitype;
47 #endif /* UNICODE_SUPPORT */
48 }
49 
50 Int4		getCharColumnSize(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as);
51 
52 /*
53  * these are the types we support.	all of the pgtype_ functions should
54  * return values for each one of these.
55  * Even types not directly supported are handled as character types
56  * so all types should work (points, etc.)
57  */
58 
59 /*
60  * ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo.  Instead, all
61  *	the SQL TYPES are reported and mapped to a corresponding Postgres Type
62  */
63 
64 /*
65 OID pgtypes_defined[][2] = {
66 			{PG_TYPE_CHAR, 0}
67 			,{PG_TYPE_CHAR2, 0}
68 			,{PG_TYPE_CHAR4, 0}
69 			,{PG_TYPE_CHAR8, 0}
70 			,{PG_TYPE_CHAR16, 0}
71 			,{PG_TYPE_NAME, 0}
72 			,{PG_TYPE_VARCHAR, 0}
73 			,{PG_TYPE_BPCHAR, 0}
74 			,{PG_TYPE_DATE, 0}
75 			,{PG_TYPE_TIME, 0}
76 			,{PG_TYPE_TIME_WITH_TMZONE, 0}
77 			,{PG_TYPE_DATETIME, 0}
78 			,{PG_TYPE_ABSTIME, 0}
79 			,{PG_TYPE_TIMESTAMP_NO_TMZONE, 0}
80 			,{PG_TYPE_TIMESTAMP, 0}
81 			,{PG_TYPE_TEXT, 0}
82 			,{PG_TYPE_INT2, 0}
83 			,{PG_TYPE_INT4, 0}
84 			,{PG_TYPE_FLOAT4, 0}
85 			,{PG_TYPE_FLOAT8, 0}
86 			,{PG_TYPE_OID, 0}
87 			,{PG_TYPE_MONEY, 0}
88 			,{PG_TYPE_BOOL, 0}
89 			,{PG_TYPE_BYTEA, 0}
90 			,{PG_TYPE_NUMERIC, 0}
91 			,{PG_TYPE_XID, 0}
92 			,{PG_TYPE_LO_UNDEFINED, 0}
93 			,{0, 0} };
94 */
95 
96 
97 /*	These are NOW the SQL Types reported in SQLGetTypeInfo.  */
98 SQLSMALLINT	sqlTypes[] = {
99 	SQL_BIGINT,
100 	/* SQL_BINARY, -- Commented out because VarBinary is more correct. */
101 	SQL_BIT,
102 	SQL_CHAR,
103 	SQL_TYPE_DATE,
104 	SQL_DATE,
105 	SQL_DECIMAL,
106 	SQL_DOUBLE,
107 	SQL_FLOAT,
108 	SQL_INTEGER,
109 	SQL_LONGVARBINARY,
110 	SQL_LONGVARCHAR,
111 	SQL_NUMERIC,
112 	SQL_REAL,
113 	SQL_SMALLINT,
114 	SQL_TYPE_TIME,
115 	SQL_TYPE_TIMESTAMP,
116 	SQL_TIME,
117 	SQL_TIMESTAMP,
118 	SQL_TINYINT,
119 	SQL_VARBINARY,
120 	SQL_VARCHAR,
121 #ifdef	UNICODE_SUPPORT
122 	SQL_WCHAR,
123 	SQL_WVARCHAR,
124 	SQL_WLONGVARCHAR,
125 #endif /* UNICODE_SUPPORT */
126 	SQL_GUID,
127 /* AFAIK SQL_INTERVAL types cause troubles in some spplications */
128 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
129 	SQL_INTERVAL_MONTH,
130 	SQL_INTERVAL_YEAR,
131 	SQL_INTERVAL_YEAR_TO_MONTH,
132 	SQL_INTERVAL_DAY,
133 	SQL_INTERVAL_HOUR,
134 	SQL_INTERVAL_MINUTE,
135 	SQL_INTERVAL_SECOND,
136 	SQL_INTERVAL_DAY_TO_HOUR,
137 	SQL_INTERVAL_DAY_TO_MINUTE,
138 	SQL_INTERVAL_DAY_TO_SECOND,
139 	SQL_INTERVAL_HOUR_TO_MINUTE,
140 	SQL_INTERVAL_HOUR_TO_SECOND,
141 	SQL_INTERVAL_MINUTE_TO_SECOND,
142 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
143 	0
144 };
145 
146 #ifdef ODBCINT64
147 #define	ALLOWED_C_BIGINT	SQL_C_SBIGINT
148 /* #define	ALLOWED_C_BIGINT	SQL_C_CHAR */ /* Delphi should be either ? */
149 #else
150 #define	ALLOWED_C_BIGINT	SQL_C_CHAR
151 #endif
152 
153 OID
pg_true_type(const ConnectionClass * conn,OID type,OID basetype)154 pg_true_type(const ConnectionClass *conn, OID type, OID basetype)
155 {
156 	if (0 == basetype)
157 		return type;
158 	else if (0 == type)
159 		return basetype;
160 	else if (type == conn->lobj_type)
161 		return type;
162 	return basetype;
163 }
164 
165 #define MONTH_BIT 	(1 << 17)
166 #define YEAR_BIT	(1 << 18)
167 #define DAY_BIT		(1 << 19)
168 #define HOUR_BIT	(1 << 26)
169 #define MINUTE_BIT	(1 << 27)
170 #define SECOND_BIT	(1 << 28)
171 
172 static SQLSMALLINT
get_interval_type(Int4 atttypmod,const char ** name)173 get_interval_type(Int4 atttypmod, const char **name)
174 {
175 MYLOG(0, "entering atttypmod=%x\n", atttypmod);
176 	if ((-1) == atttypmod)
177 		return 0;
178 	if (0 != (YEAR_BIT & atttypmod))
179 	{
180 		if (0 != (MONTH_BIT & atttypmod))
181 		{
182 			if (name)
183 				*name = "interval year to month";
184 			return SQL_INTERVAL_YEAR_TO_MONTH;
185 		}
186 		if (name)
187 			*name = "interval year";
188 		return SQL_INTERVAL_YEAR;
189 	}
190 	else if (0 != (MONTH_BIT & atttypmod))
191 	{
192 		if (name)
193 			*name = "interval month";
194 		return SQL_INTERVAL_MONTH;
195 	}
196 	else if (0 != (DAY_BIT & atttypmod))
197 	{
198 		if (0 != (SECOND_BIT & atttypmod))
199 		{
200 			if (name)
201 				*name = "interval day to second";
202 			return SQL_INTERVAL_DAY_TO_SECOND;
203 		}
204 		else if (0 != (MINUTE_BIT & atttypmod))
205 		{
206 			if (name)
207 				*name = "interval day to minute";
208 			return SQL_INTERVAL_DAY_TO_MINUTE;
209 		}
210 		else if (0 != (HOUR_BIT & atttypmod))
211 		{
212 			if (name)
213 				*name = "interval day to hour";
214 			return SQL_INTERVAL_DAY_TO_HOUR;
215 		}
216 		if (name)
217 			*name = "interval day";
218 		return SQL_INTERVAL_DAY;
219 	}
220 	else if (0 != (HOUR_BIT & atttypmod))
221 	{
222 		if (0 != (SECOND_BIT & atttypmod))
223 		{
224 			if (name)
225 				*name = "interval hour to second";
226 			return SQL_INTERVAL_HOUR_TO_SECOND;
227 		}
228 		else if (0 != (MINUTE_BIT & atttypmod))
229 		{
230 			if (name)
231 				*name = "interval hour to minute";
232 			return SQL_INTERVAL_HOUR_TO_MINUTE;
233 		}
234 		if (name)
235 			*name = "interval hour";
236 		return SQL_INTERVAL_HOUR;
237 	}
238 	else if (0 != (MINUTE_BIT & atttypmod))
239 	{
240 		if (0 != (SECOND_BIT & atttypmod))
241 		{
242 			if (name)
243 				*name = "interval minute to second";
244 			return SQL_INTERVAL_MINUTE_TO_SECOND;
245 		}
246 		if (name)
247 			*name = "interval minute";
248 		return SQL_INTERVAL_MINUTE;
249 	}
250 	else if (0 != (SECOND_BIT & atttypmod))
251 	{
252 		if (name)
253 			*name = "interval second";
254 		return SQL_INTERVAL_SECOND;
255 	}
256 
257 	if (name)
258 		*name = "interval";
259 	return 0;
260 }
261 
262 static Int4
getCharColumnSizeX(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int handle_unknown_size_as)263 getCharColumnSizeX(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
264 {
265 	int		p = -1, maxsize;
266 	const ConnInfo	*ci = &(conn->connInfo);
267 
268 	MYLOG(0, "entering type=%d, atttypmod=%d, adtsize_or=%d, unknown = %d\n", type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
269 
270 	/* Assign Maximum size based on parameters */
271 	switch (type)
272 	{
273 		case PG_TYPE_TEXT:
274 			if (ci->drivers.text_as_longvarchar)
275 				maxsize = ci->drivers.max_longvarchar_size;
276 			else
277 				maxsize = ci->drivers.max_varchar_size;
278 			break;
279 
280 		case PG_TYPE_VARCHAR:
281 		case PG_TYPE_BPCHAR:
282 			maxsize = ci->drivers.max_varchar_size;
283 			break;
284 
285 		default:
286 			if (ci->drivers.unknowns_as_longvarchar)
287 				maxsize = ci->drivers.max_longvarchar_size;
288 			else
289 				maxsize = ci->drivers.max_varchar_size;
290 			break;
291 	}
292 #ifdef	UNICODE_SUPPORT
293 	if (CC_is_in_unicode_driver(conn) &&
294 	    isSqlServr() &&
295 	    maxsize > 4000)
296 		maxsize = 4000;
297 #endif /* UNICODE_SUPPORT */
298 
299 	if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
300 		maxsize = 0;
301 
302 	/*
303 	 * Static ColumnSize (i.e., the Maximum ColumnSize of the datatype) This
304 	 * has nothing to do with a result set.
305 	 */
306 MYLOG(DETAIL_LOG_LEVEL, "!!! atttypmod  < 0 ?\n");
307 	if (atttypmod < 0 && adtsize_or_longestlen < 0)
308 		return maxsize;
309 
310 MYLOG(DETAIL_LOG_LEVEL, "!!! adtsize_or_logngest=%d\n", adtsize_or_longestlen);
311 	p = adtsize_or_longestlen; /* longest */
312 	/*
313 	 * Catalog Result Sets -- use assigned column width (i.e., from
314 	 * set_tuplefield_string)
315 	 */
316 MYLOG(DETAIL_LOG_LEVEL, "!!! catalog_result=%d\n", handle_unknown_size_as);
317 	if (UNKNOWNS_AS_LONGEST == handle_unknown_size_as)
318 	{
319 		MYLOG(0, "LONGEST: p = %d\n", p);
320 		if (p > 0 &&
321 		    (atttypmod < 0 || atttypmod > p))
322 			return p;
323 	}
324 	if (TYPE_MAY_BE_ARRAY(type))
325 	{
326 		if (p > 0)
327 			return p;
328 		return maxsize;
329 	}
330 
331 	/* Size is unknown -- handle according to parameter */
332 	if (atttypmod > 0)	/* maybe the length is known */
333 	{
334 		return atttypmod;
335 	}
336 
337 	/* The type is really unknown */
338 	switch (handle_unknown_size_as)
339 	{
340 		case UNKNOWNS_AS_DONTKNOW:
341 			return -1;
342 		case UNKNOWNS_AS_LONGEST:
343 		case UNKNOWNS_AS_MAX:
344 			break;
345 		default:
346 			return -1;
347 	}
348 	if (maxsize <= 0)
349 		return maxsize;
350 	switch (type)
351 	{
352 		case PG_TYPE_BPCHAR:
353 		case PG_TYPE_VARCHAR:
354 		case PG_TYPE_TEXT:
355 			return maxsize;
356 	}
357 
358 	if (p > maxsize)
359 		maxsize = p;
360 	return maxsize;
361 }
362 
363 /*
364  *	Specify when handle_unknown_size_as parameter is unused
365  */
366 #define	UNUSED_HANDLE_UNKNOWN_SIZE_AS	(-2)
367 
368 static SQLSMALLINT
getNumericDecimalDigitsX(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longest,int UNUSED_handle_unknown_size_as)369 getNumericDecimalDigitsX(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longest, int UNUSED_handle_unknown_size_as)
370 {
371 	Int4		default_decimal_digits = 6;
372 
373 	MYLOG(0, "entering type=%d, atttypmod=%d\n", type, atttypmod);
374 
375 	if (atttypmod < 0 && adtsize_or_longest < 0)
376 		return default_decimal_digits;
377 
378 	if (atttypmod > -1)
379 		return (atttypmod & 0xffff);
380 	if (adtsize_or_longest <= 0)
381 		return default_decimal_digits;
382 	adtsize_or_longest >>= 16; /* extract the scale part */
383 	return adtsize_or_longest;
384 }
385 
386 static Int4	/* PostgreSQL restritiction */
getNumericColumnSizeX(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longest,int handle_unknown_size_as)387 getNumericColumnSizeX(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longest, int handle_unknown_size_as)
388 {
389 	Int4	default_column_size = 28;
390 	const ConnInfo	*ci = &(conn->connInfo);
391 
392 	MYLOG(0, "entering type=%d, typmod=%d\n", type, atttypmod);
393 
394 	if (atttypmod > -1)
395 		return (atttypmod >> 16) & 0xffff;
396 	switch (ci->numeric_as)
397 	{
398 		case SQL_VARCHAR:
399 			return ci->drivers.max_varchar_size;
400 		case SQL_LONGVARCHAR:
401 			return ci->drivers.max_longvarchar_size;
402 		case SQL_DOUBLE:
403 			return PG_DOUBLE_DIGITS;
404 	}
405 	switch (handle_unknown_size_as)
406 	{
407 		case UNKNOWNS_AS_DONTKNOW:
408 			return SQL_NO_TOTAL;
409 	}
410 	if (adtsize_or_longest <= 0)
411 		return default_column_size;
412 	adtsize_or_longest %= (1 << 16); /* extract the precision part */
413 	switch (handle_unknown_size_as)
414 	{
415 		case UNKNOWNS_AS_MAX:
416 			return adtsize_or_longest > default_column_size ? adtsize_or_longest : default_column_size;
417 		default:
418 			if (adtsize_or_longest < 10)
419 				adtsize_or_longest = 10;
420 	}
421 	return adtsize_or_longest;
422 }
423 
424 static SQLSMALLINT
getTimestampDecimalDigitsX(const ConnectionClass * conn,OID type,int atttypmod)425 getTimestampDecimalDigitsX(const ConnectionClass *conn, OID type, int atttypmod)
426 {
427 	MYLOG(0, "type=%d, atttypmod=%d\n", type, atttypmod);
428 	return (atttypmod > -1 ? atttypmod : 6);
429 }
430 
431 static SQLSMALLINT
getTimestampColumnSizeX(const ConnectionClass * conn,OID type,int atttypmod)432 getTimestampColumnSizeX(const ConnectionClass *conn, OID type, int atttypmod)
433 {
434 	Int4	fixed, scale;
435 
436 	MYLOG(0, "entering type=%d, atttypmod=%d\n", type, atttypmod);
437 
438 	switch (type)
439 	{
440 		case PG_TYPE_TIME:
441 			fixed = 8;
442 			break;
443 		case PG_TYPE_TIME_WITH_TMZONE:
444 			fixed = 11;
445 			break;
446 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
447 			fixed = 19;
448 			break;
449 		default:
450 			if (USE_ZONE)
451 				fixed = 22;
452 			else
453 				fixed = 19;
454 			break;
455 	}
456 	scale = getTimestampDecimalDigitsX(conn, type, atttypmod);
457 	return (scale > 0) ? fixed + 1 + scale : fixed;
458 }
459 
460 static SQLSMALLINT
getIntervalDecimalDigits(OID type,int atttypmod)461 getIntervalDecimalDigits(OID type, int atttypmod)
462 {
463 	Int4	prec;
464 
465 	MYLOG(0, "entering type=%d, atttypmod=%d\n", type, atttypmod);
466 
467 	if ((atttypmod & SECOND_BIT) == 0)
468 		return 0;
469 	return (prec = atttypmod & 0xffff) == 0xffff ? 6 : prec ;
470 }
471 
472 static SQLSMALLINT
getIntervalColumnSize(OID type,int atttypmod)473 getIntervalColumnSize(OID type, int atttypmod)
474 {
475 	Int4	ttl, leading_precision = 9, scale;
476 
477 	MYLOG(0, "entering type=%d, atttypmod=%d\n", type, atttypmod);
478 
479 	ttl = leading_precision;
480 	switch (get_interval_type(atttypmod, NULL))
481 	{
482 		case 0:
483 			ttl = 25;
484 			break;
485 		case SQL_INTERVAL_YEAR:
486 			ttl = 16;
487 			break;
488 		case SQL_INTERVAL_MONTH:
489 			ttl = 16;
490 			break;
491 		case SQL_INTERVAL_DAY:
492 			ttl = 16;
493 			break;
494 		case SQL_INTERVAL_DAY_TO_SECOND:
495 		case SQL_INTERVAL_DAY_TO_MINUTE:
496 		case SQL_INTERVAL_DAY_TO_HOUR:
497 			ttl = 25;
498 			break;
499 		case SQL_INTERVAL_HOUR_TO_SECOND:
500 		case SQL_INTERVAL_HOUR_TO_MINUTE:
501 		case SQL_INTERVAL_HOUR:
502 			ttl = 17;
503 			break;
504 		case SQL_INTERVAL_MINUTE_TO_SECOND:
505 		case SQL_INTERVAL_MINUTE:
506 			ttl = 15;
507 			break;
508 		case SQL_INTERVAL_YEAR_TO_MONTH:
509 			ttl = 24;
510 			break;
511 	}
512 	scale = getIntervalDecimalDigits(type, atttypmod);
513 	return (scale > 0) ? ttl + 1 + scale : ttl;
514 }
515 
516 
517 SQLSMALLINT
pgtype_attr_to_concise_type(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int handle_unknown_size_as)518 pgtype_attr_to_concise_type(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
519 {
520 	const ConnInfo	*ci = &(conn->connInfo);
521 	EnvironmentClass *env = (EnvironmentClass *) CC_get_env(conn);
522 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
523 	SQLSMALLINT	sqltype;
524 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
525 	BOOL	bLongVarchar, bFixed = FALSE;
526 
527 	switch (type)
528 	{
529 		case PG_TYPE_CHAR:
530 			return ansi_to_wtype(conn, SQL_CHAR);
531 		case PG_TYPE_NAME:
532 		case PG_TYPE_REFCURSOR:
533 			return ansi_to_wtype(conn, SQL_VARCHAR);
534 
535 		case PG_TYPE_BPCHAR:
536 			bFixed = TRUE;
537 		case PG_TYPE_VARCHAR:
538 			if (getCharColumnSizeX(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as) > ci->drivers.max_varchar_size)
539 				bLongVarchar = TRUE;
540 			else
541 				bLongVarchar = FALSE;
542 			return ansi_to_wtype(conn, bLongVarchar ? SQL_LONGVARCHAR : (bFixed ? SQL_CHAR : SQL_VARCHAR));
543 		case PG_TYPE_TEXT:
544 			bLongVarchar = ci->drivers.text_as_longvarchar;
545 			if (bLongVarchar)
546 			{
547 				int column_size = getCharColumnSizeX(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
548 				if (column_size > 0 &&
549 				    column_size <= ci->drivers.max_varchar_size)
550 					bLongVarchar = FALSE;
551 			}
552 			return ansi_to_wtype(conn, bLongVarchar ? SQL_LONGVARCHAR : SQL_VARCHAR);
553 
554 		case PG_TYPE_BYTEA:
555 			if (ci->bytea_as_longvarbinary)
556 				return SQL_LONGVARBINARY;
557 			else
558 				return SQL_VARBINARY;
559 		case PG_TYPE_LO_UNDEFINED:
560 			return SQL_LONGVARBINARY;
561 
562 		case PG_TYPE_INT2:
563 			return SQL_SMALLINT;
564 
565 		case PG_TYPE_OID:
566 		case PG_TYPE_XID:
567 		case PG_TYPE_INT4:
568 			return SQL_INTEGER;
569 
570 			/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
571 		case PG_TYPE_INT8:
572 			if (ci->int8_as != 0)
573 				return ci->int8_as;
574 			if (conn->ms_jet)
575 				return SQL_NUMERIC; /* maybe a little better than SQL_VARCHAR */
576 			return SQL_BIGINT;
577 
578 		case PG_TYPE_NUMERIC:
579 			if (-1 == atttypmod && DEFAULT_NUMERIC_AS != ci->numeric_as)
580 				return ci->numeric_as;
581 			return SQL_NUMERIC;
582 
583 		case PG_TYPE_FLOAT4:
584 			return SQL_REAL;
585 		case PG_TYPE_FLOAT8:
586 			return SQL_FLOAT;
587 		case PG_TYPE_DATE:
588 			if (EN_is_odbc3(env))
589 				return SQL_TYPE_DATE;
590 			return SQL_DATE;
591 		case PG_TYPE_TIME:
592 			if (EN_is_odbc3(env))
593 				return SQL_TYPE_TIME;
594 			return SQL_TIME;
595 		case PG_TYPE_ABSTIME:
596 		case PG_TYPE_DATETIME:
597 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
598 		case PG_TYPE_TIMESTAMP:
599 			if (EN_is_odbc3(env))
600 				return SQL_TYPE_TIMESTAMP;
601 			return SQL_TIMESTAMP;
602 		case PG_TYPE_MONEY:
603 			return SQL_FLOAT;
604 		case PG_TYPE_BOOL:
605 			return ci->drivers.bools_as_char ? SQL_VARCHAR : SQL_BIT;
606 		case PG_TYPE_XML:
607 			return ansi_to_wtype(conn, SQL_LONGVARCHAR);
608 		case PG_TYPE_INET:
609 		case PG_TYPE_CIDR:
610 		case PG_TYPE_MACADDR:
611 			return ansi_to_wtype(conn, SQL_VARCHAR);
612 		case PG_TYPE_UUID:
613 			return SQL_GUID;
614 
615 		case PG_TYPE_INTERVAL:
616 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
617 			if (sqltype = get_interval_type(atttypmod, NULL), 0 != sqltype)
618 				return sqltype;
619 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
620 			return ansi_to_wtype(conn, SQL_VARCHAR);
621 		case PG_TYPE_BIT:
622 			if (1 == atttypmod)
623 				return SQL_BIT;
624 			else
625 				return SQL_VARCHAR;
626 
627 		default:
628 
629 			/*
630 			 * first, check to see if 'type' is in list.  If not, look up
631 			 * with query. Add oid, name to list.  If it's already in
632 			 * list, just return.
633 			 */
634 			/* hack until permanent type is available */
635 			if (type == conn->lobj_type)
636 				return SQL_LONGVARBINARY;
637 
638 			bLongVarchar = ci->drivers.unknowns_as_longvarchar;
639 			if (bLongVarchar)
640 			{
641 				int column_size = getCharColumnSizeX(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
642 				if (column_size > 0 &&
643 				    column_size <= ci->drivers.max_varchar_size)
644 					bLongVarchar = FALSE;
645 			}
646 #ifdef	EXPERIMENTAL_CURRENTLY
647 			return ansi_to_wtype(conn, bLongVarchar ? SQL_LONGVARCHAR : SQL_VARCHAR);
648 #endif	/* EXPERIMENTAL_CURRENTLY */
649 			return bLongVarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
650 	}
651 }
652 
653 SQLSMALLINT
pgtype_attr_to_sqldesctype(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int handle_unknown_size_as)654 pgtype_attr_to_sqldesctype(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
655 {
656 	SQLSMALLINT	rettype;
657 
658 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
659 	if (PG_TYPE_INTERVAL == type)
660 		return SQL_INTERVAL;
661 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
662 	switch (rettype = pgtype_attr_to_concise_type(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as))
663 	{
664 		case SQL_TYPE_DATE:
665 		case SQL_TYPE_TIME:
666 		case SQL_TYPE_TIMESTAMP:
667 			return SQL_DATETIME;
668 	}
669 	return rettype;
670 }
671 
672 SQLSMALLINT
pgtype_attr_to_datetime_sub(const ConnectionClass * conn,OID type,int atttypmod)673 pgtype_attr_to_datetime_sub(const ConnectionClass *conn, OID type, int atttypmod)
674 {
675 	SQLSMALLINT	rettype;
676 
677 	switch (rettype = pgtype_attr_to_concise_type(conn, type, atttypmod, PG_ADT_UNSET, PG_UNKNOWNS_UNSET))
678 	{
679 		case SQL_TYPE_DATE:
680 			return SQL_CODE_DATE;
681 		case SQL_TYPE_TIME:
682 			return SQL_CODE_TIME;
683 		case SQL_TYPE_TIMESTAMP:
684 			return SQL_CODE_TIMESTAMP;
685 		case SQL_INTERVAL_MONTH:
686 		case SQL_INTERVAL_YEAR:
687 		case SQL_INTERVAL_YEAR_TO_MONTH:
688 		case SQL_INTERVAL_DAY:
689 		case SQL_INTERVAL_HOUR:
690 		case SQL_INTERVAL_MINUTE:
691 		case SQL_INTERVAL_SECOND:
692 		case SQL_INTERVAL_DAY_TO_HOUR:
693 		case SQL_INTERVAL_DAY_TO_MINUTE:
694 		case SQL_INTERVAL_DAY_TO_SECOND:
695 		case SQL_INTERVAL_HOUR_TO_MINUTE:
696 		case SQL_INTERVAL_HOUR_TO_SECOND:
697 		case SQL_INTERVAL_MINUTE_TO_SECOND:
698 			return rettype - 100;
699 	}
700 	return -1;
701 }
702 
703 SQLSMALLINT
pgtype_attr_to_ctype(const ConnectionClass * conn,OID type,int atttypmod)704 pgtype_attr_to_ctype(const ConnectionClass *conn, OID type, int atttypmod)
705 {
706 	const ConnInfo	*ci = &(conn->connInfo);
707 	EnvironmentClass *env = (EnvironmentClass *) CC_get_env(conn);
708 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
709 	SQLSMALLINT	ctype;
710 #endif /* PG_INTERVAL_A_SQL_INTERVAL */
711 
712 	switch (type)
713 	{
714 		case PG_TYPE_INT8:
715 			if (!conn->ms_jet)
716 				return ALLOWED_C_BIGINT;
717 			return SQL_C_CHAR;
718 		case PG_TYPE_NUMERIC:
719 			return SQL_C_CHAR;
720 		case PG_TYPE_INT2:
721 			return SQL_C_SSHORT;
722 		case PG_TYPE_OID:
723 		case PG_TYPE_XID:
724 			return SQL_C_ULONG;
725 		case PG_TYPE_INT4:
726 			return SQL_C_SLONG;
727 		case PG_TYPE_FLOAT4:
728 			return SQL_C_FLOAT;
729 		case PG_TYPE_FLOAT8:
730 			return SQL_C_DOUBLE;
731 		case PG_TYPE_DATE:
732 			if (EN_is_odbc3(env))
733 				return SQL_C_TYPE_DATE;
734 			return SQL_C_DATE;
735 		case PG_TYPE_TIME:
736 			if (EN_is_odbc3(env))
737 				return SQL_C_TYPE_TIME;
738 			return SQL_C_TIME;
739 		case PG_TYPE_ABSTIME:
740 		case PG_TYPE_DATETIME:
741 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
742 		case PG_TYPE_TIMESTAMP:
743 			if (EN_is_odbc3(env))
744 				return SQL_C_TYPE_TIMESTAMP;
745 			return SQL_C_TIMESTAMP;
746 		case PG_TYPE_MONEY:
747 			return SQL_C_FLOAT;
748 		case PG_TYPE_BOOL:
749 			return ci->drivers.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
750 
751 		case PG_TYPE_BYTEA:
752 			return SQL_C_BINARY;
753 		case PG_TYPE_LO_UNDEFINED:
754 			return SQL_C_BINARY;
755 		case PG_TYPE_BPCHAR:
756 		case PG_TYPE_VARCHAR:
757 		case PG_TYPE_TEXT:
758 			return ansi_to_wtype(conn, SQL_C_CHAR);
759 		case PG_TYPE_UUID:
760 			if (!conn->ms_jet)
761 				return SQL_C_GUID;
762 			return ansi_to_wtype(conn, SQL_C_CHAR);
763 
764 		case PG_TYPE_INTERVAL:
765 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
766 			if (ctype = get_interval_type(atttypmod, NULL), 0 != ctype)
767 				return ctype;
768 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
769 			return ansi_to_wtype(conn, SQL_CHAR);
770 
771 		default:
772 			/* hack until permanent type is available */
773 			if (type == conn->lobj_type)
774 				return SQL_C_BINARY;
775 
776 			/* Experimental, Does this work ? */
777 #ifdef	EXPERIMENTAL_CURRENTLY
778 			return ansi_to_wtype(conn, SQL_C_CHAR);
779 #endif	/* EXPERIMENTAL_CURRENTLY */
780 			return SQL_C_CHAR;
781 	}
782 }
783 
784 const char *
pgtype_attr_to_name(const ConnectionClass * conn,OID type,int atttypmod,BOOL auto_increment)785 pgtype_attr_to_name(const ConnectionClass *conn, OID type, int atttypmod, BOOL auto_increment)
786 {
787 	const char	*tname = NULL;
788 
789 	switch (type)
790 	{
791 		case PG_TYPE_CHAR:
792 			return "char";
793 		case PG_TYPE_INT8:
794 			return auto_increment ? "bigserial" : "int8";
795 		case PG_TYPE_NUMERIC:
796 			return "numeric";
797 		case PG_TYPE_VARCHAR:
798 			return "varchar";
799 		case PG_TYPE_BPCHAR:
800 			return "char";
801 		case PG_TYPE_TEXT:
802 			return "text";
803 		case PG_TYPE_NAME:
804 			return "name";
805 		case PG_TYPE_REFCURSOR:
806 			return "refcursor";
807 		case PG_TYPE_INT2:
808 			return "int2";
809 		case PG_TYPE_OID:
810 			return OID_NAME;
811 		case PG_TYPE_XID:
812 			return "xid";
813 		case PG_TYPE_INT4:
814 MYLOG(DETAIL_LOG_LEVEL, "pgtype_to_name int4\n");
815 			return auto_increment ? "serial" : "int4";
816 		case PG_TYPE_FLOAT4:
817 			return "float4";
818 		case PG_TYPE_FLOAT8:
819 			return "float8";
820 		case PG_TYPE_DATE:
821 			return "date";
822 		case PG_TYPE_TIME:
823 			return "time";
824 		case PG_TYPE_ABSTIME:
825 			return "abstime";
826 		case PG_TYPE_DATETIME:
827 			return "timestamptz";
828 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
829 			return "timestamp without time zone";
830 		case PG_TYPE_TIMESTAMP:
831 			return "timestamp";
832 		case PG_TYPE_MONEY:
833 			return "money";
834 		case PG_TYPE_BOOL:
835 			return "bool";
836 		case PG_TYPE_BYTEA:
837 			return "bytea";
838 		case PG_TYPE_XML:
839 			return "xml";
840 		case PG_TYPE_MACADDR:
841 			return "macaddr";
842 		case PG_TYPE_INET:
843 			return "inet";
844 		case PG_TYPE_CIDR:
845 			return "cidr";
846 		case PG_TYPE_UUID:
847 			return "uuid";
848 		case PG_TYPE_VOID:
849 			return "void";
850 		case PG_TYPE_INT2VECTOR:
851 			return "int2vector";
852 		case PG_TYPE_OIDVECTOR:
853 			return "oidvector";
854 		case PG_TYPE_ANY:
855 			return "any";
856 		case PG_TYPE_INTERVAL:
857 			get_interval_type(atttypmod, &tname);
858 			return tname;
859 		case PG_TYPE_LO_UNDEFINED:
860 			return PG_TYPE_LO_NAME;
861 
862 		default:
863 			/* hack until permanent type is available */
864 			if (type == conn->lobj_type)
865 				return PG_TYPE_LO_NAME;
866 
867 			/*
868 			 * "unknown" can actually be used in alter table because it is
869 			 * a real PG type!
870 			 */
871 			return "unknown";
872 	}
873 }
874 
875 
876 Int4	/* PostgreSQL restriction */
pgtype_attr_column_size(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longest,int handle_unknown_size_as)877 pgtype_attr_column_size(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longest, int handle_unknown_size_as)
878 {
879 	const ConnInfo	*ci = &(conn->connInfo);
880 MYLOG(0, "entering type=%d, atttypmod=%d, adtsize_or=%d, unknown = %d\n", type, atttypmod, adtsize_or_longest, handle_unknown_size_as);
881 
882 	switch (type)
883 	{
884 		case PG_TYPE_CHAR:
885 			return 1;
886 
887 		case PG_TYPE_NAME:
888 		case PG_TYPE_REFCURSOR:
889 			{
890 				int	value = 0;
891 				if (PG_VERSION_GT(conn, 7.4))
892 				{
893 					/*
894 					 * 'conn' argument is marked as const,
895 					 * because this function just reads
896 					 * stuff from the already-filled in
897 					 * fields in the struct. But this is
898 					 * an exception: CC_get_max_idlen() can
899 					 * send a SHOW query to the backend to
900 					 * get the identifier length. Thus cast
901 					 * away the const here.
902 					 */
903 					value = CC_get_max_idlen((ConnectionClass *) conn);
904 				}
905 #ifdef	NAME_FIELD_SIZE
906 				else
907 					value = NAME_FIELD_SIZE;
908 #endif /* NAME_FIELD_SIZE */
909 				if (0 == value)
910 					value = NAMEDATALEN_V73;
911 				return value;
912 			}
913 
914 		case PG_TYPE_INT2:
915 			return 5;
916 
917 		case PG_TYPE_OID:
918 		case PG_TYPE_XID:
919 		case PG_TYPE_INT4:
920 			return 10;
921 
922 		case PG_TYPE_INT8:
923 			return 19;			/* signed */
924 
925 		case PG_TYPE_NUMERIC:
926 			return getNumericColumnSizeX(conn, type, atttypmod, adtsize_or_longest, handle_unknown_size_as);
927 
928 		case PG_TYPE_MONEY:
929 			return 10;
930 		case PG_TYPE_FLOAT4:
931 			return PG_REAL_DIGITS;
932 
933 		case PG_TYPE_FLOAT8:
934 			return PG_DOUBLE_DIGITS;
935 
936 		case PG_TYPE_DATE:
937 			return 10;
938 		case PG_TYPE_TIME:
939 			return 8;
940 
941 		case PG_TYPE_ABSTIME:
942 		case PG_TYPE_TIMESTAMP:
943 			return 22;
944 		case PG_TYPE_DATETIME:
945 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
946 			/* return 22; */
947 			return getTimestampColumnSizeX(conn, type, atttypmod);
948 
949 		case PG_TYPE_BOOL:
950 			return ci->drivers.bools_as_char ? PG_WIDTH_OF_BOOLS_AS_CHAR : 1;
951 
952 		case PG_TYPE_MACADDR:
953 			return 17;
954 
955 		case PG_TYPE_INET:
956 		case PG_TYPE_CIDR:
957 			return sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128");
958 		case PG_TYPE_UUID:
959 			return sizeof("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
960 
961 		case PG_TYPE_LO_UNDEFINED:
962 			return SQL_NO_TOTAL;
963 
964 		case PG_TYPE_INTERVAL:
965 			return getIntervalColumnSize(type, atttypmod);
966 
967 		default:
968 
969 			if (type == conn->lobj_type)	/* hack until permanent
970 												 * type is available */
971 				return SQL_NO_TOTAL;
972 			if (PG_TYPE_BYTEA == type && ci->bytea_as_longvarbinary)
973 				return SQL_NO_TOTAL;
974 
975 			/* Handle Character types and unknown types */
976 			return getCharColumnSizeX(conn, type, atttypmod, adtsize_or_longest, handle_unknown_size_as);
977 	}
978 }
979 
980 SQLSMALLINT
pgtype_attr_precision(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longest,int handle_unknown_size_as)981 pgtype_attr_precision(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longest, int handle_unknown_size_as)
982 {
983 	switch (type)
984 	{
985 		case PG_TYPE_NUMERIC:
986 			return getNumericColumnSizeX(conn, type, atttypmod, adtsize_or_longest, handle_unknown_size_as);
987 		case PG_TYPE_TIME:
988 		case PG_TYPE_DATETIME:
989 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
990 			return getTimestampDecimalDigitsX(conn, type, atttypmod);
991 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
992 		case PG_TYPE_INTERVAL:
993 			return getIntervalDecimalDigits(type, atttypmod);
994 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
995 	}
996 	return -1;
997 }
998 
999 Int4
pgtype_attr_display_size(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int handle_unknown_size_as)1000 pgtype_attr_display_size(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
1001 {
1002 	int	dsize;
1003 
1004 	switch (type)
1005 	{
1006 		case PG_TYPE_INT2:
1007 			return 6;
1008 
1009 		case PG_TYPE_OID:
1010 		case PG_TYPE_XID:
1011 			return 10;
1012 
1013 		case PG_TYPE_INT4:
1014 			return 11;
1015 
1016 		case PG_TYPE_INT8:
1017 			return 20;			/* signed: 19 digits + sign */
1018 
1019 		case PG_TYPE_NUMERIC:
1020 			dsize = getNumericColumnSizeX(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1021 			return dsize <= 0 ? dsize : dsize + 2;
1022 
1023 		case PG_TYPE_MONEY:
1024 			return 15;			/* ($9,999,999.99) */
1025 
1026 		case PG_TYPE_FLOAT4:	/* a sign, PG_REAL_DIGITS digits, a decimal point, the letter E, a sign, and 2 digits */
1027 			return (1 + PG_REAL_DIGITS + 1 + 1 + 3);
1028 
1029 		case PG_TYPE_FLOAT8:	/* a sign, PG_DOUBLE_DIGITS digits, a decimal point, the letter E, a sign, and 3 digits */
1030 			return (1 + PG_DOUBLE_DIGITS + 1 + 1 + 1 + 3);
1031 
1032 		case PG_TYPE_MACADDR:
1033 			return 17;
1034 		case PG_TYPE_INET:
1035 		case PG_TYPE_CIDR:
1036 			return sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128");
1037 		case PG_TYPE_UUID:
1038 			return 36;
1039 		case PG_TYPE_INTERVAL:
1040 			return 30;
1041 
1042 			/* Character types use regular precision */
1043 		default:
1044 			return pgtype_attr_column_size(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1045 	}
1046 }
1047 
1048 Int4
pgtype_attr_buffer_length(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int handle_unknown_size_as)1049 pgtype_attr_buffer_length(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
1050 {
1051 	int	dsize;
1052 
1053 	switch (type)
1054 	{
1055 		case PG_TYPE_INT2:
1056 			return 2; /* sizeof(SQLSMALLINT) */
1057 
1058 		case PG_TYPE_OID:
1059 		case PG_TYPE_XID:
1060 		case PG_TYPE_INT4:
1061 			return 4; /* sizeof(SQLINTEGER) */
1062 
1063 		case PG_TYPE_INT8:
1064 			if (SQL_C_CHAR == pgtype_attr_to_ctype(conn, type, atttypmod))
1065 				return 20;			/* signed: 19 digits + sign */
1066 			return 8; /* sizeof(SQLSBININT) */
1067 
1068 		case PG_TYPE_NUMERIC:
1069 			dsize = getNumericColumnSizeX(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1070 			return dsize <= 0 ? dsize : dsize + 2;
1071 
1072 		case PG_TYPE_FLOAT4:
1073 		case PG_TYPE_MONEY:
1074 			return 4; /* sizeof(SQLREAL) */
1075 
1076 		case PG_TYPE_FLOAT8:
1077 			return 8; /* sizeof(SQLFLOAT) */
1078 
1079 		case PG_TYPE_DATE:
1080 		case PG_TYPE_TIME:
1081 			return 6;		/* sizeof(DATE(TIME)_STRUCT) */
1082 
1083 		case PG_TYPE_ABSTIME:
1084 		case PG_TYPE_DATETIME:
1085 		case PG_TYPE_TIMESTAMP:
1086 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
1087 			return 16;		/* sizeof(TIMESTAMP_STRUCT) */
1088 
1089 		case PG_TYPE_MACADDR:
1090 			return 17;
1091 		case PG_TYPE_INET:
1092 		case PG_TYPE_CIDR:
1093 			return sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128");
1094 		case PG_TYPE_UUID:
1095 			return 16;		/* sizeof(SQLGUID) */
1096 
1097 			/* Character types use the default precision */
1098 		case PG_TYPE_VARCHAR:
1099 		case PG_TYPE_BPCHAR:
1100 			{
1101 			int	coef = 1;
1102 			Int4	prec = pgtype_attr_column_size(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as), maxvarc;
1103 			if (SQL_NO_TOTAL == prec)
1104 				return prec;
1105 #ifdef	UNICODE_SUPPORT
1106 			if (CC_is_in_unicode_driver(conn))
1107 				return prec * WCLEN;
1108 #endif /* UNICODE_SUPPORT */
1109 			coef = conn->mb_maxbyte_per_char;
1110 			if (coef < 2 && (conn->connInfo).lf_conversion)
1111 				/* CR -> CR/LF */
1112 				coef = 2;
1113 			if (coef == 1)
1114 				return prec;
1115 			maxvarc = conn->connInfo.drivers.max_varchar_size;
1116 			if (prec <= maxvarc && prec * coef > maxvarc)
1117 				return maxvarc;
1118 			return coef * prec;
1119 			}
1120 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
1121 		case PG_TYPE_INTERVAL:
1122 			return sizeof(SQL_INTERVAL_STRUCT);
1123 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
1124 
1125 		default:
1126 			return pgtype_attr_column_size(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1127 	}
1128 }
1129 
1130 /*
1131  */
1132 Int4
pgtype_attr_desclength(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int handle_unknown_size_as)1133 pgtype_attr_desclength(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
1134 {
1135 	int	dsize;
1136 
1137 	switch (type)
1138 	{
1139 		case PG_TYPE_INT2:
1140 			return 2;
1141 
1142 		case PG_TYPE_OID:
1143 		case PG_TYPE_XID:
1144 		case PG_TYPE_INT4:
1145 			return 4;
1146 
1147 		case PG_TYPE_INT8:
1148 			return 20;			/* signed: 19 digits + sign */
1149 
1150 		case PG_TYPE_NUMERIC:
1151 			dsize = getNumericColumnSizeX(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1152 			return dsize <= 0 ? dsize : dsize + 2;
1153 
1154 		case PG_TYPE_FLOAT4:
1155 		case PG_TYPE_MONEY:
1156 			return 4;
1157 
1158 		case PG_TYPE_FLOAT8:
1159 			return 8;
1160 
1161 		case PG_TYPE_DATE:
1162 		case PG_TYPE_TIME:
1163 		case PG_TYPE_ABSTIME:
1164 		case PG_TYPE_DATETIME:
1165 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
1166 		case PG_TYPE_TIMESTAMP:
1167 		case PG_TYPE_VARCHAR:
1168 		case PG_TYPE_BPCHAR:
1169 			return pgtype_attr_column_size(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1170 		default:
1171 			return pgtype_attr_column_size(conn, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1172 	}
1173 }
1174 
1175 Int2
pgtype_attr_decimal_digits(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int UNUSED_handle_unknown_size_as)1176 pgtype_attr_decimal_digits(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int UNUSED_handle_unknown_size_as)
1177 {
1178 	switch (type)
1179 	{
1180 		case PG_TYPE_INT2:
1181 		case PG_TYPE_OID:
1182 		case PG_TYPE_XID:
1183 		case PG_TYPE_INT4:
1184 		case PG_TYPE_INT8:
1185 		case PG_TYPE_FLOAT4:
1186 		case PG_TYPE_FLOAT8:
1187 		case PG_TYPE_MONEY:
1188 		case PG_TYPE_BOOL:
1189 
1190 			/*
1191 			 * Number of digits to the right of the decimal point in
1192 			 * "yyyy-mm=dd hh:mm:ss[.f...]"
1193 			 */
1194 		case PG_TYPE_ABSTIME:
1195 		case PG_TYPE_TIMESTAMP:
1196 			return 0;
1197 		case PG_TYPE_TIME:
1198 		case PG_TYPE_DATETIME:
1199 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
1200 			/* return 0; */
1201 			return getTimestampDecimalDigitsX(conn, type, atttypmod);
1202 
1203 		case PG_TYPE_NUMERIC:
1204 			return getNumericDecimalDigitsX(conn, type, atttypmod, adtsize_or_longestlen, UNUSED_handle_unknown_size_as);
1205 
1206 #ifdef	PG_INTERVAL_AS_SQL_INTERVAL
1207 		case PG_TYPE_INTERVAL:
1208 			return getIntervalDecimalDigits(type, atttypmod);
1209 #endif /* PG_INTERVAL_AS_SQL_INTERVAL */
1210 
1211 		default:
1212 			return -1;
1213 	}
1214 }
1215 
1216 Int2
pgtype_attr_scale(const ConnectionClass * conn,OID type,int atttypmod,int adtsize_or_longestlen,int UNUSED_handle_unknown_size_as)1217 pgtype_attr_scale(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int UNUSED_handle_unknown_size_as)
1218 {
1219 	switch (type)
1220 	{
1221 		case PG_TYPE_NUMERIC:
1222 			return getNumericDecimalDigitsX(conn, type, atttypmod, adtsize_or_longestlen, UNUSED_handle_unknown_size_as);
1223 	}
1224 	return -1;
1225 }
1226 
1227 Int4
pgtype_attr_transfer_octet_length(const ConnectionClass * conn,OID type,int atttypmod,int handle_unknown_size_as)1228 pgtype_attr_transfer_octet_length(const ConnectionClass *conn, OID type, int atttypmod, int handle_unknown_size_as)
1229 {
1230 	int	coef = 1;
1231 	Int4	maxvarc, column_size;
1232 
1233 	switch (type)
1234 	{
1235 		case PG_TYPE_VARCHAR:
1236 		case PG_TYPE_BPCHAR:
1237 		case PG_TYPE_TEXT:
1238 		case PG_TYPE_UNKNOWN:
1239 			column_size = pgtype_attr_column_size(conn, type, atttypmod, PG_ADT_UNSET, handle_unknown_size_as);
1240 			if (SQL_NO_TOTAL == column_size)
1241 				return column_size;
1242 #ifdef	UNICODE_SUPPORT
1243 			if (CC_is_in_unicode_driver(conn))
1244 				return column_size * WCLEN;
1245 #endif /* UNICODE_SUPPORT */
1246 			coef = conn->mb_maxbyte_per_char;
1247 			if (coef < 2 && (conn->connInfo).lf_conversion)
1248 				/* CR -> CR/LF */
1249 				coef = 2;
1250 			if (coef == 1)
1251 				return column_size;
1252 			maxvarc = conn->connInfo.drivers.max_varchar_size;
1253 			if (column_size <= maxvarc && column_size * coef > maxvarc)
1254 				return maxvarc;
1255 			return coef * column_size;
1256 		case PG_TYPE_BYTEA:
1257 			return pgtype_attr_column_size(conn, type, atttypmod, PG_ADT_UNSET, handle_unknown_size_as);
1258 		default:
1259 			if (type == conn->lobj_type)
1260 				return pgtype_attr_column_size(conn, type, atttypmod, PG_ADT_UNSET, handle_unknown_size_as);
1261 	}
1262 	return -1;
1263 }
1264 
1265 
1266 
1267 /*
1268  * This was used when binding a query parameter, to decide which PostgreSQL
1269  * datatype to send to the server, depending on the SQL datatype that was
1270  * used in the SQLBindParameter call.
1271  *
1272  * However it is inflexible and rather harmful.
1273  * Now this function always returns 0.
1274  * We use cast instead to keep regression test results
1275  * in order to keep regression test results.
1276  */
1277 OID
sqltype_to_bind_pgtype(const ConnectionClass * conn,SQLSMALLINT fSqlType)1278 sqltype_to_bind_pgtype(const ConnectionClass *conn, SQLSMALLINT fSqlType)
1279 {
1280 	OID		pgType = 0;
1281 
1282 	return pgType;
1283 }
1284 
1285 /*
1286  * Casting parameters e.g. ?::timestamp is much more flexible
1287  * than specifying parameter datatype oids determined by
1288  * sqltype_to_bind_pgtype() via parse message.
1289  */
1290 const char *
sqltype_to_pgcast(const ConnectionClass * conn,SQLSMALLINT fSqlType)1291 sqltype_to_pgcast(const ConnectionClass *conn, SQLSMALLINT fSqlType)
1292 {
1293 	const char *pgCast = NULL_STRING;
1294 
1295 	switch (fSqlType)
1296 	{
1297 		case SQL_BINARY:
1298 		case SQL_VARBINARY:
1299 			pgCast = "::bytea";
1300 			break;
1301 		case SQL_TYPE_DATE:
1302 		case SQL_DATE:
1303 			pgCast = "::date";
1304 			break;
1305 		case SQL_DECIMAL:
1306 		case SQL_NUMERIC:
1307 			pgCast = "::numeric";
1308 			break;
1309 		case SQL_BIGINT:
1310 			pgCast = "::int8";
1311 			break;
1312 		case SQL_INTEGER:
1313 			pgCast = "::int4";
1314 			break;
1315 		case SQL_REAL:
1316 			pgCast = "::float4";
1317 			break;
1318 		case SQL_SMALLINT:
1319 		case SQL_TINYINT:
1320 			pgCast = "::int2";
1321 			break;
1322 		case SQL_TIME:
1323 		case SQL_TYPE_TIME:
1324 			pgCast = "::time";
1325 			break;
1326 		case SQL_TIMESTAMP:
1327 		case SQL_TYPE_TIMESTAMP:
1328 			pgCast = "::timestamp";
1329 			break;
1330 		case SQL_GUID:
1331 			if (PG_VERSION_GE(conn, 8.3))
1332 				pgCast = "::uuid";
1333 			break;
1334 		case SQL_INTERVAL_MONTH:
1335 		case SQL_INTERVAL_YEAR:
1336 		case SQL_INTERVAL_YEAR_TO_MONTH:
1337 		case SQL_INTERVAL_DAY:
1338 		case SQL_INTERVAL_HOUR:
1339 		case SQL_INTERVAL_MINUTE:
1340 		case SQL_INTERVAL_SECOND:
1341 		case SQL_INTERVAL_DAY_TO_HOUR:
1342 		case SQL_INTERVAL_DAY_TO_MINUTE:
1343 		case SQL_INTERVAL_DAY_TO_SECOND:
1344 		case SQL_INTERVAL_HOUR_TO_MINUTE:
1345 		case SQL_INTERVAL_HOUR_TO_SECOND:
1346 		case SQL_INTERVAL_MINUTE_TO_SECOND:
1347 			pgCast = "::interval";
1348 			break;
1349 	}
1350 
1351 	return pgCast;
1352 }
1353 
1354 OID
sqltype_to_pgtype(const ConnectionClass * conn,SQLSMALLINT fSqlType)1355 sqltype_to_pgtype(const ConnectionClass *conn, SQLSMALLINT fSqlType)
1356 {
1357 	OID		pgType;
1358 	const ConnInfo	*ci = &(conn->connInfo);
1359 
1360 	pgType = 0; /* ??? */
1361 	switch (fSqlType)
1362 	{
1363 		case SQL_BINARY:
1364 			pgType = PG_TYPE_BYTEA;
1365 			break;
1366 
1367 		case SQL_CHAR:
1368 			pgType = PG_TYPE_BPCHAR;
1369 			break;
1370 
1371 #ifdef	UNICODE_SUPPORT
1372 		case SQL_WCHAR:
1373 			pgType = PG_TYPE_BPCHAR;
1374 			break;
1375 #endif /* UNICODE_SUPPORT */
1376 
1377 		case SQL_BIT:
1378 			pgType = PG_TYPE_BOOL;
1379 			break;
1380 
1381 		case SQL_TYPE_DATE:
1382 		case SQL_DATE:
1383 			pgType = PG_TYPE_DATE;
1384 			break;
1385 
1386 		case SQL_DOUBLE:
1387 		case SQL_FLOAT:
1388 			pgType = PG_TYPE_FLOAT8;
1389 			break;
1390 
1391 		case SQL_DECIMAL:
1392 		case SQL_NUMERIC:
1393 			pgType = PG_TYPE_NUMERIC;
1394 			break;
1395 
1396 		case SQL_BIGINT:
1397 			pgType = PG_TYPE_INT8;
1398 			break;
1399 
1400 		case SQL_INTEGER:
1401 			pgType = PG_TYPE_INT4;
1402 			break;
1403 
1404 		case SQL_LONGVARBINARY:
1405 			if (ci->bytea_as_longvarbinary)
1406 				pgType = PG_TYPE_BYTEA;
1407 			else
1408 				pgType = conn->lobj_type;
1409 			break;
1410 
1411 		case SQL_LONGVARCHAR:
1412 			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
1413 			break;
1414 
1415 #ifdef	UNICODE_SUPPORT
1416 		case SQL_WLONGVARCHAR:
1417 			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
1418 			break;
1419 #endif /* UNICODE_SUPPORT */
1420 
1421 		case SQL_REAL:
1422 			pgType = PG_TYPE_FLOAT4;
1423 			break;
1424 
1425 		case SQL_SMALLINT:
1426 		case SQL_TINYINT:
1427 			pgType = PG_TYPE_INT2;
1428 			break;
1429 
1430 		case SQL_TIME:
1431 		case SQL_TYPE_TIME:
1432 			pgType = PG_TYPE_TIME;
1433 			break;
1434 
1435 		case SQL_TIMESTAMP:
1436 		case SQL_TYPE_TIMESTAMP:
1437 			pgType = PG_TYPE_DATETIME;
1438 			break;
1439 
1440 		case SQL_VARBINARY:
1441 			pgType = PG_TYPE_BYTEA;
1442 			break;
1443 
1444 		case SQL_VARCHAR:
1445 			pgType = PG_TYPE_VARCHAR;
1446 			break;
1447 
1448 #ifdef	UNICODE_SUPPORT
1449 		case SQL_WVARCHAR:
1450 			pgType = PG_TYPE_VARCHAR;
1451 			break;
1452 #endif /* UNICODE_SUPPORT */
1453 
1454 		case SQL_GUID:
1455 			if (PG_VERSION_GE(conn, 8.3))
1456 				pgType = PG_TYPE_UUID;
1457 			break;
1458 
1459 		case SQL_INTERVAL_MONTH:
1460 		case SQL_INTERVAL_YEAR:
1461 		case SQL_INTERVAL_YEAR_TO_MONTH:
1462 		case SQL_INTERVAL_DAY:
1463 		case SQL_INTERVAL_HOUR:
1464 		case SQL_INTERVAL_MINUTE:
1465 		case SQL_INTERVAL_SECOND:
1466 		case SQL_INTERVAL_DAY_TO_HOUR:
1467 		case SQL_INTERVAL_DAY_TO_MINUTE:
1468 		case SQL_INTERVAL_DAY_TO_SECOND:
1469 		case SQL_INTERVAL_HOUR_TO_MINUTE:
1470 		case SQL_INTERVAL_HOUR_TO_SECOND:
1471 		case SQL_INTERVAL_MINUTE_TO_SECOND:
1472 			pgType = PG_TYPE_INTERVAL;
1473 			break;
1474 	}
1475 
1476 	return pgType;
1477 }
1478 
1479 static int
getAtttypmodEtc(const StatementClass * stmt,int col,int * adtsize_or_longestlen)1480 getAtttypmodEtc(const StatementClass *stmt, int col, int *adtsize_or_longestlen)
1481 {
1482 	int	atttypmod = -1;
1483 
1484 	if (NULL != adtsize_or_longestlen)
1485 		*adtsize_or_longestlen = PG_ADT_UNSET;
1486 	if (col >= 0)
1487 	{
1488 		const QResultClass	*res;
1489 
1490 		if (res = SC_get_ExecdOrParsed(stmt), NULL != res)
1491 		{
1492 			atttypmod = QR_get_atttypmod(res, col);
1493 			if (NULL != adtsize_or_longestlen)
1494 			{
1495 				if (stmt->catalog_result)
1496 					*adtsize_or_longestlen = QR_get_fieldsize(res, col);
1497 				else
1498 				{
1499 					*adtsize_or_longestlen = QR_get_display_size(res, col);
1500 					if (PG_TYPE_NUMERIC == QR_get_field_type(res, col) &&
1501 					   atttypmod < 0 &&
1502 					   *adtsize_or_longestlen > 0)
1503 					{
1504 						SQLULEN		i;
1505 						size_t		sval, maxscale = 0;
1506 						const char *tval, *sptr;
1507 
1508 						for (i = 0; i < res->num_cached_rows; i++)
1509 						{
1510 							tval = QR_get_value_backend_text(res, i, col);
1511 							if (NULL != tval)
1512 							{
1513 								sptr = strchr(tval, '.');
1514 								if (NULL != sptr)
1515 								{
1516 									sval = strlen(tval) - (sptr + 1 - tval);
1517 									if (sval > maxscale)
1518 										maxscale = sval;
1519 								}
1520 							}
1521 						}
1522 						*adtsize_or_longestlen += (int) (maxscale << 16);
1523 					}
1524 				}
1525 			}
1526 		}
1527 	}
1528 	return atttypmod;
1529 }
1530 
1531 /*
1532  *	There are two ways of calling this function:
1533  *
1534  *	1.	When going through the supported PG types (SQLGetTypeInfo)
1535  *
1536  *	2.	When taking any type id (SQLColumns, SQLGetData)
1537  *
1538  *	The first type will always work because all the types defined are returned here.
1539  *	The second type will return a default based on global parameter when it does not
1540  *	know.	This allows for supporting
1541  *	types that are unknown.  All other pg routines in here return a suitable default.
1542  */
1543 SQLSMALLINT
pgtype_to_concise_type(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1544 pgtype_to_concise_type(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1545 {
1546 	int	atttypmod, adtsize_or_longestlen;
1547 
1548 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1549 	return pgtype_attr_to_concise_type(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1550 }
1551 
1552 SQLSMALLINT
pgtype_to_sqldesctype(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1553 pgtype_to_sqldesctype(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1554 {
1555 	int	adtsize_or_longestlen;
1556 	int	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1557 
1558 	return pgtype_attr_to_sqldesctype(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);
1559 }
1560 
1561 SQLSMALLINT
pgtype_to_datetime_sub(const StatementClass * stmt,OID type,int col)1562 pgtype_to_datetime_sub(const StatementClass *stmt, OID type, int col)
1563 {
1564 	int	atttypmod = getAtttypmodEtc(stmt, col, NULL);
1565 
1566 	return pgtype_attr_to_datetime_sub(SC_get_conn(stmt), type, atttypmod);
1567 }
1568 
1569 const char *
pgtype_to_name(const StatementClass * stmt,OID type,int col,BOOL auto_increment)1570 pgtype_to_name(const StatementClass *stmt, OID type, int col, BOOL auto_increment)
1571 {
1572 	int	atttypmod = getAtttypmodEtc(stmt, col, NULL);
1573 
1574 	return pgtype_attr_to_name(SC_get_conn(stmt), type, atttypmod, auto_increment);
1575 }
1576 
1577 
1578 /*
1579  *	This corresponds to "precision" in ODBC 2.x.
1580  *
1581  *	For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
1582  *	override this length with the atttypmod length from pg_attribute .
1583  *
1584  *	If col >= 0, then will attempt to get the info from the result set.
1585  *	This is used for functions SQLDescribeCol and SQLColAttributes.
1586  */
1587 Int4	/* PostgreSQL restriction */
pgtype_column_size(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1588 pgtype_column_size(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1589 {
1590 	int	atttypmod, adtsize_or_longestlen;
1591 
1592 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1593 	return pgtype_attr_column_size(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, stmt->catalog_result ? UNKNOWNS_AS_LONGEST : handle_unknown_size_as);
1594 }
1595 
1596 /*
1597  *	precision in ODBC 3.x.
1598  */
1599 SQLSMALLINT
pgtype_precision(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1600 pgtype_precision(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1601 {
1602 	int	atttypmod, adtsize_or_longestlen;
1603 
1604 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1605 	return pgtype_attr_precision(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, stmt->catalog_result ? UNKNOWNS_AS_LONGEST : handle_unknown_size_as);
1606 }
1607 
1608 
1609 Int4
pgtype_display_size(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1610 pgtype_display_size(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1611 {
1612 	int	atttypmod, adtsize_or_longestlen;
1613 
1614 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1615 	return pgtype_attr_display_size(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, stmt->catalog_result ? UNKNOWNS_AS_LONGEST : handle_unknown_size_as);
1616 }
1617 
1618 
1619 /*
1620  *	The length in bytes of data transferred on an SQLGetData, SQLFetch,
1621  *	or SQLFetchScroll operation if SQL_C_DEFAULT is specified.
1622  */
1623 Int4
pgtype_buffer_length(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1624 pgtype_buffer_length(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1625 {
1626 	int	atttypmod, adtsize_or_longestlen;
1627 
1628 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1629 	return pgtype_attr_buffer_length(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, stmt->catalog_result ? UNKNOWNS_AS_LONGEST : handle_unknown_size_as);
1630 }
1631 
1632 /*
1633  */
1634 Int4
pgtype_desclength(const StatementClass * stmt,OID type,int col,int handle_unknown_size_as)1635 pgtype_desclength(const StatementClass *stmt, OID type, int col, int handle_unknown_size_as)
1636 {
1637 	int	atttypmod, adtsize_or_longestlen;
1638 
1639 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1640 	return pgtype_attr_desclength(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, stmt->catalog_result ? UNKNOWNS_AS_LONGEST : handle_unknown_size_as);
1641 }
1642 
1643 #ifdef	NOT_USED
1644 /*
1645  *	Transfer octet length.
1646  */
1647 Int4
pgtype_transfer_octet_length(const StatementClass * stmt,OID type,int column_size)1648 pgtype_transfer_octet_length(const StatementClass *stmt, OID type, int column_size)
1649 {
1650 	ConnectionClass	*conn = SC_get_conn(stmt);
1651 
1652 	int	coef = 1;
1653 	Int4	maxvarc;
1654 	switch (type)
1655 	{
1656 		case PG_TYPE_VARCHAR:
1657 		case PG_TYPE_BPCHAR:
1658 		case PG_TYPE_TEXT:
1659 			if (SQL_NO_TOTAL == column_size)
1660 				return column_size;
1661 #ifdef	UNICODE_SUPPORT
1662 			if (CC_is_in_unicode_driver(conn))
1663 				return column_size * WCLEN;
1664 #endif /* UNICODE_SUPPORT */
1665 			coef = conn->mb_maxbyte_per_char;
1666 			if (coef < 2 && (conn->connInfo).lf_conversion)
1667 				/* CR -> CR/LF */
1668 				coef = 2;
1669 			if (coef == 1)
1670 				return column_size;
1671 			maxvarc = conn->connInfo.drivers.max_varchar_size;
1672 			if (column_size <= maxvarc && column_size * coef > maxvarc)
1673 				return maxvarc;
1674 			return coef * column_size;
1675 		case PG_TYPE_BYTEA:
1676 			return column_size;
1677 		default:
1678 			if (type == conn->lobj_type)
1679 				return column_size;
1680 	}
1681 	return -1;
1682 }
1683 #endif /* NOT_USED */
1684 
1685 /*
1686  *	corrsponds to "min_scale" in ODBC 2.x.
1687  */
1688 Int2
pgtype_min_decimal_digits(const ConnectionClass * conn,OID type)1689 pgtype_min_decimal_digits(const ConnectionClass *conn, OID type)
1690 {
1691 	switch (type)
1692 	{
1693 		case PG_TYPE_INT2:
1694 		case PG_TYPE_OID:
1695 		case PG_TYPE_XID:
1696 		case PG_TYPE_INT4:
1697 		case PG_TYPE_INT8:
1698 		case PG_TYPE_FLOAT4:
1699 		case PG_TYPE_FLOAT8:
1700 		case PG_TYPE_MONEY:
1701 		case PG_TYPE_BOOL:
1702 		case PG_TYPE_ABSTIME:
1703 		case PG_TYPE_TIMESTAMP:
1704 		case PG_TYPE_DATETIME:
1705 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
1706 		case PG_TYPE_NUMERIC:
1707 			return 0;
1708 		default:
1709 			return -1;
1710 	}
1711 }
1712 
1713 /*
1714  *	corrsponds to "max_scale" in ODBC 2.x.
1715  */
1716 Int2
pgtype_max_decimal_digits(const ConnectionClass * conn,OID type)1717 pgtype_max_decimal_digits(const ConnectionClass *conn, OID type)
1718 {
1719 	switch (type)
1720 	{
1721 		case PG_TYPE_INT2:
1722 		case PG_TYPE_OID:
1723 		case PG_TYPE_XID:
1724 		case PG_TYPE_INT4:
1725 		case PG_TYPE_INT8:
1726 		case PG_TYPE_FLOAT4:
1727 		case PG_TYPE_FLOAT8:
1728 		case PG_TYPE_MONEY:
1729 		case PG_TYPE_BOOL:
1730 		case PG_TYPE_ABSTIME:
1731 		case PG_TYPE_TIMESTAMP:
1732 			return 0;
1733 		case PG_TYPE_DATETIME:
1734 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
1735 			return 38;
1736 		case PG_TYPE_NUMERIC:
1737 			return getNumericDecimalDigitsX(conn, type, -1, -1, UNUSED_HANDLE_UNKNOWN_SIZE_AS);
1738 		default:
1739 			return -1;
1740 	}
1741 }
1742 
1743 /*
1744  *	corrsponds to "scale" in ODBC 2.x.
1745  */
1746 Int2
pgtype_decimal_digits(const StatementClass * stmt,OID type,int col)1747 pgtype_decimal_digits(const StatementClass *stmt, OID type, int col)
1748 {
1749 	int	atttypmod, adtsize_or_longestlen;
1750 
1751 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1752 	return pgtype_attr_decimal_digits(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, UNUSED_HANDLE_UNKNOWN_SIZE_AS);
1753 }
1754 
1755 /*
1756  *	"scale" in ODBC 3.x.
1757  */
1758 Int2
pgtype_scale(const StatementClass * stmt,OID type,int col)1759 pgtype_scale(const StatementClass *stmt, OID type, int col)
1760 {
1761 	int	atttypmod, adtsize_or_longestlen;
1762 
1763 	atttypmod = getAtttypmodEtc(stmt, col, &adtsize_or_longestlen);
1764 	return pgtype_attr_scale(SC_get_conn(stmt), type, atttypmod, adtsize_or_longestlen, UNUSED_HANDLE_UNKNOWN_SIZE_AS);
1765 }
1766 
1767 
1768 Int2
pgtype_radix(const ConnectionClass * conn,OID type)1769 pgtype_radix(const ConnectionClass *conn, OID type)
1770 {
1771 	switch (type)
1772 	{
1773 		case PG_TYPE_INT2:
1774 		case PG_TYPE_XID:
1775 		case PG_TYPE_OID:
1776 		case PG_TYPE_INT4:
1777 		case PG_TYPE_INT8:
1778 		case PG_TYPE_NUMERIC:
1779 		case PG_TYPE_FLOAT4:
1780 		case PG_TYPE_MONEY:
1781 		case PG_TYPE_FLOAT8:
1782 			return 10;
1783 		default:
1784 			return -1;
1785 	}
1786 }
1787 
1788 
1789 Int2
pgtype_nullable(const ConnectionClass * conn,OID type)1790 pgtype_nullable(const ConnectionClass *conn, OID type)
1791 {
1792 	return SQL_NULLABLE;		/* everything should be nullable */
1793 }
1794 
1795 
1796 Int2
pgtype_auto_increment(const ConnectionClass * conn,OID type)1797 pgtype_auto_increment(const ConnectionClass *conn, OID type)
1798 {
1799 	switch (type)
1800 	{
1801 		case PG_TYPE_INT2:
1802 		case PG_TYPE_OID:
1803 		case PG_TYPE_XID:
1804 		case PG_TYPE_INT4:
1805 		case PG_TYPE_FLOAT4:
1806 		case PG_TYPE_MONEY:
1807 		case PG_TYPE_BOOL:
1808 		case PG_TYPE_FLOAT8:
1809 		case PG_TYPE_INT8:
1810 		case PG_TYPE_NUMERIC:
1811 
1812 		case PG_TYPE_DATE:
1813 		case PG_TYPE_TIME_WITH_TMZONE:
1814 		case PG_TYPE_TIME:
1815 		case PG_TYPE_ABSTIME:
1816 		case PG_TYPE_DATETIME:
1817 		case PG_TYPE_TIMESTAMP_NO_TMZONE:
1818 		case PG_TYPE_TIMESTAMP:
1819 			return FALSE;
1820 
1821 		default:
1822 			return -1;
1823 	}
1824 }
1825 
1826 
1827 Int2
pgtype_case_sensitive(const ConnectionClass * conn,OID type)1828 pgtype_case_sensitive(const ConnectionClass *conn, OID type)
1829 {
1830 	switch (type)
1831 	{
1832 		case PG_TYPE_CHAR:
1833 
1834 		case PG_TYPE_VARCHAR:
1835 		case PG_TYPE_BPCHAR:
1836 		case PG_TYPE_TEXT:
1837 		case PG_TYPE_NAME:
1838 		case PG_TYPE_REFCURSOR:
1839 			return TRUE;
1840 
1841 		default:
1842 			return FALSE;
1843 	}
1844 }
1845 
1846 
1847 Int2
pgtype_money(const ConnectionClass * conn,OID type)1848 pgtype_money(const ConnectionClass *conn, OID type)
1849 {
1850 	switch (type)
1851 	{
1852 		case PG_TYPE_MONEY:
1853 			return TRUE;
1854 		default:
1855 			return FALSE;
1856 	}
1857 }
1858 
1859 
1860 Int2
pgtype_searchable(const ConnectionClass * conn,OID type)1861 pgtype_searchable(const ConnectionClass *conn, OID type)
1862 {
1863 	switch (type)
1864 	{
1865 		case PG_TYPE_CHAR:
1866 
1867 		case PG_TYPE_VARCHAR:
1868 		case PG_TYPE_BPCHAR:
1869 		case PG_TYPE_TEXT:
1870 		case PG_TYPE_NAME:
1871 		case PG_TYPE_REFCURSOR:
1872 			return SQL_SEARCHABLE;
1873 
1874 		default:
1875 			if (conn && type == conn->lobj_type)
1876 				return SQL_UNSEARCHABLE;
1877 			return SQL_ALL_EXCEPT_LIKE;
1878 	}
1879 }
1880 
1881 
1882 Int2
pgtype_unsigned(const ConnectionClass * conn,OID type)1883 pgtype_unsigned(const ConnectionClass *conn, OID type)
1884 {
1885 	switch (type)
1886 	{
1887 		case PG_TYPE_OID:
1888 		case PG_TYPE_XID:
1889 			return TRUE;
1890 
1891 		case PG_TYPE_INT2:
1892 		case PG_TYPE_INT4:
1893 		case PG_TYPE_INT8:
1894 		case PG_TYPE_NUMERIC:
1895 		case PG_TYPE_FLOAT4:
1896 		case PG_TYPE_FLOAT8:
1897 		case PG_TYPE_MONEY:
1898 			return FALSE;
1899 
1900 		default:
1901 			return -1;
1902 	}
1903 }
1904 
1905 
1906 const char *
pgtype_literal_prefix(const ConnectionClass * conn,OID type)1907 pgtype_literal_prefix(const ConnectionClass *conn, OID type)
1908 {
1909 	switch (type)
1910 	{
1911 		case PG_TYPE_INT2:
1912 		case PG_TYPE_OID:
1913 		case PG_TYPE_XID:
1914 		case PG_TYPE_INT4:
1915 		case PG_TYPE_INT8:
1916 		case PG_TYPE_NUMERIC:
1917 		case PG_TYPE_FLOAT4:
1918 		case PG_TYPE_FLOAT8:
1919 		case PG_TYPE_MONEY:
1920 			return NULL;
1921 
1922 		default:
1923 			return "'";
1924 	}
1925 }
1926 
1927 
1928 const char *
pgtype_literal_suffix(const ConnectionClass * conn,OID type)1929 pgtype_literal_suffix(const ConnectionClass *conn, OID type)
1930 {
1931 	switch (type)
1932 	{
1933 		case PG_TYPE_INT2:
1934 		case PG_TYPE_OID:
1935 		case PG_TYPE_XID:
1936 		case PG_TYPE_INT4:
1937 		case PG_TYPE_INT8:
1938 		case PG_TYPE_NUMERIC:
1939 		case PG_TYPE_FLOAT4:
1940 		case PG_TYPE_FLOAT8:
1941 		case PG_TYPE_MONEY:
1942 			return NULL;
1943 
1944 		default:
1945 			return "'";
1946 	}
1947 }
1948 
1949 
1950 const char *
pgtype_create_params(const ConnectionClass * conn,OID type)1951 pgtype_create_params(const ConnectionClass *conn, OID type)
1952 {
1953 	switch (type)
1954 	{
1955 		case PG_TYPE_BPCHAR:
1956 		case PG_TYPE_VARCHAR:
1957 			return "max. length";
1958 		case PG_TYPE_NUMERIC:
1959 			return "precision, scale";
1960 		default:
1961 			return NULL;
1962 	}
1963 }
1964 
1965 
1966 SQLSMALLINT
sqltype_to_default_ctype(const ConnectionClass * conn,SQLSMALLINT sqltype)1967 sqltype_to_default_ctype(const ConnectionClass *conn, SQLSMALLINT sqltype)
1968 {
1969 	/*
1970 	 * from the table on page 623 of ODBC 2.0 Programmer's Reference
1971 	 * (Appendix D)
1972 	 */
1973 	switch (sqltype)
1974 	{
1975 		case SQL_CHAR:
1976 		case SQL_VARCHAR:
1977 		case SQL_LONGVARCHAR:
1978 		case SQL_DECIMAL:
1979 		case SQL_NUMERIC:
1980 			return SQL_C_CHAR;
1981 		case SQL_BIGINT:
1982 			return ALLOWED_C_BIGINT;
1983 
1984 #ifdef	UNICODE_SUPPORT
1985 		case SQL_WCHAR:
1986 		case SQL_WVARCHAR:
1987 		case SQL_WLONGVARCHAR:
1988 			return ansi_to_wtype(conn, SQL_C_CHAR);
1989 #endif /* UNICODE_SUPPORT */
1990 
1991 		case SQL_BIT:
1992 			return SQL_C_BIT;
1993 
1994 		case SQL_TINYINT:
1995 			return SQL_C_STINYINT;
1996 
1997 		case SQL_SMALLINT:
1998 			return SQL_C_SSHORT;
1999 
2000 		case SQL_INTEGER:
2001 			return SQL_C_SLONG;
2002 
2003 		case SQL_REAL:
2004 			return SQL_C_FLOAT;
2005 
2006 		case SQL_FLOAT:
2007 		case SQL_DOUBLE:
2008 			return SQL_C_DOUBLE;
2009 
2010 		case SQL_BINARY:
2011 		case SQL_VARBINARY:
2012 		case SQL_LONGVARBINARY:
2013 			return SQL_C_BINARY;
2014 
2015 		case SQL_DATE:
2016 			return SQL_C_DATE;
2017 
2018 		case SQL_TIME:
2019 			return SQL_C_TIME;
2020 
2021 		case SQL_TIMESTAMP:
2022 			return SQL_C_TIMESTAMP;
2023 
2024 		case SQL_TYPE_DATE:
2025 			return SQL_C_TYPE_DATE;
2026 
2027 		case SQL_TYPE_TIME:
2028 			return SQL_C_TYPE_TIME;
2029 
2030 		case SQL_TYPE_TIMESTAMP:
2031 			return SQL_C_TYPE_TIMESTAMP;
2032 
2033 		case SQL_GUID:
2034 			if (conn->ms_jet)
2035 				return SQL_C_CHAR;
2036 			else
2037 				return SQL_C_GUID;
2038 
2039 		default:
2040 			/* should never happen */
2041 			return SQL_C_CHAR;
2042 	}
2043 }
2044 
2045 Int4
ctype_length(SQLSMALLINT ctype)2046 ctype_length(SQLSMALLINT ctype)
2047 {
2048 	switch (ctype)
2049 	{
2050 		case SQL_C_SSHORT:
2051 		case SQL_C_SHORT:
2052 			return sizeof(SWORD);
2053 
2054 		case SQL_C_USHORT:
2055 			return sizeof(UWORD);
2056 
2057 		case SQL_C_SLONG:
2058 		case SQL_C_LONG:
2059 			return sizeof(SDWORD);
2060 
2061 		case SQL_C_ULONG:
2062 			return sizeof(UDWORD);
2063 
2064 		case SQL_C_FLOAT:
2065 			return sizeof(SFLOAT);
2066 
2067 		case SQL_C_DOUBLE:
2068 			return sizeof(SDOUBLE);
2069 
2070 		case SQL_C_BIT:
2071 			return sizeof(UCHAR);
2072 
2073 		case SQL_C_STINYINT:
2074 		case SQL_C_TINYINT:
2075 			return sizeof(SCHAR);
2076 
2077 		case SQL_C_UTINYINT:
2078 			return sizeof(UCHAR);
2079 
2080 		case SQL_C_DATE:
2081 		case SQL_C_TYPE_DATE:
2082 			return sizeof(DATE_STRUCT);
2083 
2084 		case SQL_C_TIME:
2085 		case SQL_C_TYPE_TIME:
2086 			return sizeof(TIME_STRUCT);
2087 
2088 		case SQL_C_TIMESTAMP:
2089 		case SQL_C_TYPE_TIMESTAMP:
2090 			return sizeof(TIMESTAMP_STRUCT);
2091 
2092 		case SQL_C_GUID:
2093 			return sizeof(SQLGUID);
2094 		case SQL_C_INTERVAL_YEAR:
2095 		case SQL_C_INTERVAL_MONTH:
2096 		case SQL_C_INTERVAL_YEAR_TO_MONTH:
2097 		case SQL_C_INTERVAL_DAY:
2098 		case SQL_C_INTERVAL_HOUR:
2099 		case SQL_C_INTERVAL_DAY_TO_HOUR:
2100 		case SQL_C_INTERVAL_MINUTE:
2101 		case SQL_C_INTERVAL_DAY_TO_MINUTE:
2102 		case SQL_C_INTERVAL_HOUR_TO_MINUTE:
2103 		case SQL_C_INTERVAL_SECOND:
2104 		case SQL_C_INTERVAL_DAY_TO_SECOND:
2105 		case SQL_C_INTERVAL_HOUR_TO_SECOND:
2106 		case SQL_C_INTERVAL_MINUTE_TO_SECOND:
2107 			return sizeof(SQL_INTERVAL_STRUCT);
2108 		case SQL_C_NUMERIC:
2109 			return sizeof(SQL_NUMERIC_STRUCT);
2110 		case SQL_C_SBIGINT:
2111 		case SQL_C_UBIGINT:
2112 			return sizeof(SQLBIGINT);
2113 
2114 		case SQL_C_BINARY:
2115 		case SQL_C_CHAR:
2116 #ifdef	UNICODE_SUPPORT
2117 		case SQL_C_WCHAR:
2118 #endif /* UNICODE_SUPPORT */
2119 			return 0;
2120 
2121 		default:				/* should never happen */
2122 			return 0;
2123 	}
2124 }
2125