summaryrefslogtreecommitdiffstats
path: root/src/plugins/sqldrivers/psql/qsql_psql.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/sqldrivers/psql/qsql_psql.cpp')
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp308
1 files changed, 140 insertions, 168 deletions
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index e928f02ff4..7b9521fec6 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtSql module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsql_psql_p.h"
#include <qcoreapplication.h>
#include <qvariant.h>
#include <qdatetime.h>
+#include <qloggingcategory.h>
#include <qregularexpression.h>
#include <qsqlerror.h>
#include <qsqlfield.h>
@@ -101,6 +66,10 @@ Q_DECLARE_METATYPE(PGresult*)
QT_BEGIN_NAMESPACE
+static Q_LOGGING_CATEGORY(lcPsql, "qt.sql.postgresql")
+
+using namespace Qt::StringLiterals;
+
inline void qPQfreemem(void *buffer)
{
PQfreemem(buffer);
@@ -108,11 +77,11 @@ inline void qPQfreemem(void *buffer)
/* Missing declaration of PGRES_SINGLE_TUPLE for PSQL below 9.2 */
#if !defined PG_VERSION_NUM || PG_VERSION_NUM-0 < 90200
-static const int PGRES_SINGLE_TUPLE = 9;
+static constexpr int PGRES_SINGLE_TUPLE = 9;
#endif
typedef int StatementId;
-static const StatementId InvalidStatementId = 0;
+static constexpr StatementId InvalidStatementId = 0;
class QPSQLResultPrivate;
@@ -156,10 +125,9 @@ public:
QSocketNotifier *sn = nullptr;
QPSQLDriver::Protocol pro = QPSQLDriver::Version6;
StatementId currentStmtId = InvalidStatementId;
- int stmtCount = 0;
+ StatementId stmtCount = InvalidStatementId;
mutable bool pendingNotifyCheck = false;
bool hasBackslashEscape = false;
- bool isUtf8 = false;
void appendTables(QStringList &tl, QSqlQuery &t, QChar type);
PGresult *exec(const char *stmt);
@@ -175,6 +143,7 @@ public:
bool setEncodingUtf8();
void setDatestyle();
void setByteaOutput();
+ void setUtcTimeZone();
void detectBackslashEscape();
mutable QHash<int, QString> oidToTable;
};
@@ -191,10 +160,10 @@ void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
t.exec(query);
while (t.next()) {
QString schema = t.value(1).toString();
- if (schema.isEmpty() || schema == QLatin1String("public"))
+ if (schema.isEmpty() || schema == "public"_L1)
tl.append(t.value(0).toString());
else
- tl.append(t.value(0).toString().prepend(QLatin1Char('.')).prepend(schema));
+ tl.append(t.value(0).toString().prepend(u'.').prepend(schema));
}
}
@@ -209,7 +178,7 @@ PGresult *QPSQLDriverPrivate::exec(const char *stmt)
PGresult *QPSQLDriverPrivate::exec(const QString &stmt)
{
- return exec((isUtf8 ? stmt.toUtf8() : stmt.toLocal8Bit()).constData());
+ return exec(stmt.toUtf8().constData());
}
StatementId QPSQLDriverPrivate::sendQuery(const QString &stmt)
@@ -217,8 +186,7 @@ StatementId QPSQLDriverPrivate::sendQuery(const QString &stmt)
// Discard any prior query results that the application didn't eat.
// This is required for PQsendQuery()
discardResults();
- const int result = PQsendQuery(connection,
- (isUtf8 ? stmt.toUtf8() : stmt.toLocal8Bit()).constData());
+ const int result = PQsendQuery(connection, stmt.toUtf8().constData());
currentStmtId = result ? generateStatementId() : InvalidStatementId;
return currentStmtId;
}
@@ -243,8 +211,8 @@ PGresult *QPSQLDriverPrivate::getResult(StatementId stmtId) const
if (stmtId != currentStmtId) {
// If you change the following warning, remember to update it
// on sql-driver.html page too.
- qWarning("QPSQLDriver::getResult: Query results lost - "
- "probably discarded on executing another SQL query.");
+ qCWarning(lcPsql, "QPSQLDriver::getResult: Query results lost - "
+ "probably discarded on executing another SQL query.");
return nullptr;
}
PGresult *result = PQgetResult(connection);
@@ -268,7 +236,7 @@ void QPSQLDriverPrivate::discardResults() const
StatementId QPSQLDriverPrivate::generateStatementId()
{
- int stmtId = ++stmtCount;
+ StatementId stmtId = ++stmtCount;
if (stmtId <= 0)
stmtId = stmtCount = 1;
return stmtId;
@@ -279,18 +247,18 @@ void QPSQLDriverPrivate::checkPendingNotifications() const
Q_Q(const QPSQLDriver);
if (seid.size() && !pendingNotifyCheck) {
pendingNotifyCheck = true;
- QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), &QPSQLDriver::_q_handleNotification, Qt::QueuedConnection);
}
}
-class QPSQLResultPrivate : public QSqlResultPrivate
+class QPSQLResultPrivate final : public QSqlResultPrivate
{
Q_DECLARE_PUBLIC(QPSQLResult)
public:
Q_DECLARE_SQLDRIVER_PRIVATE(QPSQLDriver)
using QSqlResultPrivate::QSqlResultPrivate;
- QString fieldSerial(int i) const override { return QLatin1Char('$') + QString::number(i + 1); }
+ QString fieldSerial(qsizetype i) const override { return QString("$%1"_L1).arg(i + 1); }
void deallocatePreparedStmt();
std::queue<PGresult*> nextResultSets;
@@ -308,13 +276,13 @@ static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type,
const QPSQLDriverPrivate *p, PGresult *result = nullptr)
{
const char *s = PQerrorMessage(p->connection);
- QString msg = p->isUtf8 ? QString::fromUtf8(s) : QString::fromLocal8Bit(s);
+ QString msg = QString::fromUtf8(s);
QString errorCode;
if (result) {
errorCode = QString::fromLatin1(PQresultErrorField(result, PG_DIAG_SQLSTATE));
msg += QString::fromLatin1("(%1)").arg(errorCode);
}
- return QSqlError(QLatin1String("QPSQL: ") + err, msg, type, errorCode);
+ return QSqlError("QPSQL: "_L1 + err, msg, type, errorCode);
}
bool QPSQLResultPrivate::processResults()
@@ -416,8 +384,10 @@ void QPSQLResultPrivate::deallocatePreparedStmt()
const QString stmt = QStringLiteral("DEALLOCATE ") + preparedStmtId;
PGresult *result = drv_d_func()->exec(stmt);
- if (PQresultStatus(result) != PGRES_COMMAND_OK)
- qWarning("Unable to free statement: %s", PQerrorMessage(drv_d_func()->connection));
+ if (PQresultStatus(result) != PGRES_COMMAND_OK) {
+ const QString msg = QString::fromUtf8(PQerrorMessage(drv_d_func()->connection));
+ qCWarning(lcPsql, "Unable to free statement: %ls.", qUtf16Printable(msg));
+ }
PQclear(result);
}
preparedStmtId.clear();
@@ -627,7 +597,7 @@ QVariant QPSQLResult::data(int i)
{
Q_D(const QPSQLResult);
if (i >= PQnfields(d->result)) {
- qWarning("QPSQLResult::data: column %d out of range", i);
+ qCWarning(lcPsql, "QPSQLResult::data: column %d out of range.", i);
return QVariant();
}
const int currentRow = isForwardOnly() ? 0 : at();
@@ -640,7 +610,7 @@ QVariant QPSQLResult::data(int i)
case QMetaType::Bool:
return QVariant((bool)(val[0] == 't'));
case QMetaType::QString:
- return d->drv_d_func()->isUtf8 ? QString::fromUtf8(val) : QString::fromLatin1(val);
+ return QString::fromUtf8(val);
case QMetaType::LongLong:
if (val[0] == '-')
return QByteArray::fromRawData(val, qstrlen(val)).toLongLong();
@@ -675,34 +645,32 @@ QVariant QPSQLResult::data(int i)
}
return dbl;
}
- case QMetaType::QDate:
#if QT_CONFIG(datestring)
+ case QMetaType::QDate:
return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate));
-#else
- return QVariant(QString::fromLatin1(val));
-#endif
case QMetaType::QTime:
-#if QT_CONFIG(datestring)
return QVariant(QTime::fromString(QString::fromLatin1(val), Qt::ISODate));
+ case QMetaType::QDateTime: {
+ QString tzString(QString::fromLatin1(val));
+ if (!tzString.endsWith(u'Z'))
+ tzString.append(u'Z'); // make UTC
+ return QVariant(QDateTime::fromString(tzString, Qt::ISODate));
+ }
#else
- return QVariant(QString::fromLatin1(val));
-#endif
+ case QMetaType::QDate:
+ case QMetaType::QTime:
case QMetaType::QDateTime:
-#if QT_CONFIG(datestring)
- return QVariant(QDateTime::fromString(QString::fromLatin1(val),
- Qt::ISODate).toLocalTime());
-#else
return QVariant(QString::fromLatin1(val));
#endif
case QMetaType::QByteArray: {
size_t len;
- unsigned char *data = PQunescapeBytea((const unsigned char*)val, &len);
- QByteArray ba(reinterpret_cast<const char *>(data), int(len));
+ unsigned char *data = PQunescapeBytea(reinterpret_cast<const unsigned char *>(val), &len);
+ QByteArray ba(reinterpret_cast<const char *>(data), len);
qPQfreemem(data);
return QVariant(ba);
}
default:
- qWarning("QPSQLResult::data: unknown data type");
+ qCWarning(lcPsql, "QPSQLResult::data: unhandled data type %d.", type.id());
}
return QVariant();
}
@@ -781,10 +749,7 @@ QSqlRecord QPSQLResult::record() const
int count = PQnfields(d->result);
QSqlField f;
for (int i = 0; i < count; ++i) {
- if (d->drv_d_func()->isUtf8)
- f.setName(QString::fromUtf8(PQfname(d->result, i)));
- else
- f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));
+ f.setName(QString::fromUtf8(PQfname(d->result, i)));
const int tableOid = PQftable(d->result, i);
// WARNING: We cannot execute any other SQL queries on
// the same db connection while forward-only mode is active
@@ -835,7 +800,6 @@ QSqlRecord QPSQLResult::record() const
f.setLength(len);
f.setPrecision(precision);
- f.setSqlType(ptype);
info.append(f);
}
return info;
@@ -856,12 +820,12 @@ static QString qCreateParamString(const QList<QVariant> &boundValues, const QSql
QSqlField f;
for (const QVariant &val : boundValues) {
f.setMetaType(val.metaType());
- if (val.isNull())
+ if (QSqlResultPrivate::isVariantNull(val))
f.clear();
else
f.setValue(val);
if (!params.isNull())
- params.append(QLatin1String(", "));
+ params.append(", "_L1);
params.append(driver->formatValue(f));
}
return params;
@@ -869,7 +833,7 @@ static QString qCreateParamString(const QList<QVariant> &boundValues, const QSql
QString qMakePreparedStmtId()
{
- static QBasicAtomicInt qPreparedStmtCount = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt qPreparedStmtCount = Q_BASIC_ATOMIC_INITIALIZER(0);
QString id = QStringLiteral("qpsqlpstmt_") + QString::number(qPreparedStmtCount.fetchAndAddRelaxed(1) + 1, 16);
return id;
}
@@ -952,7 +916,7 @@ void QPSQLDriverPrivate::setDatestyle()
PGresult *result = exec("SET DATESTYLE TO 'ISO'");
int status = PQresultStatus(result);
if (status != PGRES_COMMAND_OK)
- qWarning("%s", PQerrorMessage(connection));
+ qCWarning(lcPsql) << QString::fromUtf8(PQerrorMessage(connection));
PQclear(result);
}
@@ -965,11 +929,20 @@ void QPSQLDriverPrivate::setByteaOutput()
PGresult *result = exec("SET bytea_output TO escape");
int status = PQresultStatus(result);
if (status != PGRES_COMMAND_OK)
- qWarning("%s", PQerrorMessage(connection));
+ qCWarning(lcPsql) << QString::fromUtf8(PQerrorMessage(connection));
PQclear(result);
}
}
+void QPSQLDriverPrivate::setUtcTimeZone()
+{
+ PGresult *result = exec("SET TIME ZONE 'UTC'");
+ int status = PQresultStatus(result);
+ if (status != PGRES_COMMAND_OK)
+ qCWarning(lcPsql) << QString::fromUtf8(PQerrorMessage(connection));
+ PQclear(result);
+}
+
void QPSQLDriverPrivate::detectBackslashEscape()
{
// standard_conforming_strings option introduced in 8.2
@@ -981,7 +954,7 @@ void QPSQLDriverPrivate::detectBackslashEscape()
PGresult *result = exec(QStringLiteral("SELECT '\\\\' x"));
int status = PQresultStatus(result);
if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK)
- if (QString::fromLatin1(PQgetvalue(result, 0, 0)) == QLatin1String("\\"))
+ if (QString::fromLatin1(PQgetvalue(result, 0, 0)) == "\\"_L1)
hasBackslashEscape = true;
PQclear(result);
}
@@ -1093,9 +1066,9 @@ QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion()
QPSQLDriver::Protocol clientVersion =
#if defined(PG_MAJORVERSION)
- qFindPSQLVersion(QLatin1String(PG_MAJORVERSION));
+ qFindPSQLVersion(PG_MAJORVERSION ""_L1);
#elif defined(PG_VERSION)
- qFindPSQLVersion(QLatin1String(PG_VERSION));
+ qFindPSQLVersion(PG_VERSION ""_L1);
#else
QPSQLDriver::VersionUnknown;
#endif
@@ -1103,16 +1076,16 @@ QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion()
if (serverVersion == QPSQLDriver::VersionUnknown) {
serverVersion = clientVersion;
if (serverVersion != QPSQLDriver::VersionUnknown)
- qWarning("The server version of this PostgreSQL is unknown, falling back to the client version.");
+ qCWarning(lcPsql, "The server version of this PostgreSQL is unknown, "
+ "falling back to the client version.");
}
// Keep the old behavior unchanged
if (serverVersion == QPSQLDriver::VersionUnknown)
serverVersion = QPSQLDriver::Version6;
- if (serverVersion < QPSQLDriver::Version7_3) {
- qWarning("This version of PostgreSQL is not supported and may not work.");
- }
+ if (serverVersion < QPSQLDriver::Version7_3)
+ qCWarning(lcPsql, "This version of PostgreSQL is not supported and may not work.");
return serverVersion;
}
@@ -1138,8 +1111,7 @@ QPSQLDriver::QPSQLDriver(PGconn *conn, QObject *parent)
QPSQLDriver::~QPSQLDriver()
{
Q_D(QPSQLDriver);
- if (d->connection)
- PQfinish(d->connection);
+ PQfinish(d->connection);
}
QVariant QPSQLDriver::handle() const
@@ -1159,6 +1131,7 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
case EventNotifications:
case MultipleResultSets:
case BLOB:
+ case Unicode:
return true;
case PreparedQueries:
case PositionalPlaceholders:
@@ -1169,8 +1142,6 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
case FinishQuery:
case CancelQuery:
return false;
- case Unicode:
- return d->isUtf8;
}
return false;
}
@@ -1183,9 +1154,9 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
*/
static QString qQuote(QString s)
{
- s.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
- s.replace(QLatin1Char('\''), QLatin1String("\\'"));
- s.append(QLatin1Char('\'')).prepend(QLatin1Char('\''));
+ s.replace(u'\\', "\\\\"_L1);
+ s.replace(u'\'', "\\'"_L1);
+ s.append(u'\'').prepend(u'\'');
return s;
}
@@ -1197,25 +1168,24 @@ bool QPSQLDriver::open(const QString &db,
const QString &connOpts)
{
Q_D(QPSQLDriver);
- if (isOpen())
- close();
+ close();
QString connectString;
if (!host.isEmpty())
- connectString.append(QLatin1String("host=")).append(qQuote(host));
+ connectString.append("host="_L1).append(qQuote(host));
if (!db.isEmpty())
- connectString.append(QLatin1String(" dbname=")).append(qQuote(db));
+ connectString.append(" dbname="_L1).append(qQuote(db));
if (!user.isEmpty())
- connectString.append(QLatin1String(" user=")).append(qQuote(user));
+ connectString.append(" user="_L1).append(qQuote(user));
if (!password.isEmpty())
- connectString.append(QLatin1String(" password=")).append(qQuote(password));
+ connectString.append(" password="_L1).append(qQuote(password));
if (port != -1)
- connectString.append(QLatin1String(" port=")).append(qQuote(QString::number(port)));
+ connectString.append(" port="_L1).append(qQuote(QString::number(port)));
// add any connect options - the server will handle error detection
if (!connOpts.isEmpty()) {
QString opt = connOpts;
- opt.replace(QLatin1Char(';'), QLatin1Char(' '), Qt::CaseInsensitive);
- connectString.append(QLatin1Char(' ')).append(opt);
+ opt.replace(';'_L1, ' '_L1, Qt::CaseInsensitive);
+ connectString.append(u' ').append(opt);
}
d->connection = PQconnectdb(std::move(connectString).toLocal8Bit().constData());
@@ -1229,9 +1199,16 @@ bool QPSQLDriver::open(const QString &db,
d->pro = d->getPSQLVersion();
d->detectBackslashEscape();
- d->isUtf8 = d->setEncodingUtf8();
+ if (!d->setEncodingUtf8()) {
+ setLastError(qMakeError(tr("Unable to set client encoding to 'UNICODE'"), QSqlError::ConnectionError, d));
+ setOpenError(true);
+ PQfinish(d->connection);
+ d->connection = nullptr;
+ return false;
+ }
d->setDatestyle();
d->setByteaOutput();
+ d->setUtcTimeZone();
setOpen(true);
setOpenError(false);
@@ -1241,21 +1218,18 @@ bool QPSQLDriver::open(const QString &db,
void QPSQLDriver::close()
{
Q_D(QPSQLDriver);
- if (isOpen()) {
-
- d->seid.clear();
- if (d->sn) {
- disconnect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification()));
- delete d->sn;
- d->sn = nullptr;
- }
- if (d->connection)
- PQfinish(d->connection);
- d->connection = nullptr;
- setOpen(false);
- setOpenError(false);
+ d->seid.clear();
+ if (d->sn) {
+ disconnect(d->sn, &QSocketNotifier::activated, this, &QPSQLDriver::_q_handleNotification);
+ delete d->sn;
+ d->sn = nullptr;
}
+
+ PQfinish(d->connection);
+ d->connection = nullptr;
+ setOpen(false);
+ setOpenError(false);
}
QSqlResult *QPSQLDriver::createResult() const
@@ -1267,7 +1241,7 @@ bool QPSQLDriver::beginTransaction()
{
Q_D(QPSQLDriver);
if (!isOpen()) {
- qWarning("QPSQLDriver::beginTransaction: Database not open");
+ qCWarning(lcPsql, "QPSQLDriver::beginTransaction: Database not open.");
return false;
}
PGresult *res = d->exec("BEGIN");
@@ -1285,7 +1259,7 @@ bool QPSQLDriver::commitTransaction()
{
Q_D(QPSQLDriver);
if (!isOpen()) {
- qWarning("QPSQLDriver::commitTransaction: Database not open");
+ qCWarning(lcPsql, "QPSQLDriver::commitTransaction: Database not open.");
return false;
}
PGresult *res = d->exec("COMMIT");
@@ -1295,7 +1269,7 @@ bool QPSQLDriver::commitTransaction()
// XXX
// This hack is used to tell if the transaction has succeeded for the protocol versions of
// PostgreSQL below. For 7.x and other protocol versions we are left in the dark.
- // This hack can dissapear once there is an API to query this sort of information.
+ // This hack can disappear once there is an API to query this sort of information.
if (d->pro >= QPSQLDriver::Version8) {
transaction_failed = qstrcmp(PQcmdStatus(res), "ROLLBACK") == 0;
}
@@ -1314,7 +1288,7 @@ bool QPSQLDriver::rollbackTransaction()
{
Q_D(QPSQLDriver);
if (!isOpen()) {
- qWarning("QPSQLDriver::rollbackTransaction: Database not open");
+ qCWarning(lcPsql, "QPSQLDriver::rollbackTransaction: Database not open.");
return false;
}
PGresult *res = d->exec("ROLLBACK");
@@ -1338,9 +1312,9 @@ QStringList QPSQLDriver::tables(QSql::TableType type) const
t.setForwardOnly(true);
if (type & QSql::Tables)
- const_cast<QPSQLDriverPrivate*>(d)->appendTables(tl, t, QLatin1Char('r'));
+ const_cast<QPSQLDriverPrivate*>(d)->appendTables(tl, t, u'r');
if (type & QSql::Views)
- const_cast<QPSQLDriverPrivate*>(d)->appendTables(tl, t, QLatin1Char('v'));
+ const_cast<QPSQLDriverPrivate*>(d)->appendTables(tl, t, u'v');
if (type & QSql::SystemTables) {
t.exec(QStringLiteral("SELECT relname FROM pg_class WHERE (relkind = 'r') "
"AND (relname LIKE 'pg_%') "));
@@ -1353,7 +1327,7 @@ QStringList QPSQLDriver::tables(QSql::TableType type) const
static void qSplitTableName(QString &tablename, QString &schema)
{
- int dot = tablename.indexOf(QLatin1Char('.'));
+ qsizetype dot = tablename.indexOf(u'.');
if (dot == -1)
return;
schema = tablename.left(dot);
@@ -1441,8 +1415,8 @@ QSqlRecord QPSQLDriver::record(const QString &tablename) const
precision = -1;
}
QString defVal = query.value(5).toString();
- if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\'')) {
- const int end = defVal.lastIndexOf(QLatin1Char('\''));
+ if (!defVal.isEmpty() && defVal.at(0) == u'\'') {
+ const qsizetype end = defVal.lastIndexOf(u'\'');
if (end > 0)
defVal = defVal.mid(1, end - 1);
}
@@ -1451,7 +1425,6 @@ QSqlRecord QPSQLDriver::record(const QString &tablename) const
f.setLength(len);
f.setPrecision(precision);
f.setDefaultValue(defVal);
- f.setSqlType(query.value(1).toInt());
info.append(f);
}
@@ -1476,36 +1449,32 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
r = nullStr();
} else {
switch (field.metaType().id()) {
- case QMetaType::QDateTime:
-#if QT_CONFIG(datestring)
- if (field.value().toDateTime().isValid()) {
+ case QMetaType::QDateTime: {
+ const auto dt = field.value().toDateTime();
+ if (dt.isValid()) {
// we force the value to be considered with a timezone information, and we force it to be UTC
// this is safe since postgresql stores only the UTC value and not the timezone offset (only used
// while parsing), so we have correct behavior in both case of with timezone and without tz
- r = QStringLiteral("TIMESTAMP WITH TIME ZONE ") + QLatin1Char('\'') +
- QLocale::c().toString(field.value().toDateTime().toUTC(), u"yyyy-MM-ddThh:mm:ss.zzz") +
- QLatin1Char('Z') + QLatin1Char('\'');
+ r = QStringLiteral("TIMESTAMP WITH TIME ZONE ") + u'\'' +
+ QLocale::c().toString(dt.toUTC(), u"yyyy-MM-ddThh:mm:ss.zzz") +
+ u'Z' + u'\'';
} else {
r = nullStr();
}
-#else
- r = nullStr();
-#endif // datestring
break;
- case QMetaType::QTime:
-#if QT_CONFIG(datestring)
- if (field.value().toTime().isValid()) {
- r = QLatin1Char('\'') + field.value().toTime().toString(u"hh:mm:ss.zzz") + QLatin1Char('\'');
- } else
-#endif
- {
+ }
+ case QMetaType::QTime: {
+ const auto t = field.value().toTime();
+ if (t.isValid())
+ r = u'\'' + QLocale::c().toString(t, u"hh:mm:ss.zzz") + u'\'';
+ else
r = nullStr();
- }
break;
+ }
case QMetaType::QString:
r = QSqlDriver::formatValue(field, trimStrings);
if (d->hasBackslashEscape)
- r.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
+ r.replace(u'\\', "\\\\"_L1);
break;
case QMetaType::Bool:
if (field.value().toBool())
@@ -1521,9 +1490,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
#else
unsigned char *data = PQescapeBytea((const unsigned char*)ba.constData(), ba.size(), &len);
#endif
- r += QLatin1Char('\'');
- r += QLatin1String((const char*)data);
- r += QLatin1Char('\'');
+ r += u'\'';
+ r += QLatin1StringView((const char*)data);
+ r += u'\'';
qPQfreemem(data);
break;
}
@@ -1538,7 +1507,7 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
r = QSqlDriver::formatValue(field, trimStrings);
break;
case QMetaType::QUuid:
- r = QLatin1Char('\'') + field.value().toString() + QLatin1Char('\'');
+ r = u'\'' + field.value().toString() + u'\'';
break;
default:
r = QSqlDriver::formatValue(field, trimStrings);
@@ -1551,10 +1520,10 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
QString QPSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
{
QString res = identifier;
- if (!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
- res.replace(QLatin1Char('"'), QLatin1String("\"\""));
- res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
- res.replace(QLatin1Char('.'), QLatin1String("\".\""));
+ if (!identifier.isEmpty() && !identifier.startsWith(u'"') && !identifier.endsWith(u'"') ) {
+ res.replace(u'"', "\"\""_L1);
+ res.replace(u'.', "\".\""_L1);
+ res = u'"' + res + u'"';
}
return res;
}
@@ -1575,7 +1544,7 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
{
Q_D(QPSQLDriver);
if (!isOpen()) {
- qWarning("QPSQLDriver::subscribeToNotificationImplementation: database not open.");
+ qCWarning(lcPsql, "QPSQLDriver::subscribeToNotification: Database not open.");
return false;
}
@@ -1600,11 +1569,12 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
PQclear(result);
if (!d->sn) {
- d->sn = new QSocketNotifier(socket, QSocketNotifier::Read);
- connect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification()));
+ d->sn = new QSocketNotifier(socket, QSocketNotifier::Read, this);
+ connect(d->sn, &QSocketNotifier::activated, this, &QPSQLDriver::_q_handleNotification);
}
} else {
- qWarning("QPSQLDriver::subscribeToNotificationImplementation: PQsocket didn't return a valid socket to listen on");
+ qCWarning(lcPsql, "QPSQLDriver::subscribeToNotificationImplementation: "
+ "PQsocket didn't return a valid socket to listen on.");
return false;
}
@@ -1615,13 +1585,13 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
{
Q_D(QPSQLDriver);
if (!isOpen()) {
- qWarning("QPSQLDriver::unsubscribeFromNotificationImplementation: database not open.");
+ qCWarning(lcPsql, "QPSQLDriver::unsubscribeFromNotification: Database not open.");
return false;
}
if (!d->seid.contains(name)) {
- qWarning("QPSQLDriver::unsubscribeFromNotificationImplementation: not subscribed to '%s'.",
- qPrintable(name));
+ qCWarning(lcPsql, "QPSQLDriver::unsubscribeFromNotification: not subscribed to '%ls'.",
+ qUtf16Printable(name));
return false;
}
@@ -1637,7 +1607,7 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
d->seid.removeAll(name);
if (d->seid.isEmpty()) {
- disconnect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification()));
+ disconnect(d->sn, &QSocketNotifier::activated, this, &QPSQLDriver::_q_handleNotification);
delete d->sn;
d->sn = nullptr;
}
@@ -1659,22 +1629,24 @@ void QPSQLDriver::_q_handleNotification()
PGnotify *notify = nullptr;
while ((notify = PQnotifies(d->connection)) != nullptr) {
- QString name(QLatin1String(notify->relname));
+ QString name(QLatin1StringView(notify->relname));
if (d->seid.contains(name)) {
QString payload;
#if defined PG_VERSION_NUM && PG_VERSION_NUM-0 >= 70400
if (notify->extra)
- payload = d->isUtf8 ? QString::fromUtf8(notify->extra) : QString::fromLatin1(notify->extra);
+ payload = QString::fromUtf8(notify->extra);
#endif
QSqlDriver::NotificationSource source = (notify->be_pid == PQbackendPID(d->connection)) ? QSqlDriver::SelfSource : QSqlDriver::OtherSource;
emit notification(name, source, payload);
}
else
- qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.",
- qPrintable(name));
+ qCWarning(lcPsql, "QPSQLDriver: received notification for '%ls' which isn't subscribed to.",
+ qUtf16Printable(name));
qPQfreemem(notify);
}
}
QT_END_NAMESPACE
+
+#include "moc_qsql_psql_p.cpp"