You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by aw...@apache.org on 2006/09/07 19:51:09 UTC

svn commit: r441158 [3/5] - in /incubator/openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-kernel/s...

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java Thu Sep  7 10:51:05 2006
@@ -15,8 +15,6 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.Filters;
@@ -33,8 +31,6 @@
 
     private Object _val;
     private int _ptype;
-    private Object _sqlVal = null;
-    private int _otherLen = 0;
 
     /**
      * Constructor. Supply literal value.
@@ -56,7 +52,7 @@
         return _ptype;
     }
 
-    public Object getValue() {
+    public Object getValue() { 
         return _val;
     }
 
@@ -64,24 +60,42 @@
         _val = val;
     }
 
-    public void calculateValue(Select sel, JDBCStore store,
-        Object[] params, Val other, JDBCFetchConfiguration fetch) {
-        super.calculateValue(sel, store, params, other, fetch);
+    public Object getValue(Object[] params) {
+        return getValue();
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        return new LitExpState();
+    }
+
+    /**
+     * Expression state.
+     */
+    private static class LitExpState
+        extends ConstExpState {
+
+        public Object sqlValue;
+        public int otherLength; 
+    } 
+
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
+        super.calculateValue(sel, ctx, state, other, otherState);
+        LitExpState lstate = (LitExpState) state;
         if (other != null) {
-            _sqlVal = other.toDataStoreValue(_val, store);
-            _otherLen = other.length();
+            lstate.sqlValue = other.toDataStoreValue(sel, ctx, otherState,_val);
+            lstate.otherLength = other.length(sel, ctx, otherState);
         } else
-            _sqlVal = _val;
+            lstate.sqlValue = _val;
     }
 
