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

📄 sybclient.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 4 页
字号:
{
	// no preparing in OpenClient
	// all is beeing done in Execute()
}

// process command batch or stored proc results
// stop if all commands processed or result set encounted
void IsybCursor::ProcessBatchUntilEndOrResultSet()
{
	bool bParamResult = false;
	bool bStatusResult = false;

	CS_RETCODE rcd;
	CS_INT res_type;
	while((rcd = ((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_results(
		m_handles.m_command, &res_type))) == CS_SUCCEED)
	{
		bool bResultSet = false;
		switch(res_type)
		{
			case CS_CMD_SUCCEED:	// Command returning no rows completed sucessfully
				break;
			case CS_CMD_DONE:		// This means we're done with one result set
				((IsybConnection *)m_pISAConnection)->Check(g_sybAPI.ct_res_info(
					m_handles.m_command,
					CS_ROW_COUNT,
					&m_nRowsAffected, CS_UNUSED, NULL));
				break;
			case CS_CMD_FAIL:		// This means that the server encountered an error while processing our command
				((IsybConnection *)m_pISAConnection)->Check(CS_FAIL);
				break;
			case CS_ROW_RESULT:
				bResultSet = true;
				break;
			case CS_STATUS_RESULT:
				FetchStatusResult();
				bStatusResult = true;				
				break;
			case CS_PARAM_RESULT:
				FetchParamResult();
				bParamResult = true;
				break;
			case CS_COMPUTE_RESULT:
				assert(false);
				break;
			default:
				assert(false);
		}

		if(bResultSet)
		{
			m_bResultsPending = true;
			return;
		}
	}

	// We've finished processing results. Let's check the
	// return value of ct_results() to see if everything
	// went ok.
	switch(rcd)
	{
	case CS_END_RESULTS:	// Everything went fine
		m_bResultsPending = false;
		if(bStatusResult || bParamResult)
			ConvertOutputParams();
		break;
	case CS_FAIL:			// Something went wrong
		((IsybConnection*)m_pISAConnection)->Check(rcd);
		break;
	default:				// We got an unexpected return value
		assert(false);
	}
}

/*virtual */
void IsybCursor::UnExecute()
{
	CheckAndCancelPendingResults();
}

/*virtual */
void IsybCursor::Execute(
	int nPlaceHolderCount,
	saPlaceHolder **ppPlaceHolders)
{
	// some kind of Prepare() first
	if(m_pCommand->CommandType() == SA_CmdStoredProc)
	{
		((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_command(
			m_handles.m_command,
			CS_RPC_CMD,
			(CS_CHAR*)(const char*)m_pCommand->CommandText(),
			CS_NULLTERM,
			CS_NO_RECOMPILE));
	}

	// always bind, even if no parameters
	// because Bind() does ct_command for non SP
	Bind(nPlaceHolderCount, ppPlaceHolders);

	((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_send(
		m_handles.m_command));

	try
	{
		ProcessBatchUntilEndOrResultSet();
	}
	catch(SAException &)	// clean up after ct_send
	{
		// cancel any results pending
		assert(!m_bResultsPending);
		g_sybAPI.ct_cancel(NULL, m_handles.m_command, CS_CANCEL_ALL);
		throw;
	}
}

/*virtual */
void IsybCursor::Cancel()
{
	((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_cancel(
		NULL, m_handles.m_command, CS_CANCEL_ALL));
}

void IsybCursor::BindImage(SAParam &Param, SAString *pValue)
{
	*pValue += "0x";

	unsigned int nActualWrite;
	SAPieceType_t ePieceType = SA_FirstPiece;
	void *pBuf;
	while((nActualWrite = Param.InvokeWriter(
		ePieceType, 0xffff, pBuf)) != 0)
	{
		*pValue += ((IsybConnection*)m_pISAConnection)->ConvertToString(
			CS_IMAGE_TYPE, (CS_VOID*)pBuf, nActualWrite);

		if(ePieceType == SA_LastPiece)
			break;
	}
}

void IsybCursor::BindText(SAParam &Param, SAString *pValue)
{
	*pValue += "'";

	unsigned int nActualWrite;
	SAPieceType_t ePieceType = SA_FirstPiece;
	void *pBuf;
	while((nActualWrite = Param.InvokeWriter(
		ePieceType, 0xffff, pBuf)) != 0)
	{
		SAString sTemp((const char *)pBuf, nActualWrite);
		sTemp.Replace("'", "''");
		*pValue += sTemp;

		if(ePieceType == SA_LastPiece)
			break;
	}

	*pValue += "'";
}

void IsybCursor::Bind(
		int nPlaceHolderCount,
		saPlaceHolder**	ppPlaceHolders)
{
	// always alloc bind buffer, even if we will not use it
	// 'exec SP' to work
	AllocBindBuffer(sizeof(CS_SMALLINT), sizeof(CS_INT));

	SAString sOriginalStmst = m_pCommand->CommandText();

	if(m_pCommand->CommandType() == SA_CmdSQLStmt)
	{
		// we will bind directly to command buffer
		CancelPendingResults();
		SAString sBoundStmt;

		// change ':' param markers to bound values
		unsigned int nPos = 0;
		for(int i = 0; i < nPlaceHolderCount; ++i)
		{
			SAParam &Param = *ppPlaceHolders[i]->getParam();

			sBoundStmt += sOriginalStmst.Mid(nPos, ppPlaceHolders[i]->getStart()-nPos);

			SAString sBoundValue;
			SAString sTemp;
			CS_BIT bitTemp;

			if(Param.isNull())
			{
				sBoundStmt += "NULL";
			}
			else
			{
				switch(Param.DataType())
				{
				case SA_dtUnknown:
					throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_PARAMETER_TYPE, (const char*)Param.Name());
				case SA_dtBool:
					bitTemp = (CS_BIT)Param.setAsBool();
					sBoundValue = ((IsybConnection*)m_pISAConnection)->ConvertToString(
						CS_BIT_TYPE, (CS_VOID*)&bitTemp, sizeof(CS_BIT));
					break;
				case SA_dtShort:
					sBoundValue = ((IsybConnection*)m_pISAConnection)->ConvertToString(
						CS_SMALLINT_TYPE, (CS_VOID*)&Param.setAsShort(), sizeof(short));
					break;
				case SA_dtLong:
					sBoundValue = ((IsybConnection*)m_pISAConnection)->ConvertToString(
						CS_INT_TYPE, (CS_VOID*)&Param.setAsLong(), sizeof(long));
					break;
				case SA_dtDouble:
					sBoundValue = ((IsybConnection*)m_pISAConnection)->ConvertToString(
						CS_FLOAT_TYPE, (CS_VOID*)&Param.setAsDouble(), sizeof(double));
					break;
				case SA_dtDateTime:
					IsybConnection::CnvtDateTimeToInternal(
						Param.setAsDateTime(), sTemp);
					sBoundValue = "'";
					sBoundValue += sTemp;
					sBoundValue += "'";
					break;
				case SA_dtString:
					sTemp = Param.asString();
					sTemp.Replace("'", "''");
					sBoundValue = "'";
					sBoundValue += sTemp;
					sBoundValue += "'";
					break;
				case SA_dtBytes:
					sBoundValue = "0x";
					sBoundValue += ((IsybConnection*)m_pISAConnection)->ConvertToString(
						CS_BINARY_TYPE, (CS_VOID*)(const char*)Param.asBytes(), Param.asBytes().GetLength());
					break;
				case SA_dtLongBinary:
				case SA_dtBLob:
					BindImage(Param, &sBoundStmt);
					break;
				case SA_dtLongChar:
				case SA_dtCLob:
					BindText(Param, &sBoundStmt);
					break;
				default:
					assert(false);
				}

				switch(Param.DataType())
				{
				case SA_dtLongBinary:
				case SA_dtLongChar:
				case SA_dtBLob:
				case SA_dtCLob:
					break;	// was already written
				default:
					sBoundStmt += sBoundValue;
				}
			}

			nPos = ppPlaceHolders[i]->getEnd() + 1;
		}
		// copy tail
		if(nPos < strlen(sOriginalStmst))
			sBoundStmt += sOriginalStmst.Mid(nPos);

		((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_command(
			m_handles.m_command,
			CS_LANG_CMD, (CS_CHAR*)(const char*)sBoundStmt, CS_NULLTERM,
			CS_UNUSED));
	}
	else
	{
		assert(m_pCommand->CommandType() == SA_CmdStoredProc);

		void *pBuf = m_pParamBuffer;

		for(int i = 0; i < m_pCommand->ParamCount(); ++i)
		{
			SAParam &Param = m_pCommand->ParamByIndex(i);

			void *pInd;
			void *pSize;
			unsigned int nDataBufSize;
			void *pValue;
			IncParamBuffer(pBuf, pInd, pSize, nDataBufSize, pValue);

			if(Param.ParamDirType() == SA_ParamReturn)
				continue;
			assert(isInputParam(Param));	// all params can be input in ASE and ASA


			SAString sName = "@";
			sName += Param.Name();

			SADataType_t eDataType = Param.DataType();
			CS_INT type = (CS_INT)CnvtStdToNative(eDataType);
			
			unsigned int nInputBufSize = InputBufferSize(Param);
			assert(nInputBufSize <= nDataBufSize);

			CS_SMALLINT &indicator = *(CS_SMALLINT*)pInd;
			CS_INT &datalen = *(CS_INT*)pSize;
			CS_VOID *data;
			if(Param.isNull())
			{
				indicator = -1;
				datalen = CS_UNUSED;
				data = NULL;
			}
			else
			{
				indicator = 0;
				datalen = (CS_INT)nInputBufSize;
				data = (CS_VOID*)pValue;
			}
			
			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(nInputBufSize == sizeof(CS_BIT));
						*(CS_BIT*)data = (CS_BIT)Param.asBool();
						break;
					case SA_dtShort:
						assert(nInputBufSize == sizeof(short));
						*(short*)data = Param.asShort();
						break;
					case SA_dtLong:
						assert(nInputBufSize == sizeof(long));
						*(long*)data = Param.asLong();
						break;
					case SA_dtDouble:
						assert(nInputBufSize == sizeof(double));
						*(double*)data = Param.asDouble();
						break;
					case SA_dtDateTime:
						assert(nInputBufSize == sizeof(CS_DATETIME));	// Sybase internal date/time representation
						((IsybConnection*)m_pISAConnection)->CnvtDateTimeToInternal(
							Param.asDateTime(),
							(CS_DATETIME*)data);
						break;
					case SA_dtString:
						assert((int)nInputBufSize == Param.asString().GetLength());
						memcpy(data, (const char*)Param.asString(), nInputBufSize);
						break;
					case SA_dtBytes:
						assert((int)nInputBufSize == Param.asBytes().GetLength());
						memcpy(data, (const char*)Param.asBytes(), nInputBufSize);
						break;
					case SA_dtLongBinary:
					case SA_dtBLob:
					case SA_dtLongChar:
					case SA_dtCLob:
						if(Param.m_fnWriter != saDefaultLongOrLobWriter)	// use internal buffer as temp
						{
							Param.m_pString->Empty();

							unsigned int nActualWrite;
							SAPieceType_t ePieceType = SA_FirstPiece;
							void *pBuf;
							while((nActualWrite = Param.InvokeWriter(
								ePieceType, 0xffff, pBuf)) != 0)
							{
								(*Param.m_pString) += SAString((const char*)pBuf, nActualWrite);

								if(ePieceType == SA_LastPiece)
									break;
							}
						}
						pValue = (void*)(const char*)(*Param.m_pString);
						datalen = (CS_INT)Param.m_pString->GetLength();
						break;
					default:
						assert(false);
				}
			}

			CS_DATAFMT df;
			strcpy(df.name, sName);
			df.namelen = sName.GetLength();
			df.datatype = type;
			df.maxlength = (CS_INT)nDataBufSize;
			df.status = isOutputParam(Param)? CS_RETURN : CS_INPUTVALUE;
			df.locale = NULL;
			((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_param(
				m_handles.m_command,
				&df,
				(CS_VOID*)pValue,
				datalen,
				indicator));
		}
	}
}

/*virtual */
bool IsybCursor::ResultSetExists()
{
	return m_bResultsPending;
}

/*virtual */
void IsybCursor::DescribeFields(
	DescribeFields_cb_t fn)
{
	CS_INT nNumData;
	((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_res_info(
		m_handles.m_command,
		CS_NUMDATA,
		&nNumData,
		CS_UNUSED,
		NULL));

	for(CS_INT iField = 1; iField <= nNumData; ++iField)
	{
		CS_DATAFMT df;

		((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_describe(
			m_handles.m_command,
			(CS_INT)iField,
			&df));

		(m_pCommand->*fn)(
			SAString(df.name, df.namelen),
			CnvtNativeToStd(
				df.datatype, 0,
				df.maxlength,
				df.precision,
				df.scale),
			(int)df.datatype,
			df.maxlength,
			df.precision,
			df.scale,
			(df.status & CS_CANBENULL) == 0);
	}
}

/*virtual */
long IsybCursor::GetRowsAffected()
{
	return m_nRowsAffected;
}

void IsybCursor::ct_bind_Buffer(
	int nCol,	// 1-based
	void *pInd,
	unsigned int nIndSize,
	void *pSize,
	unsigned int nSizeSize,
	void *pValue,
	unsigned int nValueSize,
	SADataType_t eDataType,
	SAString sName,
	CS_INT count)
{
	assert(nIndSize == sizeof(CS_SMALLINT));
	if(nIndSize != sizeof(CS_SMALLINT))
		return;
	assert(nSizeSize == sizeof(CS_INT));
	if(nSizeSize != sizeof(CS_INT))
		return;

	CS_DATAFMT datafmt;
	datafmt.datatype = (CS_INT)CnvtStdToNative(eDataType);
	datafmt.count = count;
	datafmt.format = CS_FMT_UNUSED;
	datafmt.maxlength = nValueSize;
	datafmt.scale = CS_SRC_VALUE;
	datafmt.precision = CS_SRC_VALUE;
	datafmt.locale = NULL;

	bool bLong = false;
	switch(eDataType)
	{
		case SA_dtUnknown:
			throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_COLUMN_TYPE, (const char*)sName);
		case SA_dtBool:
			assert(datafmt.maxlength == (CS_INT)sizeof(CS_BIT));
			break;
		case SA_dtShort:
			assert(datafmt.maxlength == (CS_INT)sizeof(short));
			break;
		case SA_dtLong:
			assert(datafmt.maxlength == (CS_INT)sizeof(long));
			break;
		case SA_dtDouble:
			assert(datafmt.maxlength == (CS_INT)sizeof(double));
			break;
		case SA_dtDateTime:
			assert(datafmt.maxlength == (CS_INT)sizeof(CS_DATETIME));
			break;
		case SA_dtString:
			break;
		case SA_dtBytes:
			break;
		case SA_dtLongBinary:
		case SA_dtLongChar:
			assert(datafmt.maxlength == 0);
			bLong = true;
			break;
		default:
			assert(false);	// unknown type
	}
	
	if(!bLong)
	{
		((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_bind(
			m_handles.m_command,
			nCol,
			&datafmt,
			(CS_VOID*)pValue,
			(CS_INT*)pSize,
			(CS_SMALLINT*)pInd));
	}
}

/*virtual */
void IsybCursor::SetFieldBuffer(
	int nCol,	// 1-based
	void *pInd,
	unsigned int nIndSize,
	void *pSize,
	unsigned int nSizeSize,
	void *pValue,
	unsigned int nValueSize)
{
	SAField &Field = m_pCommand->Field(nCol);

	ct_bind_Buffer(
		nCol,
		pInd, nIndSize,
		pSize, nSizeSize,
		pValue, nValueSize,
		Field.FieldType(), Field.Name(),
		m_cRowsToPrefetch);
}

/*virtual */
void IsybCursor::SetSelectBuffers()
{
	SAString sOption = m_pCommand->Option(
		"PreFetchRows");
	if(!sOption.IsEmpty())
	{
		int cLongs = FieldCount(4, SA_dtLongBinary, SA_dtLongChar, SA_dtBLob, SA_dtCLob);
		if(cLongs)	// do not use bulk fetch if there are text or image columns
			m_cRowsToPrefetch = 1;
		else
			m_cRowsToPrefetch = atol(sOption);
	}
	else
		m_cRowsToPrefetch = 1;
	m_cRowsObtained = 0;
	m_cRowCurrent = 0;
	
	// use default helpers
	AllocSelectBuffer(sizeof(CS_SMALLINT), sizeof(CS_INT), m_cRowsToPrefetch);
}

/*virtual */
bool IsybCursor::IndicatorIsNull(
	int nPos,	// 1-based, can be field or param pos
	SAValueRead &vr,
	ValueType_t eValueType,
	void *pInd, unsigned int nIndSize,
	void *pSize, unsigned int nSizeSize,
	unsigned int &nRealSize,
	int nBulkReadingBufPos) const
{
	if(!isLongOrLob(vr.DataType()))
		return ISACursor::IndicatorIsNull(
			nPos, vr, eValueType,
			pInd, nIndSize,
			pSize, nSizeSize,
			nRealSize,
			nBulkReadingBufPos);

	char pBuf[1];
	CS_RETCODE rcd = ((IsybConnection*)m_pISAConnection)->Check(g_sybAPI.ct_get_data(
		m_handles.m_command,
		nPos,
		pBuf, 0,
		NULL));
	if(rcd == CS_END_ITEM || rcd == CS_END_DATA)
		return true;

	return false;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -