CVS update: gnucash/src/engine

Derek Atkins warlord at MIT.EDU
Fri Jun 13 00:00:48 CDT 2003


linas at linas.org (Linas Vepstas) writes:

> > There is not a generic "equals" predicate..  It's based on a data
> > type.  
> 
> That's OK.  as long as the difference between equals and equivalent is
> clear.

Uhh...  there is no difference except in the case of gnc-numeric.  For
all the core data types that you can search on (boolean, string, date,
int64, double, gnc-numeric, 'char', GUID, KVP), it is always
"equivalent".  You are never comparing by reference, you are always
comparing by value.

> > So, as I said, I could build an "AccountGroup" predicate type,
> 
> Uhh, now you are making me expend brain cells.  I probably will
> get this all wrong, but I think the textbook would say that you 
> need an 'object' predicate, with the comparisons is_a and has_a.

Well, one would hope one thinks about things before working on it.
But I don't think you've looked at how the existing query engine
works.

First, there are a set of core predicate types.  A predicate type
(Query Predicate) is a set of potential comparrisons against a
particular data type.  For example, you can create a GUID Predicate
that matches a single GUID, or matches one of a list of GUIDs, or
matches a list against a list to make sure all the GUIDs in the first
list are contained in the predicate's list.

[irrelevant query-logic removed]

> You can use the lambda-thingy to build complex predicates (at run-time
> instead of compile-time). I guess. Something like that.

We can already do runtime combinations of query logic, but you
first have to understand the limitations of the query core.

A Query Term is built by a parameter list and a Query Predicate.  The
parameter list is rooted in the object that you're searching for and
describes what you want to compare.  Each parameter has a data type
(which is either a QueryCore datatype or another object type) and an
accessor function (to obtain that parameter from the object).  The
data type of the final entry in the parameter list must machine the
type of the Query Predicate.

For example, assuming we're searching for Splits, I could have a
QueryTerm that looks like:

[Split ->] "Account" -> "GUID"      |  <Guid Predicate>

A Guid Predicate contains a match-type and a list of GUIDs to match
against.  The current match types are GUID_MATCH_ANY, GUID_MATCH_NONE,
GUID_MATCH_NULL, and GUID_MATCH_ALL[*].

Anyways, this Query Term will basically result in:

        test-object = split's account
        accessor = get-guid-from-account
        predicate-match = guid_match
        predicate = query-term's predicate

        result = predicate-match(predicate, test-object, accessor)

The result (a boolean) is then mixed in with the other QueryTerms for
this particular search-object (split)... In the end, this split is
either ignored or added to the list of results.

> > but it would be much better if I could base it on the existing "GUID"
> > match....  However the GUID match requires you to match against a list
> > of GUIDs.  I'd have to think about how to possibly extend this to
> > provide parental searches.
> 
> I think it would be fruitful to skim the literature for ideas. Besides
> (or instead of) is_a, has_a, there are other ways of combining things,
> some supposedly better than others.  I think this dates back to the 
> 70's/80's when things like relational and object-relational were being
> hotly debated.   I'd be happier if what you came up with was grounded 
> in theory.

Well, the question is can we create some "accessor" function that,
given an account can return something that we can compare against
a GUID?  I'm beginning to think we can.

First, I should mention that the GUID predicate function already has
one special-case.  For the GUID_MATCH_ALL match-type the accessor
already needs to return a GList* of GUID*, instead of a single GUID*.
So, if we had something like:

        GList* xaccAccountGetParentGroupGUIDs(Account*);

Then we could add one more GUID match-type, GUID_LIST_MATCHES_ANY,
which would be just as special-cased as GUID_MATCH_ALL in terms of
expecting a GList* of GUID*, but it would then look for a single match
from the accessor against the predicate's list, instead of matching
everything the accessor returns against the predicate's list.

So, we'd build a Guid Predicate with the top-level AccountGroup GUID,
and then use this new accessor function (and new match type) to
perform the comparrison.

So, thank you for making me explain this -- it's very much cleared up
my mind on how to proceed.

> --linas

-derek

-- 
       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL: http://web.mit.edu/warlord/    PP-ASEL-IA     N1NWH
       warlord at MIT.EDU                        PGP key available


More information about the gnucash-devel mailing list