Repository: cayenne
Updated Branches:
  refs/heads/master 008e77d1e -> 988937524


CAY-2507 Property api to add aliases


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/e996e800
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/e996e800
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/e996e800

Branch: refs/heads/master
Commit: e996e8001658698ecd4ccc56f41aafd4e04b0924
Parents: 9ea878c
Author: Arseni Bulatski <ancars...@gmail.com>
Authored: Sat Dec 29 16:58:14 2018 +0300
Committer: Arseni Bulatski <ancars...@gmail.com>
Committed: Wed Jan 2 16:10:45 2019 +0300

----------------------------------------------------------------------
 RELEASE-NOTES.txt                               |   8 +
 .../apache/cayenne/exp/ExpressionFactory.java   |   2 +-
 .../apache/cayenne/exp/parser/ASTDbPath.java    |  13 +-
 .../apache/cayenne/exp/parser/ASTObjPath.java   |   7 +-
 .../org/apache/cayenne/exp/parser/ASTPath.java  |   6 +-
 .../cayenne/exp/property/BaseProperty.java      |  10 +-
 .../cayenne/exp/property/EntityProperty.java    |   6 +-
 .../cayenne/exp/property/ListProperty.java      |  10 +-
 .../cayenne/exp/property/MapProperty.java       |  13 +-
 .../cayenne/exp/property/PropertyFactory.java   |   4 +-
 .../cayenne/exp/property/PropertyUtils.java     |  70 +++++++
 .../exp/property/RelationshipProperty.java      |  49 ++++-
 .../cayenne/exp/property/SetProperty.java       |  10 +-
 .../java/org/apache/cayenne/map/ObjEntity.java  |  51 ++---
 .../cayenne/query/SelectQueryMetadata.java      |  74 ++++++--
 .../exp/property/EntityPropertyTest.java        |  15 +-
 .../cayenne/exp/property/ListPropertyTest.java  |  22 ++-
 .../cayenne/exp/property/MapPropertyTest.java   |  19 +-
 .../cayenne/exp/property/PropertyAliasesIT.java | 189 +++++++++++++++++++
 .../cayenne/exp/property/SetPropertyTest.java   |  13 +-
 .../apache/cayenne/query/ColumnSelectIT.java    |  27 +--
 .../apache/cayenne/query/ObjectSelectTest.java  |  20 +-
 .../cayenne/query/ObjectSelect_AggregateIT.java |  18 +-
 .../cayenne/query/ObjectSelect_RunIT.java       |   5 +-
 .../org/apache/cayenne/query/SelectQueryIT.java |  23 ++-
 25 files changed, 537 insertions(+), 147 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index f2248cd..aaa4e39 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -8,6 +8,14 @@ To browse individual bug reports check out project issue 
tracker:
 https://issues.apache.org/jira/browse/CAY
 
 ----------------------------------
+Release: 4.2.M1
+Date:
+----------------------------------
+Changes/New Features:
+
+CAY-2507 Property api to add aliases
+
+----------------------------------
 Release: 4.1.M3
 Date:
 ----------------------------------

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
index 92f45cc..3ad5e77 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
@@ -329,7 +329,7 @@ public class ExpressionFactory {
 
                        int splitEnd = path.indexOf(Entity.PATH_SEPARATOR, 
split + 1);
 
-                       String beforeSplit = split > 0 ? path.substring(0, 
split) + "." : "";
+                       String beforeSplit = split > 0 ? path.substring(0, 
split) : "";
                        String afterSplit = splitEnd > 0 ? "." + 
path.substring(splitEnd + 1) : "";
                        String aliasBase = "split" + autoAliasId++ + "_";
                        String splitChunk = splitEnd > 0 ? path.substring(split 
+ 1, splitEnd) : path.substring(split + 1);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
index f3f2f7b..870b84d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
@@ -19,12 +19,6 @@
 
 package org.apache.cayenne.exp.parser;
 
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ObjectId;
@@ -39,6 +33,12 @@ import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.SelectById;
 import org.apache.cayenne.util.CayenneMapEntry;
 
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Path expression traversing DB relationships and attributes.
  * 
@@ -166,6 +166,7 @@ public class ASTDbPath extends ASTPath {
        public Expression shallowCopy() {
                ASTDbPath copy = new ASTDbPath(id);
                copy.path = path;
+               copy.setPathAliases(pathAliases);
                return copy;
        }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
index 6c1604e..c536fc6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
@@ -19,9 +19,6 @@
 
 package org.apache.cayenne.exp.parser;
 
-import java.io.IOException;
-import java.util.List;
-
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.exp.Expression;
@@ -31,6 +28,9 @@ import org.apache.cayenne.reflect.PropertyUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+import java.util.List;
+
 public class ASTObjPath extends ASTPath {
 
        private static final long serialVersionUID = -3574281576491705706L;
@@ -68,6 +68,7 @@ public class ASTObjPath extends ASTPath {
        public Expression shallowCopy() {
                ASTObjPath copy = new ASTObjPath(id);
                copy.path = path;
+               copy.setPathAliases(pathAliases);
                return copy;
        }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTPath.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTPath.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTPath.java
index 8ab1a39..f88b570 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTPath.java
@@ -19,12 +19,12 @@
 
 package org.apache.cayenne.exp.parser;
 
-import java.util.Iterator;
-import java.util.Map;
-
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.util.CayenneMapEntry;
 
+import java.util.Iterator;
+import java.util.Map;
+
 /**
  * Generic path expression.
  * 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/BaseProperty.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/BaseProperty.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/BaseProperty.java
index 1ce3836..28bc264 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/BaseProperty.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/BaseProperty.java
@@ -19,11 +19,6 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.function.Supplier;
-
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.FunctionExpressionFactory;
@@ -33,6 +28,11 @@ import org.apache.cayenne.query.Orderings;
 import org.apache.cayenne.query.SortOrder;
 import org.apache.cayenne.reflect.PropertyUtils;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Supplier;
+
 /**
  * Property that represents generic attribute.
  * <p>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/EntityProperty.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/EntityProperty.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/EntityProperty.java
index 6398a22..1f087d6 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/EntityProperty.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/EntityProperty.java
@@ -56,7 +56,11 @@ public class EntityProperty<E extends Persistent> extends 
BaseProperty<E> implem
      */
     @Override
     public EntityProperty<E> alias(String alias) {
-        return PropertyFactory.createEntity(alias, getExpression(), getType());
+        String substrPath = PropertyUtils.substringPath(this.getName());
+        String aliasedPath = substrPath + alias;
+        return PropertyFactory.createEntity(aliasedPath,
+                PropertyUtils.createPathExp(aliasedPath, 
this.getName().substring(substrPath.length()), alias, 
getExpression().getPathAliases()),
+                this.getType());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/ListProperty.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/ListProperty.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/ListProperty.java
index 410d6db..d8021dc 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/ListProperty.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/ListProperty.java
@@ -19,11 +19,11 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.util.List;
-
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.exp.Expression;
 
+import java.util.List;
+
 /**
  * Property that represents to-many relationship mapped on {@link List}.
  * <pre>{@code
@@ -52,7 +52,11 @@ public class ListProperty<V extends Persistent> extends 
CollectionProperty<V, Li
      */
     @Override
     public ListProperty<V> alias(String alias) {
-        return PropertyFactory.createList(alias, this.getExpression(), 
this.getEntityType());
+        String substrPath = PropertyUtils.substringPath(this.getName());
+        String aliasedPath = substrPath + alias;
+        return PropertyFactory.createList(aliasedPath,
+                PropertyUtils.createPathExp(aliasedPath, 
this.getName().substring(substrPath.length()), alias, 
getExpression().getPathAliases()),
+                this.getEntityType());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/MapProperty.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/MapProperty.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/MapProperty.java
index 0137659..1974de4 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/MapProperty.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/MapProperty.java
@@ -19,13 +19,13 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.util.Collection;
-import java.util.Map;
-
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 
+import java.util.Collection;
+import java.util.Map;
+
 /**
  * Property that represents to-many relationship mapped on {@link Map}.
  *
@@ -204,7 +204,12 @@ public class MapProperty<K, V extends Persistent> extends 
BaseProperty<Map<K, V>
      */
     @Override
     public MapProperty<K, V> alias(String alias) {
-        return PropertyFactory.createMap(alias, this.getExpression(), 
getKeyType(), getEntityType());
+        String substrPath = PropertyUtils.substringPath(this.getName());
+        String aliasedPath = substrPath + alias;
+        return PropertyFactory.createMap(aliasedPath,
+                PropertyUtils.createPathExp(aliasedPath, 
this.getName().substring(substrPath.length()), alias, 
getExpression().getPathAliases()),
+                this.getKeyType(),
+                this.getEntityType());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyFactory.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyFactory.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyFactory.java
index c355d73..e16d936 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyFactory.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyFactory.java
@@ -19,14 +19,14 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.time.LocalDateTime;
-
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.FunctionExpressionFactory;
 
+import java.time.LocalDateTime;
+
 /**
  *
  * Factory class that produces all property types.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyUtils.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyUtils.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyUtils.java
new file mode 100644
index 0000000..43b41fc
--- /dev/null
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/PropertyUtils.java
@@ -0,0 +1,70 @@
+/*****************************************************************
+ *   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.exp.property;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.ASTPath;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 4.2
+ */
+class PropertyUtils {
+
+    static ASTPath createPathExp(String aliasedPath, String segment, String 
alias, Map<String, String> aliasMap) {
+        ASTPath pathExp = new ASTObjPath(aliasedPath);
+        Map<String, String> aliases = new HashMap<>(aliasMap);
+        aliases.put(alias, segment);
+        pathExp.setPathAliases(aliases);
+
+        return pathExp;
+    }
+
+    static ASTPath createExpressionWithCopiedAliases(String name, Expression 
expression) {
+        if(expression instanceof ASTPath) {
+            ASTPath pathExp = new ASTObjPath(name);
+            pathExp.setPathAliases(expression.getPathAliases());
+            return pathExp;
+        }
+
+        throw new CayenneRuntimeException("Dot is used only with path 
expressions.");
+    }
+
+    static String substringPath(String propertyName){
+        for(int i = propertyName.length() - 1; i >= 0; i--) {
+            if(propertyName.charAt(i) == '.') {
+                return propertyName.substring(0, i + 1);
+            }
+        }
+
+        return "";
+    }
+
+    static void checkAliases(Expression expression) {
+        if(!expression.getPathAliases().isEmpty()) {
+            throw new CayenneRuntimeException("Can't use aliases with 
prefetch");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/RelationshipProperty.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/RelationshipProperty.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/RelationshipProperty.java
index 13b9fdc..76e9d5a 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/RelationshipProperty.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/RelationshipProperty.java
@@ -38,7 +38,10 @@ public interface RelationshipProperty<E> extends Property<E> 
{
      * @return a newly created Property object.
      */
     default BaseProperty<Object> dot(String property) {
-        return PropertyFactory.createBase(getName() + "." + property, null);
+        String path = getName() + "." + property;
+        return PropertyFactory.createBase(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                null);
     }
 
     /**
@@ -48,7 +51,10 @@ public interface RelationshipProperty<E> extends Property<E> 
{
      * @return a newly created Property object.
      */
     default <T> BaseProperty<T> dot(BaseProperty<T> property) {
-        return PropertyFactory.createBase(getName() + "." + 
property.getName(), property.getType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createBase(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getType());
     }
 
     /**
@@ -58,7 +64,10 @@ public interface RelationshipProperty<E> extends Property<E> 
{
      * @return a newly created Property object.
      */
     default <T extends Number> NumericProperty<T> dot(NumericProperty<T> 
property) {
-        return PropertyFactory.createNumeric(getName() + "." + 
property.getName(), property.getType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createNumeric(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getType());
     }
 
     /**
@@ -68,7 +77,10 @@ public interface RelationshipProperty<E> extends Property<E> 
{
      * @return a newly created Property object.
      */
     default <T extends CharSequence> StringProperty<T> dot(StringProperty<T> 
property) {
-        return PropertyFactory.createString(getName() + "." + 
property.getName(), property.getType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createString(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getType());
     }
 
     /**
@@ -78,7 +90,10 @@ public interface RelationshipProperty<E> extends Property<E> 
{
      * @return a newly created Property object.
      */
     default <T> DateProperty<T> dot(DateProperty<T> property) {
-        return PropertyFactory.createDate(getName() + "." + 
property.getName(), property.getType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createDate(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getType());
     }
 
     /**
@@ -88,7 +103,10 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * @return a newly created Property object.
      */
     default <T extends Persistent> EntityProperty<T> dot(EntityProperty<T> 
property) {
-        return PropertyFactory.createEntity(getName() + "." + 
property.getName(), property.getType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createEntity(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getType());
     }
 
     /**
@@ -98,7 +116,10 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * @return a newly created Property object.
      */
     default <T extends Persistent> ListProperty<T> dot(ListProperty<T> 
property) {
-        return PropertyFactory.createList(getName() + "." + 
property.getName(), property.getEntityType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createList(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getEntityType());
     }
 
     /**
@@ -108,7 +129,10 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * @return a newly created Property object.
      */
     default <T extends Persistent> SetProperty<T> dot(SetProperty<T> property) 
{
-        return PropertyFactory.createSet(getName() + "." + property.getName(), 
property.getEntityType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createSet(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getEntityType());
     }
 
     /**
@@ -118,7 +142,11 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * @return a newly created Property object.
      */
     default <K, V extends Persistent> MapProperty<K, V> dot(MapProperty<K, V> 
property) {
-        return PropertyFactory.createMap(getName() + "." + property.getName(), 
property.getKeyType(), property.getEntityType());
+        String path = getName() + "." + property.getName();
+        return PropertyFactory.createMap(path,
+                PropertyUtils.createExpressionWithCopiedAliases(path, 
getExpression()),
+                property.getKeyType(),
+                property.getEntityType());
     }
 
     /**
@@ -134,6 +162,7 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * prefetch semantics.
      */
     default PrefetchTreeNode joint() {
+        PropertyUtils.checkAliases(getExpression());
         return PrefetchTreeNode.withPath(getName(), 
PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
     }
 
@@ -143,6 +172,7 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * "disjoint" prefetch semantics.
      */
     default PrefetchTreeNode disjoint() {
+        PropertyUtils.checkAliases(getExpression());
         return PrefetchTreeNode.withPath(getName(), 
PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
     }
 
@@ -152,6 +182,7 @@ public interface RelationshipProperty<E> extends 
Property<E> {
      * "disjoint by id" prefetch semantics.
      */
     default PrefetchTreeNode disjointById() {
+        PropertyUtils.checkAliases(getExpression());
         return PrefetchTreeNode.withPath(getName(), 
PrefetchTreeNode.DISJOINT_BY_ID_PREFETCH_SEMANTICS);
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/exp/property/SetProperty.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/SetProperty.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/SetProperty.java
index f7ded0b..908fab7 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/property/SetProperty.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/property/SetProperty.java
@@ -19,11 +19,11 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.util.Set;
-
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.exp.Expression;
 
+import java.util.Set;
+
 /**
  * Property that represents to-many relationship mapped on {@link Set}.
  *
@@ -48,7 +48,11 @@ public class SetProperty<V extends Persistent> extends 
CollectionProperty<V, Set
      */
     @Override
     public SetProperty<V> alias(String alias) {
-        return PropertyFactory.createSet(alias, this.getExpression(), 
this.getEntityType());
+        String substrPath = PropertyUtils.substringPath(this.getName());
+        String aliasedPath = substrPath + alias;
+        return PropertyFactory.createSet(aliasedPath,
+                PropertyUtils.createPathExp(aliasedPath, 
this.getName().substring(substrPath.length()), alias, 
getExpression().getPathAliases()),
+                this.getEntityType());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java 
b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
index 74e793d..d9ddca3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
@@ -1003,15 +1003,14 @@ public class ObjEntity extends Entity implements 
ObjEntityListener, Configuratio
 
         DBPathConverter transformer = new DBPathConverter();
 
-        String dbPath = 
transformer.toDbPath(createPathIterator(relationshipPath));
+        String dbPath = 
transformer.toDbPath(createPathIterator(relationshipPath, 
expression.getPathAliases()));
         Expression dbClone = expression.transform(transformer);
 
         return getDbEntity().translateToRelatedEntity(dbClone, dbPath);
     }
 
-    private PathComponentIterator createPathIterator(String path) {
-        return new PathComponentIterator(ObjEntity.this, path, 
Collections.emptyMap());
-        // TODO: do we need aliases here?
+    private PathComponentIterator createPathIterator(String path, Map<String, 
String> aliasMap) {
+        return new PathComponentIterator(ObjEntity.this, path, aliasMap);
     }
 
     /**
@@ -1037,31 +1036,41 @@ public class ObjEntity extends Entity implements 
ObjEntityListener, Configuratio
                 PathComponent<Attribute, Relationship> component = 
objectPathComponents.next();
 
                 Iterator<?> dbSubpath;
-
-                if (component.getAttribute() != null) {
+                if(component.getAttribute() != null) {
                     dbSubpath = ((ObjAttribute) 
component.getAttribute()).getDbPathIterator();
-                } else if (component.getRelationship() != null) {
+                    buildPath(dbSubpath, component, buf);
+                } else if(component.getRelationship() != null) {
                     dbSubpath = ((ObjRelationship) 
component.getRelationship()).getDbRelationships().iterator();
+                    buildPath(dbSubpath, component, buf);
+                } else if(component.getAliasedPath() != null) {
+                    for(PathComponent<Attribute, Relationship> pathComponent : 
component.getAliasedPath()) {
+                       if(pathComponent.getRelationship() != null) {
+                           dbSubpath = ((ObjRelationship) 
pathComponent.getRelationship()).getDbRelationships().iterator();
+                           buildPath(dbSubpath, pathComponent, buf);
+                       }
+                    }
                 } else {
                     throw new CayenneRuntimeException("Unknown path component: 
%s", component);
                 }
+            }
 
-                while (dbSubpath.hasNext()) {
-                    CayenneMapEntry subComponent = (CayenneMapEntry) 
dbSubpath.next();
-                    if (buf.length() > 0) {
-                        buf.append(Entity.PATH_SEPARATOR);
-                    }
+            return buf.toString();
+        }
 
-                    buf.append(subComponent.getName());
-                    
-                    // use OUTER join for all components of the path is Obj 
path is OUTER
-                    if (component.getJoinType() == JoinType.LEFT_OUTER) {
-                        buf.append(OUTER_JOIN_INDICATOR);
-                    }
+        private void buildPath(Iterator<?> dbSubpath, PathComponent<Attribute, 
Relationship> component, StringBuilder buf) {
+            while (dbSubpath.hasNext()) {
+                CayenneMapEntry subComponent = (CayenneMapEntry) 
dbSubpath.next();
+                if (buf.length() > 0) {
+                    buf.append(Entity.PATH_SEPARATOR);
                 }
-            }
 
-            return buf.toString();
+                buf.append(subComponent.getName());
+
+                // use OUTER join for all components of the path is Obj path 
is OUTER
+                if (component.getJoinType() == JoinType.LEFT_OUTER) {
+                    buf.append(OUTER_JOIN_INDICATOR);
+                }
+            }
         }
 
         public Object apply(Object input) {
@@ -1077,7 +1086,7 @@ public class ObjEntity extends Entity implements 
ObjEntityListener, Configuratio
             }
 
             // convert obj_path to db_path
-            String converted = toDbPath(createPathIterator((String) 
expression.getOperand(0)));
+            String converted = toDbPath(createPathIterator((String) 
expression.getOperand(0), expression.getPathAliases()));
             return ExpressionFactory.dbPathExp(converted);
         }
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
index 13c6761..63e72f8 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
@@ -18,26 +18,18 @@
  ****************************************************************/
 package org.apache.cayenne.query;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.types.ValueObjectType;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
-import org.apache.cayenne.exp.property.BaseProperty;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.TraversalHandler;
 import org.apache.cayenne.exp.parser.ASTDbPath;
 import org.apache.cayenne.exp.parser.ASTFunctionCall;
 import org.apache.cayenne.exp.parser.ASTScalar;
+import org.apache.cayenne.exp.property.BaseProperty;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbJoin;
@@ -56,6 +48,15 @@ import org.apache.cayenne.reflect.ToManyProperty;
 import org.apache.cayenne.reflect.ToOneProperty;
 import org.apache.cayenne.util.CayenneMapEntry;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @since 3.0
  */
@@ -63,9 +64,9 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 
        private static final long serialVersionUID = 7465922769303943945L;
        
-       Map<String, String> pathSplitAliases;
-       boolean isSingleResultSetMapping;
-       boolean suppressingDistinct;
+       private Map<String, String> pathSplitAliases;
+       private boolean isSingleResultSetMapping;
+       private boolean suppressingDistinct;
 
        @Override
        void copyFromInfo(QueryMetadata info) {
@@ -154,21 +155,64 @@ class SelectQueryMetadata extends BaseQueryMetadata {
        }
 
        private void resolveAutoAliases(SelectQuery<?> query) {
+               resolveQualifierAliases(query);
+               resolveColumnsAliases(query);
+        resolveOrderingAliases(query);
+               resolveHavingQualifierAliases(query);
+               // TODO: include aliases in prefetches? flattened attributes?
+       }
+
+       private void resolveQualifierAliases(SelectQuery<?> query) {
                Expression qualifier = query.getQualifier();
                if (qualifier != null) {
                        resolveAutoAliases(qualifier);
                }
-
-               // TODO: include aliases in prefetches? flattened attributes?
        }
 
+       private void resolveColumnsAliases(SelectQuery<?> query) {
+        Collection<BaseProperty<?>> columns = query.getColumns();
+        if(columns != null) {
+            for(BaseProperty<?> property : columns) {
+                Expression propertyExpression = property.getExpression();
+                if(propertyExpression != null) {
+                    resolveAutoAliases(propertyExpression);
+                }
+            }
+        }
+    }
+
+    private void resolveOrderingAliases(SelectQuery<?> query) {
+        List<Ordering> orderings = query.getOrderings();
+        if(orderings != null) {
+            for(Ordering ordering : orderings) {
+                Expression sortSpec = ordering.getSortSpec();
+                if(sortSpec != null) {
+                    resolveAutoAliases(sortSpec);
+                }
+            }
+        }
+    }
+
+    private void resolveHavingQualifierAliases(SelectQuery<?> query) {
+        Expression havingQualifier = query.getHavingQualifier();
+        if(havingQualifier != null) {
+            resolveAutoAliases(havingQualifier);
+        }
+    }
+
        private void resolveAutoAliases(Expression expression) {
                Map<String, String> aliases = expression.getPathAliases();
                if (!aliases.isEmpty()) {
                        if (pathSplitAliases == null) {
                                pathSplitAliases = new HashMap<>();
                        }
-
+                       for(String key : aliases.keySet()) {
+                               if(pathSplitAliases.containsKey(key)) {
+                                       
if(!pathSplitAliases.get(key).equals(aliases.get(key))) {
+                                               throw new 
CayenneRuntimeException("Can't add the same alias to different path segments.");
+                                       }
+                               }
+                       }
                        pathSplitAliases.putAll(aliases);
                }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
index 8b9ba0e..046e37a 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
@@ -24,7 +24,7 @@ import org.apache.cayenne.testdo.testmap.Artist;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 /**
  * @since 4.2
@@ -32,21 +32,26 @@ import static org.junit.Assert.*;
 public class EntityPropertyTest {
 
     private EntityProperty<Artist> property;
+    private EntityProperty<Artist> property1;
 
     @Before
     public void createProperty() {
         property = new EntityProperty<>("path", null, Artist.class);
+        property1 = new EntityProperty<>("path.artist", null, Artist.class);
     }
 
     @Test
     public void alias() {
         assertEquals("path", property.getName());
-        assertNull(property.getAlias());
-
         property = property.alias("alias");
-
         assertEquals("alias", property.getName());
-        assertEquals("alias", property.getAlias());
+        assertEquals(1, property.getExpression().getPathAliases().size());
+
+        assertEquals("path.artist", property1.getName());
+        property1 = property1.alias("a");
+        assertEquals("path.a", property1.getName());
+        assertEquals(1, property1.getExpression().getPathAliases().size());
+        assertEquals("artist", 
property1.getExpression().getPathAliases().get("a"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
index fb775af..df87539 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
@@ -19,17 +19,16 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
 
 /**
  * @since 4.2
@@ -37,22 +36,27 @@ import static org.junit.Assert.*;
 public class ListPropertyTest {
 
     private ListProperty<Artist> property;
+    private ListProperty<Artist> property1;
 
     @Before
     public void createProperty() {
         property = new ListProperty<>("path", null, Artist.class);
+        property1 = new ListProperty<>("path.artist", null, Artist.class);
     }
 
 
     @Test
     public void alias() {
         assertEquals("path", property.getName());
-        assertNull(property.getAlias());
-
         property = property.alias("alias");
-
         assertEquals("alias", property.getName());
-        assertEquals("alias", property.getAlias());
+        assertEquals(1, property.getExpression().getPathAliases().size());
+
+        assertEquals("path.artist", property1.getName());
+        property1 = property1.alias("a");
+        assertEquals("path.a", property1.getName());
+        assertEquals(1, property1.getExpression().getPathAliases().size());
+        assertEquals("artist", 
property1.getExpression().getPathAliases().get("a"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
index bc4ee9e..5545942 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
@@ -19,15 +19,15 @@
 
 package org.apache.cayenne.exp.property;
 
-import java.util.Arrays;
-
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
 
 /**
  * @since 4.2
@@ -35,10 +35,12 @@ import static org.junit.Assert.*;
 public class MapPropertyTest {
 
     private MapProperty<Integer, Artist> property;
+    private MapProperty<Integer, Artist> property1;
 
     @Before
     public void createProperty() {
         property = new MapProperty<>("path", null, Integer.class, 
Artist.class);
+        property1 = new MapProperty<>("path.artist", null, Integer.class, 
Artist.class);
     }
 
     @Test
@@ -132,12 +134,15 @@ public class MapPropertyTest {
     @Test
     public void alias() {
         assertEquals("path", property.getName());
-        assertNull(property.getAlias());
-
         property = property.alias("alias");
-
         assertEquals("alias", property.getName());
-        assertEquals("alias", property.getAlias());
+        assertEquals(1, property.getExpression().getPathAliases().size());
+
+        assertEquals("path.artist", property1.getName());
+        property1 = property1.alias("a");
+        assertEquals("path.a", property1.getName());
+        assertEquals(1, property1.getExpression().getPathAliases().size());
+        assertEquals("artist", 
property1.getExpression().getPathAliases().get("a"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyAliasesIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyAliasesIT.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyAliasesIT.java
new file mode 100644
index 0000000..5dbfe14
--- /dev/null
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyAliasesIT.java
@@ -0,0 +1,189 @@
+/*****************************************************************
+ *   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.exp.property;
+
+import org.apache.cayenne.Cayenne;
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.exp.parser.ASTEqual;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.ASTPath;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Gallery;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @since 4.2
+ */
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class PropertyAliasesIT extends ServerCase {
+
+    @Inject
+    private DataContext context;
+
+    @Inject
+    private DBHelper dbHelper;
+
+    @Before
+    public void createArtistsDataSet() throws Exception {
+        TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
+        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME", "DATE_OF_BIRTH");
+
+        long dateBase = System.currentTimeMillis();
+        for (int i = 1; i <= 20; i++) {
+            tArtist.insert(i, "artist" + i, new java.sql.Date(dateBase + 10000 
* i));
+        }
+
+        TableHelper tGallery = new TableHelper(dbHelper, "GALLERY");
+        tGallery.setColumns("GALLERY_ID", "GALLERY_NAME");
+        tGallery.insert(1, "tate modern");
+
+        TableHelper tGallery1 = new TableHelper(dbHelper, "GALLERY");
+        tGallery1.setColumns("GALLERY_ID", "GALLERY_NAME");
+        tGallery1.insert(2, "test gallery");
+
+        TableHelper tPaintings = new TableHelper(dbHelper, "PAINTING");
+        tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", 
"GALLERY_ID");
+        for (int i = 1; i <= 20; i++) {
+            tPaintings.insert(i, "painting" + i,
+                    i % 2 == 0 ? 4 : i % 5 + 1,
+                    i % 2 == 0 ? 2 : 1);
+        }
+    }
+
+    @Test
+    public void testBeginAlias() {
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                
.where(Artist.PAINTING_ARRAY.alias("p1").dot(Painting.PAINTING_TITLE).eq("painting2"))
+                
.and(Artist.PAINTING_ARRAY.alias("p2").dot(Painting.PAINTING_TITLE).eq("painting4"))
+                .select(context);
+        assertEquals(1, artists.size());
+        assertEquals("artist4", artists.get(0).getArtistName());
+    }
+
+    @Test
+    public void testTheSameAliases() {
+        List<Object[]> results = ObjectSelect.columnQuery(Artist.class,
+                Artist.ARTIST_NAME,
+                Artist.PAINTING_ARRAY.alias("p1").dot(Painting.PAINTING_TITLE),
+                Artist.PAINTING_ARRAY.alias("p2").dot(Painting.PAINTING_TITLE))
+                
.where(Artist.PAINTING_ARRAY.alias("p1").dot(Painting.PAINTING_TITLE).eq("painting2"))
+                
.and(Artist.PAINTING_ARRAY.alias("p2").dot(Painting.PAINTING_TITLE).eq("painting4"))
+                .select(context);
+        assertEquals(1, results.size());
+        assertEquals("artist4", results.get(0)[0]);
+        assertEquals("painting2", results.get(0)[1]);
+        assertEquals("painting4", results.get(0)[2]);
+    }
+
+    @Test
+    public void testMiddleAlias() {
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                
.where(Artist.PAINTING_ARRAY.dot(Painting.TO_GALLERY).dot(Gallery.PAINTING_ARRAY).alias("p1").dot(Painting.PAINTING_TITLE).eq("painting2"))
+                
.and(Artist.PAINTING_ARRAY.dot(Painting.TO_GALLERY).dot(Gallery.PAINTING_ARRAY).alias("p2").dot(Painting.PAINTING_TITLE).eq("painting4"))
+                .select(context);
+        assertEquals(1, artists.size());
+        assertEquals("artist4", artists.get(0).getArtistName());
+    }
+
+    @Test
+    public void testEntityPropertyAliases() {
+        Artist artist = Cayenne.objectForPK(context, Artist.class, 1);
+
+        SelectQuery<Painting> query = SelectQuery.query(Painting.class);
+        Expression expression = Painting.TO_ARTIST.alias("p1").eq(artist);
+        query.setQualifier(expression);
+        List<Painting> paintings = query.select(context);
+        assertEquals(2, paintings.size());
+        assertEquals("painting5", paintings.get(0).getPaintingTitle());
+    }
+
+    @Test
+    public void testAliases() {
+        SelectQuery<Artist> query1 = new SelectQuery<>(Artist.class);
+        Expression expression = ExpressionFactory.and(
+                
Artist.PAINTING_ARRAY.alias("p1").dot(Painting.PAINTING_TITLE).eq("painting2"),
+                
Artist.PAINTING_ARRAY.alias("p2").dot(Painting.PAINTING_TITLE).eq("painting4")
+        );
+        query1.setQualifier(expression);
+        List<Artist> artists = query1.select(context);
+        assertEquals(1, artists.size());
+        assertNotNull(artists.get(0));
+        assertEquals("artist4", artists.get(0).getArtistName());
+    }
+
+    @Test
+    public void testAliasForPath() {
+        ASTPath astPath = new ASTObjPath("a.galleryName");
+        astPath.setPathAliases(Collections.singletonMap("a", 
"paintingArray.toGallery"));
+        ASTEqual astEqual = new ASTEqual(astPath, "tate modern");
+        List<Object[]> artists = ObjectSelect.columnQuery(Artist.class, 
Artist.ARTIST_NAME, PropertyFactory.createBase(astPath, String.class))
+                .where(astEqual)
+                .orderBy(Artist.ARTIST_NAME.asc())
+                .select(context);
+        assertEquals(5, artists.size());
+        assertEquals("artist1", artists.get(0)[0]);
+    }
+
+    @Test
+    public void testAggregationWithAliases() {
+        List<Object[]> artistAndPaintingCount = 
ObjectSelect.columnQuery(Artist.class, Artist.ARTIST_NAME, 
Artist.PAINTING_ARRAY.count())
+                .having(Artist.PAINTING_ARRAY.alias("p1").count().lt(5L))
+                .select(context);
+        assertEquals(4, artistAndPaintingCount.size());
+        assertTrue((Long)artistAndPaintingCount.get(0)[1] < 5);
+    }
+
+    @Test
+    public void testOrderWithAlias() {
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class)
+                
.orderBy(Artist.PAINTING_ARRAY.alias("p1").dot(Painting.ESTIMATED_PRICE).asc())
+                .prefetch(Artist.PAINTING_ARRAY.disjoint());
+        List<Artist> artists = query.select(context);
+        assertEquals(5, artists.size());
+        assertEquals(2, artists.get(0).getPaintingArray().size());
+    }
+
+    @Test(expected = CayenneRuntimeException.class)
+    public void testPrefetchWithAliases() {
+        ObjectSelect<Artist> query = ObjectSelect.query(Artist.class);
+        query.prefetch(Artist.PAINTING_ARRAY.alias("p1").disjoint());
+        query.select(context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
index 2cd258f..efba282 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
@@ -33,21 +33,26 @@ import static org.junit.Assert.*;
 public class SetPropertyTest {
 
     private SetProperty<Artist> property;
+    private SetProperty<Artist> property1;
 
     @Before
     public void createProperty() {
         property = new SetProperty<>("path", null, Artist.class);
+        property1 = new SetProperty<>("path.artist", null, Artist.class);
     }
 
     @Test
     public void alias() {
         assertEquals("path", property.getName());
-        assertNull(property.getAlias());
-
         property = property.alias("alias");
-
         assertEquals("alias", property.getName());
-        assertEquals("alias", property.getAlias());
+        assertEquals(1, property.getExpression().getPathAliases().size());
+
+        assertEquals("path.artist", property1.getName());
+        property1 = property1.alias("a");
+        assertEquals("path.a", property1.getName());
+        assertEquals(1, property1.getExpression().getPathAliases().size());
+        assertEquals("artist", 
property1.getExpression().getPathAliases().get("a"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
index 04e45b5..4d2ebab 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
@@ -19,15 +19,6 @@
 
 package org.apache.cayenne.query;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.Fault;
 import org.apache.cayenne.ObjectContext;
@@ -36,8 +27,6 @@ import org.apache.cayenne.ResultBatchIterator;
 import org.apache.cayenne.access.DataContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.FunctionExpressionFactory;
 import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
@@ -57,7 +46,21 @@ import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * @since 4.0

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
index dd9e1f2..ae06952 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelectTest.java
@@ -18,6 +18,16 @@
  ****************************************************************/
 package org.apache.cayenne.query;
 
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -25,16 +35,6 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.junit.Test;
-
 public class ObjectSelectTest {
 
        @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
index e88c7cd..b5910bc 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
@@ -19,15 +19,9 @@
 
 package org.apache.cayenne.query;
 
-import java.sql.Types;
-import java.text.DateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-
 import org.apache.cayenne.access.DataContext;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.FunctionExpressionFactory;
 import org.apache.cayenne.exp.property.BaseProperty;
 import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
@@ -42,7 +36,13 @@ import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import static org.apache.cayenne.exp.FunctionExpressionFactory.*;
+import java.sql.Types;
+import java.text.DateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
 import static org.junit.Assert.assertEquals;
 
 /**
@@ -121,7 +121,7 @@ public class ObjectSelect_AggregateIT extends ServerCase {
     @Test
     @Ignore("Not all databases support AVG(DATE) aggregation")
     public void testAvg() throws Exception {
-        BaseProperty<Date> avgProp = 
PropertyFactory.createBase(avgExp(Artist.DATE_OF_BIRTH.getExpression()), 
Date.class);
+        BaseProperty<Date> avgProp = 
PropertyFactory.createBase(FunctionExpressionFactory.avgExp(Artist.DATE_OF_BIRTH.getExpression()),
 Date.class);
 
         Date avg = ObjectSelect.query(Artist.class)
                 .column(avgProp)

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
index c353e1c..df5632f 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
@@ -18,8 +18,6 @@
  ****************************************************************/
 package org.apache.cayenne.query;
 
-import java.util.List;
-
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ResultBatchIterator;
@@ -35,6 +33,8 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.List;
+
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -195,5 +195,4 @@ public class ObjectSelect_RunIT extends ServerCase {
                assertNotNull(a);
                assertEquals("artist1", a.getArtistName());
        }
-
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e996e800/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
index 1bd6d1b..2352612 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
@@ -19,18 +19,6 @@
 
 package org.apache.cayenne.query;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.ResultSet;
-import java.sql.Types;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectContext;
@@ -58,6 +46,17 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
 public class SelectQueryIT extends ServerCase {
 

Reply via email to