📄 infclient.cpp
字号:
public: IinfCursor( IinfConnection *pIinfConnection, SACommand *pCommand); virtual ~IinfCursor(); virtual bool IsOpened(); virtual void Open(); virtual void Close(); virtual void Prepare( const SAString &sStmt, SACommandType_t eCmdType, int nPlaceHolderCount, saPlaceHolder **ppPlaceHolders); // binds parameters void Bind( int nPlaceHolderCount, saPlaceHolder **ppPlaceHolders); // executes statement virtual void Execute(
int nPlaceHolderCount,
saPlaceHolder **ppPlaceHolders);
// cleans up after execute if needed, so the statement can be reexecuted
virtual void UnExecute();
virtual void Cancel(); virtual bool ResultSetExists(); virtual void DescribeFields(
DescribeFields_cb_t fn);
virtual void SetSelectBuffers(); virtual bool FetchNext();
virtual long GetRowsAffected(); virtual void ReadLongOrLOB( ValueType_t eValueType, SAValueRead &vr, void *pValue, unsigned int nFieldBufSize, saLongOrLobReader_t fnReader, unsigned int nReaderWantedPieceSize, void *pAddlData); virtual void DescribeParamSP(); virtual saCommandHandles *NativeHandles();};//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////IinfCursor::IinfCursor( IinfConnection *pIinfConnection, SACommand *pCommand) : ISACursor(pIinfConnection, pCommand){}/*virtual */IinfCursor::~IinfCursor(){}/*virtual */unsigned int IinfCursor::InputBufferSize( const SAParam &Param) const{ if(!Param.isNull()) { switch(Param.DataType()) { case SA_dtBool:
return sizeof(unsigned char); // SQL_C_BIT
case SA_dtDateTime: return sizeof(TIMESTAMP_STRUCT); case SA_dtLongBinary: case SA_dtLongChar: case SA_dtBLob: case SA_dtCLob: return 0; default: break; } } return ISACursor::InputBufferSize(Param);}/*virtual */SADataType_t IinfCursor::CnvtNativeToStd( int dbtype, int/* dbsubtype*/, int/* dbsize*/, int prec, int scale) const{ SADataType_t eDataType = SA_dtUnknown; switch(dbtype) { case SQL_CHAR: // Character string of fixed length case SQL_VARCHAR: // Variable-length character string// case SQL_WCHAR: // Unicode character string of fixed length// case SQL_WVARCHAR: // Unicode variable-length character string eDataType = SA_dtString; break; case SQL_BINARY: case SQL_VARBINARY: eDataType = SA_dtBytes; break; case SQL_LONGVARCHAR: // Variable-length character data// case SQL_WLONGVARCHAR: // Variable-length character data eDataType = SA_dtLongChar; break; case SQL_LONGVARBINARY: // Variable-length binary data eDataType = SA_dtLongBinary; break; case SQL_DECIMAL: case SQL_NUMERIC: if(scale <= 0) { // check for exact type if(prec <= 5) eDataType = SA_dtShort; else if(prec <= 10) eDataType = SA_dtLong; else eDataType = SA_dtDouble; } else eDataType = SA_dtDouble; break; case SQL_SMALLINT: eDataType = SA_dtShort; break; case SQL_INTEGER: eDataType = SA_dtLong; break; case SQL_REAL: eDataType = SA_dtDouble; break; case SQL_FLOAT: eDataType = SA_dtDouble; break; case SQL_DOUBLE: eDataType = SA_dtDouble; break; case SQL_BIT: // Single bit binary data eDataType = SA_dtBool; break; case SQL_TINYINT: eDataType = SA_dtShort; break; case SQL_BIGINT: eDataType = SA_dtDouble; break; case SQL_TIME: case SQL_DATE: // == SQL_DATETIME case SQL_TIMESTAMP: case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: eDataType = SA_dtDateTime; break; default: assert(false); } return eDataType;}int IinfCursor::CnvtStdToNativeValueType(SADataType_t eDataType) const{ SQLSMALLINT ValueType; switch(eDataType) { case SA_dtUnknown: throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_DATA_TYPE); case SA_dtBool:
ValueType = SQL_C_BIT;
break;
case SA_dtShort: ValueType = SQL_C_SSHORT; break; case SA_dtLong: ValueType = SQL_C_SLONG; break; case SA_dtDouble: ValueType = SQL_C_DOUBLE; break; case SA_dtDateTime: ValueType = SQL_C_TYPE_TIMESTAMP; break; case SA_dtString: ValueType = SQL_C_CHAR; break; case SA_dtBytes: ValueType = SQL_C_BINARY; break; case SA_dtLongBinary: case SA_dtBLob: ValueType = SQL_C_BINARY; break; case SA_dtLongChar: case SA_dtCLob: ValueType = SQL_C_CHAR; break; default: ValueType = 0; assert(false); } if(((IinfConnection*)m_pISAConnection)->m_nDriverODBCVer < 0x00030000) { switch(eDataType) { case SA_dtDateTime: ValueType = SQL_C_TIMESTAMP; default: break; } } return ValueType;}/*virtual */int IinfCursor::CnvtStdToNative(SADataType_t eDataType) const{ SQLSMALLINT dbtype; switch(eDataType) { case SA_dtUnknown: throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_DATA_TYPE); case SA_dtBool:
dbtype = SQL_BIT;
break;
case SA_dtShort: dbtype = SQL_SMALLINT; break; case SA_dtLong: dbtype = SQL_INTEGER; break; case SA_dtDouble: dbtype = SQL_DOUBLE; break; case SA_dtDateTime: dbtype = SQL_TYPE_TIMESTAMP; break; case SA_dtString: dbtype = SQL_CHAR; break; case SA_dtBytes: dbtype = SQL_BINARY; break; case SA_dtLongBinary: case SA_dtBLob: dbtype = SQL_LONGVARBINARY; break; case SA_dtLongChar: case SA_dtCLob: dbtype = SQL_LONGVARCHAR; break; default: dbtype = 0; assert(false); } return dbtype;}/*virtual */bool IinfCursor::IsOpened(){ return m_handles.m_hstmt != NULL;}/*virtual */void IinfCursor::Open(){ SafeAllocStmt();}void IinfCursor::SafeAllocStmt(){ assert(m_handles.m_hstmt == NULL); if(g_infAPI.SQLAllocHandle) IinfConnection::Check(g_infAPI.SQLAllocHandle(SQL_HANDLE_STMT, ((IinfConnection*)m_pISAConnection)->m_handles.m_hdbc, &m_handles.m_hstmt), SQL_HANDLE_DBC, ((IinfConnection*)m_pISAConnection)->m_handles.m_hdbc); else IinfConnection::Check(g_infAPI.SQLAllocStmt(((IinfConnection*)m_pISAConnection)->m_handles.m_hdbc, &m_handles.m_hstmt), SQL_HANDLE_DBC, ((IinfConnection*)m_pISAConnection)->m_handles.m_hdbc);
assert(m_handles.m_hstmt != NULL);
}void IinfCursor::SafeFreeStmt(){ if(g_infAPI.SQLFreeHandle) IinfConnection::Check(g_infAPI.SQLFreeHandle(SQL_HANDLE_STMT, m_handles.m_hstmt), SQL_HANDLE_STMT, m_handles.m_hstmt); else IinfConnection::Check(g_infAPI.SQLFreeStmt(m_handles.m_hstmt, SQL_DROP), SQL_HANDLE_STMT, m_handles.m_hstmt); m_handles.m_hstmt = NULL;}/*virtual */void IinfCursor::Close(){ assert(m_handles.m_hstmt != NULL); SafeFreeStmt();}/*virtual */ISACursor *IinfConnection::NewCursor(SACommand *m_pCommand){ return new IinfCursor(this, m_pCommand);}/*virtual */void IinfCursor::Prepare( const SAString &sStmt, SACommandType_t eCmdType, int nPlaceHolderCount, saPlaceHolder** ppPlaceHolders){ SAString sStmtinf; int nPos = 0; int i; switch(eCmdType) { case SA_CmdSQLStmt: // replace bind variables with '?' place holder for(i = 0; i < nPlaceHolderCount; i++) { sStmtinf += sStmt.Mid(nPos, ppPlaceHolders[i]->getStart()-nPos); sStmtinf += "?"; nPos = ppPlaceHolders[i]->getEnd() + 1; } // copy tail if(nPos < sStmt.GetLength()) sStmtinf += sStmt.Mid(nPos); break; case SA_CmdStoredProc: sStmtinf = CallSubProgramSQL(); break; default: assert(false); } // a bit of clean up IinfConnection::Check(g_infAPI.SQLFreeStmt(m_handles.m_hstmt, SQL_CLOSE), SQL_HANDLE_STMT, m_handles.m_hstmt); IinfConnection::Check(g_infAPI.SQLFreeStmt(m_handles.m_hstmt, SQL_UNBIND), SQL_HANDLE_STMT, m_handles.m_hstmt); IinfConnection::Check(g_infAPI.SQLFreeStmt(m_handles.m_hstmt, SQL_RESET_PARAMS), SQL_HANDLE_STMT, m_handles.m_hstmt); IinfConnection::Check(g_infAPI.SQLPrepare( m_handles.m_hstmt, (SQLTCHAR*)(const char*)sStmtinf, SQL_NTS), SQL_HANDLE_STMT, m_handles.m_hstmt);}SAString IinfCursor::CallSubProgramSQL(){ int nParams = m_pCommand->ParamCount(); SAString sSQL = "{"; // check for Return parameter int i; for(i = 0; i < nParams; ++i) { SAParam &Param = m_pCommand->ParamByIndex(i); if(Param.ParamDirType() == SA_ParamReturn) { sSQL += "?="; break; } } sSQL += "call "; sSQL += m_pCommand->CommandText(); // specify parameters SAString sParams; for(i = 0; i < nParams; ++i) { SAParam &Param = m_pCommand->ParamByIndex(i); if(Param.ParamDirType() == SA_ParamReturn) continue; if(!sParams.IsEmpty()) sParams += ", "; sParams += "?"; }
// Informix specific: unlike other drivers
// if SP with no parameters is called it should have "()" sSQL += "(";
if(!sParams.IsEmpty()) { sSQL += sParams; } sSQL += ")";
sSQL += "}"; return sSQL;}void IinfCursor::BindLongs(){ SQLRETURN retcode; SQLPOINTER ValuePtr; try { while((retcode = g_infAPI.SQLParamData(m_handles.m_hstmt, &ValuePtr)) == SQL_NEED_DATA) { SAParam *pParam = (SAParam *)ValuePtr; unsigned int nActualWrite; SAPieceType_t ePieceType = SA_FirstPiece; void *pBuf; while((nActualWrite = pParam->InvokeWriter( ePieceType, IinfConnection::MaxLongAtExecSize, pBuf)) != 0) { IinfConnection::Check(g_infAPI.SQLPutData( m_handles.m_hstmt, pBuf, nActualWrite), SQL_HANDLE_STMT, m_handles.m_hstmt); if(ePieceType == SA_LastPiece) break; } } } catch(SAException&) { g_infAPI.SQLCancel(m_handles.m_hstmt); throw; } IinfConnection::Check(retcode, SQL_HANDLE_STMT, m_handles.m_hstmt);}
/*virtual */
void IinfCursor::UnExecute()
{
}
void IinfCursor::Bind(
int nPlaceHolderCount,
saPlaceHolder** ppPlaceHolders)
{
// we should bind for every place holder ('?')
AllocBindBuffer(nPlaceHolderCount, ppPlaceHolders,
sizeof(SQLINTEGER), 0);
void *pBuf = m_pParamBuffer;
for(int i = 0; i < nPlaceHolderCount; ++i)
{
SAParam &Param = *ppPlaceHolders[i]->getParam();
void *pInd;
void *pSize;
unsigned int nDataBufSize;
void *pValue;
IncParamBuffer(pBuf, pInd, pSize, nDataBufSize, pValue);
SADataType_t eDataType = Param.DataType();
SQLSMALLINT ParameterType = (SQLSMALLINT)(eDataType == SA_dtUnknown?
SQL_CHAR : // some type should be set
CnvtStdToNative(eDataType));
SQLSMALLINT ValueType = (SQLSMALLINT)(eDataType == SA_dtUnknown?
SQL_C_CHAR : // some type should be set
CnvtStdToNativeValueType(eDataType));
SQLINTEGER *StrLen_or_IndPtr = (SQLINTEGER *)pInd;
SQLPOINTER ParameterValuePtr = (SQLPOINTER)pValue;
SQLINTEGER BufferLength = (SQLINTEGER)nDataBufSize;
SQLUINTEGER ColumnSize = Param.ParamSize();
if(!ColumnSize) // not set explicitly
ColumnSize = BufferLength;
SQLSMALLINT InputOutputType;
switch(Param.ParamDirType())
{
case SA_ParamInput:
InputOutputType = SQL_PARAM_INPUT;
break;
case SA_ParamOutput:
InputOutputType = SQL_PARAM_OUTPUT;
break;
case SA_ParamInputOutput:
InputOutputType = SQL_PARAM_INPUT_OUTPUT;
break;
default:
assert(Param.ParamDirType() == SA_ParamReturn);
InputOutputType = SQL_PARAM_OUTPUT;
}
if(isInputParam(Param))
{
if(Param.isNull())
*StrLen_or_IndPtr = SQL_NULL_DATA; // field is null
else
*StrLen_or_IndPtr = InputBufferSize(Param); // field is not null
if(!Param.isNull())
{
switch(eDataType)
{
case SA_dtUnknown:
throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_PARAMETER_TYPE, (const char*)Param.Name());
case SA_dtBool:
assert(*StrLen_or_IndPtr == (SQLINTEGER)sizeof(unsigned char));
*(unsigned char*)ParameterValuePtr = (unsigned char)Param.asBool();
break;
case SA_dtShort:
assert(*StrLen_or_IndPtr == (SQLINTEGER)sizeof(short));
*(short*)ParameterValuePtr = Param.asShort();
break;
case SA_dtLong:
assert(*StrLen_or_IndPtr == (SQLINTEGER)sizeof(long));
*(long*)ParameterValuePtr = Param.asLong();
break;
case SA_dtDouble:
assert(*StrLen_or_IndPtr == (SQLINTEGER)sizeof(double));
*(double*)ParameterValuePtr = Param.asDouble();
break;
case SA_dtDateTime:
assert(*StrLen_or_IndPtr == (SQLINTEGER)sizeof(TIMESTAMP_STRUCT));
IinfConnection::CnvtDateTimeToInternal(
Param.asDateTime(),
*(TIMESTAMP_STRUCT*)ParameterValuePtr);
break;
case SA_dtString:
assert(*StrLen_or_IndPtr == Param.asString().GetLength());
memcpy(ParameterValuePtr, (const char*)Param.asString(), *StrLen_or_IndPtr);
break;
case SA_dtBytes:
assert(*StrLen_or_IndPtr == Param.asBytes().GetLength());
memcpy(ParameterValuePtr, (const char*)Param.asBytes(), *StrLen_or_IndPtr);
break;
case SA_dtLongBinary:
case SA_dtBLob:
case SA_dtLongChar:
case SA_dtCLob:
assert(*StrLen_or_IndPtr == 0);
break;
default:
ValueType = 0;
ParameterType = 0;
assert(false);
}
}
}
if(isLongOrLob(eDataType))
{
*StrLen_or_IndPtr = ((IinfConnection*)m_pISAConnection)->LenDataAtExec();
IinfConnection::Check(g_infAPI.SQLBindParameter(
m_handles.m_hstmt,
(SQLUSMALLINT)(i+1), InputOutputType,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -