📄 odbcclient.cpp
字号:
if(rc != SQL_NO_DATA) IodbcConnection::Check(rc, SQL_HANDLE_STMT, m_handles.m_hstmt); } else BindLongs();
m_bResultSetCanBe = true;
// cache affected rows count
IodbcConnection::Check(g_odbcAPI.SQLRowCount(m_handles.m_hstmt, &m_nRowsAffected), SQL_HANDLE_STMT, m_handles.m_hstmt);
// some drivers (e.g. Microsoft SQL Server)
// return output parameters only after SQLMoreResults returns SQL_NO_DATA
if(!ResultSetExists())
ProcessBatchUntilEndOrResultSet();
ConvertOutputParams(); // if any/if available
}
/*virtual */
void IodbcCursor::Cancel()
{
IodbcConnection::Check(g_odbcAPI.SQLCancel(
m_handles.m_hstmt), SQL_HANDLE_STMT, m_handles.m_hstmt);
}/*virtual */bool IodbcCursor::ResultSetExists(){
if(!m_bResultSetCanBe)
return false;
SQLSMALLINT ColumnCount; IodbcConnection::Check(g_odbcAPI.SQLNumResultCols(m_handles.m_hstmt, &ColumnCount), SQL_HANDLE_STMT, m_handles.m_hstmt); return ColumnCount > 0;}/*virtual */
void IodbcCursor::DescribeFields(
DescribeFields_cb_t fn)
{
SQLSMALLINT ColumnCount;
IodbcConnection::Check(g_odbcAPI.SQLNumResultCols(m_handles.m_hstmt, &ColumnCount), SQL_HANDLE_STMT, m_handles.m_hstmt);
for(SQLSMALLINT nField = 1; nField <= ColumnCount; ++nField)
{
SQLCHAR sColName[1024];
SQLSMALLINT nColLen;
SQLSMALLINT DataType;
SQLUINTEGER ColumnSize;
SQLSMALLINT Nullable;
SQLSMALLINT DecimalDigits;
IodbcConnection::Check(g_odbcAPI.SQLDescribeCol(
m_handles.m_hstmt,
nField,
sColName,
sizeof(sColName),
&nColLen,
&DataType,
&ColumnSize,
&DecimalDigits,
&Nullable), SQL_HANDLE_STMT, m_handles.m_hstmt);
(m_pCommand->*fn)(
SAString((const char*)sColName, nColLen),
CnvtNativeToStd(DataType, 0, nColLen, ColumnSize, DecimalDigits),
(int)DataType,
ColumnSize,
ColumnSize,
DecimalDigits,
Nullable == SQL_NO_NULLS);
}
}
/*virtual */long IodbcCursor::GetRowsAffected(){
return m_nRowsAffected;}/*virtual */unsigned int IodbcCursor::OutputBufferSize( SADataType_t eDataType, unsigned int nDataSize) const{ switch(eDataType) {
case SA_dtBool:
return sizeof(unsigned char); // SQL_C_BIT case SA_dtString: return nDataSize+1; // always allocate space for NULL case SA_dtDateTime: return sizeof(TIMESTAMP_STRUCT); case SA_dtLongBinary: case SA_dtLongChar: return 0;
default:
break; } return ISACursor::OutputBufferSize(eDataType, nDataSize);}/*virtual */void IodbcCursor::SetFieldBuffer( int nCol, // 1-based void *pInd, unsigned int nIndSize, void * /*pSize*/, unsigned int/* nSizeSize*/, void *pValue, unsigned int nBufSize){ assert(nIndSize == sizeof(SQLINTEGER));
if(nIndSize != sizeof(SQLINTEGER))
return; SAField &Field = m_pCommand->Field(nCol); SQLSMALLINT TargetType; bool bLong = false; switch(Field.FieldType()) { case SA_dtUnknown: throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_COLUMN_TYPE, (const char*)Field.Name());
case SA_dtBool:
TargetType = SQL_C_BIT;
break; case SA_dtShort: TargetType = SQL_C_SSHORT; break; case SA_dtLong: TargetType = SQL_C_SLONG; break; case SA_dtDouble: TargetType = SQL_C_DOUBLE; break; case SA_dtDateTime: TargetType = SQL_C_TYPE_TIMESTAMP; break; case SA_dtBytes:
TargetType = SQL_C_BINARY;
assert(nBufSize == (unsigned int)Field.FieldSize());
break;
case SA_dtString: TargetType = SQL_C_CHAR; assert(nBufSize == (unsigned int)Field.FieldSize()+1); break; case SA_dtLongBinary: TargetType = SQL_C_BINARY; assert(nBufSize == 0); bLong = true; break; case SA_dtLongChar: TargetType = SQL_C_CHAR; assert(nBufSize == 0); bLong = true; break; default: TargetType = 0; assert(false); // unknown type } if(!bLong) IodbcConnection::Check( g_odbcAPI.SQLBindCol(m_handles.m_hstmt, (SQLUSMALLINT)nCol, TargetType, pValue, nBufSize, (SQLINTEGER*)pInd), SQL_HANDLE_STMT, m_handles.m_hstmt);}/*virtual */void IodbcCursor::SetSelectBuffers(){ // use default helpers AllocSelectBuffer(sizeof(SQLINTEGER), 0);}/*virtual */bool IodbcCursor::IndicatorIsNull( int nPos, // 1-based SAValueRead &vr, ValueType_t eValueType, void *pInd, unsigned int nIndSize, void * /*pSize*/, unsigned int/* nSizeSize*/, unsigned int &nRealSize,
int/* nBulkReadingBufPos*/) const{ assert(nIndSize == sizeof(SQLINTEGER)); if(nIndSize != sizeof(SQLINTEGER))
return true;
if(*(SQLINTEGER*)pInd >= 0) nRealSize = *(SQLINTEGER*)pInd; bool bLong = false; SQLSMALLINT TargetType = 0; SQLINTEGER StrLen_or_IndPtr; bool bAddSpaceForNull = false; SADataType_t eDataType; switch(eValueType) { case ISA_FieldValue: eDataType = ((SAField&)vr).FieldType(); break; default: assert(eValueType == ISA_ParamValue); eDataType = ((SAParam&)vr).ParamType(); } switch(eDataType) { case SA_dtLongBinary: bLong = true; TargetType = SQL_C_BINARY; bAddSpaceForNull = false; break; case SA_dtLongChar: bLong = true; TargetType = SQL_C_CHAR; bAddSpaceForNull = true; break;
default:
break; } if(bLong) { // also try to get long size nRealSize = 0; char Buf[1]; IodbcConnection::Check(g_odbcAPI.SQLGetData( m_handles.m_hstmt, (SQLUSMALLINT)nPos, TargetType, Buf, bAddSpaceForNull? 1:0, &StrLen_or_IndPtr), SQL_HANDLE_STMT, m_handles.m_hstmt); if(StrLen_or_IndPtr >= 0) nRealSize = StrLen_or_IndPtr; return StrLen_or_IndPtr == SQL_NULL_DATA; } return *(SQLINTEGER*)pInd == SQL_NULL_DATA;}/*virtual */bool IodbcCursor::FetchNext(){
// SQLFetchScroll is not working with Sybase driver when reading image columns// SQLRETURN rc = g_odbcAPI.SQLFetchScroll(
// m_handles.m_hstmt, SQL_FETCH_NEXT, 0);
SQLRETURN rc = g_odbcAPI.SQLFetch(
m_handles.m_hstmt);
if(rc != SQL_NO_DATA) {
IodbcConnection::Check(rc, SQL_HANDLE_STMT, m_handles.m_hstmt); // use default helpers ConvertSelectBufferToFields(0);
}
else
ProcessBatchUntilEndOrResultSet();
return rc != SQL_NO_DATA;}
/*virtual */void IodbcCursor::ReadLongOrLOB( ValueType_t eValueType, SAValueRead &vr, void * /*pValue*/, unsigned int/* nBufSize*/, saLongOrLobReader_t fnReader, unsigned int nReaderWantedPieceSize, void *pAddlData){ if(eValueType == ISA_FieldValue) { SAField &Field = (SAField &)vr; SQLSMALLINT TargetType; SQLINTEGER StrLen_or_IndPtr; SQLRETURN rc; bool bAddSpaceForNull; switch(Field.FieldType()) { case SA_dtLongBinary: TargetType = SQL_C_BINARY; bAddSpaceForNull = false; break; case SA_dtLongChar: TargetType = SQL_C_CHAR; bAddSpaceForNull = true; break; default: TargetType = 0; bAddSpaceForNull = false; assert(false); } // try to get long size unsigned int nLongSize = 0; char Buf[1]; rc = g_odbcAPI.SQLGetData( m_handles.m_hstmt, (SQLUSMALLINT)Field.Pos(), TargetType, Buf, bAddSpaceForNull? 1:0, &StrLen_or_IndPtr); if(rc != SQL_NO_DATA) { IodbcConnection::Check(rc, SQL_HANDLE_STMT, m_handles.m_hstmt); if(StrLen_or_IndPtr >= 0) nLongSize = StrLen_or_IndPtr; } unsigned char* pBuf; unsigned int nPortionSize = vr.PrepareReader( nLongSize, IodbcConnection::MaxLongAtExecSize, pBuf, fnReader, nReaderWantedPieceSize, pAddlData, bAddSpaceForNull); assert(nPortionSize <= IodbcConnection::MaxLongAtExecSize); SAPieceType_t ePieceType = SA_FirstPiece; unsigned int nTotalRead = 0; do { if(nLongSize) // known nPortionSize = sa_min(nPortionSize, nLongSize - nTotalRead); rc = g_odbcAPI.SQLGetData( m_handles.m_hstmt, (SQLUSMALLINT)Field.Pos(), TargetType, pBuf, nPortionSize + (bAddSpaceForNull? 1:0), &StrLen_or_IndPtr); assert(nPortionSize || rc == SQL_NO_DATA); if(rc != SQL_NO_DATA) { IodbcConnection::Check(rc, SQL_HANDLE_STMT, m_handles.m_hstmt); unsigned int NumBytes = ((StrLen_or_IndPtr > (int)nPortionSize) || (StrLen_or_IndPtr == SQL_NO_TOTAL))? nPortionSize : StrLen_or_IndPtr; nTotalRead += NumBytes; vr.InvokeReader(ePieceType, pBuf, NumBytes); } else { ePieceType = SA_LastPiece; vr.InvokeReader(ePieceType, pBuf, 0); }
if(ePieceType == SA_FirstPiece)
ePieceType = SA_NextPiece;
} while(rc != SQL_NO_DATA); } else { assert(eValueType == ISA_ParamValue); assert(false); }}/*virtual */void IodbcCursor::DescribeParamSP(){ SAString sText = m_pCommand->CommandText(); SAString sSchemaName; SAString sProcName; int n = sText.Find('.'); sSchemaName = sText.Left(n); sProcName = sText.Mid(n+1); SACommand cmd(m_pISAConnection->getSAConnection()); cmd.Open(); odbcCommandHandles *pHandles = (odbcCommandHandles *)cmd.NativeHandles(); IodbcConnection::Check(g_odbcAPI.SQLProcedureColumns( pHandles->m_hstmt, NULL, 0, sSchemaName.IsEmpty()? (SQLCHAR *)SQL_ALL_SCHEMAS : (SQLCHAR *)(const char*)sSchemaName, SQL_NTS, (SQLCHAR *)(const char*)sProcName, SQL_NTS, (SQLCHAR *)NULL, 0), SQL_HANDLE_STMT, pHandles->m_hstmt); while(cmd.FetchNext()) {// SAString sCat = cmd.Field(1); // "PROCEDURE_CAT"// SAString sSchem = cmd.Field(2); // "PROCEDURE_SCHEM"// SAString sProc = cmd.Field(3); // "PROCEDURE_NAME" SAString sCol = cmd.Field(4); // "COLUMN_NAME" short nColType = cmd.Field(5); // "COLUMN_TYPE" short nDataType = cmd.Field(6); // "DATA_TYPE"// SAString sType = cmd.Field(7); // "TYPE_NAME" long nColSize = cmd.Field(8).isNull()? 0 : (long)cmd.Field(8); // "COLUMN_SIZE" long nBufferLength = cmd.Field(9).isNull()? 0 : (long)cmd.Field(9); // "BUFFER_LENGTH" short nDecDigits = cmd.Field(10).isNull()? (short)0 : (short)cmd.Field(10); // "DECIMAL_DIGITS"// short nNumPrecPadix = cmd.Field(11).isNull()? 0 : (short)cmd.Field(11);// "NUM_PREC_RADIX"// short nNullable = cmd.Field(12).isNull()? 0 : (short)cmd.Field(12); // "NULLABLE" SAParamDirType_t eDirType; switch(nColType) { case SQL_PARAM_INPUT: eDirType = SA_ParamInput; break; case SQL_PARAM_INPUT_OUTPUT: eDirType = SA_ParamInputOutput; break; case SQL_PARAM_OUTPUT: eDirType = SA_ParamOutput; break; case SQL_RETURN_VALUE: eDirType = SA_ParamReturn; break; case SQL_PARAM_TYPE_UNKNOWN: case SQL_RESULT_COL: continue; default: assert(false); continue; } SADataType_t eParamType = CnvtNativeToStd(nDataType, 0, nBufferLength, nColSize, nDecDigits); SAString sParamName; if(sCol.IsEmpty()) { assert(eDirType == SA_ParamOutput); eDirType = SA_ParamReturn; sParamName = "RETURN_VALUE"; } else sParamName = sCol; m_pCommand->CreateParam(sParamName, eParamType, nDataType, nColSize, eDirType); }}/*virtual */saAPI *IodbcConnection::NativeAPI() const{ return &g_odbcAPI;}/*virtual */saConnectionHandles *IodbcConnection::NativeHandles(){ return &m_handles;}/*virtual */saCommandHandles *IodbcCursor::NativeHandles(){ return &m_handles;}/*virtual */void IodbcConnection::setIsolationLevel( SAIsolationLevel_t eIsolationLevel){ Commit(); issueIsolationLevel(eIsolationLevel);}void IodbcConnection::issueIsolationLevel( SAIsolationLevel_t eIsolationLevel){ long isolation; switch(eIsolationLevel) { case SA_ReadUncommitted: isolation = SQL_TXN_READ_UNCOMMITTED; break; case SA_ReadCommitted: isolation = SQL_TXN_READ_COMMITTED; break; case SA_RepeatableRead: isolation = SQL_TXN_REPEATABLE_READ; break; case SA_Serializable: isolation = SQL_TXN_SERIALIZABLE; break; default: assert(false); return; } Check(g_odbcAPI.SQLSetConnectAttr( m_handles.m_hdbc, SQL_ATTR_TXN_ISOLATION, SQLPOINTER(isolation), 0), SQL_HANDLE_DBC, m_handles.m_hdbc);}/*virtual */void IodbcConnection::setAutoCommit( SAAutoCommit_t eAutoCommit){ SQLUINTEGER nAutoCommit; switch(eAutoCommit) { case SA_AutoCommitOff: nAutoCommit = SQL_AUTOCOMMIT_OFF; break; case SA_AutoCommitOn: nAutoCommit = SQL_AUTOCOMMIT_ON; break; default: assert(false); return; } Check(g_odbcAPI.SQLSetConnectAttr( m_handles.m_hdbc, SQL_ATTR_AUTOCOMMIT, SQLPOINTER(nAutoCommit), 0), SQL_HANDLE_DBC, m_handles.m_hdbc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -