Hi Eric,

Please find patch attached.  Sorry about the corruption - my mailer 
seems to be weirding out.

CHEERS> SAM

Eric Dobbs wrote:

> On Wednesday, April 24, 2002, at 06:54  PM, Sam Joseph wrote:
>
>> So I'm not sure what the likelihood is for the Criteria patch I 
>> submitted actually being incorporated into the torque code, but I 
>> would like to know what that likelihood is.  I have found at least 
>> two other people in your mailing list archives who have been tripped 
>> up by the currently incorrect description of how to combine "and" and 
>> "or" queries using Criteria.Criterion.
>
>
> I see crossdb as a possible long term replacement
> for the Criteria object.  I'm interested in your
> patch for the near term.  I'll probably have more
> comments once I can apply the patch (as I said in
> the last email, please resend it as an attachment)


Index: src/java/org/apache/torque/util/Criteria.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-turbine-torque/src/java/org/apache/torque/util/Criteria.java,v
retrieving revision 1.20
diff -u -r1.20 Criteria.java
--- src/java/org/apache/torque/util/Criteria.java       10 Apr 2002 19:41:54 -0000     
 1.20
+++ src/java/org/apache/torque/util/Criteria.java       25 Apr 2002 03:14:12 -0000
@@ -3200,6 +3200,264 @@
         blobFlag = (b ? Boolean.TRUE: Boolean.FALSE);
     }
 
