📄 cpl_odbc.cpp
字号:
/* GetLastError() *//************************************************************************//** * Returns the last ODBC error message. * * @return pointer to an internal buffer with the error message in it. * Do not free or alter. Will be an empty (but not NULL) string if there is * no pending error info. */const char *CPLODBCSession::GetLastError(){ return m_szLastError;}/************************************************************************//* ==================================================================== *//* CPLODBCStatement *//* ==================================================================== *//************************************************************************//************************************************************************//* CPLODBCStatement() *//************************************************************************/CPLODBCStatement::CPLODBCStatement( CPLODBCSession *poSession ){ m_poSession = poSession; if( Failed( SQLAllocStmt( poSession->GetConnection(), &m_hStmt ) ) ) { m_hStmt = NULL; return; } m_nColCount = 0; m_papszColNames = NULL; m_panColType = NULL; m_papszColTypeNames = NULL; m_panColSize = NULL; m_panColPrecision = NULL; m_panColNullable = NULL; m_papszColValues = NULL; m_panColValueLengths = NULL; m_pszStatement = NULL; m_nStatementMax = 0; m_nStatementLen = 0;}/************************************************************************//* ~CPLODBCStatement() *//************************************************************************/CPLODBCStatement::~CPLODBCStatement(){ Clear(); if( m_hStmt != NULL ) SQLFreeStmt( m_hStmt, SQL_DROP );}/************************************************************************//* ExecuteSQL() *//************************************************************************//** * Execute an SQL statement. * * This method will execute the passed (or stored) SQL statement, * and initialize information about the resultset if there is one. * If a NULL statement is passed, the internal stored statement that * has been previously set via Append() or Appendf() calls will be used. * * @param pszStatement the SQL statement to execute, or NULL if the * internally saved one should be used. * * @return TRUE on success or FALSE if there is an error. Error details * can be fetched with OGRODBCSession::GetLastError(). */int CPLODBCStatement::ExecuteSQL( const char *pszStatement ){ if( m_poSession == NULL || m_hStmt == NULL ) { // we should post an error. return FALSE; } if( pszStatement != NULL ) { Clear(); Append( pszStatement ); } if( Failed( SQLExecDirect( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS ) ) ) return FALSE; return CollectResultsInfo();}/************************************************************************//* CollectResultsInfo() *//************************************************************************/int CPLODBCStatement::CollectResultsInfo(){ if( m_poSession == NULL || m_hStmt == NULL ) { // we should post an error. return FALSE; } if( Failed( SQLNumResultCols(m_hStmt,&m_nColCount) ) ) return FALSE;/* -------------------------------------------------------------------- *//* Allocate per column information. *//* -------------------------------------------------------------------- */ m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1)); m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1)); m_panColValueLengths = (_SQLLEN *) CPLCalloc(sizeof(int),(m_nColCount+1)); m_panColType = (short *) CPLCalloc(sizeof(short),m_nColCount); m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1)); m_panColSize = (_SQLULEN *) CPLCalloc(sizeof(_SQLULEN),m_nColCount); m_panColPrecision = (short *) CPLCalloc(sizeof(short),m_nColCount); m_panColNullable = (short *) CPLCalloc(sizeof(short),m_nColCount);/* -------------------------------------------------------------------- *//* Fetch column descriptions. *//* -------------------------------------------------------------------- */ for( SQLUSMALLINT iCol = 0; iCol < m_nColCount; iCol++ ) { SQLCHAR szName[256]; SQLSMALLINT nNameLength = 0; if ( Failed( SQLDescribeCol(m_hStmt, iCol+1, szName, sizeof(szName), &nNameLength, m_panColType + iCol, m_panColSize + iCol, m_panColPrecision + iCol, m_panColNullable + iCol) ) ) return FALSE; szName[nNameLength] = '\0'; // Paranoid; the string should be // null-terminated by the driver m_papszColNames[iCol] = CPLStrdup((const char*)szName); // SQLDescribeCol() fetches just a subset of column attributes. // In addition to above data we need data type name. if ( Failed( SQLColAttribute(m_hStmt, iCol + 1, SQL_DESC_TYPE_NAME, szName, sizeof(szName), &nNameLength, NULL) ) ) return FALSE; szName[nNameLength] = '\0'; // Paranoid m_papszColTypeNames[iCol] = CPLStrdup((const char*)szName); } return TRUE;}/************************************************************************//* GetColCount() *//************************************************************************//** * Fetch the resultset column count. * * @return the column count, or zero if there is no resultset. */int CPLODBCStatement::GetColCount(){ return m_nColCount;}/************************************************************************//* GetColName() *//************************************************************************//** * Fetch a column name. * * @param iCol the zero based column index. * * @return NULL on failure (out of bounds column), or a pointer to an * internal copy of the column name. */const char *CPLODBCStatement::GetColName( int iCol ){ if( iCol < 0 || iCol >= m_nColCount ) return NULL; else return m_papszColNames[iCol];}/************************************************************************//* GetColType() *//************************************************************************//** * Fetch a column data type. * * The return type code is a an ODBC SQL_ code, one of SQL_UNKNOWN_TYPE, * SQL_CHAR, SQL_NUMERIC, SQL_DECIMAL, SQL_INTEGER, SQL_SMALLINT, SQL_FLOAT, * SQL_REAL, SQL_DOUBLE, SQL_DATETIME, SQL_VARCHAR, SQL_TYPE_DATE, * SQL_TYPE_TIME, SQL_TYPE_TIMESTAMPT. * * @param iCol the zero based column index. * * @return type code or -1 if the column is illegal. */short CPLODBCStatement::GetColType( int iCol ){ if( iCol < 0 || iCol >= m_nColCount ) return -1; else return m_panColType[iCol];}/************************************************************************//* GetColTypeName() *//************************************************************************//** * Fetch a column data type name. * * Returns data source-dependent data type name; for example, "CHAR", * "VARCHAR", "MONEY", "LONG VARBINAR", or "CHAR ( ) FOR BIT DATA". * * @param iCol the zero based column index. * * @return NULL on failure (out of bounds column), or a pointer to an * internal copy of the column dat type name. */const char *CPLODBCStatement::GetColTypeName( int iCol ){ if( iCol < 0 || iCol >= m_nColCount ) return NULL; else return m_papszColTypeNames[iCol];}/************************************************************************//* GetColSize() *//************************************************************************//** * Fetch the column width. * * @param iCol the zero based column index. * * @return column width, zero for unknown width columns. */short CPLODBCStatement::GetColSize( int iCol ){ if( iCol < 0 || iCol >= m_nColCount ) return -1; else return (short) m_panColSize[iCol];}/************************************************************************//* GetColPrecision() *//************************************************************************//** * Fetch the column precision. * * @param iCol the zero based column index. * * @return column precision, may be zero or the same as column size for * columns to which it does not apply. */short CPLODBCStatement::GetColPrecision( int iCol ){ if( iCol < 0 || iCol >= m_nColCount ) return -1; else return m_panColPrecision[iCol];}/************************************************************************//* GetColNullable() *//************************************************************************//** * Fetch the column nullability. * * @param iCol the zero based column index. * * @return TRUE if the column may contains or FALSE otherwise. */short CPLODBCStatement::GetColNullable( int iCol ){ if( iCol < 0 || iCol >= m_nColCount ) return -1; else return m_panColNullable[iCol];}/************************************************************************//* Fetch() *//************************************************************************//** * Fetch a new record. * * Requests the next row in the current resultset using the SQLFetchScroll() * call. Note that many ODBC drivers only support the default forward * fetching one record at a time. Only SQL_FETCH_NEXT (the default) should * be considered reliable on all drivers. * * Currently it isn't clear how to determine whether an error or a normal * out of data condition has occured if Fetch() fails. * * @param nOrientation One of SQL_FETCH_NEXT, SQL_FETCH_LAST, SQL_FETCH_PRIOR, * SQL_FETCH_ABSOLUTE, or SQL_FETCH_RELATIVE (default is SQL_FETCH_NEXT). * * @param nOffset the offset (number of records), ignored for some * orientations. * * @return TRUE if a new row is successfully fetched, or FALSE if not. */int CPLODBCStatement::Fetch( int nOrientation, int nOffset ){ ClearColumnData(); if( m_hStmt == NULL || m_nColCount < 1 ) return FALSE;/* -------------------------------------------------------------------- *//* Fetch a new row. Note that some brain dead drives (such as *//* the unixodbc text file driver) don't implement *//* SQLScrollFetch(), so we try to stick to SQLFetch() if we *//* can). *//* -------------------------------------------------------------------- */ SQLRETURN nRetCode; if( nOrientation == SQL_FETCH_NEXT && nOffset == 0 ) { nRetCode = SQLFetch( m_hStmt ); if( Failed(nRetCode) ) { if ( nRetCode != SQL_NO_DATA ) { CPLError( CE_Failure, CPLE_AppDefined, m_poSession->GetLastError() ); } return FALSE; } } else { nRetCode = SQLFetchScroll(m_hStmt, (SQLSMALLINT) nOrientation, nOffset); if( Failed(nRetCode) ) { if ( nRetCode == SQL_NO_DATA ) { CPLError( CE_Failure, CPLE_AppDefined, m_poSession->GetLastError() ); } return FALSE; } }/* -------------------------------------------------------------------- *//* Pull out all the column values. *//* -------------------------------------------------------------------- */ SQLSMALLINT iCol; for( iCol = 0; iCol < m_nColCount; iCol++ ) { char szWrkData[512]; _SQLLEN cbDataLen; SQLSMALLINT nFetchType = GetTypeMapping( m_panColType[iCol] ); // For now we will fetch data in binary and string formats only if ( nFetchType != SQL_C_BINARY ) nFetchType = SQL_C_CHAR; szWrkData[0] = '\0'; szWrkData[sizeof(szWrkData)-1] = '\0'; nRetCode = SQLGetData( m_hStmt, iCol + 1, nFetchType, szWrkData, sizeof(szWrkData)-1, &cbDataLen ); if( Failed( nRetCode ) ) { if ( nRetCode == SQL_NO_DATA ) { CPLError( CE_Failure, CPLE_AppDefined, m_poSession->GetLastError() ); } return FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -