You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mp...@apache.org on 2006/08/22 03:50:44 UTC

svn commit: r433460 - in /incubator/openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/

Author: mprudhom
Date: Mon Aug 21 18:50:43 2006
New Revision: 433460

URL: http://svn.apache.org/viewvc?rev=433460&view=rev
Log:
Added expression-level support for Map.get in queries

Added:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GetMapValue.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetMapValue.java
Modified:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ContainerFieldStrategy.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
    incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GetMapValue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GetMapValue.java?rev=433460&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GetMapValue.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GetMapValue.java Mon Aug 21 18:50:43 2006
@@ -0,0 +1,213 @@
+/*
+ * 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.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.meta.strats.ContainerFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.LRSMapFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationStrategies;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+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;
+
+/**
+ * Returns the value of the given map's key.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class GetMapValue
+    extends AbstractVal {
+    private final Val _map;
+    private final Val _key;
+    private Joins _joins = null;
+    private ClassMetaData _meta = null;
+    private Class _cast = null;
+
+    /**
+     * Constructor. Provide the map and key to operate on.
+     */
+    public GetMapValue(Val map, Val key) {
+        _map = map;
+        _key = key;
+    }
+
+    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 _map.getType();
+    }
+
+    public void setImplicitType(Class type) {
+        _cast = type;
+    }
+
+    public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+        _map.initialize(sel, store, false);
+        _key.initialize(sel, store, false);
+        _joins = sel.and(_map.getJoins(), _key.getJoins());
+    }
+
+    public Joins getJoins() {
+        return _joins;
+    }
+
+    public Object toDataStoreValue(Object val, JDBCStore store) {
+        return _map.toDataStoreValue(val, store);
+    }
+
+
+    public void select(Select sel, JDBCStore store, Object[] params,
+        boolean pks, JDBCFetchConfiguration fetch) {
+        sel.select(newSQLBuffer(sel, store, params, fetch), this);
+    }
+
+    public void selectColumns(Select sel, JDBCStore store,
+        Object[] params, boolean pks, JDBCFetchConfiguration fetch) {
+        _map.selectColumns(sel, store, params, true, fetch);
+        _key.selectColumns(sel, store, params, true, fetch);
+    }
+
+    public void groupBy(Select sel, JDBCStore store, Object[] params,
+        JDBCFetchConfiguration fetch) {
+        sel.groupBy(newSQLBuffer(sel, store, params, fetch));
+    }
+
+    public void orderBy(Select sel, JDBCStore store, Object[] params,
+        boolean asc, JDBCFetchConfiguration fetch) {
+        sel.orderBy(newSQLBuffer(sel, store, params, fetch), asc, false);
+    }
+
+    private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
+        Object[] params, JDBCFetchConfiguration fetch) {
+        calculateValue(sel, store, params, null, fetch);
+        SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
+        appendTo(buf, 0, sel, store, params, fetch);
+        clearParameters();
+        return buf;
+    }
+
+    public Object load(Result res, JDBCStore store,
+        JDBCFetchConfiguration fetch)
+        throws SQLException {
+        return Filters.convert(res.getObject(this,
+            JavaSQLTypes.JDBC_DEFAULT, null), getType());
+    }
+
+    public void calculateValue(Select sel, JDBCStore store,
+        Object[] params, Val other, JDBCFetchConfiguration fetch) {
+        _map.calculateValue(sel, store, params, null, fetch);
+        _key.calculateValue(sel, store, params, null, fetch);
+    }
+
+    public void clearParameters() {
+        _map.clearParameters();
+        _key.clearParameters();
+    }
+
+    public int length() {
+        return 1;
+    }
+
+    public void appendTo(SQLBuffer sql, int index, Select sel,
+        JDBCStore store, Object[] params, JDBCFetchConfiguration fetch) {
+        if (!(_map instanceof PCPath))
+            throw new UnsupportedOperationException();
+
+        if (!(_key instanceof Const))
+            throw new UnsupportedOperationException();
+
+        PCPath map = (PCPath) _map;
+        Object key = ((Const) _key).getValue();
+
+        FieldMapping field = map.getFieldMapping();
+
+        if (!(field.getStrategy() instanceof LRSMapFieldStrategy))
+            throw new UnsupportedOperationException();
+
+        LRSMapFieldStrategy strat = (LRSMapFieldStrategy) field.getStrategy();
+
+        ClassMapping[] clss = strat.getIndependentValueMappings(true);
+        if (clss != null && clss.length > 1)
+            throw RelationStrategies.unjoinable(field);
+
+        ClassMapping cls = (clss.length == 0) ? null : clss[0];
+        ForeignKey fk = strat.getJoinForeignKey(cls);
+        DBDictionary dict = store.getDBDictionary();
+        SQLBuffer sub = new SQLBuffer(dict);
+
+        // manually create a subselect for the Map's value
+        sub.append("(SELECT ");
+        Column[] values = field.getElementMapping().getColumns();
+        for (int i = 0; i < values.length; i++) {
+            if (i > 0)
+                sub.append(", ");
+            sub.append(values[i].getFullName());
+        }
+
+        sub.append(" FROM ").append(values[0].getTable().getFullName()).
+            append(" WHERE ");
+
+        // add in the joins
+        ContainerFieldStrategy.appendUnaliasedJoin(sub, sel, null,
+            dict, field, fk);
+
+        sub.append(" AND ");
+
+        key = strat.toKeyDataStoreValue(key, store);
+        Column[] cols = strat.getKeyColumns(cls);
+        Object[] vals = (cols.length == 1) ? null : (Object[]) key;
+
+        for (int i = 0; i < cols.length; i++) {
+            sub.append(cols[i].getFullName());
+
+            if (vals == null)
+                sub.append((key == null) ? " IS " : " = ").
+                    appendValue(key, cols[i]);
+            else
+                sub.append((vals[i] == null) ? " IS " : " = ").
+                    appendValue(vals[i], cols[i]);
+        }
+
+        sub.append(")");
+
+        sql.append(sub);
+    }
+}

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java?rev=433460&r1=433459&r2=433460&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java Mon Aug 21 18:50:43 2006
@@ -172,24 +172,24 @@
         return new IsNotEmptyExpression((Val) val);
     }
 
