summaryrefslogtreecommitdiffstats
path: root/src/plugins/sqldrivers/psql
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-11-21 14:34:31 +0100
committerLiang Qi <liang.qi@qt.io>2017-11-23 09:36:03 +0100
commit153e8b49adfe210cb00490284a14c94c08e03c3f (patch)
tree59d9522d6dc96215cc2cb1d19b3e8a0e580bcb41 /src/plugins/sqldrivers/psql
parentef7c0594bf9e41813c9c841e00c3a52269d363f5 (diff)
parenta4113d0c644edba1c39d9d268a259e95ae51c61e (diff)
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts: src/network/access/qhttp2protocolhandler_p.h src/network/kernel/kernel.pri src/network/ssl/qsslkey_qt.cpp src/plugins/platforms/cocoa/qcocoascreen.mm src/plugins/platforms/windows/accessible/iaccessible2.cpp src/plugins/platforms/windows/accessible/iaccessible2.h src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h src/widgets/widgets/qmenu_p.h tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp tests/auto/other/qaccessibility/tst_qaccessibility.cpp tests/auto/testlib/selftests/expected_cmptest.lightxml tests/auto/testlib/selftests/expected_cmptest.teamcity tests/auto/testlib/selftests/expected_cmptest.txt tests/auto/testlib/selftests/expected_cmptest.xml Done-with: Edward Welbourne <edward.welbourne@qt.io> Change-Id: I4217cc7d840cbae3e3dd28574741544469c4c6b9
Diffstat (limited to 'src/plugins/sqldrivers/psql')
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp191
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql_p.h24
2 files changed, 117 insertions, 98 deletions
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index 7699bede27..1dce2f28c1 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -181,13 +181,14 @@ public:
QPSQLDriver::Protocol getPSQLVersion();
bool setEncodingUtf8();
void setDatestyle();
+ void setByteaOutput();
void detectBackslashEscape();
};
void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
{
QString query;
- if (pro >= QPSQLDriver::Version73) {
+ if (pro >= QPSQLDriver::Version7_3) {
query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class "
"left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) "
"where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') "
@@ -525,7 +526,7 @@ int QPSQLResult::numRowsAffected()
QVariant QPSQLResult::lastInsertId() const
{
Q_D(const QPSQLResult);
- if (d->drv_d_func()->pro >= QPSQLDriver::Version81) {
+ if (d->drv_d_func()->pro >= QPSQLDriver::Version8_1) {
QSqlQuery qry(driver()->createResult());
// Most recent sequence value obtained from nextval
if (qry.exec(QLatin1String("SELECT lastval();")) && qry.next())
@@ -698,11 +699,25 @@ void QPSQLDriverPrivate::setDatestyle()
PQclear(result);
}
+void QPSQLDriverPrivate::setByteaOutput()
+{
+ if (pro >= QPSQLDriver::Version9) {
+ // Server version before QPSQLDriver::Version9 only supports escape mode for bytea type,
+ // but bytea format is set to hex by default in PSQL 9 and above. So need to force the
+ // server to use the old escape mode when connects to the new server.
+ PGresult *result = exec("SET bytea_output TO escape");
+ int status = PQresultStatus(result);
+ if (status != PGRES_COMMAND_OK)
+ qWarning("%s", PQerrorMessage(connection));
+ PQclear(result);
+ }
+}
+
void QPSQLDriverPrivate::detectBackslashEscape()
{
// standard_conforming_strings option introduced in 8.2
// http://www.postgresql.org/docs/8.2/static/runtime-config-compatible.html
- if (pro < QPSQLDriver::Version82) {
+ if (pro < QPSQLDriver::Version8_2) {
hasBackslashEscape = true;
} else {
hasBackslashEscape = false;
@@ -724,11 +739,11 @@ static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin)
{
switch (vMin) {
case 1:
- return QPSQLDriver::Version71;
+ return QPSQLDriver::Version7_1;
case 3:
- return QPSQLDriver::Version73;
+ return QPSQLDriver::Version7_3;
case 4:
- return QPSQLDriver::Version74;
+ return QPSQLDriver::Version7_4;
default:
return QPSQLDriver::Version7;
}
@@ -738,76 +753,102 @@ static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin)
{
switch (vMin) {
case 1:
- return QPSQLDriver::Version81;
+ return QPSQLDriver::Version8_1;
case 2:
- return QPSQLDriver::Version82;
+ return QPSQLDriver::Version8_2;
case 3:
- return QPSQLDriver::Version83;
+ return QPSQLDriver::Version8_3;
case 4:
- return QPSQLDriver::Version84;
+ return QPSQLDriver::Version8_4;
default:
return QPSQLDriver::Version8;
}
break;
}
case 9:
- return QPSQLDriver::Version9;
+ {
+ switch (vMin) {
+ case 1:
+ return QPSQLDriver::Version9_1;
+ case 2:
+ return QPSQLDriver::Version9_2;
+ case 3:
+ return QPSQLDriver::Version9_3;
+ case 4:
+ return QPSQLDriver::Version9_4;
+ case 5:
+ return QPSQLDriver::Version9_5;
+ case 6:
+ return QPSQLDriver::Version9_6;
+ default:
+ return QPSQLDriver::Version9;
+ }
break;
+ }
+ case 10:
+ return QPSQLDriver::Version10;
default:
+ if (vMaj > 10)
+ return QPSQLDriver::UnknownLaterVersion;
break;
}
return QPSQLDriver::VersionUnknown;
}
+static QPSQLDriver::Protocol qFindPSQLVersion(const QString &versionString)
+{
+ const QRegExp rx(QStringLiteral("(\\d+)(?:\\.(\\d+))?"));
+ if (rx.indexIn(versionString) != -1) {
+ // Beginning with PostgreSQL version 10, a major release is indicated by
+ // increasing the first part of the version, e.g. 10 to 11.
+ // Before version 10, a major release was indicated by increasing either
+ // the first or second part of the version number, e.g. 9.5 to 9.6.
+ int vMaj = rx.cap(1).toInt();
+ int vMin;
+ if (vMaj >= 10) {
+ vMin = 0;
+ } else {
+ if (rx.cap(2).isEmpty())
+ return QPSQLDriver::VersionUnknown;
+ vMin = rx.cap(2).toInt();
+ }
+ return qMakePSQLVersion(vMaj, vMin);
+ }
+
+ return QPSQLDriver::VersionUnknown;
+}
+
QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion()
{
QPSQLDriver::Protocol serverVersion = QPSQLDriver::Version6;
PGresult* result = exec("select version()");
int status = PQresultStatus(result);
if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) {
- QString val = QString::fromLatin1(PQgetvalue(result, 0, 0));
-
- QRegExp rx(QLatin1String("(\\d+)\\.(\\d+)"));
- rx.setMinimal(true); // enforce non-greedy RegExp
+ serverVersion = qFindPSQLVersion(
+ QString::fromLatin1(PQgetvalue(result, 0, 0)));
+ }
+ PQclear(result);
- if (rx.indexIn(val) != -1) {
- int vMaj = rx.cap(1).toInt();
- int vMin = rx.cap(2).toInt();
- serverVersion = qMakePSQLVersion(vMaj, vMin);
+ QPSQLDriver::Protocol clientVersion =
#if defined(PG_MAJORVERSION)
- if (rx.indexIn(QLatin1String(PG_MAJORVERSION)) != -1)
+ qFindPSQLVersion(QLatin1String(PG_MAJORVERSION));
#elif defined(PG_VERSION)
- if (rx.indexIn(QLatin1String(PG_VERSION)) != -1)
+ qFindPSQLVersion(QLatin1String(PG_VERSION));
#else
- if (0)
+ QPSQLDriver::VersionUnknown;
#endif
- {
- vMaj = rx.cap(1).toInt();
- vMin = rx.cap(2).toInt();
- QPSQLDriver::Protocol clientVersion = qMakePSQLVersion(vMaj, vMin);
-
- if (serverVersion >= QPSQLDriver::Version9 && clientVersion < QPSQLDriver::Version9) {
- //Client version before QPSQLDriver::Version9 only supports escape mode for bytea type,
- //but bytea format is set to hex by default in PSQL 9 and above. So need to force the
- //server use the old escape mode when connects to the new server with old client library.
- PQclear(result);
- result = exec("SET bytea_output=escape; ");
- status = PQresultStatus(result);
- } else 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.");
- }
- }
- }
+
+ 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.");
}
- PQclear(result);
- //keep the old behavior unchanged
+ // Keep the old behavior unchanged
if (serverVersion == QPSQLDriver::VersionUnknown)
serverVersion = QPSQLDriver::Version6;
- if (serverVersion < QPSQLDriver::Version71) {
+ if (serverVersion < QPSQLDriver::Version7_3) {
qWarning("This version of PostgreSQL is not supported and may not work.");
}
@@ -857,7 +898,7 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
return true;
case PreparedQueries:
case PositionalPlaceholders:
- return d->pro >= QPSQLDriver::Version82;
+ return d->pro >= QPSQLDriver::Version8_2;
case BatchOperations:
case NamedPlaceholders:
case SimpleLocking:
@@ -866,7 +907,7 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
case CancelQuery:
return false;
case BLOB:
- return d->pro >= QPSQLDriver::Version71;
+ return d->pro >= QPSQLDriver::Version7_1;
case Unicode:
return d->isUtf8;
}
@@ -929,6 +970,7 @@ bool QPSQLDriver::open(const QString & db,
d->detectBackslashEscape();
d->isUtf8 = d->setEncodingUtf8();
d->setDatestyle();
+ d->setByteaOutput();
setOpen(true);
setOpenError(false);
@@ -993,12 +1035,7 @@ bool QPSQLDriver::commitTransaction()
// 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.
- if (d->pro == QPSQLDriver::Version8 ||
- d->pro == QPSQLDriver::Version81 ||
- d->pro == QPSQLDriver::Version82 ||
- d->pro == QPSQLDriver::Version83 ||
- d->pro == QPSQLDriver::Version84 ||
- d->pro == QPSQLDriver::Version9) {
+ if (d->pro >= QPSQLDriver::Version8) {
transaction_failed = qstrcmp(PQcmdStatus(res), "ROLLBACK") == 0;
}
@@ -1085,8 +1122,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
else
schema = std::move(schema).toLower();
- switch(d->pro) {
- case QPSQLDriver::Version6:
+ if (d->pro == QPSQLDriver::Version6) {
stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname "
"from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
"where pg_cl.relname = '%1_pkey' "
@@ -1095,9 +1131,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
"and pg_att1.attrelid = pg_ind.indrelid "
"and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
"order by pg_att2.attnum");
- break;
- case QPSQLDriver::Version7:
- case QPSQLDriver::Version71:
+ } else if (d->pro == QPSQLDriver::Version7 || d->pro == QPSQLDriver::Version7_1) {
stmt = QLatin1String("select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname "
"from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
"where pg_cl.relname = '%1_pkey' "
@@ -1106,15 +1140,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
"and pg_att1.attrelid = pg_ind.indrelid "
"and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
"order by pg_att2.attnum");
- break;
- case QPSQLDriver::Version73:
- case QPSQLDriver::Version74:
- case QPSQLDriver::Version8:
- case QPSQLDriver::Version81:
- case QPSQLDriver::Version82:
- case QPSQLDriver::Version83:
- case QPSQLDriver::Version84:
- case QPSQLDriver::Version9:
+ } else if (d->pro >= QPSQLDriver::Version7_3) {
stmt = QLatin1String("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
"pg_class.relname "
"FROM pg_attribute, pg_class "
@@ -1129,10 +1155,8 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
else
stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
"pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema));
- break;
- case QPSQLDriver::VersionUnknown:
- qFatal("PSQL version is unknown");
- break;
+ } else {
+ qFatal("QPSQLDriver::primaryIndex(tablename): unknown PSQL version, query statement not set");
}
i.exec(stmt.arg(tbl));
@@ -1166,8 +1190,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
schema = std::move(schema).toLower();
QString stmt;
- switch(d->pro) {
- case QPSQLDriver::Version6:
+ if (d->pro == QPSQLDriver::Version6) {
stmt = QLatin1String("select pg_attribute.attname, int(pg_attribute.atttypid), "
"pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
"int(pg_attribute.attrelid), pg_attribute.attnum "
@@ -1175,8 +1198,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
"where pg_class.relname = '%1' "
"and pg_attribute.attnum > 0 "
"and pg_attribute.attrelid = pg_class.oid ");
- break;
- case QPSQLDriver::Version7:
+ } else if (d->pro == QPSQLDriver::Version7) {
stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
"pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
"pg_attribute.attrelid::int, pg_attribute.attnum "
@@ -1184,8 +1206,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
"where pg_class.relname = '%1' "
"and pg_attribute.attnum > 0 "
"and pg_attribute.attrelid = pg_class.oid ");
- break;
- case QPSQLDriver::Version71:
+ } else if (d->pro == QPSQLDriver::Version7_1) {
stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
"pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
"pg_attrdef.adsrc "
@@ -1196,15 +1217,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
"and pg_attribute.attnum > 0 "
"and pg_attribute.attrelid = pg_class.oid "
"order by pg_attribute.attnum ");
- break;
- case QPSQLDriver::Version73:
- case QPSQLDriver::Version74:
- case QPSQLDriver::Version8:
- case QPSQLDriver::Version81:
- case QPSQLDriver::Version82:
- case QPSQLDriver::Version83:
- case QPSQLDriver::Version84:
- case QPSQLDriver::Version9:
+ } else if (d->pro >= QPSQLDriver::Version7_3) {
stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
"pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
"pg_attrdef.adsrc "
@@ -1222,15 +1235,13 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
else
stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
"pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
- break;
- case QPSQLDriver::VersionUnknown:
- qFatal("PSQL version is unknown");
- break;
+ } else {
+ qFatal("QPSQLDriver::record(tablename): unknown PSQL version, query statement not set");
}
QSqlQuery query(createResult());
query.exec(stmt.arg(tbl));
- if (d->pro >= QPSQLDriver::Version71) {
+ if (d->pro >= QPSQLDriver::Version7_1) {
while (query.next()) {
int len = query.value(3).toInt();
int precision = query.value(4).toInt();
diff --git a/src/plugins/sqldrivers/psql/qsql_psql_p.h b/src/plugins/sqldrivers/psql/qsql_psql_p.h
index 3ff38f3c48..2873a9f851 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql_p.h
+++ b/src/plugins/sqldrivers/psql/qsql_psql_p.h
@@ -76,15 +76,23 @@ public:
VersionUnknown = -1,
Version6 = 6,
Version7 = 7,
- Version71 = 8,
- Version73 = 9,
- Version74 = 10,
+ Version7_1 = 8,
+ Version7_3 = 9,
+ Version7_4 = 10,
Version8 = 11,
- Version81 = 12,
- Version82 = 13,
- Version83 = 14,
- Version84 = 15,
- Version9 = 16
+ Version8_1 = 12,
+ Version8_2 = 13,
+ Version8_3 = 14,
+ Version8_4 = 15,
+ Version9 = 16,
+ Version9_1 = 17,
+ Version9_2 = 18,
+ Version9_3 = 19,
+ Version9_4 = 20,
+ Version9_5 = 21,
+ Version9_6 = 22,
+ Version10 = 23,
+ UnknownLaterVersion = 100000
};
explicit QPSQLDriver(QObject *parent=0);