14#include <QtSql/private/qsqlcachedresult_p.h>
15#include <QtSql/private/qsqldriver_p.h>
18#if QT_CONFIG(regularexpression)
22#include <QScopedValueRollback>
51 res.replace(u
'"',
"\"\""_L1);
53 res.replace(u
'.',
"\".\""_L1);
64 return QMetaType::Int;
68 ||
typeName.startsWith(
"numeric"_L1))
69 return QMetaType::Double;
71 return QMetaType::QByteArray;
73 return QMetaType::Bool;
74 return QMetaType::QString;
102 bool exec() override;
129 using QSqlCachedResultPrivate::QSqlCachedResultPrivate;
133 void initColumns(
bool emptyResultset);
139 bool skippedStatus =
false;
140 bool skipRow =
false;
148 skippedStatus =
false;
160 sqlite3_finalize(stmt);
167 int nCols = sqlite3_column_count(stmt);
173 for (
int i = 0;
i < nCols; ++
i) {
175 sqlite3_column_name16(stmt,
i))
178 sqlite3_column_table_name16(stmt,
i))
182 sqlite3_column_decltype16(stmt,
i)));
184 int stp = emptyResultset ? -1 : sqlite3_column_type(stmt,
i);
194 fieldType = QMetaType::Int;
197 fieldType = QMetaType::Double;
200 fieldType = QMetaType::QByteArray;
203 fieldType = QMetaType::QString;
226 for(
int i=0;
i<firstRow.size();
i++)
228 return skippedStatus;
230 skipRow = initialFetch;
234 firstRow.resize(sqlite3_column_count(stmt));
243 int res = sqlite3_step(stmt);
250 if (idx < 0 && !initialFetch)
252 for (
int i = 0;
i < rInf.count(); ++
i) {
253 switch (sqlite3_column_type(stmt,
i)) {
256 sqlite3_column_blob(stmt,
i)),
257 sqlite3_column_bytes(stmt,
i));
260 values[
i + idx] = sqlite3_column_int64(stmt,
i);
263 switch(
q->numericalPrecisionPolicy()) {
265 values[
i + idx] = sqlite3_column_int(stmt,
i);
268 values[
i + idx] = sqlite3_column_int64(stmt,
i);
273 values[
i + idx] = sqlite3_column_double(stmt,
i);
282 sqlite3_column_text16(stmt,
i)),
283 sqlite3_column_bytes16(stmt,
i) /
sizeof(
QChar));
295 case SQLITE_CONSTRAINT:
299 res = sqlite3_reset(stmt);
354 const void *pzTail =
nullptr;
357#if (SQLITE_VERSION_NUMBER >= 3003011)
358 int res = sqlite3_prepare16_v2(
d->drv_d_func()->access,
query.constData(),
size,
361 int res = sqlite3_prepare16(
d->access,
query.constData(),
size,
365 if (
res != SQLITE_OK) {
370 }
else if (pzTail && !
QString(
reinterpret_cast<const QChar *
>(pzTail)).trimmed().isEmpty()) {
391 auto it =
d->indexes.constBegin();
392 while (
it !=
d->indexes.constEnd()) {
407 d->skippedStatus =
false;
413 int res = sqlite3_reset(
d->stmt);
414 if (
res != SQLITE_OK) {
421 int paramCount = sqlite3_bind_parameter_count(
d->stmt);
422 bool paramCountIsValid = paramCount ==
values.size();
424#if (SQLITE_VERSION_NUMBER >= 3003011)
429 if (paramCount >= 1 && paramCount <
values.size()) {
431 return counter + indexList.size();
434 const int bindParamCount = std::accumulate(
d->indexes.cbegin(),
439 paramCountIsValid = bindParamCount ==
values.size();
445 for (
int i = 0, currentIndex = 0;
i <
values.size(); ++
i) {
448 const char *parameterName = sqlite3_bind_parameter_name(
d->stmt, currentIndex + 1);
449 if (!parameterName) {
450 paramCountIsValid =
false;
454 const auto &indexes =
d->indexes.value(placeHolder);
455 handledIndexes << indexes;
456 prunedValues <<
values.
at(indexes.first());
463 if (paramCountIsValid) {
464 for (
int i = 0;
i < paramCount; ++
i) {
469 res = sqlite3_bind_null(
d->stmt,
i + 1);
471 switch (
value.userType()) {
472 case QMetaType::QByteArray: {
475 ba->
size(), SQLITE_STATIC);
478 case QMetaType::Bool:
479 res = sqlite3_bind_int(
d->stmt,
i + 1,
value.toInt());
481 case QMetaType::Double:
482 res = sqlite3_bind_double(
d->stmt,
i + 1,
value.toDouble());
484 case QMetaType::UInt:
485 case QMetaType::LongLong:
486 res = sqlite3_bind_int64(
d->stmt,
i + 1,
value.toLongLong());
488 case QMetaType::QDateTime: {
496 case QMetaType::QTime: {
504 case QMetaType::QString: {
520 if (
res != SQLITE_OK) {
532 d->skippedStatus =
d->fetchNext(
d->firstRow, 0,
true);
546 return d->fetchNext(
row, idx,
false);
557 return sqlite3_changes(
d->drv_d_func()->access);
564 qint64 id = sqlite3_last_insert_rowid(
d->drv_d_func()->access);
583 sqlite3_reset(
d->stmt);
594#if QT_CONFIG(regularexpression)
595static void _q_regexp(sqlite3_context*
context,
int argc, sqlite3_value** argv)
598 sqlite3_result_int(
context, 0);
603 reinterpret_cast<const char*
>(sqlite3_value_text(argv[0])));
605 reinterpret_cast<const char*
>(sqlite3_value_text(argv[1])));
609 const bool wasCached = regexp;
614 const bool found = subject.
contains(*regexp);
619 sqlite3_result_int(
context,
int(found));
622static void _q_regexp_cleanup(
void *
cache)
631 sqlite3_result_text(
context,
nullptr, 0,
nullptr);
635 reinterpret_cast<const char*
>(sqlite3_value_text(argv[0]))).
toLower();
643 sqlite3_result_text(
context,
nullptr, 0,
nullptr);
647 reinterpret_cast<const char*
>(sqlite3_value_text(argv[0]))).
toUpper();
692#if (SQLITE_VERSION_NUMBER < 3003011)
714 bool sharedCache =
false;
715 bool openReadOnlyOption =
false;
716 bool openUriOption =
false;
717 bool useExtendedResultCodes =
true;
718 bool useQtVfs =
false;
719 bool useQtCaseFolding =
false;
720#if QT_CONFIG(regularexpression)
721 static const auto regexpConnectOption =
"QSQLITE_ENABLE_REGEXP"_L1;
722 bool defineRegexp =
false;
723 int regexpCacheSize = 25;
727 for (
auto option : opts) {
729 if (
option.startsWith(
"QSQLITE_BUSY_TIMEOUT"_L1)) {
731 if (
option.startsWith(u
'=')) {
733 const int nt =
option.mid(1).trimmed().toInt(&
ok);
737 }
else if (
option ==
"QSQLITE_USE_QT_VFS"_L1) {
739 }
else if (
option ==
"QSQLITE_OPEN_READONLY"_L1) {
740 openReadOnlyOption =
true;
741 }
else if (
option ==
"QSQLITE_OPEN_URI"_L1) {
742 openUriOption =
true;
743 }
else if (
option ==
"QSQLITE_ENABLE_SHARED_CACHE"_L1) {
745 }
else if (
option ==
"QSQLITE_NO_USE_EXTENDED_RESULT_CODES"_L1) {
746 useExtendedResultCodes =
false;
747 }
else if (
option ==
"QSQLITE_ENABLE_NON_ASCII_CASE_FOLDING"_L1) {
748 useQtCaseFolding =
true;
750#if QT_CONFIG(regularexpression)
751 else if (
option.startsWith(regexpConnectOption)) {
752 option =
option.mid(regexpConnectOption.size()).trimmed();
755 }
else if (
option.startsWith(u
'=')) {
768 int openMode = (openReadOnlyOption ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
769 openMode |= (sharedCache ? SQLITE_OPEN_SHAREDCACHE : SQLITE_OPEN_PRIVATECACHE);
771 openMode |= SQLITE_OPEN_URI;
773 openMode |= SQLITE_OPEN_NOMUTEX;
775 const int res = sqlite3_open_v2(
db.toUtf8().constData(), &
d->access, openMode, useQtVfs ?
"QtVFS" :
nullptr);
777 if (
res == SQLITE_OK) {
778 sqlite3_busy_timeout(
d->access, timeOut);
779 sqlite3_extended_result_codes(
d->access, useExtendedResultCodes);
782#if QT_CONFIG(regularexpression)
785 sqlite3_create_function_v2(
d->access,
"regexp", 2, SQLITE_UTF8,
cache,
787 nullptr, &_q_regexp_cleanup);
790 if (useQtCaseFolding) {
791 sqlite3_create_function_v2(
d->access,
"lower", 1, SQLITE_UTF8,
nullptr,
792 &
_q_lower,
nullptr,
nullptr,
nullptr);
793 sqlite3_create_function_v2(
d->access,
"upper", 1, SQLITE_UTF8,
nullptr,
794 &
_q_upper,
nullptr,
nullptr,
nullptr);
803 sqlite3_close(
d->access);
816 result->d_func()->finalize();
818 if (
d->access && (
d->notificationid.size() > 0)) {
819 d->notificationid.clear();
820 sqlite3_update_hook(
d->access,
nullptr,
nullptr);
823 const int res = sqlite3_close(
d->access);
825 if (
res != SQLITE_OK)
844 if (!
q.exec(
"BEGIN"_L1)) {
859 if (!
q.exec(
"COMMIT"_L1)) {
874 if (!
q.exec(
"ROLLBACK"_L1)) {
890 q.setForwardOnly(
true);
892 QString sql =
"SELECT name FROM sqlite_master WHERE %1 "
893 "UNION ALL SELECT name FROM sqlite_temp_master WHERE %1"_L1;
895 sql = sql.
arg(
"type='table' OR type='view'"_L1);
897 sql = sql.
arg(
"type='table'"_L1);
899 sql = sql.
arg(
"type='view'"_L1);
903 if (!sql.
isEmpty() &&
q.exec(sql)) {
905 res.append(
q.value(0).toString());
910 res.append(
"sqlite_master"_L1);
921 if (indexOfSeparator > -1) {
923 if (indexOfCloseBracket != tableName.
size() - 1) {
925 schema = tableName.
left(indexOfSeparator + 1);
926 table = tableName.
mid(indexOfSeparator + 1);
929 if (indexOfOpenBracket > 0) {
931 schema = tableName.
left(indexOfOpenBracket);
932 table = tableName.
mid(indexOfOpenBracket);
936 q.exec(
"PRAGMA "_L1 + schema +
"table_info ("_L1 +
941 if (onlyPIndex && !isPk)
944 QString defVal =
q.value(4).toString();
945 if (!defVal.
isEmpty() && defVal.
at(0) == u
'\'') {
948 defVal = defVal.
mid(1,
end - 1);
952 if (isPk && (
typeName ==
"integer"_L1))
973 q.setForwardOnly(
true);
987 q.setForwardOnly(
true);
1003 sqlite3_int64 arowid)
1022 if (
d->notificationid.contains(
name)) {
1028 d->notificationid <<
name;
1029 if (
d->notificationid.size() == 1)
1043 if (!
d->notificationid.contains(
name)) {
1048 d->notificationid.removeAll(
name);
1049 if (
d->notificationid.isEmpty())
1050 sqlite3_update_hook(
d->access,
nullptr,
nullptr);
1058 return d->notificationid;
1061void QSQLiteDriver::handleNotification(
const QString &tableName,
qint64 rowid)
1064 if (
d->notificationid.contains(tableName))
1070#include "moc_qsql_sqlite_p.cpp"
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
\inmodule QtCore\reentrant
bool removeOne(const AT &t)
const_reference at(qsizetype i) const noexcept
void append(parameter_type t)
\inmodule QtCore \reentrant
QList< QSQLiteResult * > results
QStringList notificationid
QSqlIndex primaryIndex(const QString &table) const override
Returns the primary index for table tableName.
QSQLiteDriver(QObject *parent=nullptr)
QStringList subscribedToNotifications() const override
Returns a list of the names of the event notifications that are currently subscribed to.
QStringList tables(QSql::TableType) const override
Returns a list of the names of the tables in the database.
void close() override
Derived classes must reimplement this pure virtual function in order to close the database connection...
bool commitTransaction() override
This function is called to commit a transaction.
bool beginTransaction() override
This function is called to begin a transaction.
QString escapeIdentifier(const QString &identifier, IdentifierType) const override
Returns the identifier escaped according to the database rules.
QVariant handle() const override
Returns the low-level database handle wrapped in a QVariant or an invalid variant if there is no hand...
QSqlResult * createResult() const override
Creates an empty SQL result on the database.
bool unsubscribeFromNotification(const QString &name) override
This function is called to unsubscribe from event notifications from the database.
bool subscribeToNotification(const QString &name) override
This function is called to subscribe to event notifications from the database.
bool rollbackTransaction() override
This function is called to rollback a transaction.
bool open(const QString &db, const QString &user, const QString &password, const QString &host, int port, const QString &connOpts) override
Derived classes must reimplement this pure virtual function to open a database connection on database...
bool hasFeature(DriverFeature f) const override
Returns true if the driver supports feature feature; otherwise returns false.
QSqlRecord record(const QString &tablename) const override
Returns a QSqlRecord populated with the names of the fields in table tableName.
QList< QVariant > firstRow
bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch)
void initColumns(bool emptyResultset)
int size() override
Returns the size of the SELECT result, or -1 if it cannot be determined or if the query is not a SELE...
bool execBatch(bool arrayBind) override
bool reset(const QString &query) override
Sets the result to use the SQL statement query for subsequent data retrieval.
QSqlRecord record() const override
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
void virtual_hook(int id, void *data) override
QSQLiteResult(const QSQLiteDriver *db)
bool exec() override
Executes the query, returning true if successful; otherwise returns false.
bool prepare(const QString &query) override
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
QVariant lastInsertId() const override
Returns the object ID of the most recent inserted row if the database supports it.
QVariant handle() const override
Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVarian...
bool gotoNext(QSqlCachedResult::ValueCache &row, int idx) override
void detachFromResultSet() override
int numRowsAffected() override
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
void virtual_hook(int id, void *data) override
The QSqlDriver class is an abstract base class for accessing specific SQL databases.
IdentifierType
This enum contains a list of SQL identifier types.
virtual QString stripDelimiters(const QString &identifier, IdentifierType type) const
Returns the identifier with the leading and trailing delimiters removed, identifier can either be a t...
DriverFeature
This enum contains a list of features a driver might support.
bool isOpenError() const
Returns true if the there was an error opening the database connection; otherwise returns false.
virtual void setLastError(const QSqlError &e)
This function is used to set the value of the last error, error, that occurred on the database.
void notification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload)
virtual bool isOpen() const
Returns true if the database connection is open; otherwise returns false.
virtual void setOpenError(bool e)
This function sets the open error state of the database to error.
virtual bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const
Returns whether identifier is escaped according to the database rules.
virtual void setOpen(bool o)
This function sets the open state of the database to open.
The QSqlError class provides SQL database error information.
ErrorType
This enum type describes the context in which the error occurred, e.g., a connection error,...
The QSqlField class manipulates the fields in SQL database tables and views.
void setAutoValue(bool autoVal)
Marks the field as an auto-generated value if autoVal is true.
void setDefaultValue(const QVariant &value)
Sets the default value used for this field to value.
void setRequired(bool required)
Sets the required status of this field to \l Required if required is true; otherwise sets it to \l Op...
void setSqlType(int type)
The QSqlIndex class provides functions to manipulate and describe database indexes.
void append(const QSqlField &field)
Appends the field field to the list of indexed fields.
The QSqlQuery class provides a means of executing and manipulating SQL statements.
The QSqlRecord class encapsulates a database record.
QVariant value(int i) const
Returns the value of the field located at position index in the record.
static bool isVariantNull(const QVariant &variant)
The QSqlResult class provides an abstract interface for accessing data from specific SQL databases.
bool isSelect() const
Returns true if the current result is from a SELECT statement; otherwise returns false.
virtual void setSelect(bool s)
This function is provided for derived classes to indicate whether or not the current statement is a S...
virtual void setActive(bool a)
This function is provided for derived classes to set the internal active state to active.
QVariantList & boundValues(QT6_DECL_NEW_OVERLOAD)
QSqlError lastError() const
Returns the last error associated with the result.
virtual void setLastError(const QSqlError &e)
This function is provided for derived classes to set the last error to error.
const QSqlDriver * driver() const
Returns the driver associated with the result.
bool isValid() const
Returns true if the result is positioned on a valid record (that is, the result is not positioned bef...
virtual void bindValue(int pos, const QVariant &val, QSql::ParamType type)
Binds the value val of parameter type paramType to position index in the current record (row).
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
void clear()
Clears the contents of the string and makes it null.
qsizetype size() const
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString toLower() const &
QChar * data()
Returns a pointer to the data stored in the QString.
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
QByteArray toUtf8() const &
QString toUpper() const &
const QChar * unicode() const
Returns a Unicode representation of the string.
\inmodule QtCore \reentrant
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
DBusConnection * connection
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_ARG(Type, data)
GLenum GLsizei GLsizei GLint * values
[15]
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void * table
static quint64 cacheSize()
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QDB2DriverPrivate *p)
static QList< QVariant > toList(char **buf, int count)
static void _q_lower(sqlite3_context *context, int argc, sqlite3_value **argv)
static void _q_upper(sqlite3_context *context, int argc, sqlite3_value **argv)
static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool onlyPIndex=false)
static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::ErrorType type, int errorCode)
static int qGetColumnType(const QString &tpName)
static void handle_sqlite_callback(void *qobj, int aoperation, char const *adbname, char const *atablename, sqlite3_int64 arowid)
static QString _q_escapeIdentifier(const QString &identifier, QSqlDriver::IdentifierType type)
#define Q_DECLARE_SQLDRIVER_PRIVATE(Class)
#define qUtf16Printable(string)
bool contains(const AT &t) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent