db-torque-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tfisc...@apache.org
Subject svn commit: r1329656 [2/4] - in /db/torque/torque4/trunk: torque-runtime/src/main/java/org/apache/torque/criteria/ torque-runtime/src/main/java/org/apache/torque/map/ torque-runtime/src/main/java/org/apache/torque/sql/ torque-runtime/src/main/java/org/...
Date Tue, 24 Apr 2012 11:52:51 GMT
Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/Criterion.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/Criterion.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/Criterion.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/Criterion.java Tue Apr 24 11:52:50 2012
@@ -27,11 +27,10 @@ import java.util.List;
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.torque.Column;
-import org.apache.torque.ColumnImpl;
 
 /**
  * Describes one or more where clause parts in the Criteria.
- * Either the parts list is not null and represe<6nts this criterion
+ * Either the parts list is not null and represents this criterion
  * or the column, value, comparison and ignoreStringCase columns
  * are not null and represent this criterion.
  */
@@ -46,14 +45,31 @@ public class Criterion implements Serial
     /** Constant for the operator " OR ". */
     public static final String OR = " OR ";
 
-    /** Value of the CO. */
-    private Object value;
+    /**
+     * Left-hand-side value of the comparison, may be null.
+     * If this object implements the Column interface, it is interpreted as
+     * a value computed by the database, otherwise as verbatim value.
+     */
+    private Object lValue;
 
-    /** Comparison value. */
+    /** Comparison operator. Can only be null if sql is not null. */
     private SqlEnum comparison;
 
-    /** Column. */
-    private Column column;
+    /**
+     * Right-hand-side value of the comparison, may be null.
+     * If this object implements the Column interface, it is interpreted as
+     * a value computed by the database, otherwise as verbatim value.
+     */
+    private Object rValue;
+
+    /** A verbatim SQL for this Criterion. */
+    private String sql;
+
+    /**
+     * Replacements for the placeholders in the verbatim SQL.
+     * Is only used if sql is not null.
+     */
+    private Object[] preparedStatementReplacements;
 
     /** Flag to ignore case in comparison */
     private boolean ignoreCase = false;
@@ -75,59 +91,94 @@ public class Criterion implements Serial
 
     /**
      * Create a new instance.
-     *
-     * @param column the column description, not null.
-     * @param val An Object with the value for the Criteria, may be null.
-     * @param comp A String with the comparison value, not null.
-     *
-     * @throws NullPointerException if column is null.
-     */
-    public Criterion(Column column, Object val, SqlEnum comp)
-    {
-        this.value = val;
-        setComparison(comp);
-        setColumn(column);
-    }
-
-    /**
-     * Create a new instance.
-     *
-     * @param column the name of the column description, not null.
-     * @param val An Object with the value for the Criteria, may be null.
-     * @param comp A String with the comparison value, not null.
+     * Either this Criterion represents a comparison without verbatim SQL;
+     * in this case the parameters lValue and comparison must be not null,
+     * rValue may be not null and sql and preparedStatementReplacements must
+     * be null; or it represents a verbatim sql condition, in which case
+     * the parameter comparison must be null and the sql must be not null
+     * (preparedStatementReplacements may be set to contain sql placeholder
+     * replacement values, and lValue and rValue can be set to add columns
+     * to the automatically computed from clause of the query).
+     *
+     * @param lValue the left hand side value of the comparison.
+     *        If this value should be a value from the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
+     * @param rValue the right hand side value of the comparison.
+     *        If this value should be a value from the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
+     * @param comparison The comparison operator. Either this parameter or
+     *        sql must be not null.
+     * @param sql a verbatim sql condition. Either this parameter or
+     *        comparison must be not null.
+     * @param preparedStatementReplacements Values for the placeholders
+     *        in the verbatim sql condition.
      *
      * @throws NullPointerException if column is null.
      */
-    public Criterion(String column, Object val, SqlEnum comp)
-    {
-        this.value = val;
-        setComparison(comp);
-        setColumn(new ColumnImpl(column));
+    public Criterion(
+            Object lValue,
+            Object rValue,
+            SqlEnum comparison,
+            String sql,
+            Object[] preparedStatementReplacements)
+    {
+        if (comparison != null
+                && (sql != null || preparedStatementReplacements != null))
+        {
+            throw new IllegalArgumentException("Either comparison or "
+                    + "some of (sql, preparedStatementReplacements) "
+                    + "can be not null, not both");
+        }
+        if ((lValue == null || comparison == null)
+                && (sql == null))
+        {
+            throw new IllegalArgumentException("Either the values"
+                    + "(lValue, comparison) or "
+                    + "sql must be not null");
+        }
+        this.lValue = lValue;
+        this.comparison = comparison;
+        this.rValue = rValue;
+        this.sql = sql;
+        this.preparedStatementReplacements = preparedStatementReplacements;
     }
 
     /**
-     * Create a new instance, using equals as comparison.
+     * Create a new instance without verbatim sql, using equals as
+     * comparison operator.
      *
-     * @param tableColumn the column description.
-     * @param val An Object with the value for the Criteria.
+     * @param lValue the left hand side value of the comparison, not null.
+     *        If this value should be a value from the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
+     * @param rValue the right hand side value of the comparison.
+     *        If this value should be a value from the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
      */
-    public Criterion(Column column, Object val)
+    public Criterion(Object lValue, Object rValue)
     {
-        this(column, val, Criteria.EQUAL);
+        this(lValue, rValue, Criteria.EQUAL, null, null);
     }
 
     /**
-     * Create a new instance.
-     *
-     * @param column the name of the column description, not null.
-     * @param val An Object with the value for the Criteria, may be null.
-     * @param comp A String with the comparison value, not null.
+     * Create a new instance without verbatim sql.
      *
-     * @throws NullPointerException if column is null.
+     * @param lValue the left hand side value of the comparison, not null.
+     *        If this value should be a value from the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
+     * @param rValue the right hand side value of the comparison.
+     *        If this value should be a value from the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
+     * @param comparison The comparison operator, not null.
      */
-    public Criterion(String column, Object val)
+    public Criterion(Object lValue, Object rValue, SqlEnum comparison)
     {
-        this(new ColumnImpl(column), val, Criteria.EQUAL);
+        this(lValue, rValue, comparison, null, null);
     }
 
     /**
@@ -137,91 +188,117 @@ public class Criterion implements Serial
      */
     public Criterion(Criterion toCopy)
     {
-        this.column = toCopy.column;
+        this.lValue = toCopy.lValue;
         this.comparison = toCopy.comparison;
-        this.value = toCopy.value;
+        this.rValue = toCopy.rValue;
+        this.sql = toCopy.sql;
+        this.preparedStatementReplacements
+                = toCopy.preparedStatementReplacements;
         this.ignoreCase = toCopy.ignoreCase;
         this.parts = toCopy.parts;
         this.conjunction = toCopy.conjunction;
     }
 
     /**
-     * Sets the column.
+     * Get the left hand side value of the comparison.
      *
-     * @param column the column, not null.
+     * @return the left hand side value of the comparison.
+     *         If this value is a value computed by the database,
+     *         the object implements the
+     *         <code>org.apache.torque.Column</code> interface.
+     */
+    public Object getLValue()
+    {
+        return this.lValue;
+    }
+
+    /**
+     * Set the left hand side value of the comparison.
      *
-     * @throws NullPointerException if column is null.
+     * @param lValue the left hand side value of the comparison.
+     *        If this value is a value computed by the database,
+     *        the object must implement the
+     *        <code>org.apache.torque.Column</code> interface.
      */
-    private void setColumn(Column column)
+    public void setLValue(Object lValue)
     {
-        if (column == null)
-        {
-            throw new NullPointerException("column must not be null");
-        }
-        this.column = column;
+        this.lValue = lValue;
     }
 
     /**
-     * Get the column.
+     * Get the comparison.
      *
-     * @return the column.
+     * @return A String with the comparison, or null if this
+     *         Criterion represents a verbatim sql condition.
      */
-    public Column getColumn()
+    public SqlEnum getComparison()
     {
-        return this.column;
+        return this.comparison;
     }
 
     /**
-     * Sets the comparison.
+     * Get the right hand side value of the comparison.
      *
-     * @param comparison the comparison, not null.
+     * @return the right hand side value of the comparison.
+     *         If this value is a value computed by the database,
+     *         the object implements the
+     *         <code>org.apache.torque.Column</code> interface.
+     */
+    public Object getRValue()
+    {
+        return this.rValue;
+    }
+
+    /**
+     * Set the right hand side value of the comparison.
      *
-     * @throws NullPointerException if comparison is null.
+     * @param rValue the right hand side value of the comparison.
+     *         If this value is a value computed by the database,
+     *         the object must implement the
+     *         <code>org.apache.torque.Column</code> interface.
      */
-    private void setComparison(SqlEnum comparison)
+    public void setRValue(Object rValue)
     {
-        if (comparison == null)
-        {
-            throw new NullPointerException("comparison must not be null");
-        }
-        this.comparison = comparison;
+        this.rValue = rValue;
     }
 
     /**
-     * Get the comparison.
+     * Returns the verbatim sql for this condition.
      *
-     * @return A String with the comparison.
+     * @return the verbatim sql for this condition, or null if this
+     *         Criterion does not represent a verbatim sql condition.
      */
-    public SqlEnum getComparison()
+    public String getSql()
     {
-        return this.comparison;
+        return sql;
     }
 
     /**
-     * Get the value.
+     * Returns the prepared statement replacements for a verbatim sql condition.
      *
-     * @return An Object with the value.
+     * @return the replacement values, or null.
      */
-    public Object getValue()
+    public Object[] getPreparedStatementReplacements()
     {
-        return this.value;
+        return preparedStatementReplacements;
     }
 
     /**
-     * Set the value of the criterion.
+     * Returns whether this Criterion represents a verbatim sql condition.
      *
-     * @param value the new value.
+     * @return true if  this Criterion represents a verbatim sql condition,
+     *         false if the sql is computed from lValue, comparison and rValue.
      */
-    public void setValue(Object value)
+    public boolean isVerbatimSqlCondition()
     {
-        this.value = value;
+        return (sql != null);
     }
 
     /**
-     * Sets ignore case.
+     * Sets ignore case. ignoreCase is ignored for a verbatim sql statement.
      *
      * @param b True if case should be ignored.
-     * @return A modified Criteria object.
+     * @return A modified Criterion object.
      */
     public Criterion setIgnoreCase(boolean b)
     {
@@ -330,9 +407,11 @@ public class Criterion implements Serial
             parts.add(copy);
             parts.add(criterion);
             this.conjunction = conjunction;
-            this.column = null;
+            this.rValue = null;
             this.comparison = null;
-            this.value = null;
+            this.lValue = null;
+            this.sql = null;
+            this.preparedStatementReplacements = null;
             this.ignoreCase = false;
         }
     }
@@ -368,15 +447,46 @@ public class Criterion implements Serial
         {
             if (Criteria.CUSTOM == comparison)
             {
-                if (value != null && !"".equals(value))
+                if (rValue != null && !"".equals(rValue))
                 {
-                    sb.append((String) value);
+                    sb.append((String) rValue);
                 }
             }
+            else if (isVerbatimSqlCondition())
+            {
+                sb.append(sql);
+            }
             else
             {
-                String field = column.getSqlExpression();
-                sb.append(field).append(comparison).append(value);
+                String lValueDisplay;
+                if (lValue instanceof Column)
+                {
+                    lValueDisplay = ((Column) lValue).getSqlExpression();
+                }
+                else if (lValue != null)
+                {
+                    lValueDisplay = lValue.toString();
+                }
+                else
+                {
+                    lValueDisplay = "";
+                }
+                String rValueDisplay;
+                if (rValue instanceof Column)
+                {
+                    rValueDisplay = ((Column) rValue).getSqlExpression();
+                }
+                else if (rValue != null)
+                {
+                    rValueDisplay = rValue.toString();
+                }
+                else
+                {
+                    rValueDisplay = "";
+                }
+                sb.append(lValueDisplay)
+                    .append(comparison)
+                    .append(rValueDisplay);
             }
         }
     }
@@ -414,12 +524,15 @@ public class Criterion implements Serial
 
         Criterion criterion = (Criterion) obj;
         EqualsBuilder equalsBuilder = new EqualsBuilder();
-        equalsBuilder.append(criterion.column, this.column);
-        equalsBuilder.append(criterion.comparison, this.comparison);
-        equalsBuilder.append(criterion.value, this.value);
-        equalsBuilder.append(criterion.ignoreCase, this.ignoreCase);
-        equalsBuilder.append(criterion.parts, this.parts);
-        equalsBuilder.append(criterion.conjunction, this.conjunction);
+        equalsBuilder.append(criterion.lValue, this.lValue)
+                .append(criterion.comparison, this.comparison)
+                .append(criterion.rValue, this.rValue)
+                .append(criterion.sql, this.sql)
+                .append(criterion.preparedStatementReplacements,
+                        this.preparedStatementReplacements)
+                .append(criterion.ignoreCase, this.ignoreCase)
+                .append(criterion.parts, this.parts)
+                .append(criterion.conjunction, this.conjunction);
         return equalsBuilder.isEquals();
     }
 
