From f82c369b0ef6f888e24d3e0f3fe8c74503af05ab Mon Sep 17 00:00:00 2001 From: Derek Atkins Date: Tue, 26 Sep 2006 23:47:09 +0000 Subject: [PATCH] Implement SubQuery functionality in QOF: qof_query_run_subquery() Now you can run one query off of the results of another query. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@14901 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 6 +++ lib/libqof/qof/qofquery.c | 89 +++++++++++++++++++++++++++++---------- lib/libqof/qof/qofquery.h | 10 +++++ 3 files changed, 83 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0f76e40a4..35e0d82ef8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-09-26 Derek Atkins + + * lib/libqof/qof/qofquery.[ch]: + Implement SubQuery functionality in QOF: qof_query_run_subquery() + Now you can run one query off of the results of another query. + 2006-09-25 Derek Atkins [ Lots of files ]: diff --git a/lib/libqof/qof/qofquery.c b/lib/libqof/qof/qofquery.c index 071c678945..48005b6fda 100644 --- a/lib/libqof/qof/qofquery.c +++ b/lib/libqof/qof/qofquery.c @@ -682,15 +682,17 @@ void qof_query_purge_terms (QofQuery *q, GSList *param_list) } } -GList * qof_query_run (QofQuery *q) +static GList * qof_query_run_internal (QofQuery *q, + void(*run_cb)(QofQueryCB*,gpointer), + gpointer cb_arg) { GList *matching_objects = NULL; - GList *node; int object_count = 0; if (!q) return NULL; g_return_val_if_fail (q->search_for, NULL); g_return_val_if_fail (q->books, NULL); + g_return_val_if_fail (run_cb, NULL); ENTER (" q=%p", q); /* XXX: Prioritize the query terms? */ @@ -712,26 +714,8 @@ GList * qof_query_run (QofQuery *q) memset (&qcb, 0, sizeof (qcb)); qcb.query = q; - /* For each book */ - for (node=q->books; node; node=node->next) - { - QofBook *book = node->data; - QofBackend *be = book->backend; - - /* run the query in the backend */ - if (be) - { - gpointer compiled_query = g_hash_table_lookup (q->be_compiled, book); - - if (compiled_query && be->run_query) - { - (be->run_query) (be, compiled_query); - } - } - - /* And then iterate over all the objects */ - qof_object_foreach (q->search_for, book, (QofEntityForeachCB) check_item_cb, &qcb); - } + /* Run the query callback */ + run_cb(&qcb, cb_arg); matching_objects = qcb.list; object_count = qcb.count; @@ -794,6 +778,67 @@ GList * qof_query_run (QofQuery *q) return matching_objects; } +static void qof_query_run_cb(QofQueryCB* qcb, gpointer cb_arg) +{ + GList *node; + + (void)cb_arg; /* unused */ + g_return_if_fail(qcb); + + for (node=qcb->query->books; node; node=node->next) + { + QofBook *book = node->data; + QofBackend *be = book->backend; + + /* run the query in the backend */ + if (be) + { + gpointer compiled_query = g_hash_table_lookup (qcb->query->be_compiled, + book); + + if (compiled_query && be->run_query) + { + (be->run_query) (be, compiled_query); + } + } + + /* And then iterate over all the objects */ + qof_object_foreach (qcb->query->search_for, book, + (QofEntityForeachCB) check_item_cb, &qcb); + } +} + +GList * qof_query_run (QofQuery *q) +{ + /* Just a wrapper */ + return qof_query_run_internal(q, qof_query_run_cb, NULL); +} + +static void qof_query_run_subq_cb(QofQueryCB* qcb, gpointer cb_arg) +{ + QofQuery* pq = cb_arg; + + g_return_if_fail(pq); + g_list_foreach(qof_query_last_run(pq), check_item_cb, qcb); +} + +GList * +qof_query_run_subquery (QofQuery *subq, const QofQuery* primaryq) +{ + if (!subq) return NULL; + if (!primaryq) return NULL; + + /* Make sure we're searching for the same thing */ + g_return_val_if_fail (subq->search_for, NULL); + g_return_val_if_fail (primaryq->search_for, NULL); + g_return_val_if_fail(!safe_strcmp(subq->search_for, primaryq->search_for), + NULL); + + /* Perform the subquery */ + return qof_query_run_internal(subq, qof_query_run_subq_cb, + (gpointer)primaryq); +} + GList * qof_query_last_run (QofQuery *query) { diff --git a/lib/libqof/qof/qofquery.h b/lib/libqof/qof/qofquery.h index fdfeaa8b81..21c9f78897 100644 --- a/lib/libqof/qof/qofquery.h +++ b/lib/libqof/qof/qofquery.h @@ -221,6 +221,16 @@ GList * qof_query_run (QofQuery *query); */ GList * qof_query_last_run (QofQuery *query); +/** Perform a subquery, return the results. + * Instead of running over a book, the subquery runs over the results + * of the primary query. + * + * Do NOT free the resulting list. This list is managed internally + * by QofQuery. + */ +GList * qof_query_run_subquery (QofQuery *subquery, + const QofQuery* primary_query); + /** Remove all query terms from query. query matches nothing * after qof_query_clear(). */