qofquery.h File Reference


Detailed Description

find objects that match a certain expression.

Author:
Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>

Copyright (C) 2003 Linas Vepstas <linas@linas.org>

Definition in file qofquery.h.

#include "guid.h"
#include "qofbook.h"
#include "qofquerycore.h"
#include "qofchoice.h"

Go to the source code of this file.

Query Subsystem Initialization and Shudown

void qof_query_init (void)
void qof_query_shutdown (void)

Low-Level API Functions

GSList * qof_query_build_param_list (char const *param,...)
QofQueryqof_query_create (void)
QofQueryqof_query_create_for (QofIdTypeConst obj_type)
void qof_query_destroy (QofQuery *q)
void qof_query_search_for (QofQuery *query, QofIdTypeConst obj_type)
void qof_query_set_book (QofQuery *q, QofBook *book)
void qof_query_add_term (QofQuery *query, GSList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
void qof_query_add_guid_match (QofQuery *q, GSList *param_list, const GUID *guid, QofQueryOp op)
void qof_query_add_guid_list_match (QofQuery *q, GSList *param_list, GList *guid_list, QofGuidMatch options, QofQueryOp op)
void qof_query_add_boolean_match (QofQuery *q, GSList *param_list, gboolean value, QofQueryOp op)
GList * qof_query_run (QofQuery *query)
GList * qof_query_last_run (QofQuery *query)
void qof_query_clear (QofQuery *query)
void qof_query_purge_terms (QofQuery *q, GSList *param_list)
int qof_query_has_terms (QofQuery *q)
int qof_query_num_terms (QofQuery *q)
gboolean qof_query_has_term_type (QofQuery *q, GSList *term_param)
GSList * qof_query_get_term_type (QofQuery *q, GSList *term_param)
QofQueryqof_query_copy (QofQuery *q)
QofQueryqof_query_invert (QofQuery *q)
QofQueryqof_query_merge (QofQuery *q1, QofQuery *q2, QofQueryOp op)
void qof_query_merge_in_place (QofQuery *q1, QofQuery *q2, QofQueryOp op)
void qof_query_set_sort_order (QofQuery *q, GSList *primary_sort_params, GSList *secondary_sort_params, GSList *tertiary_sort_params)
void qof_query_set_sort_options (QofQuery *q, gint prim_op, gint sec_op, gint tert_op)
void qof_query_set_sort_increasing (QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
void qof_query_set_max_results (QofQuery *q, int n)
gboolean qof_query_equal (QofQuery *q1, QofQuery *q2)
void qof_query_print (QofQuery *query)
QofIdType qof_query_get_search_for (QofQuery *q)
GList * qof_query_get_books (QofQuery *q)

Defines

#define QOF_MOD_QUERY   "qof-query"
#define QOF_QUERY_FIRST_TERM   QOF_QUERY_AND
#define QUERY_DEFAULT_SORT   "QofQueryDefaultSort"
#define QOF_PARAM_BOOK   "book"
#define QOF_PARAM_GUID   "guid"
#define QOF_PARAM_KVP   "kvp"
#define QOF_PARAM_ACTIVE   "active"
#define QOF_PARAM_VERSION   "version"

Typedefs

typedef _QofQuery QofQuery

Enumerations

enum  QofQueryOp {
  QOF_QUERY_AND = 1, QOF_QUERY_OR, QOF_QUERY_NAND, QOF_QUERY_NOR,
  QOF_QUERY_XOR
}


Function Documentation

void qof_query_add_boolean_match QofQuery q,
GSList *  param_list,
gboolean  value,
QofQueryOp  op
 

Handy-dandy convenience routines, avoids having to create a separate predicate for boolean matches. We might want to create handy-dandy sugar routines for the other predicate types as well.

Definition at line 1243 of file qofquery.c.

01245 {
01246   QofQueryPredData *pdata;
01247   if (!q || !param_list) return;
01248 
01249   pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
01250   qof_query_add_term (q, param_list, pdata, op);
01251 }

void qof_query_add_guid_list_match QofQuery q,
GSList *  param_list,
GList *  guid_list,
QofGuidMatch  options,
QofQueryOp  op
 

DOCUMENT ME !!

Definition at line 1191 of file qofquery.c.

01194 {
01195   QofQueryPredData *pdata;
01196 
01197   if (!q || !param_list) return;
01198 
01199   if (!guid_list)
01200     g_return_if_fail (options == QOF_GUID_MATCH_NULL);
01201 
01202   pdata = qof_query_guid_predicate (options, guid_list);
01203   qof_query_add_term (q, param_list, pdata, op);
01204 }

void qof_query_add_guid_match QofQuery q,
GSList *  param_list,
const GUID guid,
QofQueryOp  op
 

DOCUMENT ME !!

Definition at line 1206 of file qofquery.c.

01208 {
01209   GList *g = NULL;
01210 
01211   if (!q || !param_list) return;
01212 
01213   if (guid)
01214     g = g_list_prepend (g, (gpointer)guid);
01215 
01216   qof_query_add_guid_list_match (q, param_list, g,
01217                             g ? QOF_GUID_MATCH_ANY : QOF_GUID_MATCH_NULL, op);
01218 
01219   g_list_free (g);
01220 }

void qof_query_add_term QofQuery query,
GSList *  param_list,
QofQueryPredData pred_data,
QofQueryOp  op
 

This is the general function that adds a new Query Term to a query. It will find the 'obj_type' object of the search item and compare the 'param_list' parameter to the predicate data via the comparitor.

The param_list is a recursive list of parameters. For example, you can say 'split->memo' by creating a list of one element, "SPLIT_MEMO". You can say 'split->account->name' by creating a list of two elements, "SPLIT_ACCOUNT" and "ACCOUNT_NAME". The list becomes the property of the Query.

For example:

acct_name_pred_data = make_string_pred_data(QOF_STRING_MATCH_CASEINSENSITIVE, account_name); param_list = make_list (SPLIT_ACCOUNT, ACCOUNT_NAME, NULL); qof_query_add_term (query, param_list, QOF_COMPARE_EQUAL, acct_name_pred_data, QOF_QUERY_AND);

Please note that QofQuery does not, at this time, support joins. That is, one cannot specify a predicate that is a parameter list. Put another way, one cannot search for objects where obja->thingy == objb->stuff

Definition at line 631 of file qofquery.c.

00633 {
00634   QofQueryTerm *qt;
00635   QofQuery *qr, *qs;
00636 
00637   if (!q || !param_list || !pred_data) return;
00638 
00639   qt = g_new0 (QofQueryTerm, 1);
00640   qt->param_list = param_list;
00641   qt->pdata = pred_data;
00642   qs = qof_query_create ();
00643   query_init (qs, qt);
00644 
00645   if (qof_query_has_terms (q))
00646     qr = qof_query_merge (q, qs, op);
00647   else
00648     qr = qof_query_merge (q, qs, QOF_QUERY_OR);
00649 
00650   swap_terms (q, qr);
00651   qof_query_destroy (qs);
00652   qof_query_destroy (qr);
00653 }

void qof_query_clear QofQuery query  ) 
 

Remove all query terms from query. query matches nothing after qof_query_clear().

Definition at line 806 of file qofquery.c.

00807 {
00808   QofQuery *q2 = qof_query_create ();
00809   swap_terms (query, q2);
00810   qof_query_destroy (q2);
00811 
00812   g_list_free (query->books);
00813   query->books = NULL;
00814   g_list_free (query->results);
00815   query->results = NULL;
00816   query->changed = 1;
00817 }

QofQuery* qof_query_copy QofQuery q  ) 
 

Make a copy of the indicated query

Definition at line 912 of file qofquery.c.

00913 {
00914   QofQuery *copy;
00915   GHashTable *ht;
00916 
00917   if (!q) return NULL;
00918   copy = qof_query_create ();
00919   ht = copy->be_compiled;
00920   free_members (copy);
00921 
00922   memcpy (copy, q, sizeof (QofQuery));
00923 
00924   copy->be_compiled = ht;
00925   copy->terms = copy_or_terms (q->terms);
00926   copy->books = g_list_copy (q->books);
00927   copy->results = g_list_copy (q->results);
00928 
00929   copy_sort (&(copy->primary_sort), &(q->primary_sort));
00930   copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
00931   copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
00932 
00933   copy->changed = 1;
00934 
00935   return copy;
00936 }

QofQuery* qof_query_create void   ) 
 

Create a new query. Before running the query, a 'search-for' type must be set otherwise nothing will be returned. The results of the query is a list of the indicated search-for type.

Allocates and initializes a Query structure which must be freed by the user with qof_query_destroy(). A newly-allocated QofQuery object matches nothing (qof_query_run() will return NULL).

Definition at line 819 of file qofquery.c.

00820 {
00821   QofQuery *qp = g_new0 (QofQuery, 1);
00822   qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
00823   query_init (qp, NULL);
00824   return qp;
00825 }

void qof_query_destroy QofQuery q  ) 
 

Frees the resources associate with a Query object.

Definition at line 903 of file qofquery.c.

00904 {
00905   if (!q) return;
00906   free_members (q);
00907   query_clear_compiles (q);
00908   g_hash_table_destroy (q->be_compiled);
00909   g_free (q);
00910 }

gboolean qof_query_equal QofQuery q1,
QofQuery q2
 

Compare two queries for equality. Query terms are compared each to each. This is a simplistic implementation -- logical equivalences between different and/or trees are ignored.

Definition at line 1368 of file qofquery.c.

01369 {
01370   GList *or1, *or2;
01371 
01372   if (q1 == q2) return TRUE;
01373   if (!q1 || !q2) return FALSE;
01374 
01375   if (g_list_length (q1->terms) != g_list_length (q2->terms)) return FALSE;
01376   if (q1->max_results != q2->max_results) return FALSE;
01377 
01378   for (or1 = q1->terms, or2 = q2->terms; or1;
01379        or1 = or1->next, or2 = or2->next)
01380   {
01381     GList *and1, *and2;
01382 
01383     and1 = or1->data;
01384     and2 = or2->data;
01385 
01386     if (g_list_length (and1) != g_list_length (and2)) return FALSE;
01387 
01388     for ( ; and1; and1 = and1->next, and2 = and2->next)
01389       if (!qof_query_term_equal (and1->data, and2->data))
01390         return FALSE;
01391   }
01392 
01393   if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
01394     return FALSE;
01395   if (!qof_query_sort_equal (&(q1->secondary_sort), &(q2->secondary_sort)))
01396     return FALSE;
01397   if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
01398     return FALSE;
01399 
01400   return TRUE;
01401 }

GList* qof_query_get_books QofQuery q  ) 
 

Return the list of books we're using

Definition at line 1237 of file qofquery.c.

01238 {
01239   if (!q) return NULL;
01240   return q->books;
01241 }

QofIdType qof_query_get_search_for QofQuery q  ) 
 

Return the type of data we're querying for

Definition at line 1276 of file qofquery.c.

01277 {
01278   if (!q) return NULL;
01279   return q->search_for;
01280 }

gboolean qof_query_has_term_type QofQuery q,
GSList *  term_param
 

DOCUMENT ME !!

Definition at line 864 of file qofquery.c.

00865 {
00866   GList *or;
00867   GList *and;
00868 
00869   if (!q || !term_param)
00870     return FALSE;
00871 
00872   for(or = q->terms; or; or = or->next) {
00873     for(and = or->data; and; and = and->next) {
00874       QofQueryTerm *qt = and->data;
00875       if (!param_list_cmp (term_param, qt->param_list))
00876         return TRUE;
00877     }
00878   }
00879 
00880   return FALSE;
00881 }

int qof_query_has_terms QofQuery q  ) 
 

Return boolean FALSE if there are no terms in the query Can be used as a predicate to see if the query has been initialized (return value > 0) or is "blank" (return value == 0).

Definition at line 848 of file qofquery.c.

00849 {
00850   if (!q) return 0;
00851   return g_list_length (q->terms);
00852 }

void qof_query_init void   ) 
 

Subsystem initialization and shutdown. Call init() once to initalize the query subsytem; call shutdown() to free up any resources associated with the query subsystem. Typically called during application startup, shutdown.

Definition at line 1256 of file qofquery.c.

01257 {
01258   ENTER (" ");
01259   qof_query_core_init ();
01260   qof_class_init ();
01261   LEAVE ("Completed initialization of QofQuery");
01262 }

QofQuery* qof_query_invert QofQuery q  ) 
 

Make a copy of the indicated query, inverting the sense of the search. In other words, if the original query search for all objects with a certain condition, the inverted query will search for all object with NOT that condition. The union of the results returned by the original and inverted queries equals the set of all searched objects. These to sets are disjoint (share no members in common).

This will return a newly allocated QofQuery object, or NULL on error. Free it with qof_query_destroy() when no longer needed.

Definition at line 944 of file qofquery.c.

00945 {
00946   QofQuery  * retval;
00947   QofQuery  * right, * left, * iright, * ileft;
00948   QofQueryTerm * qt;
00949   GList  * aterms;
00950   GList  * cur;
00951   GList  * new_oterm;
00952   int    num_or_terms;
00953 
00954   if (!q)
00955     return NULL;
00956 
00957   num_or_terms = g_list_length(q->terms);
00958 
00959   switch(num_or_terms) 
00960   {
00961   case 0:
00962     retval = qof_query_create();
00963     retval->max_results = q->max_results;
00964     break;
00965 
00966     /* This is the DeMorgan expansion for a single AND expression. */
00967     /* !(abc) = !a + !b + !c */
00968   case 1:
00969     retval = qof_query_create();
00970     retval->max_results = q->max_results;
00971     retval->books = g_list_copy (q->books);
00972     retval->search_for = q->search_for;
00973     retval->changed = 1;
00974 
00975     aterms = g_list_nth_data(q->terms, 0);
00976     new_oterm = NULL;
00977     for(cur=aterms; cur; cur=cur->next) {
00978       qt = copy_query_term(cur->data);
00979       qt->invert = !(qt->invert);
00980       new_oterm = g_list_append(NULL, qt);
00981 
00982       /* g_list_append() can take forever, so let's do this for speed
00983        * in "large" queries.
00984        */
00985       retval->terms = g_list_reverse(retval->terms);
00986       retval->terms = g_list_prepend(retval->terms, new_oterm);
00987       retval->terms = g_list_reverse(retval->terms);
00988     }
00989     break;
00990 
00991     /* If there are multiple OR-terms, we just recurse by 
00992      * breaking it down to !(a + b + c) = 
00993      * !a * !(b + c) = !a * !b * !c.  */
00994   default:
00995     right        = qof_query_create();
00996     right->terms = copy_or_terms(g_list_nth(q->terms, 1));
00997 
00998     left         = qof_query_create();
00999     left->terms  = g_list_append(NULL, 
01000                                  copy_and_terms(g_list_nth_data(q->terms, 0)));
01001 
01002     iright       = qof_query_invert(right);
01003     ileft        = qof_query_invert(left);
01004 
01005     retval = qof_query_merge(iright, ileft, QOF_QUERY_AND);
01006     retval->books          = g_list_copy (q->books);
01007     retval->max_results    = q->max_results;
01008     retval->search_for     = q->search_for;
01009     retval->changed        = 1;
01010 
01011     qof_query_destroy(iright);
01012     qof_query_destroy(ileft);
01013     qof_query_destroy(right);
01014     qof_query_destroy(left);
01015     break;
01016   }
01017 
01018   return retval;
01019 }

GList* qof_query_last_run QofQuery query  ) 
 

Return the results of the last query, without causing the query to be re-run. Do NOT free the resulting list. This list is managed internally by QofQuery.

Definition at line 798 of file qofquery.c.

00799 {
00800   if (!query)
00801     return NULL;
00802 
00803   return query->results;
00804 }

QofQuery* qof_query_merge QofQuery q1,
QofQuery q2,
QofQueryOp  op
 

Combine two queries together using the Boolean set (logical) operator 'op'. For example, if the operator 'op' is set to QUERY_AND, then the set of results returned by the query will will be the Boolean set intersection of the results returned by q1 and q2. Similarly, QUERY_OR maps to set union, etc.

Both queries must have compatible search-types. If both queries are set, they must search for the same object type. If only one is set, the resulting query will search for the set type. If neither query has the search-type set, the result will be unset as well.

This will return a newly allocated QofQuery object, or NULL on error. Free it with qof_query_destroy() when no longer needed.

Definition at line 1027 of file qofquery.c.

01028 {
01029   
01030   QofQuery * retval = NULL;
01031   QofQuery * i1, * i2;
01032   QofQuery * t1, * t2;
01033   GList * i, * j;
01034   QofIdType search_for;
01035 
01036   if(!q1) return q2;
01037   if(!q2) return q1;
01038 
01039   if (q1->search_for && q2->search_for)
01040     g_return_val_if_fail (safe_strcmp (q1->search_for, q2->search_for) == 0,
01041                           NULL);
01042 
01043   search_for = (q1->search_for ? q1->search_for : q2->search_for);
01044 
01045   /* Avoid merge surprises if op==QOF_QUERY_AND but q1 is empty.
01046    * The goal of this tweak is to all the user to start with
01047    * an empty q1 and then append to it recursively
01048    * (and q1 (and q2 (and q3 (and q4 ....))))
01049    * without bombing out because the append started with an 
01050    * empty list.
01051    * We do essentially the same check in qof_query_add_term()
01052    * so that the first term added to an empty query doesn't screw up.
01053    */
01054   if ((QOF_QUERY_AND == op) && (0 == qof_query_has_terms (q1)))
01055   {
01056     op = QOF_QUERY_OR;
01057   }
01058 
01059   switch(op) 
01060   {
01061   case QOF_QUERY_OR:
01062     retval = qof_query_create();
01063     retval->terms = 
01064       g_list_concat(copy_or_terms(q1->terms), copy_or_terms(q2->terms));
01065     retval->books           = merge_books (q1->books, q2->books);
01066     retval->max_results    = q1->max_results;
01067     retval->changed        = 1;
01068     break;
01069 
01070   case QOF_QUERY_AND:
01071     retval = qof_query_create();
01072     retval->books          = merge_books (q1->books, q2->books);
01073     retval->max_results    = q1->max_results;
01074     retval->changed        = 1;
01075 
01076     /* g_list_append() can take forever, so let's build the list in
01077      * reverse and then reverse it at the end, to deal better with
01078      * "large" queries.
01079      */
01080     for(i=q1->terms; i; i=i->next) 
01081     {
01082       for(j=q2->terms; j; j=j->next) 
01083       {
01084         retval->terms = 
01085           g_list_prepend(retval->terms, 
01086                         g_list_concat
01087                         (copy_and_terms(i->data),
01088                          copy_and_terms(j->data)));
01089       }
01090     }
01091     retval->terms = g_list_reverse(retval->terms);
01092     break;
01093 
01094   case QOF_QUERY_NAND:
01095     /* !(a*b) = (!a + !b) */
01096     i1     = qof_query_invert(q1);
01097     i2     = qof_query_invert(q2);
01098     retval = qof_query_merge(i1, i2, QOF_QUERY_OR);
01099     qof_query_destroy(i1);
01100     qof_query_destroy(i2);
01101     break;
01102 
01103   case QOF_QUERY_NOR:
01104     /* !(a+b) = (!a*!b) */
01105     i1     = qof_query_invert(q1);
01106     i2     = qof_query_invert(q2);
01107     retval = qof_query_merge(i1, i2, QOF_QUERY_AND);
01108     qof_query_destroy(i1);
01109     qof_query_destroy(i2);
01110     break;
01111 
01112   case QOF_QUERY_XOR:
01113     /* a xor b = (a * !b) + (!a * b) */
01114     i1     = qof_query_invert(q1);
01115     i2     = qof_query_invert(q2);
01116     t1     = qof_query_merge(q1, i2, QOF_QUERY_AND);
01117     t2     = qof_query_merge(i1, q2, QOF_QUERY_AND);
01118     retval = qof_query_merge(t1, t2, QOF_QUERY_OR);
01119 
01120     qof_query_destroy(i1);
01121     qof_query_destroy(i2);
01122     qof_query_destroy(t1);
01123     qof_query_destroy(t2);     
01124     break;
01125   }
01126 
01127   retval->search_for = search_for;
01128   return retval;
01129 }

void qof_query_merge_in_place QofQuery q1,
QofQuery q2,
QofQueryOp  op
 

Like qof_query_merge, but this will merge a copy of q2 into q1. q2 remains unchanged.

Definition at line 1132 of file qofquery.c.

01133 {
01134   QofQuery *tmp_q;
01135 
01136   if (!q1 || !q2)
01137     return;
01138 
01139   tmp_q = qof_query_merge (q1, q2, op);
01140   swap_terms (q1, tmp_q);
01141   qof_query_destroy (tmp_q);
01142 }

int qof_query_num_terms QofQuery q  ) 
 

Return the number of terms in the canonical form of the query.

Definition at line 854 of file qofquery.c.

00855 {
00856   GList *o;
00857   int n = 0;
00858   if (!q) return 0;
00859   for (o = q->terms; o; o=o->next)
00860     n += g_list_length(o->data);
00861   return n;
00862 }

void qof_query_print QofQuery query  ) 
 

Deprecated:
access via qof_log instead. The query will be logged automatically if qof_log_set_default or qof_log_set_level(QOF_MOD_QUERY, ...) are set to QOF_LOG_DEBUG or higher.
This function cycles through a QofQuery object, and prints out the values of the various members of the query

Definition at line 1433 of file qofquery.c.

01434 {
01435   GList *output;
01436   GString *str;
01437   QofQuerySort *s[3];
01438   gint maxResults = 0, numSorts = 3;
01439 
01440   ENTER (" ");
01441 
01442   if (!query) {
01443       LEAVE("query is (null)");
01444       return;
01445   }
01446 
01447   output = NULL;
01448   str = NULL;
01449   maxResults = qof_query_get_max_results (query);
01450 
01451   output = qof_query_printSearchFor (query, output);
01452   output = qof_query_printTerms (query, output);
01453 
01454   qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
01455 
01456   if (s[0])
01457   {
01458     output = qof_query_printSorts (s, numSorts, output);
01459   }
01460 
01461   str = g_string_new (" ");
01462   g_string_printf (str, "Maximum number of results: %d", maxResults);
01463   output = g_list_append (output, str);
01464 
01465   qof_query_printOutput (output);
01466   LEAVE (" ");
01467 }

void qof_query_purge_terms QofQuery q,
GSList *  param_list
 

Remove query terms of a particular type from q. The "type" of a term is determined by the type of data that gets passed to the predicate function. XXX ??? Huh? remove anything of that predicate type, or just the particular predicate ?

Definition at line 655 of file qofquery.c.

00656 {
00657   QofQueryTerm *qt;
00658   GList *or, *and;
00659 
00660   if (!q || !param_list) return;
00661 
00662   for (or = q->terms; or; or = or->next) {
00663     for (and = or->data; and; and = and->next) {
00664       qt = and->data;
00665       if (!param_list_cmp (qt->param_list, param_list)) {
00666         if (g_list_length (or->data) == 1) {
00667           q->terms = g_list_remove_link (q->terms, or);
00668           g_list_free_1 (or);
00669           or = q->terms;
00670           break;
00671         } else {
00672           or->data = g_list_remove_link (or->data, and);
00673           g_list_free_1 (and);
00674           and = or->data;
00675           if (!and) break;
00676         }
00677         q->changed = 1;
00678         free_query_term (qt);
00679       }
00680     }
00681     if (!or) break;
00682   }
00683 }

GList* qof_query_run QofQuery query  ) 
 

Perform the query, return the results. The returned list is a list of the 'search-for' type that was previously set with the qof_query_search_for() or the qof_query_create_for() routines. The returned list will have been sorted using the indicated sort order, and trimed to the max_results length.

Do NOT free the resulting list. This list is managed internally by QofQuery.

Definition at line 685 of file qofquery.c.

00686 {
00687   GList *matching_objects = NULL;
00688   GList *node;
00689   int        object_count = 0;
00690 
00691   if (!q) return NULL;
00692   g_return_val_if_fail (q->search_for, NULL);
00693   g_return_val_if_fail (q->books, NULL);
00694   ENTER (" q=%p", q);
00695 
00696   /* XXX: Prioritize the query terms? */
00697 
00698   /* prepare the Query for processing */
00699   if (q->changed) 
00700   {
00701     query_clear_compiles (q);
00702     compile_terms (q);
00703   }
00704 
00705   /* Maybe log this sucker */
00706   if (qof_log_check (log_module, QOF_LOG_DETAIL)) qof_query_print (q);
00707 
00708   /* Now run the query over all the objects and save the results */
00709   {
00710     QofQueryCB qcb;
00711 
00712     memset (&qcb, 0, sizeof (qcb));
00713     qcb.query = q;
00714 
00715     /* For each book */
00716     for (node=q->books; node; node=node->next) 
00717     {
00718       QofBook *book = node->data;
00719       QofBackend *be = book->backend;
00720 
00721       /* run the query in the backend */
00722       if (be) 
00723       {
00724         gpointer compiled_query = g_hash_table_lookup (q->be_compiled, book);
00725 
00726         if (compiled_query && be->run_query)
00727         {
00728           (be->run_query) (be, compiled_query);
00729         }
00730       }
00731 
00732       /* And then iterate over all the objects */
00733       qof_object_foreach (q->search_for, book, (QofEntityForeachCB) check_item_cb, &qcb);
00734     }
00735 
00736     matching_objects = qcb.list;
00737     object_count = qcb.count;
00738   }
00739   PINFO ("matching objects=%p count=%d", matching_objects, object_count);
00740 
00741   /* There is no absolute need to reverse this list, since it's being
00742    * sorted below. However, in the common case, we will be searching
00743    * in a confined location where the objects are already in order,
00744    * thus reversing will put us in the correct order we want and make
00745    * the sorting go much faster.
00746    */
00747   matching_objects = g_list_reverse(matching_objects);
00748 
00749   /* Now sort the matching objects based on the search criteria
00750    * sortQuery is an unforgivable use of static global data...  
00751    * I just can't figure out how else to do this sanely.
00752    */
00753   if (q->primary_sort.comp_fcn || q->primary_sort.obj_cmp ||
00754       (q->primary_sort.use_default && q->defaultSort))
00755   {
00756     sortQuery = q;
00757     matching_objects = g_list_sort(matching_objects, sort_func);
00758     sortQuery = NULL;
00759   }
00760 
00761   /* Crop the list to limit the number of splits. */
00762   if((object_count > q->max_results) && (q->max_results > -1)) 
00763   {
00764     if(q->max_results > 0) 
00765     {
00766       GList *mptr;
00767 
00768       /* mptr is set to the first node of what will be the new list */
00769       mptr = g_list_nth(matching_objects, object_count - q->max_results);
00770       /* mptr should not be NULL, but let's be safe */
00771       if (mptr != NULL) 
00772       {
00773         if (mptr->prev != NULL) mptr->prev->next = NULL;
00774         mptr->prev = NULL;
00775       }
00776       g_list_free(matching_objects);
00777       matching_objects = mptr;
00778     }
00779     else 
00780     { 
00781       /* q->max_results == 0 */
00782       g_list_free(matching_objects);
00783       matching_objects = NULL;
00784     }
00785     object_count = q->max_results;
00786   }
00787   
00788   q->changed = 0;
00789   
00790   g_list_free(q->results);
00791   q->results = matching_objects;
00792   
00793   LEAVE (" q=%p", q);
00794   return matching_objects;
00795 }

void qof_query_search_for QofQuery query,
QofIdTypeConst  obj_type
 

Set the object type to be searched for. The results of performing the query will be a list of this obj_type.

Definition at line 827 of file qofquery.c.

00828 {
00829   if (!q || !obj_type)
00830     return;
00831 
00832   if (safe_strcmp (q->search_for, obj_type)) {
00833     q->search_for = (QofIdType) obj_type;
00834     q->changed = 1;
00835   }
00836 }

void qof_query_set_book QofQuery q,
QofBook book
 

Set the book to be searched. Books contain/identify collections of objects; the search will be performed over those books specified with this function. If no books are set, no results will be returned (since there is nothing to search over).

You can search multiple books. To specify multiple books, call this function multiple times with different arguments. XXX needed qof_query_clear_books() to reset the list ...

Definition at line 1222 of file qofquery.c.

01223 {
01224   GSList *slist = NULL;
01225   if (!q || !book) return;
01226 
01227   /* Make sure this book is only in the list once */
01228   if (g_list_index (q->books, book) == -1)
01229     q->books = g_list_prepend (q->books, book);
01230 
01231   slist = g_slist_prepend (slist, QOF_PARAM_GUID);
01232   slist = g_slist_prepend (slist, QOF_PARAM_BOOK);
01233   qof_query_add_guid_match (q, slist,
01234                         qof_book_get_guid(book), QOF_QUERY_AND);
01235 }

void qof_query_set_max_results QofQuery q,
int  n
 

Set the maximum number of results that should be returned. If 'max-results' is set to -1, then all of the results are returned. If there are more results than 'max-results', then the result list is trimmed. Note that there is an important interplay between 'max-results' and the sort order: only the last bit of results are returned. For example, if the sort order is set to be increasing date order, then only the objects with the most recent dates will be returned.

Definition at line 1185 of file qofquery.c.

01186 {
01187   if (!q) return;
01188   q->max_results = n;
01189 }

void qof_query_set_sort_increasing QofQuery q,
gboolean  prim_inc,
gboolean  sec_inc,
gboolean  tert_inc
 

When a query is run, the results are sorted before being returned. This routine can be used to control the direction of the ordering. A value of TRUE indicates the sort will be in increasing order, a value of FALSE will order results in decreasing order.

Note that if there are more results than the 'max-results' value, then only the *last* max-results will be returned. For example, if the sort is set to be increasing date order, then only the objects with the most recent dates will be returned.

Definition at line 1176 of file qofquery.c.

01178 {
01179   if (!q) return;
01180   q->primary_sort.increasing = prim_inc;
01181   q->secondary_sort.increasing = sec_inc;
01182   q->tertiary_sort.increasing = tert_inc;
01183 }

void qof_query_set_sort_order QofQuery q,
GSList *  primary_sort_params,
GSList *  secondary_sort_params,
GSList *  tertiary_sort_params
 

When a query is run, the results are sorted before being returned. This routine can be used to set the paramters on which the sort will be performed. Two objects in the result list will be compared using the 'primary_sort_params', and sorted based on that order. If the comparison shows that they are equal, then the 'secondary_sort_params' will be used. If still equal, then the tertiary params will be compared. Any or all of these parameter lists may be NULL. Any of these parameter lists may be set to QUERY_DEFAULT_SORT.

Note that if there are more results than the 'max-results' value, then only the *last* max-results will be returned. For example, if the sort is set to be increasing date order, then only the objects with the most recent dates will be returned.

The input lists become the property of QofQuery and are managed by it. They will be freed when the query is destroyed (or when new lists are set).

Definition at line 1145 of file qofquery.c.

01147 {
01148   if (!q) return;
01149   if (q->primary_sort.param_list)
01150     g_slist_free (q->primary_sort.param_list);
01151   q->primary_sort.param_list = params1;
01152   q->primary_sort.options = 0;
01153 
01154   if (q->secondary_sort.param_list)
01155     g_slist_free (q->secondary_sort.param_list);
01156   q->secondary_sort.param_list = params2;
01157   q->secondary_sort.options = 0;
01158 
01159   if (q->tertiary_sort.param_list)
01160     g_slist_free (q->tertiary_sort.param_list);
01161   q->tertiary_sort.param_list = params3;
01162   q->tertiary_sort.options = 0;
01163 
01164   q->changed = 1;
01165 }


Generated on Fri May 12 18:00:34 2006 for QOF by  doxygen 1.4.4