20#include "KDbTableSchemaChangeListener.h"
21#include "KDbConnection.h"
22#include "KDbConnection_p.h"
23#include "KDbLookupFieldSchema.h"
26#ifdef KDB_TABLESCHEMACHANGELISTENER_DEBUG
27# define localDebug(...) kdbDebug(__VA_ARGS__)
29# define localDebug(...) if (true) {} else kdbDebug(__VA_ARGS__)
32class KDbTableSchemaChangeListenerPrivate
35 KDbTableSchemaChangeListenerPrivate()
40 static void registerForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener,
41 const KDbTableSchema *table)
46 QSet<KDbTableSchemaChangeListener*>* listeners = conn->d->tableSchemaChangeListeners.value(table);
48 listeners =
new QSet<KDbTableSchemaChangeListener*>();
49 conn->d->tableSchemaChangeListeners.insert(table, listeners);
51 localDebug() <<
"listener=" << listener << listener->
name() <<
"table=" << table << table->
name();
52 listeners->
insert(listener);
56 static void registerForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener,
57 const KDbQuerySchema *query)
62 QSet<KDbTableSchemaChangeListener *> *listeners
63 = conn->d->queryTableSchemaChangeListeners.value(query);
65 listeners =
new QSet<KDbTableSchemaChangeListener*>();
66 conn->d->queryTableSchemaChangeListeners.insert(query, listeners);
68 localDebug() <<
"listener=" << listener->
name() <<
"query=" <<
query->name();
69 listeners->
insert(listener);
73 static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener,
74 const KDbTableSchema *table)
78 QSet<KDbTableSchemaChangeListener *> *listeners
79 = conn->d->tableSchemaChangeListeners.value(table);
84 <<
"table=" << table << table->
name();
86 listeners->
remove(listener);
88 delete conn->d->tableSchemaChangeListeners.take(table);
93 static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener,
94 const KDbQuerySchema *query)
98 QSet<KDbTableSchemaChangeListener *> *listeners
99 = conn->d->queryTableSchemaChangeListeners.value(query);
104 <<
"query=" <<
query->name();
106 listeners->
remove(listener);
113 static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener* listener)
117 localDebug() <<
"listener=" << listener->
name();
118 for (QSet<KDbTableSchemaChangeListener*> *listeners : conn->d->tableSchemaChangeListeners) {
119 listeners->
remove(listener);
121 for (QSet<KDbTableSchemaChangeListener*> *listeners : conn->d->queryTableSchemaChangeListeners) {
122 listeners->
remove(listener);
129 static bool tableDependsOnTable(QSet<const KDbTableSchema *> *checkedTables,
130 QSet<const KDbQuerySchema *> *checkedQueries,
131 KDbConnection *conn,
const KDbTableSchema *table1,
132 const KDbTableSchema *table2)
134 if (checkedTables->
contains(table1)) {
135 localDebug() <<
"Table" << table1 << table1->
name() <<
"already checked";
138 checkedTables->
insert(table1);
139 localDebug() <<
"Checking if table" << table1 << table1->
name() <<
"depends on table"
140 << table2 << table2->
name();
141 if (table1 == table2) {
142 localDebug() <<
"Yes";
145 for (KDbLookupFieldSchema *lookup : table1->
lookupFields()) {
146 switch (lookup->recordSource().type()) {
148 const KDbTableSchema *sourceTable
149 = conn->
tableSchema(lookup->recordSource().name());
151 && tableDependsOnTable(checkedTables, checkedQueries, conn, sourceTable, table2))
158 const KDbQuerySchema *sourceQuery
159 = conn->
querySchema(lookup->recordSource().name());
161 && queryDependsOnTable(checkedTables, checkedQueries, conn, sourceQuery, table2))
168 kdbWarning() <<
"Unsupported lookup field's source type" << lookup->recordSource().typeName();
173 localDebug() <<
"No";
179 static bool tableDependsOnQuery(QSet<const KDbTableSchema *> *checkedTables,
180 QSet<const KDbQuerySchema *> *checkedQueries,
181 KDbConnection *conn,
const KDbTableSchema *table,
182 const KDbQuerySchema *query)
184 if (checkedTables->
contains(table)) {
185 localDebug() <<
"Table" << table->
name() <<
"already checked";
188 checkedTables->
insert(table);
189 localDebug() <<
"Checking if table" << table->
name() <<
"depends on query" <<
query->name();
190 for (KDbLookupFieldSchema *lookup : table->
lookupFields()) {
191 switch (lookup->recordSource().type()) {
193 const KDbTableSchema *sourceTable
194 = conn->
tableSchema(lookup->recordSource().name());
196 && tableDependsOnQuery(checkedTables, checkedQueries, conn, sourceTable, query))
203 const KDbQuerySchema *sourceQuery
204 = conn->
querySchema(lookup->recordSource().name());
206 && queryDependsOnQuery(checkedTables, checkedQueries, conn, sourceQuery, query))
213 kdbWarning() <<
"Unsupported lookup field's source type" << lookup->recordSource().typeName();
223 static bool queryDependsOnTable(QSet<const KDbTableSchema *> *checkedTables,
224 QSet<const KDbQuerySchema *> *checkedQueries,
225 KDbConnection *conn,
const KDbQuerySchema *query,
226 const KDbTableSchema *table)
228 if (checkedQueries->
contains(query)) {
229 localDebug() <<
"Query" <<
query->name() <<
"already checked";
232 checkedQueries->
insert(query);
233 localDebug() <<
"Checking if query" <<
query->name() <<
"depends on table" << table->
name();
234 for (
const KDbTableSchema *queryTable : *
query->tables()) {
235 if (tableDependsOnTable(checkedTables, checkedQueries, conn, queryTable, table)) {
246 static bool queryDependsOnQuery(QSet<const KDbTableSchema *> *checkedTables,
247 QSet<const KDbQuerySchema *> *checkedQueries,
248 KDbConnection *conn,
const KDbQuerySchema *query1,
249 const KDbQuerySchema *query2)
251 if (checkedQueries->
contains(query1)) {
252 localDebug() <<
"Query" << query1->
name() <<
"already checked";
255 checkedQueries->
insert(query1);
256 localDebug() <<
"Checking if query" << query1->
name() <<
"depends on query" << query2->
name();
257 if (query1 == query2) {
258 localDebug() <<
"Yes";
261 for (
const KDbTableSchema *queryTable : *query1->
tables()) {
262 if (tableDependsOnQuery(checkedTables, checkedQueries, conn, queryTable, query2)) {
271 static void collectListeners(QSet<KDbTableSchemaChangeListener *> *result,
273 const KDbTableSchema *table)
279 for (QHash<
const KDbTableSchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it(
280 conn->d->tableSchemaChangeListeners.constBegin());
281 it != conn->d->tableSchemaChangeListeners.constEnd(); ++it)
284 QSet<const KDbTableSchema *> checkedTables;
285 QSet<const KDbQuerySchema *> checkedQueries;
286 if (tableDependsOnTable(&checkedTables, &checkedQueries, conn, it.key(), table)) {
287 QSet<KDbTableSchemaChangeListener*>* set = it.value();
292 for (QHash<
const KDbQuerySchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it(
293 conn->d->queryTableSchemaChangeListeners.constBegin());
294 it != conn->d->queryTableSchemaChangeListeners.constEnd(); ++it)
297 QSet<const KDbTableSchema *> checkedTables;
298 QSet<const KDbQuerySchema *> checkedQueries;
299 if (queryDependsOnTable(&checkedTables, &checkedQueries, conn, it.key(), table)) {
300 QSet<KDbTableSchemaChangeListener*>* set = it.value();
308 static void collectListeners(QSet<KDbTableSchemaChangeListener *> *result,
310 const KDbQuerySchema *query)
315 QSet<KDbTableSchemaChangeListener*>* set = conn->d->queryTableSchemaChangeListeners.value(query);
320 for (QHash<
const KDbTableSchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it(
321 conn->d->tableSchemaChangeListeners.constBegin());
322 it != conn->d->tableSchemaChangeListeners.constEnd(); ++it)
325 QSet<const KDbTableSchema *> checkedTables;
326 QSet<const KDbQuerySchema *> checkedQueries;
327 if (tableDependsOnQuery(&checkedTables, &checkedQueries, conn, it.key(), query)) {
328 QSet<KDbTableSchemaChangeListener*>* set = it.value();
333 for (QHash<
const KDbQuerySchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it(
334 conn->d->queryTableSchemaChangeListeners.constBegin());
335 it != conn->d->queryTableSchemaChangeListeners.constEnd(); ++it)
338 QSet<const KDbTableSchema *> checkedTables;
339 QSet<const KDbQuerySchema *> checkedQueries;
340 if (queryDependsOnQuery(&checkedTables, &checkedQueries, conn, it.key(), query)) {
341 QSet<KDbTableSchemaChangeListener*>* set = it.value();
348 Q_DISABLE_COPY(KDbTableSchemaChangeListenerPrivate)
351KDbTableSchemaChangeListener::KDbTableSchemaChangeListener()
352 : d(new KDbTableSchemaChangeListenerPrivate)
356KDbTableSchemaChangeListener::~KDbTableSchemaChangeListener()
373 KDbTableSchemaChangeListener* listener,
377 kdbWarning() <<
"Missing connection";
381 kdbWarning() <<
"Missing listener";
385 kdbWarning() <<
"Missing table";
388 KDbTableSchemaChangeListenerPrivate::registerForChanges(conn, listener, table);
393 KDbTableSchemaChangeListener *listener,
397 kdbWarning() <<
"Missing connection";
401 kdbWarning() <<
"Missing listener";
405 kdbWarning() <<
"Missing query";
408 KDbTableSchemaChangeListenerPrivate::registerForChanges(conn, listener, query);
413 KDbTableSchemaChangeListener* listener,
417 kdbWarning() <<
"Missing connection";
421 kdbWarning() <<
"Missing listener";
425 kdbWarning() <<
"Missing table";
428 KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, listener, table);
436 kdbWarning() <<
"Missing connection";
440 kdbWarning() <<
"Missing table";
443 KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn,
nullptr, table);
447 KDbTableSchemaChangeListener *listener,
451 kdbWarning() <<
"Missing connection";
455 kdbWarning() <<
"Missing listener";
459 kdbWarning() <<
"Missing query";
462 KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, listener, query);
470 kdbWarning() <<
"Missing connection";
474 kdbWarning() <<
"Missing query";
477 KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn,
nullptr, query);
485 kdbWarning() <<
"Missing connection";
489 kdbWarning() <<
"Missing listener";
492 KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, listener);
500 kdbWarning() <<
"Missing connection";
504 kdbWarning() <<
"Missing table";
508 KDbTableSchemaChangeListenerPrivate::collectListeners(&result, conn, table);
517 kdbWarning() <<
"Missing connection";
521 kdbWarning() <<
"Missing query";
525 KDbTableSchemaChangeListenerPrivate::collectListeners(&result, conn, query);
534 kdbWarning() <<
"Missing connection";
538 kdbWarning() <<
"Missing table";
543 for (KDbTableSchemaChangeListener *listener : qAsConst(toClose)) {
545 if (localResult !=
true) {
546 result = localResult;
557 kdbWarning() <<
"Missing connection";
561 kdbWarning() <<
"Missing query";
566 for (KDbTableSchemaChangeListener *listener : qAsConst(toClose)) {
568 if (localResult !=
true) {
569 result = localResult;
Provides database connection, allowing queries and data modification.
KDbTableSchema * tableSchema(int tableId)
KDbQuerySchema * querySchema(int queryId)
@ Table
table as lookup record source
@ Query
named query as lookup record source
KDbQuerySchema provides information about database query.
QList< KDbTableSchema * > * tables() const
virtual tristate closeListener()=0
Closes listening object so it will be deleted and thus no longer use a conflicting table schema.
static tristate closeListeners(KDbConnection *conn, const KDbTableSchema *table, const QList< KDbTableSchemaChangeListener * > &except=QList< KDbTableSchemaChangeListener * >())
Closes all table schema listeners for table schema table except for the ones from the except list.
static void registerForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener, const KDbTableSchema *table)
Registers listener for receiving (listening) information about changes in table schema table and all ...
static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener, const KDbTableSchema *table)
Unregisters listener for receiving (listening) information about changes in table schema table.
static QList< KDbTableSchemaChangeListener * > listeners(KDbConnection *conn, const KDbTableSchema *table)
void setName(const QString &name)
QVector< KDbLookupFieldSchema * > lookupFields() const
3-state logical type with three values: true, false and cancelled and convenient operators.
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
bool remove(const T &value)
QSet< T > & unite(const QSet< T > &other)
QList< T > values() const const
QString fromLatin1(QByteArrayView str)