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

svn commit: r423615 [9/44] - in /incubator/openjpa/trunk: ./ openjpa-jdbc-5/ openjpa-jdbc-5/src/ openjpa-jdbc-5/src/main/ openjpa-jdbc-5/src/main/java/ openjpa-jdbc-5/src/main/java/org/ openjpa-jdbc-5/src/main/java/org/apache/ openjpa-jdbc-5/src/main/j...

Added: 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?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,633 @@
+/*
+ * 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;
+
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Schemas;
+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;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * A path represents a traversal into fields of a candidate object.
+ *
+ * @author Abe White
+ */
+class PCPath
+    implements JDBCPath {
+
+    private static final int PATH = 0;
+    private static final int BOUND_VAR = 1;
+    private static final int UNBOUND_VAR = 2;
+    private static final int UNACCESSED_VAR = 3;
+
+    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 boolean _key = false;
+    private boolean _joinedRel = false;
+    private int _type = PATH;
+    private String _varName = null;
+    private Column[] _cols = null;
+    private Class _cast = null;
+
+    /**
+     * Return a path starting with the 'this' ptr.
+     */
+    public PCPath(ClassMapping type) {
+        _candidate = type;
+    }
+
+    /**
+     * Return a path starting from the given variable.
+     */
+    public PCPath(ClassMapping candidate, Variable var) {
+        _candidate = candidate;
+        _actions = new LinkedList();
+
+        PCPath other = var.getPCPath();
+        Action action = new Action();
+        if (other == null) {
+            _type = UNBOUND_VAR;
+            action.op = Action.UNBOUND_VAR;
+            action.data = var;
+        } else {
+            // bound variable; copy path
+            _type = UNACCESSED_VAR;
+            _actions.addAll(other._actions);
+
+            action.op = Action.VAR;
+            action.data = var.getName();
+        }
+        _actions.add(action);
+        _cast = var.getType(); // initial type is var type
+    }
+
+    /**
+     * Return a path starting from the given subquery.
+     */
+    public PCPath(SubQ sub) {
+        _candidate = sub.getCandidate();
+        _actions = new LinkedList();
+
+        Action action = new Action();
+        action.op = Action.SUBQUERY;
+        action.data = sub.getCandidateAlias();
+        _actions.add(action);
+        _cast = sub.getType(); // initial type is subquery type
+        _varName = sub.getCandidateAlias();
+    }
+
+    /**
+     * Set the path as a binding of the given variable.
+     */
+    public void addVariableAction(Variable var) {
+        _varName = var.getName();
+    }
+
+    /**
+     * Return true if this is a bound variable that has not been accessed
+     * after binding. Useful for filters like
+     * "coll.contains (var) && var == null", which should really
+     * just act like "coll.contains (null)".
+     */
+    public boolean isUnaccessedVariable() {
+        return _type == UNACCESSED_VAR;
+    }
+
+    /**
+     * If this path is part of a contains clause, then alias it to the
+     * proper contains id before initialization.
+     */
+    public void setContainsId(String id) {
+        // treat it just like a unique variable
+        Action action = new Action();
+        action.op = Action.VAR;
+        action.data = id;
+        if (_actions == null)
+            _actions = new LinkedList();
+        _actions.add(action);
+    }
+
+    public ClassMetaData getMetaData() {
+        return _class;
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _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;
+    }
+
+    public String getPath() {
+        if (_actions == null)
+            return (_varName == null) ? "" : _varName + ".";
+
+        StringBuffer path = new StringBuffer();
+        Action action;
+        for (Iterator itr = _actions.iterator(); itr.hasNext();) {
+            action = (Action) itr.next();
+            if (action.op == Action.VAR || action.op == Action.SUBQUERY)
+                path.append(action.data);
+            else if (action.op == Action.UNBOUND_VAR)
+                path.append(((Variable) action.data).getName());
+            else
+                path.append(((FieldMapping) action.data).getName());
+            path.append('.');
+        }
+        if (_varName != null)
+            path.append(_varName).append('.');
+        return path.toString();
+    }
+
+    public Column[] getColumns() {
+        if (_cols == null)
+            _cols = calculateColumns();
+        return _cols;
+    }
+
+    /**
+     * The columns used by this path.
+     */
+    private Column[] calculateColumns() {
+        if (_key) {
+            if (!_joinedRel && _field.getKey().getValueMappedBy() != null)
+                joinRelation();
+            else if (_joinedRel
+                && _field.getKey().getTypeCode() == JavaTypes.PC)
+                return _field.getKeyMapping().getTypeMapping().
+                    getPrimaryKeyColumns();
+            return _field.getKeyMapping().getColumns();
+        }
+        if (_field != null) {
+            switch (_field.getTypeCode()) {
+                case JavaTypes.MAP:
+                case JavaTypes.ARRAY:
+                case JavaTypes.COLLECTION:
+                    ValueMapping elem = _field.getElementMapping();
+                    if (_joinedRel && elem.getTypeCode() == JavaTypes.PC)
+                        return elem.getTypeMapping().getPrimaryKeyColumns();
+                    if (elem.getColumns().length > 0)
+                        return elem.getColumns();
+                    return _field.getColumns();
+                case JavaTypes.PC:
+                    if (_joinedRel)
+                        return _field.getTypeMapping().getPrimaryKeyColumns();
+                    return _field.getColumns();
+                default:
+                    return _field.getColumns();
+            }
+        }
+        return (_class == null) ? Schemas.EMPTY_COLUMNS
+            : _class.getPrimaryKeyColumns();
+    }
+
+    public void get(FieldMetaData field, boolean nullTraversal) {
+        if (_actions == null)
+            _actions = new LinkedList();
+        Action action = new Action();
+        action.op = (nullTraversal) ? Action.GET_OUTER : Action.GET;
+        action.data = field;
+        _actions.add(action);
+        if (_type == UNACCESSED_VAR)
+            _type = BOUND_VAR;
+        _cast = null;
+    }
+
+    public void getKey() {
+        // change the last action to a get key
+        Action action = (Action) _actions.getLast();
+        action.op = Action.GET_KEY;
+        _cast = null;
+    }
+
+    public FieldMetaData last() {
+        Action act = lastFieldAction();
+        return (act == null) ? null : (FieldMetaData) act.data;
+    }
+
+    /**
+     * Return the last action that gets a field.
+     */
+    private Action lastFieldAction() {
+        if (_actions == null)
+            return null;
+
+        ListIterator itr = _actions.listIterator(_actions.size());
+        Action prev;
+        while (itr.hasPrevious()) {
+            prev = (Action) itr.previous();
+            if (prev.op == Action.GET || prev.op == Action.GET_OUTER
+                || prev.op == Action.GET_KEY)
+                return prev;
+
+            // break if we're getting to path portions that we copied from
+            // our variable
+            if (prev.op == Action.VAR || prev.op == Action.UNBOUND_VAR
+                || prev.op == Action.SUBQUERY)
+                break;
+        }
+        return null;
+    }
+
+    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;
+        }
+
+        if (fld != null) {
+            switch (fld.getDeclaredTypeCode()) {
+                case JavaTypes.MAP:
+                    if (key)
+                        return fld.getKey().getDeclaredType();
+                    // no break
+                case JavaTypes.ARRAY:
+                case JavaTypes.COLLECTION:
+                    return fld.getElement().getDeclaredType();
+                default:
+                    return fld.getDeclaredType();
+            }
+        }
+        if (_class != null)
+            return _class.getDescribedType();
+        return Object.class;
+    }
+
+    public void setImplicitType(Class type) {
+        _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();
+
+        // iterate to the final field
+        ClassMapping rel = _candidate;
+        ClassMapping owner;
+        ClassMapping from, to;
+        Action action;
+        Variable var;
+        Iterator itr = (_actions == null) ? null : _actions.iterator();
+        while (itr != null && itr.hasNext()) {
+            action = (Action) itr.next();
+
+            // treat subqueries like variables for alias generation purposes
+            if (action.op == Action.VAR)
+                _joins = _joins.setVariable((String) action.data);
+            else if (action.op == Action.SUBQUERY)
+                _joins = _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(),
+                    rel.getTable());
+            } else {
+                // move past the previous field, if any
+                if (_field != null)
+                    rel = traverseField(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;
+
+                // 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));
+
+                // find the most-derived type between the declared relation
+                // type and the field's owner, and join from that type to
+                // the lesser derived type
+                if (rel != owner && rel != null) {
+                    if (rel.getDescribedType().isAssignableFrom
+                        (owner.getDescribedType())) {
+                        from = owner;
+                        to = rel;
+                    } else {
+                        from = rel;
+                        to = owner;
+                    }
+
+                    for (; from != null && from != to;
+                        from = from.getJoinablePCSuperclassMapping())
+                        _joins = from.joinSuperclass(_joins, false);
+                }
+            }
+        }
+        if (_varName != null)
+            _joins = _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);
+
+        // note that we haven't yet joined to the relation of the last field yet
+        _joinedRel = false;
+    }
+
+    /**
+     * Traverse into the previous field of a relation path.
+     *
+     * @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)
+            return null;
+
+        // traverse into field value
+        if (_key)
+            _joins = _field.joinKey(_joins, _forceOuter);
+        else
+            _joins = _field.join(_joins, _forceOuter);
+
+        // if this isn't the last field, traverse into the relation
+        if (!last)
+            joinRelation(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();
+    }
+
+    /**
+     * Join into the relation represented by the current field, if any.
+     */
+    void joinRelation() {
+        joinRelation(false);
+    }
+
+    private void joinRelation(boolean traverse) {
+        if (_field == null)
+            return;
+        if (_key)
+            _joins = _field.joinKeyRelation(_joins, _forceOuter, traverse);
+        else
+            _joins = _field.joinRelation(_joins, _forceOuter, traverse);
+        _joinedRel = true;
+    }
+
+    public Joins getJoins() {
+        return _joins;
+    }
+
+    public Object toDataStoreValue(Object val, JDBCStore store) {
+        if (_field != null) {
+            if (_key)
+                return _field.toKeyDataStoreValue(val, store);
+            if (_field.getElement().getDeclaredTypeCode() != JavaTypes.OBJECT)
+                return _field.toDataStoreValue(val, store);
+
+            val = _field.getExternalValue(val, store.getContext());
+            return _field.toDataStoreValue(val, store);
+        }
+        return _class.toDataStoreValue(val, _class.getPrimaryKeyColumns(),
+            store);
+    }
+
+    public void select(Select sel, JDBCStore store, Object[] params,
+        boolean pks, JDBCFetchState fetchState) {
+        selectColumns(sel, store, params, pks, fetchState);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        ClassMapping mapping = getClassMapping();
+        if (mapping == null || !_joinedRel)
+            sel.select(getColumns(), _joins);
+        else if (pks)
+            sel.select(mapping.getPrimaryKeyColumns(), _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, fetchState,
+                JDBCFetchConfiguration.EAGER_NONE, sel.outer(_joins));
+        }
+    }
+
+    public void groupBy(Select sel, JDBCStore store, Object[] params,
+        JDBCFetchState fetchState) {
+        sel.groupBy(getColumns(), sel.outer(_joins), false);
+    }
+
+    public void orderBy(Select sel, JDBCStore store, Object[] params,
+        boolean asc, JDBCFetchState fetchState) {
+        sel.orderBy(getColumns(), asc, sel.outer(_joins), false);
+    }
+
+    public Object load(Result res, JDBCStore store,
+        JDBCFetchState fetchState)
+        throws SQLException {
+        return load(res, store, false, fetchState);
+    }
+
+    Object load(Result res, JDBCStore store, boolean pks,
+        JDBCFetchState fetchState)
+        throws SQLException {
+        ClassMapping mapping = getClassMapping();
+        if (mapping != null && (_field == null || !_field.isEmbedded())) {
+            if (pks)
+                return mapping.getObjectId(store, res, null, true, _joins);
+            return res.load(mapping, store, fetchState, _joins);
+        }
+
+        Object ret;
+        if (_key)
+            ret = _field.loadKeyProjection(store, fetchState, res, _joins);
+        else
+            ret = _field.loadProjection(store, fetchState, res, _joins);
+        if (_cast != null)
+            ret = Filters.convert(ret, _cast);
+        return ret;
+    }
+
+    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, JDBCFetchState fetchState) {
+        // 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 void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        Column col = getColumns()[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));
+    }
+
+    public void appendIsEmpty(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        if (_field == null)
+            sql.append("1 <> 1");
+        else
+            _field.appendIsEmpty(sql, sel, _joins);
+    }
+
+    public void appendIsNotEmpty(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        if (_field == null)
+            sql.append("1 <> 1");
+        else
+            _field.appendIsNotEmpty(sql, sel, _joins);
+    }
+
+    public void appendSize(SQLBuffer sql, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        if (_field == null)
+            sql.append("1");
+        else
+            _field.appendSize(sql, sel, _joins);
+    }
+
+    public void appendIsNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        if (_field == null)
+            sql.append("1 <> 1");
+        else
+            _field.appendIsNull(sql, sel, _joins);
+    }
+
+    public void appendIsNotNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        if (_field == null)
+            sql.append("1 = 1");
+        else
+            _field.appendIsNotNull(sql, sel, _joins);
+    }
+
+    /**
+     * Helper class representing an action.
+     */
+    private static class Action {
+
+        public static final int GET = 0;
+        public static final int GET_OUTER = 1;
+        public static final int GET_KEY = 2;
+        public static final int VAR = 3;
+        public static final int SUBQUERY = 4;
+        public static final int UNBOUND_VAR = 5;
+        public static final int CAST = 6;
+
+        public int op = -1;
+        public Object data = null;
+
+        public String toString() {
+            return op + "|" + data;
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 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?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+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;
+import org.apache.openjpa.kernel.exps.Parameter;
+import org.apache.openjpa.util.ImplHelper;
+
+/**
+ * A parameter in a filter.
+ *
+ * @author Abe White
+ */
+class Param
+    extends Const
+    implements Parameter {
+
+    private final String _name;
+    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.
+     */
+    public Param(String name, Class type) {
+        _name = name;
+        setImplicitType(type);
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public String getParameterName() {
+        return getName();
+    }
+
+    public Class getType() {
+        return _type;
+    }
+
+    public void setImplicitType(Class type) {
+        _type = type;
+        _container = (getMetaData() == null ||
+            !ImplHelper.isManagedType(type))
+            && (Collection.class.isAssignableFrom(type)
+            || Map.class.isAssignableFrom(type));
+    }
+
+    public int getIndex() {
+        return _idx;
+    }
+
+    public void setIndex(int idx) {
+        _idx = idx;
+    }
+
+    public Object getValue() {
+        return _val;
+    }
+
+    public Object getSQLValue() {
+        return _sqlVal;
+    }
+
+    public Object getValue(Object[] params) {
+        return params[_idx];
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchState fetchState) {
+        super.calculateValue(sel, store, params, other, fetchState);
+        _val = Filters.convert(params[_idx], getType());
+        if (other != null && !_container) {
+            _sqlVal = other.toDataStoreValue(_val, store);
+            _otherLen = other.length();
+        } else
+            _sqlVal = _val;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        if (_otherLen > 1)
+            sql.appendValue(((Object[]) _sqlVal)[index], getColumn(index));
+        else
+            sql.appendValue(_sqlVal, getColumn(index));
+    }
+
+    public void clearParameters() {
+        _val = null;
+        _sqlVal = null;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 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?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+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.kernel.StoreContext;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.UnsupportedException;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * Simple listener which embeds its SQL argument into the query. Listens
+ * on <code>sql</code>.
+ *  Example:<br />
+ * <code> "price &lt; sql(\"(SELECT AVG (PRICE) FROM PRODUCT_TABLE)\")"
+ * </code>
+ *
+ * @nojavadoc
+ */
+public class SQLEmbed
+    implements JDBCFilterListener {
+
+    public static String TAG = "sql";
+
+    private static final Localizer _loc = Localizer.forPackage(SQLEmbed.class);
+
+    public String getTag() {
+        return TAG;
+    }
+
+    public boolean expectsArguments() {
+        return true;
+    }
+
+    public boolean expectsTarget() {
+        return false;
+    }
+
+    public Object evaluate(Object target, Class targetClass, Object[] args,
+        Class[] argClasses, Object candidate, StoreContext ctx) {
+        throw new UnsupportedException(_loc.get("no-in-mem", TAG));
+    }
+
+    public void appendTo(SQLBuffer buf, FilterValue target, FilterValue[] args,
+        ClassMapping type, JDBCStore store) {
+        if (!args[0].isConstant())
+            throw new UserException(_loc.get("const-only", TAG));
+        buf.append(args[0].getValue().toString());
+    }
+
+    public Class getType(Class targetClass, Class[] argClasses) {
+        return Object.class;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLEmbed.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Simple listener which embeds the argument as an expression into the
+ * where clause generated by the query. Listens on "ext:sqlExp".
+ *  Example:<br />
+ * <code>
+ * "price &lt; 10 || ext:sqlExp (\"(SELECT AVG (PRICE) FROM PRODUCT_TABLE)
+ * &gt; 100\")"
+ * </code>
+ *
+ * @nojavadoc
+ * @deprecated Use {@link SQLEmbed} directly
+ */
+public class SQLExpression
+    extends SQLEmbed {
+
+    public static final String TAG = "sqlExp";
+
+    public String getTag() {
+        return TAG;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLExpression.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLValue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLValue.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLValue.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLValue.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * Simple listener which embeds the argument as a value into the where
+ * clause generated by the query. Listens on "ext:sqlVal".
+ *  Example:<br />
+ * <code> "price &lt; ext:sqlVal (\"(SELECT AVG (PRICE) FROM PRODUCT_TABLE)\")"
+ * </code>
+ *
+ * @nojavadoc
+ * @deprecated Use {@link SQLEmbed} directly
+ */
+public class SQLValue
+    extends SQLEmbed {
+
+    public static final String TAG = "sqlVal";
+
+    public String getTag() {
+        return TAG;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SQLValue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 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?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,352 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+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.Expression;
+import org.apache.openjpa.kernel.exps.QueryExpressions;
+
+/**
+ * Turns parsed queries into selects.
+ *
+ * @author Abe White
+ */
+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.
+     * Note that even if this method returns false, {@link #evaluate} may still
+     * return null if we haven't cached whether the query is an extent yet.
+     */
+    public boolean isExtent() {
+        return _extent;
+    }
+
+    /**
+     * Evaluate the expression, returning a SQL select with the proper
+     * conditions. Use {@link #select} to then select the data.
+     */
+    public Select evaluate(JDBCStore store, Select parent, String alias,
+        QueryExpressions exps, Object[] params, int level,
+        JDBCFetchState fetchState) {
+        // already know that this query is equivalent to an extent?
+        Select sel;
+        if (_extent) {
+            sel = 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,
+                fetchState);
+        }
+
+        // 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, fetchState);
+            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, fetchState);
+                sel.having(buf);
+            }
+            for (int i = 0; i < exps.grouping.length; i++)
+                ((Val) exps.grouping[i]).groupBy(sel, store, params,
+                    fetchState);
+
+            // 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);
+            }
+        }
+        return sel;
+    }
+
+    /**
+     * Initialize the given select's joins.
+     */
+    private Select newJoinsSelect(JDBCStore store, Select parent,
+        String alias, QueryExpressions exps, Object[] params,
+        JDBCFetchState fetchState) {
+        Select sel = store.getSQLFactory().newSelect();
+        sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
+        JDBCFetchConfiguration fetch = (fetchState == null)
+            ?
+            (JDBCFetchConfiguration) store.getContext().getFetchConfiguration()
+            : fetchState.getJDBCFetchConfiguration();
+        sel.setJoinSyntax(fetch.getJoinSyntax());
+        sel.setParent(parent, alias);
+        initializeJoins(sel, store, exps, params);
+
+        if (!sel.getAutoDistinct()) {
+            if ((exps.distinct & exps.DISTINCT_TRUE) != 0)
+                sel.setDistinct(true);
+            else if ((exps.distinct & exps.DISTINCT_FALSE) != 0)
+                sel.setDistinct(false);
+        } else if (exps.projections.length > 0) {
+            if (!sel.isDistinct() && (exps.distinct & exps.DISTINCT_TRUE) != 0)
+            {
+                // if the select is not distinct but the query is, force
+                // the select to be distinct
+                sel.setDistinct(true);
+            } else if (sel.isDistinct()) {
+                // when aggregating data or making a non-distinct projection
+                // from a distinct select, we have to select from a tmp
+                // table formed by a distinct subselect in the from clause;
+                // this subselect selects the pks of the candidate (to
+                // get unique candidate values) and needed field values and
+                // applies the where conditions; the outer select applies
+                // ordering, grouping, etc
+                if (exps.aggregate || (exps.distinct & exps.DISTINCT_TRUE) == 0)
+                {
+                    DBDictionary dict = store.getDBDictionary();
+                    dict.assertSupport(dict.supportsSubselect,
+                        "SupportsSubselect");
+
+                    Select inner = sel;
+                    sel = store.getSQLFactory().newSelect();
+                    sel.setParent(parent, alias);
+                    sel.setDistinct(exps.aggregate
+                        && (exps.distinct & exps.DISTINCT_TRUE) != 0);
+                    sel.setFromSelect(inner);
+                }
+            }
+        }
+        return sel;
+    }
+
+    /**
+     * 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.
+     */
+    private void initializeJoins(Select sel, JDBCStore store,
+        QueryExpressions exps, Object[] params) {
+        Map contains = null;
+        if (((Exp) exps.filter).hasContainsExpression()
+            || (exps.having != null
+            && ((Exp) exps.having).hasContainsExpression()))
+            contains = new HashMap(7);
+
+        // initialize filter and having expressions
+        Exp filterExp = (Exp) exps.filter;
+        filterExp.initialize(sel, store, params, contains);
+        Exp havingExp = (Exp) exps.having;
+        if (havingExp != null)
+            havingExp.initialize(sel, store, params, 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 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());
+        }
+
+        // initialize grouping
+        Val groupVal;
+        for (int i = 0; i < exps.grouping.length; i++) {
+            groupVal = (Val) exps.grouping[i];
+            groupVal.initialize(sel, store, false);
+            joins = sel.and(joins, groupVal.getJoins());
+        }
+
+        // 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());
+        }
+
+        sel.where(joins);
+    }
+
+    /**
+     * Create the where sql.
+     */
+    private SQLBuffer buildWhere(Select sel, JDBCStore store,
+        Expression filter, Object[] params, JDBCFetchState fetchState) {
+        // create where buffer
+        SQLBuffer where = new SQLBuffer(store.getDBDictionary());
+        where.append("(");
+        Exp filterExp = (Exp) filter;
+        filterExp.appendTo(where, sel, store, params, fetchState);
+
+        if (where.sqlEquals("(") || where.sqlEquals("(1 = 1"))
+            return null;
+        return where.append(")");
+    }
+
+    /**
+     * Select the data for this query.
+     */
+    public void select(JDBCStore store, ClassMapping mapping,
+        boolean subclasses, Select sel, QueryExpressions exps,
+        Object[] params, JDBCFetchState fetchState, int eager) {
+        Select inner = sel.getFromSelect();
+        Val val;
+        Joins joins = null;
+        if (sel.getSubselectPath() != null)
+            joins = sel.newJoins().setSubselect(sel.getSubselectPath());
+        JDBCFetchConfiguration fetch = fetchState.getJDBCFetchConfiguration();
+        // 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], fetchState);
+
+        // 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, fetchState, eager);
+        } else if (exps.projections.length == 0) {
+            // subselect for objects; we really just need the primary key values
+            sel.select(mapping.getPrimaryKeyColumns(), joins);
+        } else {
+            // if we have an inner select, we need to select the candidate
+            // class' pk columns to guarantee unique instances
+            if (inner != null)
+                inner.select(mapping.getPrimaryKeyColumns(), joins);
+
+            // select each result value; no need to pass on the eager mode since
+            // under projections we always use EAGER_NONE
+            boolean pks = sel.getParent() != null;
+            for (int i = 0; i < exps.projections.length; i++) {
+                val = (Val) exps.projections[i];
+                if (inner != null)
+                    val.selectColumns(inner, store, params, pks, fetchState);
+                val.select(sel, store, params, pks, fetchState);
+            }
+
+            // make sure grouping and having columns are selected since it
+            // is required by most 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,
+                    fetchState);
+            for (int i = 0; i < exps.grouping.length; i++) {
+                val = (Val) exps.grouping[i];
+                if (inner != null)
+                    val.selectColumns(inner, store, params, true, fetchState);
+                val.select(sel, store, params, true, fetchState);
+            }
+        }
+
+        // select order data last so it doesn't affect result processing
+        for (int i = 0; i < exps.ordering.length; i++) {
+            val = (Val) exps.ordering[i];
+            if (inner != null)
+                val.selectColumns(inner, store, params, true, fetchState);
+            val.select(sel, store, params, true, fetchState);
+        }
+
+        // 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) {
+            Select indSel = (inner == null) ? sel : inner;
+            store.addClassConditions(indSel, mapping, subclasses, joins);
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 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?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+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.util.InternalException;
+
+/**
+ * Size.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class Size
+    extends UnaryOp
+    implements Val {
+
+    public Size(Val val) {
+        super(val);
+    }
+
+    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+        // initialize the value with a null test
+        getVal().initialize(sel, store, true);
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        getVal().calculateValue(sel, store, params, null, fetchState);
+        getVal().appendSize(sql, sel, store, params, fetchState);
+        sel.append(sql, getVal().getJoins());
+        getVal().clearParameters();
+    }
+
+    protected Class getType(Class c) {
+        return long.class;
+    }
+
+    protected String getOperator() {
+        // since we override appendTo(), this method should never be called
+        throw new InternalException();
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Size.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sqrt.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sqrt.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sqrt.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sqrt.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+/**
+ * Square root.
+ *
+ * @author Abe White
+ */
+class Sqrt
+    extends UnaryOp {
+
+    /**
+     * Constructor. Provide the value to operate on.
+     */
+    public Sqrt(Val val) {
+        super(val);
+    }
+
+    protected Class getType(Class c) {
+        return double.class;
+    }
+
+    protected String getOperator() {
+        return "SQRT";
+    }
+}
+

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sqrt.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,266 @@
+/*
+ * 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;
+
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Table;
+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 serp.util.Numbers;
+
+/**
+ * Test if one string starts with another.
+ *
+ * @author Abe White
+ */
+class StartsWithExpression
+    implements Exp {
+
+    private final Val _val1;
+    private final Val _val2;
+    private Joins _joins = null;
+    private String _pre = null;
+    private String _post = null;
+
+    /**
+     * Constructor. Supply values.
+     */
+    public StartsWithExpression(Val val1, Val val2) {
+        _val1 = val1;
+        _val2 = val2;
+    }
+
+    public void initialize(Select sel, JDBCStore store,
+        Object[] params, Map contains) {
+        _val1.initialize(sel, store, false);
+        _val2.initialize(sel, store, false);
+        _joins = sel.and(_val1.getJoins(), _val2.getJoins());
+
+        DBDictionary dict = store.getDBDictionary();
+        String func = dict.stringLengthFunction;
+        if (func != null) {
+            int idx = func.indexOf("{0}");
+            _pre = func.substring(0, idx);
+            _post = func.substring(idx + 3);
+        }
+    }
+
+    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        _val1.calculateValue(sel, store, params, _val2, fetchState);
+        _val2.calculateValue(sel, store, params, _val1, fetchState);
+
+        if (_val1 instanceof Const && ((Const) _val1).getValue() == null)
+            buf.append("1 <> 1");
+        else if (_val2 instanceof Const) {
+            Object o = ((Const) _val2).getValue();
+            if (o == null)
+                buf.append("1 <> 1");
+            else {
+                Column col = null;
+                if (_val1 instanceof PCPath) {
+                    Column[] cols = ((PCPath) _val1).getColumns();
+                    if (cols.length == 1)
+                        col = cols[0];
+                }
+
+                _val1.appendTo(buf, 0, sel, store, params, fetchState);
+                buf.append(" LIKE ");
+                buf.appendValue(o.toString() + "%", col);
+            }
+        } else {
+            // if we can't use LIKE, we have to take the substring of the
+            // first value and compare it to the second
+            DBDictionary dict = store.getDBDictionary();
+            dict.assertSupport(_pre != null, "StringLengthFunction");
+            dict.substring(buf,
+                new FilterValueImpl(_val1, sel, store, params, fetchState),
+                new ZeroFilterValue(sel),
+                new StringLengthFilterValue(sel, store, params, fetchState));
+            buf.append(" = ");
+            _val2.appendTo(buf, 0, sel, store, params, fetchState);
+        }
+
+        sel.append(buf, _joins);
+        _val1.clearParameters();
+        _val2.clearParameters();
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        _val1.selectColumns(sel, store, params, true, fetchState);
+        _val2.selectColumns(sel, store, params, true, fetchState);
+    }
+
+    public Joins getJoins() {
+        return _joins;
+    }
+
+    public boolean hasContainsExpression() {
+        return false;
+    }
+
+    public boolean hasVariable(Variable var) {
+        return _val1.hasVariable(var) || _val2.hasVariable(var);
+    }
+
+    /**
+     * Evaluates to 0.
+     */
+    private class ZeroFilterValue
+        implements FilterValue {
+
+        private final Select _sel;
+
+        public ZeroFilterValue(Select sel) {
+            _sel = sel;
+        }
+
+        public Class getType() {
+            return int.class;
+        }
+
+        public int length() {
+            return 1;
+        }
+
+        public void appendTo(SQLBuffer buf) {
+            appendTo(buf, 0);
+        }
+
+        public void appendTo(SQLBuffer buf, int index) {
+            buf.appendValue(0);
+        }
+
+        public String getColumnAlias(Column col) {
+            return _sel.getColumnAlias(col, _joins);
+        }
+
+        public String getColumnAlias(String col, Table table) {
+            return _sel.getColumnAlias(col, table, _joins);
+        }
+
+        public Object toDataStoreValue(Object val) {
+            return val;
+        }
+
+        public boolean isConstant() {
+            return true;
+        }
+
+        public Object getValue() {
+            return Numbers.valueOf(0);
+        }
+
+        public Object getSQLValue() {
+            return Numbers.valueOf(0);
+        }
+
+        public boolean isPath() {
+            return false;
+        }
+
+        public ClassMapping getClassMapping() {
+            return null;
+        }
+
+        public FieldMapping getFieldMapping() {
+            return null;
+        }
+    }
+
+    /**
+     * Evaluates to the length of a given value.
+     */
+    private class StringLengthFilterValue
+        implements FilterValue {
+
+        private final Select _sel;
+        private final JDBCStore _store;
+        private final Object[] _params;
+        private final JDBCFetchState _fetchState;
+
+        public StringLengthFilterValue(Select sel, JDBCStore store,
+            Object[] params, JDBCFetchState fetchState) {
+            _sel = sel;
+            _store = store;
+            _params = params;
+            _fetchState = fetchState;
+        }
+
+        public Class getType() {
+            return int.class;
+        }
+
+        public int length() {
+            return 1;
+        }
+
+        public void appendTo(SQLBuffer buf) {
+            appendTo(buf, 0);
+        }
+
+        public void appendTo(SQLBuffer buf, int index) {
+            buf.append(_pre);
+            _val2.appendTo(buf, index, _sel, _store, _params, _fetchState);
+            buf.append(_post);
+        }
+
+        public String getColumnAlias(Column col) {
+            return _sel.getColumnAlias(col, _val2.getJoins());
+        }
+
+        public String getColumnAlias(String col, Table table) {
+            return _sel.getColumnAlias(col, table, _val2.getJoins());
+        }
+
+        public Object toDataStoreValue(Object val) {
+            return _val2.toDataStoreValue(val, _store);
+        }
+
+        public boolean isConstant() {
+            return false;
+        }
+
+        public Object getValue() {
+            return null;
+        }
+
+        public Object getSQLValue() {
+            return null;
+        }
+
+        public boolean isPath() {
+            return false;
+        }
+
+        public ClassMapping getClassMapping() {
+            return null;
+        }
+
+        public FieldMapping getFieldMapping() {
+            return null;
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringFunction.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringFunction.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringFunction.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringFunction.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+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;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * A JDBC string function.
+ *
+ * @author Marc Prud'hommeaux
+ */
+abstract class StringFunction
+    extends AbstractVal
+    implements Val {
+
+    final Val _val;
+    ClassMetaData _meta = null;
+    String _pre = null;
+    String _post = null;
+
+    /**
+     * Constructor. Provide the string to operate on.
+     */
+    public StringFunction(Val val) {
+        _val = val;
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+
+    public boolean isVariable() {
+        return false;
+    }
+
+    public Class getType() {
+        return String.class;
+    }
+
+    public void setImplicitType(Class type) {
+    }
+
+    public Joins getJoins() {
+        return _val.getJoins();
+    }
+
+    public Object toDataStoreValue(Object val, JDBCStore store) {
+        return val;
+    }
+
+    public void select(Select sel, JDBCStore store, Object[] params,
+        boolean pks, JDBCFetchState fetchState) {
+        sel.select(newSQLBuffer(sel, store, params, fetchState), this);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        _val.selectColumns(sel, store, params, true, fetchState);
+    }
+
+    public void groupBy(Select sel, JDBCStore store, Object[] params,
+        JDBCFetchState fetchState) {
+        sel.groupBy(newSQLBuffer(sel, store, params, fetchState), false);
+    }
+
+    public void orderBy(Select sel, JDBCStore store, Object[] params,
+        boolean asc, JDBCFetchState fetchState) {
+        sel.orderBy(newSQLBuffer(sel, store, params, fetchState), asc, false);
+    }
+
+    private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        calculateValue(sel, store, params, null, fetchState);
+        SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
+        appendTo(buf, 0, sel, store, params, fetchState);
+        clearParameters();
+        return buf;
+    }
+
+    public Object load(Result res, JDBCStore store,
+        JDBCFetchState fetchState)
+        throws SQLException {
+        return Filters.convert(res.getObject(this,
+            JavaSQLTypes.JDBC_DEFAULT, null), getType());
+    }
+
+    public boolean hasVariable(Variable var) {
+        return _val.hasVariable(var);
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchState fetchState) {
+        _val.calculateValue(sel, store, params, null, fetchState);
+    }
+
+    public void clearParameters() {
+        _val.clearParameters();
+    }
+
+    public int length() {
+        return 1;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        sql.append(_pre);
+        _val.appendTo(sql, 0, sel, store, params, fetchState);
+        sql.append(_post);
+    }
+}
+

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringFunction.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringLength.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringLength.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringLength.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringLength.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Returns the number of characters in a string.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class StringLength
+    extends StringFunction {
+
+    private Class _cast = null;
+
+    /**
+     * Constructor. Provide the string to operate on.
+     */
+    public StringLength(Val val) {
+        super(val);
+    }
+
+    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+        _val.initialize(sel, store, false);
+
+        DBDictionary dict = store.getConfiguration().getDBDictionaryInstance();
+        String func = dict.stringLengthFunction;
+        dict.assertSupport(func != null, "StringLengthFunction");
+
+        int idx = func.indexOf("{0}");
+        _pre = func.substring(0, idx);
+        _post = func.substring(idx + 3);
+    }
+
+    public Class getType() {
+        if (_cast != null)
+            return _cast;
+        return int.class;
+    }
+
+    public void setImplicitType(Class type) {
+        _cast = type;
+    }
+}
+

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StringLength.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,238 @@
+/*
+ * 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;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+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;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.exps.QueryExpressions;
+import org.apache.openjpa.kernel.exps.Subquery;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * A subquery.
+ *
+ * @author Abe White
+ */
+class SubQ
+    implements Val, Subquery {
+
+    private final ClassMapping _candidate;
+    private final boolean _subs;
+    private final String _alias;
+    private final SelectConstructor _cons = new SelectConstructor();
+
+    private Class _type = null;
+    private ClassMetaData _meta = null;
+    private QueryExpressions _exps = null;
+    private long _startIdx = 0;
+    private long _endIdx = Long.MAX_VALUE;
+
+    /**
+     * Constructor. Supply candidate, whether subclasses are included in
+     * the query, and the query alias.
+     */
+    public SubQ(ClassMapping candidate, boolean subs, String alias) {
+        _candidate = candidate;
+        _subs = subs;
+        _alias = alias;
+    }
+
+    /**
+     * Return the subquery candidate type.
+     */
+    public ClassMapping getCandidate() {
+        return _candidate;
+    }
+
+    public Class getType() {
+        if (_exps != null) {
+            if (_exps.projections.length == 0)
+                return _candidate.getDescribedType();
+            if (_exps.projections.length == 1)
+                return _exps.projections[0].getType();
+        }
+        return _type;
+    }
+
+    public void setImplicitType(Class type) {
+        if (_exps != null && _exps.projections.length == 1)
+            _exps.projections[0].setImplicitType(type);
+        _type = type;
+    }
+
+    public boolean isVariable() {
+        return false;
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+
+    public String getCandidateAlias() {
+        return _alias;
+    }
+
+    public void setQueryExpressions(QueryExpressions query, long startIdx,
+        long endIdx) {
+        _exps = query;
+        _startIdx = startIdx;
+        _endIdx = endIdx;
+    }
+
+    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+    }
+
+    public Joins getJoins() {
+        return null;
+    }
+
+    public Object toDataStoreValue(Object val, JDBCStore store) {
+        if (_exps.projections.length == 0)
+            return _candidate.toDataStoreValue(val,
+                _candidate.getPrimaryKeyColumns(), store);
+        if (_exps.projections.length == 1)
+            return ((Val) _exps.projections[0]).toDataStoreValue(val, store);
+        return val;
+    }
+
+    public void select(Select sel, JDBCStore store, Object[] params,
+        boolean pks, JDBCFetchState fetchState) {
+        selectColumns(sel, store, params, pks, fetchState);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        sel.select(newSQLBuffer(sel, store, params, fetchState), this);
+    }
+
+    public void groupBy(Select sel, JDBCStore store, Object[] params,
+        JDBCFetchState fetchState) {
+        sel.groupBy(newSQLBuffer(sel, store, params, fetchState), false);
+    }
+
+    public void orderBy(Select sel, JDBCStore store, Object[] params,
+        boolean asc, JDBCFetchState fetchState) {
+        sel.orderBy(newSQLBuffer(sel, store, params, fetchState), asc, false);
+    }
+
+    private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
+        appendTo(buf, 0, sel, store, params, fetchState);
+        return buf;
+    }
+
+    public Object load(Result res, JDBCStore store,
+        JDBCFetchState fetchState)
+        throws SQLException {
+        return Filters.convert(res.getObject(this,
+            JavaSQLTypes.JDBC_DEFAULT, null), getType());
+    }
+
+    public boolean hasVariable(Variable var) {
+        for (int i = 0; i < _exps.projections.length; i++)
+            if (((Val) _exps.projections[i]).hasVariable(var))
+                return true;
+        if (_exps.filter != null)
+            if (((Exp) _exps.filter).hasVariable(var))
+                return true;
+        for (int i = 0; i < _exps.grouping.length; i++)
+            if (((Val) _exps.grouping[i]).hasVariable(var))
+                return true;
+        if (_exps.having != null)
+            if (((Exp) _exps.having).hasVariable(var))
+                return true;
+        for (int i = 0; i < _exps.ordering.length; i++)
+            if (((Val) _exps.ordering[i]).hasVariable(var))
+                return true;
+        return false;
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchState fetchState) {
+    }
+
+    public void clearParameters() {
+    }
+
+    public int length() {
+        return 1;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        appendTo(sql, index, sel, store, params, fetchState, false);
+    }
+
+    private void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState,
+        boolean size) {
+        JDBCFetchConfiguration fetch = fetchState.getJDBCFetchConfiguration();
+        sel = _cons.evaluate(store, sel, _alias, _exps, params,
+            _cons.CACHE_NULL, fetchState);
+        _cons.select(store, _candidate, _subs, sel, _exps, params,
+            fetchState, fetch.EAGER_NONE);
+        sel.setRange(_startIdx, _endIdx);
+
+        if (size)
+            sql.appendCount(sel, fetch);
+        else
+            sql.append(sel, fetch);
+    }
+
+    public void appendIsEmpty(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        sql.append("NOT EXISTS ");
+        appendTo(sql, 0, sel, store, params, fetchState);
+    }
+
+    public void appendIsNotEmpty(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        sql.append("EXISTS ");
+        appendTo(sql, 0, sel, store, params, fetchState);
+    }
+
+    public void appendSize(SQLBuffer sql, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        appendTo(sql, 0, sel, store, params, fetchState, true);
+    }
+
+    public void appendIsNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        appendTo(sql, 0, sel, store, params, fetchState);
+        sql.append(" IS NULL");
+    }
+
+    public void appendIsNotNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        appendTo(sql, 0, sel, store, params, fetchState);
+        sql.append(" IS NOT NULL");
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Substring.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Substring.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Substring.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Substring.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,158 @@
+/*
+ * 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;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+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;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * Take a substring of a string.
+ *
+ * @author Abe White
+ */
+class Substring
+    extends AbstractVal
+    implements Val {
+
+    private final Val _val1;
+    private final Val _val2;
+    private Joins _joins = null;
+    private ClassMetaData _meta = null;
+
+    /**
+     * Constructor. Provide the strings to operate on.
+     */
+    public Substring(Val val1, Val val2) {
+        _val1 = val1;
+        _val2 = val2;
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+
+    public boolean isVariable() {
+        return false;
+    }
+
+    public Class getType() {
+        return String.class;
+    }
+
+    public void setImplicitType(Class 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 Object toDataStoreValue(Object val, JDBCStore store) {
+        return val;
+    }
+
+    public void select(Select sel, JDBCStore store, Object[] params,
+        boolean pks, JDBCFetchState fetchState) {
+        sel.select(newSQLBuffer(sel, store, params, fetchState), this);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        _val1.selectColumns(sel, store, params, true, fetchState);
+        _val2.selectColumns(sel, store, params, true, fetchState);
+    }
+
+    public void groupBy(Select sel, JDBCStore store, Object[] params,
+        JDBCFetchState fetchState) {
+        sel.groupBy(newSQLBuffer(sel, store, params, fetchState), false);
+    }
+
+    public void orderBy(Select sel, JDBCStore store, Object[] params,
+        boolean asc, JDBCFetchState fetchState) {
+        sel.orderBy(newSQLBuffer(sel, store, params, fetchState), asc, false);
+    }
+
+    private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        calculateValue(sel, store, params, null, fetchState);
+        SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
+        appendTo(buf, 0, sel, store, params, fetchState);
+        clearParameters();
+        return buf;
+    }
+
+    public Object load(Result res, JDBCStore store,
+        JDBCFetchState fetchState)
+        throws SQLException {
+        return Filters.convert(res.getObject(this,
+            JavaSQLTypes.JDBC_DEFAULT, null), getType());
+    }
+
+    public boolean hasVariable(Variable var) {
+        return _val1.hasVariable(var) || _val2.hasVariable(var);
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchState fetchState) {
+        _val1.calculateValue(sel, store, params, null, fetchState);
+        _val2.calculateValue(sel, store, params, null, fetchState);
+    }
+
+    public void clearParameters() {
+        _val1.clearParameters();
+        _val2.clearParameters();
+    }
+
+    public int length() {
+        return 1;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        FilterValue str = new FilterValueImpl(_val1, sel, store, params,
+            fetchState);
+        FilterValue start;
+        FilterValue end = null;
+        if (_val2 instanceof Args) {
+            Val[] args = ((Args) _val2).getVals();
+            start =
+                new FilterValueImpl(args[0], sel, store, params, fetchState);
+            end = new FilterValueImpl(args[1], sel, store, params, fetchState);
+        } else
+            start = new FilterValueImpl(_val2, sel, store, params, fetchState);
+
+        store.getDBDictionary().substring(sql, str, start, end);
+    }
+}
+

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Substring.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sum.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sum.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sum.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sum.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Sum.
+ *
+ * @author Abe White
+ */
+class Sum
+    extends UnaryOp {
+
+    /**
+     * Constructor. Provide the value to operate on.
+     */
+    public Sum(Val val) {
+        super(val);
+    }
+
+    protected Class getType(Class c) {
+        Class wrap = Filters.wrap(c);
+        if (wrap == Integer.class
+            || wrap == Short.class
+            || wrap == Byte.class)
+            return long.class;
+        return c;
+    }
+
+    protected String getOperator() {
+        return "SUM";
+    }
+
+    protected boolean isAggregate() {
+        return true;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sum.java
------------------------------------------------------------------------------
    svn:executable = *