39QString QSqlResultPrivate::positionalToNamedBinding(
const QString &query)
const
41 if (!positionalBindingEnabled)
44 const qsizetype n = query.size();
47 result.reserve(n * 5 / 4);
50 bool ignoreBraces = (sqldriver->dbmsType() == QSqlDriver::PostgreSQL);
52 for (qsizetype i = 0; i < n; ++i) {
53 QChar ch = query.at(i);
54 if (!closingQuote.isNull()) {
55 if (ch == closingQuote) {
56 if (closingQuote == u']'
57 && i + 1 < n && query.at(i + 1) == closingQuote) {
62 closingQuote = QChar();
68 result += fieldSerial(count++);
70 if (ch == u'\'' || ch == u'"' || ch == u'`')
72 else if (!ignoreBraces && ch == u'[')
82QString QSqlResultPrivate::namedToPositionalBinding(
const QString &query)
87 if (sqldriver->dbmsType() == QSqlDriver::Interbase &&
88 query.trimmed().startsWith(
"EXECUTE BLOCK"_L1, Qt::CaseInsensitive))
91 const qsizetype n = query.size();
98 bool ignoreBraces = (sqldriver->dbmsType() == QSqlDriver::PostgreSQL);
99 const bool qmarkNotationSupported = (sqldriver->dbmsType() != QSqlDriver::PostgreSQL);
102 QChar ch = query.at(i);
103 if (!closingQuote.isNull()) {
104 if (ch == closingQuote) {
105 if (closingQuote == u']'
106 && i + 1 < n && query.at(i + 1) == closingQuote) {
111 closingQuote = QChar();
118 && (i == 0 || query.at(i - 1) != u':')
119 && (i + 1 < n && qIsAlnum(query.at(i + 1)))) {
121 while (pos < n && qIsAlnum(query.at(pos)))
126 if (qmarkNotationSupported)
129 result += fieldSerial(count);
130 QString holder(query.mid(i, pos - i));
131 indexes[holder].append(count++);
132 holders.append(QHolder(holder, i));
135 if (ch == u'\'' || ch == u'"' || ch == u'`')
137 else if (!ignoreBraces && ch == u'[')
145 values.resize(holders.size());
561bool QSqlResult::savePrepare(
const QString& query)
568 if (!driver()->hasFeature(QSqlDriver::PreparedQueries))
569 return prepare(query);
572 d->executedQuery = d->namedToPositionalBinding(query);
574 if (driver()->hasFeature(QSqlDriver::NamedPlaceholders))
575 d->executedQuery = d->positionalToNamedBinding(query);
577 return prepare(d->executedQuery);
598bool QSqlResultPrivate::isVariantNull(
const QVariant &variant)
600 if (variant.isNull())
603 switch (variant.typeId()) {
604 case qMetaTypeId<QString>():
605 return static_cast<
const QString*>(variant.constData())->isNull();
606 case qMetaTypeId<QByteArray>():
607 return static_cast<
const QByteArray*>(variant.constData())->isNull();
608 case qMetaTypeId<QDateTime>():
610 return !
static_cast<
const QDateTime*>(variant.constData())->isValid();
611 case qMetaTypeId<QDate>():
612 return static_cast<
const QDate*>(variant.constData())->isNull();
613 case qMetaTypeId<QTime>():
615 return !
static_cast<
const QTime*>(variant.constData())->isValid();
616 case qMetaTypeId<QUuid>():
617 return static_cast<
const QUuid*>(variant.constData())->isNull();
631bool QSqlResult::exec()
636 QString query = lastQuery();
637 if (d->binds == NamedBinding) {
638 for (qsizetype i = d->holders.size() - 1; i >= 0; --i) {
639 const QString &holder = d->holders.at(i).holderName;
640 const QVariant val = d->values.value(d->indexes.value(holder).value(0,-1));
641 QSqlField f(
""_L1, val.metaType());
642 if (QSqlResultPrivate::isVariantNull(val))
643 f.setValue(QVariant());
646 query = query.replace(d->holders.at(i).holderPos,
647 holder.size(), driver()->formatValue(f));
651 for (
const QVariant &var : std::as_const(d->values)) {
652 i = query.indexOf(u'?', i);
655 QSqlField f(
""_L1, var.metaType());
656 if (QSqlResultPrivate::isVariantNull(var))
660 const QString val = driver()->formatValue(f);
661 query = query.replace(i, 1, val);
667 QString orig = lastQuery();
669 d->executedQuery = query;
681void QSqlResult::bindValue(
int index,
const QVariant& val, QSql::ParamType paramType)
684 d->binds = PositionalBinding;
685 QList<
int> &indexes = d->indexes[d->fieldSerial(index)];
686 if (!indexes.contains(index))
687 indexes.append(index);
688 if (d->values.size() <= index)
689 d->values.resize(index + 1);
690 d->values[index] = val;
691 if (paramType != QSql::In || !d->types.isEmpty())
692 d->types[index] = paramType;
705void QSqlResult::bindValue(
const QString& placeholder,
const QVariant& val,
706 QSql::ParamType paramType)
709 d->binds = NamedBinding;
712 const QList<
int> indexes = d->indexes.value(placeholder);
713 for (
int idx : indexes) {
714 if (d->values.size() <= idx)
715 d->values.resize(idx + 1);
716 d->values[idx] = val;
717 if (paramType != QSql::In || !d->types.isEmpty())
718 d->types[idx] = paramType;
728void QSqlResult::addBindValue(
const QVariant& val, QSql::ParamType paramType)
731 d->binds = PositionalBinding;
732 bindValue(d->bindCount, val, paramType);
975bool QSqlResult::execBatch(
bool arrayBind)
980 const QList<QVariant> values = d->values;
981 if (values.size() == 0)
983 const qsizetype batchCount = values.at(0).toList().size();
984 const qsizetype valueCount = values.size();
985 for (qsizetype i = 0; i < batchCount; ++i) {
986 for (qsizetype j = 0; j < valueCount; ++j)
987 bindValue(j, values.at(j).toList().at(i), QSql::In);