📄 cpl_odbc.cpp
字号:
/****************************************************************************** * $Id: cpl_odbc.cpp,v 1.38 2006/10/27 04:39:53 fwarmerdam Exp $ * * Project: OGR ODBC Driver * Purpose: Declarations for ODBC Access Cover API. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2003, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log: cpl_odbc.cpp,v $ * Revision 1.38 2006/10/27 04:39:53 fwarmerdam * Close comment. * * Revision 1.37 2006/10/27 03:34:47 fwarmerdam * Avoid warnings in RemoveDriver(). * * Revision 1.36 2006/10/19 20:39:37 fwarmerdam * Provide fallback definitions for sql column codes. * * Revision 1.35 2006/10/19 17:54:54 dron * Return string type for unrecognized SQL data types in GetTypeMapping(). * * Revision 1.34 2006/10/19 17:22:54 dron * Added GetTypeMapping() conversion function; numerous clean-ups. * * Revision 1.33 2006/06/30 18:15:35 dron * Avoid warnings on win64 target. * * Revision 1.32 2006/06/06 16:25:22 mloskot * Fixed memory 4-5 leaks in CPL ODBC and OGR drivers. * * Revision 1.31 2006/06/05 20:15:52 mloskot * Fixed problem with /odbcinst.ini requirements. * * Revision 1.30 2006/06/05 18:53:28 mloskot * Added usage of ODBCSYSINI env to CPLODBCDriverInstaller. * * Revision 1.29 2006/06/05 15:52:29 mloskot * Added option to the ODBC wrapper to list views together with tables. * * Revision 1.28 2006/06/01 12:15:39 mloskot * Added CPLODBCDriverInstaller utility class to CPL. * * Revision 1.27 2006/02/19 21:54:34 mloskot * [WINCE] Changes related to Windows CE port of CPL. Most changes are #ifdef wrappers. * * Revision 1.26 2006/01/31 03:04:27 fwarmerdam * Fixed null trimming to work for long unicode text strings per: * http://bugzilla.remotesensing.org/show_bug.cgi?id=990 * * Revision 1.25 2005/09/24 04:58:16 fwarmerdam * Support SQLDriverConnect (pass opts) in EstablishSession * * Revision 1.24 2005/09/05 20:18:43 fwarmerdam * added binary column support * * Revision 1.23 2005/08/31 03:32:41 fwarmerdam * GetTypeName now returns CPLString * * Revision 1.22 2005/08/07 14:05:44 fwarmerdam * added connect/disconnect debug statements * * Revision 1.21 2005/06/29 01:01:01 ssoule * Changed return type of CPLODBCStatement::GetTypeName from const char * to * std::string. * * Revision 1.20 2005/05/23 03:56:44 fwarmerdam * make make static buffers threadlocal * * Revision 1.19 2005/01/12 07:51:29 fwarmerdam * Fix some argument types needed for ODBC 3.52. In particular SQLDescribeCol * and SQLGetData require SQLLEN and SQLULEN instead of SQLINTEGER and * SQLUINTEGER. Patches provided by David Herring. * * Revision 1.18 2004/08/18 18:47:12 warmerda * Increase size of work buffer a bit so that providers with broken support * for multiple SQLGetData() calls will still mostly work. * * Revision 1.17 2004/08/17 21:51:16 warmerda * Changed Fetch() to handle values longer than the working buffer * properly ... do extra SQLGetData() calls till complete. * * Revision 1.16 2004/08/17 20:15:56 warmerda * Allow column values up to 64K instead of limited to 8K. * * Revision 1.15 2004/06/17 17:11:51 warmerda * fixed case where vsnprintf does not exist * * Revision 1.14 2004/06/01 20:40:02 warmerda * expanded tabs * * Revision 1.13 2004/03/30 22:26:58 warmerda * Avoid use of SQLRowCount() in GetColumns(). It does not work reliably * with Oracle unixodbc driver on AIX. Argg. * * Revision 1.12 2004/03/04 16:58:05 warmerda * Fixed up memory leak of results set column definition info. * * Revision 1.11 2004/03/04 05:41:21 warmerda * Modified Fetch() method to use SQLFetch() for cases it would be * sufficient for. The SQLScrollFetch() isn't implemented on some brain * dead drivers, such as the unixODBC text file driver. * http://bugzilla.remotesensing.org/show_bug.cgi?id=463 * * Revision 1.10 2003/11/24 20:48:08 warmerda * pass NULLs t SQLColumns, not empty strings * * Revision 1.9 2003/11/24 20:32:07 warmerda * Use TABLE instead of TABLES in SQLTables() call * * Revision 1.8 2003/11/10 20:08:12 warmerda * added GetTables() implementation * * Revision 1.7 2003/10/29 17:56:57 warmerda * Added PrimaryKeys() support * * Revision 1.6 2003/10/06 20:04:08 warmerda * added escaping support * * Revision 1.5 2003/10/06 17:17:02 warmerda * fixed some type issues * * Revision 1.4 2003/09/26 20:02:41 warmerda * update GetColData() * * Revision 1.3 2003/09/26 13:51:02 warmerda * Add documentation * * Revision 1.2 2003/09/25 17:09:49 warmerda * added some more methods * * Revision 1.1 2003/09/24 15:38:27 warmerda * New * */#include "cpl_odbc.h"#include "cpl_vsi.h"#include "cpl_string.h"#include "cpl_error.h"#ifndef WIN32CE /* ODBC is not supported on Windows CE. */CPL_CVSID("$Id: cpl_odbc.cpp,v 1.38 2006/10/27 04:39:53 fwarmerdam Exp $");#ifndef SQLColumns_TABLE_CAT #define SQLColumns_TABLE_CAT 1#define SQLColumns_TABLE_SCHEM 2#define SQLColumns_TABLE_NAME 3#define SQLColumns_COLUMN_NAME 4#define SQLColumns_DATA_TYPE 5#define SQLColumns_TYPE_NAME 6#define SQLColumns_COLUMN_SIZE 7#define SQLColumns_BUFFER_LENGTH 8#define SQLColumns_DECIMAL_DIGITS 9#define SQLColumns_NUM_PREC_RADIX 10#define SQLColumns_NULLABLE 11#define SQLColumns_REMARKS 12#define SQLColumns_COLUMN_DEF 13#define SQLColumns_SQL_DATA_TYPE 14#define SQLColumns_SQL_DATETIME_SUB 15#define SQLColumns_CHAR_OCTET_LENGTH 16#define SQLColumns_ORDINAL_POSITION 17#define SQLColumns_IS_NULLABLE 18#endif /* ndef SQLColumns_TABLE_CAT *//************************************************************************//* CPLODBCDriverInstaller() *//************************************************************************/CPLODBCDriverInstaller::CPLODBCDriverInstaller() : m_nUsageCount(0){ memset( m_szPathOut, '\0', ODBC_FILENAME_MAX ); memset( m_szError, '\0', SQL_MAX_MESSAGE_LENGTH );}/************************************************************************//* InstallDriver() *//************************************************************************/int CPLODBCDriverInstaller::InstallDriver( const char* pszDriver, const char* pszPathIn, WORD fRequest ){ CPLAssert( NULL != pszDriver ); // Try to install driver to system-wide location if ( FALSE == SQLInstallDriverEx( pszDriver, NULL, m_szPathOut, ODBC_FILENAME_MAX, NULL, fRequest, &m_nUsageCount ) ) { const WORD nErrorNum = 1; // TODO - a function param? RETCODE cRet = SQL_ERROR; // Failure is likely related to no write permissions to // system-wide default location, so try to install to HOME // Read HOME location char* pszEnvHome = NULL; pszEnvHome = getenv("HOME"); CPLAssert( NULL != pszEnvHome ); CPLDebug( "ODBC", "HOME=%s", pszEnvHome ); // Set ODBCSYSINI variable pointing to HOME location char* pszEnvIni = (char *)CPLMalloc( strlen(pszEnvHome) + 12 ); sprintf( pszEnvIni, "ODBCSYSINI=%s", pszEnvHome ); putenv( pszEnvIni ); CPLDebug( "ODBC", pszEnvIni ); //CPLFree( pszEnvIni ); // Try to install ODBC driver in new location if ( FALSE == SQLInstallDriverEx( pszDriver, NULL, m_szPathOut, ODBC_FILENAME_MAX, NULL, fRequest, &m_nUsageCount ) ) { cRet = SQLInstallerError( nErrorNum, &m_nErrorCode, m_szError, SQL_MAX_MESSAGE_LENGTH, NULL ); CPLAssert( SQL_SUCCESS == cRet || SQL_SUCCESS_WITH_INFO == cRet ); // FAIL return FALSE; } } // SUCCESS return TRUE;}/************************************************************************//* RemoveDriver() *//************************************************************************/int CPLODBCDriverInstaller::RemoveDriver( const char* pszDriverName, int fRemoveDSN ){ CPLAssert( NULL != pszDriverName ); if ( FALSE == SQLRemoveDriver( pszDriverName, fRemoveDSN, &m_nUsageCount ) ) { const WORD nErrorNum = 1; // TODO - a function param? // Retrieve error code and message SQLInstallerError( nErrorNum, &m_nErrorCode, m_szError, SQL_MAX_MESSAGE_LENGTH, NULL ); return FALSE; } // SUCCESS return TRUE;}/************************************************************************//* CPLODBCSession() *//************************************************************************/CPLODBCSession::CPLODBCSession(){ m_szLastError[0] = '\0'; m_hEnv = NULL; m_hDBC = NULL;}/************************************************************************//* ~CPLODBCSession() *//************************************************************************/CPLODBCSession::~CPLODBCSession(){ CloseSession();}/************************************************************************//* CloseSession() *//************************************************************************/int CPLODBCSession::CloseSession(){ if( m_hDBC!=NULL ) { CPLDebug( "ODBC", "SQLDisconnect()" ); SQLDisconnect( m_hDBC ); SQLFreeConnect( m_hDBC ); m_hDBC = NULL; } if( m_hEnv!=NULL ) { SQLFreeEnv( m_hEnv ); m_hEnv = NULL; } return TRUE;}/************************************************************************//* Failed() *//* *//* Test if a return code indicates failure, return TRUE if that *//* is the case. Also update error text. *//************************************************************************/int CPLODBCSession::Failed( int nRetCode, HSTMT hStmt ){ SQLCHAR achSQLState[SQL_MAX_MESSAGE_LENGTH]; SQLINTEGER nNativeError; SQLSMALLINT nTextLength=0; m_szLastError[0] = '\0'; if( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO ) return FALSE; SQLError( m_hEnv, m_hDBC, hStmt, achSQLState, &nNativeError, (SQLCHAR *) m_szLastError, sizeof(m_szLastError)-1, &nTextLength ); m_szLastError[nTextLength] = '\0'; return TRUE;}/************************************************************************//* EstablishSession() *//************************************************************************//** * Connect to database and logon. * * @param pszDSN The name of the DSN being used to connect. This is not * optional. * * @param pszUserid the userid to logon as, may be NULL if not not required, * or provided by the DSN. * * @param pszPassword the password to logon with. May be NULL if not required * or provided by the DSN. * * @return TRUE on success or FALSE on failure. Call GetLastError() to get * details on failure. */int CPLODBCSession::EstablishSession( const char *pszDSN, const char *pszUserid, const char *pszPassword ){ CloseSession(); if( Failed( SQLAllocEnv( &m_hEnv ) ) ) return FALSE; if( Failed( SQLAllocConnect( m_hEnv, &m_hDBC ) ) ) { CloseSession(); return FALSE; } SQLSetConnectOption( m_hDBC,SQL_LOGIN_TIMEOUT,5 ); if( pszUserid == NULL ) pszUserid = ""; if( pszPassword == NULL ) pszPassword = ""; int bFailed; if( strstr(pszDSN,"=") != NULL ) { SQLCHAR szOutConnString[1024]; SQLSMALLINT nOutConnStringLen = 0; CPLDebug( "ODBC", "SQLDriverConnect(%s)", pszDSN ); bFailed = Failed( SQLDriverConnect( m_hDBC, NULL, (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN), szOutConnString, sizeof(szOutConnString), &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) ); } else { CPLDebug( "ODBC", "SQLConnect(%s)", pszDSN ); bFailed = Failed( SQLConnect( m_hDBC, (SQLCHAR *) pszDSN, SQL_NTS, (SQLCHAR *) pszUserid, SQL_NTS, (SQLCHAR *) pszPassword, SQL_NTS ) ); } if( bFailed ) { CPLDebug( "ODBC", "... failed: %s", GetLastError() ); CloseSession(); return FALSE; } return TRUE;}/************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -