In your documentation, under "advanced peers" (now: peers howto)
- Examples, there is an example how to build a criteria for 
a query like 
 select * from abc where (a < 1 and b > 2) or (a > 5  and b < 3)

Doing just as is described, we find that the actual sql
built together is
 ... where (a < 1) or (a > 5 and (b < 3)) and (b > 2)

Now, I am quite sure this is not equivalent.

After a (meanwhile deeper) look in Criteria/Criterion, I came
to the conclusion, that the whole Criteria/Criterion-concept 
does not allow real general and/or-nestings.
Every criterion holds one condition. con/disjunctions are
achieved by building two chains: and and or, to other criterions.
As there is no natural precedence between the and and the
or-link, it is done randomly (actually first or, then and),
leading to the above effect.

It seems there should be a more general object containing
a con- or disjunction (perhaps other kinds of links later)
and references to the sub-objects (same type) to be linked this way.
So you can build arbitrary trees of nested AND/OR.

I decided to do this, and the result is the following:

>>>

Criteria crit = new Criteria();
Criteria.Criterion a1 = crit.getNewCriterion(ABC.A,
1,Criteria.LESS_THAN);
Criteria.Criterion b2 = crit.getNewCriterion(ABC.B,
2,Criteria.GREATER_THAN);
Criteria.Criterion a5 = crit.getNewCriterion(ABC.A,
5,Criteria.GREATER_THAN);
Criteria.Criterion b3 = crit.getNewCriterion(ABC.B,
3,Criteria.LESS_THAN);
>> now the new thing:
crit.add(crit.getNewConnector(a1.and(b2),a5.and(b3),Criteria.CONN_TYPE_OR));

( completely using the new Connector technique:
  Criteria.Connector conn1=crit.getNewConnector(a1,b2,CONN_TYPE_AND);
  Criteria.Connector conn2=crit.getNewConnector(a5,b3,CONN_TYPE_AND);
  crit.add(crit.getNewConnector(conn1,conn2,Criteria.CONN_TYPE_OR));
)

----
Below you find the diff against the current version of Criteria.java.
I hope you (one of the developers, should I send email to one of them
directly?) will integrate this, as otherwise we have a problem when it 
comes to the next update..
I claim:
- This is a reasonable and "useful in practice" functionality that
  was missing
- The changes do not affect any previously written code, or with
  other words compatibility is preserved
(well, I can't guarantee, of course :-) But the only critical thing
 are the changes of the Criterion-subclass, and they should obviously
 have no side-effect. What does not work will be the auto-extraction of
 table-names, so you may use Connectors only with columns of the peer
 table, or add other tables manually(?))

And finally, you can change the example in the howto to no longer
be wrong.

Hope the work wasn't in vain, and Thanks in advance for your time,
Florian Lindauer


---- <snip> ------  Criteria_diff_cvs052901 $Id: Criteria.java,v 1.34
2001/05/13 20:54:27 jon Exp $

174a175,183
> 
>     /**
>      * Connection types for Connector-objects
>      */
>     public final static int CONN_TYPE_NONE=0;
>     public final static int CONN_TYPE_AND=1;
>     public final static int CONN_TYPE_OR=2;
> 
> 
456a466,489
>      * Method to return Connector-object that connects two criterions.
>      *
>      * @param c1/c2 The two criterions to connect
>      * @param ctype connection type - use defined static variables CONN_TYPE_xxx
>      * @return A Connector
>      */
>     public Connector getNewConnector(Criterion c1, Criterion c2, int ctype)
>     {
>         return new Connector(c1,c2,ctype);
>     }
> 
>     /**
>      * Method to return Connector-object that connects two connectors.
>      *
>      * @param c1/c2 The two connectors to connect
>      * @param ctype connection type - use defined static variables CONN_TYPE_xxx
>      * @return A Connector
>      */
>     public Connector getNewConnector(Connector c1, Connector c2, int ctype)
>     {
>         return new Connector(c1,c2,ctype);
>     }
> 
>     /**
485a519,532
>      * This method adds a prepared Connector object to the Criteria.
>      *
>      * @param c A Connector object
>      *
>      * @return A modified Criteria object.
>      */
>     public Criteria add(Connector c)
>     {
>         String hashkey=c.getHashkey();
>         super.put(hashkey, new Criterion(c));
>         return this;
>     }
> 
>     /**
3161a3209,3214
>          * holds connector if isConnector
>          */
>         private Connector connector;
>         private boolean isConnector=false;
> 
>         /**
3169a3223,3234
> 
>         /** Creates special criterion that only holds
>          *  a connector. Used to embed the Connector class
>          *  into Criterion. Considered in toString(),
>          *  appendPsTo() and getAttachedCriterion().
>          */
>         Criterion(Connector c)
>         { 
>           this.connector=c;
>           this.isConnector=true;
>         }
> 
3444a3510,3516
> 
>             if (isConnector)
>             {
>               connector.appendPsTo(sb,params);
>               return;
>             }
> 
3563a3636,3639
> 
>             if (isConnector)
>              return connector.toString();
> 
3649c3725,3726
<             traverseCriterion(this, crits);
---
>             if (!isConnector)
>              traverseCriterion(this, crits);
3668a3746,3850
> 
>     /**
>      * This is an inner class that lets you build
>      * generally nested AND/OR-clauses. A connector either
>      * holds a criterion, or connects two connectors with
>      * AND or OR
>      */
>     public final class Connector
>     {
> 
>         /**
>          * The two connector-objects connected by this (CONN_TYPE_AND/OR)
>          */
>         private Connector object1=null,object2=null;
> 
>         /**
>          * The criterion contained by this (CONN_TYPE_NONE)
>          */
>         private Criterion criterion=null;
> 
>         /**
>          * The connection's type (see static vars CONN_TYPE_xxx)
>          */
>         private int connection_type;
> 
>         Connector(Criterion crit)
>         {
>           criterion=crit;
>           connection_type=CONN_TYPE_NONE;
>         }
> 
>         Connector(Connector c1, Connector c2, int conn_type)
>         {
>           object1=c1;
>           object2=c2;
>           connection_type=conn_type;
>         }
> 
>         Connector(Criterion c1, Criterion c2, int conn_type)
>         {
>           object1=new Connector(c1);
>           object2=new Connector(c2);
>           connection_type=conn_type;
>         }
> 
>         String getHashkey()
>         { 
>           String key="CON"+this.hashCode();
>           if (object1!=null) key+=""+object1.hashCode();
>           if (object2!=null) key+=""+object2.hashCode();
>           return key;
>         }
> 
>         /**
>          * Build a string representation of the Connector.
>          *
>          * @return A String with the representation of the Connector.
>          */
>         public String toString()
>         {        
>             if (criterion!=null)
>             {
>               return criterion.toString();
>             }
>             else if (object1==null || object2==null)
>             { 
>               return ""; // should not occur
>             }
>             else
>             { 
>               String s1=object1.toString();
>               String s2=object2.toString();
>               if (connection_type==CONN_TYPE_AND)
>                return "("+s1+Criterion.AND+s2+")";
>               else
>                return "("+s1+Criterion.OR+s2+")";
> 
>             }
>         }
> 
>         public void appendPsTo(StringBuffer sb, List params)
>         {
>             if (criterion!=null)
>             {
>               criterion.appendPsTo(sb,params);
>               return;
>             }
>             else if (object1==null || object2==null)
>             { 
>               return; // should not occur
>             }
>             else
>             { sb.append("(");
>               object1.appendPsTo(sb,params);
>               if (connection_type==CONN_TYPE_AND)
>                sb.append(Criterion.AND);
>               else
>                sb.append(Criterion.OR);
>               object2.appendPsTo(sb,params);
>               sb.append(")");
>             }
> 
>         }
>     }
> 

-------------------(THE END)
------------------------------------------------

-- 
Florian Lindauer
_________________________________________
SecureNet GmbH * http://www.secure-net.de
Phone +49 89/32133-662 * [EMAIL PROTECTED]

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to