Akonadi

dbintrospector.cpp
1 /*
2  Copyright (C) 2006 by Tobias Koenig <[email protected]>
3  Copyright (c) 2012 Volker Krause <[email protected]>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 */
20 
21 #include "dbintrospector.h"
22 #include "dbintrospector_impl.h"
23 #include "dbtype.h"
24 #include "dbexception.h"
25 #include "querybuilder.h"
26 #include "akonadiserver_debug.h"
27 
28 #include <QStringList>
29 #include <QSqlField>
30 #include <QSqlRecord>
31 #include <QSqlQuery>
32 
33 using namespace Akonadi::Server;
34 
36 {
37  switch (DbType::type(database)) {
38  case DbType::MySQL:
39  return Ptr(new DbIntrospectorMySql(database));
40  case DbType::Sqlite:
41  return Ptr(new DbIntrospectorSqlite(database));
42  case DbType::PostgreSQL:
43  return Ptr(new DbIntrospectorPostgreSql(database));
44  case DbType::Unknown:
45  break;
46  }
47  qCCritical(AKONADISERVER_LOG) << database.driverName() << "backend not supported";
48  return Ptr();
49 }
50 
52  : m_database(database)
53 {
54 }
55 
56 DbIntrospector::~DbIntrospector()
57 {
58 }
59 
60 bool DbIntrospector::hasTable(const QString &tableName)
61 {
62  return m_database.tables().contains(tableName, Qt::CaseInsensitive);
63 }
64 
65 bool DbIntrospector::hasIndex(const QString &tableName, const QString &indexName)
66 {
67  QSqlQuery query(m_database);
68  if (!query.exec(hasIndexQuery(tableName, indexName))) {
69  throw DbException(query, "Failed to query index");
70  }
71  return query.next();
72 }
73 
74 bool DbIntrospector::hasColumn(const QString &tableName, const QString &columnName)
75 {
76  QStringList columns = m_columnCache.value(tableName);
77 
78  if (columns.isEmpty()) {
79  // QPSQL requires the name to be lower case, but it breaks compatibility with existing
80  // tables with other drivers (see BKO#409234). Yay for abstraction...
81  const auto name = (DbType::type(m_database) == DbType::PostgreSQL) ? tableName.toLower() : tableName;
82  const QSqlRecord table = m_database.record(name);
83  const int numTables = table.count();
84  columns.reserve(numTables);
85  for (int i = 0; i < numTables; ++i) {
86  const QSqlField column = table.field(i);
87  columns.push_back(column.name().toLower());
88  }
89 
90  m_columnCache.insert(tableName, columns);
91  }
92 
93  return columns.contains(columnName.toLower());
94 }
95 
96 bool DbIntrospector::isTableEmpty(const QString &tableName)
97 {
98  QueryBuilder queryBuilder(tableName, QueryBuilder::Select);
99  queryBuilder.addColumn(QStringLiteral("*"));
100  queryBuilder.setLimit(1);
101  if (!queryBuilder.exec()) {
102  throw DbException(queryBuilder.query(), "Unable to retrieve data from table.");
103  }
104 
105  QSqlQuery query = queryBuilder.query();
106  if (query.size() == 0 || !query.first()) { // table is empty
107  return true;
108  }
109  return false;
110 }
111 
113 {
114  Q_UNUSED(tableName);
115  return QVector<ForeignKey>();
116 }
117 
118 QString DbIntrospector::hasIndexQuery(const QString &tableName, const QString &indexName)
119 {
120  Q_UNUSED(tableName);
121  Q_UNUSED(indexName);
122  qCCritical(AKONADISERVER_LOG) << "Implement index support for your database!";
123  return QString();
124 }
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:33
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:24
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:44
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:45
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 May 30 2020 22:46:07 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.