This one time, at band camp, Keith Visco said:

KV>Thanks for your contribution to the project. The best way to handle the
KV>contribution is to open up a bugzilla report at
KV>http://bugzilla.exolab.org. This way it can be tracked easier and the
KV>appropriate individuals will be assigned to the report.
KV>
KV>Also read the simple guidelines for contribution:
KV>
KV>http://castor.exolab.org/cvs.html#Guidelines-For-Code-Contribution
KV>
KV>The primary guideline is to make sure you are the copyright holder of
KV>the code you are contributing or that you have written permission from
KV>the copyright holder to contribute the code.

Thanks for responding, Keith. 

KV>Clemens Kadura wrote:
KV>> 
KV>> last week I raised an issue regarding finding objects not only by their simple 
fields but also by related objects.
KV>> e.g. "SELECT a FROM jdo.address WHERE a.person=$1 and a.zip=$2"
KV>> and there is a many-to-one-relation between adress and person.
KV>> 
KV>> Bruce Snyder replied that it is only planned to investigate in this in the future 
but no activities currently.

This is really due to the fact that I don't want to put work into the
current OQL engine when I'm going to commit a new one very soon. See
below for further information on this.

KV>> I walked through the source code a little bit (thanks Open Source) and found that 
it not that big deal to implement this function.
KV>> 
KV>> There are mainly 2 point to be changed:
KV>> 1. in OQLQueryImpl.bind(...) we need to bind the identifier values of the objects 
instead of the objects themselves.
KV>> 
KV>> 2. for multiple PKs we need to extend the SQL query so that it asks for all 
foreign keys.
KV>> e.g. "... WHERE address.personFk1=$ AND address.personFk2=$ and address.zip=$"
KV>> 
KV>> I prepared a short change description, 2 test cases (one for singlePKs and one 
for multiple) and the changed classes.
KV>> 
KV>> If you like, you can integrate this in your next version of castor.
KV>> 
KV>> (Is it the official way to deliver patches or is there a better channel in case 
I'd have another one)
...
KV>> 0. Content
KV>> ==========
KV>> I. Problem description
KV>> II. Considerations
KV>> III. necessary changes
KV>>  1. create a suitable SQL expression
KV>>  2. change the binding process
KV>> IV. Source Code of Changes
KV>> V. other optional changes
KV>> 
KV>> I. Problem description
KV>> =======================
KV>> It is not possible to handle OQL query statement that ask for a specific
KV>> referenced object.
KV>> 
KV>> Assume the followinmg case:
KV>> There is a Person that has Addresses (one-to-many relation, lazy loaded).
KV>> Persons have more than 1000 addresses.
KV>> For performance reasons it seems worth not to load all addresses, if you only
KV>> need those for a specific zip code.
KV>> 
KV>> One approach would be to run a query:
KV>> ...
KV>> aPerson = _db.load( TestLazyPerson.class, complexPK );
KV>> query = _db.getOQLQuery(
KV>>    "SELECT a FROM jdo.TestLazyAddress a WHERE Person = $1 AND zip = $2");
KV>> query.bind( aPerson );
KV>> query.bind( "10000" );
KV>> 
KV>> You see: $1 should be bound with a person object or at least with the identity
KV>> of a person object.
KV>> 
KV>> In the current release you get an error message, especially when the person's
KV>> identity is a multi-key one.

That's what the org.exolab.castor.persist.spi.Complex object is
for - compound primary keys. My apologies for not pointing this out
previously. The Complex object is used with the db.load() method like so:

    Object[] ids = new Object [3];
    ids[0] =  new Long( fooId );
    ids[1] = new Long( barId );
    ids[2] = ( Object ) name;

    Complex compoundId = new Complex( 3, ids );
    Baz baz = null;

    try 
    {
        db.begin();
        baz = ( Baz ) db.load( Baz.class, compoundId );
        db.commit();
    }
    catch ( PersistenceException e )
    {
        ...
    }


KV>> II. Considerations
KV>> ===================
KV>> For such a multi-key case, the SQL query statement should look like:
KV>> 
KV>> SELECT id,street,city,state,zip,fname,lname
KV>>  FROM test_pks_address
KV>>   WHERE (test_pks_address.fname = ? AND test_pks_address.lname = ?
KV>>          AND test_pks_address.zip = ?)
KV>> 
KV>> You can see that for each identity field of the related object
KV>> an entry in the WHERE clause is necessary !
KV>> 
KV>> Today there are 2 problems:
KV>> - the ParseTreeWalker only maps one identifier to one entry in the where clause
KV>> - it is not possible to bind Complex keys to object parameters

Agreed. This is a problem with the current OQL engine. Very soon I'm
going to commit a new OQL engine implemented using ANTLR. With this new
OQL engine, new features will be far easier to add.

KV>> III. necessary changes
KV>> ======================
KV>> 1. create a suitable SQL expression
KV>> ===================================
KV>> 
KV>> org.exolab.castor.jdo.oql.ParseTreeWalker
KV>> -----------------------------------------
KV>> The best place to create a WHERE clause entry for each identifier field
KV>>  is directly during the creation of the SQL expression
KV>> 
KV>> The suggested solution is to replace in the parse tree
KV>> the corresponding EQUAL token
KV>> EQUAL
KV>>   IDENTIFIER or DOT
KV>>   DOLLAR
KV>> 
KV>> with
KV>> 
KV>> AND
KV>>   EQUAL
KV>>     IDENTIFIER
KV>>     DOLLAR
KV>>   EQUAL
KV>>     IDENTIFIER
KV>>     DOLLAR
KV>> 
KV>> During createQueryExpression() we will test
KV>>  for each EQUAL token, if the included field has multiple SQLNames.
KV>> In this case we change the parse tree as described above.
KV>> 
KV>> In the further processing of this adapted parse tree the correct SQL expression
KV>>  will be created (as in the current version).
KV>> Doing this also in the ParamMap the correct links between OQL parameters
KV>>  and SQL parameters will be set (without any code change).
KV>> 
KV>> ---
KV>> The following dependent changes are necessary to gain this:
KV>> 
KV>> org.exolab.castor.jdo.oql.TokenTypes
KV>> ------------------------------------
KV>> Implement a SIMPLE_EQUAL token type to mark EQUAL tokens that were already
KV>> processed.
KV>> 
KV>> org.exolab.castor.jdo.oql.ParseTreeNode
KV>> ---------------------------------------
KV>> add a public method
KV>> public void replaceChild(ParseTreeNode child, int index)
KV>> 
KV>> 2. change the binding process
KV>> =============================
KV>> org.exolab.castor.jdo.engine.OQLQueryImpl
KV>> -----------------------------------------
KV>> 1st change:
KV>> When the customer tries to bind an persistable object, already the cuurent code
KV>>  converts this object to their (Complex) primary key. (line 170)
KV>> But this is not consequently continued:
KV>> We get an error at least when the database driver tries to serialize the object
KV>> 
KV>> The change is:
KV>> before we put the value into _bindValues we test, if the value is a Complex
KV>>  object. If yes, we put the content of Complex instead of the object itself
KV>> 
KV>> 2nd change:
KV>> specific for multiple Key handling
KV>> in ParseTreeWalker there were the additional links in the ParamMap already added
KV>>  with the change described above. We can use this here.
KV>> If there are multiple key fields in the Complex object we add always the next
KV>>  value for each loop through the ParamMap.
KV>> In the (improbable) case that such objects are bound multiple times, we reset
KV>>  the field pointer of the Complex object for the next usage.

As stated above I don't want to put effort into adding features to the
current OQL engine. Once I get the ANTLR based OQL engine checked into
CVS, I encourage you to become familiar with it and add features to it
because it will be much easier to do. Does this sound fair? 

I really appreciate your hard work to implement this and I would really
like you to continue to contribute to the project. You've demonstrated
an understanding of Castor JDO internals that few users ever take the
time to learn.

Bruce
-- 
perl -e 'print unpack("u30","<0G)[EMAIL PROTECTED]&5R\"F9E<G)E=\$\!F<FEI+F-O;0\`\`");'

The Castor Project 
http://www.castor.org/

Apache Geronimo 
http://incubator.apache.org/projects/geronimo.html

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-dev

Reply via email to