You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by an...@apache.org on 2009/06/17 16:52:12 UTC
svn commit: r785634 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src:
main/java/org/apache/cayenne/access/trans/
main/java/org/apache/cayenne/dba/openbase/
main/java/org/apache/cayenne/dba/oracle/ main/java/org/apache/cayenne/map/
test...
Author: andrey
Date: Wed Jun 17 14:52:11 2009
New Revision: 785634
URL: http://svn.apache.org/viewvc?rev=785634&view=rev
Log:
CAY-1235 Implement qualifiers for DBEntities. Implementing expression-like qualifiers for DBEntities
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QualifierTranslator.java (with props)
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MapLoader.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/trans/SelectTranslatorTest.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinStack.java Wed Jun 17 14:52:11 2009
@@ -23,12 +23,17 @@
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.SimpleNode;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.JoinType;
-import org.apache.cayenne.util.Util;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.collections.Transformer;
/**
* Encapsulates join reuse/split logic used in SelectQuery processing. All expression
@@ -46,6 +51,11 @@
private int aliasCounter;
/**
+ * Helper class to process DbEntity qualifiers
+ */
+ private QualifierTranslator qualifierTranslator;
+
+ /**
* @deprecated since 3.0
*/
@Deprecated
@@ -56,7 +66,8 @@
resetStack();
}
- protected JoinStack(DbAdapter dbAdapter, DataMap dataMap) {
+ protected JoinStack(DbAdapter dbAdapter, DataMap dataMap,
+ QueryAssembler assembler) {
this.rootNode = new JoinTreeNode(this);
this.rootNode.setTargetTableAlias(newAlias());
boolean status;
@@ -66,7 +77,8 @@
status = false;
}
strategy = dbAdapter.getQuotingStrategy(status);
-
+ qualifierTranslator = dbAdapter.getQualifierTranslator(assembler);
+
resetStack();
}
@@ -159,6 +171,20 @@
out.append('.');
out.append(strategy.quoteString(join.getTargetName()));
}
+
+ /**
+ * Attaching root Db entity's qualifier
+ */
+ Expression dbQualifier = targetEntity.getQualifier();
+ if (dbQualifier != null) {
+ dbQualifier = dbQualifier.transform(new JoinedDbEntityQualifierTransformer(node));
+
+ if (len > 0) {
+ out.append(" AND ");
+ }
+ qualifierTranslator.setOut(out);
+ qualifierTranslator.doAppendPart(dbQualifier);
+ }
out.append(')');
@@ -172,39 +198,10 @@
*/
protected void appendQualifier(Appendable out, boolean firstQualifierElement)
throws IOException {
- // skip root, recursively append its children
- for (JoinTreeNode child : rootNode.getChildren()) {
- firstQualifierElement &= appendQualifier(out, child, firstQualifierElement);
- }
+ // nothing as standard join is performed before "WHERE"
}
/**
- * Append join tree node information to the qualifier - the part after "WHERE".
- * @return whether qualifier was not yet appended (i.e. firstQualifierElement is still false)
- */
- private boolean appendQualifier(Appendable out, JoinTreeNode node, boolean firstQualifierElement)
- throws IOException {
- DbRelationship relationship = node.getRelationship();
-
- DbEntity targetEntity = (DbEntity) relationship.getTargetEntity();
- if (!Util.isEmptyString(targetEntity.getQualifier())) {
- if (!firstQualifierElement) {
- out.append(" AND ");
- }
- else {
- firstQualifierElement = false;
- }
-
- out.append(targetEntity.getQualifier());
- }
-
- for (JoinTreeNode child : node.getChildren()) {
- firstQualifierElement &= appendQualifier(out, child, firstQualifierElement);
- }
- return firstQualifierElement;
- }
-
- /**
* Pops the stack all the way to the root node.
*/
void resetStack() {
@@ -223,4 +220,29 @@
return "t" + aliasCounter++;
}
+ /**
+ * Class to translate *joined* DB Entity qualifiers annotation to
+ * *current* Obj-entity qualifiers annotation
+ * This is done by changing all Obj-paths to concatenated Db-paths to root entity
+ * and rejecting all original Db-paths
+ */
+ class JoinedDbEntityQualifierTransformer implements Transformer {
+ String pathToRoot;
+
+ JoinedDbEntityQualifierTransformer(JoinTreeNode node) {
+ pathToRoot = "";
+ while (node != null && node.getRelationship() != null) {
+ pathToRoot += node.getRelationship().getName() + ObjEntity.PATH_SEPARATOR;
+ node = node.getParent();
+ }
+ }
+
+ public Object transform(Object input) {
+ if (input instanceof ASTObjPath) {
+ return new ASTDbPath(pathToRoot +
+ ((SimpleNode) input).getOperand(0));
+ }
+ return input;
+ }
+ }
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java Wed Jun 17 14:52:11 2009
@@ -38,17 +38,23 @@
private JoinType joinType;
private Collection<JoinTreeNode> children;
private JoinStack joinProcessor;
+
+ /**
+ * Parent join
+ */
+ private JoinTreeNode parent;
JoinTreeNode(JoinStack joinProcessor) {
this.joinProcessor = joinProcessor;
}
JoinTreeNode(JoinStack joinProcessor, DbRelationship relationship,
- JoinType joinType, String alias) {
+ JoinType joinType, String alias, JoinTreeNode parent) {
this(joinProcessor);
this.relationship = relationship;
this.alias = alias;
this.joinType = joinType;
+ this.parent = parent;
}
int size() {
@@ -88,7 +94,8 @@
joinProcessor,
relationship,
joinType,
- alias);
+ alias,
+ this);
child.setSourceTableAlias(this.targetTableAlias);
child.setTargetTableAlias(joinProcessor.newAlias());
children.add(child);
@@ -128,4 +135,11 @@
public JoinType getJoinType() {
return joinType;
}
+
+ /**
+ * @return parent join
+ */
+ public JoinTreeNode getParent() {
+ return parent;
+ }
}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QualifierTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QualifierTranslator.java?rev=785634&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QualifierTranslator.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QualifierTranslator.java Wed Jun 17 14:52:11 2009
@@ -0,0 +1,478 @@
+/*****************************************************************
+ * 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.cayenne.access.trans;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.TraversalHandler;
+import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.SimpleNode;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.EntityInheritanceTree;
+import org.apache.cayenne.map.JoinType;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.query.QualifiedQuery;
+import org.apache.cayenne.query.Query;
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.commons.collections.Transformer;
+
+/**
+ * Translates query qualifier to SQL. Used as a helper class by query translators.
+ */
+public class QualifierTranslator extends QueryAssemblerHelper implements TraversalHandler {
+
+ protected DataObjectMatchTranslator objectMatchTranslator;
+ protected boolean matchingObject;
+
+ public QualifierTranslator(QueryAssembler queryAssembler) {
+ super(queryAssembler);
+ }
+
+ /**
+ * Translates query qualifier to SQL WHERE clause. Qualifier is obtained from the
+ * parent queryAssembler.
+ *
+ * @since 3.0
+ */
+ @Override
+ protected void doAppendPart() throws IOException {
+ doAppendPart(extractQualifier());
+ }
+
+ /**
+ * Translates query qualifier to SQL WHERE clause. Qualifier is a method parameter *
+ * @since 3.0
+ */
+ protected void doAppendPart(Expression rootNode) throws IOException {
+ if (rootNode == null) {
+ return;
+ }
+ rootNode.traverse(this);
+ }
+
+ protected Expression extractQualifier() {
+ Query q = queryAssembler.getQuery();
+
+ Expression qualifier = ((QualifiedQuery) q).getQualifier();
+
+ // append Entity qualifiers, taking inheritance into account
+ ObjEntity entity = getObjEntity();
+
+ if (entity != null) {
+ EntityInheritanceTree tree = queryAssembler
+ .getEntityResolver()
+ .lookupInheritanceTree(entity);
+ Expression entityQualifier = (tree != null) ? tree
+ .qualifierForEntityAndSubclasses() : entity.getDeclaredQualifier();
+ if (entityQualifier != null) {
+ qualifier = (qualifier != null)
+ ? qualifier.andExp(entityQualifier)
+ : entityQualifier;
+ }
+ }
+
+ /**
+ * Attaching root Db entity's qualifier
+ */
+ if (getDbEntity() != null) {
+ Expression dbQualifier = getDbEntity().getQualifier();
+ if (dbQualifier != null) {
+ dbQualifier = dbQualifier.transform(new DbEntityQualifierTransformer());
+
+ qualifier = qualifier == null ? dbQualifier :
+ qualifier.andExp(dbQualifier);
+ }
+ }
+
+ return qualifier;
+ }
+
+ /**
+ * Called before processing an expression to initialize objectMatchTranslator if
+ * needed.
+ */
+ protected void detectObjectMatch(Expression exp) {
+ // On demand initialization of
+ // objectMatchTranslator is not possible since there may be null
+ // object values that would not allow to detect the need for
+ // such translator in the right time (e.g.: null = dbpath)
+
+ matchingObject = false;
+
+ if (exp.getOperandCount() != 2) {
+ // only binary expressions are supported
+ return;
+ }
+
+ // check if there are DataObjects among direct children of the Expression
+ for (int i = 0; i < 2; i++) {
+ Object op = exp.getOperand(i);
+ if (op instanceof Persistent || op instanceof ObjectId) {
+ matchingObject = true;
+
+ if (objectMatchTranslator == null) {
+ objectMatchTranslator = new DataObjectMatchTranslator();
+ }
+ else {
+ objectMatchTranslator.reset();
+ }
+ break;
+ }
+ }
+ }
+
+ protected void appendObjectMatch() throws IOException {
+ if (!matchingObject || objectMatchTranslator == null) {
+ throw new IllegalStateException("An invalid attempt to append object match.");
+ }
+
+ // turn off special handling, so that all the methods behave as a superclass's
+ // impl.
+ matchingObject = false;
+
+ boolean first = true;
+
+ DbRelationship relationship = objectMatchTranslator.getRelationship();
+ if (!relationship.isToMany() && !relationship.isToPK()) {
+ queryAssembler.dbRelationshipAdded(
+ relationship,
+ JoinType.INNER,
+ objectMatchTranslator.getJoinSplitAlias());
+ }
+
+ Iterator<String> it = objectMatchTranslator.keys();
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ }
+ else {
+ out.append(" AND ");
+ }
+
+ String key = it.next();
+ DbAttribute attr = objectMatchTranslator.getAttribute(key);
+ Object val = objectMatchTranslator.getValue(key);
+
+ processColumn(attr);
+ out.append(objectMatchTranslator.getOperation());
+ appendLiteral(val, attr, objectMatchTranslator.getExpression());
+ }
+
+ objectMatchTranslator.reset();
+ }
+
+ public void finishedChild(Expression node, int childIndex, boolean hasMoreChildren) {
+
+ if (!hasMoreChildren) {
+ return;
+ }
+
+ Appendable out = (matchingObject) ? new StringBuilder() : this.out;
+
+ try {
+ switch (node.getType()) {
+ case Expression.AND:
+ out.append(" AND ");
+ break;
+ case Expression.OR:
+ out.append(" OR ");
+ break;
+ case Expression.EQUAL_TO:
+ // translate NULL as IS NULL
+ if (childIndex == 0
+ && node.getOperandCount() == 2
+ && node.getOperand(1) == null) {
+ out.append(" IS ");
+ }
+ else {
+ out.append(" = ");
+ }
+ break;
+ case Expression.NOT_EQUAL_TO:
+ // translate NULL as IS NOT NULL
+ if (childIndex == 0
+ && node.getOperandCount() == 2
+ && node.getOperand(1) == null) {
+ out.append(" IS NOT ");
+ }
+ else {
+ out.append(" <> ");
+ }
+ break;
+ case Expression.LESS_THAN:
+ out.append(" < ");
+ break;
+ case Expression.GREATER_THAN:
+ out.append(" > ");
+ break;
+ case Expression.LESS_THAN_EQUAL_TO:
+ out.append(" <= ");
+ break;
+ case Expression.GREATER_THAN_EQUAL_TO:
+ out.append(" >= ");
+ break;
+ case Expression.IN:
+ out.append(" IN ");
+ break;
+ case Expression.NOT_IN:
+ out.append(" NOT IN ");
+ break;
+ case Expression.LIKE:
+ out.append(" LIKE ");
+ break;
+ case Expression.NOT_LIKE:
+ out.append(" NOT LIKE ");
+ break;
+ case Expression.LIKE_IGNORE_CASE:
+ out.append(") LIKE UPPER(");
+ break;
+ case Expression.NOT_LIKE_IGNORE_CASE:
+ out.append(") NOT LIKE UPPER(");
+ break;
+ case Expression.ADD:
+ out.append(" + ");
+ break;
+ case Expression.SUBTRACT:
+ out.append(" - ");
+ break;
+ case Expression.MULTIPLY:
+ out.append(" * ");
+ break;
+ case Expression.DIVIDE:
+ out.append(" / ");
+ break;
+ case Expression.BETWEEN:
+ if (childIndex == 0)
+ out.append(" BETWEEN ");
+ else if (childIndex == 1)
+ out.append(" AND ");
+ break;
+ case Expression.NOT_BETWEEN:
+ if (childIndex == 0)
+ out.append(" NOT BETWEEN ");
+ else if (childIndex == 1)
+ out.append(" AND ");
+ break;
+ }
+ }
+ catch (IOException ioex) {
+ throw new CayenneRuntimeException("Error appending content", ioex);
+ }
+
+ if (matchingObject) {
+ objectMatchTranslator.setOperation(out.toString());
+ objectMatchTranslator.setExpression(node);
+ }
+ }
+
+ public void startNode(Expression node, Expression parentNode) {
+ int count = node.getOperandCount();
+
+ if (count == 2) {
+ // binary nodes are the only ones that currently require this
+ detectObjectMatch(node);
+ }
+
+ try {
+
+ if (parenthesisNeeded(node, parentNode)) {
+ out.append('(');
+ }
+
+ if (count == 0) {
+ // not all databases handle true/false
+ if (node.getType() == Expression.TRUE) {
+ out.append("1 = 1");
+ }
+ if (node.getType() == Expression.FALSE) {
+ out.append("1 = 0");
+ }
+ }
+
+ if (count == 1) {
+ if (node.getType() == Expression.NEGATIVE)
+ out.append('-');
+ // ignore POSITIVE - it is a NOOP
+ // else if(node.getType() == Expression.POSITIVE)
+ // qualBuf.append('+');
+ else if (node.getType() == Expression.NOT)
+ out.append("NOT ");
+ }
+ else if (node.getType() == Expression.LIKE_IGNORE_CASE
+ || node.getType() == Expression.NOT_LIKE_IGNORE_CASE) {
+ out.append("UPPER(");
+ }
+ }
+ catch (IOException ioex) {
+ throw new CayenneRuntimeException("Error appending content", ioex);
+ }
+ }
+
+ /**
+ * @since 1.1
+ */
+ public void endNode(Expression node, Expression parentNode) {
+
+ try {
+ // check if we need to use objectMatchTranslator to finish building the
+ // expression
+ if (node.getOperandCount() == 2 && matchingObject) {
+ appendObjectMatch();
+ }
+
+ if (parenthesisNeeded(node, parentNode)) {
+ out.append(')');
+ }
+
+ if (node.getType() == Expression.LIKE_IGNORE_CASE
+ || node.getType() == Expression.NOT_LIKE_IGNORE_CASE) {
+ out.append(')');
+ }
+ }
+ catch (IOException ioex) {
+ throw new CayenneRuntimeException("Error appending content", ioex);
+ }
+ }
+
+ public void objectNode(Object leaf, Expression parentNode) {
+
+ try {
+ if (parentNode.getType() == Expression.OBJ_PATH) {
+ appendObjPath(parentNode);
+ }
+ else if (parentNode.getType() == Expression.DB_PATH) {
+ appendDbPath(parentNode);
+ }
+ else if (parentNode.getType() == Expression.LIST) {
+ appendList(parentNode, paramsDbType(parentNode));
+ }
+ else {
+ appendLiteral(leaf, paramsDbType(parentNode), parentNode);
+ }
+ }
+ catch (IOException ioex) {
+ throw new CayenneRuntimeException("Error appending content", ioex);
+ }
+ }
+
+ protected boolean parenthesisNeeded(Expression node, Expression parentNode) {
+ if (parentNode == null)
+ return false;
+
+ // only unary expressions can go w/o parenthesis
+ if (node.getOperandCount() > 1)
+ return true;
+
+ if (node.getType() == Expression.OBJ_PATH)
+ return false;
+
+ if (node.getType() == Expression.DB_PATH)
+ return false;
+
+ return true;
+ }
+
+ private final void appendList(Expression listExpr, DbAttribute paramDesc)
+ throws IOException {
+ Iterator<?> it = null;
+ Object list = listExpr.getOperand(0);
+ if (list instanceof List) {
+ it = ((List<?>) list).iterator();
+ }
+ else if (list instanceof Object[]) {
+ it = IteratorUtils.arrayIterator((Object[]) list);
+ }
+ else {
+ String className = (list != null) ? list.getClass().getName() : "<null>";
+ throw new IllegalArgumentException(
+ "Unsupported type for the list expressions: " + className);
+ }
+
+ // process first element outside the loop
+ // (unroll loop to avoid condition checking
+ if (it.hasNext())
+ appendLiteral(it.next(), paramDesc, listExpr);
+ else
+ return;
+
+ while (it.hasNext()) {
+ out.append(", ");
+ appendLiteral(it.next(), paramDesc, listExpr);
+ }
+ }
+
+ @Override
+ protected void appendLiteral(Object val, DbAttribute attr, Expression parentExpression)
+ throws IOException {
+
+ if (!matchingObject) {
+ super.appendLiteral(val, attr, parentExpression);
+ }
+ else if (val == null || (val instanceof Persistent)) {
+ objectMatchTranslator.setDataObject((Persistent) val);
+ }
+ else if (val instanceof ObjectId) {
+ objectMatchTranslator.setObjectId((ObjectId) val);
+ }
+ else {
+ throw new IllegalArgumentException(
+ "Attempt to use literal other than DataObject during object match.");
+ }
+ }
+
+ @Override
+ protected void processRelTermination(
+ DbRelationship rel,
+ JoinType joinType,
+ String joinSplitAlias) throws IOException {
+
+ if (!matchingObject) {
+ super.processRelTermination(rel, joinType, joinSplitAlias);
+ }
+ else {
+ if (rel.isToMany()) {
+ // append joins
+ queryAssembler.dbRelationshipAdded(rel, joinType, joinSplitAlias);
+ }
+ objectMatchTranslator.setRelationship(rel, joinSplitAlias);
+ }
+ }
+
+ /**
+ * Class to translate DB Entity qualifiers annotation to Obj-entity qualifiers annotation
+ * This is done by changing all Obj-paths to Db-paths and rejecting all original Db-paths
+ */
+ class DbEntityQualifierTransformer implements Transformer {
+ public Object transform(Object input) {
+ if (input instanceof ASTObjPath) {
+ return new ASTDbPath(((SimpleNode) input).getOperand(0));
+ }
+ return input;
+ }
+ }
+}
Propchange: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QualifierTranslator.java
------------------------------------------------------------------------------
svn:mergeinfo =
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java Wed Jun 17 14:52:11 2009
@@ -82,6 +82,20 @@
doAppendPart();
return out;
}
+
+ /**
+ * Sets ouput buffer
+ */
+ void setOut(Appendable out) {
+ this.out = out;
+ }
+
+ /**
+ * @return output buffer
+ */
+ Appendable getOut() {
+ return out;
+ }
/**
* @since 3.0
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/SelectTranslator.java Wed Jun 17 14:52:11 2009
@@ -97,7 +97,7 @@
boolean forcingDistinct;
protected JoinStack createJoinStack() {
- return new JoinStack(getAdapter(), queryMetadata.getDataMap());
+ return new JoinStack(getAdapter(), queryMetadata.getDataMap(), this);
}
/**
@@ -124,7 +124,8 @@
this.resultColumns = buildResultColumns();
// build qualifier
- StringBuilder qualifierBuffer = adapter.getQualifierTranslator(this).appendPart(
+ QualifierTranslator qualifierTranslator = adapter.getQualifierTranslator(this);
+ StringBuilder qualifierBuffer = qualifierTranslator.appendPart(
new StringBuilder());
// build ORDER BY
@@ -545,6 +546,7 @@
* @deprecated since 3.0. Will likely be removed after 3.0M6. Can be replaced with
* EJBQL.
*/
+ @Deprecated
List<ColumnDescriptor> appendCustomColumns(
List<ColumnDescriptor> columns,
SelectQuery query) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseJoinStack.java Wed Jun 17 14:52:11 2009
@@ -23,6 +23,7 @@
import org.apache.cayenne.access.trans.JoinStack;
import org.apache.cayenne.access.trans.JoinTreeNode;
+import org.apache.cayenne.access.trans.QueryAssembler;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
@@ -39,8 +40,8 @@
*/
class OpenBaseJoinStack extends JoinStack {
- protected OpenBaseJoinStack(DbAdapter dbAdapter, DataMap dataMap) {
- super(dbAdapter, dataMap);
+ protected OpenBaseJoinStack(DbAdapter dbAdapter, DataMap dataMap, QueryAssembler assembler) {
+ super(dbAdapter, dataMap, assembler);
}
@Override
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSelectTranslator.java Wed Jun 17 14:52:11 2009
@@ -29,7 +29,7 @@
@Override
protected JoinStack createJoinStack() {
- return new OpenBaseJoinStack(getAdapter(), queryMetadata.getDataMap());
+ return new OpenBaseJoinStack(getAdapter(), queryMetadata.getDataMap(), this);
}
@Override
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8JoinStack.java Wed Jun 17 14:52:11 2009
@@ -23,6 +23,7 @@
import org.apache.cayenne.access.trans.JoinStack;
import org.apache.cayenne.access.trans.JoinTreeNode;
+import org.apache.cayenne.access.trans.QueryAssembler;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
@@ -35,8 +36,8 @@
// cloned from OpenBaseJoin stack... need better strategies of reuse...
class Oracle8JoinStack extends JoinStack {
- Oracle8JoinStack(DbAdapter dbAdapter, DataMap dataMap) {
- super(dbAdapter, dataMap);
+ Oracle8JoinStack(DbAdapter dbAdapter, DataMap dataMap, QueryAssembler assembler) {
+ super(dbAdapter, dataMap, assembler);
}
@Override
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/Oracle8SelectTranslator.java Wed Jun 17 14:52:11 2009
@@ -31,7 +31,7 @@
*/
@Override
protected JoinStack createJoinStack() {
- return new Oracle8JoinStack(getAdapter(), queryMetadata.getDataMap());
+ return new Oracle8JoinStack(getAdapter(), queryMetadata.getDataMap(), this);
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java Wed Jun 17 14:52:11 2009
@@ -65,7 +65,7 @@
/**
* Qualifier, that will be applied to all select queries and joins with this DbEntity
*/
- protected String qualifier;
+ protected Expression qualifier;
/**
* Creates an unnamed DbEntity.
@@ -116,9 +116,9 @@
getPrimaryKeyGenerator().encodeAsXML(encoder);
}
- if (getQualifier() != null && getQualifier().trim().length() > 0) {
+ if (getQualifier() != null) {
encoder.print("<qualifier><![CDATA[");
- encoder.print(getQualifier());
+ getQualifier().encodeAsXML(encoder);
encoder.println("]]></qualifier>");
}
@@ -559,14 +559,14 @@
/**
* @return qualifier that will be ANDed to all select queries with this entity
*/
- public String getQualifier() {
+ public Expression getQualifier() {
return qualifier;
}
/**
* Sets qualifier for this entity
*/
- public void setQualifier(String qualifier) {
+ public void setQualifier(Expression qualifier) {
this.qualifier = qualifier;
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MapLoader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MapLoader.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MapLoader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MapLoader.java Wed Jun 17 14:52:11 2009
@@ -1241,7 +1241,7 @@
objEntity.setDeclaredQualifier(Expression.fromString(qualifier));
}
else if (dbEntity != null) {
- dbEntity.setQualifier(qualifier);
+ dbEntity.setQualifier(Expression.fromString(qualifier));
}
else {
queryBuilder.setQualifier(qualifier);
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/trans/SelectTranslatorTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/trans/SelectTranslatorTest.java?rev=785634&r1=785633&r2=785634&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/trans/SelectTranslatorTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/trans/SelectTranslatorTest.java Wed Jun 17 14:52:11 2009
@@ -80,8 +80,8 @@
SelectQuery q = new SelectQuery(Artist.class);
final DbEntity entity = getNode().getEntityResolver().getDbEntity("ARTIST");
final DbEntity middleEntity = getNode().getEntityResolver().getDbEntity("ARTIST_GROUP");
- entity.setQualifier("ARTIST_NAME = \"123\"");
- middleEntity.setQualifier("ARTIST_GROUP_ID = 1987");
+ entity.setQualifier(Expression.fromString("ARTIST_NAME = \"123\""));
+ middleEntity.setQualifier(Expression.fromString("GROUP_ID = 1987"));
try {
Template test = new Template() {
@@ -93,14 +93,15 @@
assertNotNull(generatedSql);
assertTrue(generatedSql.startsWith("SELECT "));
assertTrue(generatedSql.indexOf(" FROM ") > 0);
- assertTrue(generatedSql.indexOf(entity.getQualifier()) > 0);
+ assertTrue(generatedSql.indexOf("ARTIST_NAME = ") > 0);
}
};
test.test(q);
//testing quering from related table
- q = new SelectQuery(Painting.class, ExpressionFactory.matchExp("toArtist.artistName", "foo"));
+ q = new SelectQuery(Painting.class,
+ ExpressionFactory.matchExp("toArtist.artistName", "foo"));
test.test(q);
//testing flattened rels
@@ -108,7 +109,7 @@
new Template() {
@Override
void test(SelectTranslator transl) throws Exception {
- assertTrue(transl.createSqlString().indexOf(middleEntity.getQualifier()) > 0);
+ assertTrue(transl.createSqlString().indexOf("GROUP_ID = ") > 0);
}
}.test(q);
}