Qt 4.8
qsql_db2.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_db2.h"
43 #include <qcoreapplication.h>
44 #include <qdatetime.h>
45 #include <qsqlfield.h>
46 #include <qsqlerror.h>
47 #include <qsqlindex.h>
48 #include <qsqlrecord.h>
49 #include <qstringlist.h>
50 #include <qvarlengtharray.h>
51 #include <qvector.h>
52 #include <QDebug>
53 
54 #if defined(Q_CC_BOR)
55 // DB2's sqlsystm.h (included through sqlcli1.h) defines the SQL_BIGINT_TYPE
56 // and SQL_BIGUINT_TYPE to wrong the types for Borland; so do the defines to
57 // the right type before including the header
58 #define SQL_BIGINT_TYPE qint64
59 #define SQL_BIGUINT_TYPE quint64
60 #endif
61 
62 #define UNICODE
63 
64 #include <sqlcli1.h>
65 
66 #include <string.h>
67 
69 
70 static const int COLNAMESIZE = 255;
71 static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };
72 
74 {
75 public:
77  SQLHANDLE hEnv;
78  SQLHANDLE hDbc;
80 };
81 
83 {
84 public:
85  QDB2ResultPrivate(const QDB2DriverPrivate* d): dp(d), hStmt(0)
86  {}
88  {
89  emptyValueCache();
90  }
92  {
93  for (int i = 0; i < valueCache.count(); ++i) {
94  delete valueCache[i];
95  valueCache[i] = NULL;
96  }
97  }
99  {
100  clearValueCache();
101  valueCache.clear();
102  }
103 
105  SQLHANDLE hStmt;
108 };
109 
110 static QString qFromTChar(SQLTCHAR* str)
111 {
112  return QString((const QChar *)str);
113 }
114 
115 // dangerous!! (but fast). Don't use in functions that
116 // require out parameters!
117 static SQLTCHAR* qToTChar(const QString& str)
118 {
119  return (SQLTCHAR*)str.utf16();
120 }
121 
122 static QString qWarnDB2Handle(int handleType, SQLHANDLE handle)
123 {
124  SQLINTEGER nativeCode;
125  SQLSMALLINT msgLen;
126  SQLRETURN r = SQL_ERROR;
127  SQLTCHAR state[SQL_SQLSTATE_SIZE + 1];
128  SQLTCHAR description[SQL_MAX_MESSAGE_LENGTH];
129  r = SQLGetDiagRec(handleType,
130  handle,
131  1,
132  (SQLTCHAR*) state,
133  &nativeCode,
134  (SQLTCHAR*) description,
135  SQL_MAX_MESSAGE_LENGTH - 1, /* in bytes, not in characters */
136  &msgLen);
137  if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
138  return QString(qFromTChar(description));
139  return QString();
140 }
141 
143 {
144  return (qWarnDB2Handle(SQL_HANDLE_ENV, d->hEnv) + QLatin1Char(' ')
145  + qWarnDB2Handle(SQL_HANDLE_DBC, d->hDbc));
146 }
147 
149 {
150  return (qWarnDB2Handle(SQL_HANDLE_ENV, d->dp->hEnv) + QLatin1Char(' ')
151  + qWarnDB2Handle(SQL_HANDLE_DBC, d->dp->hDbc)
152  + qWarnDB2Handle(SQL_HANDLE_STMT, d->hStmt));
153 }
154 
155 static void qSqlWarning(const QString& message, const QDB2DriverPrivate* d)
156 {
157  qWarning("%s\tError: %s", message.toLocal8Bit().constData(),
159 }
160 
161 static void qSqlWarning(const QString& message, const QDB2ResultPrivate* d)
162 {
163  qWarning("%s\tError: %s", message.toLocal8Bit().constData(),
165 }
166 
168  const QDB2DriverPrivate* p)
169 {
170  return QSqlError(QLatin1String("QDB2: ") + err, qDB2Warn(p), type);
171 }
172 
174  const QDB2ResultPrivate* p)
175 {
176  return QSqlError(QLatin1String("QDB2: ") + err, qDB2Warn(p), type);
177 }
178 
179 static QVariant::Type qDecodeDB2Type(SQLSMALLINT sqltype)
180 {
182  switch (sqltype) {
183  case SQL_REAL:
184  case SQL_FLOAT:
185  case SQL_DOUBLE:
186  case SQL_DECIMAL:
187  case SQL_NUMERIC:
188  type = QVariant::Double;
189  break;
190  case SQL_SMALLINT:
191  case SQL_INTEGER:
192  case SQL_BIT:
193  case SQL_TINYINT:
194  type = QVariant::Int;
195  break;
196  case SQL_BIGINT:
197  type = QVariant::LongLong;
198  break;
199  case SQL_BLOB:
200  case SQL_BINARY:
201  case SQL_VARBINARY:
202  case SQL_LONGVARBINARY:
203  case SQL_CLOB:
204  case SQL_DBCLOB:
205  type = QVariant::ByteArray;
206  break;
207  case SQL_DATE:
208  case SQL_TYPE_DATE:
209  type = QVariant::Date;
210  break;
211  case SQL_TIME:
212  case SQL_TYPE_TIME:
213  type = QVariant::Time;
214  break;
215  case SQL_TIMESTAMP:
216  case SQL_TYPE_TIMESTAMP:
217  type = QVariant::DateTime;
218  break;
219  case SQL_WCHAR:
220  case SQL_WVARCHAR:
221  case SQL_WLONGVARCHAR:
222  case SQL_CHAR:
223  case SQL_VARCHAR:
224  case SQL_LONGVARCHAR:
225  type = QVariant::String;
226  break;
227  default:
228  type = QVariant::ByteArray;
229  break;
230  }
231  return type;
232 }
233 
235 {
236  SQLSMALLINT colNameLen;
237  SQLSMALLINT colType;
238  SQLUINTEGER colSize;
239  SQLSMALLINT colScale;
240  SQLSMALLINT nullable;
241  SQLRETURN r = SQL_ERROR;
242  SQLTCHAR colName[COLNAMESIZE];
243  r = SQLDescribeCol(d->hStmt,
244  i+1,
245  colName,
246  (SQLSMALLINT) COLNAMESIZE,
247  &colNameLen,
248  &colType,
249  &colSize,
250  &colScale,
251  &nullable);
252 
253  if (r != SQL_SUCCESS) {
254  qSqlWarning(QString::fromLatin1("qMakeFieldInfo: Unable to describe column %1").arg(i), d);
255  return QSqlField();
256  }
257  QSqlField f(qFromTChar(colName), qDecodeDB2Type(colType));
258  // nullable can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN
259  if (nullable == SQL_NO_NULLS)
260  f.setRequired(true);
261  else if (nullable == SQL_NULLABLE)
262  f.setRequired(false);
263  // else required is unknown
264  f.setLength(colSize == 0 ? -1 : int(colSize));
265  f.setPrecision(colScale == 0 ? -1 : int(colScale));
266  f.setSqlType(int(colType));
267  return f;
268 }
269 
270 static int qGetIntData(SQLHANDLE hStmt, int column, bool& isNull)
271 {
272  SQLINTEGER intbuf;
273  isNull = false;
274  SQLINTEGER lengthIndicator = 0;
275  SQLRETURN r = SQLGetData(hStmt,
276  column + 1,
277  SQL_C_SLONG,
278  (SQLPOINTER) &intbuf,
279  0,
280  &lengthIndicator);
281  if ((r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) || lengthIndicator == SQL_NULL_DATA) {
282  isNull = true;
283  return 0;
284  }
285  return int(intbuf);
286 }
287 
288 static double qGetDoubleData(SQLHANDLE hStmt, int column, bool& isNull)
289 {
290  SQLDOUBLE dblbuf;
291  isNull = false;
292  SQLINTEGER lengthIndicator = 0;
293  SQLRETURN r = SQLGetData(hStmt,
294  column+1,
295  SQL_C_DOUBLE,
296  (SQLPOINTER) &dblbuf,
297  0,
298  &lengthIndicator);
299  if ((r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) || lengthIndicator == SQL_NULL_DATA) {
300  isNull = true;
301  return 0.0;
302  }
303 
304  return (double) dblbuf;
305 }
306 
307 static SQLBIGINT qGetBigIntData(SQLHANDLE hStmt, int column, bool& isNull)
308 {
309  SQLBIGINT lngbuf = Q_INT64_C(0);
310  isNull = false;
311  SQLINTEGER lengthIndicator = 0;
312  SQLRETURN r = SQLGetData(hStmt,
313  column+1,
314  SQL_C_SBIGINT,
315  (SQLPOINTER) &lngbuf,
316  0,
317  &lengthIndicator);
318  if ((r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) || lengthIndicator == SQL_NULL_DATA)
319  isNull = true;
320 
321  return lngbuf;
322 }
323 
324 static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool& isNull)
325 {
326  QString fieldVal;
327  SQLRETURN r = SQL_ERROR;
328  SQLINTEGER lengthIndicator = 0;
329 
330  if (colSize <= 0)
331  colSize = 255;
332  else if (colSize > 65536) // limit buffer size to 64 KB
333  colSize = 65536;
334  else
335  colSize++; // make sure there is room for more than the 0 termination
336  SQLTCHAR* buf = new SQLTCHAR[colSize];
337 
338  while (true) {
339  r = SQLGetData(hStmt,
340  column + 1,
341  SQL_C_WCHAR,
342  (SQLPOINTER)buf,
343  colSize * sizeof(SQLTCHAR),
344  &lengthIndicator);
345  if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
346  if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
347  fieldVal.clear();
348  isNull = true;
349  break;
350  }
351  fieldVal += qFromTChar(buf);
352  } else if (r == SQL_NO_DATA) {
353  break;
354  } else {
355  qWarning("qGetStringData: Error while fetching data (%d)", r);
356  fieldVal.clear();
357  break;
358  }
359  }
360  delete[] buf;
361  return fieldVal;
362 }
363 
364 static QByteArray qGetBinaryData(SQLHANDLE hStmt, int column, SQLINTEGER& lengthIndicator, bool& isNull)
365 {
366  QByteArray fieldVal;
367  SQLSMALLINT colNameLen;
368  SQLSMALLINT colType;
369  SQLUINTEGER colSize;
370  SQLSMALLINT colScale;
371  SQLSMALLINT nullable;
372  SQLRETURN r = SQL_ERROR;
373 
374  SQLTCHAR colName[COLNAMESIZE];
375  r = SQLDescribeCol(hStmt,
376  column+1,
377  colName,
378  COLNAMESIZE,
379  &colNameLen,
380  &colType,
381  &colSize,
382  &colScale,
383  &nullable);
384  if (r != SQL_SUCCESS)
385  qWarning("qGetBinaryData: Unable to describe column %d", column);
386  // SQLDescribeCol may return 0 if size cannot be determined
387  if (!colSize)
388  colSize = 255;
389  else if (colSize > 65536) // read the field in 64 KB chunks
390  colSize = 65536;
391  char * buf = new char[colSize];
392  while (true) {
393  r = SQLGetData(hStmt,
394  column+1,
395  colType == SQL_DBCLOB ? SQL_C_CHAR : SQL_C_BINARY,
396  (SQLPOINTER) buf,
397  colSize,
398  &lengthIndicator);
399  if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
400  if (lengthIndicator == SQL_NULL_DATA) {
401  isNull = true;
402  break;
403  } else {
404  int rSize;
405  r == SQL_SUCCESS ? rSize = lengthIndicator : rSize = colSize;
406  if (lengthIndicator == SQL_NO_TOTAL) // size cannot be determined
407  rSize = colSize;
408  fieldVal.append(QByteArray(buf, rSize));
409  if (r == SQL_SUCCESS) // the whole field was read in one chunk
410  break;
411  }
412  } else {
413  break;
414  }
415  }
416  delete [] buf;
417  return fieldVal;
418 }
419 
420 static void qSplitTableQualifier(const QString & qualifier, QString * catalog,
421  QString * schema, QString * table)
422 {
423  if (!catalog || !schema || !table)
424  return;
425  QStringList l = qualifier.split(QLatin1Char('.'));
426  if (l.count() > 3)
427  return; // can't possibly be a valid table qualifier
428  int i = 0, n = l.count();
429  if (n == 1) {
430  *table = qualifier;
431  } else {
432  for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
433  if (n == 3) {
434  if (i == 0)
435  *catalog = *it;
436  else if (i == 1)
437  *schema = *it;
438  else if (i == 2)
439  *table = *it;
440  } else if (n == 2) {
441  if (i == 0)
442  *schema = *it;
443  else if (i == 1)
444  *table = *it;
445  }
446  i++;
447  }
448  }
449 }
450 
451 // creates a QSqlField from a valid hStmt generated
452 // by SQLColumns. The hStmt has to point to a valid position.
453 static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt)
454 {
455  bool isNull;
456  int type = qGetIntData(hStmt, 4, isNull);
457  QSqlField f(qGetStringData(hStmt, 3, -1, isNull), qDecodeDB2Type(type));
458  int required = qGetIntData(hStmt, 10, isNull); // nullable-flag
459  // required can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN
460  if (required == SQL_NO_NULLS)
461  f.setRequired(true);
462  else if (required == SQL_NULLABLE)
463  f.setRequired(false);
464  // else we don't know.
465  f.setLength(qGetIntData(hStmt, 6, isNull)); // column size
466  f.setPrecision(qGetIntData(hStmt, 8, isNull)); // precision
467  f.setSqlType(type);
468  return f;
469 }
470 
471 static bool qMakeStatement(QDB2ResultPrivate* d, bool forwardOnly, bool setForwardOnly = true)
472 {
473  SQLRETURN r;
474  if (!d->hStmt) {
475  r = SQLAllocHandle(SQL_HANDLE_STMT,
476  d->dp->hDbc,
477  &d->hStmt);
478  if (r != SQL_SUCCESS) {
479  qSqlWarning(QLatin1String("QDB2Result::reset: Unable to allocate statement handle"), d);
480  return false;
481  }
482  } else {
483  r = SQLFreeStmt(d->hStmt, SQL_CLOSE);
484  if (r != SQL_SUCCESS) {
485  qSqlWarning(QLatin1String("QDB2Result::reset: Unable to close statement handle"), d);
486  return false;
487  }
488  }
489 
490  if (!setForwardOnly)
491  return true;
492 
493  if (forwardOnly) {
494  r = SQLSetStmtAttr(d->hStmt,
495  SQL_ATTR_CURSOR_TYPE,
496  (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY,
497  SQL_IS_UINTEGER);
498  } else {
499  r = SQLSetStmtAttr(d->hStmt,
500  SQL_ATTR_CURSOR_TYPE,
501  (SQLPOINTER) SQL_CURSOR_STATIC,
502  SQL_IS_UINTEGER);
503  }
504  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
505  qSqlWarning(QString::fromLatin1("QDB2Result::reset: Unable to set %1 attribute.").arg(
506  forwardOnly ? QLatin1String("SQL_CURSOR_FORWARD_ONLY")
507  : QLatin1String("SQL_CURSOR_STATIC")), d);
508  return false;
509  }
510  return true;
511 }
512 
514 {
515  return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hStmt);
516 }
517 
518 /************************************/
519 
521  : QSqlResult(dr)
522 {
523  d = new QDB2ResultPrivate(dp);
524 }
525 
527 {
528  if (d->hStmt) {
529  SQLRETURN r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt);
530  if (r != SQL_SUCCESS)
531  qSqlWarning(QLatin1String("QDB2Driver: Unable to free statement handle ")
532  + QString::number(r), d);
533  }
534  delete d;
535 }
536 
537 bool QDB2Result::reset (const QString& query)
538 {
539  setActive(false);
541  SQLRETURN r;
542 
543  d->recInf.clear();
544  d->emptyValueCache();
545 
546  if (!qMakeStatement(d, isForwardOnly()))
547  return false;
548 
549  r = SQLExecDirect(d->hStmt,
550  qToTChar(query),
551  (SQLINTEGER) query.length());
552  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
554  "Unable to execute statement"), QSqlError::StatementError, d));
555  return false;
556  }
557  SQLSMALLINT count;
558  r = SQLNumResultCols(d->hStmt, &count);
559  if (count) {
560  setSelect(true);
561  for (int i = 0; i < count; ++i) {
563  }
564  } else {
565  setSelect(false);
566  }
567  d->valueCache.resize(count);
568  d->valueCache.fill(NULL);
569  setActive(true);
570  return true;
571 }
572 
573 bool QDB2Result::prepare(const QString& query)
574 {
575  setActive(false);
577  SQLRETURN r;
578 
579  d->recInf.clear();
580  d->emptyValueCache();
581 
582  if (!qMakeStatement(d, isForwardOnly()))
583  return false;
584 
585  r = SQLPrepare(d->hStmt,
586  qToTChar(query),
587  (SQLINTEGER) query.length());
588 
589  if (r != SQL_SUCCESS) {
591  "Unable to prepare statement"), QSqlError::StatementError, d));
592  return false;
593  }
594  return true;
595 }
596 
598 {
599  QList<QByteArray> tmpStorage; // holds temporary ptrs
600  QVarLengthArray<SQLINTEGER, 32> indicators(boundValues().count());
601 
602  memset(indicators.data(), 0, indicators.size() * sizeof(SQLINTEGER));
603  setActive(false);
605  SQLRETURN r;
606 
607  d->recInf.clear();
608  d->emptyValueCache();
609 
610  if (!qMakeStatement(d, isForwardOnly(), false))
611  return false;
612 
613 
615  int i;
616  for (i = 0; i < values.count(); ++i) {
617  // bind parameters - only positional binding allowed
618  SQLINTEGER *ind = &indicators[i];
619  if (values.at(i).isNull())
620  *ind = SQL_NULL_DATA;
621  if (bindValueType(i) & QSql::Out)
622  values[i].detach();
623 
624  switch (values.at(i).type()) {
625  case QVariant::Date: {
626  QByteArray ba;
627  ba.resize(sizeof(DATE_STRUCT));
628  DATE_STRUCT *dt = (DATE_STRUCT *)ba.constData();
629  QDate qdt = values.at(i).toDate();
630  dt->year = qdt.year();
631  dt->month = qdt.month();
632  dt->day = qdt.day();
633  r = SQLBindParameter(d->hStmt,
634  i + 1,
635  qParamType[(QFlag)(bindValueType(i)) & 3],
636  SQL_C_DATE,
637  SQL_DATE,
638  0,
639  0,
640  (void *) dt,
641  0,
642  *ind == SQL_NULL_DATA ? ind : NULL);
643  tmpStorage.append(ba);
644  break; }
645  case QVariant::Time: {
646  QByteArray ba;
647  ba.resize(sizeof(TIME_STRUCT));
648  TIME_STRUCT *dt = (TIME_STRUCT *)ba.constData();
649  QTime qdt = values.at(i).toTime();
650  dt->hour = qdt.hour();
651  dt->minute = qdt.minute();
652  dt->second = qdt.second();
653  r = SQLBindParameter(d->hStmt,
654  i + 1,
655  qParamType[(QFlag)(bindValueType(i)) & 3],
656  SQL_C_TIME,
657  SQL_TIME,
658  0,
659  0,
660  (void *) dt,
661  0,
662  *ind == SQL_NULL_DATA ? ind : NULL);
663  tmpStorage.append(ba);
664  break; }
665  case QVariant::DateTime: {
666  QByteArray ba;
667  ba.resize(sizeof(TIMESTAMP_STRUCT));
668  TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)ba.constData();
669  QDateTime qdt = values.at(i).toDateTime();
670  dt->year = qdt.date().year();
671  dt->month = qdt.date().month();
672  dt->day = qdt.date().day();
673  dt->hour = qdt.time().hour();
674  dt->minute = qdt.time().minute();
675  dt->second = qdt.time().second();
676  dt->fraction = qdt.time().msec() * 1000000;
677  r = SQLBindParameter(d->hStmt,
678  i + 1,
679  qParamType[(QFlag)(bindValueType(i)) & 3],
680  SQL_C_TIMESTAMP,
681  SQL_TIMESTAMP,
682  0,
683  0,
684  (void *) dt,
685  0,
686  *ind == SQL_NULL_DATA ? ind : NULL);
687  tmpStorage.append(ba);
688  break; }
689  case QVariant::Int:
690  r = SQLBindParameter(d->hStmt,
691  i + 1,
692  qParamType[(QFlag)(bindValueType(i)) & 3],
693  SQL_C_SLONG,
694  SQL_INTEGER,
695  0,
696  0,
697  (void *)values.at(i).constData(),
698  0,
699  *ind == SQL_NULL_DATA ? ind : NULL);
700  break;
701  case QVariant::Double:
702  r = SQLBindParameter(d->hStmt,
703  i + 1,
704  qParamType[(QFlag)(bindValueType(i)) & 3],
705  SQL_C_DOUBLE,
706  SQL_DOUBLE,
707  0,
708  0,
709  (void *)values.at(i).constData(),
710  0,
711  *ind == SQL_NULL_DATA ? ind : NULL);
712  break;
713  case QVariant::ByteArray: {
714  int len = values.at(i).toByteArray().size();
715  if (*ind != SQL_NULL_DATA)
716  *ind = len;
717  r = SQLBindParameter(d->hStmt,
718  i + 1,
719  qParamType[(QFlag)(bindValueType(i)) & 3],
720  SQL_C_BINARY,
721  SQL_LONGVARBINARY,
722  len,
723  0,
724  (void *)values.at(i).toByteArray().constData(),
725  len,
726  ind);
727  break; }
728  case QVariant::String:
729  {
730  QString str(values.at(i).toString());
731  if (*ind != SQL_NULL_DATA)
732  *ind = str.length() * sizeof(QChar);
733  if (bindValueType(i) & QSql::Out) {
734  QByteArray ba((char*)str.utf16(), str.capacity() * sizeof(QChar));
735  r = SQLBindParameter(d->hStmt,
736  i + 1,
737  qParamType[(QFlag)(bindValueType(i)) & 3],
738  SQL_C_WCHAR,
739  SQL_WVARCHAR,
740  str.length(),
741  0,
742  (void *)ba.constData(),
743  ba.size(),
744  ind);
745  tmpStorage.append(ba);
746  } else {
747  void *data = (void*)str.utf16();
748  int len = str.length();
749  r = SQLBindParameter(d->hStmt,
750  i + 1,
751  qParamType[(QFlag)(bindValueType(i)) & 3],
752  SQL_C_WCHAR,
753  SQL_WVARCHAR,
754  len,
755  0,
756  data,
757  len * sizeof(QChar),
758  ind);
759  }
760  break;
761  }
762  default: {
763  QByteArray ba = values.at(i).toString().toAscii();
764  int len = ba.length() + 1;
765  if (*ind != SQL_NULL_DATA)
766  *ind = ba.length();
767  r = SQLBindParameter(d->hStmt,
768  i + 1,
769  qParamType[(QFlag)(bindValueType(i)) & 3],
770  SQL_C_CHAR,
771  SQL_VARCHAR,
772  len,
773  0,
774  (void *) ba.constData(),
775  len,
776  ind);
777  tmpStorage.append(ba);
778  break; }
779  }
780  if (r != SQL_SUCCESS) {
781  qWarning("QDB2Result::exec: unable to bind variable: %s",
782  qDB2Warn(d).toLocal8Bit().constData());
784  "Unable to bind variable"), QSqlError::StatementError, d));
785  return false;
786  }
787  }
788 
789  r = SQLExecute(d->hStmt);
790  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
791  qWarning("QDB2Result::exec: Unable to execute statement: %s",
792  qDB2Warn(d).toLocal8Bit().constData());
794  "Unable to execute statement"), QSqlError::StatementError, d));
795  return false;
796  }
797  SQLSMALLINT count;
798  r = SQLNumResultCols(d->hStmt, &count);
799  if (count) {
800  setSelect(true);
801  for (int i = 0; i < count; ++i) {
803  }
804  } else {
805  setSelect(false);
806  }
807  setActive(true);
808  d->valueCache.resize(count);
809  d->valueCache.fill(NULL);
810 
811  //get out parameters
812  if (!hasOutValues())
813  return true;
814 
815  for (i = 0; i < values.count(); ++i) {
816  switch (values[i].type()) {
817  case QVariant::Date: {
818  DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.takeFirst().constData());
819  values[i] = QVariant(QDate(ds.year, ds.month, ds.day));
820  break; }
821  case QVariant::Time: {
822  TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.takeFirst().constData());
823  values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second));
824  break; }
825  case QVariant::DateTime: {
826  TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT *)tmpStorage.takeFirst().constData());
827  values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day),
828  QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
829  break; }
830  case QVariant::Int:
831  case QVariant::Double:
832  case QVariant::ByteArray:
833  break;
834  case QVariant::String:
835  if (bindValueType(i) & QSql::Out)
836  values[i] = QString((const QChar *)tmpStorage.takeFirst().constData());
837  break;
838  default: {
839  values[i] = QString::fromAscii(tmpStorage.takeFirst().constData());
840  break; }
841  }
842  if (indicators[i] == SQL_NULL_DATA)
843  values[i] = QVariant(values[i].type());
844  }
845  return true;
846 }
847 
848 bool QDB2Result::fetch(int i)
849 {
850  if (isForwardOnly() && i < at())
851  return false;
852  if (i == at())
853  return true;
854  d->clearValueCache();
855  int actualIdx = i + 1;
856  if (actualIdx <= 0) {
858  return false;
859  }
860  SQLRETURN r;
861  if (isForwardOnly()) {
862  bool ok = true;
863  while (ok && i > at())
864  ok = fetchNext();
865  return ok;
866  } else {
867  r = SQLFetchScroll(d->hStmt,
868  SQL_FETCH_ABSOLUTE,
869  actualIdx);
870  }
871  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r != SQL_NO_DATA) {
873  "Unable to fetch record %1").arg(i), QSqlError::StatementError, d));
874  return false;
875  }
876  else if (r == SQL_NO_DATA)
877  return false;
878  setAt(i);
879  return true;
880 }
881 
883 {
884  SQLRETURN r;
885  d->clearValueCache();
886  r = SQLFetchScroll(d->hStmt,
887  SQL_FETCH_NEXT,
888  0);
889  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
890  if (r != SQL_NO_DATA)
892  "Unable to fetch next"), QSqlError::StatementError, d));
893  return false;
894  }
895  setAt(at() + 1);
896  return true;
897 }
898 
900 {
901  if (isForwardOnly() && at() != QSql::BeforeFirstRow)
902  return false;
903  if (isForwardOnly())
904  return fetchNext();
905  d->clearValueCache();
906  SQLRETURN r;
907  r = SQLFetchScroll(d->hStmt,
908  SQL_FETCH_FIRST,
909  0);
910  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
911  if(r!= SQL_NO_DATA)
912  setLastError(qMakeError(QCoreApplication::translate("QDB2Result", "Unable to fetch first"),
914  return false;
915  }
916  setAt(0);
917  return true;
918 }
919 
921 {
922  d->clearValueCache();
923 
924  int i = at();
925  if (i == QSql::AfterLastRow) {
926  if (isForwardOnly()) {
927  return false;
928  } else {
929  if (!fetch(0))
930  return false;
931  i = at();
932  }
933  }
934 
935  while (fetchNext())
936  ++i;
937 
938  if (i == QSql::BeforeFirstRow) {
940  return false;
941  }
942 
943  if (!isForwardOnly())
944  return fetch(i);
945 
946  setAt(i);
947  return true;
948 }
949 
950 
952 {
953  if (field >= d->recInf.count()) {
954  qWarning("QDB2Result::data: column %d out of range", field);
955  return QVariant();
956  }
957  SQLRETURN r = 0;
958  SQLINTEGER lengthIndicator = 0;
959  bool isNull = false;
960  const QSqlField info = d->recInf.field(field);
961 
962  if (!info.isValid() || field >= d->valueCache.size())
963  return QVariant();
964 
965  if (d->valueCache[field])
966  return *d->valueCache[field];
967 
968 
969  QVariant* v = 0;
970  switch (info.type()) {
971  case QVariant::LongLong:
972  v = new QVariant((qint64) qGetBigIntData(d->hStmt, field, isNull));
973  break;
974  case QVariant::Int:
975  v = new QVariant(qGetIntData(d->hStmt, field, isNull));
976  break;
977  case QVariant::Date: {
978  DATE_STRUCT dbuf;
979  r = SQLGetData(d->hStmt,
980  field + 1,
981  SQL_C_DATE,
982  (SQLPOINTER) &dbuf,
983  0,
984  &lengthIndicator);
985  if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) {
986  v = new QVariant(QDate(dbuf.year, dbuf.month, dbuf.day));
987  } else {
988  v = new QVariant(QDate());
989  isNull = true;
990  }
991  break; }
992  case QVariant::Time: {
993  TIME_STRUCT tbuf;
994  r = SQLGetData(d->hStmt,
995  field + 1,
996  SQL_C_TIME,
997  (SQLPOINTER) &tbuf,
998  0,
999  &lengthIndicator);
1000  if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) {
1001  v = new QVariant(QTime(tbuf.hour, tbuf.minute, tbuf.second));
1002  } else {
1003  v = new QVariant(QTime());
1004  isNull = true;
1005  }
1006  break; }
1007  case QVariant::DateTime: {
1008  TIMESTAMP_STRUCT dtbuf;
1009  r = SQLGetData(d->hStmt,
1010  field + 1,
1011  SQL_C_TIMESTAMP,
1012  (SQLPOINTER) &dtbuf,
1013  0,
1014  &lengthIndicator);
1015  if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) {
1016  v = new QVariant(QDateTime(QDate(dtbuf.year, dtbuf.month, dtbuf.day),
1017  QTime(dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000)));
1018  } else {
1019  v = new QVariant(QDateTime());
1020  isNull = true;
1021  }
1022  break; }
1023  case QVariant::ByteArray:
1024  v = new QVariant(qGetBinaryData(d->hStmt, field, lengthIndicator, isNull));
1025  break;
1026  case QVariant::Double:
1027  {
1028  switch(numericalPrecisionPolicy()) {
1030  v = new QVariant(qGetIntData(d->hStmt, field, isNull));
1031  break;
1033  v = new QVariant((qint64) qGetBigIntData(d->hStmt, field, isNull));
1034  break;
1036  v = new QVariant(qGetDoubleData(d->hStmt, field, isNull));
1037  break;
1038  case QSql::HighPrecision:
1039  default:
1040  // length + 1 for the comma
1041  v = new QVariant(qGetStringData(d->hStmt, field, info.length() + 1, isNull));
1042  break;
1043  }
1044  break;
1045  }
1046  case QVariant::String:
1047  default:
1048  v = new QVariant(qGetStringData(d->hStmt, field, info.length(), isNull));
1049  break;
1050  }
1051  if (isNull)
1052  *v = QVariant(info.type());
1053  d->valueCache[field] = v;
1054  return *v;
1055 }
1056 
1058 {
1059  if (i >= d->valueCache.size())
1060  return true;
1061 
1062  if (d->valueCache[i])
1063  return d->valueCache[i]->isNull();
1064  return data(i).isNull();
1065 }
1066 
1068 {
1069  SQLINTEGER affectedRowCount = 0;
1070  SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount);
1071  if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
1072  return affectedRowCount;
1073  else
1074  qSqlWarning(QLatin1String("QDB2Result::numRowsAffected: Unable to count affected rows"), d);
1075  return -1;
1076 }
1077 
1079 {
1080  return -1;
1081 }
1082 
1084 {
1085  if (isActive())
1086  return d->recInf;
1087  return QSqlRecord();
1088 }
1089 
1091 {
1092  setActive(false);
1094  d->recInf.clear();
1095  d->emptyValueCache();
1096  setSelect(false);
1097 
1098  SQLRETURN r = SQLMoreResults(d->hStmt);
1099  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1100  if (r != SQL_NO_DATA) {
1102  "Unable to fetch last"), QSqlError::ConnectionError, d));
1103  }
1104  return false;
1105  }
1106 
1107  SQLSMALLINT fieldCount;
1108  r = SQLNumResultCols(d->hStmt, &fieldCount);
1109  setSelect(fieldCount > 0);
1110  for (int i = 0; i < fieldCount; ++i)
1111  d->recInf.append(qMakeFieldInfo(d, i));
1112 
1113  d->valueCache.resize(fieldCount);
1114  d->valueCache.fill(NULL);
1115  setActive(true);
1116 
1117  return true;
1118 }
1119 
1120 void QDB2Result::virtual_hook(int id, void *data)
1121 {
1122  switch (id) {
1124  Q_ASSERT(data);
1125  *static_cast<bool*>(data) = nextResult();
1126  break;
1128  if (d->hStmt)
1129  SQLCloseCursor(d->hStmt);
1130  break;
1131  default:
1132  QSqlResult::virtual_hook(id, data);
1133  }
1134 }
1135 
1136 /************************************/
1137 
1139  : QSqlDriver(parent)
1140 {
1141  d = new QDB2DriverPrivate;
1142 }
1143 
1145  : QSqlDriver(parent)
1146 {
1147  d = new QDB2DriverPrivate;
1148  d->hEnv = (SQLHANDLE)env;
1149  d->hDbc = (SQLHANDLE)con;
1150  if (env && con) {
1151  setOpen(true);
1152  setOpenError(false);
1153  }
1154 }
1155 
1157 {
1158  close();
1159  delete d;
1160 }
1161 
1162 bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString& host, int port,
1163  const QString& connOpts)
1164 {
1165  if (isOpen())
1166  close();
1167  SQLRETURN r;
1168  r = SQLAllocHandle(SQL_HANDLE_ENV,
1169  SQL_NULL_HANDLE,
1170  &d->hEnv);
1171  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1172  qSqlWarning(QLatin1String("QDB2Driver::open: Unable to allocate environment"), d);
1173  setOpenError(true);
1174  return false;
1175  }
1176 
1177  r = SQLAllocHandle(SQL_HANDLE_DBC,
1178  d->hEnv,
1179  &d->hDbc);
1180  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1181  qSqlWarning(QLatin1String("QDB2Driver::open: Unable to allocate connection"), d);
1182  setOpenError(true);
1183  return false;
1184  }
1185 
1186  QString protocol;
1187  // Set connection attributes
1188  const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
1189  for (int i = 0; i < opts.count(); ++i) {
1190  const QString tmp(opts.at(i));
1191  int idx;
1192  if ((idx = tmp.indexOf(QLatin1Char('='))) == -1) {
1193  qWarning("QDB2Driver::open: Illegal connect option value '%s'",
1194  tmp.toLocal8Bit().constData());
1195  continue;
1196  }
1197 
1198  const QString opt(tmp.left(idx));
1199  const QString val(tmp.mid(idx + 1).simplified());
1200 
1201  SQLUINTEGER v = 0;
1202  r = SQL_SUCCESS;
1203  if (opt == QLatin1String("SQL_ATTR_ACCESS_MODE")) {
1204  if (val == QLatin1String("SQL_MODE_READ_ONLY")) {
1205  v = SQL_MODE_READ_ONLY;
1206  } else if (val == QLatin1String("SQL_MODE_READ_WRITE")) {
1207  v = SQL_MODE_READ_WRITE;
1208  } else {
1209  qWarning("QDB2Driver::open: Unknown option value '%s'",
1210  tmp.toLocal8Bit().constData());
1211  continue;
1212  }
1213  r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER) v, 0);
1214  } else if (opt == QLatin1String("SQL_ATTR_LOGIN_TIMEOUT")) {
1215  v = val.toUInt();
1216  r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) v, 0);
1217  } else if (opt.compare(QLatin1String("PROTOCOL"), Qt::CaseInsensitive) == 0) {
1218  protocol = tmp;
1219  }
1220  else {
1221  qWarning("QDB2Driver::open: Unknown connection attribute '%s'",
1222  tmp.toLocal8Bit().constData());
1223  }
1224  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)
1225  qSqlWarning(QString::fromLatin1("QDB2Driver::open: "
1226  "Unable to set connection attribute '%1'").arg(opt), d);
1227  }
1228 
1229  if (protocol.isEmpty())
1230  protocol = QLatin1String("PROTOCOL=TCPIP");
1231 
1232  if (port < 0 )
1233  port = 50000;
1234 
1235  QString connQStr;
1236  connQStr = protocol + QLatin1String(";DATABASE=") + db + QLatin1String(";HOSTNAME=") + host
1237  + QLatin1String(";PORT=") + QString::number(port) + QLatin1String(";UID=") + user
1238  + QLatin1String(";PWD=") + password;
1239 
1240 
1241  SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH];
1242  SQLSMALLINT cb;
1243 
1244  r = SQLDriverConnect(d->hDbc,
1245  NULL,
1246  qToTChar(connQStr),
1247  (SQLSMALLINT) connQStr.length(),
1248  connOut,
1249  SQL_MAX_OPTION_STRING_LENGTH,
1250  &cb,
1251  SQL_DRIVER_NOPROMPT);
1252  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1253  setLastError(qMakeError(tr("Unable to connect"),
1255  setOpenError(true);
1256  return false;
1257  }
1258 
1259  d->user = user;
1260  setOpen(true);
1261  setOpenError(false);
1262  return true;
1263 }
1264 
1266 {
1267  SQLRETURN r;
1268  if (d->hDbc) {
1269  // Open statements/descriptors handles are automatically cleaned up by SQLDisconnect
1270  if (isOpen()) {
1271  r = SQLDisconnect(d->hDbc);
1272  if (r != SQL_SUCCESS)
1273  qSqlWarning(QLatin1String("QDB2Driver::close: Unable to disconnect datasource"), d);
1274  }
1275  r = SQLFreeHandle(SQL_HANDLE_DBC, d->hDbc);
1276  if (r != SQL_SUCCESS)
1277  qSqlWarning(QLatin1String("QDB2Driver::close: Unable to free connection handle"), d);
1278  d->hDbc = 0;
1279  }
1280 
1281  if (d->hEnv) {
1282  r = SQLFreeHandle(SQL_HANDLE_ENV, d->hEnv);
1283  if (r != SQL_SUCCESS)
1284  qSqlWarning(QLatin1String("QDB2Driver::close: Unable to free environment handle"), d);
1285  d->hEnv = 0;
1286  }
1287  setOpen(false);
1288  setOpenError(false);
1289 }
1290 
1292 {
1293  return new QDB2Result(this, d);
1294 }
1295 
1296 QSqlRecord QDB2Driver::record(const QString& tableName) const
1297 {
1298  QSqlRecord fil;
1299  if (!isOpen())
1300  return fil;
1301 
1302  SQLHANDLE hStmt;
1303  QString catalog, schema, table;
1304  qSplitTableQualifier(tableName, &catalog, &schema, &table);
1305  if (schema.isEmpty())
1306  schema = d->user;
1307 
1309  catalog = stripDelimiters(catalog, QSqlDriver::TableName);
1310  else
1311  catalog = catalog.toUpper();
1312 
1314  schema = stripDelimiters(schema, QSqlDriver::TableName);
1315  else
1316  schema = schema.toUpper();
1317 
1319  table = stripDelimiters(table, QSqlDriver::TableName);
1320  else
1321  table = table.toUpper();
1322 
1323  SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
1324  d->hDbc,
1325  &hStmt);
1326  if (r != SQL_SUCCESS) {
1327  qSqlWarning(QLatin1String("QDB2Driver::record: Unable to allocate handle"), d);
1328  return fil;
1329  }
1330 
1331  r = SQLSetStmtAttr(hStmt,
1332  SQL_ATTR_CURSOR_TYPE,
1333  (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY,
1334  SQL_IS_UINTEGER);
1335 
1336 
1337  //Aside: szSchemaName and szTableName parameters of SQLColumns
1338  //are case sensitive search patterns, so no escaping is used.
1339  r = SQLColumns(hStmt,
1340  NULL,
1341  0,
1342  qToTChar(schema),
1343  schema.length(),
1344  qToTChar(table),
1345  table.length(),
1346  NULL,
1347  0);
1348 
1349  if (r != SQL_SUCCESS)
1350  qSqlWarning(QLatin1String("QDB2Driver::record: Unable to execute column list"), d);
1351  r = SQLFetchScroll(hStmt,
1352  SQL_FETCH_NEXT,
1353  0);
1354  while (r == SQL_SUCCESS) {
1355  fil.append(qMakeFieldInfo(hStmt));
1356  r = SQLFetchScroll(hStmt,
1357  SQL_FETCH_NEXT,
1358  0);
1359  }
1360 
1361  r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
1362  if (r != SQL_SUCCESS)
1363  qSqlWarning(QLatin1String("QDB2Driver: Unable to free statement handle ")
1364  + QString::number(r), d);
1365 
1366  return fil;
1367 }
1368 
1370 {
1371  QStringList tl;
1372  if (!isOpen())
1373  return tl;
1374 
1375  SQLHANDLE hStmt;
1376 
1377  SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
1378  d->hDbc,
1379  &hStmt);
1380  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
1381  qSqlWarning(QLatin1String("QDB2Driver::tables: Unable to allocate handle"), d);
1382  return tl;
1383  }
1384  r = SQLSetStmtAttr(hStmt,
1385  SQL_ATTR_CURSOR_TYPE,
1386  (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
1387  SQL_IS_UINTEGER);
1388 
1389  QString tableType;
1390  if (type & QSql::Tables)
1391  tableType += QLatin1String("TABLE,");
1392  if (type & QSql::Views)
1393  tableType += QLatin1String("VIEW,");
1394  if (type & QSql::SystemTables)
1395  tableType += QLatin1String("SYSTEM TABLE,");
1396  if (tableType.isEmpty())
1397  return tl;
1398  tableType.chop(1);
1399 
1400  r = SQLTables(hStmt,
1401  NULL,
1402  0,
1403  NULL,
1404  0,
1405  NULL,
1406  0,
1407  qToTChar(tableType),
1408  tableType.length());
1409 
1410  if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)
1411  qSqlWarning(QLatin1String("QDB2Driver::tables: Unable to execute table list"), d);
1412  r = SQLFetchScroll(hStmt,
1413  SQL_FETCH_NEXT,
1414  0);
1415  while (r == SQL_SUCCESS) {
1416  bool isNull;
1417  QString fieldVal = qGetStringData(hStmt, 2, -1, isNull);
1418  QString userVal = qGetStringData(hStmt, 1, -1, isNull);
1419  QString user = d->user;
1421  user = stripDelimiters(user, QSqlDriver::TableName);
1422  else
1423  user = user.toUpper();
1424 
1425  if (userVal != user)
1426  fieldVal = userVal + QLatin1Char('.') + fieldVal;
1427  tl.append(fieldVal);
1428  r = SQLFetchScroll(hStmt,
1429  SQL_FETCH_NEXT,
1430  0);
1431  }
1432 
1433  r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
1434  if (r != SQL_SUCCESS)
1435  qSqlWarning(QLatin1String("QDB2Driver::tables: Unable to free statement handle ")
1436  + QString::number(r), d);
1437  return tl;
1438 }
1439 
1441 {
1442  QSqlIndex index(tablename);
1443  if (!isOpen())
1444  return index;
1445  QSqlRecord rec = record(tablename);
1446 
1447  SQLHANDLE hStmt;
1448  SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
1449  d->hDbc,
1450  &hStmt);
1451  if (r != SQL_SUCCESS) {
1452  qSqlWarning(QLatin1String("QDB2Driver::primaryIndex: Unable to list primary key"), d);
1453  return index;
1454  }
1455  QString catalog, schema, table;
1456  qSplitTableQualifier(tablename, &catalog, &schema, &table);
1457 
1459  catalog = stripDelimiters(catalog, QSqlDriver::TableName);
1460  else
1461  catalog = catalog.toUpper();
1462 
1464  schema = stripDelimiters(schema, QSqlDriver::TableName);
1465  else
1466  schema = schema.toUpper();
1467 
1469  table = stripDelimiters(table, QSqlDriver::TableName);
1470  else
1471  table = table.toUpper();
1472 
1473  r = SQLSetStmtAttr(hStmt,
1474  SQL_ATTR_CURSOR_TYPE,
1475  (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
1476  SQL_IS_UINTEGER);
1477 
1478  r = SQLPrimaryKeys(hStmt,
1479  NULL,
1480  0,
1481  qToTChar(schema),
1482  schema.length(),
1483  qToTChar(table),
1484  table.length());
1485  r = SQLFetchScroll(hStmt,
1486  SQL_FETCH_NEXT,
1487  0);
1488 
1489  bool isNull;
1490  QString cName, idxName;
1491  // Store all fields in a StringList because the driver can't detail fields in this FETCH loop
1492  while (r == SQL_SUCCESS) {
1493  cName = qGetStringData(hStmt, 3, -1, isNull); // column name
1494  idxName = qGetStringData(hStmt, 5, -1, isNull); // pk index name
1495  index.append(rec.field(cName));
1496  index.setName(idxName);
1497  r = SQLFetchScroll(hStmt,
1498  SQL_FETCH_NEXT,
1499  0);
1500  }
1501  r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
1502  if (r!= SQL_SUCCESS)
1503  qSqlWarning(QLatin1String("QDB2Driver: Unable to free statement handle ")
1504  + QString::number(r), d);
1505  return index;
1506 }
1507 
1509 {
1510  switch (f) {
1511  case QuerySize:
1512  case NamedPlaceholders:
1513  case BatchOperations:
1514  case LastInsertId:
1515  case SimpleLocking:
1516  case EventNotifications:
1517  return false;
1518  case BLOB:
1519  case Transactions:
1520  case MultipleResultSets:
1521  case PreparedQueries:
1523  case LowPrecisionNumbers:
1524  case FinishQuery:
1525  return true;
1526  case Unicode:
1527  return true;
1528  }
1529  return false;
1530 }
1531 
1533 {
1534  if (!isOpen()) {
1535  qWarning("QDB2Driver::beginTransaction: Database not open");
1536  return false;
1537  }
1538  return setAutoCommit(false);
1539 }
1540 
1542 {
1543  if (!isOpen()) {
1544  qWarning("QDB2Driver::commitTransaction: Database not open");
1545  return false;
1546  }
1547  SQLRETURN r = SQLEndTran(SQL_HANDLE_DBC,
1548  d->hDbc,
1549  SQL_COMMIT);
1550  if (r != SQL_SUCCESS) {
1551  setLastError(qMakeError(tr("Unable to commit transaction"),
1553  return false;
1554  }
1555  return setAutoCommit(true);
1556 }
1557 
1559 {
1560  if (!isOpen()) {
1561  qWarning("QDB2Driver::rollbackTransaction: Database not open");
1562  return false;
1563  }
1564  SQLRETURN r = SQLEndTran(SQL_HANDLE_DBC,
1565  d->hDbc,
1566  SQL_ROLLBACK);
1567  if (r != SQL_SUCCESS) {
1568  setLastError(qMakeError(tr("Unable to rollback transaction"),
1570  return false;
1571  }
1572  return setAutoCommit(true);
1573 }
1574 
1575 bool QDB2Driver::setAutoCommit(bool autoCommit)
1576 {
1577  SQLUINTEGER ac = autoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
1578  SQLRETURN r = SQLSetConnectAttr(d->hDbc,
1579  SQL_ATTR_AUTOCOMMIT,
1580  (SQLPOINTER)ac,
1581  sizeof(ac));
1582  if (r != SQL_SUCCESS) {
1583  setLastError(qMakeError(tr("Unable to set autocommit"),
1585  return false;
1586  }
1587  return true;
1588 }
1589 
1590 QString QDB2Driver::formatValue(const QSqlField &field, bool trimStrings) const
1591 {
1592  if (field.isNull())
1593  return QLatin1String("NULL");
1594 
1595  switch (field.type()) {
1596  case QVariant::DateTime: {
1597  // Use an escape sequence for the datetime fields
1598  if (field.value().toDateTime().isValid()) {
1599  QDate dt = field.value().toDateTime().date();
1600  QTime tm = field.value().toDateTime().time();
1601  // Dateformat has to be "yyyy-MM-dd hh:mm:ss", with leading zeroes if month or day < 10
1602  return QLatin1Char('\'') + QString::number(dt.year()) + QLatin1Char('-')
1603  + QString::number(dt.month()) + QLatin1Char('-')
1604  + QString::number(dt.day()) + QLatin1Char('-')
1605  + QString::number(tm.hour()) + QLatin1Char('.')
1606  + QString::number(tm.minute()).rightJustified(2, QLatin1Char('0'), true)
1607  + QLatin1Char('.')
1608  + QString::number(tm.second()).rightJustified(2, QLatin1Char('0'), true)
1609  + QLatin1Char('.')
1610  + QString::number(tm.msec() * 1000).rightJustified(6, QLatin1Char('0'), true)
1611  + QLatin1Char('\'');
1612  } else {
1613  return QLatin1String("NULL");
1614  }
1615  }
1616  case QVariant::ByteArray: {
1617  QByteArray ba = field.value().toByteArray();
1618  QString res = QString::fromLatin1("BLOB(X'");
1619  static const char hexchars[] = "0123456789abcdef";
1620  for (int i = 0; i < ba.size(); ++i) {
1621  uchar s = (uchar) ba[i];
1622  res += QLatin1Char(hexchars[s >> 4]);
1623  res += QLatin1Char(hexchars[s & 0x0f]);
1624  }
1625  res += QLatin1String("')");
1626  return res;
1627  }
1628  default:
1629  return QSqlDriver::formatValue(field, trimStrings);
1630  }
1631 }
1632 
1634 {
1635  return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hDbc);
1636 }
1637 
1639 {
1640  QString res = identifier;
1641  if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
1642  res.replace(QLatin1Char('"'), QLatin1String("\"\""));
1643  res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
1644  res.replace(QLatin1Char('.'), QLatin1String("\".\""));
1645  }
1646  return res;
1647 }
1648 
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
double d
Definition: qnumeric_p.h:62
QDB2ResultPrivate * d
Definition: qsql_db2.h:86
bool reset(const QString &query)
Sets the result to use the SQL statement query for subsequent data retrieval.
Definition: qsql_db2.cpp:537
bool isValid() const
Returns true if the field&#39;s variant type is valid; otherwise returns false.
Definition: qsqlfield.cpp:517
int type
Definition: qmetatype.cpp:239
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
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
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
bool isForwardOnly() const
Returns true if you can only scroll forward through the result set; otherwise returns false...
Definition: qsqlresult.cpp:582
DriverFeature
This enum contains a list of features a driver might support.
Definition: qsqldriver.h:75
bool isNull() const
Returns true if this is a NULL variant, false otherwise.
Definition: qvariant.cpp:3102
QVector< T > & fill(const T &t, int size=-1)
Assigns value to all items in the vector.
Definition: qvector.h:665
#define it(className, varName)
The QFlag class is a helper data type for QFlags.
Definition: qglobal.h:2289
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
QByteArray & append(char c)
Appends the character ch to this byte array.
void append(const QSqlField &field)
Appends the field field to the list of indexed fields.
Definition: qsqlindex.cpp:129
QVariant value() const
Returns the value of the field as a QVariant.
Definition: qsqlfield.h:71
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
bool beginTransaction()
This function is called to begin a transaction.
Definition: qsql_db2.cpp:1532
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
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString & prepend(QChar c)
Definition: qstring.h:261
QString toUpper() const Q_REQUIRED_RESULT
Returns an uppercase copy of the string.
Definition: qstring.cpp:5483
int month() const
Returns the number corresponding to the month of this date, using the following convention: ...
Definition: qdatetime.cpp:382
QDB2DriverPrivate * d
Definition: qsql_db2.h:117
static bool qMakeStatement(QDB2ResultPrivate *d, bool forwardOnly, bool setForwardOnly=true)
Definition: qsql_db2.cpp:471
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has type() DateTime , Date , or String ; otherwise ...
Definition: qvariant.cpp:2349
QDB2Result(const QDB2Driver *dr, const QDB2DriverPrivate *dp)
Definition: qsql_db2.cpp:520
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
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 rollbackTransaction()
This function is called to rollback a transaction.
Definition: qsql_db2.cpp:1558
int msec() const
Returns the millisecond part (0 to 999) of the time.
Definition: qdatetime.cpp:1611
bool fetchLast()
Positions the result to the last record (last row) in the result.
Definition: qsql_db2.cpp:920
int numRowsAffected()
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
Definition: qsql_db2.cpp:1067
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
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_db2.cpp:1078
virtual bool isOpen() const
Returns true if the database connection is open; otherwise returns false.
Definition: qsqldriver.cpp:182
The QSqlRecord class encapsulates a database record.
Definition: qsqlrecord.h:58
bool isNull(int i)
Returns true if the field at position index in the current row is null; otherwise returns false...
Definition: qsql_db2.cpp:1057
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
static QByteArray qGetBinaryData(SQLHANDLE hStmt, int column, SQLINTEGER &lengthIndicator, bool &isNull)
Definition: qsql_db2.cpp:364
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
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 QVector class is a template class that provides a dynamic array.
Definition: qdatastream.h:64
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
static QString qWarnDB2Handle(int handleType, SQLHANDLE handle)
Definition: qsql_db2.cpp:122
static SQLBIGINT qGetBigIntData(SQLHANDLE hStmt, int column, bool &isNull)
Definition: qsql_db2.cpp:307
QSqlRecord record() const
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
Definition: qsql_db2.cpp:1083
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
static SQLTCHAR * qToTChar(const QString &str)
Definition: qsql_db2.cpp:117
iterator Iterator
Qt-style synonym for QList::iterator.
Definition: qlist.h:278
const QDB2DriverPrivate * dp
Definition: qsql_db2.cpp:104
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
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
static QString translate(const char *context, const char *key, const char *disambiguation=0, Encoding encoding=CodecForTr)
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
bool setAutoCommit(bool autoCommit)
Definition: qsql_db2.cpp:1575
ErrorType
This enum type describes the context in which the error occurred, e.
Definition: qsqlerror.h:56
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
The QTime class provides clock time functions.
Definition: qdatetime.h:148
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
virtual void setSelect(bool s)
This function is provided for derived classes to indicate whether or not the current statement is a S...
Definition: qsqlresult.cpp:367
void emptyValueCache()
Definition: qsql_db2.cpp:98
QVariant data(int field)
Returns the data for field index in the current row as a QVariant.
Definition: qsql_db2.cpp:951
T takeFirst()
Removes the first item in the list and returns it.
Definition: qlist.h:489
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
QSqlIndex primaryIndex(const QString &tablename) const
Returns the primary index for table tableName.
Definition: qsql_db2.cpp:1440
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
bool hasOutValues() const
Returns true if at least one of the query&#39;s bound values is a QSql::Out or a QSql::InOut; otherwise r...
Definition: qsqlresult.cpp:916
void setLength(int fieldLength)
Sets the field&#39;s length to fieldLength.
Definition: qsqlfield.cpp:254
QSql::ParamType bindValueType(const QString &placeholder) const
Returns the parameter type for the value bound with the given placeholder name.
Definition: qsqlresult.cpp:838
bool nextResult()
Definition: qsql_db2.cpp:1090
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_db2.cpp:573
static void qSqlWarning(const QString &message, const QDB2DriverPrivate *d)
Definition: qsql_db2.cpp:155
Q_CORE_EXPORT void qWarning(const char *,...)
int second() const
Returns the second part (0 to 59) of the time.
Definition: qdatetime.cpp:1600
SQLHANDLE hStmt
Definition: qsql_db2.cpp:105
void setName(const QString &name)
Sets the name of the index to name.
Definition: qsqlindex.cpp:110
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
bool exec()
Executes the query, returning true if successful; otherwise returns false.
Definition: qsql_db2.cpp:597
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
__int64 qint64
Definition: qglobal.h:942
int minute() const
Returns the minute part (0 to 59) of the time.
Definition: qdatetime.cpp:1589
void * HANDLE
Definition: qnamespace.h:1671
quint16 values[128]
QVariant::Type type() const
Returns the field&#39;s type as stored in the database.
Definition: qsqlfield.cpp:394
bool fetch(int i)
Positions the result to an arbitrary (zero-based) row index.
Definition: qsql_db2.cpp:848
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
QSqlField field(int i) const
Returns the field at position index.
Definition: qsqlrecord.cpp:289
virtual void virtual_hook(int id, void *data)
Definition: qsqlresult.cpp:962
static QString qDB2Warn(const QDB2DriverPrivate *d)
Definition: qsql_db2.cpp:142
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
#define Q_INT64_C(c)
Definition: qglobal.h:940
static QVariant::Type qDecodeDB2Type(SQLSMALLINT sqltype)
Definition: qsql_db2.cpp:179
static const SQLSMALLINT qParamType[4]
Definition: qsql_db2.cpp:71
int length() const
Same as size().
Definition: qbytearray.h:356
QSqlResult * createResult() const
Creates an empty SQL result on the database.
Definition: qsql_db2.cpp:1291
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
int length() const
Returns the field&#39;s length.
Definition: qsqlfield.cpp:457
QDate toDate() const
Returns the variant as a QDate if the variant has type() Date , DateTime , or String ; otherwise retu...
Definition: qvariant.cpp:2311
int count() const
Returns the number of fields in the record.
Definition: qsqlrecord.cpp:573
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 & append(QChar c)
Definition: qstring.cpp:1777
static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool &isNull)
Definition: qsql_db2.cpp:324
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
void clearValueCache()
Definition: qsql_db2.cpp:91
QStringList tables(QSql::TableType type) const
Returns a list of the names of the tables in the database.
Definition: qsql_db2.cpp:1369
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type, const QDB2DriverPrivate *p)
Definition: qsql_db2.cpp:167
static QSqlField qMakeFieldInfo(const QDB2ResultPrivate *d, int i)
Definition: qsql_db2.cpp:234
QDB2Driver(QObject *parent=0)
Definition: qsql_db2.cpp:1138
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
QVector< QVariant * > valueCache
Definition: qsql_db2.cpp:107
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
bool fetchNext()
Positions the result to the next available record (row) in the result.
Definition: qsql_db2.cpp:882
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
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_db2.cpp:1162
bool fetchFirst()
Positions the result to the first record (row 0) in the result.
Definition: qsql_db2.cpp:899
bool isNull() const
Returns true if the field&#39;s value is NULL; otherwise returns false.
Definition: qsqlfield.cpp:428
const void * constData() const
Definition: qvariant.cpp:3065
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 formatValue(const QSqlField &field, bool trimStrings) const
Returns a string representation of the field value for the database.
Definition: qsql_db2.cpp:1590
void resize(int size)
Sets the size of the byte array to size bytes.
QByteArray toAscii() const Q_REQUIRED_RESULT
Returns an 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4014
QVariant handle() const
Returns the low-level database handle wrapped in a QVariant or an invalid variant if there is no hand...
Definition: qsql_db2.cpp:1633
if(void) toggleToolbarShown
void append(const QSqlField &field)
Append a copy of field field to the end of the record.
Definition: qsqlrecord.cpp:312
QFactoryLoader * l
void virtual_hook(int id, void *data)
Definition: qsql_db2.cpp:1120
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
virtual void setActive(bool a)
This function is provided for derived classes to set the internal active state to active...
Definition: qsqlresult.cpp:402
void clear()
Removes all the record&#39;s fields.
Definition: qsqlrecord.cpp:367
quint16 index
QString escapeIdentifier(const QString &identifier, IdentifierType type) const
Returns the identifier escaped according to the database rules.
Definition: qsql_db2.cpp:1638
bool commitTransaction()
This function is called to commit a transaction.
Definition: qsql_db2.cpp:1541
void close()
Derived classes must reimplement this pure virtual function in order to close the database connection...
Definition: qsql_db2.cpp:1265
int year() const
Returns the year of this date.
Definition: qdatetime.cpp:353
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
QTime time() const
Returns the time part of the datetime.
Definition: qdatetime.cpp:2368
Definition: qsql.h:68
QTime toTime() const
Returns the variant as a QTime if the variant has type() Time , DateTime , or String ; otherwise retu...
Definition: qvariant.cpp:2330
bool hasFeature(DriverFeature) const
Returns true if the driver supports feature feature; otherwise returns false.
Definition: qsql_db2.cpp:1508
The QSqlField class manipulates the fields in SQL database tables and views.
Definition: qsqlfield.h:56
static double qGetDoubleData(SQLHANDLE hStmt, int column, bool &isNull)
Definition: qsql_db2.cpp:288
SQLHANDLE hDbc
Definition: qsql_db2.cpp:78
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
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
static const int COLNAMESIZE
Definition: qsql_db2.cpp:70
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
QDB2ResultPrivate(const QDB2DriverPrivate *d)
Definition: qsql_db2.cpp:85
QVariant handle() const
Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVarian...
Definition: qsql_db2.cpp:513
QSqlRecord record(const QString &tableName) const
Returns a QSqlRecord populated with the names of the fields in table tableName.
Definition: qsql_db2.cpp:1296
static QString qFromTChar(SQLTCHAR *str)
Definition: qsql_db2.cpp:110
The QSqlResult class provides an abstract interface for accessing data from specific SQL databases...
Definition: qsqlresult.h:63
QSqlRecord recInf
Definition: qsql_db2.cpp:106
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
static int qGetIntData(SQLHANDLE hStmt, int column, bool &isNull)
Definition: qsql_db2.cpp:270
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
IdentifierType
This enum contains a list of SQL identifier types.
Definition: qsqldriver.h:83
static bool isNull(const QVariant::Private *d)
Definition: qvariant.cpp:300
static void qSplitTableQualifier(const QString &qualifier, QString *catalog, QString *schema, QString *table)
Definition: qsql_db2.cpp:420
int size() const
int hour() const
Returns the hour part (0 to 23) of the time.
Definition: qdatetime.cpp:1578
void setSqlType(int type)
Definition: qsqlfield.cpp:285
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
SQLHANDLE hEnv
Definition: qsql_db2.cpp:77