SQL/PSQL: Avoid copies of data in QByteArray when binding such a value
Fixes: QTBUG-132303 Change-Id: I84e822078d684850c5c0384338cfa4c01fe5007f Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de> (cherry picked from commit f346a6065d36cda4ceacce03962ba58a7cf91019) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
33d74f3f58
commit
79f96014d1
@ -818,25 +818,25 @@ void QPSQLResult::virtual_hook(int id, void *data)
|
||||
QSqlResult::virtual_hook(id, data);
|
||||
}
|
||||
|
||||
static QList<QByteArray> qCreateParamArray(const QList<QVariant> &boundValues, const QPSQLDriver *driver)
|
||||
static auto qCreateParam(QSqlField &f, const QVariant &boundValue, const QPSQLDriver *driver)
|
||||
{
|
||||
if (boundValues.isEmpty())
|
||||
return {};
|
||||
|
||||
QList<QByteArray> params;
|
||||
params.reserve(boundValues.size());
|
||||
QSqlField f;
|
||||
for (const QVariant &val : boundValues) {
|
||||
QByteArray bval;
|
||||
if (!QSqlResultPrivate::isVariantNull(val)) {
|
||||
f.setMetaType(val.metaType());
|
||||
f.setValue(val);
|
||||
if (QString strval = driver->formatValue<true>(f); !strval.isNull())
|
||||
bval = strval.toUtf8();
|
||||
std::pair<QByteArray, bool /*binary*/> param;
|
||||
if (!QSqlResultPrivate::isVariantNull(boundValue)) {
|
||||
// in this switch we define faster ways to convert string, ideally we could use binary formats for more types
|
||||
switch (boundValue.metaType().id()) {
|
||||
case QMetaType::QByteArray:
|
||||
param = {boundValue.toByteArray(), true};
|
||||
break;
|
||||
default: {
|
||||
f.setMetaType(boundValue.metaType());
|
||||
f.setValue(boundValue);
|
||||
const QString strval = driver->formatValue<true>(f);
|
||||
param = {strval.isNull() ? QByteArray{} : strval.toUtf8(), false};
|
||||
break;
|
||||
}
|
||||
params.append(bval);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
QString qMakePreparedStmtId()
|
||||
@ -881,14 +881,25 @@ bool QPSQLResult::exec()
|
||||
|
||||
cleanup();
|
||||
|
||||
const QList<QByteArray> params = qCreateParamArray(boundValues(), static_cast<const QPSQLDriver *>(driver()));
|
||||
QVarLengthArray<const char *> pgParams;
|
||||
pgParams.reserve(params.size());
|
||||
for (const QByteArray ¶m : params)
|
||||
QVarLengthArray<int> pgParamLengths;
|
||||
QVarLengthArray<int> pgParamFormats;
|
||||
QVarLengthArray<QByteArray> _refsToKeep;
|
||||
|
||||
if (const QVariantList values = boundValues(); !values.isEmpty()) {
|
||||
QSqlField f;
|
||||
for (const QVariant &value : values) {
|
||||
auto [param, binary] = qCreateParam(f, value, static_cast<const QPSQLDriver *>(driver()));
|
||||
pgParams.emplace_back(param.constBegin());
|
||||
pgParamLengths.emplace_back(param.size());
|
||||
pgParamFormats.emplace_back(binary);
|
||||
if (!param.isNull())
|
||||
_refsToKeep.emplace_back(std::move(param));
|
||||
}
|
||||
}
|
||||
|
||||
d->result = PQexecPrepared(d->drv_d_func()->connection, d->preparedStmtId.toUtf8(), pgParams.size(),
|
||||
pgParams.data(), nullptr, nullptr, 0);
|
||||
pgParams.data(), pgParamLengths.data(), pgParamFormats.data(), 0);
|
||||
|
||||
const auto status = PQresultStatus(d->result);
|
||||
if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user