-    public void appendTo(SQLBuffer sql, int index, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        if (_otherLen > 1)
-            sql.appendValue(((Object[]) _sqlVal)[index], getColumn(index));
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        LitExpState lstate = (LitExpState) state;
+        if (lstate.otherLength > 1)
+            sql.appendValue(((Object[]) lstate.sqlValue)[index], 
+                lstate.getColumn(index));
         else
-            sql.appendValue(_sqlVal, getColumn(index));
-    }
-
-    public void clearParameters() {
+            sql.appendValue(lstate.sqlValue, lstate.getColumn(index));
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MatchesExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MatchesExpression.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MatchesExpression.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MatchesExpression.java Thu Sep  7 10:51:05 2006
@@ -17,10 +17,7 @@
 
 import java.util.Map;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.schema.Column;
-import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.exps.ExpressionVisitor;
@@ -39,7 +36,6 @@
     private final String _single;
     private final String _multi;
     private final String _escape;
-    private Joins _joins = null;
 
     /**
      * Constructor. Supply values.
@@ -53,26 +49,26 @@
         _escape = escape;
     }
 
-    public void initialize(Select sel, JDBCStore store,
-        Object[] params, Map contains) {
-        _val.initialize(sel, store, false);
-        _const.initialize(sel, store, false);
-        _joins = sel.and(_val.getJoins(), _const.getJoins());
+    public ExpState initialize(Select sel, ExpContext ctx, Map contains) {
+        ExpState s1 = _val.initialize(sel, ctx, 0);
+        ExpState s2 = _const.initialize(sel, ctx, 0);
+        return new BinaryOpExpState(sel.and(s1.joins, s2.joins), s1, s2);
     }
 
-    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch) {
-        _val.calculateValue(sel, store, params, _const, fetch);
-        _const.calculateValue(sel, store, params, _val, fetch);
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _val.calculateValue(sel, ctx, bstate.state1, _const, bstate.state2);
+        _const.calculateValue(sel, ctx, bstate.state2, _val, bstate.state1);
 
         Column col = null;
         if (_val instanceof PCPath) {
-            Column[] cols = ((PCPath) _val).getColumns();
+            Column[] cols = ((PCPath) _val).getColumns(bstate.state1);
             if (cols.length == 1)
                 col = cols[0];
         }
 
-        Object o = _const.getValue();
+        Object o = _const.getValue(ctx, bstate.state2);
         if (o == null)
             buf.append("1 <> 1");
         else {
@@ -92,7 +88,7 @@
             // append target
             if (ignoreCase)
                 buf.append("LOWER(");
-            _val.appendTo(buf, 0, sel, store, params, fetch);
+            _val.appendTo(sel, ctx, bstate.state1, buf, 0);
             if (ignoreCase)
                 buf.append(")");
 
@@ -101,27 +97,20 @@
             // with '%' and '.' with '_'
             str = Strings.replace(str, _multi, "%");
             str = Strings.replace(str, _single, "_");
-
             buf.append(" LIKE ").appendValue(str, col);
 
             // escape out characters by using the database's escape sequence
             if (_escape != null)
                 buf.append(" ESCAPE '").append(_escape).append("'");
         }
-        sel.append(buf, _joins);
-
-        _val.clearParameters();
-        _const.clearParameters();
-    }
-
-    public void selectColumns(Select sel, JDBCStore store,
-        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
-        _val.selectColumns(sel, store, params, true, fetch);
-        _const.selectColumns(sel, store, params, true, fetch);
+        sel.append(buf, state.joins);
     }
 
-    public Joins getJoins() {
-        return _joins;
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _val.selectColumns(sel, ctx, bstate.state1, true);
+        _const.selectColumns(sel, ctx, bstate.state2, true);
     }
 
     public void acceptVisit(ExpressionVisitor visitor) {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java Thu Sep  7 10:51:05 2006
@@ -17,10 +17,7 @@
 
 import java.sql.SQLException;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
-import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.Result;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
@@ -45,7 +42,6 @@
     private final Val _val1;
     private final Val _val2;
     private final String _op;
-    private Joins _joins = null;
     private ClassMetaData _meta = null;
     private Class _cast = null;
 
@@ -66,10 +62,6 @@
         _meta = meta;
     }
 
-    public boolean isVariable() {
-        return false;
-    }
-
     public Class getType() {
         if (_cast != null)
             return _cast;
@@ -82,78 +74,63 @@
         _cast = type;
     }
 
-    public void initialize(Select sel, JDBCStore store,
-        boolean nullTest) {
-        _val1.initialize(sel, store, false);
-        _val2.initialize(sel, store, false);
-        _joins = sel.and(_val1.getJoins(), _val2.getJoins());
-    }
-
-    public Joins getJoins() {
-        return _joins;
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        ExpState s1 = _val1.initialize(sel, ctx, 0);
+        ExpState s2 = _val2.initialize(sel, ctx, 0);
+        return new BinaryOpExpState(sel.and(s1.joins, s2.joins), s1, s2);
     }
 
-    public Object toDataStoreValue(Object val, JDBCStore store) {
-        return val;
+    public void select(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        sel.select(newSQLBuffer(sel, ctx, state), this);
     }
 
-    public void select(Select sel, JDBCStore store, Object[] params,
-        boolean pks, JDBCFetchConfiguration fetch) {
-        sel.select(newSQLBuffer(sel, store, params, fetch), this);
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _val1.selectColumns(sel, ctx, bstate.state1, true);
+        _val2.selectColumns(sel, ctx, bstate.state2, true);
     }
 
-    public void selectColumns(Select sel, JDBCStore store,
-        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
-        _val1.selectColumns(sel, store, params, true, fetch);
-        _val2.selectColumns(sel, store, params, true, fetch);
+    public void groupBy(Select sel, ExpContext ctx, ExpState state) {
+        sel.groupBy(newSQLBuffer(sel, ctx, state));
     }
 
-    public void groupBy(Select sel, JDBCStore store, Object[] params,
-        JDBCFetchConfiguration fetch) {
-        sel.groupBy(newSQLBuffer(sel, store, params, fetch));
+    public void orderBy(Select sel, ExpContext ctx, ExpState state, 
+        boolean asc) {
+        sel.orderBy(newSQLBuffer(sel, ctx, state), asc, false);
     }
 
-    public void orderBy(Select sel, JDBCStore store, Object[] params,
-        boolean asc, JDBCFetchConfiguration fetch) {
-        sel.orderBy(newSQLBuffer(sel, store, params, fetch), asc, false);
-    }
-
-    private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch) {
-        calculateValue(sel, store, params, null, fetch);
-        SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
-        appendTo(buf, 0, sel, store, params, fetch);
-        clearParameters();
+    private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx, ExpState state) {
+        calculateValue(sel, ctx, state, null, null);
+        SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
+        appendTo(sel, ctx, state, buf, 0);
         return buf;
     }
 
-    public Object load(Result res, JDBCStore store,
-        JDBCFetchConfiguration fetch)
+    public Object load(ExpContext ctx, ExpState state, Result res)
         throws SQLException {
-        return Filters.convert(res.getObject(this,
-            JavaSQLTypes.JDBC_DEFAULT, null), getType());
-    }
-
-    public void calculateValue(Select sel, JDBCStore store,
-        Object[] params, Val other, JDBCFetchConfiguration fetch) {
-        _val1.calculateValue(sel, store, params, _val2, fetch);
-        _val2.calculateValue(sel, store, params, _val1, fetch);
+        return Filters.convert(res.getObject(this, JavaSQLTypes.JDBC_DEFAULT, 
+            null), getType());
     }
 
-    public void clearParameters() {
-        _val1.clearParameters();
-        _val2.clearParameters();
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _val1.calculateValue(sel, ctx, bstate.state1, _val2, bstate.state2);
+        _val2.calculateValue(sel, ctx, bstate.state2, _val1, bstate.state1);
     }
 
-    public int length() {
+    public int length(Select sel, ExpContext ctx, ExpState state) {
         return 1;
     }
 
-    public void appendTo(SQLBuffer sql, int index, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        store.getDBDictionary().mathFunction(sql, _op,
-            new FilterValueImpl(_val1, sel, store, params, fetch),
-            new FilterValueImpl(_val2, sel, store, params, fetch));
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        ctx.store.getDBDictionary().mathFunction(sql, _op,
+            new FilterValueImpl(sel, ctx, bstate.state1, _val1),
+            new FilterValueImpl(sel, ctx, bstate.state2, _val2));
     }
 
     public void acceptVisit(ExpressionVisitor visitor) {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java Thu Sep  7 10:51:05 2006
@@ -17,10 +17,7 @@
 
 import java.util.Map;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
-import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.exps.ExpressionVisitor;
@@ -35,7 +32,6 @@
     implements Exp {
 
     private final Exp _exp;
-    private Map _contains = null;
 
     /**
      * Constructor. Supply the expression to negate.
@@ -44,37 +40,48 @@
         _exp = exp;
     }
 
-    public void initialize(Select sel, JDBCStore store,
-        Object[] params, Map contains) {
-        _contains = contains;
+    public ExpState initialize(Select sel, ExpContext ctx, Map contains) {
+        return new NotContainsExpState(contains);
     }
 
-    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch) {
-        DBDictionary dict = store.getDBDictionary();
+    /**
+     * Expression state.
+     */
+    private static class NotContainsExpState
+        extends ExpState {
+        
+        public final Map contains;
+
+        public NotContainsExpState(Map contains) {
+            this.contains = contains;
+        }
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf) {
+        DBDictionary dict = ctx.store.getDBDictionary();
         dict.assertSupport(dict.supportsSubselect, "SupportsSubselect");
 
-        Select sub = store.getSQLFactory().newSelect();
+        Select sub = ctx.store.getSQLFactory().newSelect();
         sub.setParent(sel, null);
-        _exp.initialize(sub, store, params, _contains);
-        sub.where(sub.and(null, _exp.getJoins()));
+        ExpState estate = _exp.initialize(sub, ctx, ((NotContainsExpState) 
+            state).contains);
+        sub.where(sub.and(null, estate.joins));
 
         SQLBuffer where = new SQLBuffer(dict).append("(");
-        _exp.appendTo(where, sub, store, params, fetch);
+        _exp.appendTo(sub, ctx, estate, where);
         if (where.getSQL().length() > 1)
             sub.where(where.append(")"));
 
         buf.append("0 = ");
-        buf.appendCount(sub, fetch);
-    }
-
-    public void selectColumns(Select sel, JDBCStore store,
-        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
-        _exp.selectColumns(sel, store, params, true, fetch);
+        buf.appendCount(sub, ctx.fetch);
     }
 
-    public Joins getJoins() {
-        return null;
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        ExpState estate = _exp.initialize(sel, ctx, ((NotContainsExpState) 
+            state).contains);
+        _exp.selectColumns(sel, ctx, estate, true);
     }
 
     public void acceptVisit(ExpressionVisitor visitor) {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualExpression.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualExpression.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualExpression.java Thu Sep  7 10:51:05 2006
@@ -15,8 +15,6 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 
@@ -35,39 +33,41 @@
         super(val1, val2);
     }
 
-    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch, boolean val1Null,
-        boolean val2Null) {
+    public void appendTo(Select sel, ExpContext ctx, BinaryOpExpState bstate, 
+        SQLBuffer buf, boolean val1Null, boolean val2Null) {
         if (val1Null && val2Null)
             buf.appendValue(null).append(" IS NOT ").appendValue(null);
         else if (val1Null || val2Null) {
             Val val = (val1Null) ? getValue2() : getValue1();
+            ExpState state = (val1Null) ? bstate.state2 : bstate.state1;
             if (!isDirectComparison()) {
-                int len = val.length();
+                int len = val.length(sel, ctx, state);
                 for (int i = 0; i < len; i++) {
                     if (i > 0)
                         buf.append(" AND ");
-                    val.appendTo(buf, i, sel, store, params, fetch);
+                    val.appendTo(sel, ctx, state, buf, i);
                     buf.append(" IS NOT ").appendValue(null);
                 }
             } else
-                val.appendIsNotNull(buf, sel, store, params, fetch);
+                val.appendIsNotNull(sel, ctx, state, buf);
         } else {
             Val val1 = getValue1();
             Val val2 = getValue2();
-            if (val1.length() == 1 && val2.length() == 1) {
-                store.getDBDictionary().comparison(buf, "<>",
-                    new FilterValueImpl(val1, sel, store, params, fetch),
-                    new FilterValueImpl(val2, sel, store, params, fetch));
+            if (val1.length(sel, ctx, bstate.state1) == 1 
+                && val2.length(sel, ctx, bstate.state2) == 1) {
+                ctx.store.getDBDictionary().comparison(buf, "<>",
+                    new FilterValueImpl(sel, ctx, bstate.state1, val1),
+                    new FilterValueImpl(sel, ctx, bstate.state2, val2));
             } else {
-                int len = java.lang.Math.max(val1.length(), val2.length());
+                int len = java.lang.Math.max(val1.length(sel, ctx, 
+                    bstate.state1), val2.length(sel, ctx, bstate.state2));
                 buf.append("(");
                 for (int i = 0; i < len; i++) {
                     if (i > 0)
                         buf.append(" OR ");
-                    val1.appendTo(buf, i, sel, store, params, fetch);
+                    val1.appendTo(sel, ctx, bstate.state1, buf, i);
                     buf.append(" <> ");
-                    val2.appendTo(buf, i, sel, store, params, fetch);
+                    val2.appendTo(sel, ctx, bstate.state2, buf, i);
                 }
                 buf.append(")");
             }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotExpression.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotExpression.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotExpression.java Thu Sep  7 10:51:05 2006
@@ -17,8 +17,6 @@
 
 import java.util.Map;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
@@ -33,7 +31,6 @@
     implements Exp {
 
     private final Exp _exp;
-    private Joins _joins = null;
 
     /**
      * Constructor. Supply the expression to negate.
@@ -42,26 +39,35 @@
         _exp = exp;
     }
 
-    public void initialize(Select sel, JDBCStore store,
-        Object[] params, Map contains) {
-        _exp.initialize(sel, store, params, contains);
-        _joins = sel.or(_exp.getJoins(), null);
+    public ExpState initialize(Select sel, ExpContext ctx, Map contains) { 
+        ExpState state = _exp.initialize(sel, ctx, contains);
+        return new NotExpState(sel.or(state.joins, null), state);
     }
 
-    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch) {
-        buf.append("NOT (");
-        _exp.appendTo(buf, sel, store, params, fetch);
-        buf.append(")");
+    /**
+     * Expression state.
+     */
+    private static class NotExpState 
+        extends ExpState {
+
+        public final ExpState state;
+
+        public NotExpState(Joins joins, ExpState state) {
+            super(joins);
+            this.state = state;
+        }
     }
 
-    public void selectColumns(Select sel, JDBCStore store,
-        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
-        _exp.selectColumns(sel, store, params, pks, fetch);
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf) {
+        buf.append("NOT (");
+        _exp.appendTo(sel, ctx, ((NotExpState) state).state, buf);
+        buf.append(")");
     }
 
-    public Joins getJoins() {
-        return _joins;
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        _exp.selectColumns(sel, ctx, ((NotExpState) state).state, pks);
     }
 
     public void acceptVisit(ExpressionVisitor visitor) {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Null.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Null.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Null.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Null.java Thu Sep  7 10:51:05 2006
@@ -15,8 +15,6 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 
@@ -35,19 +33,16 @@
     public void setImplicitType(Class type) {
     }
 
-    public Object getValue() {
+    public Object getValue(Object[] params) {
         return null;
     }
 
-    public void calculateValue(Select sel, JDBCStore store,
-        Object[] params, Val other, JDBCFetchConfiguration fetch) {
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
     }
 
-    public void appendTo(SQLBuffer sql, int index, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
         sql.appendValue(null);
-    }
-
-    public void clearParameters() {
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/OrExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/OrExpression.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/OrExpression.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/OrExpression.java Thu Sep  7 10:51:05 2006
@@ -19,9 +19,6 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
-import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.exps.ExpressionVisitor;
@@ -36,7 +33,6 @@
 
     private final Exp _exp1;
     private final Exp _exp2;
-    private Joins _joins = null;
 
     /**
      * Constructor. Supply the expressions to combine.
@@ -46,56 +42,53 @@
         _exp2 = exp2;
     }
 
-    public void initialize(Select sel, JDBCStore store,
-        Object[] params, Map contains) {
+    public ExpState initialize(Select sel, ExpContext ctx, Map contains) {
         // when OR'ing expressions each expression gets its own copy of the
         // contains counts, cause it's OK for each to use the same aliases
         Map contains2 = null;
         if (contains != null)
             contains2 = new HashMap(contains);
 
-        _exp1.initialize(sel, store, params, contains);
-        _exp2.initialize(sel, store, params, contains2);
-        _joins = sel.or(_exp1.getJoins(), _exp2.getJoins());
+        ExpState s1 = _exp1.initialize(sel, ctx, contains);
+        ExpState s2 = _exp2.initialize(sel, ctx, contains2);
+        ExpState ret = new BinaryOpExpState(sel.or(s1.joins, s2.joins), s1, s2);
         if (contains == null)
-            return;
+            return ret;
 
         // combine the contains counts from the copy into the main map
         Map.Entry entry;
         Integer val1, val2;
-        for (Iterator itr = contains2.entrySet().iterator();
-            itr.hasNext();) {
+        for (Iterator itr = contains2.entrySet().iterator(); itr.hasNext();) {
             entry = (Map.Entry) itr.next();
             val2 = (Integer) entry.getValue();
             val1 = (Integer) contains.get(entry.getKey());
             if (val1 == null || val2.intValue() > val1.intValue())
                 contains.put(entry.getKey(), val2);
         }
+        return ret;
     }
 
-    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch) {
-        boolean paren = _joins != null && !_joins.isEmpty();
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        boolean paren = bstate.joins != null && !bstate.joins.isEmpty();
         if (paren)
             buf.append("(");
 
-        _exp1.appendTo(buf, sel, store, params, fetch);
+        _exp1.appendTo(sel, ctx, bstate.state1, buf);
         buf.append(" OR ");
-        _exp2.appendTo(buf, sel, store, params, fetch);
+        _exp2.appendTo(sel, ctx, bstate.state2, buf);
 
         if (paren)
             buf.append(")");
-        sel.append(buf, _joins);
+        sel.append(buf, bstate.joins);
     }
 
-    public void selectColumns(Select sel, JDBCStore store,
-        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
-        _exp1.selectColumns(sel, store, params, pks, fetch);
-        _exp2.selectColumns(sel, store, params, pks, fetch);
-    }
-
-    public Joins getJoins() {
-        return _joins;
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _exp1.selectColumns(sel, ctx, bstate.state1, pks);
+        _exp2.selectColumns(sel, ctx, bstate.state2, pks);
     }
 
     public void acceptVisit(ExpressionVisitor visitor) {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Thu Sep  7 10:51:05 2006
@@ -56,17 +56,13 @@
     private static final Localizer _loc = Localizer.forPackage(PCPath.class);
 
     private final ClassMapping _candidate;
-    private LinkedList _actions = null;
-    private Joins _joins = null;
-    private boolean _forceOuter = false;
     private ClassMapping _class = null;
-    private FieldMapping _field = null;
+    private LinkedList _actions = null;
     private boolean _key = false;
-    private boolean _joinedRel = false;
     private int _type = PATH;
     private String _varName = null;
-    private Column[] _cols = null;
     private Class _cast = null;
+    private boolean _cid = false;
 
     /**
      * Return a path starting with the 'this' ptr.
@@ -92,6 +88,7 @@
             // bound variable; copy path
             _type = UNACCESSED_VAR;
             _actions.addAll(other._actions);
+            _key = other._key;
 
             action.op = Action.VAR;
             action.data = var.getName();
@@ -136,7 +133,10 @@
      * If this path is part of a contains clause, then alias it to the
      * proper contains id before initialization.
      */
-    public void setContainsId(String id) {
+    public synchronized void setContainsId(String id) {
+        if (_cid)
+            return;
+
         // treat it just like a unique variable
         Action action = new Action();
         action.op = Action.VAR;
@@ -144,6 +144,7 @@
         if (_actions == null)
             _actions = new LinkedList();
         _actions.add(action);
+        _cid = true;
     }
 
     public ClassMetaData getMetaData() {
@@ -154,29 +155,6 @@
         _class = (ClassMapping) meta;
     }
 
-    public boolean isVariable() {
-        return false;
-    }
-
-    public ClassMapping getClassMapping() {
-        if (_field == null)
-            return _class;
-        if (_key) {
-            if (_field.getKey().getTypeCode() == JavaTypes.PC)
-                return _field.getKeyMapping().getTypeMapping();
-            return null;
-        }
-        if (_field.getElement().getTypeCode() == JavaTypes.PC)
-            return _field.getElementMapping().getTypeMapping();
-        if (_field.getTypeCode() == JavaTypes.PC)
-            return _field.getTypeMapping();
-        return null;
-    }
-
-    public FieldMapping getFieldMapping() {
-        return _field;
-    }
-
     public boolean isKey() {
         return _key;
     }
@@ -193,7 +171,7 @@
                 path.append(action.data);
             else if (action.op == Action.UNBOUND_VAR)
                 path.append(((Variable) action.data).getName());
-            else
+            else 
                 path.append(((FieldMapping) action.data).getName());
             path.append('.');
         }
@@ -202,42 +180,65 @@
         return path.toString();
     }
 
-    public Column[] getColumns() {
-        if (_cols == null)
-            _cols = calculateColumns();
-        return _cols;
+    public ClassMapping getClassMapping(ExpState state) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field == null)
+            return _class;
+        if (_key) {
+            if (pstate.field.getKey().getTypeCode() == JavaTypes.PC)
+                return pstate.field.getKeyMapping().getTypeMapping();
+            return null;
+        }
+        if (pstate.field.getElement().getTypeCode() == JavaTypes.PC)
+            return pstate.field.getElementMapping().getTypeMapping();
+        if (pstate.field.getTypeCode() == JavaTypes.PC)
+            return pstate.field.getTypeMapping();
+        return null;
+    }
+
+    public FieldMapping getFieldMapping(ExpState state) {
+        return ((PathExpState) state).field;
+    }
+
+    public Column[] getColumns(ExpState state) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.cols == null)
+            pstate.cols = calculateColumns(pstate);
+        return pstate.cols;
     }
 
     /**
      * The columns used by this path.
      */
-    private Column[] calculateColumns() {
+    private Column[] calculateColumns(PathExpState pstate) {
         if (_key) {
-            if (!_joinedRel && _field.getKey().getValueMappedBy() != null)
-                joinRelation();
-            else if (_joinedRel
-                && _field.getKey().getTypeCode() == JavaTypes.PC)
-                return _field.getKeyMapping().getTypeMapping().
+            if (!pstate.joinedRel 
+                && pstate.field.getKey().getValueMappedBy() != null)
+                joinRelation(pstate, _key, false, false);
+            else if (pstate.joinedRel 
+                && pstate.field.getKey().getTypeCode() == JavaTypes.PC)
+                return pstate.field.getKeyMapping().getTypeMapping().
                     getPrimaryKeyColumns();
-            return _field.getKeyMapping().getColumns();
+            return pstate.field.getKeyMapping().getColumns();
         }
-        if (_field != null) {
-            switch (_field.getTypeCode()) {
+        if (pstate.field != null) {
+            switch (pstate.field.getTypeCode()) {
                 case JavaTypes.MAP:
                 case JavaTypes.ARRAY:
                 case JavaTypes.COLLECTION:
-                    ValueMapping elem = _field.getElementMapping();
-                    if (_joinedRel && elem.getTypeCode() == JavaTypes.PC)
+                    ValueMapping elem = pstate.field.getElementMapping();
+                    if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC)
                         return elem.getTypeMapping().getPrimaryKeyColumns();
                     if (elem.getColumns().length > 0)
                         return elem.getColumns();
-                    return _field.getColumns();
+                    return pstate.field.getColumns();
                 case JavaTypes.PC:
-                    if (_joinedRel)
-                        return _field.getTypeMapping().getPrimaryKeyColumns();
-                    return _field.getColumns();
+                    if (pstate.joinedRel)
+                        return pstate.field.getTypeMapping().
+                            getPrimaryKeyColumns();
+                    return pstate.field.getColumns();
                 default:
-                    return _field.getColumns();
+                    return pstate.field.getColumns();
             }
         }
         return (_class == null) ? Schemas.EMPTY_COLUMNS
@@ -254,13 +255,18 @@
         if (_type == UNACCESSED_VAR)
             _type = BOUND_VAR;
         _cast = null;
+        _key = false;
     }
 
-    public void getKey() {
+    public synchronized void getKey() {
+        if (_cid)
+            return;
+
         // change the last action to a get key
         Action action = (Action) _actions.getLast();
         action.op = Action.GET_KEY;
         _cast = null;
+        _key = true;
     }
 
     public FieldMetaData last() {
@@ -295,17 +301,9 @@
     public Class getType() {
         if (_cast != null)
             return _cast;
-        FieldMetaData fld;
-        boolean key;
-        if (_field != null) {
-            fld = _field;
-            key = _key;
-        } else {
-            Action act = lastFieldAction();
-            fld = (act == null) ? null : (FieldMetaData) act.data;
-            key = act != null && act.op == Action.GET_KEY;
-        }
-
+        Action act = lastFieldAction();
+        FieldMetaData fld = (act == null) ? null : (FieldMetaData) act.data;
+        boolean key = act != null && act.op == Action.GET_KEY;
         if (fld != null) {
             switch (fld.getDeclaredTypeCode()) {
                 case JavaTypes.ARRAY:
@@ -334,16 +332,13 @@
         _cast = type;
     }
 
-    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
-        // initialize can be called more than once, so reset
-        _field = null;
-        _key = false;
-        _forceOuter = false;
-        _joinedRel = false;
-        _joins = sel.newJoins();
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        PathExpState pstate = new PathExpState(sel.newJoins());
+        boolean key = false;
+        boolean forceOuter = false;
+        ClassMapping rel = _candidate;
 
         // iterate to the final field
-        ClassMapping rel = _candidate;
         ClassMapping owner;
         ClassMapping from, to;
         Action action;
@@ -354,32 +349,33 @@
 
             // treat subqueries like variables for alias generation purposes
             if (action.op == Action.VAR)
-                _joins = _joins.setVariable((String) action.data);
+                pstate.joins = pstate.joins.setVariable((String) action.data);
             else if (action.op == Action.SUBQUERY)
-                _joins = _joins.setSubselect((String) action.data);
+                pstate.joins = pstate.joins.setSubselect((String) action.data);
             else if (action.op == Action.UNBOUND_VAR) {
                 // unbound vars are cross-joined to the candidate table
                 var = (Variable) action.data;
                 rel = (ClassMapping) var.getMetaData();
-                _joins = _joins.setVariable(var.getName());
-                _joins = _joins.crossJoin(_candidate.getTable(),
+                pstate.joins = pstate.joins.setVariable(var.getName());
+                pstate.joins = pstate.joins.crossJoin(_candidate.getTable(), 
                     rel.getTable());
             } else {
                 // move past the previous field, if any
-                if (_field != null)
-                    rel = traverseField(false);
+                if (pstate.field != null)
+                    rel = traverseField(pstate, key, forceOuter, false);
 
                 // mark if the next traversal should go through
                 // the key rather than value
-                _key = action.op == Action.GET_KEY;
-                _forceOuter |= action.op == Action.GET_OUTER;
+                key = action.op == Action.GET_KEY;
+                forceOuter |= action.op == Action.GET_OUTER;
 
                 // get mapping for the current field
-                _field = (FieldMapping) action.data;
-                owner = _field.getDefiningMapping();
-                if (_field.getManagement() != FieldMapping.MANAGE_PERSISTENT)
-                    throw new UserException(_loc.get("non-pers-field",
-                        _field));
+                pstate.field = (FieldMapping) action.data;
+                owner = pstate.field.getDefiningMapping();
+                if (pstate.field.getManagement() 
+                    != FieldMapping.MANAGE_PERSISTENT)
+                    throw new UserException(_loc.get("non-pers-field", 
+                        pstate.field));
 
                 // find the most-derived type between the declared relation
                 // type and the field's owner, and join from that type to
@@ -396,22 +392,38 @@
 
                     for (; from != null && from != to;
                         from = from.getJoinablePCSuperclassMapping())
-                        _joins = from.joinSuperclass(_joins, false);
+                        pstate.joins = from.joinSuperclass(pstate.joins, false);
                 }
             }
         }
         if (_varName != null)
-            _joins = _joins.setVariable(_varName);
+            pstate.joins = pstate.joins.setVariable(_varName);
 
         // if we're not comparing to null or doing an isEmpty, then
         // join into the data on the final field; obviously we can't do these
         // joins when comparing to null b/c the whole purpose is to see
         // whether the joins even exist
-        if (!nullTest)
-            traverseField(true);
+        if ((flags & NULL_CMP) == 0)
+            traverseField(pstate, key, forceOuter, true);
+        pstate.joinedRel = false;
+        if ((flags & JOIN_REL) != 0)
+            joinRelation(pstate, key, forceOuter, false);
+        return pstate;
+    }
+
+    /**
+     * Expression state.
+     */
+    private static class PathExpState
+        extends ExpState {
 
-        // note that we haven't yet joined to the relation of the last field yet
-        _joinedRel = false;
+        private FieldMapping field = null;
+        private Column[] cols = null;
+        private boolean joinedRel = false;
+
+        public PathExpState(Joins joins) {
+            super(joins);
+        }
     }
 
     /**
@@ -420,211 +432,201 @@
      * @param last whether this is the last field in the path
      * @return the mapping of the related type, or null
      */
-    private ClassMapping traverseField(boolean last) {
-        if (_field == null)
+    private ClassMapping traverseField(PathExpState pstate, boolean key, 
+        boolean forceOuter, boolean last) {
+        if (pstate.field == null)
             return null;
 
         // traverse into field value
-        if (_key)
-            _joins = _field.joinKey(_joins, _forceOuter);
+        if (key)
+            pstate.joins = pstate.field.joinKey(pstate.joins, forceOuter);
         else
-            _joins = _field.join(_joins, _forceOuter);
+            pstate.joins = pstate.field.join(pstate.joins, forceOuter);
 
         // if this isn't the last field, traverse into the relation
         if (!last)
-            joinRelation(true);
+            joinRelation(pstate, key, forceOuter, true);
 
         // return the maping of the related type, if any
-        if (_key)
-            return _field.getKeyMapping().getTypeMapping();
-        if (_field.getElement().getTypeCode() == JavaTypes.PC)
-            return _field.getElementMapping().getTypeMapping();
-        return _field.getTypeMapping();
+        if (key)
+            return pstate.field.getKeyMapping().getTypeMapping();
+        if (pstate.field.getElement().getTypeCode() == JavaTypes.PC)
+            return pstate.field.getElementMapping().getTypeMapping();
+        return pstate.field.getTypeMapping();
     }
 
     /**
      * Join into the relation represented by the current field, if any.
      */
-    void joinRelation() {
-        joinRelation(false);
-    }
-
-    private void joinRelation(boolean traverse) {
-        if (_field == null)
+    private void joinRelation(PathExpState pstate, boolean key, 
+        boolean forceOuter, boolean traverse) {
+        if (pstate.field == null)
             return;
-        if (_key)
-            _joins = _field.joinKeyRelation(_joins, _forceOuter, traverse);
+        if (key)
+            pstate.joins = pstate.field.joinKeyRelation(pstate.joins, 
+                forceOuter, traverse);
         else
-            _joins = _field.joinRelation(_joins, _forceOuter, traverse);
-        _joinedRel = true;
+            pstate.joins = pstate.field.joinRelation(pstate.joins, forceOuter,
+                traverse);
+        pstate.joinedRel = true;
     }
 
-    public Joins getJoins() {
-        return _joins;
-    }
-
-    public Object toDataStoreValue(Object val, JDBCStore store) {
-        if (_field != null) {
+    public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState state, 
+        Object val) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field != null) {
             if (_key)
-                return _field.toKeyDataStoreValue(val, store);
-            if (_field.getElement().getDeclaredTypeCode() != JavaTypes.OBJECT)
-                return _field.toDataStoreValue(val, store);
+                return pstate.field.toKeyDataStoreValue(val, ctx.store);
+            if (pstate.field.getElement().getDeclaredTypeCode() 
+                != JavaTypes.OBJECT)
+                return pstate.field.toDataStoreValue(val, ctx.store);
 
-            val = _field.getExternalValue(val, store.getContext());
-            return _field.toDataStoreValue(val, store);
+            val = pstate.field.getExternalValue(val, ctx.store.getContext());
+            return pstate.field.toDataStoreValue(val, ctx.store);
         }
         return _class.toDataStoreValue(val, _class.getPrimaryKeyColumns(),
-            store);
+            ctx.store);
     }
 
-    public void select(Select sel, JDBCStore store, Object[] params,
-        boolean pks, JDBCFetchConfiguration fetch) {
-        selectColumns(sel, store, params, pks, fetch);
+    public void select(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        selectColumns(sel, ctx, state, pks);
     }
 
-    public void selectColumns(Select sel, JDBCStore store,
-        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
-        ClassMapping mapping = getClassMapping();
-        if (mapping == null || !_joinedRel)
-            sel.select(getColumns(), _joins);
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        ClassMapping mapping = getClassMapping(state);
+        PathExpState pstate = (PathExpState) state;
+        if (mapping == null || !pstate.joinedRel)
+            sel.select(getColumns(state), pstate.joins);
         else if (pks)
-            sel.select(mapping.getPrimaryKeyColumns(), _joins);
+            sel.select(mapping.getPrimaryKeyColumns(), pstate.joins);
         else {
             // select the mapping; allow any subs because we know this must
             // be either a relation, in which case it will already be
             // constrained by the joins, or 'this', in which case the
             // JDBCExpressionFactory takes care of adding class conditions for
             // the candidate class on the select
-            int subs = (_type == UNBOUND_VAR) ? sel.SUBS_JOINABLE
-                : sel.SUBS_ANY_JOINABLE;
-            sel.select(mapping, subs, store, fetch,
-                JDBCFetchConfiguration.EAGER_NONE, sel.outer(_joins));
+            int subs = (_type == UNBOUND_VAR) ? Select.SUBS_JOINABLE
+                : Select.SUBS_ANY_JOINABLE;
+            sel.select(mapping, subs, ctx.store, ctx.fetch,
+                JDBCFetchConfiguration.EAGER_NONE, sel.outer(pstate.joins));
         }
     }
 
-    public void groupBy(Select sel, JDBCStore store, Object[] params,
-        JDBCFetchConfiguration fetch) {
-        ClassMapping mapping = getClassMapping();
-        if (mapping == null || !_joinedRel)
-            sel.groupBy(getColumns(), sel.outer(_joins));
+    public void groupBy(Select sel, ExpContext ctx, ExpState state) {
+        ClassMapping mapping = getClassMapping(state);
+        PathExpState pstate = (PathExpState) state;
+        if (mapping == null || !pstate.joinedRel)
+            sel.groupBy(getColumns(state), sel.outer(pstate.joins));
         else {
-            int subs = (_type == UNBOUND_VAR) ? sel.SUBS_JOINABLE
-                : sel.SUBS_ANY_JOINABLE;
-            sel.groupBy(mapping, subs, store, fetch, sel.outer(_joins));
+            int subs = (_type == UNBOUND_VAR) ? Select.SUBS_JOINABLE
+                : Select.SUBS_ANY_JOINABLE;
+            sel.groupBy(mapping, subs, ctx.store, ctx.fetch, 
+                sel.outer(pstate.joins));
         }
     }
 
-    public void orderBy(Select sel, JDBCStore store, Object[] params,
-        boolean asc, JDBCFetchConfiguration fetch) {
-        sel.orderBy(getColumns(), asc, sel.outer(_joins), false);
+    public void orderBy(Select sel, ExpContext ctx, ExpState state, 
+        boolean asc) {
+        sel.orderBy(getColumns(state), asc, sel.outer(state.joins), false);
     }
 
-    public Object load(Result res, JDBCStore store,
-        JDBCFetchConfiguration fetch)
+    public Object load(ExpContext ctx, ExpState state, Result res)
         throws SQLException {
-        return load(res, store, false, fetch);
+        return load(ctx, state, res, false);
     }
 
-    Object load(Result res, JDBCStore store, boolean pks,
-        JDBCFetchConfiguration fetch)
+    Object load(ExpContext ctx, ExpState state, Result res, boolean pks)
         throws SQLException {
-        ClassMapping mapping = getClassMapping();
-        if (mapping != null && (_field == null || !_field.isEmbedded())) {
+        ClassMapping mapping = getClassMapping(state);
+        PathExpState pstate = (PathExpState) state;
+        if (mapping != null && (pstate.field == null 
+            || !pstate.field.isEmbedded())) {
             if (pks)
-                return mapping.getObjectId(store, res, null, true, _joins);
-            return res.load(mapping, store, fetch, _joins);
+                return mapping.getObjectId(ctx.store, res, null, true, 
+                    pstate.joins);
+            return res.load(mapping, ctx.store, ctx.fetch, pstate.joins);
         }
 
         Object ret;
         if (_key)
-            ret = _field.loadKeyProjection(store, fetch, res, _joins);
+            ret = pstate.field.loadKeyProjection(ctx.store, ctx.fetch, res, 
+                pstate.joins);
         else
-            ret = _field.loadProjection(store, fetch, res, _joins);
+            ret = pstate.field.loadProjection(ctx.store, ctx.fetch, res, 
+                pstate.joins);
         if (_cast != null)
             ret = Filters.convert(ret, _cast);
         return ret;
     }
 
-    /**
-     * Whether the given variable appears in this path.
-     */
-    public boolean hasVariable(Variable var) {
-        if (_actions == null)
-            return false;
-
-        Action action;
-        for (Iterator itr = _actions.iterator(); itr.hasNext();) {
-            action = (Action) itr.next();
-            if (action.op == Action.VAR && action.data.equals(var.getName()))
-                return true;
-        }
-        return false;
-    }
-
-    public void calculateValue(Select sel, JDBCStore store,
-        Object[] params, Val other, JDBCFetchConfiguration fetch) {
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
         // we don't create the SQL b/c it forces the Select to cache aliases
         // for the tables we use, and these aliases might not ever be used if
         // we eventually call appendIsEmpty or appendIsNull rather than appendTo
     }
 
-    public void clearParameters() {
-    }
-
-    public int length() {
-        return getColumns().length;
+    public int length(Select sel, ExpContext ctx, ExpState state) {
+        return getColumns(state).length;
     }
 
-    public void appendTo(SQLBuffer sql, int index, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        Column col = getColumns()[index];
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        Column col = getColumns(state)[index];
 
         // if select is null, it means we are not aliasing columns
         // (e.g., during a bulk update)
         if (sel == null)
             sql.append(col.getName());
         else
-            sql.append(sel.getColumnAlias(col, _joins));
+            sql.append(sel.getColumnAlias(col, state.joins));
     }
 
-    public void appendIsEmpty(SQLBuffer sql, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        if (_field == null)
+    public void appendIsEmpty(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field == null)
             sql.append(FALSE);
         else
-            _field.appendIsEmpty(sql, sel, _joins);
+            pstate.field.appendIsEmpty(sql, sel, pstate.joins);
     }
 
-    public void appendIsNotEmpty(SQLBuffer sql, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        if (_field == null)
+    public void appendIsNotEmpty(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field == null)
             sql.append(FALSE);
         else
-            _field.appendIsNotEmpty(sql, sel, _joins);
+            pstate.field.appendIsNotEmpty(sql, sel, pstate.joins);
     }
 
-    public void appendSize(SQLBuffer sql, Select sel, JDBCStore store,
-        Object[] params, JDBCFetchConfiguration fetch) {
-        if (_field == null)
+    public void appendSize(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field == null)
             sql.append("1");
         else
-            _field.appendSize(sql, sel, _joins);
+            pstate.field.appendSize(sql, sel, pstate.joins);
     }
 
-    public void appendIsNull(SQLBuffer sql, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        if (_field == null)
+    public void appendIsNull(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field == null)
             sql.append(FALSE);
         else
-            _field.appendIsNull(sql, sel, _joins);
+            pstate.field.appendIsNull(sql, sel, pstate.joins);
     }
 
-    public void appendIsNotNull(SQLBuffer sql, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        if (_field == null)
+    public void appendIsNotNull(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        PathExpState pstate = (PathExpState) state;
+        if (pstate.field == null)
             sql.append(TRUE);
         else
-            _field.appendIsNotNull(sql, sel, _joins);
+            pstate.field.appendIsNotNull(sql, sel, pstate.joins);
     }
 
     public int hashCode() {

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java Thu Sep  7 10:51:05 2006
@@ -18,8 +18,8 @@
 import java.util.Collection;
 import java.util.Map;
 
-import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.Filters;
@@ -39,9 +39,6 @@
     private Class _type = null;
     private int _idx = -1;
     private boolean _container = false;
-    private Object _val = null;
-    private Object _sqlVal = null;
-    private int _otherLen = 0;
 
     /**
      * Constructor. Supply parameter name and type.
@@ -79,39 +76,54 @@
         _idx = idx;
     }
 
-    public Object getValue() {
-        return _val;
+    public Object getValue(Object[] params) {
+        return Filters.convert(params[_idx], getType());
     }
 
-    public Object getSQLValue() {
-        return _sqlVal;
+    public Object getSQLValue(Select sel, ExpContext ctx, ExpState state) {
+        return ((ParamExpState) state).sqlValue;
     }
 
-    public Object getValue(Object[] params) {
-        return params[_idx];
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        return new ParamExpState();
     }
 
-    public void calculateValue(Select sel, JDBCStore store,
-        Object[] params, Val other, JDBCFetchConfiguration fetch) {
-        super.calculateValue(sel, store, params, other, fetch);
-        _val = Filters.convert(params[_idx], getType());
+    /**
+     * Expression state.
+     */
+    private static class ParamExpState
+        extends ConstExpState {
+
+        public Object sqlValue = null;
+        public int otherLength = 1; 
+    } 
+
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
+        super.calculateValue(sel, ctx, state, other, otherState);
+        Object val = getValue(ctx.params);
+        ParamExpState pstate = (ParamExpState) state;
         if (other != null && !_container) {
-            _sqlVal = other.toDataStoreValue(_val, store);
-            _otherLen = other.length();
+            pstate.sqlValue = other.toDataStoreValue(sel, ctx, otherState, val);
+            pstate.otherLength = other.length(sel, ctx, otherState);
+        } else if (val instanceof PersistenceCapable) {
+            ClassMapping mapping = ctx.store.getConfiguration().
+                getMappingRepositoryInstance().getMapping(val.getClass(), 
+                ctx.store.getContext().getClassLoader(), true);
+            pstate.sqlValue = mapping.toDataStoreValue(val, 
+                mapping.getPrimaryKeyColumns(), ctx.store);
+            pstate.otherLength = mapping.getPrimaryKeyColumns().length;
         } else
-            _sqlVal = _val;
+            pstate.sqlValue = val;
     }
 
-    public void appendTo(SQLBuffer sql, int index, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        if (_otherLen > 1)
-            sql.appendValue(((Object[]) _sqlVal)[index], getColumn(index));
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        ParamExpState pstate = (ParamExpState) state;
+        if (pstate.otherLength > 1)
+            sql.appendValue(((Object[]) pstate.sqlValue)[index], 
+                pstate.getColumn(index));
         else
-            sql.appendValue(_sqlVal, getColumn(index));
-    }
-
-    public void clearParameters() {
-        _val = null;
-        _sqlVal = null;
+            sql.appendValue(pstate.sqlValue, pstate.getColumn(index));
     }
 }

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/QueryExpressionsState.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/QueryExpressionsState.java?view=auto&rev=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/QueryExpressionsState.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/QueryExpressionsState.java Thu Sep  7 10:51:05 2006
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+/**
+ * Struct to hold the state of a query expressions instance.
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class QueryExpressionsState {
+
+    public static final ExpState[] EMPTY_STATES = new ExpState[0];
+
+    public ExpState[] projections = EMPTY_STATES;
+    public ExpState filter = null;
+    public ExpState[] grouping = EMPTY_STATES;
+    public ExpState having = null;
+    public ExpState[] ordering = EMPTY_STATES;
+}

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java Thu Sep  7 10:51:05 2006
@@ -18,6 +18,7 @@
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.StoreContext;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.util.UnsupportedException;

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java Thu Sep  7 10:51:05 2006
@@ -32,17 +32,11 @@
  * Turns parsed queries into selects.
  *
  * @author Abe White
+ * @nojavadoc
  */
-class SelectConstructor {
+public class SelectConstructor {
 
-    public static final int CACHE_NULL = 0;
-    public static final int CACHE_JOINS = 1;
-    public static final int CACHE_FULL = 2;
-
-    // cache as much as we can for multiple executions of the same query
-    private Select _template = null;
     private boolean _extent = false;
-    private int _cacheLevel = -1;
 
     /**
      * Return true if we know the select to have on criteria; to be an extent.
@@ -54,109 +48,71 @@
     }
 
     /**
-     * Evaluate the expression, returning a SQL select with the proper
-     * conditions. Use {@link #select} to then select the data.
+     * Evaluate the expression, returning a new select and filling in any
+     * associated expression state. Use {@link #select} to then select the data.
+     * 
+     * @param ctx fill with execution context
+     * @param state will be filled with expression state
      */
-    public Select evaluate(JDBCStore store, Select parent, String alias,
-        QueryExpressions exps, Object[] params, int level,
-        JDBCFetchConfiguration fetch) {
+    public Select evaluate(ExpContext ctx, Select parent, String alias, 
+        QueryExpressions exps, QueryExpressionsState state) {
         // already know that this query is equivalent to an extent?
         Select sel;
         if (_extent) {
-            sel = store.getSQLFactory().newSelect();
+            sel = ctx.store.getSQLFactory().newSelect();
             sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
             return sel;
         }
 
-        // already cached some SQL? if we're changing our cache level, we
-        // have to abandon any already-cached data because a change means
-        // different joins
-        if (level != _cacheLevel)
-            _template = null;
-        _cacheLevel = level;
-
-        if (_template != null && level == CACHE_FULL) {
-            sel = (Select) _template.fullClone(1);
-            sel.setParent(parent, alias);
-        } else if (_template != null) {
-            sel = (Select) _template.whereClone(1);
-            sel.setParent(parent, alias);
-        } else {
-            // create a new select and initialize it with the joins needed for
-            // the criteria of this query
-            sel = newJoinsSelect(store, parent, alias, exps, params, fetch);
+        // create a new select and initialize it with the joins needed for
+        // the criteria of this query
+        sel = newSelect(ctx, parent, alias, exps, state);
+
+        // create where clause; if there are no where conditions and
+        // no ordering or projections, we return null to signify that this
+        // query should be treated like an extent
+        Select inner = sel.getFromSelect();
+        SQLBuffer where = buildWhere((inner != null) ? inner : sel, ctx, 
+            state.filter, exps.filter);
+        if (where == null && exps.projections.length == 0
+            && exps.ordering.length == 0
+            && (sel.getJoins() == null || sel.getJoins().isEmpty())) {
+            _extent = true;
+            sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
+            return sel;
         }
 
-        // if this select wasn't cloned from a full template,
-        // build up sql conditions
-        if (_template == null || level != CACHE_FULL) {
-            // create where clause; if there are no where conditions and
-            // no ordering or projections, we return null to signify that this
-            // query should be treated like an extent
-            Select inner = sel.getFromSelect();
-            SQLBuffer where = buildWhere((inner != null) ? inner : sel,
-                store, exps.filter, params, fetch);
-            if (where == null && exps.projections.length == 0
-                && exps.ordering.length == 0
-                && (sel.getJoins() == null || sel.getJoins().isEmpty())) {
-                _extent = true;
-                sel = store.getSQLFactory().newSelect();
-                sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
-                return sel;
-            }
-
-            // if we're caching joins, do that now before we start setting sql.
-            // we can't cache subselects because they are also held in the
-            // where buffer
-            if (_template == null && level == CACHE_JOINS
-                && (inner == null || inner.getSubselects().isEmpty())
-                && sel.getSubselects().isEmpty()) {
-                _template = sel;
-                sel = (Select) sel.whereClone(1);
-                sel.setParent(parent, alias);
-                inner = sel.getFromSelect();
-            }
-
-            // now set sql criteria; it goes on the inner select if present
-            if (inner != null)
-                inner.where(where);
-            else
-                sel.where(where);
-
-            // apply grouping and having.  this does not select the grouping
-            // columns, just builds the GROUP BY clauses.  we don't build the
-            // ORDER BY clauses yet because if we decide to add this select
-            // to a union, the ORDER BY values get aliased differently
-            if (exps.having != null) {
-                Exp havingExp = (Exp) exps.having;
-                SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
-                havingExp.appendTo(buf, sel, store, params, fetch);
-                sel.having(buf);
-            }
-            for (int i = 0; i < exps.grouping.length; i++)
-                ((Val) exps.grouping[i]).groupBy(sel, store, params, fetch);
-
-            // if template is still null at this point, must be a full cache
-            if (_template == null && level == CACHE_FULL) {
-                _template = sel;
-                sel = (Select) _template.fullClone(1);
-                sel.setParent(parent, alias);
-            }
+        // now set sql criteria; it goes on the inner select if present
+        if (inner != null)
+            inner.where(where);
+        else
+            sel.where(where);
+
+        // apply grouping and having.  this does not select the grouping
+        // columns, just builds the GROUP BY clauses.  we don't build the
+        // ORDER BY clauses yet because if we decide to add this select
+        // to a union, the ORDER BY values get aliased differently
+        if (exps.having != null) {
+            Exp havingExp = (Exp) exps.having;
+            SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
+            havingExp.appendTo(sel, ctx, state.having, buf);
+            sel.having(buf);
         }
+        for (int i = 0; i < exps.grouping.length; i++)
+            ((Val) exps.grouping[i]).groupBy(sel, ctx, state.grouping[i]);
         return sel;
     }
 
     /**
-     * Initialize the given select's joins.
+     * Return a new select with expressions initialized.
      */
-    private Select newJoinsSelect(JDBCStore store, Select parent,
-        String alias, QueryExpressions exps, Object[] params,
-        JDBCFetchConfiguration fetch) {
-        Select sel = store.getSQLFactory().newSelect();
+    private Select newSelect(ExpContext ctx, Select parent,
+        String alias, QueryExpressions exps, QueryExpressionsState state) {
+        Select sel = ctx.store.getSQLFactory().newSelect();
         sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
-        sel.setJoinSyntax(fetch.getJoinSyntax());
+        sel.setJoinSyntax(ctx.fetch.getJoinSyntax());
         sel.setParent(parent, alias);
-        initializeJoins(sel, store, exps, params);
+        initialize(sel, ctx, exps, state);
 
         if (!sel.getAutoDistinct()) {
             if ((exps.distinct & exps.DISTINCT_TRUE) != 0)
@@ -179,12 +135,12 @@
                 // ordering, grouping, etc
                 if (exps.isAggregate() 
                     || (exps.distinct & exps.DISTINCT_TRUE) == 0) {
-                    DBDictionary dict = store.getDBDictionary();
+                    DBDictionary dict = ctx.store.getDBDictionary();
                     dict.assertSupport(dict.supportsSubselect,
                         "SupportsSubselect");
 
                     Select inner = sel;
-                    sel = store.getSQLFactory().newSelect();
+                    sel = ctx.store.getSQLFactory().newSelect();
                     sel.setParent(parent, alias);
                     sel.setDistinct(exps.isAggregate()
                         && (exps.distinct & exps.DISTINCT_TRUE) != 0);
@@ -196,14 +152,10 @@
     }
 
     /**
-     * Initialize the joins for all expressions. This only has to be done
-     * once for the template select, since each factory is only used for a
-     * single filter + projections + grouping + having + ordering combination.
-     * By initializing the joins once, we speed up subsequent executions
-     * because the relation traversal logic, etc is cached.
+     * Initialize all expressions.
      */
-    private void initializeJoins(Select sel, JDBCStore store,
-        QueryExpressions exps, Object[] params) {
+    private void initialize(Select sel, ExpContext ctx, QueryExpressions exps, 
+        QueryExpressionsState state) {
         Map contains = null;
         if (HasContainsExpressionVisitor.hasContains(exps.filter)
             || HasContainsExpressionVisitor.hasContains(exps.having))
@@ -211,64 +163,67 @@
 
         // initialize filter and having expressions
         Exp filterExp = (Exp) exps.filter;
-        filterExp.initialize(sel, store, params, contains);
+        state.filter = filterExp.initialize(sel, ctx, contains);
         Exp havingExp = (Exp) exps.having;
         if (havingExp != null)
-            havingExp.initialize(sel, store, params, contains);
+            state.having = havingExp.initialize(sel, ctx, contains);
 
         // get the top-level joins and null the expression's joins
         // at the same time so they aren't included in the where/having SQL
-        Joins filterJoins = filterExp.getJoins();
-        Joins havingJoins = (havingExp == null) ? null : havingExp.getJoins();
+        Joins filterJoins = state.filter.joins;
+        Joins havingJoins = (state.having == null) ? null : state.having.joins;
         Joins joins = sel.and(filterJoins, havingJoins);
 
         // initialize result values
-        Val resultVal;
-        for (int i = 0; i < exps.projections.length; i++) {
-            resultVal = (Val) exps.projections[i];
-            resultVal.initialize(sel, store, false);
-
-            // have to join through to related type for pc object projections;
-            // this ensures that we have all our joins cached
-            if (resultVal instanceof PCPath)
-                ((PCPath) resultVal).joinRelation();
-            joins = sel.and(joins, resultVal.getJoins());
+        if (exps.projections.length > 0) {
+            state.projections = new ExpState[exps.projections.length];
+            Val resultVal;
+            for (int i = 0; i < exps.projections.length; i++) {
+                resultVal = (Val) exps.projections[i];
+                // have to join through to related type for pc object 
+                // projections; this ensures that we have all our joins cached
+                state.projections[i] = resultVal.initialize(sel, ctx, 
+                    Val.JOIN_REL);
+                joins = sel.and(joins, state.projections[i].joins);
+            }
         }
 
         // initialize grouping
-        Val groupVal;
-        for (int i = 0; i < exps.grouping.length; i++) {
-            groupVal = (Val) exps.grouping[i];
-            groupVal.initialize(sel, store, false);
-
-            // have to join through to related type for pc object groupings;
-            // this ensures that we have all our joins cached
-            if (groupVal instanceof PCPath)
-                ((PCPath) groupVal).joinRelation();
-            joins = sel.and(joins, groupVal.getJoins());
+        if (exps.grouping.length > 0) {
+            state.grouping = new ExpState[exps.grouping.length];
+            Val groupVal;
+            for (int i = 0; i < exps.grouping.length; i++) {
+                groupVal = (Val) exps.grouping[i];
+                // have to join through to related type for pc object groupings;
+                // this ensures that we have all our joins cached
+                state.grouping[i] = groupVal.initialize(sel, ctx, Val.JOIN_REL);
+                joins = sel.and(joins, state.grouping[i].joins);
+            }
         }
 
         // initialize ordering
-        Val orderVal;
-        for (int i = 0; i < exps.ordering.length; i++) {
-            orderVal = (Val) exps.ordering[i];
-            orderVal.initialize(sel, store, false);
-            joins = sel.and(joins, orderVal.getJoins());
+        if (exps.ordering.length > 0) {
+            state.ordering = new ExpState[exps.ordering.length];
+            Val orderVal;
+            for (int i = 0; i < exps.ordering.length; i++) {
+                orderVal = (Val) exps.ordering[i];
+                state.ordering[i] = orderVal.initialize(sel, ctx, 0);
+                joins = sel.and(joins, state.ordering[i].joins);
+            }
         }
-
         sel.where(joins);
     }
 
     /**
      * Create the where sql.
      */
-    private SQLBuffer buildWhere(Select sel, JDBCStore store,
-        Expression filter, Object[] params, JDBCFetchConfiguration fetch) {
+    private SQLBuffer buildWhere(Select sel, ExpContext ctx, ExpState state, 
+        Expression filter) {
         // create where buffer
-        SQLBuffer where = new SQLBuffer(store.getDBDictionary());
+        SQLBuffer where = new SQLBuffer(ctx.store.getDBDictionary());
         where.append("(");
         Exp filterExp = (Exp) filter;
-        filterExp.appendTo(where, sel, store, params, fetch);
+        filterExp.appendTo(sel, ctx, state, where);
 
         if (where.sqlEquals("(") || where.sqlEquals("(1 = 1"))
             return null;
@@ -278,9 +233,9 @@
     /**
      * Select the data for this query.
      */
-    public void select(JDBCStore store, ClassMapping mapping,
-        boolean subclasses, Select sel, QueryExpressions exps,
-        Object[] params, JDBCFetchConfiguration fetch, int eager) {
+    public void select(Select sel, ExpContext ctx, ClassMapping mapping,
+        boolean subclasses, QueryExpressions exps, QueryExpressionsState state,
+        int eager) {
         Select inner = sel.getFromSelect();
         Val val;
         Joins joins = null;
@@ -290,13 +245,13 @@
         // build ordering clauses before select so that any eager join
         // ordering gets applied after query ordering
         for (int i = 0; i < exps.ordering.length; i++)
-            ((Val) exps.ordering[i]).orderBy(sel, store, params,
-                exps.ascending[i], fetch);
+            ((Val) exps.ordering[i]).orderBy(sel, ctx, state.ordering[i],
+                exps.ascending[i]);
 
         // if no result string set, select matching objects like normal
         if (exps.projections.length == 0 && sel.getParent() == null) {
-            int subs = (subclasses) ? sel.SUBS_JOINABLE : sel.SUBS_NONE;
-            sel.selectIdentifier(mapping, subs, store, fetch, eager);
+            int subs = (subclasses) ? Select.SUBS_JOINABLE : Select.SUBS_NONE;
+            sel.selectIdentifier(mapping, subs, ctx.store, ctx.fetch, eager);
         } else if (exps.projections.length == 0) {
             // subselect for objects; we really just need the primary key values
             sel.select(mapping.getPrimaryKeyColumns(), joins);
@@ -312,15 +267,15 @@
             for (int i = 0; i < exps.projections.length; i++) {
                 val = (Val) exps.projections[i];
                 if (inner != null)
-                    val.selectColumns(inner, store, params, pks, fetch);
-                val.select(sel, store, params, pks, fetch);
+                    val.selectColumns(inner, ctx, state.projections[i], pks);
+                val.select(sel, ctx, state.projections[i], pks);
             }
 
             // make sure having columns are selected since it is required by 
             // some DBs.  put them last so they don't affect result processing
             if (exps.having != null && inner != null)
-                ((Exp) exps.having).selectColumns(inner, store, params, true,
-                    fetch);
+                ((Exp) exps.having).selectColumns(inner, ctx, state.having, 
+                    true);
         }
 
         // select ordering columns, since it is required by some DBs.  put them
@@ -328,17 +283,16 @@
         for (int i = 0; i < exps.ordering.length; i++) {
             val = (Val) exps.ordering[i];
             if (inner != null)
-                val.selectColumns(inner, store, params, true, fetch);
-            val.select(sel, store, params, true, fetch);
+                val.selectColumns(inner, ctx, state.ordering[i], true);
+            val.select(sel, ctx, state.ordering[i], true);
         }
 
         // add conditions limiting the projections to the proper classes; if
         // this isn't a projection then they will already be added
         if (exps.projections.length > 0) {
-            store.loadSubclasses(mapping);
-            Select indSel = (inner == null) ? sel : inner;
-            mapping.getDiscriminator().addClassConditions(indSel, subclasses, 
-                joins);
+            ctx.store.loadSubclasses(mapping);
+            mapping.getDiscriminator().addClassConditions((inner != null) 
+                ? inner : sel, subclasses, joins);
         }
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java?view=diff&rev=441158&r1=441157&r2=441158
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java Thu Sep  7 10:51:05 2006
@@ -33,17 +33,16 @@
         super(val);
     }
 
-    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
         // initialize the value with a null test
-        getVal().initialize(sel, store, true);
+        return initializeValue(sel, ctx, NULL_CMP);
     }
 
-    public void appendTo(SQLBuffer sql, int index, Select sel,
-        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
-        getVal().calculateValue(sel, store, params, null, fetch);
-        getVal().appendSize(sql, sel, store, params, fetch);
-        sel.append(sql, getVal().getJoins());
-        getVal().clearParameters();
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        getValue().calculateValue(sel, ctx, state, null, null);
+        getValue().appendSize(sel, ctx, state, sql);
+        sel.append(sql, state.joins);
     }
 
     protected Class getType(Class c) {