SQL/OCI: use OCIBindByPos2 instead OCIBindByPos

Use OCIBindByPos2 instead OCIBindByPos where it was not yet changed to
allow lengths > 2^31 (and avoid unneeded casts).

This is a follow-up of 7005630a9b735f2e59e3345fee0305e0277c0208.

Change-Id: I8b6efdfdb0fb349043e9c84ceba17e008882f584
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 911eac26d482b8d63419648d6f735c49e9e17c82)
This commit is contained in:
Christian Ehrlicher 2024-08-23 13:12:43 +02:00
parent ca3fa76a4e
commit e99c2d9314

View File

@ -77,7 +77,7 @@ static const ub2 qOraCharset = OCI_UCS2ID;
#endif #endif
typedef QVarLengthArray<sb2, 32> IndicatorArray; typedef QVarLengthArray<sb2, 32> IndicatorArray;
typedef QVarLengthArray<ub2, 32> SizeArray; typedef QVarLengthArray<ub4, 32> SizeArray;
static QByteArray qMakeOCINumber(const qlonglong &ll, OCIError *err); static QByteArray qMakeOCINumber(const qlonglong &ll, OCIError *err);
static QByteArray qMakeOCINumber(const qulonglong& ull, OCIError* err); static QByteArray qMakeOCINumber(const qulonglong& ull, OCIError* err);
@ -248,7 +248,7 @@ public:
void setStatementAttributes(); void setStatementAttributes();
int bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, int pos, int bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, int pos,
const QVariant &val, dvoid *indPtr, ub2 *tmpSize, TempStorage &tmpStorage); const QVariant &val, dvoid *indPtr, ub4 *tmpSize, TempStorage &tmpStorage);
int bindValues(QVariantList &values, IndicatorArray &indicators, SizeArray &tmpSizes, int bindValues(QVariantList &values, IndicatorArray &indicators, SizeArray &tmpSizes,
TempStorage &tmpStorage); TempStorage &tmpStorage);
void outValues(QVariantList &values, IndicatorArray &indicators, void outValues(QVariantList &values, IndicatorArray &indicators,
@ -325,7 +325,7 @@ void QOCIResultPrivate::setStatementAttributes()
} }
int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, int pos, int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, int pos,
const QVariant &val, dvoid *indPtr, ub2 *tmpSize, TempStorage &tmpStorage) const QVariant &val, dvoid *indPtr, ub4 *tmpSize, TempStorage &tmpStorage)
{ {
int r = OCI_SUCCESS; int r = OCI_SUCCESS;
void *data = const_cast<void *>(val.constData()); void *data = const_cast<void *>(val.constData());
@ -344,62 +344,62 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
case QMetaType::QDate: case QMetaType::QDate:
case QMetaType::QDateTime: { case QMetaType::QDateTime: {
QOCIDateTime *ptr = new QOCIDateTime(env, err, val.toDateTime()); QOCIDateTime *ptr = new QOCIDateTime(env, err, val.toDateTime());
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
&ptr->dateTime, &ptr->dateTime,
sizeof(OCIDateTime *), sizeof(OCIDateTime *),
SQLT_TIMESTAMP_TZ, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_TIMESTAMP_TZ, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
tmpStorage.dateTimes.append(ptr); tmpStorage.dateTimes.append(ptr);
break; break;
} }
case QMetaType::Int: case QMetaType::Int:
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
// if it's an out value, the data is already detached // if it's an out value, the data is already detached
// so the const cast is safe. // so the const cast is safe.
const_cast<void *>(data), const_cast<void *>(data),
sizeof(int), sizeof(int),
SQLT_INT, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_INT, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
break; break;
case QMetaType::UInt: case QMetaType::UInt:
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
// if it's an out value, the data is already detached // if it's an out value, the data is already detached
// so the const cast is safe. // so the const cast is safe.
const_cast<void *>(data), const_cast<void *>(data),
sizeof(uint), sizeof(uint),
SQLT_UIN, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_UIN, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
break; break;
case QMetaType::LongLong: case QMetaType::LongLong:
{ {
QByteArray ba = qMakeOCINumber(val.toLongLong(), err); QByteArray ba = qMakeOCINumber(val.toLongLong(), err);
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
ba.data(), ba.data(),
ba.size(), ba.size(),
SQLT_VNU, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_VNU, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
tmpStorage.rawData.append(ba); tmpStorage.rawData.append(ba);
break; break;
} }
case QMetaType::ULongLong: case QMetaType::ULongLong:
{ {
QByteArray ba = qMakeOCINumber(val.toULongLong(), err); QByteArray ba = qMakeOCINumber(val.toULongLong(), err);
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
ba.data(), ba.data(),
ba.size(), ba.size(),
SQLT_VNU, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_VNU, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
tmpStorage.rawData.append(ba); tmpStorage.rawData.append(ba);
break; break;
} }
case QMetaType::Double: case QMetaType::Double:
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
// if it's an out value, the data is already detached // if it's an out value, the data is already detached
// so the const cast is safe. // so the const cast is safe.
const_cast<void *>(data), const_cast<void *>(data),
sizeof(double), sizeof(double),
SQLT_FLT, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_FLT, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
break; break;
case QMetaType::QString: { case QMetaType::QString: {
const QString s = val.toString(); const QString s = val.toString();
@ -429,12 +429,12 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
if (val.canConvert<QOCIRowIdPointer>() && !isOutValue(pos)) { if (val.canConvert<QOCIRowIdPointer>() && !isOutValue(pos)) {
// use a const pointer to prevent a detach // use a const pointer to prevent a detach
const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val);
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
// it's an IN value, so const_cast is ok // it's an IN value, so const_cast is ok
const_cast<OCIRowid **>(&rptr->id), const_cast<OCIRowid **>(&rptr->id),
-1, -1,
SQLT_RDD, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_RDD, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
} else { } else {
qCWarning(lcOci, "Unknown bind variable"); qCWarning(lcOci, "Unknown bind variable");
r = OCI_ERROR; r = OCI_ERROR;
@ -446,17 +446,17 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
if (isOutValue(pos)) { if (isOutValue(pos)) {
ba.reserve((s.capacity() + 1) * sizeof(QChar)); ba.reserve((s.capacity() + 1) * sizeof(QChar));
*tmpSize = ba.size(); *tmpSize = ba.size();
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
ba.data(), ba.data(),
ba.capacity(), ba.capacity(),
SQLT_STR, indPtr, tmpSize, 0, 0, 0, OCI_DEFAULT); SQLT_STR, indPtr, tmpSize, 0, 0, 0, OCI_DEFAULT);
} else { } else {
r = OCIBindByPos(sql, hbnd, err, r = OCIBindByPos2(sql, hbnd, err,
pos + 1, pos + 1,
ba.data(), ba.data(),
ba.size(), ba.size(),
SQLT_STR, indPtr, 0, 0, 0, 0, OCI_DEFAULT); SQLT_STR, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
} }
if (r == OCI_SUCCESS) if (r == OCI_SUCCESS)
setCharset(*hbnd, OCI_HTYPE_BIND); setCharset(*hbnd, OCI_HTYPE_BIND);
@ -1492,7 +1492,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVariantList &boundValues, bool a
QOCIBatchColumn &bindColumn = columns[i]; QOCIBatchColumn &bindColumn = columns[i];
#ifdef QOCI_DEBUG #ifdef QOCI_DEBUG
qCDebug(lcOci, "OCIBindByPos(%p, %p, %p, %d, %p, %d, %d, %p, %p, 0, %d, %p, OCI_DEFAULT)", qCDebug(lcOci, "OCIBindByPos2(%p, %p, %p, %d, %p, %d, %d, %p, %p, 0, %d, %p, OCI_DEFAULT)",
d->sql, &bindColumn.bindh, d->err, i + 1, bindColumn.data, d->sql, &bindColumn.bindh, d->err, i + 1, bindColumn.data,
bindColumn.maxLen, bindColumn.bindAs, bindColumn.indicators, bindColumn.lengths, bindColumn.maxLen, bindColumn.bindAs, bindColumn.indicators, bindColumn.lengths,
arrayBind ? bindColumn.maxarr_len : 0, arrayBind ? &bindColumn.curelep : 0); arrayBind ? bindColumn.maxarr_len : 0, arrayBind ? &bindColumn.curelep : 0);