-    public Expression contains(Value v1, Value v2) {
-        if (v1 instanceof Const)
-            return new InExpression((Val) v2, (Const) v1);
-        if (v1 instanceof SubQ)
-            return new InSubQExpression((Val) v2, (SubQ) v1);
-        return new ContainsExpression((Val) v1, (Val) v2);
-    }
-
-    public Expression containsKey(Value v1, Value v2) {
-        if (v1 instanceof Const)
-            return new InKeyExpression((Val) v2, (Const) v1);
-        return new ContainsKeyExpression((Val) v1, (Val) v2);
-    }
-
-    public Expression containsValue(Value v1, Value v2) {
-        if (v1 instanceof Const)
-            return new InValueExpression((Val) v2, (Const) v1);
-        return new ContainsExpression((Val) v1, (Val) v2);
+    public Expression contains(Value map, Value arg) {
+        if (map instanceof Const)
+            return new InExpression((Val) arg, (Const) map);
+        if (map instanceof SubQ)
+            return new InSubQExpression((Val) arg, (SubQ) map);
+        return new ContainsExpression((Val) map, (Val) arg);
+    }
+
+    public Expression containsKey(Value map, Value arg) {
+        if (map instanceof Const)
+            return new InKeyExpression((Val) arg, (Const) map);
+        return new ContainsKeyExpression((Val) map, (Val) arg);
+    }
+
+    public Expression containsValue(Value map, Value arg) {
+        if (map instanceof Const)
+            return new InValueExpression((Val) arg, (Const) map);
+        return new ContainsExpression((Val) map, (Val) arg);
     }
 
     public Expression isInstance(Value val, Class c) {
@@ -441,5 +441,9 @@
         if (val instanceof Const)
             return new ConstGetObjectId((Const) val);
         return new GetObjectId((PCPath) val);
+    }
+
+    public Value getMapValue(Value map, Value arg) {
+        return new GetMapValue((Val) map, (Val) arg);
     }
 }

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ContainerFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ContainerFieldStrategy.java?rev=433460&r1=433459&r2=433460&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ContainerFieldStrategy.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ContainerFieldStrategy.java Mon Aug 21 18:50:43 2006
@@ -93,6 +93,13 @@
         String fullTable = dict.getFullName(fk.getTable(), false);
         sql.append("(SELECT COUNT(*) FROM ").append(fullTable).
             append(" WHERE ");
+        appendUnaliasedJoin(sql, sel, joins, dict, field, fk);
+        sql.append(")");
+    }
+
+    public static void appendUnaliasedJoin(SQLBuffer sql, Select sel,
+        Joins joins, DBDictionary dict, FieldMapping field, ForeignKey fk) {
+        String fullTable = dict.getFullName(fk.getTable(), false);
 
         Column[] cols = fk.getColumns();
         Column[] pks = fk.getPrimaryKeyColumns();
@@ -119,6 +126,5 @@
             sql.append(sel.getColumnAlias(pks[i], joins)).append(" = ").
                 appendValue(fk.getPrimaryKeyConstant(pks[i]), pks[i]);
         }
-        sql.append(")");
     }
 }

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java?rev=433460&r1=433459&r2=433460&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java Mon Aug 21 18:50:43 2006
@@ -92,6 +92,11 @@
     public Expression containsValue(Value map, Value arg);
 
     /**
+     * Return an expression representing the given condition.
+     */
+    public Value getMapValue(Value map, Value arg);
+
+    /**
      * Return whether the first value is an instance of the given class.
      */
     public Expression isInstance(Value obj, Class c);

Added: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetMapValue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetMapValue.java?rev=433460&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetMapValue.java (added)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/GetMapValue.java Mon Aug 21 18:50:43 2006
@@ -0,0 +1,57 @@
+/*
+ * 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.kernel.exps;
+
+import java.util.Map;
+
+import org.apache.openjpa.kernel.StoreContext;
+
+/**
+ * Returns the value of the specified key in a Map.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class GetMapValue
+    extends Val {
+
+    private final Val _map;
+    private final Val _arg;
+
+    /**
+     * Constructor. Provide value to upper-case.
+     */
+    public GetMapValue(Val map, Val arg) {
+        _map = map;
+        _arg = arg;
+    }
+
+    public boolean isVariable() {
+        return false;
+    }
+
+    public Class getType() {
+        return Object.class;
+    }
+
+    public void setImplicitType(Class type) {
+    }
+
+    protected Object eval(Object candidate, Object orig,
+        StoreContext ctx, Object[] params) {
+        return ((Map) _map.eval(candidate, orig, ctx, params)).
+            get(_arg.eval(candidate, orig, ctx, params));
+    }
+}

Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java?rev=433460&r1=433459&r2=433460&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java (original)
+++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java Mon Aug 21 18:50:43 2006
@@ -405,6 +405,10 @@
         return new ContainsValueExpression((Val) v1, (Val) v2);
     }
 
+    public Value getMapValue(Value map, Value arg) {
+        return new GetMapValue((Val) map, (Val) arg);
+    }
+
     public Expression isInstance(Value v1, Class c) {
         return new InstanceofExpression((Val) v1, c);
     }