I tried something here for curiousity's sake.
I modified Criteria and Criterion to see what would happen if I used crossdb as the
underlying structure rather than the hashtable, so I added this as a global variable:
com.crossdb.sql.WhereClause wc = new WhereClause();
Then I changed the final add() function with this: The only line added here is:
wc.addCondition(new WhereCondition(column, WhereCondition.EQUAL_TO, value.toString()));
public Criteria add ( String column,
Object value,
SqlEnum comparison )
{
super.put( column, new Criterion(column, value, comparison) );
// TR MODIFIED//////////////////
// can replace the conparison here pretty easily by changing SqlEnum
or making new similar class
// using EQUAL_TO for test.
// also this would be better off being set in the appropriate function
so you can pass in the
// primitive value
wc.addCondition(new WhereCondition(column, WhereCondition.EQUAL_TO,
value.toString()));
// END MODIFY/////////////////
return this;
}
then in Criterion.and() I added one line:
wc.addCondition(new WhereCondition(criterion.column, WhereCondition.EQUAL_TO,
criterion.value.toString()));
So that looks like this now:
public Criterion and(Criterion criterion)
{
if (this.and == null)
{
this.and = criterion;
wc.addCondition(new WhereCondition(criterion.column,
WhereCondition.EQUAL_TO, criterion.value.toString()));
}
else
{
this.and.and(criterion);
}
return this;
}
And I added a second createQuery to BasePeer:
public static String createCrossdbQueryString(Criteria crit){
return crit.wc.toString();
}
Compare that to the original in BasePeer.createQueryString().
That's all I added, then I made a test class to setup the query you specified in the
e-mail below:
package org.apache.torque.util;
import org.apache.torque.TorqueException;
public class CriteriaCrossdbTest {
public static void main(String[] args) {
String colname = "invoice_cost";
Criteria criteria = new Criteria();
criteria.add(colname,
1000,
Criteria.GREATER_EQUAL);
Criteria.Criterion criterion =
criteria.getCriterion(colname);
criterion.and(
criteria.getNewCriterion(
criterion.getTable(),
criterion.getColumn(),
new
Integer(5000),
Criteria.LESS_EQUAL )
);
try {
System.out.println("NORMAL: " +
BasePeer.createQueryString(criteria));
System.out.println("CROSSDB: " +
BasePeer.createCrossdbQueryString(criteria));
} catch (TorqueException e) {
e.printStackTrace();
}
}
}
And that's it, now the output is the following:
NORMAL: SELECT FROM WHERE (.invoice_cost>=1000 AND (.invoice_cost<=5000))
CROSSDB: invoice_cost = 1000 AND invoice_cost = 5000
Would be identical if i made the converter from SqlEnum to Crossdb conditions, but
this is just for samples sake.
So basically, what I've done here is proven that you could keep backwards
compatability with people using Criteria, and at the same time, you could allow
complex querying by using Crossdb (and database independence at runtime).
Travis
---- Original Message ----
From: Eric Dobbs <[EMAIL PROTECTED]>
Sent: 2002-04-28
To: Turbine Torque Developers List <[EMAIL PROTECTED]>
Subject: Re: Why I don't like Criteria (was Re: Crossdb and Criteria Patch)
On Friday, April 26, 2002, at 12:24 AM, Sam Joseph wrote:
> Eric Dobbs wrote:
>
>> 1. wish it didn't extend hashtable,
>> would prefer 'has-a' instead of 'is-a'
>
> why?
It is a generally accepted practice to favor
composition over inheritance. Some of my complaints
below are classic examples of why composition is
favored.
I want to change the implementation because I think
hashtable is the wrong tool for the job. But I can't
without possibly breaking existing code which has been
written with the expectation that Criteria 'is-a'
hashtable.
>> 2. wish it wasn't implemented as a hashtable at all,
>> the use of column names for keys means
>> "FOO >= 10 AND FOO < 20" must use a Criterion.
>
> presumably this is only bad because you don't like Criterion
Hashtable is a poor tool for modeling SQL. A Hashtable
is a one-to-one map of keys and values. SQL doesn't
fit that structure. I see Criterion as a symptom that
Hashtable is the wrong tool for the job.
Criteria uses column names for keys. But nested
Criterion can include various column names. So which
column name is the right one for use with the key?
You could surely establish rules and conventions about
how to handle that situation, but the *need* for those
rules is an indication that Hashtable doesn't do what
an SQL statement needs.
>> 3. Criterion is ugly, and I wish client code didn't even know
>> about it.
>
> Ugliness is in the eye of the beholder :-)
Behold!
Item 1. An example from the Criteria HOWTO
Criteria criteria = new Criteria();
criteria.add(InvoicePeer.COST,
1000,
Criteria.GREATER_EQUAL);
Criteria.Criterion criterion =
criteria.getCriterion(InvoicePeer.COST);
criterion.and(
criteria.getNewCriterion(
criterion.getTable(),
criterion.getColumn(),
new Integer(5000),
Criteria.LESS_EQUAL )
);
Item 2. The equivalent SQL:
WHERE INVOICE_COST >= 1000
AND INVOICE_COST <= 5000
I want the Criteria object to be as readable as item 2,
or as close to that as possible within the confines of
Java syntax. The code I proposed last year was
something like this:
Sql sql = SqlFactory.getInstance("MySQL");
String where = sql.where(
sql.and(sql.greaterEqual(INVOICE_COST,1000),
sql.lessEqual(INVOICE_COST,5000) ));
Which is not totally readable, but much better than
what Criteria currently offers.
>> 4. as you have pointed out, queries of modest complexity using
>> nested Criterion have precedence problems (which is why I'm
>> interested in your patch).
>
> This seems to be the only substantial problem no? I mean points 1-3
> are personal preference (at least superficially). As long as the
> appropriate functionality is supported I don't think most users will
> care one way or the other.
>
> Is there a specific functional or maintenance reason why, if Criterion
> was fixed regarding precedence issues, that we would still want to
> replace Criteria/Criterion?
I think those fixes would extend the life of Criteria
a lot, but I'd still want to replace it.
-Eric
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>