-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathSchema.cpp
More file actions
124 lines (109 loc) · 3.88 KB
/
Copy pathSchema.cpp
File metadata and controls
124 lines (109 loc) · 3.88 KB
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
#include "Schema.h"
#include <QSqlQuery>
#include <QSqlError>
bool Schema::load(QSqlDatabase& db)
{
m_tables.clear();
m_foreignKeys.clear();
m_indexes.clear();
m_errorMessage.clear();
QSqlQuery tableListQuery(db);
if (!tableListQuery.exec(
"SELECT name FROM sqlite_master "
"WHERE type='table' AND name NOT LIKE 'sqlite_%' "
"ORDER BY name;")) {
m_errorMessage = tableListQuery.lastError().text();
return false;
}
while (tableListQuery.next()) {
Table table;
table.name = tableListQuery.value(0).toString();
// PRAGMA statements can't be parameterised, so we build the string
// directly. Table names come from sqlite_master, not user input,
// so this is safe.
QSqlQuery columnQuery(db);
if (!columnQuery.exec(QString("PRAGMA table_info(%1);").arg(table.name))) {
m_errorMessage = columnQuery.lastError().text();
return false;
}
while (columnQuery.next()) {
Column col;
col.name = columnQuery.value("name").toString();
col.type = columnQuery.value("type").toString();
col.isNotNull = columnQuery.value("notnull").toInt() != 0;
col.isPrimaryKey = columnQuery.value("pk").toInt() != 0;
table.columns.push_back(col);
}
QSqlQuery fkQuery(db);
if (!fkQuery.exec(QString("PRAGMA foreign_key_list(%1);").arg(table.name))) {
m_errorMessage = fkQuery.lastError().text();
return false;
}
while (fkQuery.next()) {
ForeignKey fk;
fk.fromTable = table.name;
fk.fromColumn = fkQuery.value("from").toString();
fk.toTable = fkQuery.value("table").toString();
fk.toColumn = fkQuery.value("to").toString();
m_foreignKeys.push_back(fk);
}
QSqlQuery indexListQuery(db);
if (!indexListQuery.exec(QString("PRAGMA index_list(%1);").arg(table.name))) {
m_errorMessage = indexListQuery.lastError().text();
return false;
}
while (indexListQuery.next()) {
const QString indexName = indexListQuery.value("name").toString();
// SQLite creates these implicitly to back PRIMARY KEY/UNIQUE
// constraints; they can't be dropped directly and aren't
// something the user created, so skip them.
if (indexName.startsWith("sqlite_autoindex_")) {
continue;
}
Index index;
index.name = indexName;
index.table = table.name;
index.isUnique = indexListQuery.value("unique").toInt() != 0;
QSqlQuery indexInfoQuery(db);
if (!indexInfoQuery.exec(QString("PRAGMA index_info(%1);").arg(index.name))) {
m_errorMessage = indexInfoQuery.lastError().text();
return false;
}
while (indexInfoQuery.next()) {
index.columns << indexInfoQuery.value("name").toString();
}
m_indexes.push_back(index);
}
m_tables.push_back(table);
}
return true;
}
const Table* Schema::findTable(const QString& tableName) const
{
for (const auto& t : m_tables) {
if (t.name == tableName) {
return &t;
}
}
return nullptr;
}
QVector<ForeignKey> Schema::relationsFor(const QString& tableName) const
{
QVector<ForeignKey> result;
for (const auto& fk : m_foreignKeys) {
if (fk.fromTable == tableName || fk.toTable == tableName) {
result.push_back(fk);
}
}
return result;
}
QVector<Index> Schema::indexesFor(const QString& tableName) const
{
QVector<Index> result;
for (const auto& index : m_indexes) {
if (index.table == tableName) {
result.push_back(index);
}
}
return result;
}