On Thursday 01 September 2005 11:19 pm, Mike B wrote: > Hey everyone, Welcome!
> I've just been playing around with the > GNUCash source for the first time, and I'm having a > little trouble. I haven't seen anything in the design > documents about how account data is organized and how > the object mapping interfaces with that, so I'm having > trouble making the queries that I want to make. As already mentioned, each object describes itself to the query object framework. A static object description outlines what data the object can accept and provide, how to iterate over each instance of that object and how to mark an instance as dirty. The mapping from the object data to a specific backend layout is full of indirection because the object neither knows nor cares about the detail of the backend and vice versa. Each application using QOF can provide it's own objects and / or it's own backends. > I think it's interesting that when someone like me is > first getting into the GNUCash source, what I really > want is a database schema and access to SQL queries. (repeat ten times: gnucash has no database). If you want to, you could download CashUtil http://www.linux.codehelp.co.uk/cashutil/ (it needs CVS QOF to build currently) as this does provide command line SQL queries. It's far from complete but it's easier than compiling new SQL queries via the gnucash tree. > I'm sure that I'll learn to appreciate the OR mapping > layer, but right now I'm just confused. That would be because you are looking for something that does not exist! :-) I was just as confused when I started with the gnucash source tree. Josh wrote: > > You should take a good look at QOF, however. It's not an OR mapping > > layer so much as a mappable object model ... i.e., queries expressed > > over in-memory QOF object-graphs can be translated into SQL. I'm still > > not sure how it handles data-modificiation, though. In QOF, object descriptions provide the object model map using a list of parameters that have a name, data type, get function and set function. This list is static within the application and referenced via a GHashTable in QOF. There is no need to copy QofParam - it's always static and sufficient to keep just a pointer. The SQL translation is actually the reverse of how Josh described it. Incoming SQL is converted to the QOF predicates (which can also be manipulated directly) where the search is actually achieved. QOF can accept limited SQL commands but only by converting them to a QofQuery that it understands. i.e. SQL support is not native (and will be implemented via the GDA external library in due course). There is currently no way to convert a series of predicates into SQL but I'm working on that for CashUtil so that it can have some rudimentary macro functions. Data-modification is done via QofParam and param_setfcn - a pointer to the actual object function that modifies the instance. QofParam *param; // assuming a string param_type in this case param->param_setfcn(QofEntity *ent, const char *string); If this was the Account name parameter (from Account.c): { ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, (QofSetterFunc) xaccAccountSetName }, This would actually call: void xaccAccountSetName (Account *account, const char *name) The Account* is cast from the QofEntity*. param->param_getfcn works in a similar way. There's also an important distinction between parameters that are "calculated" and those that can be "set". Parameters like the Account balance can be queried (using get) but should never be set, so the param_setfcn is NULL. This rule is fundamental to QOF and it is vital that all objects implement the distinction in a logical manner. Function pointers are required to set certain parameters (like gnc_numeric, boolean and dates) that are not passed as pointers themselves: Timespec cli_date; void (*date_setter) (QofEntity*, Timespec); date_setter = (void(*)(QofEntity*, Timespec))param->param_setfcn; if(date_setter != NULL) { date_setter(ent, cli_date); } (That took me ages to understand but thanks to Derek's patience, I got it eventually!) Example: http://code.neil.williamsleesmill.me.uk/cashutil/group__UNDO.html#ga2 All data modification should occur between a begin_edit and commit_edit pair. Once QOF undo is implemented, there'll be a further wrapper for a series of data modifications that form a single "operation" from the user perspective. (For those who are interested, the limited undo support for QOF as currently implemented in CashUtil is documented using (a buggy) Doxygen output here: http://code.neil.williamsleesmill.me.uk/cashutil/group__UNDO.html > I think what I really need is an example that I don't > have to follow through layers of indirection. If you want to experiment with your own objects, try QOF-gen: http://qof-gen.sourceforge.net/ Or PilotQOF (which uses simpler objects): http://pilot-qof.sourceforge.net/ -- Neil Williams ============= http://www.data-freedom.org/ http://www.nosoftwarepatents.com/ http://www.linux.codehelp.co.uk/
pgpL9PCBgVWuy.pgp
Description: PGP signature
_______________________________________________ gnucash-devel mailing list [email protected] https://lists.gnucash.org/mailman/listinfo/gnucash-devel
