Changeset View
Changeset View
Standalone View
Standalone View
src/KDbTableSchemaChangeListener.cpp
1 | /* This file is part of the KDE project | 1 | /* This file is part of the KDE project | ||
---|---|---|---|---|---|
2 | Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org> | 2 | Copyright (C) 2003-2017 Jarosław Staniek <staniek@kde.org> | ||
3 | 3 | | |||
4 | This program is free software; you can redistribute it and/or | 4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public | 5 | modify it under the terms of the GNU Library General Public | ||
6 | License as published by the Free Software Foundation; either | 6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | 7 | version 2 of the License, or (at your option) any later version. | ||
8 | 8 | | |||
9 | This program is distributed in the hope that it will be useful, | 9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Library General Public License for more details. | 12 | Library General Public License for more details. | ||
13 | 13 | | |||
14 | You should have received a copy of the GNU Library General Public License | 14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; see the file COPYING. If not, write to | 15 | along with this program; see the file COPYING. If not, write to | ||
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | * Boston, MA 02110-1301, USA. | 17 | * Boston, MA 02110-1301, USA. | ||
18 | */ | 18 | */ | ||
19 | 19 | | |||
20 | #include "KDbTableSchemaChangeListener.h" | 20 | #include "KDbTableSchemaChangeListener.h" | ||
21 | #include "KDbConnection.h" | 21 | #include "KDbConnection.h" | ||
22 | #include "KDbConnection_p.h" | 22 | #include "KDbConnection_p.h" | ||
23 | #include "KDbLookupFieldSchema.h" | ||||
24 | #include "kdb_debug.h" | ||||
23 | 25 | | |||
24 | class Q_DECL_HIDDEN KDbTableSchemaChangeListener::Private | 26 | #ifdef KDB_TABLESCHEMACHANGELISTENER_DEBUG | ||
27 | # define localDebug(...) kdbDebug(__VA_ARGS__) | ||||
28 | #else | ||||
29 | # define localDebug(...) if (true) {} else kdbDebug(__VA_ARGS__) | ||||
30 | #endif | ||||
31 | | ||||
32 | class KDbTableSchemaChangeListenerPrivate | ||||
25 | { | 33 | { | ||
26 | public: | 34 | public: | ||
27 | Private() {} | 35 | KDbTableSchemaChangeListenerPrivate() | ||
36 | { | ||||
37 | } | ||||
38 | | ||||
39 | //! Registers listener @a listener for changes in table @a table | ||||
40 | static void registerForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener, | ||||
41 | const KDbTableSchema *table) | ||||
42 | { | ||||
43 | Q_ASSERT(conn); | ||||
44 | Q_ASSERT(listener); | ||||
45 | Q_ASSERT(table); | ||||
46 | QSet<KDbTableSchemaChangeListener*>* listeners = conn->d->tableSchemaChangeListeners.value(table); | ||||
47 | if (!listeners) { | ||||
48 | listeners = new QSet<KDbTableSchemaChangeListener*>(); | ||||
49 | conn->d->tableSchemaChangeListeners.insert(table, listeners); | ||||
50 | } | ||||
51 | localDebug() << "listener=" << listener->name() << "table=" << table->name(); | ||||
52 | listeners->insert(listener); | ||||
53 | } | ||||
54 | | ||||
55 | //! Registers listener @a listener for changes in query @a query | ||||
56 | static void registerForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener, | ||||
57 | const KDbQuerySchema *query) | ||||
58 | { | ||||
59 | Q_ASSERT(conn); | ||||
60 | Q_ASSERT(listener); | ||||
61 | Q_ASSERT(query); | ||||
62 | QSet<KDbTableSchemaChangeListener *> *listeners | ||||
63 | = conn->d->queryTableSchemaChangeListeners.value(query); | ||||
64 | if (!listeners) { | ||||
65 | listeners = new QSet<KDbTableSchemaChangeListener*>(); | ||||
66 | conn->d->queryTableSchemaChangeListeners.insert(query, listeners); | ||||
67 | } | ||||
68 | localDebug() << "listener=" << listener->name() << "query=" << query->name(); | ||||
69 | listeners->insert(listener); | ||||
70 | } | ||||
71 | | ||||
72 | //! Unregisters listener @a listener for changes in table @a table | ||||
73 | static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener, | ||||
74 | const KDbTableSchema *table) | ||||
75 | { | ||||
76 | Q_ASSERT(conn); | ||||
77 | Q_ASSERT(table); | ||||
78 | QSet<KDbTableSchemaChangeListener *> *listeners | ||||
79 | = conn->d->tableSchemaChangeListeners.value(table); | ||||
80 | if (!listeners) { | ||||
81 | return; | ||||
82 | } | ||||
83 | localDebug() << "listener=" << (listener ? listener->name() : QString::fromLatin1("<all>")) | ||||
84 | << "table=" << table->name(); | ||||
85 | if (listener) { | ||||
86 | listeners->remove(listener); | ||||
87 | } else { | ||||
88 | listeners->clear(); | ||||
89 | } | ||||
90 | } | ||||
91 | | ||||
92 | //! Unregisters listener @a listener for changes in query @a query | ||||
93 | static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener *listener, | ||||
94 | const KDbQuerySchema *query) | ||||
95 | { | ||||
96 | Q_ASSERT(conn); | ||||
97 | Q_ASSERT(query); | ||||
98 | QSet<KDbTableSchemaChangeListener *> *listeners | ||||
99 | = conn->d->queryTableSchemaChangeListeners.value(query); | ||||
100 | if (!listeners) { | ||||
101 | return; | ||||
102 | } | ||||
103 | localDebug() << "listener=" << (listener ? listener->name() : QString::fromLatin1("<all>")) | ||||
104 | << "query=" << query->name(); | ||||
105 | if (listener) { | ||||
106 | listeners->remove(listener); | ||||
107 | } else { | ||||
108 | listeners->clear(); | ||||
109 | } | ||||
110 | } | ||||
111 | | ||||
112 | //! Unregisters listener @a listener for any changes | ||||
113 | static void unregisterForChanges(KDbConnection *conn, KDbTableSchemaChangeListener* listener) | ||||
114 | { | ||||
115 | Q_ASSERT(conn); | ||||
116 | Q_ASSERT(listener); | ||||
117 | localDebug() << "listener=" << listener->name(); | ||||
118 | for (QSet<KDbTableSchemaChangeListener*> *listeners : conn->d->tableSchemaChangeListeners) { | ||||
119 | listeners->remove(listener); | ||||
120 | } | ||||
121 | for (QSet<KDbTableSchemaChangeListener*> *listeners : conn->d->queryTableSchemaChangeListeners) { | ||||
122 | listeners->remove(listener); | ||||
123 | } | ||||
124 | } | ||||
125 | | ||||
126 | //! Returns @c true if @a table1 depends on @a table2, that is, if: | ||||
127 | //! - @a table1 == @a table2, or | ||||
128 | //! - @a table1 has lookup columns that reference @a table2 | ||||
129 | static bool tableDependsOnTable(QSet<const KDbTableSchema *> *checkedTables, | ||||
130 | QSet<const KDbQuerySchema *> *checkedQueries, | ||||
131 | KDbConnection *conn, const KDbTableSchema *table1, | ||||
132 | const KDbTableSchema *table2) | ||||
133 | { | ||||
134 | if (checkedTables->contains(table1)) { | ||||
135 | localDebug() << "Table" << table1->name() << "already checked"; | ||||
136 | return false; // protection against infinite recursion | ||||
137 | } | ||||
138 | checkedTables->insert(table1); | ||||
139 | localDebug() << "Checking if table" << table1->name() << "depends on table" << table2->name(); | ||||
140 | if (table1 == table2) { | ||||
141 | localDebug() << "Yes"; | ||||
142 | return true; | ||||
143 | } | ||||
144 | for (KDbLookupFieldSchema *lookup : table1->lookupFields()) { | ||||
145 | switch (lookup->recordSource().type()) { | ||||
146 | case KDbLookupFieldSchemaRecordSource::Type::Table: { | ||||
147 | const KDbTableSchema *sourceTable | ||||
148 | = conn->tableSchema(lookup->recordSource().name()); | ||||
149 | if (sourceTable | ||||
150 | && tableDependsOnTable(checkedTables, checkedQueries, conn, sourceTable, table2)) | ||||
151 | { | ||||
152 | return true; | ||||
153 | } | ||||
154 | break; | ||||
155 | } | ||||
156 | case KDbLookupFieldSchemaRecordSource::Type::Query: { | ||||
157 | const KDbQuerySchema *sourceQuery | ||||
158 | = conn->querySchema(lookup->recordSource().name()); | ||||
159 | if (sourceQuery | ||||
160 | && queryDependsOnTable(checkedTables, checkedQueries, conn, sourceQuery, table2)) | ||||
161 | { | ||||
162 | return true; | ||||
163 | } | ||||
164 | break; | ||||
165 | } | ||||
166 | default: | ||||
167 | kdbWarning() << "Unsupported lookup field's source type" << lookup->recordSource().typeName(); | ||||
168 | //! @todo support more record source types | ||||
169 | break; | ||||
170 | } | ||||
171 | } | ||||
172 | return false; | ||||
173 | } | ||||
174 | | ||||
175 | //! Returns @c true if @a table depends on @a query, that is, if: | ||||
176 | //! - @a table has lookup columns that reference @a query | ||||
177 | static bool tableDependsOnQuery(QSet<const KDbTableSchema *> *checkedTables, | ||||
178 | QSet<const KDbQuerySchema *> *checkedQueries, | ||||
179 | KDbConnection *conn, const KDbTableSchema *table, | ||||
180 | const KDbQuerySchema *query) | ||||
181 | { | ||||
182 | if (checkedTables->contains(table)) { | ||||
183 | localDebug() << "Table" << table->name() << "already checked"; | ||||
184 | return false; // protection against infinite recursion | ||||
185 | } | ||||
186 | checkedTables->insert(table); | ||||
187 | localDebug() << "Checking if table" << table->name() << "depends on query" << query->name(); | ||||
188 | for (KDbLookupFieldSchema *lookup : table->lookupFields()) { | ||||
189 | switch (lookup->recordSource().type()) { | ||||
190 | case KDbLookupFieldSchemaRecordSource::Type::Table: { | ||||
191 | const KDbTableSchema *sourceTable | ||||
192 | = conn->tableSchema(lookup->recordSource().name()); | ||||
193 | if (sourceTable | ||||
194 | && tableDependsOnQuery(checkedTables, checkedQueries, conn, sourceTable, query)) | ||||
195 | { | ||||
196 | return true; | ||||
197 | } | ||||
198 | break; | ||||
199 | } | ||||
200 | case KDbLookupFieldSchemaRecordSource::Type::Query: { | ||||
201 | const KDbQuerySchema *sourceQuery | ||||
202 | = conn->querySchema(lookup->recordSource().name()); | ||||
203 | if (sourceQuery | ||||
204 | && queryDependsOnQuery(checkedTables, checkedQueries, conn, sourceQuery, query)) | ||||
205 | { | ||||
206 | return true; | ||||
207 | } | ||||
208 | break; | ||||
209 | } | ||||
210 | default: | ||||
211 | kdbWarning() << "Unsupported lookup field's source type" << lookup->recordSource().typeName(); | ||||
212 | //! @todo support more record source types | ||||
213 | } | ||||
214 | } | ||||
215 | return false; | ||||
216 | } | ||||
217 | | ||||
218 | //! Returns @c true if @a query depends on @a table, that is, if: | ||||
219 | //! - @a query references table that depends on @a table (dependency is checked using | ||||
220 | //! tableDependsOnTable()) | ||||
221 | static bool queryDependsOnTable(QSet<const KDbTableSchema *> *checkedTables, | ||||
222 | QSet<const KDbQuerySchema *> *checkedQueries, | ||||
223 | KDbConnection *conn, const KDbQuerySchema *query, | ||||
224 | const KDbTableSchema *table) | ||||
225 | { | ||||
226 | if (checkedQueries->contains(query)) { | ||||
227 | localDebug() << "Query" << query->name() << "already checked"; | ||||
228 | return false; // protection against infinite recursion | ||||
229 | } | ||||
230 | checkedQueries->insert(query); | ||||
231 | localDebug() << "Checking if query" << query->name() << "depends on table" << table->name(); | ||||
232 | for (const KDbTableSchema *queryTable : *query->tables()) { | ||||
233 | if (tableDependsOnTable(checkedTables, checkedQueries, conn, queryTable, table)) { | ||||
234 | return true; | ||||
235 | } | ||||
236 | } | ||||
237 | return false; | ||||
238 | } | ||||
239 | | ||||
240 | //! Returns @c true if @a query1 depends on @a query2, that is, if: | ||||
241 | //! - @a query1 == @a query2, or | ||||
242 | //! - @a query2 references table that depends on @a query (dependency is checked using | ||||
243 | //! tableDependsOnQuery()) | ||||
244 | static bool queryDependsOnQuery(QSet<const KDbTableSchema *> *checkedTables, | ||||
245 | QSet<const KDbQuerySchema *> *checkedQueries, | ||||
246 | KDbConnection *conn, const KDbQuerySchema *query1, | ||||
247 | const KDbQuerySchema *query2) | ||||
248 | { | ||||
249 | if (checkedQueries->contains(query1)) { | ||||
250 | localDebug() << "Query" << query1->name() << "already checked"; | ||||
251 | return false; // protection against infinite recursion | ||||
252 | } | ||||
253 | checkedQueries->insert(query1); | ||||
254 | localDebug() << "Checking if query" << query1->name() << "depends on query" << query2->name(); | ||||
255 | if (query1 == query2) { | ||||
256 | localDebug() << "Yes"; | ||||
257 | return true; | ||||
258 | } | ||||
259 | for (const KDbTableSchema *queryTable : *query1->tables()) { | ||||
260 | if (tableDependsOnQuery(checkedTables, checkedQueries, conn, queryTable, query2)) { | ||||
261 | return true; | ||||
262 | } | ||||
263 | } | ||||
264 | return false; | ||||
265 | } | ||||
266 | | ||||
267 | //! Inserts to @a *result all listeners that listen to changes in table @a table and other tables | ||||
268 | //! or queries depending on @a table. | ||||
269 | static void collectListeners(QSet<KDbTableSchemaChangeListener *> *result, | ||||
270 | KDbConnection *conn, | ||||
271 | const KDbTableSchema *table) | ||||
272 | { | ||||
273 | Q_ASSERT(result); | ||||
274 | Q_ASSERT(conn); | ||||
275 | Q_ASSERT(table); | ||||
276 | // for all tables with listeners: | ||||
277 | for (QHash<const KDbTableSchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it( | ||||
278 | conn->d->tableSchemaChangeListeners.constBegin()); | ||||
279 | it != conn->d->tableSchemaChangeListeners.constEnd(); ++it) | ||||
280 | { | ||||
281 | // check if it depends on our table | ||||
282 | QSet<const KDbTableSchema *> checkedTables; | ||||
283 | QSet<const KDbQuerySchema *> checkedQueries; | ||||
284 | if (tableDependsOnTable(&checkedTables, &checkedQueries, conn, it.key(), table)) { | ||||
285 | QSet<KDbTableSchemaChangeListener*>* set = it.value(); | ||||
286 | result->unite(*set); | ||||
287 | } | ||||
288 | } | ||||
289 | // for all queries with listeners: | ||||
290 | for (QHash<const KDbQuerySchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it( | ||||
291 | conn->d->queryTableSchemaChangeListeners.constBegin()); | ||||
292 | it != conn->d->queryTableSchemaChangeListeners.constEnd(); ++it) | ||||
293 | { | ||||
294 | // check if it depends on our table | ||||
295 | QSet<const KDbTableSchema *> checkedTables; | ||||
296 | QSet<const KDbQuerySchema *> checkedQueries; | ||||
297 | if (queryDependsOnTable(&checkedTables, &checkedQueries, conn, it.key(), table)) { | ||||
298 | QSet<KDbTableSchemaChangeListener*>* set = it.value(); | ||||
299 | result->unite(*set); | ||||
300 | } | ||||
301 | } | ||||
302 | } | ||||
303 | | ||||
304 | //! Inserts to @a *result all listeners that listen to changes in query @a table and other tables | ||||
305 | //! or queries depending on @a query. | ||||
306 | static void collectListeners(QSet<KDbTableSchemaChangeListener *> *result, | ||||
307 | KDbConnection *conn, | ||||
308 | const KDbQuerySchema *query) | ||||
309 | { | ||||
310 | Q_ASSERT(result); | ||||
311 | Q_ASSERT(conn); | ||||
312 | Q_ASSERT(query); | ||||
313 | QSet<KDbTableSchemaChangeListener*>* set = conn->d->queryTableSchemaChangeListeners.value(query); | ||||
314 | if (set) { | ||||
315 | result->unite(*set); | ||||
316 | } | ||||
317 | // for all tables with listeners: | ||||
318 | for (QHash<const KDbTableSchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it( | ||||
319 | conn->d->tableSchemaChangeListeners.constBegin()); | ||||
320 | it != conn->d->tableSchemaChangeListeners.constEnd(); ++it) | ||||
321 | { | ||||
322 | // check if it depends on our query | ||||
323 | QSet<const KDbTableSchema *> checkedTables; | ||||
324 | QSet<const KDbQuerySchema *> checkedQueries; | ||||
325 | if (tableDependsOnQuery(&checkedTables, &checkedQueries, conn, it.key(), query)) { | ||||
326 | QSet<KDbTableSchemaChangeListener*>* set = it.value(); | ||||
327 | result->unite(*set); | ||||
328 | } | ||||
329 | } | ||||
330 | // for all queries with listeners: | ||||
331 | for (QHash<const KDbQuerySchema*, QSet<KDbTableSchemaChangeListener*>* >::ConstIterator it( | ||||
332 | conn->d->queryTableSchemaChangeListeners.constBegin()); | ||||
333 | it != conn->d->queryTableSchemaChangeListeners.constEnd(); ++it) | ||||
334 | { | ||||
335 | // check if it depends on our query | ||||
336 | QSet<const KDbTableSchema *> checkedTables; | ||||
337 | QSet<const KDbQuerySchema *> checkedQueries; | ||||
338 | if (queryDependsOnQuery(&checkedTables, &checkedQueries, conn, it.key(), query)) { | ||||
339 | QSet<KDbTableSchemaChangeListener*>* set = it.value(); | ||||
340 | result->unite(*set); | ||||
341 | } | ||||
342 | } | ||||
343 | } | ||||
344 | | ||||
28 | QString name; | 345 | QString name; | ||
29 | Q_DISABLE_COPY(Private) | 346 | Q_DISABLE_COPY(KDbTableSchemaChangeListenerPrivate) | ||
30 | }; | 347 | }; | ||
31 | 348 | | |||
32 | KDbTableSchemaChangeListener::KDbTableSchemaChangeListener() | 349 | KDbTableSchemaChangeListener::KDbTableSchemaChangeListener() | ||
33 | : d(new Private) | 350 | : d(new KDbTableSchemaChangeListenerPrivate) | ||
34 | { | 351 | { | ||
35 | } | 352 | } | ||
36 | 353 | | |||
37 | KDbTableSchemaChangeListener::~KDbTableSchemaChangeListener() | 354 | KDbTableSchemaChangeListener::~KDbTableSchemaChangeListener() | ||
38 | { | 355 | { | ||
39 | delete d; | 356 | delete d; | ||
40 | } | 357 | } | ||
41 | 358 | | |||
42 | QString KDbTableSchemaChangeListener::name() const | 359 | QString KDbTableSchemaChangeListener::name() const | ||
43 | { | 360 | { | ||
44 | return d->name; | 361 | return d->name; | ||
45 | } | 362 | } | ||
46 | 363 | | |||
47 | void KDbTableSchemaChangeListener::setName(const QString &name) | 364 | void KDbTableSchemaChangeListener::setName(const QString &name) | ||
48 | { | 365 | { | ||
49 | d->name = name; | 366 | d->name = name; | ||
50 | } | 367 | } | ||
51 | 368 | | |||
52 | // static | 369 | // static | ||
53 | void KDbTableSchemaChangeListener::registerForChanges(KDbConnection *conn, | 370 | void KDbTableSchemaChangeListener::registerForChanges(KDbConnection *conn, | ||
54 | KDbTableSchemaChangeListener* listener, | 371 | KDbTableSchemaChangeListener* listener, | ||
55 | const KDbTableSchema* table) | 372 | const KDbTableSchema* table) | ||
56 | { | 373 | { | ||
57 | QSet<KDbTableSchemaChangeListener*>* listeners = conn->d->tableSchemaChangeListeners.value(table); | 374 | if (!conn) { | ||
58 | if (!listeners) { | 375 | kdbWarning() << "Missing connection"; | ||
59 | listeners = new QSet<KDbTableSchemaChangeListener*>(); | 376 | return; | ||
60 | conn->d->tableSchemaChangeListeners.insert(table, listeners); | | |||
61 | } | 377 | } | ||
62 | listeners->insert(listener); | 378 | if (!listener) { | ||
379 | kdbWarning() << "Missing listener"; | ||||
380 | return; | ||||
381 | } | ||||
382 | if (!table) { | ||||
383 | kdbWarning() << "Missing table"; | ||||
384 | return; | ||||
385 | } | ||||
386 | KDbTableSchemaChangeListenerPrivate::registerForChanges(conn, listener, table); | ||||
387 | } | ||||
388 | | ||||
389 | // static | ||||
390 | void KDbTableSchemaChangeListener::registerForChanges(KDbConnection *conn, | ||||
391 | KDbTableSchemaChangeListener *listener, | ||||
392 | const KDbQuerySchema *query) | ||||
393 | { | ||||
394 | if (!conn) { | ||||
395 | kdbWarning() << "Missing connection"; | ||||
396 | return; | ||||
397 | } | ||||
398 | if (!listener) { | ||||
399 | kdbWarning() << "Missing listener"; | ||||
400 | return; | ||||
401 | } | ||||
402 | if (!query) { | ||||
403 | kdbWarning() << "Missing query"; | ||||
404 | return; | ||||
405 | } | ||||
406 | KDbTableSchemaChangeListenerPrivate::registerForChanges(conn, listener, query); | ||||
63 | } | 407 | } | ||
64 | 408 | | |||
65 | // static | 409 | // static | ||
66 | void KDbTableSchemaChangeListener::unregisterForChanges(KDbConnection *conn, | 410 | void KDbTableSchemaChangeListener::unregisterForChanges(KDbConnection *conn, | ||
67 | KDbTableSchemaChangeListener* listener, | 411 | KDbTableSchemaChangeListener* listener, | ||
68 | const KDbTableSchema* table) | 412 | const KDbTableSchema* table) | ||
69 | { | 413 | { | ||
70 | QSet<KDbTableSchemaChangeListener*>* listeners = conn->d->tableSchemaChangeListeners.value(table); | 414 | if (!conn) { | ||
71 | if (!listeners) | 415 | kdbWarning() << "Missing connection"; | ||
416 | return; | ||||
417 | } | ||||
418 | if (!listener) { | ||||
419 | kdbWarning() << "Missing listener"; | ||||
72 | return; | 420 | return; | ||
73 | listeners->remove(listener); | 421 | } | ||
422 | if (!table) { | ||||
423 | kdbWarning() << "Missing table"; | ||||
424 | return; | ||||
425 | } | ||||
426 | KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, listener, table); | ||||
74 | } | 427 | } | ||
75 | 428 | | |||
76 | // static | 429 | // static | ||
77 | void KDbTableSchemaChangeListener::unregisterForChanges(KDbConnection *conn, | 430 | void KDbTableSchemaChangeListener::unregisterForChanges(KDbConnection *conn, | ||
78 | KDbTableSchemaChangeListener* listener) | 431 | const KDbTableSchema* table) | ||
79 | { | 432 | { | ||
80 | foreach(QSet<KDbTableSchemaChangeListener*> *listeners, conn->d->tableSchemaChangeListeners) { | 433 | if (!conn) { | ||
81 | listeners->remove(listener); | 434 | kdbWarning() << "Missing connection"; | ||
435 | return; | ||||
436 | } | ||||
437 | if (!table) { | ||||
438 | kdbWarning() << "Missing table"; | ||||
439 | return; | ||||
440 | } | ||||
441 | KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, nullptr, table); | ||||
442 | } | ||||
443 | | ||||
444 | void KDbTableSchemaChangeListener::unregisterForChanges(KDbConnection *conn, | ||||
445 | KDbTableSchemaChangeListener *listener, | ||||
446 | const KDbQuerySchema *query) | ||||
447 | { | ||||
448 | if (!conn) { | ||||
449 | kdbWarning() << "Missing connection"; | ||||
450 | return; | ||||
451 | } | ||||
452 | if (!listener) { | ||||
453 | kdbWarning() << "Missing listener"; | ||||
454 | return; | ||||
455 | } | ||||
456 | if (!query) { | ||||
457 | kdbWarning() << "Missing query"; | ||||
458 | return; | ||||
459 | } | ||||
460 | KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, listener, query); | ||||
461 | } | ||||
462 | | ||||
463 | // static | ||||
464 | void KDbTableSchemaChangeListener::unregisterForChanges(KDbConnection *conn, | ||||
465 | const KDbQuerySchema *query) | ||||
466 | { | ||||
467 | if (!conn) { | ||||
468 | kdbWarning() << "Missing connection"; | ||||
469 | return; | ||||
470 | } | ||||
471 | if (!query) { | ||||
472 | kdbWarning() << "Missing query"; | ||||
473 | return; | ||||
82 | } | 474 | } | ||
475 | KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, nullptr, query); | ||||
476 | } | ||||
477 | | ||||
478 | // static | ||||
479 | void KDbTableSchemaChangeListener::unregisterForChanges( | ||||
480 | KDbConnection *conn, KDbTableSchemaChangeListener* listener) | ||||
481 | { | ||||
482 | if (!conn) { | ||||
483 | kdbWarning() << "Missing connection"; | ||||
484 | return; | ||||
485 | } | ||||
486 | if (!listener) { | ||||
487 | kdbWarning() << "Missing listener"; | ||||
488 | return; | ||||
489 | } | ||||
490 | KDbTableSchemaChangeListenerPrivate::unregisterForChanges(conn, listener); | ||||
83 | } | 491 | } | ||
84 | 492 | | |||
85 | // static | 493 | // static | ||
86 | QList<KDbTableSchemaChangeListener*> KDbTableSchemaChangeListener::listeners( | 494 | QList<KDbTableSchemaChangeListener*> KDbTableSchemaChangeListener::listeners( | ||
87 | const KDbConnection *conn, const KDbTableSchema* table) | 495 | KDbConnection *conn, const KDbTableSchema* table) | ||
88 | { | 496 | { | ||
89 | //kdbDebug() << d->tableSchemaChangeListeners.count(); | 497 | if (!conn) { | ||
90 | QSet<KDbTableSchemaChangeListener*>* set = conn->d->tableSchemaChangeListeners.value(table); | 498 | kdbWarning() << "Missing connection"; | ||
91 | return set ? set->toList() : QList<KDbTableSchemaChangeListener*>(); | 499 | return QList<KDbTableSchemaChangeListener*>(); | ||
500 | } | ||||
501 | if (!table) { | ||||
502 | kdbWarning() << "Missing table"; | ||||
503 | return QList<KDbTableSchemaChangeListener*>(); | ||||
504 | } | ||||
505 | QSet<KDbTableSchemaChangeListener *> result; | ||||
506 | KDbTableSchemaChangeListenerPrivate::collectListeners(&result, conn, table); | ||||
507 | return result.toList(); | ||||
92 | } | 508 | } | ||
93 | 509 | | |||
94 | // static | 510 | // static | ||
95 | tristate KDbTableSchemaChangeListener::closeListeners(KDbConnection *conn, const KDbTableSchema* table) | 511 | QList<KDbTableSchemaChangeListener*> KDbTableSchemaChangeListener::listeners( | ||
512 | KDbConnection *conn, const KDbQuerySchema *query) | ||||
96 | { | 513 | { | ||
97 | QSet<KDbTableSchemaChangeListener*> *listeners = conn->d->tableSchemaChangeListeners.value(table); | 514 | if (!conn) { | ||
98 | if (!listeners) { | 515 | kdbWarning() << "Missing connection"; | ||
99 | return true; | 516 | return QList<KDbTableSchemaChangeListener*>(); | ||
517 | } | ||||
518 | if (!query) { | ||||
519 | kdbWarning() << "Missing query"; | ||||
520 | return QList<KDbTableSchemaChangeListener*>(); | ||||
521 | } | ||||
522 | QSet<KDbTableSchemaChangeListener *> result; | ||||
523 | KDbTableSchemaChangeListenerPrivate::collectListeners(&result, conn, query); | ||||
524 | return result.toList(); | ||||
100 | } | 525 | } | ||
101 | 526 | | |||
102 | //try to close every window | 527 | // static | ||
103 | tristate res = true; | 528 | tristate KDbTableSchemaChangeListener::closeListeners(KDbConnection *conn, | ||
104 | QList<KDbTableSchemaChangeListener*> list(listeners->toList()); | 529 | const KDbTableSchema *table, const QList<KDbTableSchemaChangeListener *> &except) | ||
105 | foreach (KDbTableSchemaChangeListener* listener, list) { | 530 | { | ||
531 | if (!conn) { | ||||
532 | kdbWarning() << "Missing connection"; | ||||
533 | return false; | ||||
534 | } | ||||
535 | if (!table) { | ||||
536 | kdbWarning() << "Missing table"; | ||||
537 | return false; | ||||
538 | } | ||||
539 | QSet<KDbTableSchemaChangeListener*> toClose(listeners(conn, table).toSet().subtract(except.toSet())); | ||||
540 | tristate result = true; | ||||
541 | for (KDbTableSchemaChangeListener *listener : toClose) { | ||||
542 | const tristate localResult = listener->closeListener(); | ||||
543 | if (localResult != true) { | ||||
544 | result = localResult; | ||||
545 | } | ||||
546 | } | ||||
547 | return result; | ||||
548 | } | ||||
549 | | ||||
550 | // static | ||||
551 | tristate KDbTableSchemaChangeListener::closeListeners(KDbConnection *conn, | ||||
552 | const KDbQuerySchema *query, const QList<KDbTableSchemaChangeListener *> &except) | ||||
553 | { | ||||
554 | if (!conn) { | ||||
555 | kdbWarning() << "Missing connection"; | ||||
556 | return false; | ||||
557 | } | ||||
558 | if (!query) { | ||||
559 | kdbWarning() << "Missing query"; | ||||
560 | return false; | ||||
561 | } | ||||
562 | QSet<KDbTableSchemaChangeListener*> toClose(listeners(conn, query).toSet().subtract(except.toSet())); | ||||
563 | tristate result = true; | ||||
564 | for (KDbTableSchemaChangeListener *listener : toClose) { | ||||
106 | const tristate localResult = listener->closeListener(); | 565 | const tristate localResult = listener->closeListener(); | ||
107 | if (localResult != true) { | 566 | if (localResult != true) { | ||
108 | res = localResult; | 567 | result = localResult; | ||
109 | } | 568 | } | ||
110 | } | 569 | } | ||
111 | return res; | 570 | return result; | ||
112 | } | 571 | } |