+    private Hashtable x_clause_table = new Hashtable();
+
+    /**
+     * This function takes a string representation of multiple Criterions
+     * and turns it into a set of nested criterion objects
+     *
+     * @param p_criterion_string     Criterion String representation we want to parse
+     * @return Criterion             Criterion object containing all sub Criterion 
+objects
+     */
+    public Criterion parseCriterionString(String p_criterion_string)
+      throws Exception
+    {
+        // find the first closing bracket
+       int x_first_close = p_criterion_string.indexOf(')');
+       if(x_first_close == -1) throw new Exception("no closing brace");
+       int x_latest = -1;
+       int x_matching_open = 0;
+       
+       // find the opening bracket in front of the closing bracket
+       
+       while(x_matching_open < x_first_close && x_matching_open != -1)
+       {
+         x_latest = x_matching_open;   
+         x_matching_open = p_criterion_string.indexOf('(',x_latest+1);
+
+       }
+       if(x_latest == -1) throw new Exception("no opening brace");
+       
+       // extract the internal criterion pair in between the brackets
+       
+       String x_pair = p_criterion_string.substring(x_latest+1,x_first_close);
+       boolean x_or = false;
+       
+       // work out what kind of clause it is
+       
+       int x_connector_start = x_pair.indexOf(Criterion.AND); 
+       int x_connector_end = -1;
+       if(x_connector_start == -1)
+       {
+         x_or = true;
+         x_connector_start = x_pair.indexOf(Criterion.OR);
+         if(x_connector_start == -1) 
+           throw new Exception("no connecting element: " + x_pair);
+         x_connector_end = x_connector_start + Criterion.OR.length();
+       }
+       else
+         x_connector_end = x_connector_start + Criterion.AND.length();
+         
+       // work out start position of former criterion  
+       
+       char x_char = '?';
+       int x_former_start = x_latest;
+       int x_incrementer = x_latest;
+       while(x_char == '?')
+       {
+         x_char = p_criterion_string.charAt(++x_incrementer);
+         x_former_start++;
+       }
+       
+       // see if we have already parsed this criterion or not 
+       
+       Integer x_position = new Integer(x_former_start);
+       Criterion x_former = (Criterion)(x_clause_table.get(x_position));
+       if(x_former == null)
+       {
+         x_former = parseCriterion(x_pair.substring(0,x_connector_start));
+         x_clause_table.put(x_position,x_former);
+       }
+       
+       // see if we have already parsed the latter criterion or not 
+       
+       x_position = new Integer(x_latest+1+x_connector_end+1);
+       Criterion x_latter = (Criterion)(x_clause_table.get(x_position));
+       if(x_latter == null)
+       {
+         x_latter = parseCriterion(x_pair.substring(x_connector_end));
+         x_clause_table.put(x_position,x_latter);
+       }
+       
+       Vector x_v = null;
+       
+       if(x_or == true)
+         x_former.or(x_latter);
+       else
+         x_former.and(x_latter);
+         
+       // now take original string and remove latter Criterion
+       
+       char[] x_array = new char[p_criterion_string.length()];
+         
+       p_criterion_string.getChars(0, x_latest, x_array, 0); 
+       x_array[x_latest] = '?';
+       
+       int x_end_former = x_latest+1+x_connector_start;
+       
+       p_criterion_string.getChars(x_latest+1,x_end_former,x_array,x_latest+1); 
+       for(int i=x_latest+1+x_connector_start+1;i<x_first_close+1;i++)
+         x_array[i] = '?';
+         
+       int x_end_string = p_criterion_string.length();
+       int x_end_pair = x_first_close+1;
+       p_criterion_string.getChars(x_end_pair, x_end_string, x_array, x_end_pair); 
+       String x_new_string = new String(x_array);
+       if(x_new_string.indexOf('(') == -1 && x_new_string.indexOf(')') == -1) 
+         return x_former;  // if the remaining string has no brackets return criterion
+       else
+          return parseCriterionString(x_new_string); // otherwise delve deeper
+    }
+    
+    /**
+     * This function takes in a string representation of a single Criterion with
+     * no brackets, and returns a Criterion object for that string
+     *
+     *@param p_criterion_string       Criterion string representation
+     *@return Criterion               the corresponding Criterion object
+     */
+    public Criterion parseCriterion(String p_criterion_string)
+      throws Exception
+    {
+       String x_table = null;
+       
+       // find the dot marking the end of the table name
+       
+        int x_end_table = p_criterion_string.indexOf('.');
+        if(x_end_table!=-1) 
+          x_table = p_criterion_string.substring(0,x_end_table);
+        
+        SqlEnum x_sql_enum = EQUAL;
+        
+        // determine what kind of comparator is being used
+        // apologies for heavy nesting here
+        // any suggestions for improvement gratefully recieved
+        
+        int x_end_column = p_criterion_string.indexOf(EQUAL.toString());
+        if(x_end_column==-1) 
+        {
+          x_end_column = p_criterion_string.indexOf(NOT_EQUAL.toString());
+          if(x_end_column==-1) 
+          {
+            x_end_column = p_criterion_string.indexOf(ALT_NOT_EQUAL.toString());
+            if(x_end_column==-1) 
+            {
+              x_end_column = p_criterion_string.indexOf(GREATER_THAN.toString());
+              if(x_end_column==-1) 
+              {
+                x_end_column = p_criterion_string.indexOf(LESS_THAN.toString());
+                if(x_end_column==-1) 
+                {
+                  x_end_column = p_criterion_string.indexOf(GREATER_EQUAL.toString());
+                  if(x_end_column==-1) 
+                  {
+                    x_end_column = p_criterion_string.indexOf(LESS_EQUAL.toString());
+                    if(x_end_column==-1) 
+                    {
+                      x_end_column = p_criterion_string.indexOf(LIKE.toString());
+                      if(x_end_column==-1) 
+                      { 
+                        x_end_column = 
+p_criterion_string.indexOf(NOT_LIKE.toString());
+                        if(x_end_column==-1) 
+                        {
+                          x_end_column = p_criterion_string.indexOf(IN.toString());
+                          if(x_end_column==-1) 
+                          {
+                            x_end_column = 
+p_criterion_string.indexOf(NOT_IN.toString());
+                            if(x_end_column==-1) 
+                            {
+                              x_end_column = 
+p_criterion_string.indexOf(ISNULL.toString());
+                              if(x_end_column==-1)
+                              { 
+                                x_end_column = 
+p_criterion_string.indexOf(ISNOTNULL.toString());
+                                if(x_end_column==-1)       
+                                {
+                                  throw new Exception("No recognised comparator in 
+this criterion: " 
+                                                       + 
+p_criterion_string.toString());
+                                }
+                                else
+                                  x_sql_enum = ISNOTNULL;     
+                              }
+                              else
+                              {
+                                x_sql_enum = ISNULL;
+                              }
+                            }
+                            else
+                            {
+                              x_sql_enum = NOT_IN;
+                            }
+                          }
+                          else
+                          {
+                            x_sql_enum = IN;
+                          }
+                        }
+                        else
+                        {
+                          x_sql_enum = NOT_LIKE;
+                        }
+                      }
+                      else
+                      {
+                        x_sql_enum = LIKE;
+                      }
+                    }
+                    else
+                    {
+                      x_sql_enum = LESS_EQUAL;  
+                    }              
+                  }
+                  else
+                  {
+                    x_sql_enum = GREATER_EQUAL;               
+                  }
+                }
+                else
+                {
+                  x_sql_enum = LESS_THAN;
+                }
+              }
+              else
+              {
+                x_sql_enum = GREATER_THAN;
+              }
+            }
+            else
+            {
+              x_sql_enum = ALT_NOT_EQUAL;
+            }
+          }
+          else
+          {
+            x_sql_enum = NOT_EQUAL;
+          }
+        }
+        else
+        {
+          x_sql_enum = EQUAL;
+        }
+        
+        // extract the various components
+        
+        if(x_end_table == -1) x_end_table++;
+        String x_column = p_criterion_string.substring(x_end_table+1,x_end_column);
+        String x_value = 
+p_criterion_string.substring(x_end_column+x_sql_enum.toString().length());
+        x_value = x_value.replace('\'',' ');
+        x_value = x_value.trim();
+        
+        // try and create the Criterion object
+        
+        Criterion x_criterion = null;
+        if(x_table != null)
+          x_criterion = new Criterion(x_table,x_column,(Object)(x_value),x_sql_enum);
+        else
+          x_criterion = new Criterion(x_column,(Object)(x_value),x_sql_enum);
+          
+       return x_criterion;
+    }
+
+
     /**
      * This is an inner class that describes an object in the
      * criteria.
@@ -3217,6 +3475,7 @@
 
         /** Table name. */
         private String table;
