Qt 4.8
qsql_symsql.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_symsql.h"
43 
44 
45 #define SYMBIAN_ENABLE_PUBLIC_PLATFORM_HEADER_SPLIT
46 
47 #include <qcoreapplication.h>
48 #include <qvariant.h>
49 #include <qsqlerror.h>
50 #include <qsqlfield.h>
51 #include <qsqlindex.h>
52 #include <qsqlquery.h>
53 #include <qstringlist.h>
54 #include <qvector.h>
55 #include <qdebug.h>
56 #include "../../../corelib/kernel/qcore_symbian_p.h"
57 
58 #if defined Q_OS_WIN
59 # include <qt_windows.h>
60 #else
61 # include <unistd.h>
62 #endif
63 
64 #include <sqldb.h>
65 #include <e32capability.h>
66 
67 const char* qCapabilityNames[ECapability_Limit] =
68 {
69  "TCB",
70  "CommDD",
71  "PowerMgmt",
72  "MultimediaDD",
73  "ReadDeviceData",
74  "WriteDeviceData",
75  "DRM",
76  "TrustedUI",
77  "ProtServ",
78  "DiskAdmin",
79  "NetworkControl",
80  "AllFiles",
81  "SwEvent",
82  "NetworkServices",
83  "LocalServices",
84  "ReadUserData",
85  "WriteUserData",
86  "Location",
87  "SurroundingsDD",
88  "UserEnvironment"
89 };
90 
91 const char qCapabilityNone[] = "None";
92 
93 
94 Q_DECLARE_METATYPE(RSqlDatabase)
95 Q_DECLARE_METATYPE(RSqlStatement)
96 
98 
101 
102 static QString _q_escapeIdentifier(const QString &identifier)
103 {
104  QString res = identifier;
105  if (!identifier.isEmpty()
106  && identifier.left(1) != QString(QLatin1Char('"'))
107  && identifier.right(1) != QString(QLatin1Char('"'))) {
108  res.replace(QLatin1Char('"'), QLatin1String("\"\""));
109  res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
110  res.replace(QLatin1Char('.'), QLatin1String("\".\""));
111  }
112  return res;
113 }
114 
115 static QVariant::Type qGetColumnType(const TSqlColumnType coltype)
116 {
117  switch(coltype){
118  case ESqlInt:
119  case ESqlInt64:
120  return QVariant::Int;
121  case ESqlReal:
122  return QVariant::Double;
123  case ESqlBinary:
124  return QVariant::ByteArray;
125  case ESqlText:
126  case ESqlNull:
127  default:
128  return QVariant::String;
129  }
130 }
131 
132 static QVariant::Type qGetColumnType(const QString &tpName)
133 {
134  const QString typeName = tpName.toLower();
135 
136  if (typeName == QLatin1String("integer")
137  || typeName == QLatin1String("int"))
138  return QVariant::Int;
139  if (typeName == QLatin1String("double")
140  || typeName == QLatin1String("float")
141  || typeName == QLatin1String("real")
142  || typeName.startsWith(QLatin1String("numeric")))
143  return QVariant::Double;
144  if (typeName == QLatin1String("blob"))
145  return QVariant::ByteArray;
146  return QVariant::String;
147 }
148 
149 static QSqlError qMakeError(RSqlDatabase& access,
150  const QString &descr,
152  int errorCode = -1)
153 {
154  return QSqlError(descr,
155  QString::fromUtf16(static_cast<const ushort *>(access.LastErrorMessage().Ptr())),
156  type,
157  errorCode);
158 }
159 
160 
161 static QSqlError gMakeErrorOpen(const QString &descr,
163  TInt errorCode)
164 {
165  return QSqlError(descr, QLatin1String(""), type, errorCode);
166 }
167 
169 {
170 public:
172  RSqlDatabase access;
173 };
174 
176 {
177 public:
179  void cleanup();
180  bool fetchNext(bool initialFetch);
181  // initializes the recordInfo
182  void initColumns(QSqlRecord& rec);
183  void finalize();
184 
186  RSqlDatabase access;
187  RSqlStatement stmt;
188  bool skipRow; // skip the next fetchNext()?
189  bool skippedStatus; // the status of the fetchNext() that's skipped
191 };
192 
194  skipRow(false),
195  skippedStatus(false),
196  prepareCalled(false)
197 {
198 }
199 
201 {
202  finalize();
203  skippedStatus = false;
204  skipRow = false;
206  q->setActive(false);
207 }
208 
210 {
211  prepareCalled = false;
212  stmt.Close();
213 }
214 
216 {
217  int nCols = stmt.ColumnCount();
218  if (nCols <= 0) {
220  "Error retrieving column count"), QSqlError::UnknownError, nCols));
221  return;
222  }
223 
224  for (int i = 0; i < nCols; ++i) {
225  TPtrC cName;
226  TInt err = stmt.ColumnName(i, cName);
227 
228  if (err != KErrNone) {
230  "Error retrieving column name"), QSqlError::UnknownError, err));
231  return;
232  }
233 
234  QString colName = qt_TDesC2QString(cName);
235 
236  // must use typeName for resolving the type to match QSymSQLDriver::record
237  TPtrC tName;
238  TSqlColumnType decColType;
239  err = stmt.DeclaredColumnType(i, decColType);
240 
241  if (err != KErrNone) {
243  "Error retrieving column type"), QSqlError::UnknownError, err));
244  return;
245  }
246 
247  int dotIdx = colName.lastIndexOf(QLatin1Char('.'));
248  QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(decColType));
249 
250  rec.append(fld);
251  }
252 }
253 
254 bool QSymSQLResultPrivate::fetchNext(bool initialFetch)
255 {
256  int res;
257 
258  if (skipRow) {
259  // already fetched
260  Q_ASSERT(!initialFetch);
261  skipRow = false;
262  return skippedStatus;
263  }
264 
265  skipRow = initialFetch;
266  res = stmt.Next();
267 
268  switch(res) {
269  case KSqlAtRow:
270  return true;
271  case KSqlAtEnd:
272  stmt.Reset();
273  return false;
274  case KSqlErrGeneral:
275  // KSqlErrGeneral is a generic error code and we must call stmt.Reset()
276  // to get the specific error message.
277  stmt.Reset();
279  "Unable to fetch row"), QSqlError::ConnectionError, res));
281  return false;
282  case KSqlErrMisuse:
283  case KSqlErrBusy:
284  default:
285  // something wrong, don't get col info, but still return false
287  "Unable to fetch row"), QSqlError::ConnectionError, res));
288  stmt.Reset();
290  return false;
291  }
292  return false;
293 }
294 
296 
298  : QSqlResult(db)
299 {
300  d = new QSymSQLResultPrivate(this);
301  d->access = db->d->access;
302 }
303 
304 
306 {
307  d->cleanup();
308  delete d;
309 }
310 
311 bool QSymSQLResult::reset(const QString &query)
312 {
313  if (!prepare(query))
314  return false;
315 
316  return exec();
317 }
318 
319 bool QSymSQLResult::prepare(const QString &query)
320 {
321  if (!driver() || !driver()->isOpen() || driver()->isOpenError())
322  return false;
323 
324  d->cleanup();
325  setSelect(false);
326 
327  TInt res = d->stmt.Prepare(d->access, qt_QString2TPtrC(query));
328 
329  if (res != KErrNone) {
331  "Unable to execute statement"), QSqlError::StatementError, res));
332  d->finalize();
333  return false;
334  }
335 
336  d->prepareCalled = true;
337 
338  return true;
339 }
340 
342 {
343  if (d->prepareCalled == false) {
345  "Statement is not prepared"), QSqlError::StatementError, KErrGeneral));
346  return false;
347  }
348 
350 
351  d->skippedStatus = false;
352  d->skipRow = false;
355  int res = d->stmt.Reset();
356 
357  if (res != KErrNone) {
359  "Unable to reset statement"), QSqlError::StatementError, res));
360  d->finalize();
361  return false;
362  }
363  TPtrC tmp;
364  TInt paramCount = 0;
365  while (d->stmt.ParamName(paramCount, tmp) == KErrNone)
366  paramCount++;
367 
368  if (paramCount == values.count()) {
369  for (int i = 0; i < paramCount; ++i) {
370  res = KErrNone;
371  const QVariant value = values.at(i);
372 
373  if (value.isNull()) {
374  res = d->stmt.BindNull(i); //replaced i + 1 with i
375  } else {
376  switch (value.type()) {
377  case QVariant::ByteArray: {
378  const QByteArray *ba = static_cast<const QByteArray*>(value.constData());
379  TPtrC8 data(reinterpret_cast<const TUint8 *>(ba->constData()), ba->length());
380  res = d->stmt.BindBinary(i, data); //replaced i + 1 with i
381  break; }
382  case QVariant::Int:
383  res = d->stmt.BindInt(i, value.toInt()); //replaced i + 1 with i
384  break;
385  case QVariant::Double:
386  res = d->stmt.BindReal(i, value.toDouble()); //replaced i + 1 with i
387 
388  break;
389  case QVariant::UInt:
390  case QVariant::LongLong:
391  res = d->stmt.BindReal(i, value.toLongLong()); //replaced i + 1 with i
392  break;
393 
394  case QVariant::String: {
395  // lifetime of string == lifetime of its qvariant
396  const QString *str = static_cast<const QString*>(value.constData());
397  res = d->stmt.BindText(i, qt_QString2TPtrC(*str)); // replaced i + 1 with i
398  break; }
399  default: {
400  QString str = value.toString();
401  res = d->stmt.BindText(i, qt_QString2TPtrC(str)); //replaced i + 1 with i
402  break; }
403  }
404  }
405  if (res != KErrNone) {
407  "Unable to bind parameters"), QSqlError::StatementError, res));
408  d->finalize();
409  return false;
410  }
411  }
412  } else {
414  "Parameter count mismatch"), QString(), QSqlError::StatementError));
415  return false;
416  }
417 
418  d->skippedStatus = d->fetchNext(true);
419 
420  if (lastError().isValid()) {
421  setSelect(false);
422  setActive(false);
423  return false;
424  }
425 
426  if (d->stmt.ColumnCount() > 0) {
427  //If there is something, it has to be select
428  setSelect(true);
429  } else {
430  //If there isn't it might be just bad query, let's check manually whether we can find SELECT
431  QString query = this->lastQuery();
432  query = query.trimmed();
433  query = query.toLower();
434 
435  //Just check whether there is one in the beginning, don't know if this is enough
436  //Comments should be at the end of line if those are passed
437  //For some reason, case insensitive indexOf didn't work for me
438  if (query.indexOf(QLatin1String("select")) == 0) {
439  setSelect(true);
440  } else {
441  setSelect(false);
442  }
443  }
444 
445  setActive(true);
446  return true;
447 }
448 
449 
451 {
452  return -1;
453 }
454 
456 {
457  return -1;
458 }
459 
461 {
462  if (isActive()) {
463  qint64 id = static_cast<qint64>(d->access.LastInsertedRowId());
464  if (id)
465  return id;
466  }
467 
468  return QVariant();
469 }
470 
472 {
473  if (!isActive() || !isSelect())
474  return QSqlRecord();
475 
476  QSqlRecord res;
477  d->initColumns(res);
478 
479  return res;
480 }
481 
483 {
484  return qVariantFromValue(d->stmt);
485 }
486 
487 
489 {
490  switch (id)
491  {
493  d->stmt.Reset();
494  break;
495  default:
496  QSqlResult::virtual_hook(id, data);
497  }
498 }
499 
501 {
502  QVariant r;
503 
504  switch (d->stmt.ColumnType(idx)) {
505  case ESqlBinary:
506  {
507  TPtrC8 data;
508  d->stmt.ColumnBinary(idx, data);
509  return QByteArray(reinterpret_cast<const char *>(data.Ptr()), data.Length());
510  break;
511  }
512  case ESqlInt:
513  r = QVariant(d->stmt.ColumnInt(idx));
514  break;
515  case ESqlInt64:
516  r = QVariant(d->stmt.ColumnInt64(idx));
517  break;
518  case ESqlReal:
519  switch(numericalPrecisionPolicy()) {
521  r = QVariant(d->stmt.ColumnInt(idx));
522  break;
524  r = QVariant(d->stmt.ColumnInt64(idx));
525  break;
527  r = QVariant(d->stmt.ColumnReal(idx));
528  break;
529  case QSql::HighPrecision:
530  default:
531  TPtrC res;
532  d->stmt.ColumnText(idx, res);
533  r = QVariant(qt_TDesC2QString(res));
534  break;
535  };
536  break;
537  case ESqlNull:
539  break;
540  default:
541  TPtrC res;
542  d->stmt.ColumnText(idx, res);
543  r = QVariant(qt_TDesC2QString(res));
544  break;
545  }
546 
547  return r;
548 }
549 
551 {
552  return d->stmt.IsNull(i);
553 }
554 
556 {
557  //Single return point modified according to review
558  bool retVal = true;
559 
560  if (i < 0 || !isActive()) {
561  retVal = false;
562  } else {
563  if (at() <= -1 || i < at()) {
564  d->stmt.Reset();
565  setAt(-1);
566  d->skipRow = false;
567  }
568 
569  while (at() < i) {
570  if (!d->fetchNext(false)) {
571  retVal = false;
572  break;
573  }
574 
575  setAt(at() + 1);
576  }
577  }
578 
579  return retVal;
580 }
581 
583 {
584  bool res = d->fetchNext(false);
585  if (res) {
586  setAt(at()+1);
587  }
588 
589  return res;
590 }
591 
593 {
594  return QSqlResult::fetchPrevious();
595 }
596 
598 {
599  return fetch(0);
600 }
601 
603 {
604  if (!isActive())
605  return false;
606 
607  if (at() <= -1) {
608  if (!fetchFirst())
609  return false;
610  }
611 
612  TInt res;
613 
614  do {
615  res = d->stmt.Next();
616  setAt(at()+1);
617  } while (res == KSqlAtRow);
618 
619  if (res != KSqlAtEnd)
620  return false;
621 
622  d->skippedStatus = false;
623  d->skipRow = false;
624 
625  return fetchPrevious();
626 }
628 
630  : QSqlDriver(parent)
631 {
632  d = new QSymSQLDriverPrivate();
633 }
634 
635 QSymSQLDriver::QSymSQLDriver(RSqlDatabase& connection, QObject *parent)
636  : QSqlDriver(parent)
637 {
638  d = new QSymSQLDriverPrivate();
639  d->access = connection;
640  setOpen(true);
641  setOpenError(false);
642 }
643 
644 
646 {
647  d->access.Close();
648  delete d;
649 }
650 
652 {
653  switch (f) {
654  case BLOB:
655  case Transactions:
656  case Unicode:
657  case PreparedQueries:
659  case SimpleLocking:
660  case FinishQuery:
661  case LowPrecisionNumbers:
662  case LastInsertId:
663  case NamedPlaceholders:
664  return true;
665  case QuerySize:
666  case BatchOperations:
667  case EventNotifications:
668  case MultipleResultSets:
669  return false;
670  }
671  return false;
672 }
673 
677 TCapability qMatchCapStr(QString& str)
678 {
679  TCapability cap = ECapability_HardLimit;
680 
681  for (int i = 0; i < static_cast<int>(ECapability_Limit); i++) {
683  cap = static_cast<TCapability>(i);
684  break;
685  }
686  }
687 
688  //Special case, we allow ECapability_None to be defined
689  if (cap == ECapability_HardLimit
691  cap = ECapability_None;
692 
693  return cap;
694 }
695 
696 bool qExtractSecurityPolicyFromString(const QString &string, TSecurityPolicy &policy)
697 {
698  int startPos = string.indexOf(QLatin1Char('='));
700  bool ret = false;
701 
702  if (startPos == -1) {
703  values = string.split(QLatin1Char(','), QString::SkipEmptyParts);
704  } else {
705  values = string.mid(startPos + 1).split(QLatin1Char(','), QString::SkipEmptyParts);
706  }
707 
708  if (values.count() > 0) {
709  const QString findVid(QLatin1String("vid["));
710  const QString findSid(QLatin1String("sid["));
711  const int MaxCapCount = 7;
712  const int VidMaxCount = 3;
713  const int SidMaxCount = 3;
714 
715  TCapability capList[MaxCapCount] = { ECapability_None,ECapability_None,ECapability_None,
716  ECapability_None,ECapability_None,ECapability_None,ECapability_None };
717 
718  bool isVID = false;
719  bool isSID = false;
720 
721  QString idString(QLatin1String(""));
722  int maxAllowed = MaxCapCount;
723 
724  if (values[0].contains(findVid, Qt::CaseInsensitive)) {
725  idString = values[0].remove(findVid, Qt::CaseInsensitive);
726  idString = idString.remove(QLatin1Char(']'));
727  values.removeAt(0);
728  isVID = true;
729  maxAllowed = VidMaxCount;
730 
731  } else if (values[0].contains(findSid, Qt::CaseInsensitive)) {
732  idString = values[0].remove(findSid, Qt::CaseInsensitive);
733  idString = idString.remove(QLatin1Char(']'));
734  values.removeAt(0);
735  isSID = true;
736  maxAllowed = SidMaxCount;
737  }
738 
739  if (values.count() <= maxAllowed) {
740  bool wasSuccesful = true;
741 
742  for (int i = 0; i < values.count(); i++) {
743  capList[i] = qMatchCapStr(values[i]);
744 
745  if (capList[i] == ECapability_HardLimit) {
746  wasSuccesful = false;
747  break;
748  }
749  }
750 
751  if (wasSuccesful) {
752  if (isVID || isSID){
753  bool ok = true;
754  quint32 id = idString.toUInt(&ok, 16);
755 
756  if (ok) {
757  if (isVID) {
758  TVendorId vid(id);
759  policy = TSecurityPolicy(vid, capList[0], capList[1], capList[2]);
760  } else {
761  TSecureId sid(id);
762  policy = TSecurityPolicy(sid, capList[0], capList[1], capList[2]);
763  }
764 
765  ret = true; //Everything is fine
766  }
767  } else {
768  policy = TSecurityPolicy(capList[0], capList[1], capList[2], capList[3],
769  capList[4], capList[5], capList[6]);
770 
771  ret = true; //Everything is fine
772  }
773  }
774  }
775  }
776 
777  return ret;
778 }
779 
847 bool QSymSQLDriver::open(const QString & db, const QString &, const QString &, const QString &, int, const QString &conOpts)
848 {
849  if (isOpen())
850  close();
851  if (db.isEmpty())
852  return false;
853 
854  //Separating our parameters from Symbian ones and construct new connection options
855  const QString itemSeparator(QLatin1String(";"));
856  QRegExp isOurOption(QLatin1String("POLICY_*"), Qt::CaseInsensitive, QRegExp::Wildcard);
857 
858  QStringList optionList = conOpts.split(itemSeparator, QString::SkipEmptyParts);
859  QStringList symbianList;
860 
861  for (int i = optionList.count() - 1; i >= 0; i--) {
862  if (!optionList[i].contains(isOurOption)) {
863  symbianList.append(optionList[i]);
864  optionList.removeAt(i);
865  } else {
866  //Removing whitespace
867  QString formatted = optionList[i];
868  formatted = formatted.remove(QLatin1Char(' '));
869  formatted = formatted.remove(QLatin1Char('\t'));
870  formatted = formatted.remove(QLatin1Char('\n'));
871  formatted = formatted.remove(QLatin1Char('\r'));
872  optionList[i] = formatted;
873  }
874  }
875 
876  QString symbianOpt;
877 
878  for (int i = 0; i < symbianList.count(); i++) {
879  symbianOpt += symbianList[i];
880  symbianOpt += itemSeparator;
881  }
882 
883  TPtrC dbName(qt_QString2TPtrC(db));
884  QByteArray conOpts8 = symbianOpt.toUtf8();
885  const TPtrC8 config(reinterpret_cast<const TUint8*>(conOpts8.constData()), (conOpts8.length()));
886 
887  TInt res = d->access.Open(dbName, &config);
888 
889  if (res == KErrNotFound) {
890 
891  QRegExp findDefault(QLatin1String("POLICY_DB_DEFAULT=*"), Qt::CaseInsensitive, QRegExp::Wildcard);
892  QRegExp findRead(QLatin1String("POLICY_DB_READ=*"), Qt::CaseInsensitive, QRegExp::Wildcard);
893  QRegExp findWrite(QLatin1String("POLICY_DB_WRITE=*"), Qt::CaseInsensitive, QRegExp::Wildcard);
894  QRegExp findSchema(QLatin1String("POLICY_DB_SCHEMA=*"), Qt::CaseInsensitive, QRegExp::Wildcard);
895  QRegExp findTableRead(QLatin1String("POLICY_TABLE_READ=*"), Qt::CaseInsensitive, QRegExp::Wildcard);
896  QRegExp findTableWrite(QLatin1String("POLICY_TABLE_WRITE=*"), Qt::CaseInsensitive, QRegExp::Wildcard);
897 
898  int policyIndex = optionList.indexOf(findDefault);
899 
900  if (policyIndex != -1) {
901  QString defaultPolicyString = optionList[policyIndex];
902  optionList.removeAt(policyIndex);
903 
904  TSecurityPolicy policyItem;
905 
906  if (qExtractSecurityPolicyFromString(defaultPolicyString, policyItem)) {
907  RSqlSecurityPolicy policy;
908  res = policy.Create(policyItem);
909 
910  if (res == KErrNone) {
911  for (int i = 0; i < optionList.count(); i++) {
912  QString option = optionList[i];
913 
914  if (option.contains(findRead)) {
915  if (qExtractSecurityPolicyFromString(option, policyItem)) {
916  res = policy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, policyItem);
917  } else {
918  res = KErrArgument;
919  }
920  } else if (option.contains(findWrite)) {
921  if (qExtractSecurityPolicyFromString(option, policyItem)) {
922  res = policy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy, policyItem);
923  } else {
924  res = KErrArgument;
925  }
926  } else if (option.contains(findSchema)) {
927  if (qExtractSecurityPolicyFromString(option, policyItem)) {
928  res = policy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy, policyItem);
929  } else {
930  res = KErrArgument;
931  }
932  } else if (option.contains(findTableWrite)) {
933  QString tableOption = option.mid(option.indexOf(QLatin1Char('=')) + 1);
934  int firstComma = tableOption.indexOf(QLatin1Char(','));
935 
936  if (firstComma != -1) {
937  QString tableName = tableOption.left(firstComma);
938  tableOption = tableOption.mid(firstComma + 1);
939 
940  if (qExtractSecurityPolicyFromString(tableOption, policyItem)) {
941  TPtrC symTableName(qt_QString2TPtrC(tableName));
942 
943  res = policy.SetPolicy(RSqlSecurityPolicy::ETable, symTableName,
944  RSqlSecurityPolicy::EWritePolicy, policyItem);
945  } else {
946  res = KErrArgument;
947  }
948  } else {
949  res = KErrArgument;
950  }
951  } else if (option.contains(findTableRead)) {
952  QString tableOption = option.mid(option.indexOf(QLatin1Char('=')) + 1);
953  int firstComma = tableOption.indexOf(QLatin1Char(','));
954 
955  if (firstComma != -1) {
956  QString tableName = tableOption.left(firstComma);
957  tableOption = tableOption.mid(firstComma + 1);
958 
959  if (qExtractSecurityPolicyFromString(tableOption, policyItem)) {
960  TPtrC symTableName(qt_QString2TPtrC(tableName));
961 
962  res = policy.SetPolicy(RSqlSecurityPolicy::ETable, symTableName,
963  RSqlSecurityPolicy::EReadPolicy, policyItem);
964  } else {
965  res = KErrArgument;
966  }
967  } else {
968  res = KErrArgument;
969  }
970  } else {
971  res = KErrArgument;
972  }
973 
974  if (res != KErrNone) {
975  setLastError(gMakeErrorOpen(tr("Invalid option: ") + option, QSqlError::ConnectionError, res));
976  break;
977  }
978  }
979 
980  if (res == KErrNone) {
981  res = d->access.Create(dbName, policy, &config);
982  policy.Close();
983 
984  if (res != KErrNone)
985  setLastError(gMakeErrorOpen(tr("Error opening database"), QSqlError::ConnectionError, res));
986  }
987  }
988 
989  } else {
990  res = KErrArgument;
991  setLastError(gMakeErrorOpen(tr("Invalid option: ") + defaultPolicyString, QSqlError::ConnectionError, res));
992  }
993 
994  } else {
995  //Check whether there is some of our options, fail if so.
996  policyIndex = optionList.indexOf(isOurOption);
997 
998  if (policyIndex == -1) {
999  res = d->access.Create(dbName, &config);
1000 
1001  if (res != KErrNone)
1002  setLastError(gMakeErrorOpen(tr("Error opening database"), QSqlError::ConnectionError, res));
1003  } else {
1004  res = KErrArgument;
1005  setLastError(gMakeErrorOpen(tr("POLICY_DB_DEFAULT must be defined before any other POLICY definitions can be used"), QSqlError::ConnectionError, res));
1006  }
1007  }
1008  }
1009 
1010  if (res == KErrNone) {
1011  setOpen(true);
1012  setOpenError(false);
1013  return true;
1014  } else {
1015  setOpenError(true);
1016  return false;
1017  }
1018 }
1019 
1020 void QSymSQLDriver::close()
1021 {
1022  if (isOpen()) {
1023  d->access.Close();
1024  setOpen(false);
1025  setOpenError(false);
1026  }
1027 }
1028 
1030 {
1031  return new QSymSQLResult(this);
1032 }
1033 
1035 {
1036  if (!isOpen() || isOpenError())
1037  return false;
1038 
1039  TInt err = d->access.Exec(_L("BEGIN"));
1040  if (err < KErrNone) {
1041  setLastError(QSqlError(tr("Unable to begin transaction"),
1042  qt_TDesC2QString(d->access.LastErrorMessage()), QSqlError::TransactionError, err));
1043  return false;
1044  }
1045 
1046  return true;
1047 }
1048 
1050 {
1051  if (!isOpen() || isOpenError())
1052  return false;
1053 
1054  TInt err = d->access.Exec(_L("COMMIT"));
1055  if (err < KErrNone) {
1056  setLastError(QSqlError(tr("Unable to commit transaction"),
1057  qt_TDesC2QString(d->access.LastErrorMessage()), QSqlError::TransactionError, err));
1058  return false;
1059  }
1060 
1061  return true;
1062 }
1063 
1065 {
1066  if (!isOpen() || isOpenError())
1067  return false;
1068 
1069  TInt err = d->access.Exec(_L("ROLLBACK"));
1070  if (err < KErrNone) {
1071  setLastError(QSqlError(tr("Unable to rollback transaction"),
1072  qt_TDesC2QString(d->access.LastErrorMessage()), QSqlError::TransactionError, err));
1073  return false;
1074  }
1075 
1076  return true;
1077 }
1078 
1080 {
1081  QStringList res;
1082  if (!isOpen())
1083  return res;
1084 
1085  QSqlQuery q(createResult());
1086  q.setForwardOnly(true);
1087 
1088  QString sql = QLatin1String("SELECT name FROM sqlite_master WHERE %1 "
1089  "UNION ALL SELECT name FROM sqlite_temp_master WHERE %1");
1090  if ((type & QSql::Tables) && (type & QSql::Views))
1091  sql = sql.arg(QLatin1String("type='table' OR type='view'"));
1092  else if (type & QSql::Tables)
1093  sql = sql.arg(QLatin1String("type='table'"));
1094  else if (type & QSql::Views)
1095  sql = sql.arg(QLatin1String("type='view'"));
1096  else
1097  sql.clear();
1098 
1099  if (!sql.isEmpty() && q.exec(sql)) {
1100  while (q.next())
1101  res.append(q.value(0).toString());
1102  }
1103 
1104  if (type & QSql::SystemTables)
1105  // there are no internal tables beside this one:
1106  res.append(QLatin1String("sqlite_master"));
1107 
1108  return res;
1109 }
1110 
1111 static QSqlIndex qGetTableInfo(QSqlQuery &q, QString &tableName, bool onlyPIndex = false)
1112 {
1113  QString dbName;
1114  QString table(tableName);
1115  int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
1116  if (indexOfSeparator > -1) {
1117  dbName = tableName.left(indexOfSeparator +1 );
1118  table = tableName.mid(indexOfSeparator + 1);
1119  }
1120  q.exec(QLatin1String("PRAGMA ") + dbName + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1String(")"));
1121 
1122  const int NAME_IDX = 1;
1123  const int TYPE_IDX = 2;
1124  const int NOTNULL_IDX = 3;
1125  const int DFLT_VALUE_IDX = 4;
1126  const int PK_IDX = 5;
1127 
1128  QSqlIndex ind;
1129  while (q.next()) {
1130  bool isPk = q.value(PK_IDX).toInt();
1131  if (onlyPIndex && !isPk)
1132  continue;
1133  QString typeName = q.value(TYPE_IDX).toString().toLower();
1134  QSqlField fld(q.value(NAME_IDX).toString(), qGetColumnType(typeName));
1135  if (isPk && (typeName == QLatin1String("integer")))
1136  // INTEGER PRIMARY KEY fields are auto-generated in sqlite
1137  // INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
1138  fld.setAutoValue(true);
1139  fld.setRequired(q.value(NOTNULL_IDX).toInt() != 0);
1140  fld.setDefaultValue(q.value(DFLT_VALUE_IDX));
1141  ind.append(fld);
1142  }
1143  return ind;
1144 }
1145 
1146 QSqlIndex QSymSQLDriver::primaryIndex(const QString &tblname) const
1147 {
1148  if (!isOpen())
1149  return QSqlIndex();
1150 
1151  QString table = tblname;
1153  table = stripDelimiters(table, QSqlDriver::TableName);
1154 
1155  QSqlQuery q(createResult());
1156  q.setForwardOnly(true);
1157  return qGetTableInfo(q, table, true);
1158 }
1159 
1160 QSqlRecord QSymSQLDriver::record(const QString &tbl) const
1161 {
1162  if (!isOpen())
1163  return QSqlRecord();
1164 
1165  QString table = tbl;
1167  table = stripDelimiters(table, QSqlDriver::TableName);
1168 
1169  QSqlQuery q(createResult());
1170  q.setForwardOnly(true);
1171  return qGetTableInfo(q, table);
1172 }
1173 
1175 {
1176  return qVariantFromValue(d->access);
1177 }
1178 
1179 QString QSymSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
1180 {
1181  Q_UNUSED(type);
1182  return _q_escapeIdentifier(identifier);
1183 }
1184 
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
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
QVariant handle() const
Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVarian...
bool qExtractSecurityPolicyFromString(const QString &string, TSecurityPolicy &policy)
const QSqlDriver * driver() const
Returns the driver associated with the result.
Definition: qsqlresult.cpp:389
QSymSQLDriver(QObject *parent=0)
int type
Definition: qmetatype.cpp:239
static QVariant::Type qGetColumnType(const TSqlColumnType coltype)
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
Definition: qsqlresult.cpp:340
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QVariant qVariantFromValue(const T &)
Definition: qvariant.h:451
virtual void setOpen(bool o)
This function sets the open state of the database to open.
Definition: qsqldriver.cpp:283
int size()
Returns the size of the SELECT result, or -1 if it cannot be determined or if the query is not a SELE...
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
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
const char qCapabilityNone[]
Definition: qsql_symsql.cpp:91
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
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
bool fetchNext(bool initialFetch)
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QString & prepend(QChar c)
Definition: qstring.h:261
The QSqlQuery class provides a means of executing and manipulating SQL statements.
Definition: qsqlquery.h:63
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
bool fetch(int i)
Positions the result to an arbitrary (zero-based) row index.
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
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static QSqlError gMakeErrorOpen(const QString &descr, QSqlError::ErrorType type, TInt errorCode)
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
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 hasFeature(DriverFeature f) const
Returns true if the driver supports feature feature; otherwise returns false.
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
int at() const
Returns the current (zero-based) row position of the result.
Definition: qsqlresult.cpp:306
const QString fieldSeparator(QLatin1String(","))
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
bool isNull(int i)
Returns true if the field at position index in the current row is null; otherwise returns false...
int numRowsAffected()
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
QStringList tables(QSql::TableType) const
Returns a list of the names of the tables in the database.
QString lastQuery() const
Returns the current SQL query text, or an empty string if there isn&#39;t one.
Definition: qsqlresult.cpp:294
void initColumns(QSqlRecord &rec)
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
static QString translate(const char *context, const char *key, const char *disambiguation=0, Encoding encoding=CodecForTr)
QList< T > mid(int pos, int length=-1) const
Returns a list whose elements are copied from this list, starting at position pos.
Definition: qlist.h:637
QSqlRecord record() const
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
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
bool fetchFirst()
Positions the result to the first record (row 0) in the result.
bool isOpenError() const
Returns true if the there was an error opening the database connection; otherwise returns false...
Definition: qsqldriver.cpp:192
static QString _q_escapeIdentifier(const QString &identifier)
ErrorType
This enum type describes the context in which the error occurred, e.
Definition: qsqlerror.h:56
QSymSQLResult(const QSymSQLDriver *db)
QSqlRecord record(const QString &tablename) const
Returns a QSqlRecord populated with the names of the fields in table tableName.
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
int indexOf(const QRegExp &rx, int from=0) const
Returns the index position of the first exact match of rx in the list, searching forward from index p...
Definition: qstringlist.h:195
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
qlonglong toLongLong(bool *ok=0) const
Returns the variant as a long long int if the variant has type() LongLong , Bool , ByteArray , Char , Double , Int , String , UInt , or ULongLong ; otherwise returns 0.
Definition: qvariant.cpp:2659
bool fetchLast()
Positions the result to the last record (last row) in the result.
const char * qCapabilityNames[ECapability_Limit]
Definition: qsql_symsql.cpp:67
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
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
int access(const char *, int)
const char * typeName
Definition: qmetatype.cpp:239
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
bool exec()
Executes the query, returning true if successful; otherwise returns false.
const QString valueSeparator(QLatin1String("="))
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
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
QString right(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n rightmost characters of the string.
Definition: qstring.cpp:3682
__int64 qint64
Definition: qglobal.h:942
quint16 values[128]
TCapability qMatchCapStr(QString &str)
Converts capability string to TCapability.
QVariant lastInsertId() const
Returns the object ID of the most recent inserted row if the database supports it.
virtual void virtual_hook(int id, void *data)
Definition: qsqlresult.cpp:962
#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
QVariant data(int field)
Returns the data for field index in the current row as a QVariant.
void setForwardOnly(bool forward)
Sets forward only mode to forward.
Definition: qsqlquery.cpp:835
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
bool prepare(const QString &query)
Prepares the given query for execution; the query will normally use placeholders so that it can be ex...
QSymSQLDriverPrivate * d
Definition: qsql_symsql.h:125
bool commitTransaction()
This function is called to commit a transaction.
int length() const
Same as size().
Definition: qbytearray.h:356
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QSqlResult * createResult() const
Creates an empty SQL result on the database.
static QSqlError qMakeError(RSqlDatabase &access, const QString &descr, QSqlError::ErrorType type, int errorCode=-1)
QSqlIndex primaryIndex(const QString &table) const
Returns the primary index for table tableName.
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
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
bool fetchPrevious()
Positions the result to the previous record (row) in the result.
QString & append(QChar c)
Definition: qstring.cpp:1777
int compare(const QString &s) const
Definition: qstring.cpp:5037
friend class QSymSQLResult
Definition: qsql_symsql.h:100
QSymSQLResult * q
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
friend class QSymSQLResultPrivate
Definition: qsql_symsql.h:68
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
bool rollbackTransaction()
This function is called to rollback a transaction.
const void * constData() const
Definition: qvariant.cpp:3065
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
unsigned int quint32
Definition: qglobal.h:938
uint toUInt(bool *ok=0, int base=10) const
Returns the string converted to an unsigned int using base base, which is 10 by default and must be b...
Definition: qstring.cpp:6120
static void cleanup()
Definition: qpicture.cpp:1508
QVariant handle() const
Returns the low-level database handle wrapped in a QVariant or an invalid variant if there is no hand...
QSymSQLResultPrivate * d
Definition: qsql_symsql.h:94
void append(const QSqlField &field)
Append a copy of field field to the end of the record.
Definition: qsqlrecord.cpp:312
QSqlError lastError() const
Returns the last error associated with the result.
Definition: qsqlresult.cpp:427
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
virtual bool fetchPrevious()
Positions the result to the previous record (row) in the result.
Definition: qsqlresult.cpp:571
bool beginTransaction()
This function is called to begin a transaction.
static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool onlyPIndex=false)
bool isValid() const
Returns true if the result is positioned on a valid record (that is, the result is not positioned bef...
Definition: qsqlresult.cpp:320
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
The QSqlField class manipulates the fields in SQL database tables and views.
Definition: qsqlfield.h:56
bool reset(const QString &query)
Sets the result to use the SQL statement query for subsequent data retrieval.
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
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
void setAutoValue(bool autoVal)
Marks the field as an auto-generated value if autoVal is true.
Definition: qsqlfield.cpp:575
QSymSQLResultPrivate(QSymSQLResult *res)
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
RSqlStatement stmt
QVariant value(int i) const
Returns the value of field index in the current record.
Definition: qsqlquery.cpp:403
QString escapeIdentifier(const QString &identifier, IdentifierType) const
Returns the identifier escaped according to the database rules.
bool fetchNext()
Positions the result to the next available record (row) in the result.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
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
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void close()
Derived classes must reimplement this pure virtual function in order to close the database connection...
IdentifierType
This enum contains a list of SQL identifier types.
Definition: qsqldriver.h:83
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...
static QString fromUtf16(const ushort *, int size=-1)
Returns a QString initialized with the first size characters of the Unicode string unicode (ISO-10646...
Definition: qstring.cpp:4329
void virtual_hook(int id, void *data)
void removeAt(int i)
Removes the item at index position i.
Definition: qlist.h:480