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

📄 oraclient.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	try
	{
		// it is a piecewise bind, so we can bind only one column
		sword rc = 0;
		SAPieceType_t ePieceType = SA_FirstPiece;
		while(m_handles.m_cda.rc == 3129)
		{
			ub1 piece;
			dvoid* ctxp;
			ub4 iter;
			ub4 index;
			((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.ogetpi(
				&m_handles.m_cda,
				&piece, &ctxp, &iter, &index), &m_handles.m_cda);

			LongContext_t *pLongContext = (LongContext_t *)ctxp;
			void *pBuf;
			ub4 nActualWrite =
				pLongContext->pWriter->InvokeWriter(ePieceType, Iora7Connection::MaxLongPiece, pBuf);
			if(!nActualWrite || ePieceType == SA_LastPiece || ePieceType == SA_OnePiece)
				piece = OCI_LAST_PIECE;
			if(!nActualWrite)
				pBuf = NULL;

			((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.osetpi(
				&m_handles.m_cda,
				piece, pBuf, &nActualWrite), &m_handles.m_cda);

			rc = g_ora7API.oexec(&m_handles.m_cda);
		}

		if(m_handles.m_cda.rc != 3130) // the buffer for the next Piece to be fetched is required
			((Iora7Connection*)m_pISAConnection)->Check(rc, &m_handles.m_cda);
	}

	catch(SAUserException &)	// clean up after user exception
	{
		ub4 nActualWrite = 0;
		g_ora7API.osetpi(&m_handles.m_cda, OCI_LAST_PIECE, NULL, &nActualWrite);
		g_ora7API.oexec(&m_handles.m_cda);
		throw;
	}
}

/*virtual */
void Iora7Cursor::UnExecute()
{
	m_bResultSetExist = false;
}

/*virtual */
void Iora7Cursor::Execute(
	int nPlaceHolderCount,
	saPlaceHolder **ppPlaceHolders)
{
	if(nPlaceHolderCount)
		Bind(nPlaceHolderCount, ppPlaceHolders);

	sword rc = g_ora7API.oexec(&m_handles.m_cda);
	ub2 ft = m_handles.m_cda.ft;

	if(m_handles.m_cda.rc != 3129	// the next Piece to be inserted is required
		&& m_handles.m_cda.rc != 3130) // the buffer for the next Piece to be fetched is required
		((Iora7Connection*)m_pISAConnection)->Check(rc, &m_handles.m_cda);

	// Oracle can return both 3129 and 3130 (f.ex. in PL/SQL block)
	// we will be ready
	if(m_handles.m_cda.rc == 3129)
		BindLongs();
	if(m_handles.m_cda.rc == 3130) // the buffer for the next Piece to be fetched is required
	{
		assert(m_bPiecewiseBindAllowed);
		m_bPiecewiseFetchPending = true;
		CheckPiecewiseNull(true);
	}

	m_bResultSetExist = (ft == 4);
	ConvertOutputParams();	// if any
}

/*virtual */
void Iora7Cursor::Cancel()
{
	((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.obreak(
		&((Iora7Connection*)m_pISAConnection)->m_handles.m_lda), NULL);
}

void Iora7Cursor::Bind(
		int nPlaceHolderCount,
		saPlaceHolder**	ppPlaceHolders)
{
	// we should bind all params, not place holders in Oracle
	// one exception: :a and :"a" are belong to the same parameter in SQLAPI
	// but Oracle treats them as different
	AllocBindBuffer(sizeof(sb2), sizeof(ub2));
	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);

		SADataType_t eDataType = Param.DataType();
		sword ftype = (sword)(eDataType == SA_dtUnknown?
			1 : // VARCHAR2, some type should be set
			CnvtStdToNative(eDataType));

		sb2 *indp = (sb2 *)pInd;	// bind null indicator
		ub1 *pvctx = (ub1 *)pValue;
		sword progvl = nDataBufSize;	// allocated
		ub2 *alenp = (ub2 *)pSize;

		// special code for ref cursors
		if(eDataType == SA_dtCursor)
		{
			*indp = 0;	// set indicator as if field is not null always, or Oracle can throw an error ("invalid cursor")

			assert(nDataBufSize == sizeof(Cda_Def));
			memset(pvctx, 0, nDataBufSize);
			*alenp = 0;

			if(!Param.isNull() && isInputParam(Param))
			{
				SACommand *pCursor = Param.asCursor();
				assert(pCursor);

				const ora7CommandHandles *pH = (ora7CommandHandles *)pCursor->NativeHandles();
				memcpy(pvctx, &pH->m_cda, sizeof(Cda_Def));

				*alenp = (ub2)InputBufferSize(Param);
			}
		}
		else
		{
			if(isInputParam(Param))
			{
				if(Param.isNull())
					*indp = -1;	// field is null
				else
					*indp = 0;	// field is not null

				*alenp = (ub2)InputBufferSize(Param);
				assert(progvl >= *alenp);

				if(Param.isNull())
				{
					if(progvl == 0)
						progvl = 1;	// dummy, because Oracle can hang when == 0
				}
				else
				{
					switch(eDataType)
					{
					case SA_dtUnknown:
						throw SAException(SA_Library_Error, -1, -1, IDS_UNKNOWN_PARAMETER_TYPE, (const char*)Param.Name());
					case SA_dtBool:
						// there is no "native" boolean type in Oracle,
						// so treat boolean as 16-bit signed INTEGER in Oracle
						assert(*alenp == sizeof(short));
						*(short*)pvctx = (short)Param.asBool();
						break;
					case SA_dtShort:
						assert(*alenp == sizeof(short));
						*(short*)pvctx = Param.asShort();
						break;
					case SA_dtLong:
						assert(*alenp == sizeof(long));
						*(long*)pvctx = Param.asLong();
						break;
					case SA_dtDouble:
						assert(*alenp == sizeof(double));
						*(double*)pvctx = Param.asDouble();
						break;
					case SA_dtDateTime:
						assert(*alenp == sizeof(OraDate_t));
						IoraConnection::CnvtDateTimeToInternal(
							Param.asDateTime(),
							(OraDate_t*)pvctx);
						break;
					case SA_dtString:
						assert(*alenp == (ub2)Param.asString().GetLength());
						memcpy(pvctx, (const char*)Param.asString(), *alenp);
						break;
					case SA_dtBytes:
						assert(*alenp == (ub2)Param.asBytes().GetLength());
						memcpy(pvctx, (const char*)Param.asBytes(), *alenp);
						break;
					case SA_dtLongBinary:
					case SA_dtBLob:
						assert(*alenp == sizeof(LongContext_t));
						break;
					case SA_dtLongChar:
					case SA_dtCLob:
						assert(*alenp == sizeof(LongContext_t));
						break;
					case SA_dtCursor:
						assert(false);	// already handled
						break;
					default:
						assert(false);
					}
				}
			}
		}

		bool bLong = isLongOrLob(eDataType);

		for(int j = 0; j < nPlaceHolderCount; ++j)
		{
			saPlaceHolder &PlaceHolder = *ppPlaceHolders[j];
			if(PlaceHolder.getParam() != &Param)
				continue;

			if(bLong)
			{
				LongContext_t *pLongContext = (LongContext_t *)pvctx;
				pLongContext->pReader = &Param;
				pLongContext->pWriter = &Param;
				pLongContext->pInd = (sb2*)pInd;

				if(m_bPiecewiseBindAllowed)
				{
					((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.obindps(
						&m_handles.m_cda,	0,
						(text*)(const char*)PlaceHolder.getFullName(), -1,
						pvctx, SB4MAXVAL, ftype,
						0,	// scale, not used
						indp, (ub2*)0,
						NULL, 0, 0, 0, 0, 0, NULL, NULL, 0, 0), &m_handles.m_cda);	// not used
					pLongContext->eState = LongContextPiecewiseBind;
				}
				else
				{
					((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.obndra(
						&m_handles.m_cda, 
						(text*)(const char*)Param.Name(), -1,
						pvctx, progvl, ftype,
						0,	// scale, not used
						indp, alenp,
						NULL, 0, NULL, NULL, 0, 0), &m_handles.m_cda);	// not used
					pLongContext->eState = LongContextNormal;
				}
			}
			else
			{
				if(m_bPiecewiseBindAllowed)
					((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.obindps(
						&m_handles.m_cda,	1,
						(text*)(const char*)PlaceHolder.getFullName(), -1,
						pvctx, progvl, ftype,
						0,	// scale, not used
						indp, alenp,
						NULL, 0, 0, 0, 0, 0, NULL, NULL, 0, 0), &m_handles.m_cda);	// not used
				else
				{
					((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.obndra(
						&m_handles.m_cda, 
						(text*)(const char*)Param.Name(), -1,
						pvctx, progvl, ftype,
						0,	// scale, not used
						indp, alenp,
						NULL, 0, NULL, NULL, 0, 0), &m_handles.m_cda);	// not used
				}
			}
		}
	}
}

/*virtual */
bool Iora7Cursor::ResultSetExists()
{
	return m_bResultSetExist;
}

void Iora7Cursor::DescribeFields(
	DescribeFields_cb_t fn)
{
	sword iField = 0;
	do
	{
		sb4 dbsize;
		sb2 dbtype;
		sb1 cbuf[1024];
		sb4 cbufl = sizeof(cbuf);
		sb4 dsize;
		sb2 prec;
		sb2 scale;
		sb2 nullok;

		sword rc = g_ora7API.odescr(
			&m_handles.m_cda, ++iField,
			&dbsize,
			&dbtype,
			cbuf,
			&cbufl,
			&dsize,
			&prec,
			&scale,
			&nullok);

		if(m_handles.m_cda.rc == 1007)
			break;
		((Iora7Connection*)m_pISAConnection)->Check(rc, &m_handles.m_cda);

		(m_pCommand->*fn)(
			SAString((const char*)cbuf, cbufl),
			CnvtNativeToStd(dbtype, 0, dbsize, prec, scale),
			(int)dbtype,
			dbsize,
			prec,
			scale,
			nullok == 0);
	}
	while(m_handles.m_cda.rc != 1007);
}

/*virtual */
long Iora7Cursor::GetRowsAffected()
{
	return m_handles.m_cda.rpc;
}

SAField *Iora7Cursor::WhichFieldIsPiecewise() const
{
	// field can be fetched piecewise if:
	// 1. it it Long*
	// 2. it is the last in select list
	// 3. it is the only Long* field in select list
	if(FieldCount(2,
		SA_dtLongBinary, SA_dtLongChar) == 1)
	{
		SAField &Field = m_pCommand->Field(m_pCommand->FieldCount());
		switch(Field.FieldType())
		{
		case SA_dtLongBinary:
		case SA_dtLongChar:
			return &Field;
		default:
			break;
		}
	}
	return 0;
}

/*virtual */
void Iora7Cursor::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);

	sword ftype;
	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_dtShort:
			ftype = 3;	// 16-bit signed integer
			break;
		case SA_dtLong:
			ftype = 3;	// 32-bit signed integer
			break;
		case SA_dtDouble:
			ftype = 4;	// FLOAT;
			break;
		case SA_dtDateTime:
			ftype = 12;	// DATE;
			break;
		case SA_dtString:
			ftype = 1;	// VARCHAR2
			break;
		case SA_dtLongBinary:
			bLong = true;	// piecewise define
			ftype = 24;	// LONG RAW
			break;
		case SA_dtLongChar:
			bLong = true;	// piecewise define
			ftype = 8;	// LONG
			break;
		case SA_dtCursor:
			ftype = 102;	// CURSOR VARIABLE
			memset(pValue, 0, sizeof(Cda_Def));
			break;
		default:
			ftype = 0;
			assert(false);	// unknown type
	}

	if(bLong)
	{
		LongContext_t *pLongContext = (LongContext_t *)pValue;
		pLongContext->pReader = &Field;
		pLongContext->pWriter = 0;
		pLongContext->pInd = (sb2*)pInd;

		if(m_bPiecewiseFetchAllowed)
		{
			// use piecewise only if this long column is the last column and the only long column
			if(WhichFieldIsPiecewise() == &Field)
			{
				((Iora7Connection*)m_pISAConnection)->Check(
					g_ora7API.odefinps(&m_handles.m_cda, 0, nCol, (ub1*)pLongContext, SB4MAXVAL,
					ftype, 0, (sb2*)pInd,
					NULL, 0, 0,
					(ub2*)pSize,
					NULL, 0, 0, 0, 0), &m_handles.m_cda);
				pLongContext->eState = LongContextPiecewiseDefine;
			}
			else
			{
				((Iora7Connection*)m_pISAConnection)->Check(
					g_ora7API.odefinps(&m_handles.m_cda, 1, nCol, NULL, 0,
					ftype, 0, (sb2*)pInd,
					NULL, 0, 0,
					(ub2*)pSize,
					NULL, 0, 0, 0, 0), &m_handles.m_cda);
				pLongContext->eState = LongContextNormal;
			}
		}
		else
		{
			((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.odefin(&m_handles.m_cda, nCol,
				(ub1*)NULL, 0, ftype,
				0, // scale, not used
				(sb2*)pInd, 
				(text*)NULL, 0, 0, // fmt, fmtl, fmtt, not used
				(ub2*)pSize,
				NULL), &m_handles.m_cda);	// rcode not used
			pLongContext->eState = LongContextNormal;
		}
	}
	else
	{
		if(m_bPiecewiseFetchAllowed)
		{
			((Iora7Connection*)m_pISAConnection)->Check(
				g_ora7API.odefinps(&m_handles.m_cda, 1, nCol, (ub1*)pValue, nValueSize,
				ftype, 0, (sb2*)pInd,
				NULL, 0, 0,
				(ub2*)pSize,
				NULL, 0, 0, 0, 0), &m_handles.m_cda);
		}
		else
		{
			((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.odefin(&m_handles.m_cda, nCol,
				(ub1*)pValue, nValueSize, ftype,
				0, // scale, not used
				(sb2*)pInd, 
				(text*)NULL, 0, 0, // fmt, fmtl, fmtt, not used
				(ub2*)pSize,
				NULL), &m_handles.m_cda);	// rcode not used
		}
	}
}

/*virtual */
void Iora7Cursor::SetSelectBuffers()
{
	// use default helpers
	AllocSelectBuffer(sizeof(sb2), sizeof(ub2));
}

void Iora7Cursor::DiscardPiecewiseFetch()
{
	sword rc;
	do
	{
		ub1 piece;
		dvoid *ctxp;
		ub4 iter, index;
		char buf[0xFFFF];
		ub4 len = sizeof(buf);

		((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.ogetpi(
			&m_handles.m_cda,
			&piece, &ctxp, &iter, &index), &m_handles.m_cda);

		((Iora7Connection*)m_pISAConnection)->Check(g_ora7API.osetpi(
			&m_handles.m_cda,
			piece, buf, &len), &m_handles.m_cda);

		rc = g_ora7API.ofetch(&m_handles.m_cda);
	}
	while(m_handles.m_cda.rc == 3130);
	((Iora7Connection*)m_pISAConnection)->Check(rc, &m_handles.m_cda);

⌨️ 快捷键说明

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