+        
 
         /** Column name. */
         private String column;
@@ -3233,14 +3492,20 @@
         /**
          * Another Criterion connected to this one by an OR clause.
          */
-        private Criterion or;
+        //private Criterion or;
 
         /**
          * Another criterion connected to this one by an AND clause.
          */
-        private Criterion and;
+        //private Criterion and;
 
         /**
+         * other connected criteria and their types.
+         */
+        private Vector clauses = new Vector(); 
+        private Vector types = new Vector(); 
+        
+        /**
          * Creates a new instance, initializing a couple members.
          */
         private Criterion( Object val, SqlEnum comp )
@@ -3412,13 +3677,10 @@
         public void setDB(DB  v)
         {
             this.db = v;
-            if ( and != null )
+            
+            for(int i=0;i<this.clauses.size();i++)
             {
-                and.setDB(v);
-            }
-            if ( or != null )
-            {
-                or.setDB(v);
+              ((Criterion)(clauses.elementAt(i))).setDB(v);
             }
         }
 
@@ -3447,48 +3709,45 @@
         /**
          *  get the criterion from this Criterion's AND field.
          */
-        public Criterion getAnd()
+        public Vector getClauses()
+        {
+            return clauses;
+        }
+
+        /**
+         *  get the criterion from this Criterion's AND field.
+         */
+        public Vector getTypes()
         {
-            return and;
+            return types;
         }
 
         /**
-         * Append a Criteria onto this Criteria's AND field.
+         * Append an AND Criterion onto this Criterion's list.
          */
         public Criterion and(Criterion criterion)
         {
-            if (this.and == null)
-            {
-                this.and = criterion;
-            }
-            else
-            {
-                this.and.and(criterion);
-            }
+            this.clauses.addElement(criterion);
+            this.types.addElement(AND);
             return this;
         }
 
         /**
          *  get the criterion from this Criterion's AND field.
          */
+         /*
         public Criterion getOr()
         {
             return or;
-        }
+        }*/
 
         /**
-         * Append a Criterion onto this Criterion's OR field.
+         * Append an OR Criterion onto this Criterion's list.
          */
         public Criterion or(Criterion criterion)
         {
-            if (this.or == null)
-            {
-                this.or = criterion;
-            }
-            else
-            {
-                this.or.or(criterion);
-            }
+            this.clauses.addElement(criterion);
+            this.types.addElement(OR);
             return this;
         }
 
@@ -3500,13 +3759,15 @@
             //
             // it is alright if value == null
             //
-
+            
             if (column == null)
             {
                 return;
             }
 
-            sb.append('(');
+            Criterion x_clause = null;
+            for(int j=0;j<this.clauses.size();j++)
+              sb.append('(');
             if ( CUSTOM == comparison )
             {
                 if ( value != null && ! "".equals(value) )
@@ -3532,18 +3793,13 @@
                                     ignoreStringCase, getDb(), sb);
             }
 
