diff options
Diffstat (limited to 'src/interfaces/odbc/pgtypes.c')
-rw-r--r-- | src/interfaces/odbc/pgtypes.c | 1475 |
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; - } -} |