1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
#ifndef DBATTACHER_H
#define DBATTACHER_H
#include "parser/ast/sqlitequery.h"
#include "common/bistrhash.h"
#include "common/strhash.h"
#include <QList>
class Db;
/**
* @brief Transparent attaching of databases used in the query.
*
* Scans query (or queries) for names of databases registered in DbManager.
* If a database is recognized, it's automatically attached and the mapping
* of its database name to its attach name is created for later information.
*
* The attacher looks for database names only at those spots in the query,
* where the database name is valid by SQLite syntax (this is accomplished
* with SqliteStatement::getContextDatabaseTokens()).
*/
class API_EXPORT DbAttacher
{
public:
/**
* @brief Default destructor.
*/
virtual ~DbAttacher();
/**
* @brief Scans for databases in given query and attaches them.
* @param query Query string to be executed.
* @return true on success, or false on failure.
*
* The method can fail if any of databases used in the query could
* not be attached (the ATTACH statement caused error).
*
* To get query with database names replaced with attach names use getQuery().
*/
virtual bool attachDatabases(const QString& query) = 0;
/**
* Be aware that database names in queries are replaced with attach names in SqliteStatement::tokens,
* thus modified query can be achived with SqliteStatement::detokenize(). This also means
* that the input queries will contain modified token list.
*
* @overload
*/
virtual bool attachDatabases(const QList<SqliteQueryPtr>& queries) = 0;
/**
* @overload
*/
virtual bool attachDatabases(SqliteQueryPtr query) = 0;
/**
* @brief Detaches all databases attached by the attacher.
*/
virtual void detachDatabases() = 0;
/**
* @brief Provides mapping of database names to their attach names.
* @return Database name to attach name mapping.
*
* The returned map is bi-directional, so you can easly translate database name to attach name
* and vice versa. Left values of the map are database names (as registered in DbManager)
* and right values are attach names assigned to them.
*/
virtual BiStrHash getDbNameToAttach() const = 0;
/**
* @brief Provices mapping of databases pre-attached by a user.
* @return List of databases attached manually by user with ATTACH statements.
*
* This is pretty much a convenient method for PRAGMA database_list, that excludes 'main' and 'temp' entries.
* It also excludes entries with empty file path (i.e. memory databases, etc).
*
* Left side values are file paths, while right side values are attached database ID/name.
*/
virtual BiStrHash getNativePathToAttachName() const = 0;
/**
* @brief Provides query string updated with attach names.
* @return Query string.
*/
virtual QString getQuery() const = 0;
/**
* @brief Tells if "main" database name was used in the query and was ommited.
* @return true when "main" db token was in the query, or false otherwise.
*
* The "main" database will not be attached and this getter tells wheter such situation occurred.
* This is to assert situation when user has database on the list which name is actually "main".
* Table window always uses "main." prefix when reading data and this caused attacher to step in,
* which then caused some execution error.
*/
virtual bool getMainDbNameUsed() const = 0;
};
/**
* @brief Abstract factory for DbAttacher objects.
*
* The abstract factory is accessed from SQLiteStudio class in order to produce DbAttacher instances.
* The default DbAttacherFactory implementation (DbAttacherFactoryImpl) produces default DbAttacher instances
* (DbAttacherImpl), but it can be replaced with other factory to produce other attachers, just like unit tests
* in this project do.
*/
class API_EXPORT DbAttacherFactory
{
public:
virtual ~DbAttacherFactory();
/**
* @brief Produces single attacher instance.
* @param db Database to produce attacher for.
* @return Attacher instance. Factory doesn't own it, you have to delete it when you're done.
*/
virtual DbAttacher* create(Db* db) = 0;
};
#endif // DBATTACHER_H
|