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]>