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 [6/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/SelectResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SelectResultObjectProvider.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SelectResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/SelectResultObjectProvider.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,166 @@
+/*
+ * 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;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.SelectExecutor;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+import org.apache.openjpa.util.StoreException;
+
+/**
+ * Abstract provider implementation wrapped around a {@link Select}.
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public abstract class SelectResultObjectProvider
+    implements ResultObjectProvider {
+
+    private final SelectExecutor _sel;
+    private final JDBCStore _store;
+    private final JDBCFetchConfiguration _fetch;
+    private final JDBCFetchState _fetchState;
+    private Result _res = null;
+    private int _size = -1;
+    private Boolean _ra = null;
+
+    /**
+     * Constructor.
+     *
+     * @param sel the select to execute
+     * @param store the store to delegate loading to
+     * @param fetch the fetch configuration, or null for the default
+     */
+    public SelectResultObjectProvider(SelectExecutor sel, JDBCStore store,
+        JDBCFetchState fetchState) {
+        _sel = sel;
+        _store = store;
+//		if (fetch == null)
+//			_fetch = store.getFetchConfiguration ();
+//		else
+//			_fetch = fetch;
+        _fetchState = fetchState;
+        _fetch = fetchState.getJDBCFetchConfiguration();
+    }
+
+    public SelectExecutor getSelect() {
+        return _sel;
+    }
+
+    public JDBCStore getStore() {
+        return _store;
+    }
+
+    public JDBCFetchConfiguration getFetchConfiguration() {
+        return _fetch;
+    }
+
+    public JDBCFetchState getFetchState() {
+        return _fetchState;
+    }
+
+    public Result getResult() {
+        return _res;
+    }
+
+    public boolean supportsRandomAccess() {
+        if (_ra == null) {
+            boolean ra;
+            if (_res != null) {
+                try {
+                    ra = _res.supportsRandomAccess();
+                } catch (SQLException se) {
+                    throw SQLExceptions.getStore(se, _store.getDBDictionary());
+                }
+            } else
+                ra = _sel.supportsRandomAccess(_fetch.getReadLockLevel() > 0);
+            _ra = (ra) ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return _ra.booleanValue();
+    }
+
+    public void open()
+        throws SQLException {
+        _res = _sel.execute(_store, _fetch);
+    }
+
+    public boolean next()
+        throws SQLException {
+        return _res.next();
+    }
+
+    public boolean absolute(int pos)
+        throws SQLException {
+        return _res.absolute(pos);
+    }
+
+    public int size()
+        throws SQLException {
+        if (_size == -1) {
+            // if res is null, don't cache size
+            if (_res == null)
+                return Integer.MAX_VALUE;
+
+            switch (_fetch.getLRSSize()) {
+                case LRSSizes.SIZE_UNKNOWN:
+                    _size = Integer.MAX_VALUE;
+                    break;
+                case LRSSizes.SIZE_LAST:
+                    if (supportsRandomAccess())
+                        _size = _res.size();
+                    else
+                        _size = Integer.MAX_VALUE;
+                    break;
+                default: // query
+                    _size = _sel.getCount(_store);
+            }
+        }
+        return _size;
+    }
+
+    /**
+     * Allow subclasses that know the size to set it; otherwise we calculate
+     * it internally.
+     */
+    protected void setSize(int size) {
+        if (_size == -1)
+            _size = size;
+    }
+
+    public void reset()
+        throws SQLException {
+        close();
+        open();
+    }
+
+    public void close() {
+        if (_res != null) {
+            _res.close();
+            _res = null;
+        }
+    }
+
+    public void handleCheckedException(Exception e) {
+        if (e instanceof SQLException)
+            throw SQLExceptions.getStore((SQLException) e,
+                _store.getDBDictionary());
+        throw new StoreException(e);
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,625 @@
+/*
+ * 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;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.PrimaryKey;
+import org.apache.openjpa.jdbc.schema.Schema;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.schema.SchemaTool;
+import org.apache.openjpa.jdbc.schema.Schemas;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.Options;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.InvalidStateException;
+import serp.util.Numbers;
+import serp.util.Strings;
+
+////////////////////////////////////////////////////////////
+// NOTE: Do not change property names; see SequenceMetaData
+// and SequenceMapping for standard property names.
+////////////////////////////////////////////////////////////
+
+/**
+ * {@link JDBCSeq} implementation that uses a database table
+ * for sequence number generation. This base implementation uses a single
+ * row for a global sequence number.
+ *
+ * @author Abe White
+ */
+public class TableJDBCSeq
+    extends AbstractJDBCSeq
+    implements Configurable {
+
+    public static final String ACTION_DROP = "drop";
+    public static final String ACTION_ADD = "add";
+    public static final String ACTION_GET = "get";
+    public static final String ACTION_SET = "set";
+
+    private static final Localizer _loc = Localizer.forPackage
+        (TableJDBCSeq.class);
+
+    private JDBCConfiguration _conf = null;
+    private Log _log = null;
+    private int _alloc = 50;
+    private final Status _stat = new Status();
+
+    private String _table = "OPENJPA_SEQUENCE_TABLE";
+    private String _seqColumnName = "SEQUENCE_VALUE";
+    private String _pkColumnName = "ID";
+
+    private Column _seqColumn = null;
+    private Column _pkColumn = null;
+
+    /**
+     * The sequence table name. Defaults to <code>OPENJPA_SEQUENCE_TABLE</code>.
+     * By default, the table will be placed in the first schema listed in your
+     * <code>org.apache.openjpa.jdbc.Schemas</code> property, or in the default schema if
+     * the property is not given. If you specify a table name in the form
+     * <code>&lt;schema&gt;.&lt;table&gt;</code>, then the given schema
+     * will be used.
+     */
+    public String getTable() {
+        return _table;
+    }
+
+    /**
+     * The sequence table name. Defaults to <code>OPENJPA_SEQUENCE_TABLE</code>.
+     * By default, the table will be placed in the first schema listed in your
+     * <code>org.apache.openjpa.jdbc.Schemas</code> property, or in the default schema if
+     * the property is not given. If you specify a table name in the form
+     * <code>&lt;schema&gt;.&lt;table&gt;</code>, then the given schema
+     * will be used.
+     */
+    public void setTable(String name) {
+        _table = name;
+    }
+
+    /**
+     * @deprecated Use {@link #setTable}. Retained for
+     * backwards-compatibility	with auto-configuration.
+     */
+    public void setTableName(String name) {
+        setTable(name);
+    }
+
+    /**
+     * The name of the column that holds the sequence value. Defaults
+     * to <code>SEQUENCE_VALUE</code>.
+     */
+    public String getSequenceColumn() {
+        return _seqColumnName;
+    }
+
+    /**
+     * The name of the column that holds the sequence value. Defaults
+     * to <code>SEQUENCE_VALUE</code>.
+     */
+    public void setSequenceColumn(String sequenceColumn) {
+        _seqColumnName = sequenceColumn;
+    }
+
+    /**
+     * The name of the table's primary key column. Defaults to
+     * <code>ID</code>.
+     */
+    public String getPrimaryKeyColumn() {
+        return _pkColumnName;
+    }
+
+    /**
+     * The name of the table's primary key column. Defaults to
+     * <code>ID</code>.
+     */
+    public void setPrimaryKeyColumn(String primaryKeyColumn) {
+        _pkColumnName = primaryKeyColumn;
+    }
+
+    /**
+     * Return the number of sequences to allocate for each update of the
+     * sequence table. Sequence numbers will be grabbed in blocks of this
+     * value to reduce the number of transactions that must be performed on
+     * the sequence table.
+     */
+    public int getAllocate() {
+        return _alloc;
+    }
+
+    /**
+     * Return the number of sequences to allocate for each update of the
+     * sequence table. Sequence numbers will be grabbed in blocks of this
+     * value to reduce the number of transactions that must be performed on
+     * the sequence table.
+     */
+    public void setAllocate(int alloc) {
+        _alloc = alloc;
+    }
+
+    /**
+     * @deprecated Use {@link #setAllocate}. Retained for backwards
+     * compatibility of auto-configuration.
+     */
+    public void setIncrement(int inc) {
+        setAllocate(inc);
+    }
+
+    public JDBCConfiguration getConfiguration() {
+        return _conf;
+    }
+
+    public void setConfiguration(Configuration conf) {
+        _conf = (JDBCConfiguration) conf;
+        _log = _conf.getLog(JDBCConfiguration.LOG_RUNTIME);
+    }
+
+    public void startConfiguration() {
+    }
+
+    public void endConfiguration() {
+        buildTable();
+    }
+
+    public void addSchema(ClassMapping mapping, SchemaGroup group) {
+        // table already exists?
+        if (group.isKnownTable(_table))
+            return;
+
+        String schemaName = Strings.getPackageName(_table);
+        if (schemaName.length() == 0)
+            schemaName = Schemas.getNewTableSchema(_conf);
+
+        // create table in this group
+        Schema schema = group.getSchema(schemaName);
+        if (schema == null)
+            schema = group.addSchema(schemaName);
+        schema.importTable(_pkColumn.getTable());
+    }
+
+    protected Object nextInternal(JDBCStore store, ClassMapping mapping)
+        throws Exception {
+        // if needed, grab the next handful of ids
+        Status stat = getStatus(mapping);
+        if (stat == null)
+            throw new InvalidStateException(_loc.get("bad-seq-type",
+                getClass(), mapping));
+
+        // make sure seq is at least 1, since autoassigned ids of 0 can
+        // conflict with uninitialized values
+        stat.seq = Math.max(stat.seq, 1);
+        if (stat.seq >= stat.max)
+            allocateSequence(store, mapping, stat, _alloc, true);
+        return Numbers.valueOf(stat.seq++);
+    }
+
+    protected Object currentInternal(JDBCStore store, ClassMapping mapping)
+        throws Exception {
+        if (current == null) {
+            long cur = getSequence(mapping, getConnection(store));
+            if (cur != -1)
+                current = Numbers.valueOf(cur);
+        }
+        return super.currentInternal(store, mapping);
+    }
+
+    protected void allocateInternal(int count, JDBCStore store,
+        ClassMapping mapping)
+        throws SQLException {
+        Status stat = getStatus(mapping);
+        if (stat != null && stat.max - stat.seq < count)
+            allocateSequence(store, mapping, stat,
+                count - (int) (stat.max - stat.seq), false);
+    }
+
+    /**
+     * Return the appropriate status object for the given class, or null
+     * if cannot handle the given class. The mapping may be null.
+     */
+    protected Status getStatus(ClassMapping mapping) {
+        return _stat;
+    }
+
+    /**
+     * Add the primary key column to the given table and return it.
+     */
+    protected Column addPrimaryKeyColumn(Table table) {
+        DBDictionary dict = _conf.getDBDictionaryInstance();
+        Column pkColumn = table.addColumn(dict.getValidColumnName
+            (getPrimaryKeyColumn(), table));
+        pkColumn.setType(dict.getPreferredType(Types.TINYINT));
+        pkColumn.setJavaType(JavaTypes.INT);
+        return pkColumn;
+    }
+
+    /**
+     * Return the primary key value for the given class.
+     */
+    protected Object getPrimaryKey(ClassMapping mapping) {
+        return Numbers.valueOf(0);
+    }
+
+    /**
+     * Creates the object-level representation of the sequence table.
+     */
+    private void buildTable() {
+        String tableName = Strings.getClassName(_table);
+        String schemaName = Strings.getPackageName(_table);
+        if (schemaName.length() == 0)
+            schemaName = Schemas.getNewTableSchema(_conf);
+
+        SchemaGroup group = new SchemaGroup();
+        Schema schema = group.addSchema(schemaName);
+
+        Table table = schema.addTable(tableName);
+        _pkColumn = addPrimaryKeyColumn(table);
+        PrimaryKey pk = table.addPrimaryKey();
+        pk.addColumn(_pkColumn);
+
+        DBDictionary dict = _conf.getDBDictionaryInstance();
+        _seqColumn = table.addColumn(dict.getValidColumnName
+            (_seqColumnName, table));
+        _seqColumn.setType(dict.getPreferredType(Types.BIGINT));
+        _seqColumn.setJavaType(JavaTypes.LONG);
+    }
+
+    /**
+     * Updates the max available sequence value.
+     */
+    private void allocateSequence(JDBCStore store, ClassMapping mapping,
+        Status stat, int alloc, boolean updateStatSeq) {
+        try {
+            // if the update fails, probably because row doesn't exist yet
+            if (!setSequence(mapping, stat, alloc, updateStatSeq,
+                getConnection(store))) {
+                closeConnection();
+
+                // possible that we might get errors when inserting if
+                // another thread/process is inserting same pk at same time
+                SQLException err = null;
+                Connection conn = _conf.getDataSource2(store.getContext()).
+                    getConnection();
+                try {
+                    insertSequence(mapping, conn);
+                } catch (SQLException se) {
+                    err = se;
+                } finally {
+                    try {
+                        conn.close();
+                    } catch (SQLException se) {
+                    }
+                }
+
+                // now we should be able to update...
+                if (!setSequence(mapping, stat, alloc, updateStatSeq,
+                    getConnection(store)))
+                    throw(err != null) ? err : new SQLException(_loc.get
+                        ("no-seq-row", mapping, _table));
+            }
+        }
+        catch (SQLException se2) {
+            throw SQLExceptions.getStore(_loc.get("bad-seq-up", _table),
+                se2, _conf.getDBDictionaryInstance());
+        }
+    }
+
+    /**
+     * Inserts the initial sequence information into the database, if any.
+     */
+    private void insertSequence(ClassMapping mapping, Connection conn)
+        throws SQLException {
+        if (_log.isTraceEnabled())
+            _log.trace(_loc.get("insert-seq"));
+
+        Object pk = getPrimaryKey(mapping);
+        if (pk == null)
+            throw new InvalidStateException(_loc.get("bad-seq-type",
+                getClass(), mapping));
+
+        DBDictionary dict = _conf.getDBDictionaryInstance();
+        SQLBuffer insert = new SQLBuffer(dict).append("INSERT INTO ").
+            append(_pkColumn.getTable()).append(" (").
+            append(_pkColumn).append(", ").append(_seqColumn).
+            append(") VALUES (").
+            appendValue(pk, _pkColumn).append(", ").
+            appendValue(Numbers.valueOf(1), _seqColumn).append(")");
+
+        boolean wasAuto = conn.getAutoCommit();
+        if (!wasAuto)
+            conn.setAutoCommit(true);
+
+        PreparedStatement stmnt = null;
+        try {
+            stmnt = insert.prepareStatement(conn);
+            stmnt.executeUpdate();
+        } finally {
+            if (stmnt != null)
+                try {
+                    stmnt.close();
+                } catch (SQLException se) {
+                }
+            if (!wasAuto)
+                conn.setAutoCommit(false);
+        }
+    }
+
+    /**
+     * Return the current sequence value, or -1 if unattainable.
+     */
+    protected long getSequence(ClassMapping mapping, Connection conn)
+        throws SQLException {
+        if (_log.isTraceEnabled())
+            _log.trace(_loc.get("get-seq"));
+
+        Object pk = getPrimaryKey(mapping);
+        if (pk == null)
+            return -1;
+
+        DBDictionary dict = _conf.getDBDictionaryInstance();
+        SQLBuffer sel = new SQLBuffer(dict).append(_seqColumn);
+        SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(" = ").
+            appendValue(pk, _pkColumn);
+        SQLBuffer tables = new SQLBuffer(dict).append(_seqColumn.getTable());
+
+        SQLBuffer select = dict.toSelect(sel, null, tables, where, null,
+            null, null, false, dict.supportsSelectForUpdate, 0, Long.MAX_VALUE);
+
+        PreparedStatement stmnt = select.prepareStatement(conn);
+        ResultSet rs = null;
+        try {
+            rs = stmnt.executeQuery();
+            if (!rs.next())
+                return -1;
+            return dict.getLong(rs, 1);
+        } finally {
+            if (rs != null)
+                try {
+                    rs.close();
+                } catch (SQLException se) {
+                }
+            try {
+                stmnt.close();
+            } catch (SQLException se) {
+            }
+        }
+    }
+
+    /**
+     * Grabs the next handful of sequence numbers.
+     *
+     * @return true if the sequence was updated, false if no sequence
+     * row existed for this mapping
+     */
+    protected boolean setSequence(ClassMapping mapping, Status stat, int inc,
+        boolean updateStatSeq, Connection conn)
+        throws SQLException {
+        if (_log.isTraceEnabled())
+            _log.trace(_loc.get("update-seq"));
+
+        Object pk = getPrimaryKey(mapping);
+        if (pk == null)
+            throw new InvalidStateException(_loc.get("bad-seq-type",
+                getClass(), mapping));
+
+        DBDictionary dict = _conf.getDBDictionaryInstance();
+        SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(" = ").
+            appendValue(pk, _pkColumn);
+
+        // not all databases support locking, so loop until we have a
+        // successful atomic select/update sequence
+        long cur = 0;
+        PreparedStatement stmnt;
+        ResultSet rs;
+        SQLBuffer upd;
+        for (int updates = 0; updates == 0;) {
+            stmnt = null;
+            rs = null;
+            try {
+                cur = getSequence(mapping, conn);
+                if (cur == -1)
+                    return false;
+
+                // update the value
+                upd = new SQLBuffer(dict);
+                upd.append("UPDATE ").append(_seqColumn.getTable()).
+                    append(" SET ").append(_seqColumn).append(" = ").
+                    appendValue(Numbers.valueOf(cur + inc), _seqColumn).
+                    append(" WHERE ").append(where).append(" AND ").
+                    append(_seqColumn).append(" = ").
+                    appendValue(Numbers.valueOf(cur), _seqColumn);
+
+                stmnt = upd.prepareStatement(conn);
+                updates = stmnt.executeUpdate();
+            } finally {
+                if (rs != null)
+                    try {
+                        rs.close();
+                    } catch (SQLException se) {
+                    }
+                if (stmnt != null)
+                    try {
+                        stmnt.close();
+                    } catch (SQLException se) {
+                    }
+            }
+        }
+
+        // setup new sequence range
+        if (updateStatSeq)
+            stat.seq = cur;
+        stat.max = cur + inc;
+        return true;
+    }
+
+    /**
+     * Creates the sequence table in the DB.
+     */
+    public void refreshTable()
+        throws SQLException {
+        if (_log.isInfoEnabled())
+            _log.info(_loc.get("make-seq-table"));
+
+        // create the table
+        SchemaTool tool = new SchemaTool(_conf);
+        tool.setIgnoreErrors(true);
+        tool.createTable(_pkColumn.getTable());
+    }
+
+    /**
+     * Drops the sequence table in the DB.
+     */
+    public void dropTable()
+        throws SQLException {
+        if (_log.isInfoEnabled())
+            _log.info(_loc.get("drop-seq-table"));
+
+        // drop the table
+        SchemaTool tool = new SchemaTool(_conf);
+        tool.setIgnoreErrors(true);
+        tool.dropTable(_pkColumn.getTable());
+    }
+
+    /////////
+    // Main
+    /////////
+
+    /**
+     * Usage: java org.apache.openjpa.jdbc.schema.TableJDBCSequence [option]*
+     * -action/-a &lt;add | drop | get | set&gt; [value]
+     *  Where the following options are recognized.
+     * <ul>
+     * <li><i>-properties/-p &lt;properties file or resource&gt;</i>: The
+     * path or resource name of a OpenJPA properties file containing
+     * information such as the license key	and connection data as
+     * outlined in {@link JDBCConfiguration}. Optional.</li>
+     * <li><i>-&lt;property name&gt; &lt;property value&gt;</i>: All bean
+     * properties of the OpenJPA {@link JDBCConfiguration} can be set by
+     * using their	names and supplying a value. For example:
+     * <code>-licenseKey adslfja83r3lkadf</code></li>
+     * </ul>
+     *  The various actions are as follows.
+     * <ul>
+     * <li><i>add</i>: Create the sequence table.</li>
+     * <li><i>drop</i>: Drop the sequence table.</li>
+     * <li><i>get</i>: Print the current sequence value.</li>
+     * <li><i>set</i>: Set the sequence value.</li>
+     * </ul>
+     */
+    public static void main(String[] args)
+        throws Exception {
+        Options opts = new Options();
+        args = opts.setFromCmdLine(args);
+        JDBCConfiguration conf = new JDBCConfigurationImpl();
+        try {
+            if (!run(conf, args, opts))
+                System.out.println(_loc.get("seq-usage"));
+        } finally {
+            conf.close();
+        }
+    }
+
+    /**
+     * Run the tool. Returns false if invalid options were given.
+     */
+    public static boolean run(JDBCConfiguration conf, String[] args,
+        Options opts)
+        throws Exception {
+        if (opts.containsKey("help") || opts.containsKey("-help"))
+            return false;
+
+        String action = opts.removeProperty("action", "a", null);
+        Configurations.populateConfiguration(conf, opts);
+        return run(conf, args, action);
+    }
+
+    /**
+     * Run the tool. Return false if an invalid option was given.
+     */
+    public static boolean run(JDBCConfiguration conf, String[] args,
+        String action)
+        throws Exception {
+        if (args.length > 1 || (args.length != 0
+            && !ACTION_SET.equals(action)))
+            return false;
+
+        TableJDBCSeq seq = new TableJDBCSeq();
+        String props = Configurations.getProperties(conf.getSequence());
+        Configurations.configureInstance(seq, conf, props);
+
+        if (ACTION_DROP.equals(action))
+            seq.dropTable();
+        else if (ACTION_ADD.equals(action))
+            seq.refreshTable();
+        else if (ACTION_GET.equals(action) || ACTION_SET.equals(action)) {
+            Connection conn = conf.getDataSource2(null).getConnection();
+            try {
+                long cur = seq.getSequence(null, conn);
+                if (ACTION_GET.equals(action))
+                    System.out.println(cur);
+                else {
+                    long set;
+                    if (args.length > 0)
+                        set = Long.parseLong(args[0]);
+                    else
+                        set = cur + seq.getAllocate();
+                    if (set < cur)
+                        set = cur;
+                    else {
+                        Status stat = seq.getStatus(null);
+                        seq.setSequence(null, stat, (int) (set - cur), true,
+                            conn);
+                        set = stat.seq;
+                    }
+                    System.err.println(set);
+                }
+            }
+            catch (NumberFormatException nfe) {
+                return false;
+            } finally {
+                try {
+                    conn.close();
+                } catch (SQLException se) {
+                }
+            }
+        } else
+            return false;
+        return true;
+    }
+
+    /**
+     * Helper struct to hold status information.
+     */
+    protected static class Status {
+
+        public long seq = 1L;
+        public long max = 0L;
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/UpdateManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/UpdateManager.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/UpdateManager.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/UpdateManager.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import java.util.Collection;
+
+/**
+ * This interface is used to customize the way that updates are made to
+ * database records.
+ *
+ * @author Abe White
+ */
+public interface UpdateManager {
+
+    /**
+     * Whether the store context should maintain the order in which instances
+     * are dirtied.
+     */
+    public boolean orderDirty();
+
+    /**
+     * Flush the given instances to the data store.
+     *
+     * @see org.apache.openjpa.kernel.StoreManager#flush
+     */
+    public Collection flush(Collection states, JDBCStore store);
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ValueTableJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ValueTableJDBCSeq.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ValueTableJDBCSeq.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ValueTableJDBCSeq.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,200 @@
+/*
+ * 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;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.MappingRepository;
+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.lib.conf.Configurations;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.Options;
+import org.apache.openjpa.meta.JavaTypes;
+
+////////////////////////////////////////////////////////////
+// NOTE: Do not change property names; see SequenceMetaData
+// and SequenceMapping for standard property names.
+////////////////////////////////////////////////////////////
+
+/**
+ * Specialization of the {@link TableJDBCSeq} that maintains multiple
+ * sequence counts. Each instance of this class represents one row with
+ * a known string primary key value, more or less. The table name defaults
+ * to <code>OPENJPA_SEQUENCES_TABLE</code>.
+ *
+ * @author Abe White
+ */
+public class ValueTableJDBCSeq
+    extends TableJDBCSeq {
+
+    public static final String PK_VALUE = "PrimaryKeyValue";
+
+    private static final Localizer _loc = Localizer.forPackage
+        (ValueTableJDBCSeq.class);
+
+    private String _value = "DEFAULT";
+
+    public ValueTableJDBCSeq() {
+        setTable("OPENJPA_SEQUENCES_TABLE");
+    }
+
+    /**
+     * The primary key value for this row. Defaults to <code>DEFAULT</code>.
+     */
+    public String getPrimaryKeyValue() {
+        return _value;
+    }
+
+    /**
+     * The primary key value for this row. Defaults to <code>DEFAULT</code>.
+     */
+    public void setPrimaryKeyValue(String value) {
+        _value = value;
+    }
+
+    protected Column addPrimaryKeyColumn(Table table) {
+        DBDictionary dict = getConfiguration().getDBDictionaryInstance();
+        Column pkColumn = table.addColumn(dict.getValidColumnName
+            (getPrimaryKeyColumn(), table));
+        pkColumn.setType(dict.getPreferredType(Types.VARCHAR));
+        pkColumn.setJavaType(JavaTypes.STRING);
+        pkColumn.setSize(dict.characterColumnSize);
+        return pkColumn;
+    }
+
+    protected Object getPrimaryKey(ClassMapping mapping) {
+        return _value;
+    }
+
+    /////////
+    // Main
+    /////////
+
+    /**
+     * Usage: java org.apache.openjpa.jdbc.kernel.ValueTableJDBCSeq [option]*
+     * -action/-a &lt;add | drop | get | set&gt; [primary key value] [value]
+     *  Where the following options are recognized.
+     * <ul>
+     * <li><i>-properties/-p &lt;properties file or resource&gt;</i>: The
+     * path or resource name of a OpenJPA properties file containing
+     * information such as the license key	and connection data as
+     * outlined in {@link JDBCConfiguration}. Optional.</li>
+     * <li><i>-&lt;property name&gt; &lt;property value&gt;</i>: All bean
+     * properties of the OpenJPA {@link JDBCConfiguration} can be set by
+     * using their	names and supplying a value. For example:
+     * <code>-licenseKey adslfja83r3lkadf</code></li>
+     * </ul>
+     *  The various actions are as follows.
+     * <ul>
+     * <li><i>add</i>: Create the sequence table.</li>
+     * <li><i>drop</i>: Drop the sequence table.</li>
+     * <li><i>get</i>: Print the current sequence value for the given
+     * primary key value.</li>
+     * <li><i>set</i>: Set the sequence value for the given primary key
+     * value.</li>
+     * </ul>
+     */
+    public static void main(String[] args)
+        throws Exception {
+        Options opts = new Options();
+        args = opts.setFromCmdLine(args);
+        JDBCConfiguration conf = new JDBCConfigurationImpl();
+        try {
+            if (!run(conf, args, opts))
+                System.out.println(_loc.get("clstable-seq-usage"));
+        } finally {
+            conf.close();
+        }
+    }
+
+    /**
+     * Run the tool. Returns false if invalid options were given.
+     */
+    public static boolean run(JDBCConfiguration conf, String[] args,
+        Options opts)
+        throws Exception {
+        if (opts.containsKey("help") || opts.containsKey("-help"))
+            return false;
+
+        String action = opts.removeProperty("action", "a", null);
+        Configurations.populateConfiguration(conf, opts);
+        return run(conf, args, action, null, null);
+    }
+
+    /**
+     * Run the tool. Return false if an invalid option was given.
+     */
+    public static boolean run(JDBCConfiguration conf, String[] args,
+        String action, MappingRepository repos, ClassLoader loader)
+        throws Exception {
+        ValueTableJDBCSeq seq = new ValueTableJDBCSeq();
+        String props = Configurations.getProperties(conf.getSequence());
+        Configurations.configureInstance(seq, conf, props);
+
+        if (ACTION_DROP.equals(action)) {
+            if (args.length != 0)
+                return false;
+            seq.dropTable();
+        } else if (ACTION_ADD.equals(action)) {
+            if (args.length != 0)
+                return false;
+            seq.refreshTable();
+        } else if (ACTION_GET.equals(action) || ACTION_SET.equals(action)) {
+            if (args.length > 0)
+                seq.setPrimaryKeyValue(args[0]);
+
+            Connection conn = conf.getDataSource2(null).getConnection();
+            try {
+                long cur = seq.getSequence(null, conn);
+                if (ACTION_GET.equals(action))
+                    System.out.println(seq.getPrimaryKeyValue() + ": " + cur);
+                else {
+                    long set;
+                    if (args.length > 1)
+                        set = Long.parseLong(args[1]);
+                    else
+                        set = cur + seq.getAllocate();
+                    if (set < cur)
+                        set = cur;
+                    else {
+                        Status stat = seq.getStatus(null);
+                        seq.setSequence(null, stat, (int) (set - cur), true,
+                            conn);
+                        set = stat.seq;
+                    }
+                    System.err.println(seq.getPrimaryKeyValue() + ": " + set);
+                }
+            }
+            catch (NumberFormatException nfe) {
+                return false;
+            } finally {
+                try {
+                    conn.close();
+                } catch (SQLException se) {
+                }
+            }
+        } else
+            return false;
+        return true;
+    }
+}

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

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

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.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.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Aggregate listener that evaluates to a value.
+ *
+ * @author Marc Prud'hommeaux
+ */
+abstract class AbstractVal
+    implements Val {
+
+    private static final String TRUE = "1 = 1";
+    private static final String FALSE = "1 <> 1";
+
+    public void appendIsEmpty(SQLBuffer sql, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        sql.append(FALSE);
+    }
+
+    public void appendIsNotEmpty(SQLBuffer sql, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        sql.append(TRUE);
+    }
+
+    public void appendIsNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+        appendTo(sql, 0, sel, store, params, fetchState);
+        sql.append(" IS ").appendValue(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 ").appendValue(null);
+    }
+
+    public void appendSize(SQLBuffer sql, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        sql.append("1");
+    }
+}
+

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Aggregate.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Aggregate.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Aggregate.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Aggregate.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,192 @@
+/*
+ * 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.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.meta.ClassMetaData;
+
+/**
+ * Aggregate listener that evaluates to a value.
+ *
+ * @author Abe White
+ */
+class Aggregate
+    extends AbstractVal
+    implements Val {
+
+    private final JDBCAggregateListener _listener;
+    private final Val _arg;
+    private final ClassMapping _candidate;
+    private Joins _joins = null;
+    private ClassMetaData _meta = null;
+    private Class _cast = null;
+
+    /**
+     * Constructor.
+     */
+    public Aggregate(JDBCAggregateListener listener, Val arg,
+        ClassMapping candidate) {
+        _listener = listener;
+        _arg = arg;
+        _candidate = candidate;
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+
+    public boolean isVariable() {
+        return false;
+    }
+
+    public Class getType() {
+        if (_cast != null)
+            return _cast;
+        return _listener.getType(getArgTypes());
+    }
+
+    private Class[] getArgTypes() {
+        if (_arg == null)
+            return null;
+        if (_arg instanceof Args)
+            return ((Args) _arg).getTypes();
+        return new Class[]{ _arg.getType() };
+    }
+
+    public void setImplicitType(Class type) {
+        _cast = type;
+    }
+
+    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+        // note that we tell targets and args to extensions that are sql
+        // paths to go ahead and join to their related object (if any),
+        // because we assume that, unlike most operations, if a relation
+        // field like a 1-1 is given as the target of an extension, then
+        // the extension probably acts on some field or column in the
+        // related object, not the 1-1 field itself
+        if (_arg != null) {
+            _arg.initialize(sel, store, false);
+            if (_arg instanceof PCPath)
+                ((PCPath) _arg).joinRelation();
+            _joins = _arg.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);
+        sel.setAggregate(true);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store, Object[] params,
+        boolean pks, JDBCFetchState fetchState) {
+        if (_arg != null)
+            _arg.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) {
+        if (_arg != null)
+            return _arg.hasVariable(var);
+        return false;
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchState fetchState) {
+        if (_arg != null)
+            _arg.calculateValue(sel, store, params, null, fetchState);
+    }
+
+    public void clearParameters() {
+        if (_arg != null)
+            _arg.clearParameters();
+    }
+
+    public int length() {
+        return 1;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        _listener.appendTo(sql, getArgs(sel, store, params, fetchState),
+            _candidate, store);
+        sel.append(sql, _joins);
+    }
+
+    private FilterValue[] getArgs(Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        if (_arg == null)
+            return null;
+        if (_arg instanceof Args) {
+            Val[] vals = ((Args) _arg).getVals();
+            FilterValue[] filts = new FilterValue[vals.length];
+            for (int i = 0; i < vals.length; i++)
+                filts[i] = new FilterValueImpl(vals[i], sel, store, params,
+                    fetchState);
+            return filts;
+        }
+        return new FilterValue[]{
+            new FilterValueImpl(_arg, sel, store, params, fetchState)
+        };
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/All.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/All.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/All.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/All.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * All.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class All
+    extends UnaryOp {
+
+    public All(Val val) {
+        super(val);
+    }
+
+    protected String getOperator() {
+        return "ALL";
+    }
+}
+

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,91 @@
+/*
+ * 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.sql.Joins;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Combines two expressions.
+ *
+ * @author Abe White
+ */
+class AndExpression
+    implements Exp {
+
+    private final Exp _exp1;
+    private final Exp _exp2;
+    private Joins _joins = null;
+    private boolean _paren1 = false;
+    private boolean _paren2 = false;
+
+    /**
+     * Constructor. Supply the expressions to combine.
+     */
+    public AndExpression(Exp exp1, Exp exp2) {
+        _exp1 = exp1;
+        _exp2 = exp2;
+    }
+
+    public void initialize(Select sel, JDBCStore store,
+        Object[] params, Map contains) {
+        _exp1.initialize(sel, store, params, contains);
+        _exp2.initialize(sel, store, params, contains);
+        _joins = sel.and(_exp1.getJoins(), _exp2.getJoins());
+
+        _paren1 = _exp1 instanceof OrExpression;
+        _paren2 = _exp2 instanceof OrExpression;
+    }
+
+    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        if (_paren1)
+            buf.append("(");
+        _exp1.appendTo(buf, sel, store, params, fetchState);
+        if (_paren1)
+            buf.append(")");
+        buf.append(" AND ");
+        if (_paren2)
+            buf.append("(");
+        _exp2.appendTo(buf, sel, store, params, fetchState);
+        if (_paren2)
+            buf.append(")");
+        sel.append(buf, _joins);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        _exp1.selectColumns(sel, store, params, pks, fetchState);
+        _exp2.selectColumns(sel, store, params, pks, fetchState);
+    }
+
+    public Joins getJoins() {
+        return _joins;
+    }
+
+    public boolean hasContainsExpression() {
+        return _exp1.hasContainsExpression() || _exp2.hasContainsExpression();
+    }
+
+    public boolean hasVariable(Variable var) {
+        return _exp1.hasVariable(var) || _exp2.hasVariable(var);
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Any.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Any.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Any.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Any.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Any.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class Any
+    extends UnaryOp {
+
+    public Any(Val val) {
+        super(val);
+    }
+
+    protected String getOperator() {
+        return "ANY";
+    }
+}
+

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Args.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Args.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Args.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Args.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,178 @@
+/*
+ * 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.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.exps.Arguments;
+import org.apache.openjpa.kernel.exps.Value;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * A list of arguments to a multi-argument function.
+ *
+ * @author Abe White
+ */
+public class Args
+    implements Val, Arguments {
+
+    private final Val[] _args;
+    private Joins _joins = null;
+    private ClassMetaData _meta = null;
+
+    /**
+     * Constructor. Supply values being combined.
+     */
+    public Args(Val val1, Val val2) {
+        int len1 = (val1 instanceof Args) ? ((Args) val1)._args.length : 1;
+        int len2 = (val2 instanceof Args) ? ((Args) val2)._args.length : 1;
+
+        _args = new Val[len1 + len2];
+        if (val1 instanceof Args)
+            System.arraycopy(((Args) val1)._args, 0, _args, 0, len1);
+        else
+            _args[0] = val1;
+        if (val2 instanceof Args)
+            System.arraycopy(((Args) val2)._args, 0, _args, len1, len2);
+        else
+            _args[len1] = val2;
+    }
+
+    public Value[] getValues() {
+        return _args;
+    }
+
+    public Val[] getVals() {
+        return _args;
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+
+    public boolean isVariable() {
+        return false;
+    }
+
+    public Class getType() {
+        return Object[].class;
+    }
+
+    public Class[] getTypes() {
+        Class[] c = new Class[_args.length];
+        for (int i = 0; i < _args.length; i++)
+            c[i] = _args[i].getType();
+        return c;
+    }
+
+    public void setImplicitType(Class type) {
+    }
+
+    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+        for (int i = 0; i < _args.length; i++) {
+            _args[i].initialize(sel, store, nullTest);
+            if (_joins == null)
+                _joins = _args[i].getJoins();
+            else
+                _joins = sel.and(_joins, _args[i].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) {
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        for (int i = 0; i < _args.length; i++)
+            _args[i].selectColumns(sel, store, params, pks, fetchState);
+    }
+
+    public void groupBy(Select sel, JDBCStore store, Object[] params,
+        JDBCFetchState fetchState) {
+    }
+
+    public void orderBy(Select sel, JDBCStore store, Object[] params,
+        boolean asc, JDBCFetchState fetchState) {
+    }
+
+    public Object load(Result res, JDBCStore store,
+        JDBCFetchState fetchState) {
+        return null;
+    }
+
+    public boolean hasVariable(Variable var) {
+        for (int i = 0; i < _args.length; i++)
+            if (_args[i].hasVariable(var))
+                return true;
+        return false;
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchState fetchState) {
+        for (int i = 0; i < _args.length; i++)
+            _args[i].calculateValue(sel, store, params, null, fetchState);
+    }
+
+    public void clearParameters() {
+        for (int i = 0; i < _args.length; i++)
+            _args[i].clearParameters();
+    }
+
+    public int length() {
+        return 0;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+    }
+
+    public void appendIsEmpty(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+    }
+
+    public void appendIsNotEmpty(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+    }
+
+    public void appendSize(SQLBuffer sql, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+    }
+
+    public void appendIsNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+    }
+
+    public void appendIsNotNull(SQLBuffer sql, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Avg.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Avg.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Avg.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Avg.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;
+
+/**
+ * Average.
+ *
+ * @author Abe White
+ */
+class Avg
+    extends UnaryOp {
+
+    /**
+     * Constructor. Provide the value to operate on.
+     */
+    public Avg(Val val) {
+        super(val);
+    }
+
+    protected String getOperator() {
+        return "AVG";
+    }
+
+    protected boolean isAggregate() {
+        return true;
+    }
+}
+

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableAndExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableAndExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableAndExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableAndExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,79 @@
+/*
+ * 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.sql.Joins;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Combines a bind variable expression with another.
+ *
+ * @author Abe White
+ */
+class BindVariableAndExpression
+    implements Exp {
+
+    private final BindVariableExpression _bind;
+    private final Exp _exp;
+    private Joins _joins = null;
+
+    /**
+     * Constructor. Supply the two combined expressions.
+     */
+    public BindVariableAndExpression(BindVariableExpression bind, Exp exp) {
+        _bind = bind;
+        _exp = exp;
+    }
+
+    public void initialize(Select sel, JDBCStore store,
+        Object[] params, Map contains) {
+        _bind.initialize(sel, store, params, contains);
+        _exp.initialize(sel, store, params, contains);
+        _joins = sel.and(_bind.getJoins(), _exp.getJoins());
+    }
+
+    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        boolean or = _exp instanceof OrExpression;
+        if (or)
+            buf.append("(");
+        _exp.appendTo(buf, sel, store, params, fetchState);
+        if (or)
+            buf.append(")");
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+        _exp.selectColumns(sel, store, params, pks, fetchState);
+    }
+
+    public Joins getJoins() {
+        return _joins;
+    }
+
+    public boolean hasContainsExpression() {
+        return true;
+    }
+
+    public boolean hasVariable(Variable var) {
+        return _exp.hasVariable(var);
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/BindVariableExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,81 @@
+/*
+ * 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.sql.Joins;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Binds a variable to a value. Typically, the {@link #initialize} and
+ * {@link #getJoins} methods of this expression are not called. They are
+ * only called if the variable being bound is otherwise unused in the filter,
+ * in which case we must at least make the joins to the variable because the
+ * act of binding a variable should at least guarantee that an instance
+ * represting the variable could exist (i.e. the binding collection is not
+ * empty).
+ *
+ * @author Abe White
+ */
+class BindVariableExpression
+    extends EmptyExpression {
+
+    private final Variable _var;
+
+    /**
+     * Constructor. Supply values.
+     */
+    public BindVariableExpression(Variable var, PCPath val, boolean key) {
+        if (key)
+            val.getKey();
+        var.setPCPath(val);
+        _var = var;
+    }
+
+    public Variable getVariable() {
+        return _var;
+    }
+
+    public void initialize(Select sel, JDBCStore store,
+        Object[] params, Map contains) {
+        _var.initialize(sel, store, false);
+    }
+
+    public void appendTo(SQLBuffer buf, Select sel, JDBCStore store,
+        Object[] params, JDBCFetchState fetchState) {
+        buf.append("1 = 1");
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchState fetchState) {
+    }
+
+    public Joins getJoins() {
+        return _var.getJoins();
+    }
+
+    public boolean hasContainsExpression() {
+        return false;
+    }
+
+    public boolean hasVariable(Variable var) {
+        return _var == var;
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareEqualExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareEqualExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareEqualExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareEqualExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,134 @@
+/*
+ * 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.sql.Joins;
+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.util.UserException;
+
+/**
+ * Compares two values for equality.
+ *
+ * @author Abe White
+ */
+abstract class CompareEqualExpression
+    implements Exp {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (CompareEqualExpression.class);
+
+    private final Val _val1;
+    private final Val _val2;
+    private Joins _joins = null;
+
+    /**
+     * Constructor. Supply values to compare.
+     */
+    public CompareEqualExpression(Val val1, Val val2) {
+        _val1 = val1;
+        _val2 = val2;
+    }
+
+    public Val getValue1() {
+        return _val1;
+    }
+
+    public Val getValue2() {
+        return _val2;
+    }
+
+    public void initialize(Select sel, JDBCStore store,
+        Object[] params, Map contains) {
+        boolean direct = isDirectComparison();
+        _val1.initialize(sel, store, direct && isNull(_val2, params));
+        _val2.initialize(sel, store, direct && isNull(_val1, params));
+        _joins = sel.and(_val1.getJoins(), _val2.getJoins());
+    }
+
+    /**
+     * Return whether the given value is null.
+     */
+    private boolean isNull(Val val, Object[] params) {
+        if (val instanceof Null)
+            return true;
+        if (!(val instanceof Param))
+            return false;
+
+        Param param = (Param) val;
+        return params[param.getIndex()] == null;
+    }
+
+    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 (!Filters.canConvert(_val1.getType(), _val2.getType(), false)
+            && !Filters.canConvert(_val2.getType(), _val1.getType(), false))
+            throw new UserException(_loc.get("cant-convert", _val1.getType(),
+                _val2.getType()));
+
+        boolean val1Null = _val1 instanceof Const
+            && ((Const) _val1).isSQLValueNull();
+        boolean val2Null = _val2 instanceof Const
+            && ((Const) _val2).isSQLValueNull();
+        appendTo(buf, sel, store, params, fetchState, val1Null, val2Null);
+        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);
+    }
+
+    /**
+     * Append the SQL for the comparison.
+     */
+    protected abstract void appendTo(SQLBuffer buf, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchState fetchState,
+        boolean val1Null, boolean val2Null);
+
+    /**
+     * Subclasses can override this method if, when they compare to another,
+     * value, the comparison is indirect. For example, field.contains (x)
+     * should compare element values to null, not the field itself.
+     */
+    protected boolean isDirectComparison() {
+        return true;
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareExpression.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareExpression.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareExpression.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/CompareExpression.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,101 @@
+/*
+ * 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.sql.Joins;
+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.util.UserException;
+
+/**
+ * Compares two values.
+ *
+ * @author Abe White
+ */
+class CompareExpression
+    implements Exp {
+
+    public static final String LESS = "<";
+    public static final String GREATER = ">";
+    public static final String LESS_EQUAL = "<=";
+    public static final String GREATER_EQUAL = ">=";
+
+    private static final Localizer _loc = Localizer.forPackage
+        (CompareExpression.class);
+
+    private final Val _val1;
+    private final Val _val2;
+    private final String _op;
+    private Joins _joins = null;
+
+    /**
+     * Constructor. Supply values and operator.
+     */
+    public CompareExpression(Val val1, Val val2, String op) {
+        _val1 = val1;
+        _val2 = val2;
+        _op = op;
+    }
+
+    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());
+    }
+
+    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 (!Filters.canConvert(_val1.getType(), _val2.getType(), false)
+            && !Filters.canConvert(_val2.getType(), _val1.getType(), false))
+            throw new UserException(_loc.get("cant-convert", _val1.getType(),
+                _val2.getType()));
+
+        store.getDBDictionary().comparison(buf, _op,
+            new FilterValueImpl(_val1, sel, store, params, fetchState),
+            new FilterValueImpl(_val2, 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);
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Concat.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Concat.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Concat.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Concat.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,171 @@
+/*
+ * 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.lang.Math;
+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.DBDictionary;
+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;
+
+/**
+ * Concatenate one string with another.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class Concat
+    extends AbstractVal
+    implements Val {
+
+    private final Val _val1;
+    private final Val _val2;
+    private Joins _joins = null;
+    private ClassMetaData _meta = null;
+    private String _part1;
+    private String _part2;
+    private String _part3;
+
+    /**
+     * Constructor. Provide the strings to operate on.
+     */
+    public Concat(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());
+
+        DBDictionary dict = store.getDBDictionary();
+        String func = dict.concatenateFunction;
+
+        dict.assertSupport(func != null, "ConcatenateFunction");
+
+        int part1idx = func.indexOf("{0}");
+        int part2idx = func.indexOf("{1}");
+
+        _part1 = func.substring(0, Math.min(part1idx, part2idx));
+        _part2 = func.substring(Math.min(part1idx, part2idx) + 3,
+            Math.max(part1idx, part2idx));
+        _part3 = func.substring(Math.max(part1idx, part2idx) + 3);
+    }
+
+    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) {
+        _val1.calculateValue(sel, store, params, _val2, fetchState);
+        _val2.calculateValue(sel, store, params, _val1, fetchState);
+
+        sql.append(_part1);
+        _val1.appendTo(sql, 0, sel, store, params, fetchState);
+        sql.append(_part2);
+        _val2.appendTo(sql, 0, sel, store, params, fetchState);
+        sql.append(_part3);
+    }
+}
+

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