Qt 4.8
qsql_psql.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtSql module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qsql_psql.h"
43 
44 #include <qcoreapplication.h>
45 #include <qvariant.h>
46 #include <qdatetime.h>
47 #include <qregexp.h>
48 #include <qsqlerror.h>
49 #include <qsqlfield.h>
50 #include <qsqlindex.h>
51 #include <qsqlrecord.h>
52 #include <qsqlquery.h>
53 #include <qsocketnotifier.h>
54 #include <qstringlist.h>
55 #include <qmutex.h>
56 
57 #include <libpq-fe.h>
58 #include <pg_config.h>
59 
60 #include <stdlib.h>
61 #include <math.h>
62 // below code taken from an example at http://www.gnu.org/software/hello/manual/autoconf/Function-Portability.html
63 #ifndef isnan
64  # define isnan(x) \
65  (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
66  : sizeof (x) == sizeof (double) ? isnan_d (x) \
67  : isnan_f (x))
68  static inline int isnan_f (float x) { return x != x; }
69  static inline int isnan_d (double x) { return x != x; }
70  static inline int isnan_ld (long double x) { return x != x; }
71 #endif
72 
73 #ifndef isinf
74  # define isinf(x) \
75  (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
76  : sizeof (x) == sizeof (double) ? isinf_d (x) \
77  : isinf_f (x))
78  static inline int isinf_f (float x) { return isnan (x - x); }
79  static inline int isinf_d (double x) { return isnan (x - x); }
80  static inline int isinf_ld (long double x) { return isnan (x - x); }
81 #endif
82 
83 
84 // workaround for postgres defining their OIDs in a private header file
85 #define QBOOLOID 16
86 #define QINT8OID 20
87 #define QINT2OID 21
88 #define QINT4OID 23
89 #define QNUMERICOID 1700
90 #define QFLOAT4OID 700
91 #define QFLOAT8OID 701
92 #define QABSTIMEOID 702
93 #define QRELTIMEOID 703
94 #define QDATEOID 1082
95 #define QTIMEOID 1083
96 #define QTIMETZOID 1266
97 #define QTIMESTAMPOID 1114
98 #define QTIMESTAMPTZOID 1184
99 #define QOIDOID 2278
100 #define QBYTEAOID 17
101 #define QREGPROCOID 24
102 #define QXIDOID 28
103 #define QCIDOID 29
104 
105 /* This is a compile time switch - if PQfreemem is declared, the compiler will use that one,
106  otherwise it'll run in this template */
107 template <typename T>
108 inline void PQfreemem(T *t, int = 0) { free(t); }
109 
112 
114 
115 inline void qPQfreemem(void *buffer)
116 {
117  PQfreemem(buffer);
118 }
119 
121 {
122 public:
124  : q(qq),
125  connection(0),
126  isUtf8(false),
127  pro(QPSQLDriver::Version6),
128  sn(0),
129  pendingNotifyCheck(false),
130  hasBackslashEscape(false)
131  { }
132 
135  bool isUtf8;
139  mutable bool pendingNotifyCheck;
141 
143  PGresult * exec(const char * stmt) const;
144  PGresult * exec(const QString & stmt) const;
146  bool setEncodingUtf8();
147  void setDatestyle();
148  void detectBackslashEscape();
149 };
150 
152 {
153  QString query;
154  if (pro >= QPSQLDriver::Version73) {
155  query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class "
156  "left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) "
157  "where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') "
158  "and (pg_class.relname !~ '^pg_') "
159  "and (pg_namespace.nspname != 'information_schema') ").arg(type);
160  } else {
161  query = QString::fromLatin1("select relname, null from pg_class where (relkind = '%1') "
162  "and (relname !~ '^Inv') "
163  "and (relname !~ '^pg_') ").arg(type);
164  }
165  t.exec(query);
166  while (t.next()) {
167  QString schema = t.value(1).toString();
168  if (schema.isEmpty() || schema == QLatin1String("public"))
169  tl.append(t.value(0).toString());
170  else
171  tl.append(t.value(0).toString().prepend(QLatin1Char('.')).prepend(schema));
172  }
173 }
174 
175 PGresult * QPSQLDriverPrivate::exec(const char * stmt) const
176 {
177  PGresult *result = PQexec(connection, stmt);
178  if (seid.size() && !pendingNotifyCheck) {
179  pendingNotifyCheck = true;
180  QMetaObject::invokeMethod(q, "_q_handleNotification", Qt::QueuedConnection, Q_ARG(int,0));
181  }
182  return result;
183 }
184 
186 {
187  return exec(isUtf8 ? stmt.toUtf8().constData() : stmt.toLocal8Bit().constData());
188 }
189 
191 {
192 public:
193  QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1), preparedQueriesEnabled(false) {}
194 
201 
202  bool processResults();
203 };
204 
206  const QPSQLDriverPrivate *p, PGresult* result = 0)
207 {
208  const char *s = PQerrorMessage(p->connection);
210  if (result) {
211  const char *sCode = PQresultErrorField(result, PG_DIAG_SQLSTATE);
212  msg += QString::fromLatin1("(%1)").arg(QString::fromLatin1(sCode));
213  }
214  return QSqlError(QLatin1String("QPSQL: ") + err, msg, type);
215 }
216 
218 {
219  if (!result)
220  return false;
221 
222  int status = PQresultStatus(result);
223  if (status == PGRES_TUPLES_OK) {
224  q->setSelect(true);
225  q->setActive(true);
226  currentSize = PQntuples(result);
227  return true;
228  } else if (status == PGRES_COMMAND_OK) {
229  q->setSelect(false);
230  q->setActive(true);
231  currentSize = -1;
232  return true;
233  }
235  "Unable to create query"), QSqlError::StatementError, driver, result));
236  return false;
237 }
238 
240 {
242  switch (t) {
243  case QBOOLOID:
244  type = QVariant::Bool;
245  break;
246  case QINT8OID:
247  type = QVariant::LongLong;
248  break;
249  case QINT2OID:
250  case QINT4OID:
251  case QOIDOID:
252  case QREGPROCOID:
253  case QXIDOID:
254  case QCIDOID:
255  type = QVariant::Int;
256  break;
257  case QNUMERICOID:
258  case QFLOAT4OID:
259  case QFLOAT8OID:
260  type = QVariant::Double;
261  break;
262  case QABSTIMEOID:
263  case QRELTIMEOID:
264  case QDATEOID:
265  type = QVariant::Date;
266  break;
267  case QTIMEOID:
268  case QTIMETZOID:
269  type = QVariant::Time;
270  break;
271  case QTIMESTAMPOID:
272  case QTIMESTAMPTZOID:
273  type = QVariant::DateTime;
274  break;
275  case QBYTEAOID:
276  type = QVariant::ByteArray;
277  break;
278  default:
279  type = QVariant::String;
280  break;
281  }
282  return type;
283 }
284 
286 {
287  const QString stmt = QLatin1String("DEALLOCATE ") + d->preparedStmtId;
288  PGresult *result = d->driver->exec(stmt);
289 
290  if (PQresultStatus(result) != PGRES_COMMAND_OK)
291  qWarning("Unable to free statement: %s", PQerrorMessage(d->driver->connection));
292  PQclear(result);
293  d->preparedStmtId.clear();
294 }
295 
297  : QSqlResult(db)
298 {
299  d = new QPSQLResultPrivate(this);
300  d->driver = p;
302 }
303 
305 {
306  cleanup();
307 
310 
311  delete d;
312 }
313 
315 {
316  return QVariant::fromValue(d->result);
317 }
318 
320 {
321  if (d->result)
322  PQclear(d->result);
323  d->result = 0;
325  d->currentSize = -1;
326  setActive(false);
327 }
328 
330 {
331  if (!isActive())
332  return false;
333  if (i < 0)
334  return false;
335  if (i >= d->currentSize)
336  return false;
337  if (at() == i)
338  return true;
339  setAt(i);
340  return true;
341 }
342 
344 {
345  return fetch(0);
346 }
347 
349 {
350  return fetch(PQntuples(d->result) - 1);
351 }
352 
354 {
355  if (i >= PQnfields(d->result)) {
356  qWarning("QPSQLResult::data: column %d out of range", i);
357  return QVariant();
358  }
359  int ptype = PQftype(d->result, i);
361  const char *val = PQgetvalue(d->result, at(), i);
362  if (PQgetisnull(d->result, at(), i))
363  return QVariant(type);
364  switch (type) {
365  case QVariant::Bool:
366  return QVariant((bool)(val[0] == 't'));
367  case QVariant::String:
368  return d->driver->isUtf8 ? QString::fromUtf8(val) : QString::fromAscii(val);
369  case QVariant::LongLong:
370  if (val[0] == '-')
371  return QString::fromLatin1(val).toLongLong();
372  else
373  return QString::fromLatin1(val).toULongLong();
374  case QVariant::Int:
375  return atoi(val);
376  case QVariant::Double:
377  if (ptype == QNUMERICOID) {
379  QVariant retval;
380  bool convert;
381  double dbl=QString::fromAscii(val).toDouble(&convert);
383  retval = (qlonglong)dbl;
385  retval = (int)dbl;
387  retval = dbl;
388  if (!convert)
389  return QVariant();
390  return retval;
391  }
392  return QString::fromAscii(val);
393  }
394  return QString::fromAscii(val).toDouble();
395  case QVariant::Date:
396  if (val[0] == '\0') {
397  return QVariant(QDate());
398  } else {
399 #ifndef QT_NO_DATESTRING
401 #else
402  return QVariant(QString::fromLatin1(val));
403 #endif
404  }
405  case QVariant::Time: {
406  const QString str = QString::fromLatin1(val);
407 #ifndef QT_NO_DATESTRING
408  if (str.isEmpty())
409  return QVariant(QTime());
410  if (str.at(str.length() - 3) == QLatin1Char('+') || str.at(str.length() - 3) == QLatin1Char('-'))
411  // strip the timezone
412  // TODO: fix this when timestamp support comes into QDateTime
413  return QVariant(QTime::fromString(str.left(str.length() - 3), Qt::ISODate));
414  return QVariant(QTime::fromString(str, Qt::ISODate));
415 #else
416  return QVariant(str);
417 #endif
418  }
419  case QVariant::DateTime: {
420  QString dtval = QString::fromLatin1(val);
421 #ifndef QT_NO_DATESTRING
422  if (dtval.length() < 10)
423  return QVariant(QDateTime());
424  // remove the timezone
425  // TODO: fix this when timestamp support comes into QDateTime
426  if (dtval.at(dtval.length() - 3) == QLatin1Char('+') || dtval.at(dtval.length() - 3) == QLatin1Char('-'))
427  dtval.chop(3);
428  // milliseconds are sometimes returned with 2 digits only
429  if (dtval.at(dtval.length() - 3).isPunct())
430  dtval += QLatin1Char('0');
431  if (dtval.isEmpty())
432  return QVariant(QDateTime());
433  else
435 #else
436  return QVariant(dtval);
437 #endif
438  }
439  case QVariant::ByteArray: {
440  size_t len;
441  unsigned char *data = PQunescapeBytea((unsigned char*)val, &len);
442  QByteArray ba((const char*)data, len);
443  qPQfreemem(data);
444  return QVariant(ba);
445  }
446  default:
447  case QVariant::Invalid:
448  qWarning("QPSQLResult::data: unknown data type");
449  }
450  return QVariant();
451 }
452 
453 bool QPSQLResult::isNull(int field)
454 {
455  PQgetvalue(d->result, at(), field);
456  return PQgetisnull(d->result, at(), field);
457 }
458 
459 bool QPSQLResult::reset (const QString& query)
460 {
461  cleanup();
462  if (!driver())
463  return false;
464  if (!driver()->isOpen() || driver()->isOpenError())
465  return false;
466  d->result = d->driver->exec(query);
467  return d->processResults();
468 }
469 
471 {
472  return d->currentSize;
473 }
474 
476 {
477  return QString::fromLatin1(PQcmdTuples(d->result)).toInt();
478 }
479 
481 {
482  if (isActive()) {
483  Oid id = PQoidValue(d->result);
484  if (id != InvalidOid)
485  return QVariant(id);
486  }
487  return QVariant();
488 }
489 
491 {
493  if (!isActive() || !isSelect())
494  return info;
495 
496  int count = PQnfields(d->result);
497  for (int i = 0; i < count; ++i) {
498  QSqlField f;
499  if (d->driver->isUtf8)
500  f.setName(QString::fromUtf8(PQfname(d->result, i)));
501  else
502  f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));
503  f.setType(qDecodePSQLType(PQftype(d->result, i)));
504  int len = PQfsize(d->result, i);
505  int precision = PQfmod(d->result, i);
506  // swap length and precision if length == -1
507  if (len == -1 && precision > -1) {
508  len = precision - 4;
509  precision = -1;
510  }
511  f.setLength(len);
512  f.setPrecision(precision);
513  f.setSqlType(PQftype(d->result, i));
514  info.append(f);
515  }
516  return info;
517 }
518 
519 void QPSQLResult::virtual_hook(int id, void *data)
520 {
521  Q_ASSERT(data);
522 
523  switch (id) {
524  default:
525  QSqlResult::virtual_hook(id, data);
526  }
527 }
528 
530 {
531  const int originalLength = query.length();
532  bool inQuote = false;
533  int markerIdx = 0;
534  QString result;
535  result.reserve(originalLength + 23);
536  for (int i = 0; i < originalLength; ++i) {
537  const QChar ch = query.at(i);
538  if (ch == QLatin1Char('?') && !inQuote) {
539  result += QLatin1Char('$');
540  result += QString::number(++markerIdx);
541  } else {
542  if (ch == QLatin1Char('\''))
543  inQuote = !inQuote;
544  result += ch;
545  }
546  }
547 
548  result.squeeze();
549  return result;
550 }
551 
553 {
554  if (boundValues.isEmpty())
555  return QString();
556 
557  QString params;
558  QSqlField f;
559  for (int i = 0; i < boundValues.count(); ++i) {
560  const QVariant &val = boundValues.at(i);
561 
562  f.setType(val.type());
563  if (val.isNull())
564  f.clear();
565  else
566  f.setValue(val);
567  if(!params.isNull())
568  params.append(QLatin1String(", "));
569  params.append(driver->formatValue(f));
570  }
571  return params;
572 }
573 
574 Q_GLOBAL_STATIC(QMutex, qMutex)
576 {
577  qMutex()->lock();
578  static unsigned int qPreparedStmtCount = 0;
579  QString id = QLatin1String("qpsqlpstmt_") + QString::number(++qPreparedStmtCount, 16);
580  qMutex()->unlock();
581  return id;
582 }
583 
584 bool QPSQLResult::prepare(const QString &query)
585 {
587  return QSqlResult::prepare(query);
588 
589  cleanup();
590 
591  if (!d->preparedStmtId.isEmpty())
593 
594  const QString stmtId = qMakePreparedStmtId();
595  const QString stmt = QString::fromLatin1("PREPARE %1 AS ").arg(stmtId).append(qReplacePlaceholderMarkers(query));
596 
597  PGresult *result = d->driver->exec(stmt);
598 
599  if (PQresultStatus(result) != PGRES_COMMAND_OK) {
601  "Unable to prepare statement"), QSqlError::StatementError, d->driver, result));
602  PQclear(result);
604  return false;
605  }
606 
607  PQclear(result);
608  d->preparedStmtId = stmtId;
609  return true;
610 }
611 
613 {
615  return QSqlResult::exec();
616 
617  cleanup();
618 
619  QString stmt;
620  const QString params = qCreateParamString(boundValues(), d->q->driver());
621  if (params.isEmpty())
622  stmt = QString::fromLatin1("EXECUTE %1").arg(d->preparedStmtId);
623  else
624  stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId).arg(params);
625 
626  d->result = d->driver->exec(stmt);
627 
628  return d->processResults();
629 }
630 
632 
634 {
635  PGresult* result = exec("SET CLIENT_ENCODING TO 'UNICODE'");
636  int status = PQresultStatus(result);
637  PQclear(result);
638  return status == PGRES_COMMAND_OK;
639 }
640 
642 {
643  PGresult* result = exec("SET DATESTYLE TO 'ISO'");
644  int status = PQresultStatus(result);
645  if (status != PGRES_COMMAND_OK)
646  qWarning("%s", PQerrorMessage(connection));
647  PQclear(result);
648 }
649 
651 {
652  // standard_conforming_strings option introduced in 8.2
653  // http://www.postgresql.org/docs/8.2/static/runtime-config-compatible.html
654  if (pro < QPSQLDriver::Version82) {
655  hasBackslashEscape = true;
656  } else {
657  hasBackslashEscape = false;
658  PGresult* result = exec(QLatin1String("SELECT '\\\\' x"));
659  int status = PQresultStatus(result);
660  if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK)
661  if (QString::fromLatin1(PQgetvalue(result, 0, 0)) == QLatin1String("\\"))
662  hasBackslashEscape = true;
663  PQclear(result);
664  }
665 }
666 
667 static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin)
668 {
669  switch (vMaj) {
670  case 6:
671  return QPSQLDriver::Version6;
672  case 7:
673  {
674  switch (vMin) {
675  case 1:
676  return QPSQLDriver::Version71;
677  case 3:
678  return QPSQLDriver::Version73;
679  case 4:
680  return QPSQLDriver::Version74;
681  default:
682  return QPSQLDriver::Version7;
683  }
684  break;
685  }
686  case 8:
687  {
688  switch (vMin) {
689  case 1:
690  return QPSQLDriver::Version81;
691  case 2:
692  return QPSQLDriver::Version82;
693  case 3:
694  return QPSQLDriver::Version83;
695  case 4:
696  return QPSQLDriver::Version84;
697  default:
698  return QPSQLDriver::Version8;
699  }
700  break;
701  }
702  case 9:
703  return QPSQLDriver::Version9;
704  break;
705  default:
706  break;
707  }
709 }
710 
712 {
714  PGresult* result = exec("select version()");
715  int status = PQresultStatus(result);
716  if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) {
717  QString val = QString::fromAscii(PQgetvalue(result, 0, 0));
718 
719  QRegExp rx(QLatin1String("(\\d+)\\.(\\d+)"));
720  rx.setMinimal(true); // enforce non-greedy RegExp
721 
722  if (rx.indexIn(val) != -1) {
723  int vMaj = rx.cap(1).toInt();
724  int vMin = rx.cap(2).toInt();
725  serverVersion = qMakePSQLVersion(vMaj, vMin);
726 #ifdef PG_MAJORVERSION
727  if (rx.indexIn(QLatin1String(PG_MAJORVERSION)) != -1) {
728  vMaj = rx.cap(1).toInt();
729  vMin = rx.cap(2).toInt();
730  }
731  QPSQLDriver::Protocol clientVersion = qMakePSQLVersion(vMaj, vMin);
732 
733  if (serverVersion >= QPSQLDriver::Version9 && clientVersion < QPSQLDriver::Version9) {
734  //Client version before QPSQLDriver::Version9 only supports escape mode for bytea type,
735  //but bytea format is set to hex by default in PSQL 9 and above. So need to force the
736  //server use the old escape mode when connects to the new server with old client library.
737  result = exec("SET bytea_output=escape; ");
738  status = PQresultStatus(result);
739  } else if (serverVersion == QPSQLDriver::VersionUnknown) {
740  serverVersion = clientVersion;
741  if (serverVersion != QPSQLDriver::VersionUnknown)
742  qWarning("The server version of this PostgreSQL is unknown, falling back to the client version.");
743  }
744 #endif
745  }
746  }
747  PQclear(result);
748 
749  //keep the old behavior unchanged
750  if (serverVersion == QPSQLDriver::VersionUnknown)
751  serverVersion = QPSQLDriver::Version6;
752 
753  if (serverVersion < QPSQLDriver::Version71) {
754  qWarning("This version of PostgreSQL is not supported and may not work.");
755  }
756 
757  return serverVersion;
758 }
759 
761  : QSqlDriver(parent)
762 {
763  init();
764 }
765 
767  : QSqlDriver(parent)
768 {
769  init();
770  d->connection = conn;
771  if (conn) {
772  d->pro = d->getPSQLVersion();
774  setOpen(true);
775  setOpenError(false);
776  }
777 }
778 
780 {
781  d = new QPSQLDriverPrivate(this);
782 }
783 
785 {
786  if (d->connection)
787  PQfinish(d->connection);
788  delete d;
789 }
790 
792 {
794 }
795 
797 {
798  switch (f) {
799  case Transactions:
800  case QuerySize:
801  case LastInsertId:
802  case LowPrecisionNumbers:
803  case EventNotifications:
804  return true;
805  case PreparedQueries:
807  return d->pro >= QPSQLDriver::Version82;
808  case BatchOperations:
809  case NamedPlaceholders:
810  case SimpleLocking:
811  case FinishQuery:
812  case MultipleResultSets:
813  return false;
814  case BLOB:
815  return d->pro >= QPSQLDriver::Version71;
816  case Unicode:
817  return d->isUtf8;
818  }
819  return false;
820 }
821 
822 /*
823  Quote a string for inclusion into the connection string
824  \ -> \\
825  ' -> \'
826  surround string by single quotes
827  */
829 {
830  s.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
831  s.replace(QLatin1Char('\''), QLatin1String("\\'"));
832  s.append(QLatin1Char('\'')).prepend(QLatin1Char('\''));
833  return s;
834 }
835 
836 bool QPSQLDriver::open(const QString & db,
837  const QString & user,
838  const QString & password,
839  const QString & host,
840  int port,
841  const QString& connOpts)
842 {
843  if (isOpen())
844  close();
845  QString connectString;
846  if (!host.isEmpty())
847  connectString.append(QLatin1String("host=")).append(qQuote(host));
848  if (!db.isEmpty())
849  connectString.append(QLatin1String(" dbname=")).append(qQuote(db));
850  if (!user.isEmpty())
851  connectString.append(QLatin1String(" user=")).append(qQuote(user));
852  if (!password.isEmpty())
853  connectString.append(QLatin1String(" password=")).append(qQuote(password));
854  if (port != -1)
855  connectString.append(QLatin1String(" port=")).append(qQuote(QString::number(port)));
856 
857  // add any connect options - the server will handle error detection
858  if (!connOpts.isEmpty()) {
859  QString opt = connOpts;
861  connectString.append(QLatin1Char(' ')).append(opt);
862  }
863 
864  d->connection = PQconnectdb(connectString.toLocal8Bit().constData());
865  if (PQstatus(d->connection) == CONNECTION_BAD) {
866  setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d));
867  setOpenError(true);
868  PQfinish(d->connection);
869  d->connection = 0;
870  return false;
871  }
872 
873  d->pro = d->getPSQLVersion();
875  d->isUtf8 = d->setEncodingUtf8();
876  d->setDatestyle();
877 
878  setOpen(true);
879  setOpenError(false);
880  return true;
881 }
882 
884 {
885  if (isOpen()) {
886 
887  d->seid.clear();
888  if (d->sn) {
889  disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
890  delete d->sn;
891  d->sn = 0;
892  }
893 
894  if (d->connection)
895  PQfinish(d->connection);
896  d->connection = 0;
897  setOpen(false);
898  setOpenError(false);
899  }
900 }
901 
903 {
904  return new QPSQLResult(this, d);
905 }
906 
908 {
909  if (!isOpen()) {
910  qWarning("QPSQLDriver::beginTransaction: Database not open");
911  return false;
912  }
913  PGresult* res = d->exec("BEGIN");
914  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
915  setLastError(qMakeError(tr("Could not begin transaction"),
917  PQclear(res);
918  return false;
919  }
920  PQclear(res);
921  return true;
922 }
923 
925 {
926  if (!isOpen()) {
927  qWarning("QPSQLDriver::commitTransaction: Database not open");
928  return false;
929  }
930  PGresult* res = d->exec("COMMIT");
931 
932  bool transaction_failed = false;
933 
934  // XXX
935  // This hack is used to tell if the transaction has succeeded for the protocol versions of
936  // PostgreSQL below. For 7.x and other protocol versions we are left in the dark.
937  // This hack can dissapear once there is an API to query this sort of information.
938  if (d->pro == QPSQLDriver::Version8 ||
944  transaction_failed = qstrcmp(PQcmdStatus(res), "ROLLBACK") == 0;
945  }
946 
947  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK || transaction_failed) {
948  setLastError(qMakeError(tr("Could not commit transaction"),
950  PQclear(res);
951  return false;
952  }
953  PQclear(res);
954  return true;
955 }
956 
958 {
959  if (!isOpen()) {
960  qWarning("QPSQLDriver::rollbackTransaction: Database not open");
961  return false;
962  }
963  PGresult* res = d->exec("ROLLBACK");
964  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
965  setLastError(qMakeError(tr("Could not rollback transaction"),
967  PQclear(res);
968  return false;
969  }
970  PQclear(res);
971  return true;
972 }
973 
975 {
976  QStringList tl;
977  if (!isOpen())
978  return tl;
979  QSqlQuery t(createResult());
980  t.setForwardOnly(true);
981 
982  if (type & QSql::Tables)
983  d->appendTables(tl, t, QLatin1Char('r'));
984  if (type & QSql::Views)
985  d->appendTables(tl, t, QLatin1Char('v'));
986  if (type & QSql::SystemTables) {
987  t.exec(QLatin1String("select relname from pg_class where (relkind = 'r') "
988  "and (relname like 'pg_%') "));
989  while (t.next())
990  tl.append(t.value(0).toString());
991  }
992 
993  return tl;
994 }
995 
996 static void qSplitTableName(QString &tablename, QString &schema)
997 {
998  int dot = tablename.indexOf(QLatin1Char('.'));
999  if (dot == -1)
1000  return;
1001  schema = tablename.left(dot);
1002  tablename = tablename.mid(dot + 1);
1003 }
1004 
1006 {
1007  QSqlIndex idx(tablename);
1008  if (!isOpen())
1009  return idx;
1010  QSqlQuery i(createResult());
1011  QString stmt;
1012 
1013  QString tbl = tablename;
1014  QString schema;
1015  qSplitTableName(tbl, schema);
1016 
1019  else
1020  tbl = tbl.toLower();
1021 
1023  schema = stripDelimiters(schema, QSqlDriver::TableName);
1024  else
1025  schema = schema.toLower();
1026 
1027  switch(d->pro) {
1028  case QPSQLDriver::Version6:
1029  stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname "
1030  "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
1031  "where pg_cl.relname = '%1_pkey' "
1032  "and pg_cl.oid = pg_ind.indexrelid "
1033  "and pg_att2.attrelid = pg_ind.indexrelid "
1034  "and pg_att1.attrelid = pg_ind.indrelid "
1035  "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
1036  "order by pg_att2.attnum");
1037  break;
1038  case QPSQLDriver::Version7:
1040  stmt = QLatin1String("select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname "
1041  "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
1042  "where pg_cl.relname = '%1_pkey' "
1043  "and pg_cl.oid = pg_ind.indexrelid "
1044  "and pg_att2.attrelid = pg_ind.indexrelid "
1045  "and pg_att1.attrelid = pg_ind.indrelid "
1046  "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
1047  "order by pg_att2.attnum");
1048  break;
1051  case QPSQLDriver::Version8:
1056  case QPSQLDriver::Version9:
1057  stmt = QLatin1String("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
1058  "pg_class.relname "
1059  "FROM pg_attribute, pg_class "
1060  "WHERE %1 pg_class.oid IN "
1061  "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
1062  " (SELECT oid FROM pg_class WHERE relname = '%2')) "
1063  "AND pg_attribute.attrelid = pg_class.oid "
1064  "AND pg_attribute.attisdropped = false "
1065  "ORDER BY pg_attribute.attnum");
1066  if (schema.isEmpty())
1067  stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid) AND"));
1068  else
1069  stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
1070  "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema));
1071  break;
1073  qFatal("PSQL version is unknown");
1074  break;
1075  }
1076 
1077  i.exec(stmt.arg(tbl));
1078  while (i.isActive() && i.next()) {
1079  QSqlField f(i.value(0).toString(), qDecodePSQLType(i.value(1).toInt()));
1080  idx.append(f);
1081  idx.setName(i.value(2).toString());
1082  }
1083  return idx;
1084 }
1085 
1086 QSqlRecord QPSQLDriver::record(const QString& tablename) const
1087 {
1088  QSqlRecord info;
1089  if (!isOpen())
1090  return info;
1091 
1092  QString tbl = tablename;
1093  QString schema;
1094  qSplitTableName(tbl, schema);
1095 
1098  else
1099  tbl = tbl.toLower();
1100 
1102  schema = stripDelimiters(schema, QSqlDriver::TableName);
1103  else
1104  schema = schema.toLower();
1105 
1106  QString stmt;
1107  switch(d->pro) {
1108  case QPSQLDriver::Version6:
1109  stmt = QLatin1String("select pg_attribute.attname, int(pg_attribute.atttypid), "
1110  "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
1111  "int(pg_attribute.attrelid), pg_attribute.attnum "
1112  "from pg_class, pg_attribute "
1113  "where pg_class.relname = '%1' "
1114  "and pg_attribute.attnum > 0 "
1115  "and pg_attribute.attrelid = pg_class.oid ");
1116  break;
1117  case QPSQLDriver::Version7:
1118  stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
1119  "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
1120  "pg_attribute.attrelid::int, pg_attribute.attnum "
1121  "from pg_class, pg_attribute "
1122  "where pg_class.relname = '%1' "
1123  "and pg_attribute.attnum > 0 "
1124  "and pg_attribute.attrelid = pg_class.oid ");
1125  break;
1127  stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
1128  "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
1129  "pg_attrdef.adsrc "
1130  "from pg_class, pg_attribute "
1131  "left join pg_attrdef on (pg_attrdef.adrelid = "
1132  "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
1133  "where pg_class.relname = '%1' "
1134  "and pg_attribute.attnum > 0 "
1135  "and pg_attribute.attrelid = pg_class.oid "
1136  "order by pg_attribute.attnum ");
1137  break;
1140  case QPSQLDriver::Version8:
1145  case QPSQLDriver::Version9:
1146  stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
1147  "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
1148  "pg_attrdef.adsrc "
1149  "from pg_class, pg_attribute "
1150  "left join pg_attrdef on (pg_attrdef.adrelid = "
1151  "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
1152  "where %1 "
1153  "and pg_class.relname = '%2' "
1154  "and pg_attribute.attnum > 0 "
1155  "and pg_attribute.attrelid = pg_class.oid "
1156  "and pg_attribute.attisdropped = false "
1157  "order by pg_attribute.attnum ");
1158  if (schema.isEmpty())
1159  stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid)"));
1160  else
1161  stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
1162  "pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
1163  break;
1165  qFatal("PSQL version is unknown");
1166  break;
1167  }
1168 
1169  QSqlQuery query(createResult());
1170  query.exec(stmt.arg(tbl));
1171  if (d->pro >= QPSQLDriver::Version71) {
1172  while (query.next()) {
1173  int len = query.value(3).toInt();
1174  int precision = query.value(4).toInt();
1175  // swap length and precision if length == -1
1176  if (len == -1 && precision > -1) {
1177  len = precision - 4;
1178  precision = -1;
1179  }
1180  QString defVal = query.value(5).toString();
1181  if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
1182  defVal = defVal.mid(1, defVal.length() - 2);
1183  QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()));
1184  f.setRequired(query.value(2).toBool());
1185  f.setLength(len);
1186  f.setPrecision(precision);
1187  f.setDefaultValue(defVal);
1188  f.setSqlType(query.value(1).toInt());
1189  info.append(f);
1190  }
1191  } else {
1192  // Postgres < 7.1 cannot handle outer joins
1193  while (query.next()) {
1194  QString defVal;
1195  QString stmt2 = QLatin1String("select pg_attrdef.adsrc from pg_attrdef where "
1196  "pg_attrdef.adrelid = %1 and pg_attrdef.adnum = %2 ");
1197  QSqlQuery query2(createResult());
1198  query2.exec(stmt2.arg(query.value(5).toInt()).arg(query.value(6).toInt()));
1199  if (query2.isActive() && query2.next())
1200  defVal = query2.value(0).toString();
1201  if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
1202  defVal = defVal.mid(1, defVal.length() - 2);
1203  int len = query.value(3).toInt();
1204  int precision = query.value(4).toInt();
1205  // swap length and precision if length == -1
1206  if (len == -1 && precision > -1) {
1207  len = precision - 4;
1208  precision = -1;
1209  }
1210  QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()));
1211  f.setRequired(query.value(2).toBool());
1212  f.setLength(len);
1213  f.setPrecision(precision);
1214  f.setDefaultValue(defVal);
1215  f.setSqlType(query.value(1).toInt());
1216  info.append(f);
1217  }
1218  }
1219 
1220  return info;
1221 }
1222 
1223 QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
1224 {
1225  QString r;
1226  if (field.isNull()) {
1227  r = QLatin1String("NULL");
1228  } else {
1229  switch (field.type()) {
1230  case QVariant::DateTime:
1231 #ifndef QT_NO_DATESTRING
1232  if (field.value().toDateTime().isValid()) {
1233  QDate dt = field.value().toDateTime().date();
1234  QTime tm = field.value().toDateTime().time();
1235  // msecs need to be right aligned otherwise psql
1236  // interpretes them wrong
1237  r = QLatin1Char('\'') + QString::number(dt.year()) + QLatin1Char('-')
1238  + QString::number(dt.month()) + QLatin1Char('-')
1239  + QString::number(dt.day()) + QLatin1Char(' ')
1240  + tm.toString() + QLatin1Char('.')
1241  + QString::number(tm.msec()).rightJustified(3, QLatin1Char('0'))
1242  + QLatin1Char('\'');
1243  } else {
1244  r = QLatin1String("NULL");
1245  }
1246 #else
1247  r = QLatin1String("NULL");
1248 #endif // QT_NO_DATESTRING
1249  break;
1250  case QVariant::Time:
1251 #ifndef QT_NO_DATESTRING
1252  if (field.value().toTime().isValid()) {
1253  r = QLatin1Char('\'') + field.value().toTime().toString(QLatin1String("hh:mm:ss.zzz")) + QLatin1Char('\'');
1254  } else
1255 #endif
1256  {
1257  r = QLatin1String("NULL");
1258  }
1259  break;
1260  case QVariant::String:
1261  r = QSqlDriver::formatValue(field, trimStrings);
1262  if (d->hasBackslashEscape)
1263  r.replace(QLatin1String("\\"), QLatin1String("\\\\"));
1264  break;
1265  case QVariant::Bool:
1266  if (field.value().toBool())
1267  r = QLatin1String("TRUE");
1268  else
1269  r = QLatin1String("FALSE");
1270  break;
1271  case QVariant::ByteArray: {
1272  QByteArray ba(field.value().toByteArray());
1273  size_t len;
1274 #if defined PG_VERSION_NUM && PG_VERSION_NUM-0 >= 80200
1275  unsigned char *data = PQescapeByteaConn(d->connection, (unsigned char*)ba.constData(), ba.size(), &len);
1276 #else
1277  unsigned char *data = PQescapeBytea((unsigned char*)ba.constData(), ba.size(), &len);
1278 #endif
1279  r += QLatin1Char('\'');
1280  r += QLatin1String((const char*)data);
1281  r += QLatin1Char('\'');
1282  qPQfreemem(data);
1283  break;
1284  }
1285  case QVariant::Double: {
1286  double val = field.value().toDouble();
1287  if (isnan(val))
1288  r = QLatin1String("'NaN'");
1289  else {
1290  int res = isinf(val);
1291  if (res == 1)
1292  r = QLatin1String("'Infinity'");
1293  else if (res == -1)
1294  r = QLatin1String("'-Infinity'");
1295  else
1296  r = QSqlDriver::formatValue(field, trimStrings);
1297  }
1298  break;
1299  }
1300  default:
1301  r = QSqlDriver::formatValue(field, trimStrings);
1302  break;
1303  }
1304  }
1305  return r;
1306 }
1307 
1309 {
1310  QString res = identifier;
1311  if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
1312  res.replace(QLatin1Char('"'), QLatin1String("\"\""));
1313  res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
1314  res.replace(QLatin1Char('.'), QLatin1String("\".\""));
1315  }
1316  return res;
1317 }
1318 
1320 {
1321  return PQstatus(d->connection) == CONNECTION_OK;
1322 }
1323 
1325 {
1326  return d->pro;
1327 }
1328 
1330 {
1331  if (!isOpen()) {
1332  qWarning("QPSQLDriver::subscribeToNotificationImplementation: database not open.");
1333  return false;
1334  }
1335 
1336  if (d->seid.contains(name)) {
1337  qWarning("QPSQLDriver::subscribeToNotificationImplementation: already subscribing to '%s'.",
1338  qPrintable(name));
1339  return false;
1340  }
1341 
1342  int socket = PQsocket(d->connection);
1343  if (socket) {
1344  // Add the name to the list of subscriptions here so that QSQLDriverPrivate::exec knows
1345  // to check for notifications immediately after executing the LISTEN
1346  d->seid << name;
1347  QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
1348  PGresult *result = d->exec(query);
1349  if (PQresultStatus(result) != PGRES_COMMAND_OK) {
1350  setLastError(qMakeError(tr("Unable to subscribe"), QSqlError::StatementError, d, result));
1351  return false;
1352  }
1353 
1354  if (!d->sn) {
1355  d->sn = new QSocketNotifier(socket, QSocketNotifier::Read);
1356  connect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
1357  }
1358  } else {
1359  qWarning("QPSQLDriver::subscribeToNotificationImplementation: PQsocket didn't return a valid socket to listen on");
1360  return false;
1361  }
1362 
1363  return true;
1364 }
1365 
1367 {
1368  if (!isOpen()) {
1369  qWarning("QPSQLDriver::unsubscribeFromNotificationImplementation: database not open.");
1370  return false;
1371  }
1372 
1373  if (!d->seid.contains(name)) {
1374  qWarning("QPSQLDriver::unsubscribeFromNotificationImplementation: not subscribed to '%s'.",
1375  qPrintable(name));
1376  return false;
1377  }
1378 
1379  QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
1380  PGresult *result = d->exec(query);
1381  if (PQresultStatus(result) != PGRES_COMMAND_OK) {
1382  setLastError(qMakeError(tr("Unable to unsubscribe"), QSqlError::StatementError, d, result));
1383  return false;
1384  }
1385 
1386  d->seid.removeAll(name);
1387 
1388  if (d->seid.isEmpty()) {
1389  disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
1390  delete d->sn;
1391  d->sn = 0;
1392  }
1393 
1394  return true;
1395 }
1396 
1398 {
1399  return d->seid;
1400 }
1401 
1403 {
1404  d->pendingNotifyCheck = false;
1405  PQconsumeInput(d->connection);
1406 
1407  PGnotify *notify = 0;
1408  while((notify = PQnotifies(d->connection)) != 0) {
1409  QString name(QLatin1String(notify->relname));
1410  if (d->seid.contains(name))
1411  emit notification(name);
1412  else
1413  qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.",
1414  qPrintable(name));
1415 
1416  qPQfreemem(notify);
1417  }
1418 }
1419 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QSqlError class provides SQL database error information.
Definition: qsqlerror.h:53
The QSqlIndex class provides functions to manipulate and describe database indexes.
Definition: qsqlindex.h:55
QPSQLResultPrivate * d
Definition: qsql_psql.h:92
QString formatValue(const QSqlField &field, bool trimStrings) const
Returns a string representation of the field value for the database.
Definition: qsql_psql.cpp:1223
double d
Definition: qnumeric_p.h:62
const QSqlDriver * driver() const
Returns the driver associated with the result.
Definition: qsqlresult.cpp:389
void setType(QVariant::Type type)
Set&#39;s the field&#39;s variant type to type.
Definition: qsqlfield.cpp:404
qlonglong toLongLong(bool *ok=0, int base=10) const
Returns the string converted to a long long using base base, which is 10 by default and must be betwe...
Definition: qstring.cpp:5943
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
int type
Definition: qmetatype.cpp:239
#define QTIMESTAMPTZOID
Definition: qsql_psql.cpp:98
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
Definition: qsqlresult.cpp:340
static mach_timebase_info_data_t info
QString cap(int nth=0) const
Returns the text captured by the nth subexpression.
Definition: qregexp.cpp:4310
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
virtual void setOpen(bool o)
This function sets the open state of the database to open.
Definition: qsqldriver.cpp:283
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
qulonglong toULongLong(bool *ok=0, int base=10) const
Returns the string converted to an unsigned long long using base base, which is 10 by default and mus...
Definition: qstring.cpp:5984
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
bool isOpen() const
Returns true if the database connection is open; otherwise returns false.
Definition: qsql_psql.cpp:1319
bool subscribeToNotificationImplementation(const QString &name)
Definition: qsql_psql.cpp:1329
DriverFeature
This enum contains a list of features a driver might support.
Definition: qsqldriver.h:75
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
static QString qCreateParamString(const QVector< QVariant > boundValues, const QSqlDriver *driver)
Definition: qsql_psql.cpp:552
bool isNull() const
Returns true if this is a NULL variant, false otherwise.
Definition: qvariant.cpp:3102
virtual void setOpenError(bool e)
This function sets the open error state of the database to error.
Definition: qsqldriver.cpp:297
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
void append(const QSqlField &field)
Appends the field field to the list of indexed fields.
Definition: qsqlindex.cpp:129
int size()
Returns the size of the SELECT result, or -1 if it cannot be determined or if the query is not a SELE...
Definition: qsql_psql.cpp:470
#define QREGPROCOID
Definition: qsql_psql.cpp:101
QString qMakePreparedStmtId()
Definition: qsql_psql.cpp:575
QVariant value() const
Returns the value of the field as a QVariant.
Definition: qsqlfield.h:71
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
void setName(const QString &name)
Sets the name of the field to name.
Definition: qsqlfield.cpp:347
#define QDATEOID
Definition: qsql_psql.cpp:94
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
static int isnan_d(double x)
Definition: qsql_psql.cpp:69
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString & prepend(QChar c)
Definition: qstring.h:261
#define SLOT(a)
Definition: qobjectdefs.h:226
int month() const
Returns the number corresponding to the month of this date, using the following convention: ...
Definition: qdatetime.cpp:382
QPSQLResult * q
Definition: qsql_psql.cpp:195
The QSqlQuery class provides a means of executing and manipulating SQL statements.
Definition: qsqlquery.h:63
#define QTIMEOID
Definition: qsql_psql.cpp:95
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
static int isinf_d(double x)
Definition: qsql_psql.cpp:79
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has type() DateTime , Date , or String ; otherwise ...
Definition: qvariant.cpp:2349
#define isinf(x)
Definition: qsql_psql.cpp:74
void setPrecision(int precision)
Sets the field&#39;s precision.
Definition: qsqlfield.cpp:265
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
int day() const
Returns the day of the month (1 to 31) of this date.
Definition: qdatetime.cpp:395
PGresult * result
Definition: qsql_psql.cpp:197
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
#define Q_ARG(type, data)
Definition: qobjectdefs.h:246
bool isValid() const
Returns true if both the date and the time are valid; otherwise returns false.
Definition: qdatetime.cpp:2346
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
The QDate class provides date functions.
Definition: qdatetime.h:55
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool toBool() const
Returns the variant as a bool if the variant has type() Bool.
Definition: qvariant.cpp:2691
QString preparedStmtId
Definition: qsql_psql.cpp:200
int msec() const
Returns the millisecond part (0 to 999) of the time.
Definition: qdatetime.cpp:1611
#define QTIMESTAMPOID
Definition: qsql_psql.cpp:97
QSqlIndex primaryIndex(const QString &tablename) const
Returns the primary index for table tableName.
Definition: qsql_psql.cpp:1005
void setDefaultValue(const QVariant &value)
Sets the default value used for this field to value.
Definition: qsqlfield.cpp:276
The QSqlRecord class encapsulates a database record.
Definition: qsqlrecord.h:58
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
The QSqlDriver class is an abstract base class for accessing specific SQL databases.
Definition: qsqldriver.h:68
The QString class provides a Unicode character string.
Definition: qstring.h:83
bool isActive() const
Returns true if the query is active.
Definition: qsqlquery.cpp:785
#define isnan(x)
Definition: qsql_psql.cpp:64
void detectBackslashEscape()
Definition: qsql_psql.cpp:650
int at() const
Returns the current (zero-based) row position of the result.
Definition: qsqlresult.cpp:306
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
struct pg_conn PGconn
Definition: qsql_psql.h:56
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has type() ByteArray or String (converted using QS...
Definition: qvariant.cpp:2383
bool beginTransaction()
This function is called to begin a transaction.
Definition: qsql_psql.cpp:907
bool unsubscribeFromNotificationImplementation(const QString &name)
Definition: qsql_psql.cpp:1366
virtual void setAt(int at)
This function is provided for derived classes to set the internal (zero-based) row position to index...
Definition: qsqlresult.cpp:352
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
static QString translate(const char *context, const char *key, const char *disambiguation=0, Encoding encoding=CodecForTr)
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
#define QBOOLOID
Definition: qsql_psql.cpp:85
void PQfreemem(T *t, int=0)
Definition: qsql_psql.cpp:108
virtual void setLastError(const QSqlError &e)
This function is provided for derived classes to set the last error to error.
Definition: qsqlresult.cpp:417
bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const
Returns whether identifier is escaped according to the database rules.
Definition: qsqldriver.cpp:429
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
ErrorType
This enum type describes the context in which the error occurred, e.
Definition: qsqlerror.h:56
static int isinf_ld(long double x)
Definition: qsql_psql.cpp:80
void reserve(int size)
Attempts to allocate memory for at least size characters.
Definition: qstring.h:881
QPSQLDriverPrivate * d
Definition: qsql_psql.h:152
#define SIGNAL(a)
Definition: qobjectdefs.h:227
static QDateTime fromString(const QString &s, Qt::DateFormat f=Qt::TextDate)
Returns the QDateTime represented by the string, using the format given, or an invalid datetime if th...
Definition: qdatetime.cpp:3487
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QVariant handle() const
Returns the low-level database handle wrapped in a QVariant or an invalid variant if there is no hand...
Definition: qsql_psql.cpp:791
QPSQLDriverPrivate(QPSQLDriver *qq)
Definition: qsql_psql.cpp:123
void setMinimal(bool minimal)
Enables or disables minimal matching.
Definition: qregexp.cpp:4068
void qPQfreemem(void *buffer)
Definition: qsql_psql.cpp:115
The QTime class provides clock time functions.
Definition: qdatetime.h:148
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool open(const QString &db, const QString &user, const QString &password, const QString &host, int port, const QString &connOpts)
Derived classes must reimplement this pure virtual function to open a database connection on database...
Definition: qsql_psql.cpp:836
QPSQLDriver * q
Definition: qsql_psql.cpp:133
static void qDeallocatePreparedStmt(QPSQLResultPrivate *d)
Definition: qsql_psql.cpp:285
QVariant handle() const
Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVarian...
Definition: qsql_psql.cpp:314
void appendTables(QStringList &tl, QSqlQuery &t, QChar type)
Definition: qsql_psql.cpp:151
int indexIn(const QString &str, int offset=0, CaretMode caretMode=CaretAtZero) const
Attempts to find a match in str from position offset (0 by default).
Definition: qregexp.cpp:4136
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static QString qQuote(QString s)
Definition: qsql_psql.cpp:828
void virtual_hook(int id, void *data)
Definition: qsql_psql.cpp:519
#define QINT8OID
Definition: qsql_psql.cpp:86
const char * name
QPSQLDriver::Protocol getPSQLVersion()
Definition: qsql_psql.cpp:711
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
void clear()
Clears the value of the field and sets it to NULL.
Definition: qsqlfield.cpp:334
#define emit
Definition: qobjectdefs.h:76
bool rollbackTransaction()
This function is called to rollback a transaction.
Definition: qsql_psql.cpp:957
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void setLength(int fieldLength)
Sets the field&#39;s length to fieldLength.
Definition: qsqlfield.cpp:254
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
QSqlRecord record() const
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
Definition: qsql_psql.cpp:490
Q_CORE_EXPORT void qWarning(const char *,...)
#define QABSTIMEOID
Definition: qsql_psql.cpp:92
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QPSQLDriverPrivate *p, PGresult *result=0)
Definition: qsql_psql.cpp:205
static const char * data(const QByteArray &arr)
void setName(const QString &name)
Sets the name of the index to name.
Definition: qsqlindex.cpp:110
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
TableType
Definition: qsql.h:74
#define QCIDOID
Definition: qsql_psql.cpp:103
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
Definition: qstringlist.h:172
void clear()
Removes all items from the list.
Definition: qlist.h:764
QVariant lastInsertId() const
Returns the object ID of the most recent inserted row if the database supports it.
Definition: qsql_psql.cpp:480
virtual bool exec()
Executes the query, returning true if successful; otherwise returns false.
Definition: qsqlresult.cpp:675
virtual bool prepare(const QString &query)
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
Definition: qsqlresult.cpp:641
QVariant::Type type() const
Returns the field&#39;s type as stored in the database.
Definition: qsqlfield.cpp:394
static QVariant fromValue(const T &value)
Returns a QVariant containing a copy of value.
Definition: qvariant.h:336
friend class QPSQLResultPrivate
Definition: qsql_psql.h:68
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
void squeeze()
Releases any memory not required to store the character data.
Definition: qstring.h:114
virtual void virtual_hook(int id, void *data)
Definition: qsqlresult.cpp:962
struct pg_result PGresult
Definition: qsql_psql.h:57
bool fetchLast()
Positions the result to the last record (last row) in the result.
Definition: qsql_psql.cpp:348
#define Q_DECLARE_METATYPE(TYPE)
This macro makes the type Type known to QMetaType as long as it provides a public default constructor...
Definition: qmetatype.h:265
void setForwardOnly(bool forward)
Sets forward only mode to forward.
Definition: qsqlquery.cpp:835
void cleanup()
Definition: qsql_psql.cpp:319
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
static QTime fromString(const QString &s, Qt::DateFormat f=Qt::TextDate)
Returns the time represented in the string as a QTime using the format given, or an invalid time if t...
Definition: qdatetime.cpp:1928
static int isnan_ld(long double x)
Definition: qsql_psql.cpp:70
bool fetchFirst()
Positions the result to the first record (row 0) in the result.
Definition: qsql_psql.cpp:343
#define QXIDOID
Definition: qsql_psql.cpp:102
QPSQLDriver::Protocol pro
Definition: qsql_psql.cpp:136
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QDate date() const
Returns the date part of the datetime.
Definition: qdatetime.cpp:2357
static QVariant::Type qDecodePSQLType(int t)
Definition: qsql_psql.cpp:239
QString toString(Qt::DateFormat f=Qt::TextDate) const
Returns the time as a string.
Definition: qdatetime.cpp:1653
static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, bool *ok)
Definition: qvariant.cpp:627
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
Q_CORE_EXPORT void qFatal(const char *,...)
void setRequired(bool required)
Sets the required status of this field to Required if required is true; otherwise sets it to Optional...
Definition: qsqlfield.h:84
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
#define QFLOAT4OID
Definition: qsql_psql.cpp:90
QString & append(QChar c)
Definition: qstring.cpp:1777
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
static int isnan_f(float x)
Definition: qsql_psql.cpp:68
bool reset(const QString &query)
Sets the result to use the SQL statement query for subsequent data retrieval.
Definition: qsql_psql.cpp:459
#define QRELTIMEOID
Definition: qsql_psql.cpp:93
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
QPSQLResultPrivate(QPSQLResult *qq)
Definition: qsql_psql.cpp:193
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
bool prepare(const QString &query)
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
Definition: qsql_psql.cpp:584
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
bool isNull() const
Returns true if the field&#39;s value is NULL; otherwise returns false.
Definition: qsqlfield.cpp:428
bool commitTransaction()
This function is called to commit a transaction.
Definition: qsql_psql.cpp:924
virtual QString formatValue(const QSqlField &field, bool trimStrings=false) const
Returns a string representation of the field value for the database.
Definition: qsqldriver.cpp:597
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
static QDate fromString(const QString &s, Qt::DateFormat f=Qt::TextDate)
Returns the QDate represented by the string, using the format given, or an invalid date if the string...
Definition: qdatetime.cpp:1203
QSqlResult * createResult() const
Creates an empty SQL result on the database.
Definition: qsql_psql.cpp:902
double toDouble(bool *ok=0) const
Returns the string converted to a double value.
Definition: qstring.cpp:6227
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QSocketNotifier * sn
Definition: qsql_psql.cpp:137
void _q_handleNotification(int)
Definition: qsql_psql.cpp:1402
bool hasFeature(DriverFeature f) const
Returns true if the driver supports feature feature; otherwise returns false.
Definition: qsql_psql.cpp:796
#define QTIMETZOID
Definition: qsql_psql.cpp:96
void append(const QSqlField &field)
Append a copy of field field to the end of the record.
Definition: qsqlrecord.cpp:312
#define QFLOAT8OID
Definition: qsql_psql.cpp:91
bool isSelect() const
Returns true if the current result is from a SELECT statement; otherwise returns false.
Definition: qsqlresult.cpp:379
double toDouble(bool *ok=0) const
Returns the variant as a double if the variant has type() Double , QMetaType::Float ...
Definition: qvariant.cpp:2710
virtual void setActive(bool a)
This function is provided for derived classes to set the internal active state to active...
Definition: qsqlresult.cpp:402
static QString qReplacePlaceholderMarkers(const QString &query)
Definition: qsql_psql.cpp:529
#define QBYTEAOID
Definition: qsql_psql.cpp:100
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
Invokes the member (a signal or a slot name) on the object obj.
QSqlRecord record(const QString &tablename) const
Returns a QSqlRecord populated with the names of the fields in table tableName.
Definition: qsql_psql.cpp:1086
Protocol protocol() const
Definition: qsql_psql.cpp:1324
int year() const
Returns the year of this date.
Definition: qdatetime.cpp:353
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
QVariant data(int i)
Returns the data for field index in the current row as a QVariant.
Definition: qsql_psql.cpp:353
int qstrcmp(const QByteArray &str1, const char *str2)
Definition: qbytearray.cpp:336
QTime time() const
Returns the time part of the datetime.
Definition: qdatetime.cpp:2368
#define QINT2OID
Definition: qsql_psql.cpp:87
QTime toTime() const
Returns the variant as a QTime if the variant has type() Time , DateTime , or String ; otherwise retu...
Definition: qvariant.cpp:2330
The QSqlField class manipulates the fields in SQL database tables and views.
Definition: qsqlfield.h:56
#define QINT4OID
Definition: qsql_psql.cpp:88
bool exec(const QString &query)
Executes the SQL in query.
Definition: qsqlquery.cpp:355
virtual void setLastError(const QSqlError &e)
This function is used to set the value of the last error, error, that occurred on the database...
Definition: qsqldriver.cpp:350
static void qSplitTableName(QString &tablename, QString &schema)
Definition: qsql_psql.cpp:996
#define QOIDOID
Definition: qsql_psql.cpp:99
QStringList subscribedToNotificationsImplementation() const
Definition: qsql_psql.cpp:1397
QStringList seid
Definition: qsql_psql.cpp:138
QPSQLResult(const QPSQLDriver *db, const QPSQLDriverPrivate *p)
Definition: qsql_psql.cpp:296
QString stripDelimiters(const QString &identifier, IdentifierType type) const
Returns the identifier with the leading and trailing delimiters removed, identifier can either be a t...
Definition: qsqldriver.cpp:455
QVector< QVariant > & boundValues() const
Returns a vector of the result&#39;s bound values for the current record (row).
Definition: qsqlresult.cpp:859
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
QPSQLDriver(QObject *parent=0)
Definition: qsql_psql.cpp:760
void init()
Definition: qsql_psql.cpp:779
static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin)
Definition: qsql_psql.cpp:667
QStringList tables(QSql::TableType) const
Returns a list of the names of the tables in the database.
Definition: qsql_psql.cpp:974
qint64 qlonglong
Definition: qglobal.h:951
#define qPrintable(string)
Definition: qglobal.h:1750
static qreal dot(const QPointF &a, const QPointF &b)
QVariant value(int i) const
Returns the value of field index in the current record.
Definition: qsqlquery.cpp:403
PGresult * exec(const char *stmt) const
Definition: qsql_psql.cpp:175
static int isinf_f(float x)
Definition: qsql_psql.cpp:78
bool next()
Retrieves the next record in the result, if available, and positions the query on the retrieved recor...
Definition: qsqlquery.cpp:594
The QSqlResult class provides an abstract interface for accessing data from specific SQL databases...
Definition: qsqlresult.h:63
bool fetch(int i)
Positions the result to an arbitrary (zero-based) row index.
Definition: qsql_psql.cpp:329
const QPSQLDriverPrivate * driver
Definition: qsql_psql.cpp:196
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
bool exec()
Executes the query, returning true if successful; otherwise returns false.
Definition: qsql_psql.cpp:612
void close()
Derived classes must reimplement this pure virtual function in order to close the database connection...
Definition: qsql_psql.cpp:883
IdentifierType
This enum contains a list of SQL identifier types.
Definition: qsqldriver.h:83
#define QNUMERICOID
Definition: qsql_psql.cpp:89
bool isNull(int field)
Returns true if the field at position index in the current row is null; otherwise returns false...
Definition: qsql_psql.cpp:453
void setValue(const QVariant &value)
Sets the value of the field to value.
Definition: qsqlfield.cpp:320
bool isValid() const
Returns true if the time is valid; otherwise returns false.
Definition: qdatetime.cpp:1566
void setSqlType(int type)
Definition: qsqlfield.cpp:285
QString escapeIdentifier(const QString &identifier, IdentifierType type) const
Returns the identifier escaped according to the database rules.
Definition: qsql_psql.cpp:1308
int removeAll(const T &t)
Removes all occurrences of value in the list and returns the number of entries removed.
Definition: qlist.h:770
int numRowsAffected()
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
Definition: qsql_psql.cpp:475
void notification(const QString &name)
This signal is emitted when the database posts an event notification that the driver subscribes to...