You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2009/07/20 19:49:37 UTC
svn commit: r795934 [1/2] - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/
openjpa-jdbc/src/main/jav...
Author: faywang
Date: Mon Jul 20 17:49:36 2009
New Revision: 795934
URL: http://svn.apache.org/viewvc?rev=795934&view=rev
Log:
OPENJPA-1185: commit subquery overhaul on behalf of Catalina
Added:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java (with props)
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Joins.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SubQ.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subquery.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestSubquery.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Mon Jul 20 17:49:36 2009
@@ -30,7 +30,6 @@
import java.util.Map;
import org.apache.openjpa.event.LifecycleEventManager;
-import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.kernel.exps.ExpContext;
import org.apache.openjpa.jdbc.kernel.exps.GetColumn;
import org.apache.openjpa.jdbc.kernel.exps.JDBCExpressionFactory;
@@ -46,20 +45,20 @@
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
import org.apache.openjpa.jdbc.schema.Column;
-import org.apache.openjpa.jdbc.schema.ForeignKey;
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.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.SelectImpl;
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.QueryContext;
import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.kernel.exps.Constant;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.ExpressionParser;
import org.apache.openjpa.kernel.exps.FilterListener;
@@ -143,11 +142,28 @@
protected ExpressionFactory getExpressionFactory(ClassMetaData meta) {
return new JDBCExpressionFactory((ClassMapping) meta);
}
+
+ private void resetSelect(Context ctx) {
+ List<Context> subselCtxs = ctx.getSubselContexts();
+ if (subselCtxs != null) {
+ for (Context subselCtx : subselCtxs) {
+ SelectImpl sel = (SelectImpl)subselCtx.getSelect();
+ sel.reset();
+ resetSelect(subselCtx);
+ }
+ }
+ }
protected ResultObjectProvider executeQuery(Executor ex,
ClassMetaData base, ClassMetaData[] metas, boolean subclasses,
ExpressionFactory[] facts, QueryExpressions[] exps, Object[] params,
Range range) {
+ Context expCtx = exps[0].ctx();
+ if (expCtx != null) {
+ expCtx.resetAliasCount();
+ expCtx.setSelect(null);
+ resetSelect(expCtx);
+ }
if (metas.length > 1 && exps[0].isAggregate())
throw new UserException(Localizer.forPackage(JDBCStoreQuery.class).
get("mult-mapping-aggregate", Arrays.asList(metas)));
@@ -449,6 +465,13 @@
private Number executeBulkOperation(ClassMetaData[] metas,
boolean subclasses, ExpressionFactory[] facts, QueryExpressions[] exps,
Object[] params, Map updates) {
+ Context expCtx = exps[0].ctx();
+ if (ctx != null) {
+ expCtx.resetAliasCount();
+ expCtx.setSelect(null);
+ resetSelect(expCtx);
+ }
+
// we cannot execute a bulk delete statement when have mappings in
// multiple tables, so indicate we want to use in-memory with null
ClassMapping[] mappings = (ClassMapping[]) metas;
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java Mon Jul 20 17:49:36 2009
@@ -114,5 +114,9 @@
public Path getPath() {
return null;
}
+
+ public String getName() {
+ return null;
+ }
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java Mon Jul 20 17:49:36 2009
@@ -27,6 +27,7 @@
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
@@ -217,4 +218,14 @@
public XMLMetaData getXmlMapping() {
return null;
}
+
+ public void setSchemaAlias(String schemaAlias) {
+ }
+
+ public String getSchemaAlias() {
+ return null;
+ }
+
+ public void setSubqueryContext(Context conext) {
+ }
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java Mon Jul 20 17:49:36 2009
@@ -167,7 +167,8 @@
}
public Expression not(Expression exp) {
- if (HasContainsExpressionVisitor.hasContains(exp))
+ if (!(exp instanceof IsNotEmptyExpression) &&
+ HasContainsExpressionVisitor.hasContains(exp))
return new NotContainsExpression((Exp) exp);
return new NotExpression((Exp) exp);
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Lit.java Mon Jul 20 17:49:36 2009
@@ -36,6 +36,7 @@
private Object _val;
private int _ptype;
private boolean _isRaw;
+ private Object _rawVal;
/**
* Constructor. Supply literal value.
@@ -46,6 +47,8 @@
}
public Class getType() {
+ if (_isRaw && _rawVal != null)
+ return Raw.class;
return (_val == null) ? Object.class : _val.getClass();
}
@@ -77,6 +80,10 @@
_isRaw = isRaw;
}
+ public Object getRawValue() {
+ return _rawVal;
+ }
+
public ExpState initialize(Select sel, ExpContext ctx, int flags) {
return new LitExpState();
}
@@ -120,7 +127,7 @@
if (!isOrdinal)
value.append("'");
lstate.sqlValue = new Raw(value.toString());
- setValue(lstate.sqlValue);
+ _rawVal = lstate.sqlValue;
}
sql.appendValue(lstate.sqlValue, lstate.getColumn(index));
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotContainsExpression.java Mon Jul 20 17:49:36 2009
@@ -67,6 +67,10 @@
Select sub = ctx.store.getSQLFactory().newSelect();
sub.setParent(sel, null);
+ // this subselect has the same context as its parent
+ sub.setContext(sel.ctx());
+ // the context select should still belong to parent
+ sub.ctx().setSelect(sel);
ExpState estate = _exp.initialize(sub, ctx, ((NotContainsExpState)
state).contains);
sub.where(sub.and(null, estate.joins));
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Mon Jul 20 17:49:36 2009
@@ -45,6 +45,7 @@
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.kernel.exps.CandidatePath;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
@@ -82,6 +83,7 @@
private boolean _cid = false;
private FieldMetaData _xmlfield = null;
private boolean _keyPath = false;
+ private String _schemaAlias = null;
/**
* Return a path starting with the 'this' ptr.
@@ -99,10 +101,12 @@
PCPath other = var.getPCPath();
Action action = new Action();
+ action.var = var.getName();
if (other == null) {
_type = UNBOUND_VAR;
action.op = Action.UNBOUND_VAR;
action.data = var;
+ _schemaAlias = var.getName();
} else {
// bound variable; copy path
_type = UNACCESSED_VAR;
@@ -111,6 +115,7 @@
action.op = Action.VAR;
action.data = var.getName();
+ _schemaAlias = other._schemaAlias;
}
_actions.add(action);
_cast = var.getType(); // initial type is var type
@@ -131,6 +136,22 @@
_varName = sub.getCandidateAlias();
}
+ public void setSchemaAlias(String schemaAlias) {
+ if (_schemaAlias == null)
+ _schemaAlias = schemaAlias;
+ }
+
+ public String getSchemaAlias() {
+ return _schemaAlias;
+ }
+
+ public void setSubqueryContext(Context context) {
+ Action action = lastFieldAction();
+ if (action == null)
+ return;
+ action.context = context;
+ }
+
/**
* Set the path as a binding of the given variable.
*/
@@ -420,8 +441,7 @@
if (act != null && act.op == Action.GET_XPATH)
return ((XMLMetaData) act.data).getType();
- FieldMetaData fld = act == null ? null :
- (FieldMetaData) act.data;
+ FieldMetaData fld = (act == null) ? null : (FieldMetaData) act.data;
boolean key = act != null && act.op == Action.GET_KEY;
if (fld != null) {
switch (fld.getDeclaredTypeCode()) {
@@ -457,6 +477,8 @@
boolean forceOuter = false;
ClassMapping rel = _candidate;
+ sel.setSchemaAlias(_schemaAlias);
+
// iterate to the final field
ClassMapping owner;
ClassMapping from, to;
@@ -464,14 +486,27 @@
Variable var;
Iterator itr = (_actions == null) ? null : _actions.iterator();
FieldMapping field = null;
+ Action prevaction = null;
+ boolean isCorrelatedPath = false;
+ boolean fromParentRootInSubselect = navigateFromParentRootInSubselect(sel);
+
while (itr != null && itr.hasNext()) {
action = (Action) itr.next();
// treat subqueries like variables for alias generation purposes
- if (action.op == Action.VAR)
- pstate.joins = pstate.joins.setVariable((String) action.data);
- else if (action.op == Action.SUBQUERY)
+ if (action.op == Action.VAR) {
+ if (sel.getParent() != null && action.var != null &&
+ prevaction != null && prevaction.data != null &&
+ sel.ctx().getVariable(action.var) == null) {
+ //System.out.println("Correlated action var="+action.var);
+ isCorrelatedPath = true;
+ pstate.joins = pstate.joins.setCorrelatedVariable(action.var);
+ } else
+ pstate.joins = pstate.joins.setVariable((String) action.data);
+ }
+ else if (action.op == Action.SUBQUERY) {
pstate.joins = pstate.joins.setSubselect((String) action.data);
+ }
else if (action.op == Action.UNBOUND_VAR) {
// unbound vars are cross-joined to the candidate table
var = (Variable) action.data;
@@ -479,8 +514,16 @@
if (rel == null)
throw new IllegalArgumentException(_loc.get(
"invalid-unbound-var", var.getName()).toString());
- pstate.joins = pstate.joins.setVariable(var.getName());
- pstate.joins = pstate.joins.crossJoin(_candidate.getTable(),
+
+ if (sel.getParent() != null && action.var != null &&
+ sel.ctx().getVariable(action.var) == null) {
+ //System.out.println("Correlated action var="+action.var);
+ isCorrelatedPath = true;
+ pstate.joins = pstate.joins.setCorrelatedVariable(var.getName());
+ } else
+ pstate.joins = pstate.joins.setVariable(var.getName());
+
+ pstate.joins = pstate.joins.crossJoin(_candidate.getTable(),
rel.getTable());
} else {
// move past the previous field, if any
@@ -496,6 +539,13 @@
pstate.cmpfield = field;
break;
}
+
+ if (fromParentRootInSubselect) {
+ isCorrelatedPath = true;
+ pstate.joins = pstate.joins.setCorrelatedVariable(_schemaAlias);
+ pstate.joins.setJoinContext(null);
+ }
+
rel = traverseField(pstate, key, forceOuter, false);
}
@@ -543,6 +593,9 @@
if (action.op == Action.GET_XPATH)
break;
}
+ prevaction = action;
+ if (prevaction != null && prevaction.context != null)
+ pstate.joins = pstate.joins.setJoinContext(prevaction.context);
}
if (_varName != null)
pstate.joins = pstate.joins.setVariable(_varName);
@@ -557,10 +610,56 @@
if ((flags & JOIN_REL) != 0)
joinRelation(pstate, key, forceOuter || (flags & FORCE_OUTER) != 0,
false);
+ if (isCorrelatedPath) {
+ // check if there are joins that belong to parent
+ pstate.joins.moveJoinsToParent();
+ }
+ pstate.joins.setJoinContext(null);
+
+ if (_actions == null) {
+ String subqAlias = findSubqAlias(sel);
+ pstate.joins = pstate.joins.setSubselect(subqAlias);
+ pstate.joins.setCorrelatedVariable(_schemaAlias);
+ }
+
return pstate;
}
+
+ public String findSubqAlias(Select sel) {
+ Select pSel = sel.getParent();
+ if (pSel == null)
+ return null;
+ Context pCtx = pSel.ctx();
+ if (pCtx.subquery == null)
+ return null;
+ if (pCtx.getSchema(_schemaAlias) != null)
+ return ((SubQ)pCtx.subquery).getCandidateAlias();
+ return findSubqAlias(pSel);
+ }
/**
+ * When a PCPath is in subselect, and it is simply a navigation
+ * from the parent root, the joins involved in this PCPath
+ * must happen in the main select.
+ */
+ private boolean navigateFromParentRootInSubselect(Select sel) {
+ if (sel.getParent() == null)
+ return false;
+ Iterator itr = (_actions == null) ? null : _actions.iterator();
+ boolean navigateFromRoot = false;
+ boolean hasVar = false;
+ boolean startsWithSubquery = false;
+ while (itr != null && itr.hasNext()) {
+ Action action = (Action) itr.next();
+ if (action.op == Action.VAR)
+ hasVar = true;
+ else if (action.op == Action.SUBQUERY)
+ startsWithSubquery = true;
+ }
+ return !hasVar && !startsWithSubquery && sel.ctx().getSchema(_schemaAlias) == null;
+ }
+
+ /**
* Return whether the given source field joins to the given target field.
*/
private static boolean isJoinedField(FieldMapping src, boolean key,
@@ -846,6 +945,8 @@
public void appendTo(Select sel, ExpContext ctx, ExpState state,
SQLBuffer sql, int index) {
Column col = getColumns(state)[index];
+ if (sel != null)
+ sel.setSchemaAlias(_schemaAlias);
// if select is null, it means we are not aliasing columns
// (e.g., during a bulk update)
@@ -977,6 +1078,8 @@
public int op = -1;
public Object data = null;
+ public String var = null;
+ public Context context = null;
public String toString() {
return op + "|" + data;
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SelectConstructor.java Mon Jul 20 17:49:36 2009
@@ -20,6 +20,7 @@
import java.io.Serializable;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@@ -29,8 +30,10 @@
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.exps.AbstractExpressionVisitor;
import org.apache.openjpa.kernel.exps.Constant;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.kernel.exps.Expression;
import org.apache.openjpa.kernel.exps.QueryExpressions;
+import org.apache.openjpa.kernel.exps.Subquery;
import org.apache.openjpa.kernel.exps.Value;
/**
@@ -43,6 +46,7 @@
implements Serializable {
private boolean _extent = false;
+ private Select _subselect = null;
/**
* Return true if we know the select to have on criteria; to be an extent.
@@ -53,6 +57,10 @@
return _extent;
}
+ public void setSubselect(Select subselect) {
+ _subselect = subselect;
+ }
+
/**
* Evaluate the expression, returning a new select and filling in any
* associated expression state. Use {@link #select} to then select the data.
@@ -114,10 +122,25 @@
*/
private Select newSelect(ExpContext ctx, Select parent,
String alias, QueryExpressions exps, QueryExpressionsState state) {
- Select sel = ctx.store.getSQLFactory().newSelect();
+ Select sel = parent != null ? _subselect
+ : ctx.store.getSQLFactory().newSelect();
sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
sel.setJoinSyntax(ctx.fetch.getJoinSyntax());
sel.setParent(parent, alias);
+
+ if (sel.ctx() == null)
+ sel.setContext(exps.ctx());
+
+ if (parent == null && exps.ctx().getSubselContexts() != null) {
+ // this is the case subselect was created before parent got created
+ List<Context> subselCtxs = exps.ctx().getSubselContexts();
+ for (Context subselCtx : subselCtxs) {
+ Select subsel = (Select) subselCtx.getSelect();
+ Subquery subquery = subselCtx.getSubquery();
+ subsel.setParent(sel, subquery.getCandidateAlias());
+ }
+ }
+
initialize(sel, ctx, exps, state);
if (!sel.getAutoDistinct()) {
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java Mon Jul 20 17:49:36 2009
@@ -20,6 +20,7 @@
import java.sql.SQLException;
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
@@ -38,18 +39,19 @@
*
* @author Abe White
*/
-class SubQ
+public class SubQ
extends AbstractVal
implements Subquery {
private final ClassMapping _candidate;
private final boolean _subs;
- private final String _alias;
+ private final String _subqAlias;
private final SelectConstructor _cons = new SelectConstructor();
private Class _type = null;
private ClassMetaData _meta = null;
private QueryExpressions _exps = null;
+ private Select _select = null;
/**
* Constructor. Supply candidate, whether subclasses are included in
@@ -58,7 +60,14 @@
public SubQ(ClassMapping candidate, boolean subs, String alias) {
_candidate = candidate;
_subs = subs;
- _alias = alias;
+ _subqAlias = alias;
+ _select = (((JDBCConfiguration) candidate.getMappingRepository().
+ getConfiguration()).getSQLFactoryInstance().newSelect());
+ _cons.setSubselect(_select);
+ }
+
+ public Object getSelect() {
+ return _select;
}
/**
@@ -67,6 +76,14 @@
public ClassMapping getCandidate() {
return _candidate;
}
+
+ public boolean getSubs() {
+ return _subs;
+ }
+
+ public String getSubqAlias() {
+ return _subqAlias;
+ }
public Class getType() {
if (_exps != null && _type == null) {
@@ -93,16 +110,19 @@
}
public String getCandidateAlias() {
- return _alias;
+ return _subqAlias;
}
public void setQueryExpressions(QueryExpressions query) {
_exps = query;
+ _select.setContext(query.ctx());
}
public ExpState initialize(Select sel, ExpContext ctx, int flags) {
- if (_exps.projections.length == 1)
- return ((Val) _exps.projections[0]).initialize(sel, ctx, flags);
+ _select.setParent(sel, null);
+ if (_exps.projections.length == 1) {
+ return ((Val) _exps.projections[0]).initialize(_select, ctx, flags);
+ }
return ExpState.NULL;
}
@@ -180,7 +200,7 @@
private void appendTo(Select sel, ExpContext ctx, ExpState state,
SQLBuffer sql, int index, boolean size) {
QueryExpressionsState substate = new QueryExpressionsState();
- Select sub = _cons.evaluate(ctx, sel, _alias, _exps, substate);
+ Select sub = _cons.evaluate(ctx, sel, _subqAlias, _exps, substate);
_cons.select(sub, ctx, _candidate, _subs, _exps, substate,
JDBCFetchConfiguration.EAGER_NONE);
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java Mon Jul 20 17:49:36 2009
@@ -583,6 +583,7 @@
_unq = _info.getJoinUnique(this, false, adapt);
_joinTableUniques = _info.getJoinTableUniques(this, false, adapt);
_idx = _info.getJoinIndex(this, adapt);
+ table.setAssociation();
}
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/Table.java Mon Jul 20 17:49:36 2009
@@ -62,7 +62,8 @@
private Unique[] _unqs = null;
private String _comment = null;
private int _lineNum = 0;
- private int _colNum = 0;
+ private int _colNum = 0;
+ private boolean _isAssociation = false;
/**
* Default constructor.
@@ -84,6 +85,14 @@
_schema = schema;
}
+ public void setAssociation() {
+ _isAssociation = true;
+ }
+
+ public boolean isAssociation() {
+ return _isAssociation;
+ }
+
/**
* Called when the table is removed from its schema. Removes all table
* members, and invalidates the table.
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java Mon Jul 20 17:49:36 2009
@@ -47,6 +47,7 @@
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.UnsupportedException;
@@ -885,7 +886,22 @@
return this;
}
+ public Joins setJoinContext(Context context) {
+ return this;
+ }
+
public void appendTo(SQLBuffer buf) {
}
+
+ public Joins setCorrelatedVariable(String var) {
+ return this;
+ }
+
+ public String getCorrelatedVariable() {
+ return null;
+ }
+
+ public void moveJoinsToParent() {
+ }
}
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Mon Jul 20 17:49:36 2009
@@ -2197,14 +2197,59 @@
Iterator itr = sel.getJoinIterator();
boolean first = true;
while (itr.hasNext()) {
- fromSQL.append(toSQL92Join((Join) itr.next(), forUpdate,
+ Join join = (Join) itr.next();
+ if (correlatedJoinCondition(join, sel))
+ continue;
+ fromSQL.append(toSQL92Join(sel, join, forUpdate,
first));
first = false;
+ if (itr.hasNext() && join.isCorrelated()) {
+ fromSQL.append(", ");
+ first = true;
+ }
+ }
+
+ for (Iterator itr2 = aliases.iterator(); itr2.hasNext();) {
+ String tableAlias = itr2.next().toString();
+ if (fromSQL.getSQL().indexOf(tableAlias) == -1) {
+ if (!first)
+ fromSQL.append(", ");
+ fromSQL.append(tableAlias);
+ first = false;
+ }
}
}
return fromSQL;
}
+ private boolean correlatedJoinCondition(Join join, Select sel) {
+ if (!join.isCorrelated())
+ return false;
+ Iterator itr = sel.getJoinIterator();
+ boolean skip = false;
+ //if table1 in join is in the main query, table2 is in
+ //subquery, and table2 participates in other joins
+ //in subquery, the join condition can only be placed in
+ //the where clause in the subquery
+ while (itr.hasNext()) {
+ Join join1 = (Join) itr.next();
+ if (join == join1)
+ continue;
+ if (join.getIndex2() == join1.getIndex1() ||
+ join.getIndex2() == join1.getIndex2()) {
+ skip = true;
+ if (join.getForeignKey() != null){
+ SQLBuffer where = new SQLBuffer(this);
+ where.append("(").append(toTraditionalJoin(join)).append(")");
+ sel.where(where.getSQL());
+ }
+ break;
+ }
+ }
+ return skip;
+ }
+
+
/**
* Return the FROM clause for a select that selects from a tmp table
* created by an inner select.
@@ -2308,9 +2353,11 @@
* Use the given join instance to create SQL joining its tables in
* the SQL92 style.
*/
- public SQLBuffer toSQL92Join(Join join, boolean forUpdate, boolean first) {
+ public SQLBuffer toSQL92Join(Select sel, Join join, boolean forUpdate,
+ boolean first) {
SQLBuffer buf = new SQLBuffer(this);
- if (first) {
+ boolean corelated = join.isCorrelated();
+ if (first && !corelated) {
buf.append(join.getTable1()).append(" ").
append(join.getAlias1());
if (forUpdate && tableForUpdateClause != null)
@@ -2318,23 +2365,31 @@
}
buf.append(" ");
- if (join.getType() == Join.TYPE_OUTER)
- buf.append(outerJoinClause);
- else if (join.getType() == Join.TYPE_INNER)
- buf.append(innerJoinClause);
- else // cross
- buf.append(crossJoinClause);
- buf.append(" ");
+ if (!corelated) {
+ if (join.getType() == Join.TYPE_OUTER)
+ buf.append(outerJoinClause);
+ else if (join.getType() == Join.TYPE_INNER)
+ buf.append(innerJoinClause);
+ else // cross
+ buf.append(crossJoinClause);
+ buf.append(" ");
+ }
buf.append(join.getTable2()).append(" ").append(join.getAlias2());
if (forUpdate && tableForUpdateClause != null)
buf.append(" ").append(tableForUpdateClause);
- if (join.getForeignKey() != null)
- buf.append(" ON ").append(toTraditionalJoin(join));
- else if (requiresConditionForCrossJoin &&
- join.getType() == Join.TYPE_CROSS)
- buf.append(" ON (1 = 1)");
+ if (!corelated) {
+ if (join.getForeignKey() != null)
+ buf.append(" ON ").append(toTraditionalJoin(join));
+ else if (requiresConditionForCrossJoin &&
+ join.getType() == Join.TYPE_CROSS)
+ buf.append(" ON (1 = 1)");
+ } else if (join.getForeignKey() != null){
+ SQLBuffer where = new SQLBuffer(this);
+ where.append("(").append(toTraditionalJoin(join)).append(")");
+ sel.where(where.getSQL());
+ }
return buf;
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java Mon Jul 20 17:49:36 2009
@@ -45,6 +45,8 @@
private int _subs;
private Joins _joins;
private boolean _inverse;
+ private boolean _correlated = false;
+ private boolean _isNotMyJoin = false;
/**
* Constructor for inner and outer joins.
@@ -189,5 +191,21 @@
return null;
}
}
+
+ public boolean isCorrelated() {
+ return _correlated;
+ }
+
+ public void setCorrelated() {
+ _correlated = true;
+ }
+
+ public boolean isNotMyJoin() {
+ return _isNotMyJoin;
+ }
+
+ public void setIsNotMyJoin() {
+ _isNotMyJoin = true;
+ }
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Joins.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Joins.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Joins.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Joins.java Mon Jul 20 17:49:36 2009
@@ -21,6 +21,7 @@
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.kernel.exps.Context;
/**
* Tracks joins made when traversing relations in a select.
@@ -77,4 +78,28 @@
* Set the subquery alias.
*/
public Joins setSubselect(String alias);
+
+ /**
+ * Set subquery context when traversing into the next join is
+ * in transition from parent context to subquery.
+ * @param context
+ */
+ public Joins setJoinContext(Context context);
+
+ /**
+ * Set the correlated variable name being traversed into
+ * with the next join.
+ */
+ public Joins setCorrelatedVariable(String var);
+
+ /**
+ * Return correlated variable name
+ * @return
+ */
+ public String getCorrelatedVariable();
+
+ /**
+ * Move joins that belong to subquery's parent
+ */
+ public void moveJoinsToParent();
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java Mon Jul 20 17:49:36 2009
@@ -30,6 +30,7 @@
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.kernel.exps.Value;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.schema.Column;
@@ -880,6 +881,18 @@
boolean force) {
sel.setExpectedResultCount(expectedResultCount, force);
}
+
+ public void setContext(Context context) {
+ sel.setContext(context);
+ }
+
+ public Context ctx() {
+ return sel.ctx();
+ }
+
+ public void setSchemaAlias(String schemaAlias) {
+ sel.setSchemaAlias(schemaAlias);
+ }
}
/**
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java Mon Jul 20 17:49:36 2009
@@ -30,6 +30,7 @@
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.kernel.exps.Value;
+import org.apache.openjpa.kernel.exps.Context;
/**
* Abstraction of a SQL SELECT statement.
@@ -701,4 +702,21 @@
* Return the alias for the given column, without creating new table alias
*/
public String getColumnAlias(Column col, Object path);
+
+ /**
+ * Set JPQL query context for this select
+ * @param context
+ */
+ public void setContext(Context context);
+
+ /**
+ * Return the JPQL query context of this select
+ */
+ public Context ctx();
+
+ /**
+ * Record the initial schemaAlias of a join path
+ * @param schemaAlias
+ */
+ public void setSchemaAlias(String schemaAlias);
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java Mon Jul 20 17:49:36 2009
@@ -26,7 +26,6 @@
import java.sql.Types;
import java.util.AbstractList;
import java.util.ArrayList;
-import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -56,6 +55,7 @@
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.kernel.exps.Value;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.ApplicationIds;
@@ -119,9 +119,6 @@
// 'parent.address.street' for the purposes of comparisons
private Map _aliases = null;
- // to cache table alias using Table as the key
- private Map _tableAliases = null;
-
// map of indexes to table aliases like 'TABLENAME t0'
private SortedMap _tables = null;
@@ -165,13 +162,12 @@
// from select if this select selects from a tmp table created by another
private SelectImpl _from = null;
protected SelectImpl _outer = null;
-
- // bitSet indicating if an alias is removed from parent select
- // bit 0 : correspond to alias 0
- // bit 1 : correspond to alias 1, etc.
- // if the bit is set, the corresponding alias has been removed from parent
- // and recorded under subselect.
- private BitSet _removedAliasFromParent = new BitSet(16);
+
+ // JPQL Query context this select is associated with
+ private Context _ctx = null;
+
+ // A path navigation is begin with this schema alias
+ private String _schemaAlias = null;
/**
* Helper method to return the proper table alias for the given alias index.
@@ -206,6 +202,21 @@
_selects._dict = _dict;
}
+ public void setContext(Context context) {
+ if (_ctx == null) {
+ _ctx = context;
+ _ctx.setSelect(this);
+ }
+ }
+
+ public Context ctx() {
+ return _ctx;
+ }
+
+ public void setSchemaAlias(String schemaAlias) {
+ _schemaAlias = schemaAlias;
+ }
+
/////////////////////////////////
// SelectExecutor implementation
/////////////////////////////////
@@ -521,7 +532,7 @@
public void setParent(Select parent, String path) {
if (path != null)
- _subPath = path + ':';
+ _subPath = path;
else
_subPath = null;
@@ -546,62 +557,6 @@
else
_joinSyntax = _parent._joinSyntax;
}
-
- if (_parent.getAliases() == null || _subPath == null)
- return;
-
- if (_parent._aliases.size() <= 1)
- return;
- // Do not remove aliases for databases that use SYNTAX_DATABASE (oracle)
- if(_parent._joinSyntax != JoinSyntaxes.SYNTAX_DATABASE) {
- // resolve aliases for subselect from parent
- Set<Map.Entry> entries = _parent.getAliases().entrySet();
- for (Map.Entry entry : entries) {
- Object key = entry.getKey();
- Integer alias = (Integer) entry.getValue();
- if (key.toString().indexOf(_subPath) != -1 ||
- _parent.findTableAlias(alias) == false) {
- if (_aliases == null)
- _aliases = new HashMap();
- _aliases.put(key, alias);
-
- Object tableString = _parent.getTables().get(alias);
- if (_tables == null)
- _tables = new TreeMap();
- _tables.put(alias, tableString);
-
- _removedAliasFromParent.set(alias.intValue());
- }
- }
-
- if (_aliases != null) {
- // aliases moved into subselect should be removed from parent
- entries = _aliases.entrySet();
- for (Map.Entry entry : entries) {
- Object key = entry.getKey();
- Integer alias = (Integer) entry.getValue();
- if (key.toString().indexOf(_subPath) != -1 ||
- _parent.findTableAlias(alias) == false) {
- _parent.removeAlias(key);
-
- Object tableString = _parent.getTables().get(alias);
- _parent.removeTable(alias);
- }
- }
- }
- }
- }
-
- private boolean findTableAlias(Integer alias) {
- // if alias is defined and referenced, return true.
- String value = "t" + alias.toString() + ".";
- if (_tableAliases != null)
- if (_tableAliases.containsValue(value))
- return _tables.containsKey(alias);
- else
- return _joins != null;
- else
- return true;
}
public Map getAliases() {
@@ -773,17 +728,6 @@
* Return the alias for the given column.
*/
private String getColumnAlias(String col, Table table, PathJoins pj) {
- String tableAlias = null;
- if (pj == null || pj.path() == null) {
- if (_tableAliases == null)
- _tableAliases = new HashMap();
- tableAlias = (String) _tableAliases.get(table);
- if (tableAlias == null) {
- tableAlias = getTableAlias(table, pj).toString();
- _tableAliases.put(table, tableAlias);
- }
- return new StringBuilder(tableAlias).append(col).toString();
- }
return getTableAlias(table, pj).append(col).toString();
}
@@ -1663,10 +1607,7 @@
if ((_flags & OUTER) != 0)
pj = (PathJoins) outer(pj);
if (record) {
- if (!pj.isEmpty())
- removeParentJoins(pj);
if (!pj.isEmpty()) {
- removeJoinsFromSubselects(pj);
if (_joins == null)
_joins = new SelectJoins(this);
if (_joins.joins() == null)
@@ -1679,43 +1620,6 @@
return pj;
}
- /**
- * Remove any joins already in our parent select from the given non-empty
- * join set.
- */
- private void removeParentJoins(PathJoins pj) {
- if (_parent == null)
- return;
- if (_parent._joins != null && !_parent._joins.isEmpty()) {
- boolean removed = false;
- if (!_removedAliasFromParent.isEmpty()) {
- for (Iterator itr = pj.joins().iterator(); itr.hasNext();) {
- Join jn = (Join) itr.next();
- if (_aliases.containsValue(jn.getIndex1()))
- removed = _parent._joins.joins().remove(jn);
- }
- }
- if (!removed)
- pj.joins().removeAll(_parent._joins.joins());
- }
- if (!pj.isEmpty())
- _parent.removeParentJoins(pj);
- }
-
- /**
- * Remove the given non-empty joins from the joins of our subselects.
- */
- private void removeJoinsFromSubselects(PathJoins pj) {
- if (_subsels == null)
- return;
- SelectImpl sub;
- for (int i = 0; i < _subsels.size(); i++) {
- sub = (SelectImpl) _subsels.get(i);
- if (sub._joins != null && !sub._joins.isEmpty())
- sub._joins.joins().removeAll(pj.joins());
- }
- }
-
public SelectExecutor whereClone(int sels) {
if (sels < 1)
sels = 1;
@@ -1732,6 +1636,7 @@
sel._flags &= ~EAGER_TO_MANY;
sel._flags &= ~FORCE_COUNT;
sel._joinSyntax = _joinSyntax;
+ sel._schemaAlias = _schemaAlias;
if (_aliases != null)
sel._aliases = new HashMap(_aliases);
if (_tables != null)
@@ -1888,6 +1793,8 @@
public void append(SQLBuffer buf, Joins joins) {
if (joins == null || joins.isEmpty())
return;
+ if (_joinSyntax == JoinSyntaxes.SYNTAX_SQL92)
+ return;
if (!buf.isEmpty())
buf.append(" AND ");
@@ -1915,6 +1822,10 @@
return and((PathJoins) joins1, (PathJoins) joins2, true);
}
+ public Select getSelect() {
+ return null;
+ }
+
/**
* Combine the given joins.
*/
@@ -1925,20 +1836,25 @@
SelectJoins sj = new SelectJoins(this);
if (j1 == null || j1.isEmpty()) {
- if (nullJoins)
- sj.setJoins(j2.joins());
- else
- sj.setJoins(new JoinSet(j2.joins()));
+ if (j2.getSelect() == this) {
+ if (nullJoins)
+ sj.setJoins(j2.joins());
+ else
+ sj.setJoins(new JoinSet(j2.joins()));
+ }
} else {
- JoinSet set;
- if (nullJoins)
- set = j1.joins();
- else
- set = new JoinSet(j1.joins());
+ JoinSet set = null;
+ if (j1.getSelect() == this) {
+ if (nullJoins)
+ set = j1.joins();
+ else
+ set = new JoinSet(j1.joins());
- if (j2 != null && !j2.isEmpty())
- set.addAll(j2.joins());
- sj.setJoins(set);
+ if (j2 != null && !j2.isEmpty()
+ && j2.getSelect() == this)
+ set.addAll(j2.joins());
+ sj.setJoins(set);
+ }
}
// null previous joins; all are combined into this one
@@ -2070,72 +1986,111 @@
if (_from != null)
return -1;
+ Integer i = null;
Object key = table.getFullName();
if (pj != null && pj.path() != null)
key = new Key(pj.path().toString(), key);
+ if (_ctx != null)
+ i = findAliasForQuery(table, pj, key, create);
+
+ if (i != null)
+ return i.intValue();
+
// check out existing aliases
- Integer i = findAlias(table, key, false, null);
+ i = findAlias(table, key);
+
if (i != null)
return i.intValue();
if (!create)
return -1;
// not found; create alias
- i = Numbers.valueOf(aliasSize());
+ i = Numbers.valueOf(aliasSize(null));
+// System.out.println("GetTableIndex\t"+
+// ((_parent != null) ? "Sub" :"") +
+// " created alias: "+
+// i.intValue()+ " "+ key);
recordTableAlias(table, key, i);
return i.intValue();
}
- /**
- * Attempt to find the alias for the given key.
- *
- * @param fromParent whether a parent is checking its subselects
- * @param fromSub the subselect checking its parent
- */
- private Integer findAlias(Table table, Object key, boolean fromParent,
- SelectImpl fromSub) {
+ private Integer findAliasForQuery(Table table, PathJoins pj, Object key,
+ boolean create) {
+ Integer i = null;
+ SelectImpl sel = this;
+ String alias = _schemaAlias;
+ if (isPathInThisContext(pj) || table.isAssociation())
+ alias = null;
+
+ // find the context where this alias is defined
+ Context ctx = (alias != null) ?
+ _ctx.findContext(alias) : null;
+ if (ctx != null)
+ sel = (SelectImpl) ctx.getSelect();
+
+ if (!create)
+ i = sel.findAlias(table, key); // find in parent and in myself
+ else
+ i = sel.getAlias(table, key); // find in myself
+ if (i != null)
+ return i;
+
+ if (create) { // create here
+ i = sel.createAlias(table, key);
+ } else if (ctx != null && ctx != ctx()) { // create in other select
+ i = ((SelectImpl)ctx.getSelect()).createAlias(table, key);
+ }
+
+ return i;
+ }
+
+ private boolean isPathInThisContext(PathJoins pj) {
+ // currCtx is set from Action, it is reset to null after the PCPath initialization
+ Context currCtx = pj == null ? null : ((PathJoinsImpl)pj).context;
+
+ // lastCtx is set to currCtx after the SelectJoins.join. pj.lastCtx and pj.path string are
+ // the last snapshot of pj. They will be used together for later table alias resolution in
+ // the getColumnAlias().
+ Context lastCtx = pj == null ? null : ((PathJoinsImpl)pj).lastContext;
+ Context thisCtx = currCtx == null ? lastCtx : currCtx;
+ String corrVar = pj == null ? null : pj.getCorrelatedVariable();
+
+ return (pj != null && pj.path() != null &&
+ (corrVar == null || (thisCtx != null && ctx() == thisCtx)));
+ }
+
+ private Integer getAlias(Table table, Object key) {
+ Integer alias = null;
+ if (_aliases != null)
+ alias = (Integer) _aliases.get(key);
+ return alias;
+ }
+
+ private int createAlias(Table table, Object key) {
+ Integer i = Numbers.valueOf(ctx().nextAlias());
+// System.out.println("\t"+
+// ((_parent != null) ? "Sub" :"") +
+// "Query created alias: "+
+// i.intValue()+ " "+ key);
+ recordTableAlias(table, key, i);
+ return i.intValue();
+ }
+
+ private Integer findAlias(Table table, Object key) {
Integer alias = null;
if (_aliases != null) {
- alias = (Integer) ((fromParent) ? _aliases.remove(key)
- : _aliases.get(key));
+ alias = (Integer) _aliases.get(key);
if (alias != null) {
- if (fromParent)
- _tables.remove(alias);
return alias;
}
}
- if (!fromParent && _parent != null) {
- boolean removeAliasFromParent = key.toString().indexOf(":") != -1;
- alias = _parent.findAlias(table, key, removeAliasFromParent, this);
+ if (_parent != null) {
+ alias = _parent.findAlias(table, key);
if (alias != null) {
- if (removeAliasFromParent) {
- recordTableAlias(table, key, alias);
- _removedAliasFromParent.set(alias.intValue());
- }
return alias;
}
}
- if (_subsels != null) {
- SelectImpl sub;
- for (int i = 0; i < _subsels.size(); i++) {
- sub = (SelectImpl) _subsels.get(i);
- if (sub == fromSub)
- continue;
- if (alias != null) {
- if (sub._aliases != null)
- sub._aliases.remove(key);
- if (sub._tables != null)
- sub._tables.remove(alias);
- } else {
- if (key instanceof String) {
- alias = sub.findAlias(table, key, true, null);
- if (!fromParent && alias != null)
- recordTableAlias(table, key, alias);
- }
- }
- }
- }
return alias;
}
@@ -2157,26 +2112,16 @@
/**
* Calculate total number of aliases.
*/
- private int aliasSize() {
- return aliasSize(false, null);
- }
-
- /**
- * Calculate total number of aliases.
- *
- * @param fromParent whether a parent is checking its subselects
- * @param fromSub the subselect checking its parent
- */
- private int aliasSize(boolean fromParent, SelectImpl fromSub) {
- int aliases = (fromParent || _parent == null) ? 0
- : _parent.aliasSize(false, this);
+ private int aliasSize(SelectImpl fromSub) {
+ int aliases = (_parent == null) ? 0
+ : _parent.aliasSize(this);
aliases += (_aliases == null) ? 0 : _aliases.size();
if (_subsels != null) {
SelectImpl sub;
for (int i = 0; i < _subsels.size(); i++) {
sub = (SelectImpl) _subsels.get(i);
if (sub != fromSub)
- aliases += sub.aliasSize(true, null);
+ aliases += sub.aliasSize(null);
}
}
return aliases;
@@ -2268,6 +2213,37 @@
*/
private static class Placeholder {
}
+
+ public void reset() {
+ _aliases = null;
+ _eager = null;
+ _eagerKeys = null;
+ _expectedResultCount = 0;
+ _flags = 0;
+ _from = null;
+ _grouped = null;
+ _grouping = null;
+ _having = null;
+ _joins = null;
+ _joinSyntax = 0;
+ _nullIds = 0;
+ _ordered = null;
+ _ordering = null;
+ _orders = 0;
+ _outer = null;
+ _parent = null;
+ _placeholders = 0;
+ _preJoins = null;
+ _schemaAlias = null;
+ _selects._aliases = null;
+ _selects._ids = null;
+ _subPath = null;
+ _subsels = null;
+ _tables = null;
+ _where = null;
+
+ }
+
/**
* Key type used for aliases.
@@ -2599,6 +2575,21 @@
return this;
return new PathJoinsImpl().setSubselect(alias);
}
+
+ public Joins setCorrelatedVariable(String var) {
+ return this;
+ }
+
+ public Joins setJoinContext(Context ctx) {
+ return this;
+ }
+
+ public String getCorrelatedVariable() {
+ return null;
+ }
+
+ public void moveJoinsToParent() {
+ }
}
/**
@@ -2609,6 +2600,13 @@
protected StringBuffer path = null;
protected String var = null;
+ protected String correlatedVar = null;
+ protected Context context = null;
+ protected Context lastContext = null;
+
+ public Select getSelect() {
+ return null;
+ }
public boolean isOuter() {
return false;
@@ -2642,9 +2640,25 @@
return this;
}
+ public String getVariable() {
+ return var;
+ }
+
+ public Joins setCorrelatedVariable(String var) {
+ this.correlatedVar = var;
+ return this;
+ }
+
+ public String getCorrelatedVariable() {
+ return correlatedVar;
+ }
+
+ public Joins setJoinContext(Context context) {
+ this.context = context;
+ return this;
+ }
+
public Joins setSubselect(String alias) {
- if (!alias.endsWith(":"))
- alias += ':';
append(alias);
return this;
}
@@ -2700,6 +2714,9 @@
return "PathJoinsImpl<" + hashCode() + ">: "
+ String.valueOf(path);
}
+
+ public void moveJoinsToParent() {
+ }
}
/**
@@ -2718,6 +2735,10 @@
_sel = sel;
}
+ public Select getSelect() {
+ return _sel;
+ }
+
public boolean isOuter() {
return _outer;
}
@@ -2778,9 +2799,14 @@
// until we get past the local table
String var = this.var;
this.var = null;
+ Context ctx = context;
+ context = null;
int alias1 = _sel.getTableIndex(localTable, this, true);
this.append(var);
+ this.append(correlatedVar);
+ context = ctx;
+
int alias2 = _sel.getTableIndex(foreignTable, this, true);
Join j = new Join(localTable, alias1, foreignTable, alias2,
null, false);
@@ -2789,7 +2815,10 @@
if (_joins == null)
_joins = new JoinSet();
_joins.add(j);
+ setCorrelated(j);
_outer = false;
+ lastContext = context;
+ context = null;
return this;
}
@@ -2817,6 +2846,8 @@
// until we get past the local table
String var = this.var;
this.var = null;
+ Context ctx = context;
+ context = null;
// get first table alias before updating path; if there is a from
// select then we shouldn't actually create a join object, since
@@ -2825,13 +2856,19 @@
Table table1 = null;
int alias1 = -1;
if (createJoin) {
+ boolean createIndex = true;
table1 = (inverse) ? fk.getPrimaryKeyTable() : fk.getTable();
- alias1 = _sel.getTableIndex(table1, this, true);
+ if (correlatedVar != null)
+ createIndex = false; // not to create here
+ alias1 = _sel.getTableIndex(table1, this, createIndex);
}
// update the path with the relation name before getting pk alias
this.append(name);
this.append(var);
+ this.append(correlatedVar);
+ context = ctx;
+
if (toMany) {
_sel._flags |= IMPLICIT_DISTINCT;
_sel._flags |= TO_MANY;
@@ -2839,9 +2876,16 @@
_outer = outer;
if (createJoin) {
+ boolean createIndex = true;
Table table2 = (inverse) ? fk.getTable()
: fk.getPrimaryKeyTable();
- int alias2 = _sel.getTableIndex(table2, this, true);
+ if (table2.isAssociation())
+ createIndex = true;
+ else if (context == _sel.ctx())
+ createIndex = true;
+ else if (correlatedVar != null)
+ createIndex = false;
+ int alias2 = _sel.getTableIndex(table2, this, createIndex);
Join j = new Join(table1, alias1, table2, alias2, fk, inverse);
j.setType((outer) ? Join.TYPE_OUTER : Join.TYPE_INNER);
@@ -2850,10 +2894,91 @@
if (_joins.add(j) && (subs == Select.SUBS_JOINABLE
|| subs == Select.SUBS_NONE))
j.setRelation(target, subs, clone(_sel));
+
+ setCorrelated(j);
}
+ lastContext = context;
+ context = null;
return this;
}
+ private void setCorrelated(Join j) {
+ if (_sel._parent == null)
+ return;
+
+ if (_sel._aliases == null) {
+ j.setIsNotMyJoin();
+ return;
+ }
+
+ Object aliases[] = _sel._aliases.values().toArray();
+ boolean found1 = false;
+ boolean found2 = false;
+
+ for (int i = 0; i < aliases.length; i++) {
+ int alias = ((Integer)aliases[i]).intValue();
+ if (alias == j.getIndex1())
+ found1 = true;
+ if (alias == j.getIndex2())
+ found2 = true;
+ }
+
+ if (found1 && found2)
+ return;
+ else if (!found1 && !found2) {
+ j.setIsNotMyJoin();
+ return;
+ }
+ else {
+ j.setCorrelated();
+ }
+ }
+
+ public void moveJoinsToParent() {
+ if (_joins == null)
+ return;
+ Join j = null;
+ List<Join> removed = new ArrayList<Join>(5);
+ for (Iterator itr = _joins.iterator(); itr.hasNext();) {
+ j = (Join) itr.next();
+ if (j.isNotMyJoin()) {
+ addJoinsToParent(_sel._parent, j);
+ removed.add(j);
+ }
+ }
+ for (Join join : removed) {
+ _joins.remove(join);
+ }
+ }
+
+ private void addJoinsToParent(SelectImpl parent, Join join) {
+ if (parent._aliases == null)
+ return;
+ Object aliases[] = parent._aliases.values().toArray();
+ boolean found1 = false;
+ boolean found2 = false;
+
+ for (int i = 0; i < aliases.length; i++) {
+ int alias = ((Integer)aliases[i]).intValue();
+ if (alias == join.getIndex1())
+ found1 = true;
+ if (alias == join.getIndex2())
+ found2 = true;
+ }
+
+ if (found1 && found2) {
+ // this is my join, add join
+ if (parent._joins == null)
+ parent._joins = new SelectJoins(parent);
+ SelectJoins p = parent._joins;
+ if (p.joins() == null)
+ p.setJoins(new JoinSet());
+ p.joins().add(join);
+ }
+ else if (parent._parent != null)
+ addJoinsToParent(parent._parent, join);
+ }
+
public SelectJoins clone(SelectImpl sel) {
SelectJoins sj = new SelectJoins(sel);
sj.var = var;
@@ -3067,6 +3192,25 @@
_idents = null;
}
}
+
+ public Joins setCorrelatedVariable(String var) {
+ if (var == null)
+ return this;
+ return new SelectJoins(this).setCorrelatedVariable(var);
+ }
+
+ public Joins setJoinContext(Context ctx) {
+ if (ctx == null)
+ return this;
+ return new SelectJoins(this).setJoinContext(ctx);
+ }
+
+ public String getCorrelatedVariable() {
+ return null;
+ }
+
+ public void moveJoinsToParent() {
+ }
}
/**
@@ -3106,5 +3250,11 @@
* Null the set of {@link Join} elements.
*/
public void nullJoins();
+
+ /**
+ * The select owner of this join
+ * @return
+ */
+ public Select getSelect();
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java Mon Jul 20 17:49:36 2009
@@ -169,10 +169,12 @@
type = TYPE_OBJECT;
else
meta = getMetaData(type, false);
- if (meta != null)
+ if (meta != null) {
addAccessPath(meta);
+ addSchemaToContext(id, meta);
+ }
- Value var;
+ Value var = null;
if (bind)
var = factory.newBoundVariable(id, type);
else
@@ -182,6 +184,8 @@
if (_seenVars == null)
_seenVars = new HashMap<String,Value>();
_seenVars.put(id, var);
+
+ addVariableToContext(id, var);
return var;
}
@@ -308,7 +312,7 @@
}
}
- if (meta != null || !pcOnly)
+ if (meta != null || !pcOnly)
path.get(fmd, allowNull);
return path;
@@ -521,5 +525,28 @@
* Returns the current string being parsed; used for error messages.
*/
protected abstract String currentQuery ();
+
+ /**
+ * Register the schema alias to the current JPQL query context.
+ * @param alias
+ * @param meta
+ */
+ protected abstract void addSchemaToContext(String alias,
+ ClassMetaData meta);
+
+ /**
+ * Register the variable associated with the schema alias (id) to
+ * the current JPQL query context.
+ * @param id
+ * @param var
+ */
+ protected abstract void addVariableToContext(String id, Value var);
+
+ /**
+ * Returns the variable associated with the schema alias (id).
+ * @param id
+ * @return
+ */
+ protected abstract Value getSeenVariable(String id);
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java Mon Jul 20 17:49:36 2009
@@ -196,4 +196,14 @@
public XMLMetaData getXmlMapping() {
return null;
}
+
+ public void setSchemaAlias(String schemaAlias) {
+ }
+
+ public String getSchemaAlias() {
+ return null;
+ }
+
+ public void setSubqueryContext(Context conext) {
+ }
}
Added: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java?rev=795934&view=auto
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java (added)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java Mon Jul 20 17:49:36 2009
@@ -0,0 +1,224 @@
+/*
+ * 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.exps;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.ParsedJPQL;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * JPQL / Criteria Query Context
+ * @since 2.0
+ *
+ */
+public class Context implements Serializable {
+
+ public final ParsedJPQL parsed;
+ public ClassMetaData meta;
+ public String schemaAlias;
+ public Subquery subquery;
+ public Expression from = null;
+ private Context parent = null;
+ private List<Context> subsels = null;
+ private Object select = null;
+ private int aliasCount = -1;
+ private Map<String,Value> variables = new HashMap<String,Value>();
+ private Map<String,ClassMetaData> schemas =
+ new HashMap<String,ClassMetaData>();
+
+ public Context(ParsedJPQL parsed, Subquery subquery, Context parent) {
+ this.parsed = parsed;
+ this.subquery = subquery;
+ this.parent = parent;
+ if (subquery != null) {
+ this.select = subquery.getSelect();
+ parent.addSubselContext(this);
+ }
+ }
+
+ public void setSubquery(Subquery subquery) {
+ this.subquery = subquery;
+ this.select = subquery.getSelect();
+ parent.addSubselContext(this);
+ }
+
+ public ClassMetaData meta() {
+ return meta;
+ }
+
+ public String schemaAlias() {
+ return schemaAlias;
+ }
+
+ public Subquery subquery() {
+ return subquery;
+ }
+
+ /**
+ * Returns next table alias to be created.
+ * @return
+ */
+ public int nextAlias() {
+ Context p = this;
+ while (p.subquery != null) {
+ p = p.parent;
+ }
+ p.aliasCount++;
+ return p.aliasCount;
+ }
+
+ /**
+ * Reset alias count for prepared query cache
+ *
+ */
+ public void resetAliasCount() {
+ Context p = this;
+ while (p.subquery != null) {
+ p = p.parent;
+ }
+ p.aliasCount = -1;
+ }
+
+ /**
+ * Register the select for this context.
+ * @param select
+ */
+ public void setSelect(Object select) {
+ this.select = select;
+ }
+
+ /**
+ * Returns the select associated with this context.
+ * @return
+ */
+ public Object getSelect() {
+ return select;
+ }
+
+ /**
+ * Register the subquery context in this context.
+ * @param sub
+ */
+ private void addSubselContext(Context sub) {
+ if (subsels == null)
+ subsels = new ArrayList<Context>();
+ subsels.add(sub);
+ }
+
+ /**
+ * Returns the subquery context.
+ * @return
+ */
+ public List<Context> getSubselContexts() {
+ return subsels;
+ }
+
+ /**
+ * Returns the subquery in this context.
+ * @return
+ */
+ public Subquery getSubquery() {
+ return subquery;
+ }
+
+ public Context getParent() {
+ return parent;
+ }
+
+ public void setParent(Context parent) {
+ this.parent = parent;
+ }
+
+ public void addVariable(String id, Value var) {
+ variables.put(id.toLowerCase(), var);
+ }
+
+ public void addSchema(String id, ClassMetaData meta) {
+ schemas.put(id.toLowerCase(), meta);
+ }
+
+ public ClassMetaData getSchema(String id) {
+ if (id != null)
+ return schemas.get(id.toLowerCase());
+ return null;
+ }
+
+ /**
+ * Given an alias and return its associated variable.
+ * @param var
+ * @return
+ */
+ public Value getVariable(String var) {
+ Value variable = var == null ? null
+ : variables.get(var.toLowerCase());
+ return variable;
+ }
+
+ /**
+ * Given an alias find the context of its associated
+ * variable where it is defined.
+ * @param alias
+ * @return
+ */
+ public Context findContext(String alias) {
+ Value var = getVariable(alias);
+ if (var != null)
+ return this;
+ for (Context p = parent; p != null; ) {
+ var = p.getVariable(alias);
+ if (var != null)
+ return p;
+ p = p.parent;
+ }
+ if (subsels != null) {
+ for (Context subsel : subsels) {
+ if (subsel != null) {
+ var = subsel.getVariable(alias);
+ if (var != null)
+ return subsel;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Given an alias find the variable in JPQL contexts.
+ * @param alias
+ * @return
+ */
+ public Value findVariable(String alias) {
+ Value var = getVariable(alias);
+ if (var != null)
+ return var;
+ for (Context p = parent; p != null; ) {
+ var = p.getVariable(alias);
+ if (var != null)
+ return var;
+ p = p.parent;
+ }
+ return null;
+ }
+}
+
Propchange: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Context.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java Mon Jul 20 17:49:36 2009
@@ -67,4 +67,15 @@
* @return Return xmlmapping
*/
public XMLMetaData getXmlMapping();
+
+ /**
+ * Set the schema alias (the identification variable)
+ * this path is begin with.
+ * @param schemaAlias
+ */
+ public void setSchemaAlias(String schemaAlias);
+
+ public String getSchemaAlias();
+
+ public void setSubqueryContext(Context context);
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java Mon Jul 20 17:49:36 2009
@@ -22,10 +22,12 @@
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Stack;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.openjpa.kernel.QueryOperations;
import org.apache.openjpa.kernel.StoreQuery;
+import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
@@ -69,9 +71,26 @@
public String[] fetchInnerPaths = StoreQuery.EMPTY_STRINGS;
public Value[] range = EMPTY_VALUES;
private Boolean _aggregate = null;
+ private Stack<Context> _contexts = null;
public Object state;
/**
+ * Set reference to the JPQL query contexts.
+ * @param contexts
+ */
+ public void setContexts(Stack<Context> contexts) {
+ _contexts = contexts;
+ }
+
+ /**
+ * Returns the current JPQL query context.
+ * @return
+ */
+ public Context ctx() {
+ return _contexts.peek();
+ }
+
+ /**
* Whether this is an aggregate results.
*/
public boolean isAggregate() {
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SubQ.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SubQ.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SubQ.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/SubQ.java Mon Jul 20 17:49:36 2009
@@ -41,6 +41,10 @@
_alias = alias;
}
+ public Object getSelect() {
+ return null;
+ }
+
public String getCandidateAlias() {
return _alias;
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subquery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subquery.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subquery.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Subquery.java Mon Jul 20 17:49:36 2009
@@ -36,4 +36,6 @@
* Set the parsed subquery.
*/
public void setQueryExpressions(QueryExpressions query);
+
+ public Object getSelect();
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java Mon Jul 20 17:49:36 2009
@@ -135,4 +135,8 @@
public Path getPath() {
return null;
}
+
+ public String getName() {
+ return null;
+ }
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java?rev=795934&r1=795933&r2=795934&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java Mon Jul 20 17:49:36 2009
@@ -90,4 +90,6 @@
public Value getSelectAs();
public Path getPath();
+
+ public String getName();
}