📄 oraclient.cpp
字号:
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 + -