Akonadi

dbintrospector.cpp
1 /*
2  SPDX-FileCopyrightText: 2006 Tobias Koenig <[email protected]>
3  SPDX-FileCopyrightText: 2012 Volker Krause <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "dbintrospector.h"
9 #include "dbintrospector_impl.h"
10 #include "dbtype.h"
11 #include "dbexception.h"
12 #include "querybuilder.h"
13 #include "akonadiserver_debug.h"
14 
15 #include <QSqlField>
16 #include <QSqlRecord>
17 #include <QSqlQuery>
18 
19 using namespace Akonadi::Server;
20 
22 {
23  switch (DbType::type(database)) {
24  case DbType::MySQL:
25  return Ptr(new DbIntrospectorMySql(database));
26  case DbType::Sqlite:
27  return Ptr(new DbIntrospectorSqlite(database));
28  case DbType::PostgreSQL:
29  return Ptr(new DbIntrospectorPostgreSql(database));
30  case DbType::Unknown:
31  break;
32  }
33  qCCritical(AKONADISERVER_LOG) << database.driverName() << "backend not supported";
34  return Ptr();
35 }
36 
38  : m_database(database)
39 {
40 }
41 
42 DbIntrospector::~DbIntrospector()
43 {
44 }
45 
46 bool DbIntrospector::hasTable(const QString &tableName)
47 {
48  return m_database.tables().contains(tableName, Qt::CaseInsensitive);
49 }
50 
51 bool DbIntrospector::hasIndex(const QString &tableName, const QString &indexName)
52 {
53  QSqlQuery query(m_database);
54  if (!query.exec(hasIndexQuery(tableName, indexName))) {
55  throw DbException(query, "Failed to query index");
56  }
57  return query.next();
58 }
59 
60 bool DbIntrospector::hasColumn(const QString &tableName, const QString &columnName)
61 {
62  QStringList columns = m_columnCache.value(tableName);
63 
64  if (columns.isEmpty()) {
65  // QPSQL requires the name to be lower case, but it breaks compatibility with existing
66  // tables with other drivers (see BKO#409234). Yay for abstraction...
67  const auto name = (DbType::type(m_database) == DbType::PostgreSQL) ? tableName.toLower() : tableName;
68  const QSqlRecord table = m_database.record(name);
69  const int numTables = table.count();
70  columns.reserve(numTables);
71  for (int i = 0; i < numTables; ++i) {
72  const QSqlField column = table.field(i);
73  columns.push_back(column.name().toLower());
74  }
75 
76  m_columnCache.insert(tableName, columns);
77  }
78 
79  return columns.contains(columnName.toLower());
80 }
81 
82 bool DbIntrospector::isTableEmpty(const QString &tableName)
83 {
84  QueryBuilder queryBuilder(tableName, QueryBuilder::Select);
85  queryBuilder.addColumn(QStringLiteral("*"));
86  queryBuilder.setLimit(1);
87  if (!queryBuilder.exec()) {
88  throw DbException(queryBuilder.query(), "Unable to retrieve data from table.");
89  }
90 
91  QSqlQuery query = queryBuilder.query();
92  return (query.size() == 0 || !query.first());
93 }
94 
96 {
97  Q_UNUSED(tableName);
98  return QVector<ForeignKey>();
99 }
100 
101 QString DbIntrospector::hasIndexQuery(const QString &tableName, const QString &indexName)
102 {
103  Q_UNUSED(tableName);
104  Q_UNUSED(indexName);
105  qCCritical(AKONADISERVER_LOG) << "Implement index support for your database!";
106  return QString();
107 }
virtual bool hasIndex(const QString &tableName, const QString &indexName)
Returns true of the given table has an index with the given name.
virtual bool hasTable(const QString &tableName)
Returns true if table tableName exists.
QHash::iterator insert(const Key &key, const T &value)
QSqlQuery & query()
Returns the query, only valid after exec().
virtual bool isTableEmpty(const QString &tableName)
Check whether table tableName is empty, ie.
void push_back(const T &value)
void reserve(int alloc)
bool exec(const QString &query)
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QSqlRecord record(const QString &tablename) const const
Exception for reporting SQL errors.
Definition: dbexception.h:20
static DbIntrospector::Ptr createInstance(const QSqlDatabase &database)
Returns an introspector instance for a given database.
void addColumn(const QString &col)
Adds the given column to a select query.
virtual QString hasIndexQuery(const QString &tableName, const QString &indexName)
Returns a query string to determine if tableName has an index indexName.
virtual QVector< ForeignKey > foreignKeyConstraints(const QString &tableName)
Returns the foreign key constraints on table tableName.
Type type(const QSqlDatabase &db)
Returns the type of the given database object.
Definition: dbtype.cpp:11
CaseInsensitive
bool isEmpty() const const
DbIntrospector(const QSqlDatabase &database)
Creates a new database introspector, call from subclass.
bool next()
QSqlDatabase m_database
The database connection we are introspecting.
QSqlField field(int index) const const
QString toLower() const const
const T value(const Key &key) const const
virtual bool hasColumn(const QString &tableName, const QString &columnName)
Check whether table tableName has a column named columnName.
Definition: item.h:31
void setLimit(int limit)
Limits the amount of retrieved rows.
QStringList tables(QSql::TableType type) const const
int count() const const
Helper class to construct arbitrary SQL queries.
Definition: querybuilder.h:32
QString driverName() const const
QString name() const const
bool exec()
Executes the query, returns true on success.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat Nov 21 2020 23:17:04 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.