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);
}