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
This commit is contained in:
Derek Atkins 2006-09-26 23:47:09 +00:00
parent 9c4cf55144
commit f82c369b0e
3 changed files with 83 additions and 22 deletions

View File

@ -1,3 +1,9 @@
2006-09-26 Derek Atkins <derek@ihtfp.com>
* 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 <derek@ihtfp.com>
[ Lots of files ]:

View File

@ -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)
{

View File

@ -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().
*/