⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 odbcclient.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -