Akonadi

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

KDE's Doxygen guidelines are available online.