@@ -429,12 +542,14 @@ public class Criterion implements Serial
     public int hashCode()
     {
         HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
-        hashCodeBuilder.append(this.column);
-        hashCodeBuilder.append(this.comparison);
-        hashCodeBuilder.append(this.value);
-        hashCodeBuilder.append(this.ignoreCase);
-        hashCodeBuilder.append(this.parts);
-        hashCodeBuilder.append(this.conjunction);
+        hashCodeBuilder.append(this.lValue)
+                .append(this.comparison)
+                .append(this.rValue)
+                .append(this.sql)
+                .append(this.preparedStatementReplacements)
+                .append(this.ignoreCase)
+                .append(this.parts)
+                .append(this.conjunction);
         return hashCodeBuilder.toHashCode();
     }
 }

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/FromElement.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/FromElement.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/FromElement.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/criteria/FromElement.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,163 @@
+package org.apache.torque.criteria;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+/**
+ * This class describes an Element in the From-part of a SQL clause.
+ * It must contain the name of the database table.
+ * It might contain an alias for the table name, a join type
+ * and a join condition.
+ * The class is immutable.
+ */
+public class FromElement
+{
+    /** The tablename, might contain an appended alias name */
+    private String tableName = null;
+
+    /** The type of the join, e.g. SqlEnum.LEFT_JOIN */
+    private SqlEnum joinType = null;
+
+    /** The join condition, e.g. table_a.id = table_b.a_id */
+    private String joinCondition = null;
+
+    /**
+     * Constructor with join type null and joinCondition null.
+     * @param tableName the table name, might contain an appended alias name
+     *        e.g. <br />
+     *        table_1<br />
+     *        table_1 alias_for_table_1
+     */
+    public FromElement(String tableName)
+    {
+        this(tableName, null, null);
+    }
+
+    /**
+     * Constructor
+     * @param tableName the tablename, might contain an appended alias name
+     *        e.g. <br />
+     *        table_1<br />
+     *        table_1 alias_for_table_1
+     * @param joinType the type of the join, e.g. SqlEnum.LEFT_JOIN,
+     *        or null if no excplicit join is wanted
+     * @param joinCondition the join condition,
+     *        e.g. table_a.id = table_b.a_id,
+     *        or null if no explicit join is wanted
+     *        (In this case, the join condition is appended to the
+     *         whereClause instead)
+     */
+    public FromElement(String tableName,
+            SqlEnum joinType,
+            String joinCondition)
+    {
+        this.tableName = tableName;
+        this.joinType = joinType;
+        this.joinCondition = joinCondition;
+    }
+
+
+    /**
+     * @return the join condition, e.g. table_a.id = table_b.a_id,
+     *         or null if the join is not an explicit join
+     */
+    public String getJoinCondition()
+    {
+        return joinCondition;
+    }
+
+    /**
+     * @return the type of the join, e.g. SqlEnum.LEFT_JOIN,
+     *         or null if the join is not an explicit join
+     */
+    public SqlEnum getJoinType()
+    {
+        return joinType;
+    }
+
+    /**
+     * @return the tablename, might contain an appended alias name,
+     *         e.g. <br />
+     *         table_1<br />
+     *         table_1 alias_for_table_1
+     *
+     */
+    public String getTableName()
+    {
+        return tableName;
+    }
+
+    /**
+     * Returns a SQL representation of the element
+     * @return a SQL representation of the element
+     */
+    public String toString()
+    {
+        StringBuffer result = new StringBuffer();
+        if (joinType != null)
+        {
+            result.append(joinType);
+        }
+        result.append(tableName);
+        if (joinCondition != null)
+        {
+            result.append(SqlEnum.ON);
+            result.append(joinCondition);
+        }
+        return result.toString();
+    }
+
+
+    @Override
+    public int hashCode()
+    {
+        return new HashCodeBuilder()
+                .append(joinCondition)
+                .append(joinType)
+                .append(tableName)
+                .toHashCode();
+    }
+
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+        {
+            return true;
+        }
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        FromElement other = (FromElement) obj;
+        return new EqualsBuilder()
+            .append(joinCondition, other.joinCondition)
+            .append(joinType, other.joinType)
+            .append(tableName, other.tableName)
+            .isEquals();
+    }
+}

Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/map/MapHelper.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/map/MapHelper.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/map/MapHelper.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/map/MapHelper.java Tue Apr 24 11:52:50 2012
@@ -43,18 +43,25 @@ public final class MapHelper
      * As aliases and asColumns are resolved, the returned table map need not
      * contain the same table name as the column.
      *
-     * @param column the column to get the table map for.
+     * @param possibleColumn the possible column to get the table map for.
      * @param criteria A criteria containing the database name and perhaps
      *        aliases for the column and table name, not null.
      * @param defaultTableMap a default table map which is used if the table
      *        name cannot be resolved, may be null.
-     * @return the table map, or null if the table name cannot be resolved.
+     *
+     * @return the table map, or null if possibleColumn does not implement
+     *         the column interface or if the table name cannot be resolved.
      */
     public static TableMap getTableMap(
-            Column column,
+            Object possibleColumn,
             CriteriaInterface criteria,
             TableMap defaultTableMap)
     {
+        if (!(possibleColumn instanceof Column))
+        {
+            return null;
+        }
+        Column column = (Column) possibleColumn;
         TableMap result = null;
         String tableName = column.getTableName();
         if (tableName == null)

Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/JoinBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/JoinBuilder.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/JoinBuilder.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/JoinBuilder.java Tue Apr 24 11:52:50 2012
@@ -25,6 +25,7 @@ import org.apache.torque.Column;
 import org.apache.torque.Database;
 import org.apache.torque.TorqueException;
 import org.apache.torque.criteria.CriteriaInterface;
+import org.apache.torque.criteria.FromElement;
 import org.apache.torque.criteria.Join;
 import org.apache.torque.criteria.SqlEnum;
 import org.apache.torque.util.UniqueList;
@@ -70,7 +71,7 @@ public final class JoinBuilder
             return;
         }
 
-        UniqueList<Query.FromElement> queryFromClause = query.getFromClause();
+        UniqueList<FromElement> queryFromClause = query.getFromClause();
         UniqueList<String> queryWhereClause = query.getWhereClause();
 
         for (int i = 0; i < criteriaJoins.size(); i++)
