📄 info.c
字号:
/*-------- * Module: info.c * * Description: This module contains routines related to * ODBC informational functions. * * Classes: n/a * * API functions: SQLGetInfo, SQLGetTypeInfo, SQLGetFunctions, * SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns, * SQLPrimaryKeys, SQLForeignKeys, * SQLProcedureColumns, SQLProcedures, * SQLTablePrivileges, SQLColumnPrivileges(NI) * * Comments: See "notice.txt" for copyright and license information. *-------- */#include "psqlodbc.h"#include <string.h>#include <stdio.h>#ifndef WIN32#include <ctype.h>#endif#include "tuple.h"#include "pgtypes.h"#include "dlg_specific.h"#include "environ.h"#include "connection.h"#include "statement.h"#include "qresult.h"#include "bind.h"#include "misc.h"#include "pgtypes.h"#include "pgapifunc.h"#include "multibyte.h"#include "catfunc.h"/* Trigger related stuff for SQLForeign Keys */#define TRIGGER_SHIFT 3#define TRIGGER_MASK 0x03#define TRIGGER_DELETE 0x01#define TRIGGER_UPDATE 0x02#define NULL_IF_NULL(a) ((a) ? ((const char *) a) : "(NULL)")/* extern GLOBAL_VALUES globals; */CSTR pubstr = "public";CSTR likeop = "like";CSTR eqop = "=";RETCODE SQL_APIPGAPI_GetInfo( HDBC hdbc, SQLUSMALLINT fInfoType, PTR rgbInfoValue, SQLSMALLINT cbInfoValueMax, SQLSMALLINT FAR * pcbInfoValue){ CSTR func = "PGAPI_GetInfo"; ConnectionClass *conn = (ConnectionClass *) hdbc; ConnInfo *ci; const char *p = NULL; char tmp[MAX_INFO_STRING]; SQLULEN len = 0, value = 0; RETCODE result; char odbcver[16]; int i_odbcver; mylog("%s: entering...fInfoType=%d\n", func, fInfoType); if (!conn) { CC_log_error(func, NULL_STRING, NULL); return SQL_INVALID_HANDLE; } ci = &(conn->connInfo); switch (fInfoType) { case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */ p = "N"; break; case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */ p = CC_accessible_only(conn) ? "Y" : "N"; break; case SQL_ACTIVE_CONNECTIONS: /* ODBC 1.0 */ len = 2; value = 0; break; case SQL_ACTIVE_STATEMENTS: /* ODBC 1.0 */ len = 2; value = 0; break; case SQL_ALTER_TABLE: /* ODBC 2.0 */ len = 4; value = SQL_AT_ADD_COLUMN; if (PG_VERSION_GE(conn, 7.3)) value |= SQL_AT_DROP_COLUMN;#if (ODBCVER >= 0x0300) value |= SQL_AT_ADD_COLUMN_SINGLE; if (PG_VERSION_GE(conn, 7.1)) value |= SQL_AT_ADD_CONSTRAINT | SQL_AT_ADD_TABLE_CONSTRAINT | SQL_AT_CONSTRAINT_INITIALLY_DEFERRED | SQL_AT_CONSTRAINT_INITIALLY_IMMEDIATE | SQL_AT_CONSTRAINT_DEFERRABLE; if (PG_VERSION_GE(conn, 7.3)) value |= SQL_AT_DROP_TABLE_CONSTRAINT_RESTRICT | SQL_AT_DROP_TABLE_CONSTRAINT_CASCADE | SQL_AT_DROP_COLUMN_RESTRICT | SQL_AT_DROP_COLUMN_CASCADE;#endif /* ODBCVER */ break; case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */ /* very simple bookmark support */ len = 4; value = ci->drivers.use_declarefetch && PG_VERSION_LT(conn, 7.4) ? 0 : (SQL_BP_SCROLL | SQL_BP_DELETE | SQL_BP_UPDATE | SQL_BP_TRANSACTION); break; case SQL_COLUMN_ALIAS: /* ODBC 2.0 */ p = "N"; break; case SQL_CONCAT_NULL_BEHAVIOR: /* ODBC 1.0 */ len = 2; value = SQL_CB_NON_NULL; break; case SQL_CONVERT_INTEGER: case SQL_CONVERT_SMALLINT: case SQL_CONVERT_TINYINT: case SQL_CONVERT_BIT: case SQL_CONVERT_VARCHAR: /* ODBC 1.0 */ len = sizeof(SQLUINTEGER); value = SQL_CVT_BIT | SQL_CVT_INTEGER;mylog("SQL_CONVERT_ mask=" FORMAT_ULEN "\n", value); break; case SQL_CONVERT_BIGINT: case SQL_CONVERT_DECIMAL: case SQL_CONVERT_DOUBLE: case SQL_CONVERT_FLOAT: case SQL_CONVERT_NUMERIC: case SQL_CONVERT_REAL: case SQL_CONVERT_DATE: case SQL_CONVERT_TIME: case SQL_CONVERT_TIMESTAMP: case SQL_CONVERT_BINARY: case SQL_CONVERT_LONGVARBINARY: case SQL_CONVERT_VARBINARY: /* ODBC 1.0 */ case SQL_CONVERT_CHAR: case SQL_CONVERT_LONGVARCHAR:#ifdef UNICODE_SUPPORT case SQL_CONVERT_WCHAR: case SQL_CONVERT_WLONGVARCHAR: case SQL_CONVERT_WVARCHAR:#endif /* UNICODE_SUPPORT */ len = sizeof(SQLUINTEGER); value = 0; /* CONVERT is unavailable */ break; case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */ len = sizeof(SQLUINTEGER); value = SQL_FN_CVT_CONVERT;mylog("CONVERT_FUNCTIONS=" FORMAT_ULEN "\n", value); break; case SQL_CORRELATION_NAME: /* ODBC 1.0 */ /* * Saying no correlation name makes Query not work right. * value = SQL_CN_NONE; */ len = 2; value = SQL_CN_ANY; break; case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */ len = 2; value = SQL_CB_CLOSE; if (!ci->drivers.use_declarefetch || PG_VERSION_GE(conn, 7.4)) value = SQL_CB_PRESERVE; break; case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */ len = 2; value = SQL_CB_CLOSE; if (!ci->drivers.use_declarefetch) value = SQL_CB_PRESERVE; break; case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */ p = CC_get_DSN(conn); break; case SQL_DATA_SOURCE_READ_ONLY: /* ODBC 1.0 */ p = CC_is_onlyread(conn) ? "Y" : "N"; break; case SQL_DATABASE_NAME: /* Support for old ODBC 1.0 Apps */ /* * Returning the database name causes problems in MS Query. It * generates query like: "SELECT DISTINCT a FROM byronnbad3 * bad3" * * p = CC_get_database(conn); */ p = CurrCatString(conn); break; case SQL_DBMS_NAME: /* ODBC 1.0 */ if (CC_fake_mss(conn)) p = "Microsoft SQL Server"; else p = "PostgreSQL"; break; case SQL_DBMS_VER: /* ODBC 1.0 */ /* * The ODBC spec wants ##.##.#### ...whatever... so prepend * the driver */ /* version number to the dbms version string */ /* snprintf(tmp, sizeof(tmp) - 1, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version); tmp[sizeof(tmp) - 1] = '\0'; */ if (CC_fake_mss(conn)) p = "09.00.1399"; else { strncpy_null(tmp, conn->pg_version, sizeof(tmp)); p = tmp; } break; case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */ len = 4; if (PG_VERSION_LT(conn, 6.5)) value = SQL_TXN_SERIALIZABLE; else value = SQL_TXN_READ_COMMITTED; break; case SQL_DRIVER_NAME: /* ODBC 1.0 */ p = DRIVER_FILE_NAME; break; case SQL_DRIVER_ODBC_VER: i_odbcver = conn->driver_version; snprintf(odbcver, sizeof(odbcver), "%02x.%02x", i_odbcver / 256, i_odbcver % 256); /* p = DRIVER_ODBC_VER; */ p = odbcver; break; case SQL_DRIVER_VER: /* ODBC 1.0 */ p = POSTGRESDRIVERVERSION; break; case SQL_EXPRESSIONS_IN_ORDERBY: /* ODBC 1.0 */ p = "N"; break; case SQL_FETCH_DIRECTION: /* ODBC 1.0 */ len = 4; value = (SQL_FD_FETCH_NEXT | SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST | SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE | SQL_FD_FETCH_RELATIVE | SQL_FD_FETCH_BOOKMARK); break; case SQL_FILE_USAGE: /* ODBC 2.0 */ len = 2; value = SQL_FILE_NOT_SUPPORTED; break; case SQL_GETDATA_EXTENSIONS: /* ODBC 2.0 */ len = 4; value = (SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND | SQL_GD_BLOCK); break; case SQL_GROUP_BY: /* ODBC 2.0 */ len = 2; value = SQL_GB_GROUP_BY_EQUALS_SELECT; break; case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */ /* * are identifiers case-sensitive (yes, but only when quoted. * If not quoted, they default to lowercase) */ len = 2; value = SQL_IC_LOWER; break; case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */ /* the character used to quote "identifiers" */ p = PG_VERSION_LE(conn, 6.2) ? " " : "\""; break; case SQL_KEYWORDS: /* ODBC 2.0 */ p = NULL_STRING; break; case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */ /* * is there a character that escapes '%' and '_' in a LIKE * clause? not as far as I can tell */ p = "N"; break; case SQL_LOCK_TYPES: /* ODBC 2.0 */ len = 4; value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE; break; case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */ len = 4; value = 0; break; case SQL_MAX_CHAR_LITERAL_LEN: /* ODBC 2.0 */ len = 4; value = 0; break; case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */ len = 2; if (PG_VERSION_GT(conn, 7.4)) value = CC_get_max_idlen(conn);#ifdef MAX_COLUMN_LEN else value = MAX_COLUMN_LEN;#endif /* MAX_COLUMN_LEN */ if (0 == value) { if (PG_VERSION_GE(conn, 7.3)) value = NAMEDATALEN_V73; else value = NAMEDATALEN_V72; } break; case SQL_MAX_COLUMNS_IN_GROUP_BY: /* ODBC 2.0 */ len = 2; value = 0; break; case SQL_MAX_COLUMNS_IN_INDEX: /* ODBC 2.0 */ len = 2; value = 0; break; case SQL_MAX_COLUMNS_IN_ORDER_BY: /* ODBC 2.0 */ len = 2; value = 0; break; case SQL_MAX_COLUMNS_IN_SELECT: /* ODBC 2.0 */ len = 2; value = 0; break; case SQL_MAX_COLUMNS_IN_TABLE: /* ODBC 2.0 */ len = 2; value = 0; break; case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */ len = 2; value = MAX_CURSOR_LEN; break; case SQL_MAX_INDEX_SIZE: /* ODBC 2.0 */ len = 4; value = 0; break; case SQL_MAX_OWNER_NAME_LEN: /* ODBC 1.0 */ len = 2; value = 0; if (PG_VERSION_GT(conn, 7.4)) value = CC_get_max_idlen(conn);#ifdef MAX_SCHEMA_LEN else if (conn->schema_support) value = MAX_SCHEMA_LEN;#endif /* MAX_SCHEMA_LEN */ if (0 == value) { if (PG_VERSION_GE(conn, 7.3)) value = NAMEDATALEN_V73; } break; case SQL_MAX_PROCEDURE_NAME_LEN: /* ODBC 1.0 */ len = 2; value = 0; break; case SQL_MAX_QUALIFIER_NAME_LEN: /* ODBC 1.0 */ len = 2; value = 0; break; case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */ len = 4; if (PG_VERSION_GE(conn, 7.1)) { /* Large Rowa in 7.1+ */ value = MAX_ROW_SIZE; } else { /* Without the Toaster we're limited to the blocksize */ value = BLCKSZ; } break; case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */ /* * does the preceding value include LONGVARCHAR and * LONGVARBINARY fields? Well, it does include longvarchar, * but not longvarbinary. */ p = "Y"; break; case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */ /* maybe this should be 0? */ len = 4; value = CC_get_max_query_len(conn); break; case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */ len = 2; if (PG_VERSION_GT(conn, 7.4)) value = CC_get_max_idlen(conn);#ifdef MAX_TABLE_LEN else value = MAX_TABLE_LEN;#endif /* MAX_TABLE_LEN */ if (0 == value) { if (PG_VERSION_GE(conn, 7.3)) value = NAMEDATALEN_V73; else value = NAMEDATALEN_V72; } break; case SQL_MAX_TABLES_IN_SELECT: /* ODBC 2.0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -