File indexing completed on 2025-01-05 04:46:58

0001 /*
0002     SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org>
0003     SPDX-FileCopyrightText: 2012 Volker Krause <vkrause@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 #pragma once
0008 
0009 #include <QHash>
0010 #include <QSharedPointer>
0011 #include <QSqlDatabase>
0012 #include <QStringList>
0013 
0014 class DbIntrospectorTest;
0015 
0016 namespace Akonadi
0017 {
0018 namespace Server
0019 {
0020 /**
0021  * Methods for introspecting the current state of a database schema.
0022  * I.e. this is about the structure of a database, not its content.
0023  */
0024 class DbIntrospector
0025 {
0026 public:
0027     using Ptr = QSharedPointer<DbIntrospector>;
0028 
0029     /** A structure describing an existing foreign key. */
0030     class ForeignKey
0031     {
0032     public:
0033         QString name;
0034         QString column;
0035         QString refTable;
0036         QString refColumn;
0037         QString onUpdate; // TODO use same enum as DbInitializer
0038         QString onDelete; // dito
0039     };
0040 
0041     /**
0042      * Returns an introspector instance for a given database.
0043      */
0044     static DbIntrospector::Ptr createInstance(const QSqlDatabase &database);
0045 
0046     virtual ~DbIntrospector();
0047 
0048     /**
0049      * Returns @c true if table @p tableName exists.
0050      * The default implementation relies on QSqlDatabase::tables(). Usually this
0051      * does not need to be reimplemented.
0052      */
0053     virtual bool hasTable(const QString &tableName);
0054 
0055     /**
0056      * Returns @c true of the given table has an index with the given name.
0057      * The default implementation performs the query returned by hasIndexQuery().
0058      * @see hasIndexQuery()
0059      * @throws DbException on database errors.
0060      */
0061     virtual bool hasIndex(const QString &tableName, const QString &indexName);
0062 
0063     /**
0064      * Check whether table @p tableName has a column named @p columnName.
0065      * The default implementation should work with all backends.
0066      */
0067     virtual bool hasColumn(const QString &tableName, const QString &columnName);
0068 
0069     /**
0070      * Check whether table @p tableName is empty, ie. does not contain any rows.
0071      * The default implementation should work for all backends.
0072      * @throws DbException on database errors.
0073      */
0074     virtual bool isTableEmpty(const QString &tableName);
0075 
0076     /**
0077      * Returns the foreign key constraints on table @p tableName.
0078      * The default implementation returns an empty list, so any backend supporting
0079      * referential integrity should reimplement this.
0080      */
0081     virtual QList<ForeignKey> foreignKeyConstraints(const QString &tableName);
0082 
0083     /**
0084      * Returns query to retrieve the next autoincrement value for @p tableName.@p columnName.
0085      */
0086     virtual QString getAutoIncrementValueQuery(const QString &tableName, const QString &columnName) = 0;
0087 
0088     /**
0089      * Returns query to update the next autoincrement value for @p tableName.@p columnName to value @p value.
0090      */
0091     virtual QString updateAutoIncrementValueQuery(const QString &tableName, const QString &columnName, qint64 value) = 0;
0092 
0093 protected:
0094     /**
0095      * Creates a new database introspector, call from subclass.
0096      *
0097      * @param database The database to introspect.
0098      */
0099     DbIntrospector(const QSqlDatabase &database);
0100 
0101     /**
0102      * Returns a query string to determine if @p tableName has an index @p indexName.
0103      * The query is expected to have one boolean result row/column.
0104      * This is used by the default implementation of hasIndex() only, thus reimplementation
0105      * is not necessary if you reimplement hasIndex()
0106      * The default implementation asserts.
0107      */
0108     virtual QString hasIndexQuery(const QString &tableName, const QString &indexName);
0109 
0110     /** The database connection we are introspecting. */
0111     QSqlDatabase m_database;
0112 
0113 private:
0114     Q_DISABLE_COPY_MOVE(DbIntrospector)
0115 
0116     friend class ::DbIntrospectorTest;
0117     QHash<QString, QStringList> m_columnCache; // avoids extra db roundtrips
0118 };
0119 
0120 } // namespace Server
0121 } // namespace Akonadi