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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
#ifndef SCHEMARESOLVER_H
#define SCHEMARESOLVER_H
#include "parser/parser.h"
#include "parser/ast/sqlitequerytype.h"
#include "parser/ast/sqlitecreatetable.h"
#include "parser/ast/sqlitecreateindex.h"
#include "parser/ast/sqlitecreateview.h"
#include "parser/ast/sqlitecreatetrigger.h"
#include "coreSQLiteStudio_global.h"
#include "common/utils_sql.h"
#include "selectresolver.h"
#include "db/sqlresultsrow.h"
#include "db/sqlquery.h"
#include "db/db.h"
#include "common/strhash.h"
#include <QStringList>
class SqliteCreateTable;
// TODO add cache
class API_EXPORT SchemaResolver
{
public:
enum ObjectType
{
TABLE,
INDEX,
TRIGGER,
VIEW,
ANY
};
struct ObjectDetails
{
ObjectType type;
QString ddl;
};
explicit SchemaResolver(Db* db);
virtual ~SchemaResolver();
QStringList getTables(const QString& database = QString::null);
QStringList getIndexes(const QString& database = QString::null);
QStringList getTriggers(const QString& database = QString::null);
QStringList getViews(const QString& database = QString::null);
StrHash<QStringList> getGroupedIndexes(const QString& database = QString::null);
StrHash<QStringList> getGroupedTriggers(const QString& database = QString::null);
QSet<QString> getDatabases();
QStringList getObjects(const QString& type);
QStringList getObjects(const QString& database, const QString& type);
QStringList getAllObjects();
QStringList getAllObjects(const QString& database);
QString getUniqueName(const QString& database, const QString& namePrefix, const QStringList& forbiddenNames = QStringList());
QString getUniqueName(const QString& namePrefix = QString::null, const QStringList& forbiddenNames = QStringList());
QStringList getFkReferencingTables(const QString& table);
QStringList getFkReferencingTables(const QString& database, const QString& table);
QStringList getIndexesForTable(const QString& database, const QString& table);
QStringList getIndexesForTable(const QString& table);
QStringList getTriggersForTable(const QString& database, const QString& table);
QStringList getTriggersForTable(const QString& table);
QStringList getTriggersForView(const QString& database, const QString& view);
QStringList getTriggersForView(const QString& view);
QStringList getViewsForTable(const QString& database, const QString& table);
QStringList getViewsForTable(const QString& table);
StrHash<ObjectDetails> getAllObjectDetails();
StrHash<ObjectDetails> getAllObjectDetails(const QString& database);
QList<SqliteCreateIndexPtr> getParsedIndexesForTable(const QString& database, const QString& table);
QList<SqliteCreateIndexPtr> getParsedIndexesForTable(const QString& table);
QList<SqliteCreateTriggerPtr> getParsedTriggersForTable(const QString& database, const QString& table, bool includeContentReferences = false);
QList<SqliteCreateTriggerPtr> getParsedTriggersForTable(const QString& table, bool includeContentReferences = false);
QList<SqliteCreateTriggerPtr> getParsedTriggersForView(const QString& database, const QString& view, bool includeContentReferences = false);
QList<SqliteCreateTriggerPtr> getParsedTriggersForView(const QString& view, bool includeContentReferences = false);
QList<SqliteCreateViewPtr> getParsedViewsForTable(const QString& database, const QString& table);
QList<SqliteCreateViewPtr> getParsedViewsForTable(const QString& table);
bool isWithoutRowIdTable(const QString& table);
bool isWithoutRowIdTable(const QString& database, const QString& table);
bool isVirtualTable(const QString& database, const QString& table);
bool isVirtualTable(const QString& table);
SqliteCreateTablePtr resolveVirtualTableAsRegularTable(const QString& table);
SqliteCreateTablePtr resolveVirtualTableAsRegularTable(const QString& database, const QString& table);
QStringList getWithoutRowIdTableColumns(const QString& table);
QStringList getWithoutRowIdTableColumns(const QString& database, const QString& table);
/**
* @brief getTableColumns Get column names for a table.
* @param table Table to query.
* @return List of column names of the table.
* This does something similar to getting list of columns with
* PRAGMA table_info(), but the pragma in Sqlite2 doesn't support
* queries for attached databases, therefore this method is provided
* to make this possible. It finds table's DDL and parses it,
* then extracts list of columns from parsing results.
*/
QStringList getTableColumns(const QString& table);
/**
* @brief getTableColumns Get column names for a table.
* @param database Attached database name.
* @param table Table to query.
* @return List of column names of the table.
* @overload
*/
QStringList getTableColumns(const QString& database, const QString& table);
QList<DataType> getTableColumnDataTypes(const QString& table, int expectedNumberOfTypes = -1);
QList<DataType> getTableColumnDataTypes(const QString& database, const QString& table, int expectedNumberOfTypes = -1);
StrHash<QStringList> getAllTableColumns(const QString& database = QString::null);
QStringList getViewColumns(const QString& view);
QStringList getViewColumns(const QString& database, const QString& view);
QList<SelectResolver::Column> getViewColumnObjects(const QString& view);
QList<SelectResolver::Column> getViewColumnObjects(const QString& database, const QString& view);
QString getObjectDdl(const QString& name, ObjectType type);
QString getObjectDdl(const QString& database, const QString& name, ObjectType type);
/**
* @brief Parses given object's DDL.
* @param name Name of the object in the database.
* @return Parsed object, or null pointer if named object was not in the database, or parsing error occured.
*
* Returned query has to be deleted outside!
*/
SqliteQueryPtr getParsedObject(const QString& name, ObjectType type);
/**
* @brief Parses given object's DDL.
* @param database Database that the object is in (the attach name of the database).
* @param name Name of the object in the database.
* @return Parsed object, or null pointer if named object was not in the database, or parsing error occured.
* @overload
*/
SqliteQueryPtr getParsedObject(const QString& database, const QString& name, ObjectType type);
StrHash<SqliteQueryPtr> getAllParsedObjects();
StrHash<SqliteQueryPtr> getAllParsedObjects(const QString& database);
StrHash<SqliteCreateTablePtr> getAllParsedTables();
StrHash<SqliteCreateTablePtr> getAllParsedTables(const QString& database);
StrHash<SqliteCreateIndexPtr> getAllParsedIndexes();
StrHash<SqliteCreateIndexPtr> getAllParsedIndexes(const QString& database);
StrHash<SqliteCreateTriggerPtr> getAllParsedTriggers();
StrHash<SqliteCreateTriggerPtr> getAllParsedTriggers(const QString& database);
StrHash<SqliteCreateViewPtr> getAllParsedViews();
StrHash<SqliteCreateViewPtr> getAllParsedViews(const QString& database);
static QString getSqliteMasterDdl(bool temp = false);
static QStringList getFkReferencingTables(const QString& table, const QList<SqliteCreateTablePtr>& allParsedTables);
QStringList getCollations();
bool getIgnoreSystemObjects() const;
void setIgnoreSystemObjects(bool value);
bool getNoDbLocking() const;
void setNoDbLocking(bool value);
static QString objectTypeToString(ObjectType type);
static ObjectType stringToObjectType(const QString& type);
private:
SqliteQueryPtr getParsedDdl(const QString& ddl);
SqliteCreateTablePtr virtualTableAsRegularTable(const QString& database, const QString& table);
StrHash< QStringList> getGroupedObjects(const QString &database, const QStringList& inputList, SqliteQueryType type);
bool isFilteredOut(const QString& value, const QString& type);
void filterSystemIndexes(QStringList& indexes);
QList<SqliteCreateTriggerPtr> getParsedTriggersForTableOrView(const QString& database, const QString& tableOrView, bool includeContentReferences, bool table);
template <class T>
StrHash<QSharedPointer<T>> getAllParsedObjectsForType(const QString& database, const QString& type);
Db* db = nullptr;
Parser* parser = nullptr;
bool ignoreSystemObjects = false;
Db::Flags dbFlags;
};
template <class T>
StrHash<QSharedPointer<T>> SchemaResolver::getAllParsedObjectsForType(const QString& database, const QString& type)
{
StrHash< QSharedPointer<T>> parsedObjects;
QString dbName = getPrefixDb(database, db->getDialect());
SqlQueryPtr results;
if (type.isNull())
results = db->exec(QString("SELECT name, type, sql FROM %1.sqlite_master;").arg(dbName));
else
results = db->exec(QString("SELECT name, type, sql FROM %1.sqlite_master WHERE type = '%2';").arg(dbName, type));
QString name;
SqliteQueryPtr parsedObject;
QSharedPointer<T> castedObject;
foreach (SqlResultsRowPtr row, results->getAll())
{
name = row->value("name").toString();
parsedObject = getParsedDdl(row->value("sql").toString());
if (!parsedObject)
continue;
if (isFilteredOut(name, row->value("type").toString()))
continue;
castedObject = parsedObject.dynamicCast<T>();
if (castedObject)
parsedObjects[name] = castedObject;
}
return parsedObjects;
}
#endif // SCHEMARESOLVER_H
|