mirror of https://github.com/apache/openjpa.git
OPENJPA-612 Add support for calculating update value in QueryImpl.updateInMemory
Help comitting patch provided by Fay Wang git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@660825 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c1e5f27724
commit
dbbd1236f2
|
@ -35,10 +35,12 @@ import org.apache.openjpa.jdbc.kernel.exps.GetColumn;
|
|||
import org.apache.openjpa.jdbc.kernel.exps.JDBCExpressionFactory;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.JDBCStringContains;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.JDBCWildcardMatch;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.PCPath;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.QueryExpressionsState;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.SQLEmbed;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.SQLExpression;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.SQLValue;
|
||||
import org.apache.openjpa.jdbc.kernel.exps.Val;
|
||||
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
||||
import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
|
||||
|
@ -50,18 +52,24 @@ import org.apache.openjpa.jdbc.sql.SQLExceptions;
|
|||
import org.apache.openjpa.jdbc.sql.Select;
|
||||
import org.apache.openjpa.jdbc.sql.Union;
|
||||
import org.apache.openjpa.kernel.ExpressionStoreQuery;
|
||||
import org.apache.openjpa.kernel.Filters;
|
||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||
import org.apache.openjpa.kernel.OrderingMergedResultObjectProvider;
|
||||
import org.apache.openjpa.kernel.QueryHints;
|
||||
import org.apache.openjpa.kernel.exps.Constant;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionFactory;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionParser;
|
||||
import org.apache.openjpa.kernel.exps.FilterListener;
|
||||
import org.apache.openjpa.kernel.exps.Literal;
|
||||
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||
import org.apache.openjpa.lib.rop.MergedResultObjectProvider;
|
||||
import org.apache.openjpa.lib.rop.RangeResultObjectProvider;
|
||||
import org.apache.openjpa.lib.rop.ResultObjectProvider;
|
||||
import org.apache.openjpa.lib.util.Localizer;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.JavaTypes;
|
||||
import org.apache.openjpa.meta.ValueMetaData;
|
||||
import org.apache.openjpa.util.UnsupportedException;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
import serp.util.Numbers;
|
||||
|
||||
|
@ -671,4 +679,105 @@ public class JDBCStoreQuery
|
|||
throws SQLException {
|
||||
return sql.prepareStatement(conn);
|
||||
}
|
||||
|
||||
public Object evaluate(Object value, Object ob, Object[] params,
|
||||
OpenJPAStateManager sm) {
|
||||
if (value instanceof org.apache.openjpa.jdbc.kernel.exps.Math) {
|
||||
org.apache.openjpa.jdbc.kernel.exps.Math mathVal =
|
||||
(org.apache.openjpa.jdbc.kernel.exps.Math) value;
|
||||
|
||||
Val value1 = mathVal.getVal1();
|
||||
Object val1 = getValue(value1, ob, params, sm);
|
||||
Class c1 = value1.getType();
|
||||
|
||||
Val value2 = mathVal.getVal2();
|
||||
Object val2 = getValue(value2, ob, params, sm);
|
||||
Class c2 = value2.getType();
|
||||
|
||||
String op = mathVal.getOperation();
|
||||
|
||||
if (op.equals(org.apache.openjpa.jdbc.kernel.exps.Math.ADD))
|
||||
return Filters.add(val1, c1, val2, c2);
|
||||
else if (op.equals(
|
||||
org.apache.openjpa.jdbc.kernel.exps.Math.SUBTRACT))
|
||||
return Filters.subtract(val1, c1, val2, c2);
|
||||
else if (op.equals(
|
||||
org.apache.openjpa.jdbc.kernel.exps.Math.MULTIPLY))
|
||||
return Filters.multiply(val1, c1, val2, c2);
|
||||
else if (op.equals(
|
||||
org.apache.openjpa.jdbc.kernel.exps.Math.DIVIDE))
|
||||
return Filters.divide(val1, c1, val2, c2);
|
||||
else if (op.equals(org.apache.openjpa.jdbc.kernel.exps.Math.MOD))
|
||||
return Filters.mod(val1, c1, val2, c2);
|
||||
throw new UnsupportedException();
|
||||
}
|
||||
throw new UnsupportedException();
|
||||
}
|
||||
|
||||
private Object getValue(Object ob, FieldMapping fmd,
|
||||
OpenJPAStateManager sm) {
|
||||
int i = fmd.getIndex();
|
||||
switch (fmd.getDeclaredTypeCode()) {
|
||||
case JavaTypes.BOOLEAN:
|
||||
return sm.fetchBooleanField(i);
|
||||
case JavaTypes.BYTE:
|
||||
return sm.fetchByteField(i);
|
||||
case JavaTypes.CHAR:
|
||||
return sm.fetchCharField(i);
|
||||
case JavaTypes.DOUBLE:
|
||||
return sm.fetchDoubleField(i);
|
||||
case JavaTypes.FLOAT:
|
||||
return sm.fetchFloatField(i);
|
||||
case JavaTypes.INT:
|
||||
return sm.fetchIntField(i);
|
||||
case JavaTypes.LONG:
|
||||
return sm.fetchLongField(i);
|
||||
case JavaTypes.SHORT:
|
||||
return sm.fetchShortField(i);
|
||||
case JavaTypes.STRING:
|
||||
return sm.fetchStringField(i);
|
||||
case JavaTypes.DATE:
|
||||
case JavaTypes.NUMBER:
|
||||
case JavaTypes.BOOLEAN_OBJ:
|
||||
case JavaTypes.BYTE_OBJ:
|
||||
case JavaTypes.CHAR_OBJ:
|
||||
case JavaTypes.DOUBLE_OBJ:
|
||||
case JavaTypes.FLOAT_OBJ:
|
||||
case JavaTypes.INT_OBJ:
|
||||
case JavaTypes.LONG_OBJ:
|
||||
case JavaTypes.SHORT_OBJ:
|
||||
case JavaTypes.BIGDECIMAL:
|
||||
case JavaTypes.BIGINTEGER:
|
||||
case JavaTypes.LOCALE:
|
||||
case JavaTypes.OBJECT:
|
||||
case JavaTypes.OID:
|
||||
return sm.fetchObjectField(i);
|
||||
default:
|
||||
throw new UnsupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
private Object eval(Object ob, Object value, Object[] params,
|
||||
OpenJPAStateManager sm) {
|
||||
Object val = null;
|
||||
if (value instanceof Literal)
|
||||
val = ((Literal) value).getValue();
|
||||
else if (value instanceof Constant)
|
||||
val = ((Constant) value).getValue(params);
|
||||
else
|
||||
val = evaluate(value, ob, params, sm);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
private Object getValue(Object value, Object ob, Object[] params,
|
||||
OpenJPAStateManager sm) {
|
||||
if (value instanceof org.apache.openjpa.jdbc.kernel.exps.Math)
|
||||
return evaluate(value, ob, params, sm);
|
||||
else if (value instanceof PCPath) {
|
||||
FieldMapping fm = (FieldMapping)((PCPath)value).last();
|
||||
return getValue(ob, fm, sm);
|
||||
} else
|
||||
return eval(ob, value, params, sm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.apache.openjpa.meta.ClassMetaData;
|
|||
*
|
||||
* @author Abe White
|
||||
*/
|
||||
class Math
|
||||
public class Math
|
||||
extends AbstractVal {
|
||||
|
||||
public static final String ADD = "+";
|
||||
|
@ -57,6 +57,18 @@ class Math
|
|||
_op = op;
|
||||
}
|
||||
|
||||
public Val getVal1() {
|
||||
return _val1;
|
||||
}
|
||||
|
||||
public Val getVal2() {
|
||||
return _val2;
|
||||
}
|
||||
|
||||
public String getOperation() {
|
||||
return _op;
|
||||
}
|
||||
|
||||
public ClassMetaData getMetaData() {
|
||||
return _meta;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,184 +1,190 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.map.LinkedMap;
|
||||
import org.apache.openjpa.kernel.exps.AggregateListener;
|
||||
import org.apache.openjpa.kernel.exps.FilterListener;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.util.InternalException;
|
||||
|
||||
/**
|
||||
* Abstract {@link StoreQuery} that implements most methods as no-ops.
|
||||
*
|
||||
* @author Abe White
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public abstract class AbstractStoreQuery
|
||||
implements StoreQuery {
|
||||
|
||||
protected QueryContext ctx = null;
|
||||
|
||||
public QueryContext getContext() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public void setContext(QueryContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public boolean setQuery(Object query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public FilterListener getFilterListener(String tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public AggregateListener getAggregateListener(String tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object newCompilationKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object newCompilation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void populateFromCompilation(Object comp) {
|
||||
}
|
||||
|
||||
public void invalidateCompilation() {
|
||||
}
|
||||
|
||||
public boolean supportsDataStoreExecution() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsInMemoryExecution() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs) {
|
||||
throw new InternalException();
|
||||
}
|
||||
|
||||
public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs) {
|
||||
throw new InternalException();
|
||||
}
|
||||
|
||||
public boolean supportsAbstractExecutors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean requiresCandidateType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean requiresParameterDeclarations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsParameterDeclarations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract {@link Executor} that implements most methods as no-ops.
|
||||
*/
|
||||
public static abstract class AbstractExecutor
|
||||
implements Executor {
|
||||
|
||||
public Number executeDelete(StoreQuery q, Object[] params) {
|
||||
return q.getContext().deleteInMemory(q, this, params);
|
||||
}
|
||||
|
||||
public Number executeUpdate(StoreQuery q, Object[] params) {
|
||||
return q.getContext().updateInMemory(q, this, params);
|
||||
}
|
||||
|
||||
public String[] getDataStoreActions(StoreQuery q, Object[] params,
|
||||
Range range) {
|
||||
return EMPTY_STRINGS;
|
||||
}
|
||||
|
||||
public void validate(StoreQuery q) {
|
||||
}
|
||||
|
||||
public void getRange(StoreQuery q, Object[] params, Range range) {
|
||||
}
|
||||
|
||||
public Object getOrderingValue(StoreQuery q, Object[] params,
|
||||
Object resultObject, int orderIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean[] getAscending(StoreQuery q) {
|
||||
return EMPTY_BOOLEANS;
|
||||
}
|
||||
|
||||
public boolean isPacking(StoreQuery q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getAlias(StoreQuery q) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getProjectionAliases(StoreQuery q) {
|
||||
return EMPTY_STRINGS;
|
||||
}
|
||||
|
||||
public Class[] getProjectionTypes(StoreQuery q) {
|
||||
return EMPTY_CLASSES;
|
||||
}
|
||||
|
||||
public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q) {
|
||||
return EMPTY_METAS;
|
||||
}
|
||||
|
||||
public int getOperation(StoreQuery q) {
|
||||
return OP_SELECT;
|
||||
}
|
||||
|
||||
public boolean isAggregate(StoreQuery q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasGrouping(StoreQuery q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public LinkedMap getParameterTypes(StoreQuery q) {
|
||||
return EMPTY_PARAMS;
|
||||
}
|
||||
|
||||
public Class getResultClass(StoreQuery q) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map getUpdates(StoreQuery q) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.map.LinkedMap;
|
||||
import org.apache.openjpa.kernel.exps.AggregateListener;
|
||||
import org.apache.openjpa.kernel.exps.FilterListener;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.util.InternalException;
|
||||
import org.apache.openjpa.util.UnsupportedException;
|
||||
|
||||
/**
|
||||
* Abstract {@link StoreQuery} that implements most methods as no-ops.
|
||||
*
|
||||
* @author Abe White
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public abstract class AbstractStoreQuery
|
||||
implements StoreQuery {
|
||||
|
||||
protected QueryContext ctx = null;
|
||||
|
||||
public QueryContext getContext() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public void setContext(QueryContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public boolean setQuery(Object query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public FilterListener getFilterListener(String tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public AggregateListener getAggregateListener(String tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object newCompilationKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object newCompilation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void populateFromCompilation(Object comp) {
|
||||
}
|
||||
|
||||
public void invalidateCompilation() {
|
||||
}
|
||||
|
||||
public boolean supportsDataStoreExecution() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsInMemoryExecution() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs) {
|
||||
throw new InternalException();
|
||||
}
|
||||
|
||||
public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs) {
|
||||
throw new InternalException();
|
||||
}
|
||||
|
||||
public boolean supportsAbstractExecutors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean requiresCandidateType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean requiresParameterDeclarations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsParameterDeclarations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object evaluate(Object value, Object ob, Object[] params,
|
||||
OpenJPAStateManager sm) {
|
||||
throw new UnsupportedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract {@link Executor} that implements most methods as no-ops.
|
||||
*/
|
||||
public static abstract class AbstractExecutor
|
||||
implements Executor {
|
||||
|
||||
public Number executeDelete(StoreQuery q, Object[] params) {
|
||||
return q.getContext().deleteInMemory(q, this, params);
|
||||
}
|
||||
|
||||
public Number executeUpdate(StoreQuery q, Object[] params) {
|
||||
return q.getContext().updateInMemory(q, this, params);
|
||||
}
|
||||
|
||||
public String[] getDataStoreActions(StoreQuery q, Object[] params,
|
||||
Range range) {
|
||||
return EMPTY_STRINGS;
|
||||
}
|
||||
|
||||
public void validate(StoreQuery q) {
|
||||
}
|
||||
|
||||
public void getRange(StoreQuery q, Object[] params, Range range) {
|
||||
}
|
||||
|
||||
public Object getOrderingValue(StoreQuery q, Object[] params,
|
||||
Object resultObject, int orderIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean[] getAscending(StoreQuery q) {
|
||||
return EMPTY_BOOLEANS;
|
||||
}
|
||||
|
||||
public boolean isPacking(StoreQuery q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getAlias(StoreQuery q) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getProjectionAliases(StoreQuery q) {
|
||||
return EMPTY_STRINGS;
|
||||
}
|
||||
|
||||
public Class[] getProjectionTypes(StoreQuery q) {
|
||||
return EMPTY_CLASSES;
|
||||
}
|
||||
|
||||
public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q) {
|
||||
return EMPTY_METAS;
|
||||
}
|
||||
|
||||
public int getOperation(StoreQuery q) {
|
||||
return OP_SELECT;
|
||||
}
|
||||
|
||||
public boolean isAggregate(StoreQuery q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasGrouping(StoreQuery q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public LinkedMap getParameterTypes(StoreQuery q) {
|
||||
return EMPTY_PARAMS;
|
||||
}
|
||||
|
||||
public Class getResultClass(StoreQuery q) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map getUpdates(StoreQuery q) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1048,7 +1048,7 @@ public class QueryImpl
|
|||
|
||||
int size = 0;
|
||||
for (Iterator i = ((Collection) o).iterator(); i.hasNext(); size++)
|
||||
updateInMemory(i.next(), params);
|
||||
updateInMemory(i.next(), params, q);
|
||||
return Numbers.valueOf(size);
|
||||
} catch (OpenJPAException ke) {
|
||||
throw ke;
|
||||
|
@ -1063,12 +1063,13 @@ public class QueryImpl
|
|||
* @param ob the persistent instance to change
|
||||
* @param params the parameters passed to the query
|
||||
*/
|
||||
private void updateInMemory(Object ob, Object[] params) {
|
||||
private void updateInMemory(Object ob, Object[] params, StoreQuery q) {
|
||||
for (Iterator it = getUpdates().entrySet().iterator();
|
||||
it.hasNext();) {
|
||||
Map.Entry e = (Map.Entry) it.next();
|
||||
Path path = (Path) e.getKey();
|
||||
FieldMetaData fmd = (FieldMetaData) path.last();
|
||||
OpenJPAStateManager sm = _broker.getStateManager(ob);
|
||||
|
||||
Object val;
|
||||
Object value = e.getValue();
|
||||
|
@ -1080,10 +1081,13 @@ public class QueryImpl
|
|||
} else if (value instanceof Constant) {
|
||||
val = ((Constant) value).getValue(params);
|
||||
} else {
|
||||
throw new UserException(_loc.get("only-update-primitives"));
|
||||
try {
|
||||
val = q.evaluate(value, ob, params, sm);
|
||||
} catch (UnsupportedException e1) {
|
||||
throw new UserException(_loc.get("fail-to-get-update-value"));
|
||||
}
|
||||
}
|
||||
|
||||
OpenJPAStateManager sm = _broker.getStateManager(ob);
|
||||
int i = fmd.getIndex();
|
||||
PersistenceCapable into = ImplHelper.toPersistenceCapable(ob,
|
||||
_broker.getConfiguration());
|
||||
|
|
|
@ -1,322 +1,325 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.map.LinkedMap;
|
||||
import org.apache.openjpa.kernel.exps.AggregateListener;
|
||||
import org.apache.openjpa.kernel.exps.Constant;
|
||||
import org.apache.openjpa.kernel.exps.FilterListener;
|
||||
import org.apache.openjpa.lib.rop.ResultObjectProvider;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
|
||||
/**
|
||||
* Component that executes queries against the datastore. For
|
||||
* expression-based queries, consider subclassing
|
||||
* {@link ExpressionStoreManagerQuery}.
|
||||
*
|
||||
* @author Abe White
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public interface StoreQuery
|
||||
extends QueryOperations, Serializable {
|
||||
|
||||
// linkedmap doesn't allow a size of 0, so use 1
|
||||
public static final LinkedMap EMPTY_PARAMS = new LinkedMap(1, 1F);
|
||||
public static final ClassMetaData[] EMPTY_METAS = new ClassMetaData[0];
|
||||
public static final String[] EMPTY_STRINGS = new String[0];
|
||||
public static final Object[] EMPTY_OBJECTS = new Object[0];
|
||||
public static final Class[] EMPTY_CLASSES = new Class[0];
|
||||
public static final boolean[] EMPTY_BOOLEANS = new boolean[0];
|
||||
|
||||
/**
|
||||
* Return the query context that has been set.
|
||||
*/
|
||||
public QueryContext getContext();
|
||||
|
||||
/**
|
||||
* Set the current query context. This will be called before use.
|
||||
*/
|
||||
public void setContext(QueryContext ctx);
|
||||
|
||||
/**
|
||||
* This is invoked when the user or a facade creates a new query with
|
||||
* an object that the system does not recognize. Return true if
|
||||
* the object is recognized by the store, false otherwise.
|
||||
*/
|
||||
public boolean setQuery(Object query);
|
||||
|
||||
/**
|
||||
* Return the standard filter listener for the given tag, or null.
|
||||
*/
|
||||
public FilterListener getFilterListener(String tag);
|
||||
|
||||
/**
|
||||
* Return the standard filter listener for the given tag, or null.
|
||||
*/
|
||||
public AggregateListener getAggregateListener(String tag);
|
||||
|
||||
/**
|
||||
* Create a new key for caching compiled query information. May be null.
|
||||
*/
|
||||
public Object newCompilationKey();
|
||||
|
||||
/**
|
||||
* Create a new compilation for this query. May be null.
|
||||
*/
|
||||
public Object newCompilation();
|
||||
|
||||
/**
|
||||
* Populate internal data from compilation.
|
||||
*/
|
||||
public void populateFromCompilation(Object comp);
|
||||
|
||||
/**
|
||||
* Invalidate any internal compilation state.
|
||||
*/
|
||||
public void invalidateCompilation();
|
||||
|
||||
/**
|
||||
* True if this query supports datastore execution, false if it
|
||||
* can only run in memory.
|
||||
*/
|
||||
public boolean supportsDataStoreExecution();
|
||||
|
||||
/**
|
||||
* True if this query supports in-memory execution, false if it
|
||||
* can only run against the datastore.
|
||||
*/
|
||||
public boolean supportsInMemoryExecution();
|
||||
|
||||
/**
|
||||
* Return an executor for in-memory execution of this query.
|
||||
* Executors must be cachable and thread safe. If this class returns
|
||||
* true from {@link #supportsAbstractExecutors}, the given metadata
|
||||
* will always be for the candidate class of this query, or possibly
|
||||
* null if the candidate class is not itself persistence capable (like
|
||||
* an interface or abstract base class). Otherwise, the given type will
|
||||
* be a mapped class.
|
||||
*
|
||||
* @param subs whether to include dependent mapped subclasses in the
|
||||
* results; independent subclasses should never be included
|
||||
*/
|
||||
public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs);
|
||||
|
||||
/**
|
||||
* Return an executor for datastore execution of this query.
|
||||
* Executors must be cachable and thread safe. If this class returns
|
||||
* true from {@link #supportsAbstractExecutors}, the given metadata
|
||||
* will always be for the candidate class of this query, or possibly
|
||||
* null if the candidate class is not itself persistence capable (like
|
||||
* an interface or abstract base class). Otherwise, the given type will
|
||||
* be a mapped class.
|
||||
*
|
||||
* @param subs whether to include dependent mapped subclasses in the
|
||||
* results; independent subclasses should never be included
|
||||
*/
|
||||
public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs);
|
||||
|
||||
/**
|
||||
* Return true if this query supports execution against abstract or
|
||||
* interface types. Returns false by default, meaning we will only
|
||||
* request executors for persistent classes. In this case, we will
|
||||
* automatically combine the results of the executors for all
|
||||
* implementing classes if we execute a query for an interface for
|
||||
* abstract type.
|
||||
*/
|
||||
public boolean supportsAbstractExecutors();
|
||||
|
||||
/**
|
||||
* Whether this query requires a candidate class.
|
||||
*/
|
||||
public boolean requiresCandidateType();
|
||||
|
||||
/**
|
||||
* Whether this query requires parameters to be declared.
|
||||
*/
|
||||
public boolean requiresParameterDeclarations();
|
||||
|
||||
/**
|
||||
* Whether this query supports declared parameters.
|
||||
*/
|
||||
public boolean supportsParameterDeclarations();
|
||||
|
||||
/**
|
||||
* A query result range.
|
||||
*/
|
||||
public static class Range {
|
||||
public long start = 0L;
|
||||
public long end = Long.MAX_VALUE;
|
||||
public boolean lrs = false;
|
||||
|
||||
public Range() {
|
||||
}
|
||||
|
||||
public Range(long start, long end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An executor provides a uniform interface to the mechanism for executing
|
||||
* either an in-memory or datastore query. In the common case, the
|
||||
* {@link #executeQuery} method will be called before other methods,
|
||||
* though this is not guaranteed.
|
||||
*
|
||||
* @author Marc Prud'hommeaux
|
||||
*/
|
||||
public static interface Executor {
|
||||
|
||||
/**
|
||||
* Return the result of executing this query with the given parameter
|
||||
* values. If this query is a projection and this executor does not
|
||||
* pack results itself, each element of the returned result object
|
||||
* provider should be an object array containing the projection values.
|
||||
*
|
||||
* @param lrs true if the query result should be treated as a
|
||||
* large result set, assuming the query is not an
|
||||
* aggregate and does not have grouping
|
||||
* @see #isPacking
|
||||
*/
|
||||
public ResultObjectProvider executeQuery(StoreQuery q, Object[] params,
|
||||
Range range);
|
||||
|
||||
/**
|
||||
* Deleted the objects that result from the execution of the
|
||||
* query, retuning the number of objects that were deleted.
|
||||
*/
|
||||
public Number executeDelete(StoreQuery q, Object[] params);
|
||||
|
||||
/**
|
||||
* Updates the objects that result from the execution of the
|
||||
* query, retuning the number of objects that were updated.
|
||||
*/
|
||||
public Number executeUpdate(StoreQuery q, Object[] params);
|
||||
|
||||
/**
|
||||
* Return a description of the commands that will be sent to
|
||||
* the datastore in order to execute the query.
|
||||
*/
|
||||
public String[] getDataStoreActions(StoreQuery q, Object[] params,
|
||||
Range range);
|
||||
|
||||
/**
|
||||
* Validate components of query.
|
||||
*/
|
||||
public void validate(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Mutate the given range to set any range information stored in
|
||||
* the query string and/or parameters.
|
||||
*/
|
||||
public void getRange(StoreQuery q, Object[] params, Range range);
|
||||
|
||||
/**
|
||||
* Extract the value of the <code>orderIndex</code>th ordering
|
||||
* expression in {@link Query#getOrderingClauses} from the
|
||||
* given result object. The result object will be an object from
|
||||
* the result object provider returned from {@link #executeQuery}.
|
||||
* This method is used when several result lists have to be merged
|
||||
* in memory. If this exeuctor's parent query supports executors on
|
||||
* abstract or interface classes, this method will not be used.
|
||||
*
|
||||
* @see StoreQuery#supportsAbstractExecutors
|
||||
*/
|
||||
public Object getOrderingValue(StoreQuery q, Object[] params,
|
||||
Object resultObject, int orderIndex);
|
||||
|
||||
/**
|
||||
* Return the ordering direction for all ordering clauses, or empty
|
||||
* array if none.
|
||||
*/
|
||||
public boolean[] getAscending(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return true if this executor packs projections into the result
|
||||
* class itself. Executors for query languages that allow projections
|
||||
* without result clauses must return true and perform the result
|
||||
* packing themselves.
|
||||
*/
|
||||
public boolean isPacking(StoreQuery q);
|
||||
|
||||
/**
|
||||
* If this is not a projection but the candidate results are placed
|
||||
* into a result class with an alias, return that alias.
|
||||
*/
|
||||
public String getAlias(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return the alias for each projection element, or empty array
|
||||
* if not a projection.
|
||||
*/
|
||||
public String[] getProjectionAliases(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return the expected types of the projections used by this query,
|
||||
* or an empty array if not a projection.
|
||||
*/
|
||||
public Class[] getProjectionTypes(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return an array of all persistent classes used in this query, or
|
||||
* empty array if unknown.
|
||||
*/
|
||||
public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Returns the operation this executor is meant to execute.
|
||||
*
|
||||
* @see QueryOperations
|
||||
*/
|
||||
public int getOperation(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return true if the compiled query is an aggregate.
|
||||
*/
|
||||
public boolean isAggregate(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Whether the compiled query has grouping.
|
||||
*/
|
||||
public boolean hasGrouping(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return a map of parameter names to types. The returned
|
||||
* {@link Map#entrySet}'s {@link Iterator} must return values in the
|
||||
* order in which they were declared or used.
|
||||
*/
|
||||
public LinkedMap getParameterTypes(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Returns the result class, if any.
|
||||
*/
|
||||
public Class getResultClass(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return a map of {@link FieldMetaData} to update
|
||||
* {@link Constant}s, in cases where this query is for a bulk update.
|
||||
*/
|
||||
public Map getUpdates (StoreQuery q);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.map.LinkedMap;
|
||||
import org.apache.openjpa.kernel.exps.AggregateListener;
|
||||
import org.apache.openjpa.kernel.exps.Constant;
|
||||
import org.apache.openjpa.kernel.exps.FilterListener;
|
||||
import org.apache.openjpa.lib.rop.ResultObjectProvider;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
|
||||
/**
|
||||
* Component that executes queries against the datastore. For
|
||||
* expression-based queries, consider subclassing
|
||||
* {@link ExpressionStoreManagerQuery}.
|
||||
*
|
||||
* @author Abe White
|
||||
* @since 0.4.0
|
||||
*/
|
||||
public interface StoreQuery
|
||||
extends QueryOperations, Serializable {
|
||||
|
||||
// linkedmap doesn't allow a size of 0, so use 1
|
||||
public static final LinkedMap EMPTY_PARAMS = new LinkedMap(1, 1F);
|
||||
public static final ClassMetaData[] EMPTY_METAS = new ClassMetaData[0];
|
||||
public static final String[] EMPTY_STRINGS = new String[0];
|
||||
public static final Object[] EMPTY_OBJECTS = new Object[0];
|
||||
public static final Class[] EMPTY_CLASSES = new Class[0];
|
||||
public static final boolean[] EMPTY_BOOLEANS = new boolean[0];
|
||||
|
||||
/**
|
||||
* Return the query context that has been set.
|
||||
*/
|
||||
public QueryContext getContext();
|
||||
|
||||
/**
|
||||
* Set the current query context. This will be called before use.
|
||||
*/
|
||||
public void setContext(QueryContext ctx);
|
||||
|
||||
/**
|
||||
* This is invoked when the user or a facade creates a new query with
|
||||
* an object that the system does not recognize. Return true if
|
||||
* the object is recognized by the store, false otherwise.
|
||||
*/
|
||||
public boolean setQuery(Object query);
|
||||
|
||||
/**
|
||||
* Return the standard filter listener for the given tag, or null.
|
||||
*/
|
||||
public FilterListener getFilterListener(String tag);
|
||||
|
||||
/**
|
||||
* Return the standard filter listener for the given tag, or null.
|
||||
*/
|
||||
public AggregateListener getAggregateListener(String tag);
|
||||
|
||||
/**
|
||||
* Create a new key for caching compiled query information. May be null.
|
||||
*/
|
||||
public Object newCompilationKey();
|
||||
|
||||
/**
|
||||
* Create a new compilation for this query. May be null.
|
||||
*/
|
||||
public Object newCompilation();
|
||||
|
||||
/**
|
||||
* Populate internal data from compilation.
|
||||
*/
|
||||
public void populateFromCompilation(Object comp);
|
||||
|
||||
/**
|
||||
* Invalidate any internal compilation state.
|
||||
*/
|
||||
public void invalidateCompilation();
|
||||
|
||||
/**
|
||||
* True if this query supports datastore execution, false if it
|
||||
* can only run in memory.
|
||||
*/
|
||||
public boolean supportsDataStoreExecution();
|
||||
|
||||
/**
|
||||
* True if this query supports in-memory execution, false if it
|
||||
* can only run against the datastore.
|
||||
*/
|
||||
public boolean supportsInMemoryExecution();
|
||||
|
||||
/**
|
||||
* Return an executor for in-memory execution of this query.
|
||||
* Executors must be cachable and thread safe. If this class returns
|
||||
* true from {@link #supportsAbstractExecutors}, the given metadata
|
||||
* will always be for the candidate class of this query, or possibly
|
||||
* null if the candidate class is not itself persistence capable (like
|
||||
* an interface or abstract base class). Otherwise, the given type will
|
||||
* be a mapped class.
|
||||
*
|
||||
* @param subs whether to include dependent mapped subclasses in the
|
||||
* results; independent subclasses should never be included
|
||||
*/
|
||||
public Executor newInMemoryExecutor(ClassMetaData meta, boolean subs);
|
||||
|
||||
/**
|
||||
* Return an executor for datastore execution of this query.
|
||||
* Executors must be cachable and thread safe. If this class returns
|
||||
* true from {@link #supportsAbstractExecutors}, the given metadata
|
||||
* will always be for the candidate class of this query, or possibly
|
||||
* null if the candidate class is not itself persistence capable (like
|
||||
* an interface or abstract base class). Otherwise, the given type will
|
||||
* be a mapped class.
|
||||
*
|
||||
* @param subs whether to include dependent mapped subclasses in the
|
||||
* results; independent subclasses should never be included
|
||||
*/
|
||||
public Executor newDataStoreExecutor(ClassMetaData meta, boolean subs);
|
||||
|
||||
/**
|
||||
* Return true if this query supports execution against abstract or
|
||||
* interface types. Returns false by default, meaning we will only
|
||||
* request executors for persistent classes. In this case, we will
|
||||
* automatically combine the results of the executors for all
|
||||
* implementing classes if we execute a query for an interface for
|
||||
* abstract type.
|
||||
*/
|
||||
public boolean supportsAbstractExecutors();
|
||||
|
||||
/**
|
||||
* Whether this query requires a candidate class.
|
||||
*/
|
||||
public boolean requiresCandidateType();
|
||||
|
||||
/**
|
||||
* Whether this query requires parameters to be declared.
|
||||
*/
|
||||
public boolean requiresParameterDeclarations();
|
||||
|
||||
/**
|
||||
* Whether this query supports declared parameters.
|
||||
*/
|
||||
public boolean supportsParameterDeclarations();
|
||||
|
||||
public Object evaluate(Object value, Object ob, Object[] params,
|
||||
OpenJPAStateManager sm);
|
||||
|
||||
/**
|
||||
* A query result range.
|
||||
*/
|
||||
public static class Range {
|
||||
public long start = 0L;
|
||||
public long end = Long.MAX_VALUE;
|
||||
public boolean lrs = false;
|
||||
|
||||
public Range() {
|
||||
}
|
||||
|
||||
public Range(long start, long end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An executor provides a uniform interface to the mechanism for executing
|
||||
* either an in-memory or datastore query. In the common case, the
|
||||
* {@link #executeQuery} method will be called before other methods,
|
||||
* though this is not guaranteed.
|
||||
*
|
||||
* @author Marc Prud'hommeaux
|
||||
*/
|
||||
public static interface Executor {
|
||||
|
||||
/**
|
||||
* Return the result of executing this query with the given parameter
|
||||
* values. If this query is a projection and this executor does not
|
||||
* pack results itself, each element of the returned result object
|
||||
* provider should be an object array containing the projection values.
|
||||
*
|
||||
* @param lrs true if the query result should be treated as a
|
||||
* large result set, assuming the query is not an
|
||||
* aggregate and does not have grouping
|
||||
* @see #isPacking
|
||||
*/
|
||||
public ResultObjectProvider executeQuery(StoreQuery q, Object[] params,
|
||||
Range range);
|
||||
|
||||
/**
|
||||
* Deleted the objects that result from the execution of the
|
||||
* query, retuning the number of objects that were deleted.
|
||||
*/
|
||||
public Number executeDelete(StoreQuery q, Object[] params);
|
||||
|
||||
/**
|
||||
* Updates the objects that result from the execution of the
|
||||
* query, retuning the number of objects that were updated.
|
||||
*/
|
||||
public Number executeUpdate(StoreQuery q, Object[] params);
|
||||
|
||||
/**
|
||||
* Return a description of the commands that will be sent to
|
||||
* the datastore in order to execute the query.
|
||||
*/
|
||||
public String[] getDataStoreActions(StoreQuery q, Object[] params,
|
||||
Range range);
|
||||
|
||||
/**
|
||||
* Validate components of query.
|
||||
*/
|
||||
public void validate(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Mutate the given range to set any range information stored in
|
||||
* the query string and/or parameters.
|
||||
*/
|
||||
public void getRange(StoreQuery q, Object[] params, Range range);
|
||||
|
||||
/**
|
||||
* Extract the value of the <code>orderIndex</code>th ordering
|
||||
* expression in {@link Query#getOrderingClauses} from the
|
||||
* given result object. The result object will be an object from
|
||||
* the result object provider returned from {@link #executeQuery}.
|
||||
* This method is used when several result lists have to be merged
|
||||
* in memory. If this exeuctor's parent query supports executors on
|
||||
* abstract or interface classes, this method will not be used.
|
||||
*
|
||||
* @see StoreQuery#supportsAbstractExecutors
|
||||
*/
|
||||
public Object getOrderingValue(StoreQuery q, Object[] params,
|
||||
Object resultObject, int orderIndex);
|
||||
|
||||
/**
|
||||
* Return the ordering direction for all ordering clauses, or empty
|
||||
* array if none.
|
||||
*/
|
||||
public boolean[] getAscending(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return true if this executor packs projections into the result
|
||||
* class itself. Executors for query languages that allow projections
|
||||
* without result clauses must return true and perform the result
|
||||
* packing themselves.
|
||||
*/
|
||||
public boolean isPacking(StoreQuery q);
|
||||
|
||||
/**
|
||||
* If this is not a projection but the candidate results are placed
|
||||
* into a result class with an alias, return that alias.
|
||||
*/
|
||||
public String getAlias(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return the alias for each projection element, or empty array
|
||||
* if not a projection.
|
||||
*/
|
||||
public String[] getProjectionAliases(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return the expected types of the projections used by this query,
|
||||
* or an empty array if not a projection.
|
||||
*/
|
||||
public Class[] getProjectionTypes(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return an array of all persistent classes used in this query, or
|
||||
* empty array if unknown.
|
||||
*/
|
||||
public ClassMetaData[] getAccessPathMetaDatas(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Returns the operation this executor is meant to execute.
|
||||
*
|
||||
* @see QueryOperations
|
||||
*/
|
||||
public int getOperation(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return true if the compiled query is an aggregate.
|
||||
*/
|
||||
public boolean isAggregate(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Whether the compiled query has grouping.
|
||||
*/
|
||||
public boolean hasGrouping(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return a map of parameter names to types. The returned
|
||||
* {@link Map#entrySet}'s {@link Iterator} must return values in the
|
||||
* order in which they were declared or used.
|
||||
*/
|
||||
public LinkedMap getParameterTypes(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Returns the result class, if any.
|
||||
*/
|
||||
public Class getResultClass(StoreQuery q);
|
||||
|
||||
/**
|
||||
* Return a map of {@link FieldMetaData} to update
|
||||
* {@link Constant}s, in cases where this query is for a bulk update.
|
||||
*/
|
||||
public Map getUpdates (StoreQuery q);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue