]> granicus.if.org Git - postgresql/blob - src/interfaces/odbc/pgtypes.c
dd242d7bdcdc13a228a8739f4294169a9461824d
[postgresql] / src / interfaces / odbc / pgtypes.c
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 "notice.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 "qresult.h"
25
26 #ifndef WIN32
27 #include "iodbc.h"
28 #include "isql.h"
29 #include "isqlext.h"
30 #else
31 #include <windows.h>
32 #include <sql.h>
33 #include <sqlext.h>
34 #endif
35
36
37
38 Int4            getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
39
40 /*
41  * these are the types we support.      all of the pgtype_ functions should
42  * return values for each one of these.
43  * Even types not directly supported are handled as character types
44  * so all types should work (points, etc.)
45  */
46
47 /*
48  * ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo.  Instead, all
49  *      the SQL TYPES are reported and mapped to a corresponding Postgres Type
50  */
51
52 /*
53 Int4 pgtypes_defined[]  = {
54                                 PG_TYPE_CHAR,
55                                 PG_TYPE_CHAR2,
56                                 PG_TYPE_CHAR4,
57                                 PG_TYPE_CHAR8,
58                                 PG_TYPE_CHAR16,
59                                 PG_TYPE_NAME,
60                                 PG_TYPE_VARCHAR,
61                                 PG_TYPE_BPCHAR,
62                                 PG_TYPE_DATE,
63                                 PG_TYPE_TIME,
64                                 PG_TYPE_DATETIME,
65                                 PG_TYPE_ABSTIME,
66                                 PG_TYPE_TIMESTAMP,
67                                 PG_TYPE_TEXT,
68                                 PG_TYPE_INT2,
69                                 PG_TYPE_INT4,
70                                 PG_TYPE_FLOAT4,
71                                 PG_TYPE_FLOAT8,
72                                 PG_TYPE_OID,
73                                 PG_TYPE_MONEY,
74                                 PG_TYPE_BOOL,
75                                 PG_TYPE_BYTEA,
76                                 PG_TYPE_LO,
77                                 0 };
78 */
79
80
81 /*      These are NOW the SQL Types reported in SQLGetTypeInfo.  */
82 Int2            sqlTypes[] = {
83         SQL_BIGINT,
84         /* SQL_BINARY, -- Commented out because VarBinary is more correct. */
85         SQL_BIT,
86         SQL_CHAR,
87         SQL_DATE,
88         SQL_DECIMAL,
89         SQL_DOUBLE,
90         SQL_FLOAT,
91         SQL_INTEGER,
92         SQL_LONGVARBINARY,
93         SQL_LONGVARCHAR,
94         SQL_NUMERIC,
95         SQL_REAL,
96         SQL_SMALLINT,
97         SQL_TIME,
98         SQL_TIMESTAMP,
99         SQL_TINYINT,
100         SQL_VARBINARY,
101         SQL_VARCHAR,
102         0
103 };
104
105
106 Int4
107 sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
108 {
109         Int4            pgType;
110         ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
111
112         switch (fSqlType)
113         {
114                 case SQL_BINARY:
115                         pgType = PG_TYPE_BYTEA;
116                         break;
117
118                 case SQL_CHAR:
119                         pgType = PG_TYPE_BPCHAR;
120                         break;
121
122                 case SQL_BIT:
123                         pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
124                         break;
125
126                 case SQL_DATE:
127                         pgType = PG_TYPE_DATE;
128                         break;
129
130                 case SQL_DOUBLE:
131                 case SQL_FLOAT:
132                         pgType = PG_TYPE_FLOAT8;
133                         break;
134
135                 case SQL_DECIMAL:
136                 case SQL_NUMERIC:
137                         pgType = PG_TYPE_NUMERIC;
138                         break;
139
140                 case SQL_BIGINT:
141                         pgType = PG_TYPE_INT8;
142                         break;
143
144                 case SQL_INTEGER:
145                         pgType = PG_TYPE_INT4;
146                         break;
147
148                 case SQL_LONGVARBINARY:
149                         pgType = PG_TYPE_LO;
150                         break;
151
152                 case SQL_LONGVARCHAR:
153                         pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
154                         break;
155
156                 case SQL_REAL:
157                         pgType = PG_TYPE_FLOAT4;
158                         break;
159
160                 case SQL_SMALLINT:
161                 case SQL_TINYINT:
162                         pgType = PG_TYPE_INT2;
163                         break;
164
165                 case SQL_TIME:
166                         pgType = PG_TYPE_TIME;
167                         break;
168
169                 case SQL_TIMESTAMP:
170                         pgType = PG_TYPE_DATETIME;
171                         break;
172
173                 case SQL_VARBINARY:
174                         pgType = PG_TYPE_BYTEA;
175                         break;
176
177                 case SQL_VARCHAR:
178                         pgType = PG_TYPE_VARCHAR;
179                         break;
180
181                 default:
182                         pgType = 0;                     /* ??? */
183                         break;
184         }
185
186         return pgType;
187 }
188
189
190 /*
191  *      There are two ways of calling this function:
192  *
193  *      1.      When going through the supported PG types (SQLGetTypeInfo)
194  *
195  *      2.      When taking any type id (SQLColumns, SQLGetData)
196  *
197  *      The first type will always work because all the types defined are returned here.
198  *      The second type will return a default based on global parameter when it does not
199  *      know.   This allows for supporting
200  *      types that are unknown.  All other pg routines in here return a suitable default.
201  */
202 Int2
203 pgtype_to_sqltype(StatementClass *stmt, Int4 type)
204 {
205         ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
206         switch (type)
207         {
208                 case PG_TYPE_CHAR:
209                 case PG_TYPE_CHAR2:
210                 case PG_TYPE_CHAR4:
211                 case PG_TYPE_CHAR8:
212                 case PG_TYPE_NAME:
213                         return SQL_CHAR;
214
215                 case PG_TYPE_BPCHAR:
216                         return SQL_CHAR;
217
218                 case PG_TYPE_VARCHAR:
219                         return SQL_VARCHAR;
220
221                 case PG_TYPE_TEXT:
222                         return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
223
224                 case PG_TYPE_BYTEA:
225                         return SQL_VARBINARY;
226                 case PG_TYPE_LO:
227                         return SQL_LONGVARBINARY;
228
229                 case PG_TYPE_INT2:
230                         return SQL_SMALLINT;
231
232                 case PG_TYPE_OID:
233                 case PG_TYPE_XID:
234                 case PG_TYPE_INT4:
235                         return SQL_INTEGER;
236
237                         /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
238                 case PG_TYPE_INT8:
239                         return SQL_CHAR;
240
241                 case PG_TYPE_NUMERIC:
242                         return SQL_NUMERIC;
243
244                 case PG_TYPE_FLOAT4:
245                         return SQL_REAL;
246                 case PG_TYPE_FLOAT8:
247                         return SQL_FLOAT;
248                 case PG_TYPE_DATE:
249                         return SQL_DATE;
250                 case PG_TYPE_TIME:
251                         return SQL_TIME;
252                 case PG_TYPE_ABSTIME:
253                 case PG_TYPE_DATETIME:
254                 case PG_TYPE_TIMESTAMP:
255                         return SQL_TIMESTAMP;
256                 case PG_TYPE_MONEY:
257                         return SQL_FLOAT;
258                 case PG_TYPE_BOOL:
259                         return ci->drivers.bools_as_char ? SQL_CHAR : SQL_BIT;
260
261                 default:
262
263                         /*
264                          * first, check to see if 'type' is in list.  If not, look up
265                          * with query. Add oid, name to list.  If it's already in
266                          * list, just return.
267                          */
268                         /* hack until permanent type is available */
269                         if (type == stmt->hdbc->lobj_type)
270                                 return SQL_LONGVARBINARY;
271
272                         return ci->drivers.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
273         }
274 }
275
276
277 Int2
278 pgtype_to_ctype(StatementClass *stmt, Int4 type)
279 {
280         ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
281         switch (type)
282         {
283                 case PG_TYPE_INT8:
284                         return SQL_C_CHAR;
285                 case PG_TYPE_NUMERIC:
286                         return SQL_C_CHAR;
287                 case PG_TYPE_INT2:
288                         return SQL_C_SSHORT;
289                 case PG_TYPE_OID:
290                 case PG_TYPE_XID:
291                 case PG_TYPE_INT4:
292                         return SQL_C_SLONG;
293                 case PG_TYPE_FLOAT4:
294                         return SQL_C_FLOAT;
295                 case PG_TYPE_FLOAT8:
296                         return SQL_C_DOUBLE;
297                 case PG_TYPE_DATE:
298                         return SQL_C_DATE;
299                 case PG_TYPE_TIME:
300                         return SQL_C_TIME;
301                 case PG_TYPE_ABSTIME:
302                 case PG_TYPE_DATETIME:
303                 case PG_TYPE_TIMESTAMP:
304                         return SQL_C_TIMESTAMP;
305                 case PG_TYPE_MONEY:
306                         return SQL_C_FLOAT;
307                 case PG_TYPE_BOOL:
308                         return ci->drivers.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
309
310                 case PG_TYPE_BYTEA:
311                         return SQL_C_BINARY;
312                 case PG_TYPE_LO:
313                         return SQL_C_BINARY;
314
315                 default:
316                         /* hack until permanent type is available */
317                         if (type == stmt->hdbc->lobj_type)
318                                 return SQL_C_BINARY;
319
320                         return SQL_C_CHAR;
321         }
322 }
323
324
325 char *
326 pgtype_to_name(StatementClass *stmt, Int4 type)
327 {
328         switch (type)
329         {
330                 case PG_TYPE_CHAR:
331                         return "char";
332                 case PG_TYPE_CHAR2:
333                         return "char2";
334                 case PG_TYPE_CHAR4:
335                         return "char4";
336                 case PG_TYPE_CHAR8:
337                         return "char8";
338                 case PG_TYPE_INT8:
339                         return "int8";
340                 case PG_TYPE_NUMERIC:
341                         return "numeric";
342                 case PG_TYPE_VARCHAR:
343                         return "varchar";
344                 case PG_TYPE_BPCHAR:
345                         return "char";
346                 case PG_TYPE_TEXT:
347                         return "text";
348                 case PG_TYPE_NAME:
349                         return "name";
350                 case PG_TYPE_INT2:
351                         return "int2";
352                 case PG_TYPE_OID:
353                         return "oid";
354                 case PG_TYPE_INT4:
355                         return "int4";
356                 case PG_TYPE_FLOAT4:
357                         return "float4";
358                 case PG_TYPE_FLOAT8:
359                         return "float8";
360                 case PG_TYPE_DATE:
361                         return "date";
362                 case PG_TYPE_TIME:
363                         return "time";
364                 case PG_TYPE_ABSTIME:
365                         return "abstime";
366                 case PG_TYPE_DATETIME:
367                         return "datetime";
368                 case PG_TYPE_TIMESTAMP:
369                         return "timestamp";
370                 case PG_TYPE_MONEY:
371                         return "money";
372                 case PG_TYPE_BOOL:
373                         return "bool";
374                 case PG_TYPE_BYTEA:
375                         return "bytea";
376
377                 case PG_TYPE_LO:
378                         return PG_TYPE_LO_NAME;
379
380                 default:
381                         /* hack until permanent type is available */
382                         if (type == stmt->hdbc->lobj_type)
383                                 return PG_TYPE_LO_NAME;
384
385                         /*
386                          * "unknown" can actually be used in alter table because it is
387                          * a real PG type!
388                          */
389                         return "unknown";
390         }
391 }
392
393
394 static Int2
395 getNumericScale(StatementClass *stmt, Int4 type, int col)
396 {
397         Int4            atttypmod;
398         QResultClass *result;
399         ColumnInfoClass *flds;
400
401         mylog("getNumericScale: type=%d, col=%d\n", type, col);
402
403         if (col < 0)
404                 return PG_NUMERIC_MAX_SCALE;
405
406         result = SC_get_Result(stmt);
407
408         /*
409          * Manual Result Sets -- use assigned column width (i.e., from
410          * set_tuplefield_string)
411          */
412         if (stmt->manual_result)
413         {
414                 flds = result->fields;
415                 if (flds)
416                         return flds->adtsize[col];
417                 else
418                         return PG_NUMERIC_MAX_SCALE;
419         }
420
421         atttypmod = QR_get_atttypmod(result, col);
422         if (atttypmod > -1)
423                 return (atttypmod & 0xffff);
424         else
425                 return (QR_get_display_size(result, col) ?
426                                 QR_get_display_size(result, col) :
427                                 PG_NUMERIC_MAX_SCALE);
428 }
429
430
431 static Int4
432 getNumericPrecision(StatementClass *stmt, Int4 type, int col)
433 {
434         Int4            atttypmod;
435         QResultClass *result;
436         ColumnInfoClass *flds;
437
438         mylog("getNumericPrecision: type=%d, col=%d\n", type, col);
439
440         if (col < 0)
441                 return PG_NUMERIC_MAX_PRECISION;
442
443         result = SC_get_Result(stmt);
444
445         /*
446          * Manual Result Sets -- use assigned column width (i.e., from
447          * set_tuplefield_string)
448          */
449         if (stmt->manual_result)
450         {
451                 flds = result->fields;
452                 if (flds)
453                         return flds->adtsize[col];
454                 else
455                         return PG_NUMERIC_MAX_PRECISION;
456         }
457
458         atttypmod = QR_get_atttypmod(result, col);
459         if (atttypmod > -1)
460                 return (atttypmod >> 16) & 0xffff;
461         else
462                 return (QR_get_display_size(result, col) >= 0 ?
463                                 QR_get_display_size(result, col) :
464                                 PG_NUMERIC_MAX_PRECISION);
465 }
466
467
468 Int4
469 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
470 {
471         int                     p = -1,
472                                 maxsize;
473         QResultClass *result;
474         ColumnInfoClass *flds;
475         ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
476
477         mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as);
478
479         /* Assign Maximum size based on parameters */
480         switch (type)
481         {
482                 case PG_TYPE_TEXT:
483                         if (ci->drivers.text_as_longvarchar)
484                                 maxsize = ci->drivers.max_longvarchar_size;
485                         else
486                                 maxsize = ci->drivers.max_varchar_size;
487                         break;
488
489                 case PG_TYPE_VARCHAR:
490                 case PG_TYPE_BPCHAR:
491                         maxsize = ci->drivers.max_varchar_size;
492                         break;
493
494                 default:
495                         if (ci->drivers.unknowns_as_longvarchar)
496                                 maxsize = ci->drivers.max_longvarchar_size;
497                         else
498                                 maxsize = ci->drivers.max_varchar_size;
499                         break;
500         }
501
502         /*
503          * Static Precision (i.e., the Maximum Precision of the datatype) This
504          * has nothing to do with a result set.
505          */
506         if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
507         {
508                 if (PG_VERSION_GE(SC_get_conn(stmt), 7.1))
509                         maxsize = 0;
510                 else 
511                         maxsize = TEXT_FIELD_SIZE;
512         }
513         if (col < 0)
514                 return maxsize;
515
516         result = SC_get_Result(stmt);
517
518         /*
519          * Manual Result Sets -- use assigned column width (i.e., from
520          * set_tuplefield_string)
521          */
522         if (stmt->manual_result)
523         {
524                 flds = result->fields;
525                 if (flds)
526                         return flds->adtsize[col];
527                 else
528                         return maxsize;
529         }
530
531         /* Size is unknown -- handle according to parameter */
532         if (QR_get_atttypmod(result, col) > -1)
533                 return QR_get_atttypmod(result, col);
534
535         if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
536         {
537                 p = QR_get_display_size(result, col);
538                 mylog("getCharPrecision: LONGEST: p = %d\n", p);
539         }
540
541         if (p < 0 && handle_unknown_size_as == UNKNOWNS_AS_MAX)
542                 return maxsize;
543         else
544                 return p;
545 }
546
547
548 /*
549  *      For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
550  *      override this length with the atttypmod length from pg_attribute .
551  *
552  *      If col >= 0, then will attempt to get the info from the result set.
553  *      This is used for functions SQLDescribeCol and SQLColAttributes.
554  */
555 Int4
556 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
557 {
558         switch (type)
559         {
560                 case PG_TYPE_CHAR:
561                         return 1;
562                 case PG_TYPE_CHAR2:
563                         return 2;
564                 case PG_TYPE_CHAR4:
565                         return 4;
566                 case PG_TYPE_CHAR8:
567                         return 8;
568
569                 case PG_TYPE_NAME:
570                         return NAME_FIELD_SIZE;
571
572                 case PG_TYPE_INT2:
573                         return 5;
574
575                 case PG_TYPE_OID:
576                 case PG_TYPE_XID:
577                 case PG_TYPE_INT4:
578                         return 10;
579
580                 case PG_TYPE_INT8:
581                         return 19;                      /* signed */
582
583                 case PG_TYPE_NUMERIC:
584                         return getNumericPrecision(stmt, type, col);
585
586                 case PG_TYPE_FLOAT4:
587                 case PG_TYPE_MONEY:
588                         return 7;
589
590                 case PG_TYPE_FLOAT8:
591                         return 15;
592
593                 case PG_TYPE_DATE:
594                         return 10;
595                 case PG_TYPE_TIME:
596                         return 8;
597
598                 case PG_TYPE_ABSTIME:
599                 case PG_TYPE_DATETIME:
600                 case PG_TYPE_TIMESTAMP:
601                         /*return 19;*/
602 return 21;
603
604                 case PG_TYPE_BOOL:
605                         return 1;
606
607                 case PG_TYPE_LO:
608                         return SQL_NO_TOTAL;
609
610                 default:
611
612                         if (type == stmt->hdbc->lobj_type)      /* hack until permanent
613                                                                                                  * type is available */
614                                 return SQL_NO_TOTAL;
615
616                         /* Handle Character types and unknown types */
617                         return getCharPrecision(stmt, type, col, handle_unknown_size_as);
618         }
619 }
620
621
622 Int4
623 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
624 {
625         switch (type)
626         {
627                 case PG_TYPE_INT2:
628                         return 6;
629
630                 case PG_TYPE_OID:
631                 case PG_TYPE_XID:
632                         return 10;
633
634                 case PG_TYPE_INT4:
635                         return 11;
636
637                 case PG_TYPE_INT8:
638                         return 20;                      /* signed: 19 digits + sign */
639
640                 case PG_TYPE_NUMERIC:
641                         return getNumericPrecision(stmt, type, col) + 2;
642
643                 case PG_TYPE_MONEY:
644                         return 15;                      /* ($9,999,999.99) */
645
646                 case PG_TYPE_FLOAT4:
647                         return 13;
648
649                 case PG_TYPE_FLOAT8:
650                         return 22;
651
652                         /* Character types use regular precision */
653                 default:
654                         return pgtype_precision(stmt, type, col, handle_unknown_size_as);
655         }
656 }
657
658
659 /*
660  *      For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
661  *      override this length with the atttypmod length from pg_attribute
662  */
663 Int4
664 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
665 {
666         switch (type)
667         {
668                 case PG_TYPE_INT2:
669                         return 2;
670
671                 case PG_TYPE_OID:
672                 case PG_TYPE_XID:
673                 case PG_TYPE_INT4:
674                         return 4;
675
676                 case PG_TYPE_INT8:
677                         return 20;                      /* signed: 19 digits + sign */
678
679                 case PG_TYPE_NUMERIC:
680                         return getNumericPrecision(stmt, type, col) + 2;
681
682                 case PG_TYPE_FLOAT4:
683                 case PG_TYPE_MONEY:
684                         return 4;
685
686                 case PG_TYPE_FLOAT8:
687                         return 8;
688
689                 case PG_TYPE_DATE:
690                 case PG_TYPE_TIME:
691                         return 6;
692
693                 case PG_TYPE_ABSTIME:
694                 case PG_TYPE_DATETIME:
695                 case PG_TYPE_TIMESTAMP:
696                         return 16;
697
698                         /* Character types (and NUMERIC) use the default precision */
699                 case PG_TYPE_VARCHAR:
700                 case PG_TYPE_BPCHAR:
701 #ifdef MULTIBYTE
702                         /* after 7.2 */
703                         if (PG_VERSION_GE(SC_get_conn(stmt), 7.2))
704                                 return 3 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
705                         else
706 #else
707                         /* CR -> CR/LF */
708                                 return 2 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
709 #endif /* MULTIBYTE */
710                 default:
711                         return pgtype_precision(stmt, type, col, handle_unknown_size_as);
712         }
713 }
714
715
716 Int2
717 pgtype_scale(StatementClass *stmt, Int4 type, int col)
718 {
719         switch (type)
720         {
721                 case PG_TYPE_INT2:
722                 case PG_TYPE_OID:
723                 case PG_TYPE_XID:
724                 case PG_TYPE_INT4:
725                 case PG_TYPE_INT8:
726                 case PG_TYPE_FLOAT4:
727                 case PG_TYPE_FLOAT8:
728                 case PG_TYPE_MONEY:
729                 case PG_TYPE_BOOL:
730
731                         /*
732                          * Number of digits to the right of the decimal point in
733                          * "yyyy-mm=dd hh:mm:ss[.f...]"
734                          */
735                 case PG_TYPE_ABSTIME:
736                 case PG_TYPE_DATETIME:
737                 case PG_TYPE_TIMESTAMP:
738                         return 0;
739
740                 case PG_TYPE_NUMERIC:
741                         return getNumericScale(stmt, type, col);
742
743                 default:
744                         return -1;
745         }
746 }
747
748
749 Int2
750 pgtype_radix(StatementClass *stmt, Int4 type)
751 {
752         switch (type)
753         {
754                 case PG_TYPE_INT2:
755                 case PG_TYPE_OID:
756                 case PG_TYPE_INT4:
757                 case PG_TYPE_INT8:
758                 case PG_TYPE_NUMERIC:
759                 case PG_TYPE_FLOAT4:
760                 case PG_TYPE_MONEY:
761                 case PG_TYPE_FLOAT8:
762                         return 10;
763                 default:
764                         return -1;
765         }
766 }
767
768
769 Int2
770 pgtype_nullable(StatementClass *stmt, Int4 type)
771 {
772         return SQL_NULLABLE;            /* everything should be nullable */
773 }
774
775
776 Int2
777 pgtype_auto_increment(StatementClass *stmt, Int4 type)
778 {
779         switch (type)
780         {
781                 case PG_TYPE_INT2:
782                 case PG_TYPE_OID:
783                 case PG_TYPE_XID:
784                 case PG_TYPE_INT4:
785                 case PG_TYPE_FLOAT4:
786                 case PG_TYPE_MONEY:
787                 case PG_TYPE_BOOL:
788                 case PG_TYPE_FLOAT8:
789                 case PG_TYPE_INT8:
790                 case PG_TYPE_NUMERIC:
791
792                 case PG_TYPE_DATE:
793                 case PG_TYPE_TIME:
794                 case PG_TYPE_ABSTIME:
795                 case PG_TYPE_DATETIME:
796                 case PG_TYPE_TIMESTAMP:
797                         return FALSE;
798
799                 default:
800                         return -1;
801         }
802 }
803
804
805 Int2
806 pgtype_case_sensitive(StatementClass *stmt, Int4 type)
807 {
808         switch (type)
809         {
810                 case PG_TYPE_CHAR:
811
812                 case PG_TYPE_CHAR2:
813                 case PG_TYPE_CHAR4:
814                 case PG_TYPE_CHAR8:
815
816                 case PG_TYPE_VARCHAR:
817                 case PG_TYPE_BPCHAR:
818                 case PG_TYPE_TEXT:
819                 case PG_TYPE_NAME:
820                         return TRUE;
821
822                 default:
823                         return FALSE;
824         }
825 }
826
827
828 Int2
829 pgtype_money(StatementClass *stmt, Int4 type)
830 {
831         switch (type)
832         {
833                 case PG_TYPE_MONEY:
834                         return TRUE;
835                 default:
836                         return FALSE;
837         }
838 }
839
840
841 Int2
842 pgtype_searchable(StatementClass *stmt, Int4 type)
843 {
844         switch (type)
845         {
846                 case PG_TYPE_CHAR:
847                 case PG_TYPE_CHAR2:
848                 case PG_TYPE_CHAR4:
849                 case PG_TYPE_CHAR8:
850
851                 case PG_TYPE_VARCHAR:
852                 case PG_TYPE_BPCHAR:
853                 case PG_TYPE_TEXT:
854                 case PG_TYPE_NAME:
855                         return SQL_SEARCHABLE;
856
857                 default:
858                         return SQL_ALL_EXCEPT_LIKE;
859         }
860 }
861
862
863 Int2
864 pgtype_unsigned(StatementClass *stmt, Int4 type)
865 {
866         switch (type)
867         {
868                 case PG_TYPE_OID:
869                 case PG_TYPE_XID:
870                         return TRUE;
871
872                 case PG_TYPE_INT2:
873                 case PG_TYPE_INT4:
874                 case PG_TYPE_INT8:
875                 case PG_TYPE_NUMERIC:
876                 case PG_TYPE_FLOAT4:
877                 case PG_TYPE_FLOAT8:
878                 case PG_TYPE_MONEY:
879                         return FALSE;
880
881                 default:
882                         return -1;
883         }
884 }
885
886
887 char *
888 pgtype_literal_prefix(StatementClass *stmt, Int4 type)
889 {
890         switch (type)
891         {
892                         case PG_TYPE_INT2:
893                         case PG_TYPE_OID:
894                         case PG_TYPE_XID:
895                         case PG_TYPE_INT4:
896                         case PG_TYPE_INT8:
897                         case PG_TYPE_NUMERIC:
898                         case PG_TYPE_FLOAT4:
899                         case PG_TYPE_FLOAT8:
900                         case PG_TYPE_MONEY:return NULL;
901
902                 default:
903                         return "'";
904         }
905 }
906
907
908 char *
909 pgtype_literal_suffix(StatementClass *stmt, Int4 type)
910 {
911         switch (type)
912         {
913                         case PG_TYPE_INT2:
914                         case PG_TYPE_OID:
915                         case PG_TYPE_XID:
916                         case PG_TYPE_INT4:
917                         case PG_TYPE_INT8:
918                         case PG_TYPE_NUMERIC:
919                         case PG_TYPE_FLOAT4:
920                         case PG_TYPE_FLOAT8:
921                         case PG_TYPE_MONEY:return NULL;
922
923                 default:
924                         return "'";
925         }
926 }
927
928
929 char *
930 pgtype_create_params(StatementClass *stmt, Int4 type)
931 {
932         switch (type)
933         {
934                         case PG_TYPE_CHAR:
935                         case PG_TYPE_VARCHAR:return "max. length";
936                 default:
937                         return NULL;
938         }
939 }
940
941
942 Int2
943 sqltype_to_default_ctype(Int2 sqltype)
944 {
945
946         /*
947          * from the table on page 623 of ODBC 2.0 Programmer's Reference
948          * (Appendix D)
949          */
950         switch (sqltype)
951         {
952                 case SQL_CHAR:
953                 case SQL_VARCHAR:
954                 case SQL_LONGVARCHAR:
955                 case SQL_DECIMAL:
956                 case SQL_NUMERIC:
957                 case SQL_BIGINT:
958                         return SQL_C_CHAR;
959
960                 case SQL_BIT:
961                         return SQL_C_BIT;
962
963                 case SQL_TINYINT:
964                         return SQL_C_STINYINT;
965
966                 case SQL_SMALLINT:
967                         return SQL_C_SSHORT;
968
969                 case SQL_INTEGER:
970                         return SQL_C_SLONG;
971
972                 case SQL_REAL:
973                         return SQL_C_FLOAT;
974
975                 case SQL_FLOAT:
976                 case SQL_DOUBLE:
977                         return SQL_C_DOUBLE;
978
979                 case SQL_BINARY:
980                 case SQL_VARBINARY:
981                 case SQL_LONGVARBINARY:
982                         return SQL_C_BINARY;
983
984                 case SQL_DATE:
985                         return SQL_C_DATE;
986
987                 case SQL_TIME:
988                         return SQL_C_TIME;
989
990                 case SQL_TIMESTAMP:
991                         return SQL_C_TIMESTAMP;
992
993                 default:
994                         /* should never happen */
995                         return SQL_C_CHAR;
996         }
997 }
998
999 Int4
1000 ctype_length(Int2 ctype)
1001 {
1002         switch (ctype)
1003         {
1004                 case SQL_C_SSHORT:
1005                 case SQL_C_SHORT:
1006                         return sizeof(SWORD);
1007
1008                 case SQL_C_USHORT:
1009                         return sizeof(UWORD);
1010
1011                 case SQL_C_SLONG:
1012                 case SQL_C_LONG:
1013                         return sizeof(SDWORD);
1014
1015                 case SQL_C_ULONG:
1016                         return sizeof(UDWORD);
1017
1018                 case SQL_C_FLOAT:
1019                         return sizeof(SFLOAT);
1020
1021                 case SQL_C_DOUBLE:
1022                         return sizeof(SDOUBLE);
1023
1024                 case SQL_C_BIT:
1025                         return sizeof(UCHAR);
1026
1027                 case SQL_C_STINYINT:
1028                 case SQL_C_TINYINT:
1029                         return sizeof(SCHAR);
1030
1031                 case SQL_C_UTINYINT:
1032                         return sizeof(UCHAR);
1033
1034                 case SQL_C_DATE:
1035                         return sizeof(DATE_STRUCT);
1036
1037                 case SQL_C_TIME:
1038                         return sizeof(TIME_STRUCT);
1039
1040                 case SQL_C_TIMESTAMP:
1041                         return sizeof(TIMESTAMP_STRUCT);
1042
1043                 case SQL_C_BINARY:
1044                 case SQL_C_CHAR:
1045                         return 0;
1046
1047                 default:                                /* should never happen */
1048                         return 0;
1049         }
1050 }