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