aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/pgtypes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/pgtypes.c')
-rw-r--r--src/interfaces/odbc/pgtypes.c1475
1 files changed, 0 insertions, 1475 deletions
diff --git a/src/interfaces/odbc/pgtypes.c b/src/interfaces/odbc/pgtypes.c
deleted file mode 100644
index 6f3d1df3a94..00000000000
--- a/src/interfaces/odbc/pgtypes.c
+++ /dev/null
@@ -1,1475 +0,0 @@
-/*--------
- * Module: pgtypes.c
- *
- * Description: This module contains routines for getting information
- * about the supported Postgres data types. Only the
- * function pgtype_to_sqltype() returns an unknown condition.
- * All other functions return a suitable default so that
- * even data types that are not directly supported can be
- * used (it is handled as char data).
- *
- * Classes: n/a
- *
- * API functions: none
- *
- * Comments: See "notice.txt" for copyright and license information.
- *--------
- */
-
-#include "pgtypes.h"
-
-#include "dlg_specific.h"
-#include "statement.h"
-#include "connection.h"
-#include "environ.h"
-#include "qresult.h"
-
-
-
-Int4 getCharColumnSize(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
-
-/*
- * these are the types we support. all of the pgtype_ functions should
- * return values for each one of these.
- * Even types not directly supported are handled as character types
- * so all types should work (points, etc.)
- */
-
-/*
- * ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all
- * the SQL TYPES are reported and mapped to a corresponding Postgres Type
- */
-
-/*
-Int4 pgtypes_defined[] = {
- PG_TYPE_CHAR,
- PG_TYPE_CHAR2,
- PG_TYPE_CHAR4,
- PG_TYPE_CHAR8,
- PG_TYPE_CHAR16,
- PG_TYPE_NAME,
- PG_TYPE_VARCHAR,
- PG_TYPE_BPCHAR,
- PG_TYPE_DATE,
- PG_TYPE_TIME,
- PG_TYPE_TIME_WITH_TMZONE,
- PG_TYPE_DATETIME,
- PG_TYPE_ABSTIME,
- PG_TYPE_TIMESTAMP_NO_TMZONE,
- PG_TYPE_TIMESTAMP,
- PG_TYPE_TEXT,
- PG_TYPE_INT2,
- PG_TYPE_INT4,
- PG_TYPE_FLOAT4,
- PG_TYPE_FLOAT8,
- PG_TYPE_OID,
- PG_TYPE_MONEY,
- PG_TYPE_BOOL,
- PG_TYPE_BYTEA,
- PG_TYPE_LO,
- 0 };
-*/
-
-
-/* These are NOW the SQL Types reported in SQLGetTypeInfo. */
-Int2 sqlTypes[] = {
- SQL_BIGINT,
- /* SQL_BINARY, -- Commented out because VarBinary is more correct. */
- SQL_BIT,
- SQL_CHAR,
- SQL_DATE,
- SQL_DECIMAL,
- SQL_DOUBLE,
- SQL_FLOAT,
- SQL_INTEGER,
- SQL_LONGVARBINARY,
- SQL_LONGVARCHAR,
- SQL_NUMERIC,
- SQL_REAL,
- SQL_SMALLINT,
- SQL_TIME,
- SQL_TIMESTAMP,
- SQL_TINYINT,
- SQL_VARBINARY,
- SQL_VARCHAR,
-#ifdef UNICODE_SUPPORT
- SQL_WCHAR,
- SQL_WVARCHAR,
- SQL_WLONGVARCHAR,
-#endif /* UNICODE_SUPPORT */
- 0
-};
-
-#if (ODBCVER >= 0x0300) && defined(OBDCINT64)
-/* #define ALLOWED_C_BIGINT SQL_C_SBIGINT */
-#define ALLOWED_C_BIGINT SQL_C_CHAR /* Delphi should be either ? */
-#else
-#define ALLOWED_C_BIGINT SQL_C_CHAR
-#endif
-
-Int4
-sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
-{
- Int4 pgType;
- ConnectionClass *conn = SC_get_conn(stmt);
- ConnInfo *ci = &(conn->connInfo);
-
- switch (fSqlType)
- {
- case SQL_BINARY:
- pgType = PG_TYPE_BYTEA;
- break;
-
- case SQL_CHAR:
- pgType = PG_TYPE_BPCHAR;
- break;
-
-#ifdef UNICODE_SUPPORT
- case SQL_WCHAR:
- pgType = PG_TYPE_BPCHAR;
- break;
-#endif /* UNICODE_SUPPORT */
-
- case SQL_BIT:
- pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
- break;
-
- case SQL_DATE:
-#if (ODBCVER >= 0x0300)
- case SQL_TYPE_DATE:
-#endif /* ODBCVER */
- pgType = PG_TYPE_DATE;
- break;
-
- case SQL_DOUBLE:
- case SQL_FLOAT:
- pgType = PG_TYPE_FLOAT8;
- break;
-
- case SQL_DECIMAL:
- case SQL_NUMERIC:
- pgType = PG_TYPE_NUMERIC;
- break;
-
- case SQL_BIGINT:
- pgType = PG_TYPE_INT8;
- break;
-
- case SQL_INTEGER:
- pgType = PG_TYPE_INT4;
- break;
-
- case SQL_LONGVARBINARY:
- pgType = PG_TYPE_LO;
- break;
-
- case SQL_LONGVARCHAR:
- pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
- break;
-
-#ifdef UNICODE_SUPPORT
- case SQL_WLONGVARCHAR:
- pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
- break;
-#endif /* UNICODE_SUPPORT */
-
- case SQL_REAL:
- pgType = PG_TYPE_FLOAT4;
- break;
-
- case SQL_SMALLINT:
- case SQL_TINYINT:
- pgType = PG_TYPE_INT2;
- break;
-
- case SQL_TIME:
-#if (ODBCVER >= 0x0300)
- case SQL_TYPE_TIME:
-#endif /* ODBCVER */
- pgType = PG_TYPE_TIME;
- break;
-
- case SQL_TIMESTAMP:
-#if (ODBCVER >= 0x0300)
- case SQL_TYPE_TIMESTAMP:
-#endif /* ODBCVER */
- pgType = PG_TYPE_DATETIME;
- break;
-
- case SQL_VARBINARY:
- pgType = PG_TYPE_BYTEA;
- break;
-
- case SQL_VARCHAR:
- pgType = PG_TYPE_VARCHAR;
- break;
-
-#if UNICODE_SUPPORT
- case SQL_WVARCHAR:
- pgType = PG_TYPE_VARCHAR;
- break;
-#endif /* UNICODE_SUPPORT */
-
- default:
- pgType = 0; /* ??? */
- break;
- }
-
- return pgType;
-}
-
-
-/*
- * There are two ways of calling this function:
- *
- * 1. When going through the supported PG types (SQLGetTypeInfo)
- *
- * 2. When taking any type id (SQLColumns, SQLGetData)
- *
- * The first type will always work because all the types defined are returned here.
- * The second type will return a default based on global parameter when it does not
- * know. This allows for supporting
- * types that are unknown. All other pg routines in here return a suitable default.
- */
-Int2
-pgtype_to_concise_type(StatementClass *stmt, Int4 type)
-{
- ConnectionClass *conn = SC_get_conn(stmt);
- ConnInfo *ci = &(conn->connInfo);
-#if (ODBCVER >= 0x0300)
- EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
-#endif /* ODBCVER */
-
- switch (type)
- {
- case PG_TYPE_CHAR:
- case PG_TYPE_CHAR2:
- case PG_TYPE_CHAR4:
- case PG_TYPE_CHAR8:
- case PG_TYPE_NAME:
- return SQL_CHAR;
-
-#ifdef UNICODE_SUPPORT
- case PG_TYPE_BPCHAR:
- return conn->unicode ? SQL_WCHAR : SQL_CHAR;
-
- case PG_TYPE_VARCHAR:
- return conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR;
-
- case PG_TYPE_TEXT:
- return ci->drivers.text_as_longvarchar ?
- (conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR) :
- (conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR);
-
-#else
- case PG_TYPE_BPCHAR:
- return SQL_CHAR;
-
- case PG_TYPE_VARCHAR:
- return SQL_VARCHAR;
-
- case PG_TYPE_TEXT:
- return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
-#endif /* UNICODE_SUPPORT */
-
- case PG_TYPE_BYTEA:
- return SQL_VARBINARY;
- case PG_TYPE_LO:
- return SQL_LONGVARBINARY;
-
- case PG_TYPE_INT2:
- return SQL_SMALLINT;
-
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- return SQL_INTEGER;
-
- /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
- case PG_TYPE_INT8:
- if (ci->int8_as != 0)
- return ci->int8_as;
- if (conn->ms_jet)
- return SQL_NUMERIC; /* maybe a little better than SQL_VARCHAR */
-#if (ODBCVER >= 0x0300)
- return SQL_BIGINT;
-#else
- return SQL_VARCHAR;
-#endif /* ODBCVER */
-
- case PG_TYPE_NUMERIC:
- return SQL_NUMERIC;
-
- case PG_TYPE_FLOAT4:
- return SQL_REAL;
- case PG_TYPE_FLOAT8:
- return SQL_FLOAT;
- case PG_TYPE_DATE:
-#if (ODBCVER >= 0x0300)
- if (EN_is_odbc3(env))
- return SQL_TYPE_DATE;
-#endif /* ODBCVER */
- return SQL_DATE;
- case PG_TYPE_TIME:
-#if (ODBCVER >= 0x0300)
- if (EN_is_odbc3(env))
- return SQL_TYPE_TIME;
-#endif /* ODBCVER */
- return SQL_TIME;
- case PG_TYPE_ABSTIME:
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- case PG_TYPE_TIMESTAMP:
-#if (ODBCVER >= 0x0300)
- if (EN_is_odbc3(env))
- return SQL_TYPE_TIMESTAMP;
-#endif /* ODBCVER */
- return SQL_TIMESTAMP;
- case PG_TYPE_MONEY:
- return SQL_FLOAT;
- case PG_TYPE_BOOL:
- return ci->drivers.bools_as_char ? SQL_CHAR : SQL_BIT;
-
- default:
-
- /*
- * first, check to see if 'type' is in list. If not, look up
- * with query. Add oid, name to list. If it's already in
- * list, just return.
- */
- /* hack until permanent type is available */
- if (type == stmt->hdbc->lobj_type)
- return SQL_LONGVARBINARY;
-
- return ci->drivers.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
- }
-}
-
-Int2
-pgtype_to_sqldesctype(StatementClass *stmt, Int4 type)
-{
- Int2 rettype;
-
- switch (rettype = pgtype_to_concise_type(stmt, type))
- {
-#if (ODBCVER >= 0x0300)
- case SQL_TYPE_DATE:
- case SQL_TYPE_TIME:
- case SQL_TYPE_TIMESTAMP:
- return SQL_DATETIME;
-#endif /* ODBCVER */
- }
- return rettype;
-}
-
-Int2
-pgtype_to_datetime_sub(StatementClass *stmt, Int4 type)
-{
- switch (pgtype_to_concise_type(stmt, type))
- {
-#if (ODBCVER >= 0x0300)
- case SQL_TYPE_DATE:
- return SQL_CODE_DATE;
- case SQL_TYPE_TIME:
- return SQL_CODE_TIME;
- case SQL_TYPE_TIMESTAMP:
- return SQL_CODE_TIMESTAMP;
-#endif /* ODBCVER */
- }
- return -1;
-}
-
-
-Int2
-pgtype_to_ctype(StatementClass *stmt, Int4 type)
-{
- ConnectionClass *conn = SC_get_conn(stmt);
- ConnInfo *ci = &(conn->connInfo);
-#if (ODBCVER >= 0x0300)
- EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
-#endif /* ODBCVER */
-
- switch (type)
- {
- case PG_TYPE_INT8:
-#if (ODBCVER >= 0x0300)
- if (!conn->ms_jet)
- return ALLOWED_C_BIGINT;
-#endif /* ODBCVER */
- return SQL_C_CHAR;
- case PG_TYPE_NUMERIC:
- return SQL_C_CHAR;
- case PG_TYPE_INT2:
- return SQL_C_SSHORT;
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- return SQL_C_SLONG;
- case PG_TYPE_FLOAT4:
- return SQL_C_FLOAT;
- case PG_TYPE_FLOAT8:
- return SQL_C_DOUBLE;
- case PG_TYPE_DATE:
-#if (ODBCVER >= 0x0300)
- if (EN_is_odbc3(env))
- return SQL_C_TYPE_DATE;
-#endif /* ODBCVER */
- return SQL_C_DATE;
- case PG_TYPE_TIME:
-#if (ODBCVER >= 0x0300)
- if (EN_is_odbc3(env))
- return SQL_C_TYPE_TIME;
-#endif /* ODBCVER */
- return SQL_C_TIME;
- case PG_TYPE_ABSTIME:
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- case PG_TYPE_TIMESTAMP:
-#if (ODBCVER >= 0x0300)
- if (EN_is_odbc3(env))
- return SQL_C_TYPE_TIMESTAMP;
-#endif /* ODBCVER */
- return SQL_C_TIMESTAMP;
- case PG_TYPE_MONEY:
- return SQL_C_FLOAT;
- case PG_TYPE_BOOL:
- return ci->drivers.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
-
- case PG_TYPE_BYTEA:
- return SQL_C_BINARY;
- case PG_TYPE_LO:
- return SQL_C_BINARY;
-#ifdef UNICODE_SUPPORT
- case PG_TYPE_BPCHAR:
- case PG_TYPE_VARCHAR:
- case PG_TYPE_TEXT:
- return conn->unicode ? SQL_C_WCHAR : SQL_C_CHAR;
-#endif /* UNICODE_SUPPORT */
-
- default:
- /* hack until permanent type is available */
- if (type == stmt->hdbc->lobj_type)
- return SQL_C_BINARY;
-
- return SQL_C_CHAR;
- }
-}
-
-
-char *
-pgtype_to_name(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_CHAR:
- return "char";
- case PG_TYPE_CHAR2:
- return "char2";
- case PG_TYPE_CHAR4:
- return "char4";
- case PG_TYPE_CHAR8:
- return "char8";
- case PG_TYPE_INT8:
- return "int8";
- case PG_TYPE_NUMERIC:
- return "numeric";
- case PG_TYPE_VARCHAR:
- return "varchar";
- case PG_TYPE_BPCHAR:
- return "char";
- case PG_TYPE_TEXT:
- return "text";
- case PG_TYPE_NAME:
- return "name";
- case PG_TYPE_INT2:
- return "int2";
- case PG_TYPE_OID:
- return "oid";
- case PG_TYPE_INT4:
- return "int4";
- case PG_TYPE_FLOAT4:
- return "float4";
- case PG_TYPE_FLOAT8:
- return "float8";
- case PG_TYPE_DATE:
- return "date";
- case PG_TYPE_TIME:
- return "time";
- case PG_TYPE_ABSTIME:
- return "abstime";
- case PG_TYPE_DATETIME:
- return "datetime";
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- return "timestamp_nozone";
- case PG_TYPE_TIMESTAMP:
- return "timestamp";
- case PG_TYPE_MONEY:
- return "money";
- case PG_TYPE_BOOL:
- return "bool";
- case PG_TYPE_BYTEA:
- return "bytea";
-
- case PG_TYPE_LO:
- return PG_TYPE_LO_NAME;
-
- default:
- /* hack until permanent type is available */
- if (type == stmt->hdbc->lobj_type)
- return PG_TYPE_LO_NAME;
-
- /*
- * "unknown" can actually be used in alter table because it is
- * a real PG type!
- */
- return "unknown";
- }
-}
-
-
-static Int2
-getNumericDecimalDigits(StatementClass *stmt, Int4 type, int col)
-{
- Int4 atttypmod = -1, default_decimal_digits = 6;
- QResultClass *result;
- ColumnInfoClass *flds;
-
- mylog("getNumericDecimalDigits: type=%d, col=%d\n", type, col);
-
- if (col < 0)
- return PG_NUMERIC_MAX_SCALE;
-
- result = SC_get_Curres(stmt);
-
- /*
- * Manual Result Sets -- use assigned column width (i.e., from
- * set_tuplefield_string)
- */
- if (stmt->manual_result)
- {
- flds = result->fields;
- if (flds)
- {
- atttypmod = flds->atttypmod[col];
- if (atttypmod < 0 && flds->adtsize[col] > 0)
- return flds->adtsize[col];
- }
- if (atttypmod < 0)
- return default_decimal_digits;
- }
- else
- atttypmod = QR_get_atttypmod(result, col);
- if (atttypmod > -1)
- return (atttypmod & 0xffff);
- else
- {
- Int4 dsp_size = QR_get_display_size(result, col);
- if (dsp_size <= 0)
- return default_decimal_digits;
- if (dsp_size < 5)
- dsp_size = 5;
- return dsp_size;
- }
-}
-
-
-static Int4
-getNumericColumnSize(StatementClass *stmt, Int4 type, int col)
-{
- Int4 atttypmod = -1, max_column_size = PG_NUMERIC_MAX_PRECISION + PG_NUMERIC_MAX_SCALE, default_column_size = 28;
- QResultClass *result;
- ColumnInfoClass *flds;
-
- mylog("getNumericColumnSize: type=%d, col=%d\n", type, col);
-
- if (col < 0)
- return max_column_size;
-
- result = SC_get_Curres(stmt);
-
- /*
- * Manual Result Sets -- use assigned column width (i.e., from
- * set_tuplefield_string)
- */
- if (stmt->manual_result)
- {
- flds = result->fields;
- if (flds)
- {
- atttypmod = flds->atttypmod[col];
- if (atttypmod < 0 && flds->adtsize[col] > 0)
- return 2 * flds->adtsize[col];
- }
- if (atttypmod < 0)
- return default_column_size;
- }
- else
- atttypmod = QR_get_atttypmod(result, col);
- if (atttypmod > -1)
- return (atttypmod >> 16) & 0xffff;
- else
- {
- Int4 dsp_size = QR_get_display_size(result, col);
- if (dsp_size <= 0)
- return default_column_size;
- dsp_size *= 2;
- if (dsp_size < 10)
- dsp_size = 10;
- return dsp_size;
- }
-}
-
-
-Int4
-getCharColumnSize(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- int p = -1, attlen = -1,
- maxsize;
- QResultClass *result;
- ColumnInfoClass *flds;
- ConnectionClass *conn = SC_get_conn(stmt);
- ConnInfo *ci = &(conn->connInfo);
-
- mylog("getCharColumnSize: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as);
-
- /* Assign Maximum size based on parameters */
- switch (type)
- {
- case PG_TYPE_TEXT:
- if (ci->drivers.text_as_longvarchar)
- maxsize = ci->drivers.max_longvarchar_size;
- else
- maxsize = ci->drivers.max_varchar_size;
- break;
-
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- maxsize = ci->drivers.max_varchar_size;
- break;
-
- default:
- if (ci->drivers.unknowns_as_longvarchar)
- maxsize = ci->drivers.max_longvarchar_size;
- else
- maxsize = ci->drivers.max_varchar_size;
- break;
- }
-
- if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
- {
- if (PG_VERSION_GE(SC_get_conn(stmt), 7.1))
- maxsize = 0;
- else
- maxsize = TEXT_FIELD_SIZE;
- }
- /*
- * Static ColumnSize (i.e., the Maximum ColumnSize of the datatype) This
- * has nothing to do with a result set.
- */
- if (col < 0)
- return maxsize;
-
- result = SC_get_Curres(stmt);
-
- /*
- * Manual Result Sets -- use assigned column width (i.e., from
- * set_tuplefield_string)
- */
- if (stmt->manual_result)
- {
- flds = result->fields;
- if (flds)
- return flds->adtsize[col];
- else
- return maxsize;
- }
-
- p = QR_get_display_size(result, col); /* longest */
- attlen = QR_get_atttypmod(result, col);
- /* Size is unknown -- handle according to parameter */
- if (attlen > 0) /* maybe the length is known */
- {
- if (attlen >= p)
- return attlen;
- switch (type)
- {
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- if (conn->unicode || conn->ms_jet)
- return attlen;
-#if (ODBCVER >= 0x0300)
-#ifdef MULTIBYTE
- return attlen;
-#endif /* MULTIBYTE */
-#endif /* ODBCVER */
- return p;
- }
- }
-
- /* The type is really unknown */
- if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
- {
- mylog("getCharColumnSize: LONGEST: p = %d\n", p);
- if (p >= 0)
- return p;
- }
-
- if (p > maxsize)
- maxsize = p;
- if (handle_unknown_size_as == UNKNOWNS_AS_MAX)
- return maxsize;
- else /* handle_unknown_size_as == DONT_KNOW */
- return -1;
-}
-
-static Int2
-getTimestampDecimalDigits(StatementClass *stmt, Int4 type, int col)
-{
- ConnectionClass *conn = SC_get_conn(stmt);
- Int4 atttypmod;
- QResultClass *result;
- ColumnInfoClass *flds;
-
- mylog("getTimestampDecimalDigits: type=%d, col=%d\n", type, col);
-
- if (col < 0)
- return 0;
- if (PG_VERSION_LT(conn, 7.2))
- return 0;
-
- result = SC_get_Curres(stmt);
-
- /*
- * Manual Result Sets -- use assigned column width (i.e., from
- * set_tuplefield_string)
- */
- atttypmod = 0;
- if (stmt->manual_result)
- {
- flds = result->fields;
- if (flds)
- atttypmod = flds->atttypmod[col];
- mylog("atttypmod1=%d\n", atttypmod);
- }
- else
- atttypmod = QR_get_atttypmod(result, col);
- mylog("atttypmod2=%d\n", atttypmod);
- return (atttypmod > -1 ? atttypmod : 0);
-}
-
-
-static Int4
-getTimestampColumnSize(StatementClass *stmt, Int4 type, int col)
-{
- Int4 fixed,
- scale;
-
- mylog("getTimestampColumnSize: type=%d, col=%d\n", type, col);
-
- switch (type)
- {
- case PG_TYPE_TIME:
- fixed = 8;
- break;
- case PG_TYPE_TIME_WITH_TMZONE:
- fixed = 11;
- break;
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- fixed = 19;
- break;
- default:
- if (USE_ZONE)
- fixed = 22;
- else
- fixed = 19;
- break;
- }
- scale = getTimestampDecimalDigits(stmt, type, col);
- return (scale > 0) ? fixed + 1 + scale : fixed;
-}
-
-/*
- * This corresponds to "precision" in ODBC 2.x.
- *
- * For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
- * override this length with the atttypmod length from pg_attribute .
- *
- * If col >= 0, then will attempt to get the info from the result set.
- * This is used for functions SQLDescribeCol and SQLColAttributes.
- */
-Int4
-pgtype_column_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- switch (type)
- {
- case PG_TYPE_CHAR:
- return 1;
- case PG_TYPE_CHAR2:
- return 2;
- case PG_TYPE_CHAR4:
- return 4;
- case PG_TYPE_CHAR8:
- return 8;
-
- case PG_TYPE_NAME:
- return NAME_FIELD_SIZE;
-
- case PG_TYPE_INT2:
- return 5;
-
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- return 10;
-
- case PG_TYPE_INT8:
- return 19; /* signed */
-
- case PG_TYPE_NUMERIC:
- return getNumericColumnSize(stmt, type, col);
-
- case PG_TYPE_FLOAT4:
- case PG_TYPE_MONEY:
- return 7;
-
- case PG_TYPE_FLOAT8:
- return 15;
-
- case PG_TYPE_DATE:
- return 10;
- case PG_TYPE_TIME:
- return 8;
-
- case PG_TYPE_ABSTIME:
- case PG_TYPE_TIMESTAMP:
- return 22;
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- /* return 22; */
- return getTimestampColumnSize(stmt, type, col);
-
- case PG_TYPE_BOOL:
- {
- BOOL true_is_minus1 = FALSE;
- return true_is_minus1 ? 2 : 1;
- }
-
- case PG_TYPE_LO:
- return SQL_NO_TOTAL;
-
- default:
-
- if (type == stmt->hdbc->lobj_type) /* hack until permanent
- * type is available */
- return SQL_NO_TOTAL;
-
- /* Handle Character types and unknown types */
- return getCharColumnSize(stmt, type, col, handle_unknown_size_as);
- }
-}
-
-/*
- * "precision in ODBC 3.x.
- */
-Int4
-pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- switch (type)
- {
- case PG_TYPE_NUMERIC:
- return getNumericColumnSize(stmt, type, col);
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- return getTimestampDecimalDigits(stmt, type, col);
- }
- return -1;
-}
-
-
-Int4
-pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- int dsize;
-
- switch (type)
- {
- case PG_TYPE_INT2:
- return 6;
-
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- return 10;
-
- case PG_TYPE_INT4:
- return 11;
-
- case PG_TYPE_INT8:
- return 20; /* signed: 19 digits + sign */
-
- case PG_TYPE_NUMERIC:
- dsize = getNumericColumnSize(stmt, type, col);
- return dsize < 0 ? dsize : dsize + 2;
-
- case PG_TYPE_MONEY:
- return 15; /* ($9,999,999.99) */
-
- case PG_TYPE_FLOAT4:
- return 13;
-
- case PG_TYPE_FLOAT8:
- return 22;
-
- /* Character types use regular precision */
- default:
- return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
- }
-}
-
-
-/*
- * The length in bytes of data transferred on an SQLGetData, SQLFetch,
- * or SQLFetchScroll operation if SQL_C_DEFAULT is specified.
- */
-Int4
-pgtype_buffer_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- ConnectionClass *conn = SC_get_conn(stmt);
-
- switch (type)
- {
- case PG_TYPE_INT2:
- return 2; /* sizeof(SQLSMALLINT) */
-
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- return 4; /* sizeof(SQLINTEGER) */
-
- case PG_TYPE_INT8:
- if (SQL_C_CHAR == pgtype_to_ctype(stmt, type))
- return 20; /* signed: 19 digits + sign */
- return 8; /* sizeof(SQLSBININT) */
-
- case PG_TYPE_NUMERIC:
- return getNumericColumnSize(stmt, type, col) + 2;
-
- case PG_TYPE_FLOAT4:
- case PG_TYPE_MONEY:
- return 4; /* sizeof(SQLREAL) */
-
- case PG_TYPE_FLOAT8:
- return 8; /* sizeof(SQLFLOAT) */
-
- case PG_TYPE_DATE:
- case PG_TYPE_TIME:
- return 6; /* sizeof(DATE(TIME)_STRUCT) */
-
- case PG_TYPE_ABSTIME:
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- return 16; /* sizeof(TIMESTAMP_STRUCT) */
-
- /* Character types use the default precision */
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- {
- int coef = 1;
- Int4 prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc;
- if (conn->unicode)
- return prec * 2;
-#ifdef MULTIBYTE
- /* after 7.2 */
- if (PG_VERSION_GE(conn, 7.2))
- coef = 3;
- else
-#endif /* MULTIBYTE */
- if ((conn->connInfo).lf_conversion)
- /* CR -> CR/LF */
- coef = 2;
- if (coef == 1)
- return prec;
- maxvarc = conn->connInfo.drivers.max_varchar_size;
- if (prec <= maxvarc && prec * coef > maxvarc)
- return maxvarc;
- return coef * prec;
- }
- default:
- return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
- }
-}
-
-/*
- */
-Int4
-pgtype_desclength(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- switch (type)
- {
- case PG_TYPE_INT2:
- return 2;
-
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- return 4;
-
- case PG_TYPE_INT8:
- return 20; /* signed: 19 digits + sign */
-
- case PG_TYPE_NUMERIC:
- return getNumericColumnSize(stmt, type, col) + 2;
-
- case PG_TYPE_FLOAT4:
- case PG_TYPE_MONEY:
- return 4;
-
- case PG_TYPE_FLOAT8:
- return 8;
-
- case PG_TYPE_DATE:
- case PG_TYPE_TIME:
- case PG_TYPE_ABSTIME:
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- case PG_TYPE_TIMESTAMP:
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
- default:
- return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
- }
-}
-
-/*
- * Transfer octet length.
- */
-Int4
-pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
-{
- ConnectionClass *conn = SC_get_conn(stmt);
-
- int coef = 1;
- Int4 prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc;
- switch (type)
- {
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- if (conn->unicode)
- return prec * 2;
-#ifdef MULTIBYTE
- /* after 7.2 */
- if (PG_VERSION_GE(conn, 7.2))
- coef = 3;
- else
-#endif /* MULTIBYTE */
- if ((conn->connInfo).lf_conversion)
- /* CR -> CR/LF */
- coef = 2;
- if (coef == 1)
- return prec;
- maxvarc = conn->connInfo.drivers.max_varchar_size;
- if (prec <= maxvarc && prec * coef > maxvarc)
- return maxvarc;
- return coef * prec;
- case PG_TYPE_BYTEA:
- return prec;
- }
- return -1;
-}
-
-/*
- * corrsponds to "scale" in ODBC 2.x.
- */
-Int2
-pgtype_decimal_digits(StatementClass *stmt, Int4 type, int col)
-{
- switch (type)
- {
- case PG_TYPE_INT2:
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- case PG_TYPE_INT8:
- case PG_TYPE_FLOAT4:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_MONEY:
- case PG_TYPE_BOOL:
-
- /*
- * Number of digits to the right of the decimal point in
- * "yyyy-mm=dd hh:mm:ss[.f...]"
- */
- case PG_TYPE_ABSTIME:
- case PG_TYPE_TIMESTAMP:
- return 0;
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- /* return 0; */
- return getTimestampDecimalDigits(stmt, type, col);
-
- case PG_TYPE_NUMERIC:
- return getNumericDecimalDigits(stmt, type, col);
-
- default:
- return -1;
- }
-}
-
-/*
- * "scale" in ODBC 3.x.
- */
-Int2
-pgtype_scale(StatementClass *stmt, Int4 type, int col)
-{
- switch (type)
- {
- case PG_TYPE_NUMERIC:
- return getNumericDecimalDigits(stmt, type, col);
- }
- return -1;
-}
-
-
-Int2
-pgtype_radix(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_INT2:
- case PG_TYPE_OID:
- case PG_TYPE_INT4:
- case PG_TYPE_INT8:
- case PG_TYPE_NUMERIC:
- case PG_TYPE_FLOAT4:
- case PG_TYPE_MONEY:
- case PG_TYPE_FLOAT8:
- return 10;
- default:
- return -1;
- }
-}
-
-
-Int2
-pgtype_nullable(StatementClass *stmt, Int4 type)
-{
- return SQL_NULLABLE; /* everything should be nullable */
-}
-
-
-Int2
-pgtype_auto_increment(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_INT2:
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- case PG_TYPE_FLOAT4:
- case PG_TYPE_MONEY:
- case PG_TYPE_BOOL:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_INT8:
- case PG_TYPE_NUMERIC:
-
- case PG_TYPE_DATE:
- case PG_TYPE_TIME_WITH_TMZONE:
- case PG_TYPE_TIME:
- case PG_TYPE_ABSTIME:
- case PG_TYPE_DATETIME:
- case PG_TYPE_TIMESTAMP_NO_TMZONE:
- case PG_TYPE_TIMESTAMP:
- return FALSE;
-
- default:
- return -1;
- }
-}
-
-
-Int2
-pgtype_case_sensitive(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_CHAR:
-
- case PG_TYPE_CHAR2:
- case PG_TYPE_CHAR4:
- case PG_TYPE_CHAR8:
-
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- case PG_TYPE_TEXT:
- case PG_TYPE_NAME:
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
-
-Int2
-pgtype_money(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_MONEY:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-
-Int2
-pgtype_searchable(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_CHAR:
- case PG_TYPE_CHAR2:
- case PG_TYPE_CHAR4:
- case PG_TYPE_CHAR8:
-
- case PG_TYPE_VARCHAR:
- case PG_TYPE_BPCHAR:
- case PG_TYPE_TEXT:
- case PG_TYPE_NAME:
- return SQL_SEARCHABLE;
-
- default:
- return SQL_ALL_EXCEPT_LIKE;
- }
-}
-
-
-Int2
-pgtype_unsigned(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- return TRUE;
-
- case PG_TYPE_INT2:
- case PG_TYPE_INT4:
- case PG_TYPE_INT8:
- case PG_TYPE_NUMERIC:
- case PG_TYPE_FLOAT4:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_MONEY:
- return FALSE;
-
- default:
- return -1;
- }
-}
-
-
-char *
-pgtype_literal_prefix(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_INT2:
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- case PG_TYPE_INT8:
- case PG_TYPE_NUMERIC:
- case PG_TYPE_FLOAT4:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_MONEY:
- return NULL;
-
- default:
- return "'";
- }
-}
-
-
-char *
-pgtype_literal_suffix(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_INT2:
- case PG_TYPE_OID:
- case PG_TYPE_XID:
- case PG_TYPE_INT4:
- case PG_TYPE_INT8:
- case PG_TYPE_NUMERIC:
- case PG_TYPE_FLOAT4:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_MONEY:
- return NULL;
-
- default:
- return "'";
- }
-}
-
-
-char *
-pgtype_create_params(StatementClass *stmt, Int4 type)
-{
- switch (type)
- {
- case PG_TYPE_BPCHAR:
- case PG_TYPE_VARCHAR:
- return "max. length";
- default:
- return NULL;
- }
-}
-
-
-Int2
-sqltype_to_default_ctype(Int2 sqltype)
-{
- /*
- * from the table on page 623 of ODBC 2.0 Programmer's Reference
- * (Appendix D)
- */
- switch (sqltype)
- {
- case SQL_CHAR:
- case SQL_VARCHAR:
- case SQL_LONGVARCHAR:
- case SQL_DECIMAL:
- case SQL_NUMERIC:
-#if (ODBCVER < 0x0300)
- case SQL_BIGINT:
- return SQL_C_CHAR;
-#else
- return SQL_C_CHAR;
- case SQL_BIGINT:
- return ALLOWED_C_BIGINT;
-#endif
-
-#ifdef UNICODE_SUPPORT
- case SQL_WCHAR:
- case SQL_WVARCHAR:
- case SQL_WLONGVARCHAR:
- return SQL_C_WCHAR;
-#endif /* UNICODE_SUPPORT */
-
- case SQL_BIT:
- return SQL_C_BIT;
-
- case SQL_TINYINT:
- return SQL_C_STINYINT;
-
- case SQL_SMALLINT:
- return SQL_C_SSHORT;
-
- case SQL_INTEGER:
- return SQL_C_SLONG;
-
- case SQL_REAL:
- return SQL_C_FLOAT;
-
- case SQL_FLOAT:
- case SQL_DOUBLE:
- return SQL_C_DOUBLE;
-
- case SQL_BINARY:
- case SQL_VARBINARY:
- case SQL_LONGVARBINARY:
- return SQL_C_BINARY;
-
- case SQL_DATE:
- return SQL_C_DATE;
-
- case SQL_TIME:
- return SQL_C_TIME;
-
- case SQL_TIMESTAMP:
- return SQL_C_TIMESTAMP;
-
-#if (ODBCVER >= 0x0300)
- case SQL_TYPE_DATE:
- return SQL_C_TYPE_DATE;
-
- case SQL_TYPE_TIME:
- return SQL_C_TYPE_TIME;
-
- case SQL_TYPE_TIMESTAMP:
- return SQL_C_TYPE_TIMESTAMP;
-#endif /* ODBCVER */
-
- default:
- /* should never happen */
- return SQL_C_CHAR;
- }
-}
-
-Int4
-ctype_length(Int2 ctype)
-{
- switch (ctype)
- {
- case SQL_C_SSHORT:
- case SQL_C_SHORT:
- return sizeof(SWORD);
-
- case SQL_C_USHORT:
- return sizeof(UWORD);
-
- case SQL_C_SLONG:
- case SQL_C_LONG:
- return sizeof(SDWORD);
-
- case SQL_C_ULONG:
- return sizeof(UDWORD);
-
- case SQL_C_FLOAT:
- return sizeof(SFLOAT);
-
- case SQL_C_DOUBLE:
- return sizeof(SDOUBLE);
-
- case SQL_C_BIT:
- return sizeof(UCHAR);
-
- case SQL_C_STINYINT:
- case SQL_C_TINYINT:
- return sizeof(SCHAR);
-
- case SQL_C_UTINYINT:
- return sizeof(UCHAR);
-
- case SQL_C_DATE:
-#if (ODBCVER >= 0x0300)
- case SQL_C_TYPE_DATE:
-#endif /* ODBCVER */
- return sizeof(DATE_STRUCT);
-
- case SQL_C_TIME:
-#if (ODBCVER >= 0x0300)
- case SQL_C_TYPE_TIME:
-#endif /* ODBCVER */
- return sizeof(TIME_STRUCT);
-
- case SQL_C_TIMESTAMP:
-#if (ODBCVER >= 0x0300)
- case SQL_C_TYPE_TIMESTAMP:
-#endif /* ODBCVER */
- return sizeof(TIMESTAMP_STRUCT);
-
- case SQL_C_BINARY:
- case SQL_C_CHAR:
-#ifdef UNICODE_SUPPORT
- case SQL_C_WCHAR:
-#endif /* UNICODE_SUPPORT */
- return 0;
-
- default: /* should never happen */
- return 0;
- }
-}