@@ -126,14 +127,14 @@ public final class JoinBuilder
                                 queryFromClause,
                                 leftTableName))
                     {
-                        Query.FromElement fromElement
-                                = new Query.FromElement(
+                        FromElement fromElement
+                                = new FromElement(
                                         leftTableName, null, null);
                         queryFromClause.add(fromElement);
                     }
 
-                    Query.FromElement fromElement
-                            = new Query.FromElement(
+                    FromElement fromElement
+                            = new FromElement(
                                     rightTableName,
                                     joinType,
                                     buildJoinCondition(
@@ -158,8 +159,8 @@ public final class JoinBuilder
                     // now add the join in reverse order
                     // rightTableName must not be added
                     // because it is already present
-                    Query.FromElement fromElement
-                            = new Query.FromElement(
+                    FromElement fromElement
+                            = new FromElement(
                                     leftTableName,
                                     reverseJoinType(joinType),
                                     buildJoinCondition(

Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/PreparedStatementPart.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/PreparedStatementPart.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/PreparedStatementPart.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/PreparedStatementPart.java Tue Apr 24 11:52:50 2012
@@ -62,6 +62,21 @@ public class PreparedStatementPart
         return preparedStatementReplacements;
     }
 
+    /**
+     * Appends another PreparedStatementPart to this part.
+     *
+     * @param toAppend the part to append, not null.
+     *
+     * @return this PreparedStatementPart (with toAppend appended).
+     */
+    public PreparedStatementPart append(PreparedStatementPart toAppend)
+    {
+        sql.append(toAppend.sql);
+        preparedStatementReplacements.addAll(
+                toAppend.preparedStatementReplacements);
+        return this;
+    }
+
     @Override
     public int hashCode()
     {

Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/Query.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/Query.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/Query.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/Query.java Tue Apr 24 11:52:50 2012
@@ -24,10 +24,8 @@ import java.util.Iterator;
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.torque.TorqueException;
-import org.apache.torque.criteria.SqlEnum;
+import org.apache.torque.criteria.FromElement;
 import org.apache.torque.util.UniqueList;
 
 /**
@@ -567,135 +565,4 @@ public class Query
         return stringBuilder.toString();
     }
 
-    /**
-     * This class describes an Element in the From-part of a SQL clause.
-     * It must contain the name of the database table.
-     * It might contain an alias for the table name, a join type
-     * and a join condition.
-     * The class is package visible, as it is used in BasePeer,
-     * and is immutable.
-     */
-    public static class FromElement
-    {
-
-        /** The tablename, might contain an appended alias name */
-        private String tableName = null;
-
-        /** The type of the join, e.g. SqlEnum.LEFT_JOIN */
-        private SqlEnum joinType = null;
-
-        /** The join condition, e.g. table_a.id = table_b.a_id */
-        private String joinCondition = null;
-
-        /**
-         * Constructor
-         * @param tableName the tablename, might contain an appended alias name
-         *        e.g. <br />
-         *        table_1<br />
-         *        table_1 alias_for_table_1
-         * @param joinType the type of the join, e.g. SqlEnum.LEFT_JOIN,
-         *        or null if no excplicit join is wanted
-         * @param joinCondition the join condition,
-         *        e.g. table_a.id = table_b.a_id,
-         *        or null if no explicit join is wanted
-         *        (In this case, the join condition is appended to the
-         *         whereClause instead)
-         */
-        public FromElement(String tableName,
-                SqlEnum joinType,
-                String joinCondition)
-        {
-            this.tableName = tableName;
-            this.joinType = joinType;
-            this.joinCondition = joinCondition;
-        }
-
-
-        /**
-         * @return the join condition, e.g. table_a.id = table_b.a_id,
-         *         or null if the join is not an explicit join
-         */
-        public String getJoinCondition()
-        {
-            return joinCondition;
-        }
-
-        /**
-         * @return the type of the join, e.g. SqlEnum.LEFT_JOIN,
-         *         or null if the join is not an explicit join
-         */
-        public SqlEnum getJoinType()
-        {
-            return joinType;
-        }
-
-        /**
-         * @return the tablename, might contain an appended alias name,
-         *         e.g. <br />
-         *         table_1<br />
-         *         table_1 alias_for_table_1
-         *
-         */
-        public String getTableName()
-        {
-            return tableName;
-        }
-
-        /**
-         * Returns a SQL representation of the element
-         * @return a SQL representation of the element
-         */
-        public String toString()
-        {
-            StringBuffer result = new StringBuffer();
-            if (joinType != null)
-            {
-                result.append(joinType);
-            }
-            result.append(tableName);
-            if (joinCondition != null)
-            {
-                result.append(SqlEnum.ON);
-                result.append(joinCondition);
-            }
-            return result.toString();
-        }
-
-
-        @Override
-        public int hashCode()
-        {
-            return new HashCodeBuilder()
-                    .append(joinCondition)
-                    .append(joinType)
-                    .append(tableName)
-                    .toHashCode();
-        }
-
-
-        @Override
-        public boolean equals(Object obj)
-        {
-            if (this == obj)
-            {
-                return true;
-            }
-            if (obj == null)
-            {
-                return false;
-            }
-            if (getClass() != obj.getClass())
-            {
-                return false;
-            }
-            FromElement other = (FromElement) obj;
-            return new EqualsBuilder()
-                .append(joinCondition, other.joinCondition)
-                .append(joinType, other.joinType)
-                .append(tableName, other.tableName)
-                .isEquals();
-        }
-
-
-    } // end of inner class FromElement
 }

Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/SqlBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/SqlBuilder.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/SqlBuilder.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/SqlBuilder.java Tue Apr 24 11:52:50 2012
@@ -35,12 +35,21 @@ import org.apache.torque.adapter.DB;
 import org.apache.torque.criteria.Criteria;
 import org.apache.torque.criteria.CriteriaInterface;
 import org.apache.torque.criteria.Criterion;
+import org.apache.torque.criteria.FromElement;
 import org.apache.torque.criteria.SqlEnum;
 import org.apache.torque.map.ColumnMap;
 import org.apache.torque.map.DatabaseMap;
 import org.apache.torque.map.MapHelper;
 import org.apache.torque.map.TableMap;
 import org.apache.torque.om.ObjectKey;
+import org.apache.torque.sql.whereclausebuilder.CurrentDateTimePsPartBuilder;
+import org.apache.torque.sql.whereclausebuilder.CustomBuilder;
+import org.apache.torque.sql.whereclausebuilder.InBuilder;
+import org.apache.torque.sql.whereclausebuilder.LikeBuilder;
+import org.apache.torque.sql.whereclausebuilder.NullValueBuilder;
+import org.apache.torque.sql.whereclausebuilder.StandardBuilder;
+import org.apache.torque.sql.whereclausebuilder.VerbatimSqlConditionBuilder;
+import org.apache.torque.sql.whereclausebuilder.WhereClausePsPartBuilder;
 import org.apache.torque.util.UniqueColumnList;
 import org.apache.torque.util.UniqueList;
 
@@ -67,6 +76,23 @@ public final class SqlBuilder
     private static final char BACKSLASH = '\\';
 
     /**
+     * The list of WhereClausePsPartBuilders which can build the where clause.
+     */
+    private static List<WhereClausePsPartBuilder> whereClausePsPartBuilders
+        = new ArrayList<WhereClausePsPartBuilder>();
+
+    static
+    {
+        whereClausePsPartBuilders.add(new VerbatimSqlConditionBuilder());
+        whereClausePsPartBuilders.add(new CustomBuilder());
+        whereClausePsPartBuilders.add(new CurrentDateTimePsPartBuilder());
+        whereClausePsPartBuilders.add(new NullValueBuilder());
+        whereClausePsPartBuilders.add(new LikeBuilder());
+        whereClausePsPartBuilders.add(new InBuilder());
+        whereClausePsPartBuilders.add(new StandardBuilder());
+    }
+
+    /**
      * Private constructor to prevent instantiation.
      *
      * Class contains only static method and should therefore not be
@@ -77,6 +103,18 @@ public final class SqlBuilder
     }
 
     /**
+     * Returns the Builders which are responsible to render single where clause
+     * conditions. The returned list can be modified in order to change
+     * the rendered SQL.
+     *
+     * @return the current WhereClausePsPartBuilders, not null.
+     */
+    public static List<WhereClausePsPartBuilder> getWhereClausePsPartBuilders()
+    {
+        return whereClausePsPartBuilders;
+    }
+
+    /**
      * Builds a Query from a criteria.
      *
      * @param crit the criteria to build the query from, not null.
@@ -136,6 +174,7 @@ public final class SqlBuilder
         processHaving(crit, sqlStatement);
         processOrderBy(db, database, crit, sqlStatement);
         processLimits(crit, sqlStatement);
+        processFromElements(crit, sqlStatement);
         sqlStatement.setFetchSize(crit.getFetchSize());
 
         return sqlStatement;
@@ -296,56 +335,50 @@ public final class SqlBuilder
             where.append(')');
             return;
         }
-        Column column = criterion.getColumn();
-
         // add the table to the from clause, if it is not already
         // contained there
         // it is important that this piece of code is executed AFTER
         // the joins are processed
         addTableToFromClause(
-            column,
-            database,
-            criteria,
-            query);
+                criterion.getLValue(),
+                database,
+                criteria,
+                query);
+        addTableToFromClause(
+                criterion.getRValue(),
+                database,
+                criteria,
+                query);
 
         boolean ignoreCase
-                = criteria.isIgnoreCase() || criterion.isIgnoreCase();
+                = isIgnoreCase(criterion, criteria, database);
+
+        WhereClauseExpression whereClausePartInput
+                = new WhereClauseExpression(
+                        criterion.getLValue(),
+                        criterion.getComparison(),
+                        criterion.getRValue(),
+                        criterion.getSql(),
+                        criterion.getPreparedStatementReplacements());
+        PreparedStatementPart whereClausePartOutput = null;
+        for (WhereClausePsPartBuilder builder : whereClausePsPartBuilders)
         {
-            Column databaseColumn = resolveAliasAndAsColumnAndSchema(
-                    column,
-                    criteria,
-                    database);
-            ColumnMap columnMap = null;
-            {
-                DatabaseMap databaseMap = database.getDatabaseMap();
-                TableMap tableMap = databaseMap.getTable(
-                        databaseColumn.getTableName());
-                if (tableMap != null)
-                {
-                    columnMap = tableMap.getColumn(
-                            databaseColumn.getColumnName());
-                }
-            }
-            if (columnMap != null)
+            if (builder.isApplicable(whereClausePartInput, db))
             {
-                // do not use ignoreCase on columns
-                // which do not contain String values
-                ignoreCase = ignoreCase
-                    && columnMap.getType() instanceof String;
+                whereClausePartOutput
+                        = builder.buildPs(whereClausePartInput, ignoreCase, db);
+                break;
             }
         }
 
-        String columnName = criterion.getColumn().getSqlExpression();
-        WhereClauseExpression whereClausePartInput
-                = new WhereClauseExpression(
-                        columnName,
-                        criterion.getComparison(),
-                        criterion.getValue());
-        PreparedStatementPart whereClausePartOutput
-            = buildPs(
-                whereClausePartInput,
-                ignoreCase,
-                db);
+        if (whereClausePartOutput == null)
+        {
+            // should not happen as last element in list is standardHandler
+            // which takes all
+            throw new RuntimeException("No handler found for whereClausePart "
+                    + whereClausePartInput);
+        }
+
         where.append(whereClausePartOutput.getSql());
         query.getPreparedStatementReplacements().addAll(
                 whereClausePartOutput.getPreparedStatementReplacements());
@@ -448,7 +481,9 @@ public final class SqlBuilder
                 = new WhereClauseExpression(
                         columnName,
                         criterion.getComparison(),
-                        criterion.getValue());
+                        criterion.getValue(),
+                        null,
+                        null);
         PreparedStatementPart whereClausePartOutput
             = buildPs(
                 whereClausePartInput,
@@ -636,6 +671,27 @@ public final class SqlBuilder
     }
 
     /**
+     * Checks the fromElements in the criteria and replaces the automatically
+     * calculated fromElements in the query b them, if they are filled.
+     *
+     * @param criteria the criteria from which the query should be built.
+     * @param query the query to build.
+     */
+    private static void processFromElements(
+            final Criteria criteria,
+            final Query query)
+    {
+        if (criteria.getFromElements().isEmpty())
+        {
+            log.trace("criteria's from Elements is empty,"
+                    + " using automatically calculated from clause");
+            return;
+        }
+        query.getFromClause().clear();
+        query.getFromClause().addAll(criteria.getFromElements());
+    }
+
+    /**
      * Returns the tablename which can be added to a From Clause.
      * This takes care of any aliases that might be defined.
      * For example, if an alias "a" for the table AUTHOR is defined
@@ -773,8 +829,14 @@ public final class SqlBuilder
         {
             criterion = criterion.getParts().iterator().next();
         }
-        Column column = criterion.getColumn();
-        String tableName = column.getFullTableName();
+        String tableName = null;
+
+        Object lValue = criterion.getLValue();
+        if (lValue instanceof Column)
+        {
+            Column column = (Column) lValue;
+            tableName = column.getFullTableName();
+        }
         if (tableName == null)
         {
             throw new TorqueException("Could not determine table name "
@@ -895,14 +957,14 @@ public final class SqlBuilder
      *         If tableName is null, true is returned.
      */
     static boolean fromClauseContainsTableName(
-            final UniqueList<Query.FromElement> fromClause,
+            final UniqueList<FromElement> fromClause,
             final String tableName)
     {
         if (tableName == null)
         {
             return false;
         }
-        for (Query.FromElement fromElement : fromClause)
+        for (FromElement fromElement : fromClause)
         {
             if (tableName.equals(fromElement.getTableName()))
             {
@@ -927,16 +989,21 @@ public final class SqlBuilder
      *         supplied tableOrAliasName
      */
     static String addTableToFromClause(
-                final Column column,
+                final Object possibleColumn,
                 final Database database,
                 final CriteriaInterface criteria,
                 Query query)
             throws TorqueException
     {
-        if (column == null)
+        if (possibleColumn == null)
+        {
+            return null;
+        }
+        if (!(possibleColumn instanceof Column))
         {
             return null;
         }
+        Column column = (Column) possibleColumn;
         if (column.getTableName() == null)
         {
             return null;
@@ -946,7 +1013,7 @@ public final class SqlBuilder
                 database,
                 criteria);
 
-        UniqueList<Query.FromElement> queryFromClause = query.getFromClause();
+        UniqueList<FromElement> queryFromClause = query.getFromClause();
 
         // it is important that this piece of code is executed AFTER
         // the joins are processed
@@ -954,8 +1021,8 @@ public final class SqlBuilder
             queryFromClause,
             tableNameForFromClause))
         {
-            Query.FromElement fromElement
-                    = new Query.FromElement(
+            FromElement fromElement
+                    = new FromElement(
                             tableNameForFromClause, null, null);
             queryFromClause.add(fromElement);
         }
@@ -963,6 +1030,98 @@ public final class SqlBuilder
     }
 
     /**
+     * Checks whether ignoreCase is used for this criterion.
+     * This is the case if ignoreCase is either set on the criterion
+     * or the criteria and if ignoreCase is applicable for both values.
+     *
+     * @param criterion the value to check.
+     * @param criteria the criteria where the criterion stems from.
+     * @param database The database to check.
+     *
+     * @return Whether to use ignoreCase for the passed criterion.
+     *
+     * @throws TorqueException in the case of an error.
+     */
+    static boolean isIgnoreCase(
+                Criterion criterion,
+                CriteriaInterface criteria,
+                Database database)
+            throws TorqueException
+    {
+        boolean ignoreCase
+            = criteria.isIgnoreCase() || criterion.isIgnoreCase();
+        ignoreCase = ignoreCase
+                && ignoreCaseApplicable(
+                        criterion.getLValue(),
+                        criteria,
+                        database)
+                && ignoreCaseApplicable(
+                        criterion.getRValue(),
+                        criteria,
+                        database);
+        return ignoreCase;
+    }
+
+    /**
+     * Checks whether ignoreCase is applicable for this column.
+     * This is not the case if the value is a column and the column type is
+     * not varchar, or if the object is no column and not a String;
+     * in all other cases ignoreCase is applicable.
+     *
+     * @param value the value to check.
+     * @param criteria the criteria where the value stems from.
+     * @param database The database to check.
+     *
+     * @return false if ignoreCase is not applicable, true otherwise.
+     *
+     * @throws TorqueException in the case of an error.
+     */
+    private static boolean ignoreCaseApplicable(
+                Object value,
+                CriteriaInterface criteria,
+                Database database)
+            throws TorqueException
+    {
+        if (value == null)
+        {
+            return true;
+        }
+        if (!(value instanceof Column))
+        {
+            if (value instanceof String
+                    || value instanceof Iterable
+                    || value.getClass().isArray())
+            {
+                return true;
+            }
+            return false;
+        }
+        Column column = (Column) value;
+        Column databaseColumn = resolveAliasAndAsColumnAndSchema(
+                column,
+                criteria,
+                database);
+        ColumnMap columnMap = null;
+        {
+            DatabaseMap databaseMap = database.getDatabaseMap();
+            TableMap tableMap = databaseMap.getTable(
+                    databaseColumn.getTableName());
+            if (tableMap != null)
+            {
+                columnMap = tableMap.getColumn(
+                        databaseColumn.getColumnName());
+            }
+        }
+        if (columnMap == null)
+        {
+            return true;
+        }
+        // do not use ignoreCase on columns
+        // which do not contain String values
+        return columnMap.getType() instanceof String;
+    }
+
+    /**
      * Builds an element of the where clause of a prepared statement.
      *
      * @param whereClausePart the part of the where clause to build.
@@ -971,6 +1130,8 @@ public final class SqlBuilder
      *        function defined for the database will be used to ignore
      *        differences in case.
      * @param db The database for which the SQL should be created, not null.
+     *
+     * @deprecated remove when util.Criteria is removed
      */
     private static PreparedStatementPart buildPs(
                 WhereClauseExpression whereClausePart,
@@ -1083,7 +1244,7 @@ public final class SqlBuilder
             && whereClausePart.getRValue() instanceof String)
         {
             result.getSql().append(
-                    db.ignoreCase(whereClausePart.getLValue()))
+                    db.ignoreCase((String) whereClausePart.getLValue()))
                 .append(whereClausePart.getOperator())
                 .append(db.ignoreCase("?"));
         }
@@ -1116,6 +1277,8 @@ public final class SqlBuilder
      * @param db The database for which the SQL should be created, not null.
      *
      * @return the rendered SQL for the WhereClauseExpression
+     *
+     * @deprecated remove when util.Criteria is removed
      */
     static PreparedStatementPart buildPsLike(
                 WhereClauseExpression whereClausePart,
@@ -1202,7 +1365,7 @@ public final class SqlBuilder
                 // or the LIKE was replaced with equals.
                 // need to ignore case manually.
                 whereClausePart.setLValue(
-                        db.ignoreCase(whereClausePart.getLValue()));
+                        db.ignoreCase((String) whereClausePart.getLValue()));
             }
         }
 
@@ -1273,6 +1436,10 @@ public final class SqlBuilder
      *        function defined for the database will be used to ignore
      *        differences in case.
      * @param db The database for which the SQL should be created, not null.
+     *
+     * @return the built part.
+     *
+     * @deprecated remove when util.Criteria is removed
      */
     static PreparedStatementPart buildPsIn(
             WhereClauseExpression whereClausePart,
@@ -1342,7 +1509,8 @@ public final class SqlBuilder
 
         if (ignoreCaseApplied)
         {
-            result.getSql().append(db.ignoreCase(whereClausePart.getLValue()));
+            result.getSql().append(
+                    db.ignoreCase((String) whereClausePart.getLValue()));
         }
         else
         {

Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/WhereClauseExpression.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/WhereClauseExpression.java?rev=1329656&r1=1329655&r2=1329656&view=diff
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/WhereClauseExpression.java (original)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/WhereClauseExpression.java Tue Apr 24 11:52:50 2012
@@ -19,23 +19,23 @@ package org.apache.torque.sql;
  * under the License.
  */
 
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.torque.criteria.SqlEnum;
 
 /**
  * The raw values for a part of the where clause of a SQL statement,
- * typically of the form lValue operator rValue, e.g. author.author_id = 1.
- * The lValue always contains a column name
- * or a function applied to a column name.
+ * either of the form lValue operator rValue, e.g. author.author_id = 1,
+ * or in form of a custom sql query with sql and replacement values.
  *
  * @version $Id: $
  */
 public class WhereClauseExpression
 {
     /**
-     * The value on the left hand side of the operator, not null or empty.
+     * The value on the left hand side of the operator, not null.
      */
-    private String lValue;
+    private Object lValue;
 
     /**
      * The operator.
@@ -47,31 +47,64 @@ public class WhereClauseExpression
      */
     private Object rValue;
 
+    /** A verbatim SQL for this Criterion. */
+    private String sql;
+
+    /**
+     * Replacements for the placeholders in the verbatim SQL.
+     * Is only used if sql is not null.
+     */
+    private Object[] preparedStatementReplacements;
+
     /**
      * Constructor.
      *
      * @param lValue The value on the left hand side of the operator of the
      *        expression. The value represents the name of a database column.
-     * @param operator the operator.
-     * @param rValue
+     * @param operator the operator. Either this parameter or sql must be
+     *        not null.
+     * @param rValue The value on the right hand side of the operator of the
+     *        expression. The value represents the name of a database column.
+     * @param sql a verbatim sql condition. Either this parameter or
+     *        operator must be not null.
+     * @param preparedStatementReplacements Values for the placeholders
+     *        in the verbatim sql condition.
      */
     public WhereClauseExpression(
-            String lValue,
+            Object lValue,
             SqlEnum operator,
-            Object rValue)
+            Object rValue,
+            String sql,
+            Object[] preparedStatementReplacements)
     {
-        setLValue(lValue);
-        setOperator(operator);
-        setRValue(rValue);
+        if (operator != null
+                && (sql != null || preparedStatementReplacements != null))
+        {
+            throw new IllegalArgumentException("Either operator or "
+                    + "some of (sql, preparedStatementReplacements) "
+                    + "can be not null, not both");
+        }
+        if ((lValue == null || operator == null)
+                && (sql == null))
+        {
+            throw new IllegalArgumentException("Eitherthe values"
+                    + "(lValue, comparison) or "
+                    + "sql must be not null");
+        }
+        this.lValue = lValue;
+        this.operator = operator;
+        this.rValue = rValue;
+        this.sql = sql;
+        this.preparedStatementReplacements = preparedStatementReplacements;
     }
 
     /**
      * Returns the value on the left hand side of the operator of the
-     * expression. The value represents the name of a database column.
+     * expression.
      *
-     * @return the lValue, not null.
+     * @return the lValue.
      */
-    public String getLValue()
+    public Object getLValue()
     {
         return lValue;
     }
@@ -86,21 +119,14 @@ public class WhereClauseExpression
      */
     public void setLValue(String lValue)
     {
-        if (StringUtils.isEmpty(lValue))
-        {
-            throw new IllegalArgumentException(
-                    "lValue must not be null or empty");
-        }
-        else
-        {
-            this.lValue = lValue;
-        }
+        this.lValue = lValue;
     }
 
     /**
      * Returns the value on the operator of the expression.
      *
-     * @return the operator, or null for no operator.
+     * @return the operator, or null if this Expression represents a verbatim
+     *         sql expression.
      */
     public SqlEnum getOperator()
     {
@@ -139,15 +165,47 @@ public class WhereClauseExpression
         this.rValue = rValue;
     }
 
+    /**
+     * Returns the verbatim sql for this expression, if any.
+     *
+     * @return the verbatim sql for this expression, or null if not given.
+     */
+    public String getSql()
+    {
+        return sql;
+    }
+
+    /**
+     * Returns the values for the placeholders in the verbatim sql condition.
+     *
+     * @return the placeholder values, or null.
+     */
+    public Object[] getPreparedStatementReplacements()
+    {
+        return preparedStatementReplacements;
+    }
+
+    /**
+     * Returns whether this expression represents a verbatim sql condition.
+     *
+     * @return true if  this Criterion represents a verbatim sql condition,
+     *         false if the sql is computed from lValue, comparison and rValue.
+     */
+    public boolean isVerbatimSqlCondition()
+    {
+        return (sql != null);
+    }
+
     @Override
     public int hashCode()
     {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + lValue.hashCode();
-        result = prime * result + operator.hashCode();
-        result = prime * result + rValue.hashCode();
-        return result;
+        HashCodeBuilder hashCodeBuilder = new HashCodeBuilder()
+            .append(lValue)
+            .append(operator)
+            .append(rValue)
+            .append(sql)
+            .append(preparedStatementReplacements);
+        return hashCodeBuilder.toHashCode();
     }
 
     @Override
@@ -166,25 +224,21 @@ public class WhereClauseExpression
             return false;
         }
         WhereClauseExpression other = (WhereClauseExpression) obj;
-        if (!lValue.equals(other.lValue))
-        {
-            return false;
-        }
-        if (!operator.equals(other.operator))
-        {
-            return false;
-        }
-        if (!rValue.equals(other.rValue))
-        {
-            return false;
-        }
-        return true;
+        EqualsBuilder equalsBuilder = new EqualsBuilder()
+                .append(lValue, other.lValue)
+                .append(operator, other.operator)
+                .append(rValue, other.rValue)
+                .append(sql, other.sql)
+                .append(
+                    preparedStatementReplacements,
+                    other.preparedStatementReplacements);
+        return equalsBuilder.isEquals();
     }
 
     @Override
     public String toString()
     {
-        StringBuilder result = new StringBuilder(lValue);
+        StringBuilder result = new StringBuilder(lValue.toString());
         if (operator != null)
         {
             result.append(operator);

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectOrColumnPsPartBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectOrColumnPsPartBuilder.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectOrColumnPsPartBuilder.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectOrColumnPsPartBuilder.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,122 @@
+package org.apache.torque.sql.objectbuilder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.torque.Column;
+import org.apache.torque.TorqueException;
+import org.apache.torque.adapter.DB;
+import org.apache.torque.criteria.Criteria;
+import org.apache.torque.criteria.SqlEnum;
+import org.apache.torque.om.ObjectKey;
+import org.apache.torque.sql.PreparedStatementPart;
+import org.apache.torque.sql.Query;
+import org.apache.torque.sql.SqlBuilder;
+
+/**
+ * Builds a PreparedStatementPart from a column or single value.
+ *
+ * @version $Id: $
+ */
+public class ObjectOrColumnPsPartBuilder implements ObjectPsPartBuilder
+{
+    /**
+     * Builds a PreparedStatementPart from a column or single value.
+     *
+     * @param toBuildFrom the object to build the psPart from.
+     * @param ignoreCase If true and columns represent Strings, the appropriate
+     *        function defined for the database will be used to ignore
+     *        differences in case.
+     * @param db The database for which the SQL should be created, not null.
+     *
+     * @return the PreparedStatementPart for the object.
+     *
+     * @throws TorqueException when rendering fails.
+     */
+    public PreparedStatementPart buildPs(
+            Object toBuildFrom,
+            boolean ignoreCase,
+            DB db)
+        throws TorqueException
+    {
+        PreparedStatementPart result = new PreparedStatementPart();
+        if (toBuildFrom instanceof Column)
+        {
+            Column column = (Column) toBuildFrom;
+            if (ignoreCase)
+            {
+                result.getSql().append(
+                        db.ignoreCase(column.getSqlExpression()));
+            }
+            else
+            {
+                result.getSql().append(column.getSqlExpression());
+            }
+            return result;
+        }
+
+        // plain object
+
+        if (toBuildFrom instanceof Criteria)
+        {
+            Query subquery = SqlBuilder.buildQuery(
+                    (Criteria) toBuildFrom);
+            result.getPreparedStatementReplacements().addAll(
+                    subquery.getPreparedStatementReplacements());
+            result.getSql().append("(").append(subquery.toString()).append(")");
+            return result;
+        }
+
+        if (toBuildFrom instanceof org.apache.torque.util.Criteria)
+        {
+            Query subquery = SqlBuilder.buildQuery(
+                    (org.apache.torque.util.Criteria) toBuildFrom);
+            result.getPreparedStatementReplacements().addAll(
+                    subquery.getPreparedStatementReplacements());
+            result.getSql().append("(").append(subquery.toString()).append(")");
+            return result;
+        }
+
+        if (toBuildFrom.equals(
+                SqlEnum.CURRENT_DATE)
+                || toBuildFrom.equals(
+                        SqlEnum.CURRENT_TIME))
+        {
+            result.getSql().append(toBuildFrom.toString());
+            return result;
+        }
+        // If rValue is an ObjectKey, take the value of that ObjectKey.
+        if (toBuildFrom instanceof ObjectKey)
+        {
+            toBuildFrom = ((ObjectKey) toBuildFrom).getValue();
+        }
+
+        // handle ignoreCase
+        if (ignoreCase && toBuildFrom instanceof String)
+        {
+            result.getSql().append(db.ignoreCase("?"));
+        }
+        else
+        {
+            result.getSql().append("?");
+        }
+        result.getPreparedStatementReplacements().add(toBuildFrom);
+        return result;
+    }
+}

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectPsPartBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectPsPartBuilder.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectPsPartBuilder.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/ObjectPsPartBuilder.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,52 @@
+package org.apache.torque.sql.objectbuilder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.torque.TorqueException;
+import org.apache.torque.adapter.DB;
+import org.apache.torque.sql.PreparedStatementPart;
+
+/**
+ * Builds a PreparedStatementPart from a single object
+ * (e.g. a column or a SQL value).
+ *
+ * @version $Id: $
+ */
+public interface ObjectPsPartBuilder
+{
+    /**
+     * Builds a PreparedStatementPart from a single Object.
+     *
+     * @param toBuildFrom the object to build the psPart from.
+     * @param ignoreCase If true and columns represent Strings, the appropriate
+     *        function defined for the database will be used to ignore
+     *        differences in case.
+     * @param db The database for which the SQL should be created, not null.
+     *
+     * @return the PreparedStatementPart for the object.
+     *
+     * @throws TorqueException when rendering fails.
+     */
+    PreparedStatementPart buildPs(
+            Object toBuildFrom,
+            boolean ignoreCase,
+            DB db)
+        throws TorqueException;
+}

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/package.html
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/package.html?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/package.html (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/objectbuilder/package.html Tue Apr 24 11:52:50 2012
@@ -0,0 +1,26 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<html>
+  <head>
+  </head>
+  <body>
+    This package contains classes which can build
+    PreparedStatementParts from a single value or column.
+  </body>
+</html>

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/AbstractWhereClausePsPartBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/AbstractWhereClausePsPartBuilder.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/AbstractWhereClausePsPartBuilder.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/AbstractWhereClausePsPartBuilder.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,46 @@
+package org.apache.torque.sql.whereclausebuilder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.torque.sql.objectbuilder.ObjectOrColumnPsPartBuilder;
+import org.apache.torque.sql.objectbuilder.ObjectPsPartBuilder;
+
+/**
+ * Abstract base class for a WhereClausePsPartBuilder.
+ *
+ * @version $Id: $
+ */
+public abstract class AbstractWhereClausePsPartBuilder
+        implements WhereClausePsPartBuilder
+{
+    /** The ObjectPsPartBuilder to use for single values or columns. */
+    protected static ObjectPsPartBuilder objectOrColumnPsPartBuilder
+            = new ObjectOrColumnPsPartBuilder();
+
+    /**
+     * Set the ObjectPsPartBuilder to use for single values or columns.
+     *
+     * @param builder the new ObjectPsPartBuilder to use.
+     */
+    void setObjectOrColumnPsPartBuilder(ObjectPsPartBuilder builder)
+    {
+        AbstractWhereClausePsPartBuilder.objectOrColumnPsPartBuilder = builder;
+    }
+}

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CurrentDateTimePsPartBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CurrentDateTimePsPartBuilder.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CurrentDateTimePsPartBuilder.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CurrentDateTimePsPartBuilder.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,75 @@
+package org.apache.torque.sql.whereclausebuilder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.torque.TorqueException;
+import org.apache.torque.adapter.DB;
+import org.apache.torque.criteria.SqlEnum;
+import org.apache.torque.sql.PreparedStatementPart;
+import org.apache.torque.sql.WhereClauseExpression;
+
+/**
+ * A WhereClausePsPartBuilder which handles <code>SqlEnum.CURRENT_DATE</code>
+ * and <code>SqlEnum.CURRENT_TIME</code>.
+ *
+ * @version $Id: $
+ */
+public class CurrentDateTimePsPartBuilder
+        extends AbstractWhereClausePsPartBuilder
+{
+    /**
+     * {@inheritDoc}
+     */
+    public PreparedStatementPart buildPs(
+            WhereClauseExpression whereClauseExpression,
+            boolean ignoreCase,
+            DB db)
+        throws TorqueException
+    {
+        PreparedStatementPart result
+            = objectOrColumnPsPartBuilder.buildPs(
+                    whereClauseExpression.getLValue(),
+                    ignoreCase,
+                    db);
+        result.getSql().append(whereClauseExpression.getOperator());
+        result .append(objectOrColumnPsPartBuilder.buildPs(
+                whereClauseExpression.getRValue(),
+                ignoreCase,
+                db));
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isApplicable(
+            WhereClauseExpression whereClauseExpression,
+            DB db)
+    {
+        if (whereClauseExpression.getOperator().equals(
+                        SqlEnum.CURRENT_DATE)
+                || whereClauseExpression.getOperator().equals(
+                        SqlEnum.CURRENT_TIME))
+            {
+                return true;
+            }
+            return false;
+    }
+}

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CustomBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CustomBuilder.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CustomBuilder.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/CustomBuilder.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,87 @@
+package org.apache.torque.sql.whereclausebuilder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.torque.TorqueException;
+import org.apache.torque.adapter.DB;
+import org.apache.torque.criteria.SqlEnum;
+import org.apache.torque.sql.PreparedStatementPart;
+import org.apache.torque.sql.WhereClauseExpression;
+
+/**
+ * Builds a PreparedStatementPart from a WhereClauseExpression containing
+ * a <code>SqlEnum.CUSTOM</code> operator.
+ *
+ * @version $Id: $
+ */
+public class CustomBuilder implements WhereClausePsPartBuilder
+{
+    /**
+     * Builds the PS part for a WhereClauseExpression with a
+     * <code>SqlEnum.CUSTOM</code> operator.
+     * The rendered SQL contains only the RHS of the whereClauseExpression
+     * as String.
+     *
+     * @param whereClausePart the part of the where clause to build.
+     *        Can be modified in this method.
+     * @param ignoreCase If true and columns represent Strings, the appropriate
+     *        function defined for the database will be used to ignore
+     *        differences in case.
+     * @param db The database for which the SQL should be created, not null.
+     *
+     * @return the rendered SQL for the WhereClauseExpression
+     */
+    public PreparedStatementPart buildPs(
+                WhereClauseExpression whereClausePart,
+                boolean ignoreCase,
+                DB db)
+            throws TorqueException
+    {
+        if (!(whereClausePart.getRValue() instanceof String))
+        {
+            throw new TorqueException(
+                "rValue must be a String for the operator "
+                    + whereClausePart.getOperator());
+        }
+        PreparedStatementPart result = new PreparedStatementPart();
+        result.getSql().append(whereClausePart.getRValue());
+        return result;
+    }
+
+    /**
+     * Returns whether this WhereClausePsPartBuilder is applicable for
+     * a given WhereClauseExpression.
+     *
+     * @param whereClauseExpression the WhereClauseExpression in question.
+     * @param db The database for which the SQL should be created, not null.
+     *
+     * @return true if applicable, false otherwise.
+     */
+    public boolean isApplicable(
+            WhereClauseExpression whereClauseExpression,
+            DB db)
+    {
+        if (whereClauseExpression.getOperator().equals(SqlEnum.CUSTOM))
+        {
+            return true;
+        }
+        return false;
+    }
+}

Added: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/InBuilder.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/InBuilder.java?rev=1329656&view=auto
==============================================================================
--- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/InBuilder.java (added)
+++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/sql/whereclausebuilder/InBuilder.java Tue Apr 24 11:52:50 2012
@@ -0,0 +1,172 @@
+package org.apache.torque.sql.whereclausebuilder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.torque.TorqueException;
+import org.apache.torque.adapter.DB;
+import org.apache.torque.criteria.Criteria;
+import org.apache.torque.criteria.Criterion;
+import org.apache.torque.criteria.SqlEnum;
+import org.apache.torque.sql.PreparedStatementPart;
+import org.apache.torque.sql.WhereClauseExpression;
+
+/**
+ * Builds a PreparedStatementPart from a WhereClauseExpression containing
+ * a Like operator.
+ *
+ * @version $Id: $
+ */
+public class InBuilder extends AbstractWhereClausePsPartBuilder
+{
+    /**
+     * Takes a columnName and criteria and
+     * builds a SQL 'IN' expression taking into account the ignoreCase
+     * flag.
+     *
+     * @param whereClausePart the part of the where clause to build.
+     *        Can be modified in this method.
+     * @param ignoreCase If true and columns represent Strings, the appropriate
+     *        function defined for the database will be used to ignore
+     *        differences in case.
+     * @param db The database for which the SQL should be created, not null.
+     */
+    public PreparedStatementPart buildPs(
+                WhereClauseExpression whereClausePart,
+                boolean ignoreCase,
+                DB db)
+            throws TorqueException
+    {
+        PreparedStatementPart result = new PreparedStatementPart();
+
+        boolean ignoreCaseApplied = false;
+        List<String> inClause = new ArrayList<String>();
+        boolean nullContained = false;
+        if (whereClausePart.getRValue() instanceof Iterable)
+        {
+            for (Object listValue : (Iterable<?>) whereClausePart.getRValue())
+            {
+                if (listValue == null)
+                {
+                    nullContained = true;
+                    continue;
+                }
+                result.getPreparedStatementReplacements().add(listValue);
+                if (ignoreCase && listValue instanceof String)
+                {
+                    inClause.add(db.ignoreCase("?"));
+                    ignoreCaseApplied = true;
+                }
+                else
+                {
+                    inClause.add("?");
+                }
+            }
+        }
+        else if (whereClausePart.getRValue().getClass().isArray())
+        {
+            for (Object arrayValue : (Object[]) whereClausePart.getRValue())
+            {
+                if (arrayValue == null)
+                {
+                    nullContained = true;
+                    continue;
+                }
+                result.getPreparedStatementReplacements().add(arrayValue);
+                if (ignoreCase && arrayValue instanceof String)
+                {
+                    inClause.add(db.ignoreCase("?"));
+                    ignoreCaseApplied = true;
+                }
+                else
+                {
+                    inClause.add("?");
+                }
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException(
+                    "Unknown rValue type "
+                    + whereClausePart.getRValue().getClass().getName()
+                    + ". rValue must be an instance of "
+                    + " Iterable or Array");
+        }
+
+        if (nullContained)
+        {
+            result.getSql().append('(');
+        }
+
+        result.append(objectOrColumnPsPartBuilder.buildPs(
+                whereClausePart.getLValue(),
+                ignoreCaseApplied,
+                db));
+
+        result.getSql().append(whereClausePart.getOperator())
+                .append('(')
+                .append(StringUtils.join(inClause.iterator(), ","))
+                .append(')');
+        if (nullContained)
+        {
+            if (whereClausePart.getOperator() == SqlEnum.IN)
+            {
+                result.getSql().append(Criterion.OR);
+                result.append(objectOrColumnPsPartBuilder.buildPs(
+                        whereClausePart.getLValue(),
+                        false,
+                        db));
+                result.getSql().append(SqlEnum.ISNULL);
+            }
+            else if (whereClausePart.getOperator() == SqlEnum.NOT_IN)
+            {
+                result.getSql().append(Criterion.AND);
+                result.append(objectOrColumnPsPartBuilder.buildPs(
+                        whereClausePart.getLValue(),
+                        false,
+                        db));
+                result.getSql().append(SqlEnum.ISNOTNULL);
+            }
+            result.getSql().append(')');
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isApplicable(
+            WhereClauseExpression whereClauseExpression,
+            DB db)
+    {
+        if (whereClauseExpression.getOperator().equals(Criteria.IN)
+                || whereClauseExpression.getOperator().equals(Criteria.NOT_IN))
+        {
+            if (!(whereClauseExpression.getRValue() instanceof Criteria))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org


Mime
View raw message