-            if (or != null)
-            {
-                sb.append(OR);
-                or.appendTo(sb);
-            }
-
-            if (and != null)
+            for(int i=0;i<this.clauses.size();i++)
             {
-                sb.append(AND);
-                and.appendTo(sb);
+                sb.append(this.types.elementAt(i));
+                x_clause = (Criterion)(this.clauses.elementAt(i));
+                x_clause.appendTo(sb);
+                sb.append(')');
             }
-            sb.append(')');
         }
 
         /**
@@ -3562,8 +3818,10 @@
             }
 
             DB db = getDb();
-
-            sb.append('(');
+            
+            Criterion x_clause = null;
+            for(int j=0;j<this.clauses.size();j++)
+              sb.append('(');
             if ( CUSTOM == comparison )
             {
                 if ( !"".equals(value) )
@@ -3640,18 +3898,15 @@
                 }
             }
 
-            if (or != null)
+            for(int i=0;i<this.clauses.size();i++)
             {
-                sb.append(OR);
-                or.appendPsTo(sb,params);
+                sb.append(this.types.elementAt(i));
+                x_clause = (Criterion)(this.clauses.elementAt(i));
+                x_clause.appendPsTo(sb,params);
+                sb.append(')');
             }
+            
 
-            if (and != null)
-            {
-                sb.append(AND);
-                and.appendPsTo(sb,params);
-            }
-            sb.append(')');
         }
 
         /**
@@ -3717,12 +3972,14 @@
             }
 
             // check chained criterion
-            isEquiv &= (and == null && crit.getAnd() == null )
-                || (and != null && and.equals(crit.getAnd()));
-
-            isEquiv &= (or == null && crit.getOr() == null )
-                || (or != null && or.equals(crit.getOr()));
-
+            
+            isEquiv &= this.clauses.size() == crit.getClauses().size();
+            for(int i=0;i<this.clauses.size();i++)
+            {
+              isEquiv &=  
+((String)(types.elementAt(i))).equals((String)(crit.getTypes().elementAt(i))); 
+              isEquiv &=  
+((Criterion)(clauses.elementAt(i))).equals((Criterion)(crit.getClauses().elementAt(i)));
+ 
+            }
+                
             return isEquiv;
         }
 
@@ -3743,19 +4000,17 @@
                 h ^= column.hashCode();
             }
 
-            if (and != null)
+            for(int i=0;i<this.clauses.size();i++)
             {
-                h ^= and.hashCode();
-            }
-
-            if (or != null)
-            {
-                h ^= or.hashCode();
+                h ^= ((Criterion)(clauses.elementAt(i))).hashCode();
             }
 
             return h;
         }
 
+        /**
+         * get all tables from nested criterion objects
+         */
         public String[] getAllTables()
         {
             StringStack tables = new StringStack();
@@ -3763,16 +4018,24 @@
             return tables.toStringArray();
         }
 
+        /**
+         * method supporting recursion through all criterions to give
+         * us a StringStack of tables from each criterion
+         */
         private void addCriterionTable(Criterion c, StringStack s)
         {
             if ( c != null )
             {
                 s.add(c.getTable());
-                addCriterionTable(c.getAnd(), s);
-                addCriterionTable(c.getOr(), s);
+                for(int i=0;i<c.getClauses().size();i++)
+                  addCriterionTable((Criterion)(c.getClauses().elementAt(i)), s);
             }
         }
-
+        
+        /**
+         * get an array of all criterion attached to this
+         * recursing through all sub criterion
+         */
         public Criterion[] getAttachedCriterion()
         {
             ArrayList crits = new ArrayList();
@@ -3786,14 +4049,19 @@
             return crita;
         }
 
+        /**
+         * method supporting recursion through all criterions to give
+         * us an ArrayList of them
+         */
         private void traverseCriterion(Criterion c, ArrayList a)
         {
             if ( c != null )
             {
                 a.add(c);
-                traverseCriterion(c.getAnd(), a);
-                traverseCriterion(c.getOr(), a);
+                for(int i=0;i<c.getClauses().size();i++)
+                  traverseCriterion((Criterion)(c.getClauses().elementAt(i)), a);
             }
         }
     }
 }
+

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

Reply via email to