You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lens.apache.org by am...@apache.org on 2015/04/30 09:07:27 UTC

incubator-lens git commit: LENS-526 : Fix multiple issues in multifact queries (Rajat Khandelwal via amareshwari)

Repository: incubator-lens
Updated Branches:
  refs/heads/master f14d2d0ac -> b5defa9cf


LENS-526 : Fix multiple issues in multifact queries (Rajat Khandelwal via amareshwari)


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

Branch: refs/heads/master
Commit: b5defa9cf434c917d068167db1aceebe9b510422
Parents: f14d2d0
Author: Rajat Khandelwal <pr...@apache.org>
Authored: Thu Apr 30 12:36:53 2015 +0530
Committer: Amareshwari Sriramadasu <am...@apache.org>
Committed: Thu Apr 30 12:36:53 2015 +0530

----------------------------------------------------------------------
 .../lens/cube/parse/MultiFactHQLContext.java    |  35 ++--
 .../lens/cube/parse/TestBaseCubeQueries.java    | 175 +++++++++++--------
 2 files changed, 131 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/b5defa9c/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java b/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
index ca680e1..0228fb8 100644
--- a/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
+++ b/lens-cube/src/main/java/org/apache/lens/cube/parse/MultiFactHQLContext.java
@@ -18,10 +18,7 @@
  */
 package org.apache.lens.cube.parse;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import org.apache.lens.cube.metadata.Dimension;
 
@@ -31,6 +28,8 @@ import org.apache.hadoop.hive.ql.ErrorMsg;
 import org.apache.hadoop.hive.ql.parse.ASTNode;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
 
+import com.google.common.collect.Lists;
+
 /**
  * Writes a join query with all the facts involved, with where, groupby and having expressions pushed down to the fact
  * queries.
@@ -83,13 +82,15 @@ class MultiFactHQLContext extends SimpleHQLContext {
   }
 
   private String getSelectString() throws SemanticException {
-    Map<Integer, Integer> selectToFactIndex = new HashMap<Integer, Integer>(query.getSelectAST().getChildCount());
+    Map<Integer, List<Integer>> selectToFactIndex =
+      new HashMap<Integer, List<Integer>>(query.getSelectAST().getChildCount());
     int fi = 1;
     for (CandidateFact fact : facts) {
       for (int ind : fact.getSelectIndices()) {
         if (!selectToFactIndex.containsKey(ind)) {
-          selectToFactIndex.put(ind, fi);
+          selectToFactIndex.put(ind, Lists.<Integer>newArrayList());
         }
+        selectToFactIndex.get(ind).add(fi);
       }
       fi++;
     }
@@ -99,8 +100,19 @@ class MultiFactHQLContext extends SimpleHQLContext {
         throw new SemanticException(ErrorMsg.EXPRESSION_NOT_IN_ANY_FACT, HQLParser.getString((ASTNode) query
           .getSelectAST().getChild(i)));
       }
-      select.append("mq").append(selectToFactIndex.get(i)).append(".").append(query.getSelectAlias(i)).append(" ")
-        .append(query.getSelectFinalAlias(i));
+      if (selectToFactIndex.get(i).size() == 1) {
+        select.append("mq").append(selectToFactIndex.get(i).get(0)).append(".")
+          .append(query.getSelectAlias(i)).append(" ");
+      } else {
+        select.append("COALESCE(");
+        String sep = "";
+        for (Integer factIndex : selectToFactIndex.get(i)) {
+          select.append(sep).append("mq").append(factIndex).append(".").append(query.getSelectAlias(i));
+          sep = ", ";
+        }
+        select.append(") ");
+      }
+      select.append(query.getSelectFinalAlias(i));
       if (i != query.getSelectAST().getChildCount() - 1) {
         select.append(", ");
       }
@@ -132,13 +144,16 @@ class MultiFactHQLContext extends SimpleHQLContext {
         fromBuilder.append(" full outer join ");
       }
     }
-    fromBuilder.append(" on ");
     CandidateFact firstFact = facts.iterator().next();
+    if (!firstFact.getDimFieldIndices().isEmpty()) {
+      fromBuilder.append(" on ");
+    }
     for (int i = 2; i <= facts.size(); i++) {
       Iterator<Integer> dimIter = firstFact.getDimFieldIndices().iterator();
       while (dimIter.hasNext()) {
         String dim = query.getSelectAlias(dimIter.next());
-        fromBuilder.append("mq1").append(".").append(dim).append(" = ").append("mq").append(i).append(".").append(dim);
+        fromBuilder.append("mq1").append(".").append(dim).append(" <=> ").append("mq").append(i).append(".")
+          .append(dim);
         if (dimIter.hasNext()) {
           fromBuilder.append(" AND ");
         }

http://git-wip-us.apache.org/repos/asf/incubator-lens/blob/b5defa9c/lens-cube/src/test/java/org/apache/lens/cube/parse/TestBaseCubeQueries.java
----------------------------------------------------------------------
diff --git a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestBaseCubeQueries.java b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestBaseCubeQueries.java
index 69451ad..b1d7a32 100644
--- a/lens-cube/src/test/java/org/apache/lens/cube/parse/TestBaseCubeQueries.java
+++ b/lens-cube/src/test/java/org/apache/lens/cube/parse/TestBaseCubeQueries.java
@@ -21,6 +21,8 @@ package org.apache.lens.cube.parse;
 
 import static org.apache.lens.cube.parse.CubeTestSetup.*;
 
+import static org.testng.Assert.*;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -31,7 +33,6 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.ql.ErrorMsg;
 import org.apache.hadoop.hive.ql.parse.SemanticException;
 
-import org.testng.Assert;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
@@ -55,72 +56,72 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
     SemanticException e;
 
     e = getSemanticExceptionInRewrite("select dim2, SUM(msr1) from basecube" + " where " + TWO_DAYS_RANGE, conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
-    Assert.assertTrue(e.getMessage().contains("dim2") && e.getMessage().contains("msr1"));
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
+    assertTrue(e.getMessage().contains("dim2") && e.getMessage().contains("msr1"));
 
     // Query with only measure should pass, since dim is not in where or group by
     String hql = rewrite("select SUM(msr1), "
       + "SUM(CASE WHEN cityState.name ='foo' THEN msr2"
       + " WHEN dim2 = 'bar' THEN msr1 ELSE msr2 END) "
       + "from basecube where " + TWO_DAYS_RANGE, conf);
-    Assert.assertNotNull(hql);
+    assertNotNull(hql);
 
     // This query should fail because chain ref in where clause
     e = getSemanticExceptionInRewrite("select SUM(msr1), "
       + "SUM(case WHEN cityState.capital ='foo' THEN msr2 ELSE msr1 END) "
       + "from basecube where " + TWO_DAYS_RANGE + " AND cityState.name='foo'", conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
     // Error message should contain chain_name.col_name and it should not contain dim attributes in select clause
     // it should also contain the measure name
-    Assert.assertTrue(e.getMessage().contains("citystate.name")
+    assertTrue(e.getMessage().contains("citystate.name")
       && e.getMessage().contains("msr1")
       && !e.getMessage().contains("capital"), e.getMessage());
 
 
     e = getSemanticExceptionInRewrite("select cityStateCapital, SUM(msr1) from basecube" + " where " + TWO_DAYS_RANGE,
       conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
-    Assert.assertTrue(e.getMessage().contains("citystatecapital") && e.getMessage().contains("msr1"), e.getMessage());
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
+    assertTrue(e.getMessage().contains("citystatecapital") && e.getMessage().contains("msr1"), e.getMessage());
 
     e = getSemanticExceptionInRewrite("select cityState.name, SUM(msr1) from basecube" + " where " + TWO_DAYS_RANGE,
       conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
-    Assert.assertTrue(e.getMessage().contains("citystate.name") && e.getMessage().contains("msr1"));
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
+    assertTrue(e.getMessage().contains("citystate.name") && e.getMessage().contains("msr1"));
 
     e = getSemanticExceptionInRewrite("select cubeState.name, SUM(msr1) from basecube" + " where " + TWO_DAYS_RANGE,
       conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
-    Assert.assertTrue(e.getMessage().contains("cubestate.name") && e.getMessage().contains("msr1"));
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(), ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
+    assertTrue(e.getMessage().contains("cubestate.name") && e.getMessage().contains("msr1"));
 
     e = getSemanticExceptionInRewrite("select dim2, countryid, SUM(msr2) from basecube" + " where " + TWO_DAYS_RANGE,
       conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
       ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
-    Assert.assertTrue(e.getMessage().contains("dim2") && e.getMessage().contains("countryid"));
+    assertTrue(e.getMessage().contains("dim2") && e.getMessage().contains("countryid"));
 
     e = getSemanticExceptionInRewrite("select newmeasure from basecube" + " where " + TWO_DAYS_RANGE, conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
       ErrorMsg.FIELDS_NOT_QUERYABLE.getErrorCode());
-    Assert.assertTrue(e.getMessage().contains("newmeasure"));
+    assertTrue(e.getMessage().contains("newmeasure"));
 
     e = getSemanticExceptionInRewrite("select msr11 + msr2 from basecube" + " where " + TWO_DAYS_RANGE, conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
       ErrorMsg.EXPRESSION_NOT_IN_ANY_FACT.getErrorCode());
     // no fact has the all the dimensions queried
     e = getSemanticExceptionInRewrite("select dim1, stateid, msr3, msr13 from basecube" + " where " + TWO_DAYS_RANGE,
       conf);
-    Assert.assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
+    assertEquals(e.getCanonicalErrorMsg().getErrorCode(),
       ErrorMsg.NO_CANDIDATE_FACT_AVAILABLE.getErrorCode());
     PruneCauses.BriefAndDetailedError pruneCauses = extractPruneCause(e);
     String regexp = String.format(CandidateTablePruneCause.CandidateTablePruneCode.COLUMN_NOT_FOUND.errorFormat,
       "Column Sets: (.*?)", "queriable together");
     Matcher matcher = Pattern.compile(regexp).matcher(pruneCauses.getBrief());
-    Assert.assertTrue(matcher.matches());
-    Assert.assertEquals(matcher.groupCount(), 1);
+    assertTrue(matcher.matches());
+    assertEquals(matcher.groupCount(), 1);
     String columnSetsStr = matcher.group(1);
-    Assert.assertNotEquals(columnSetsStr.indexOf("stateid"), -1);
-    Assert.assertNotEquals(columnSetsStr.indexOf("msr3, msr13"), -1);
-    Assert.assertEquals(pruneCauses.getDetails(),
+    assertNotEquals(columnSetsStr.indexOf("stateid"), -1);
+    assertNotEquals(columnSetsStr.indexOf("msr3, msr13"), -1);
+    assertEquals(pruneCauses.getDetails(),
       new HashMap<String, List<CandidateTablePruneCause>>() {
         {
           put("testfact3_base,testfact3_raw_base", Arrays.asList(CandidateTablePruneCause.columnNotFound("stateid")));
@@ -131,7 +132,6 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
     );
 
 
-
   }
 
 
@@ -173,19 +173,35 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
 
   @Test
   public void testMultipleFacts() throws Exception {
-    String hqlQuery = rewrite("select dim1, roundedmsr2, msr12 from basecube" + " where " + TWO_DAYS_RANGE, conf);
+    String hqlQuery = rewrite("select roundedmsr2, msr12 from basecube" + " where " + TWO_DAYS_RANGE, conf);
     String expected1 =
+      getExpectedQuery(cubeName, "select sum(basecube.msr12) msr12 FROM ", null,
+        null, getWhereForDailyAndHourly2days(cubeName, "C1_testFact2_BASE"));
+    String expected2 =
+      getExpectedQuery(cubeName, "select round(sum(basecube.msr2)/1000) msr2 FROM ", null,
+        null, getWhereForDailyAndHourly2days(cubeName, "C1_testFact1_BASE"));
+    TestCubeRewriter.compareContains(expected1, hqlQuery);
+    TestCubeRewriter.compareContains(expected2, hqlQuery);
+    String lower = hqlQuery.toLowerCase();
+    assertTrue(lower.startsWith("select mq2.msr2 msr2, mq1.msr12 msr12 from ")
+      || lower.startsWith("select mq1.msr2 msr2, mq2.msr12 msr12 from "));
+    assertTrue(lower.contains("mq1 full outer join") && lower.endsWith("mq2"));
+    assertFalse(lower.contains("<=>"));
+
+    hqlQuery = rewrite("select dim1, roundedmsr2, msr12 from basecube" + " where " + TWO_DAYS_RANGE, conf);
+    expected1 =
       getExpectedQuery(cubeName, "select basecube.dim1 dim1, sum(basecube.msr12) msr12 FROM ", null,
         " group by basecube.dim1", getWhereForDailyAndHourly2days(cubeName, "C1_testFact2_BASE"));
-    String expected2 =
+    expected2 =
       getExpectedQuery(cubeName, "select basecube.dim1 dim1, round(sum(basecube.msr2)/1000) msr2 FROM ", null,
         " group by basecube.dim1", getWhereForDailyAndHourly2days(cubeName, "C1_testFact1_BASE"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq2.msr2 msr2, mq1.msr12 msr12 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq1.msr2 msr2, mq2.msr12 msr12 from "));
+    lower = hqlQuery.toLowerCase();
+    assertTrue(lower.startsWith("select coalesce(mq1.dim1, mq2.dim1) dim1, mq2.msr2 msr2, mq1.msr12 msr12 from ")
+      || lower.startsWith("select coalesce(mq1.dim1, mq2.dim1) dim1, mq1.msr2 msr2, mq2.msr12 msr12 from "));
 
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 = mq2.dim1"));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 <=> mq2.dim1"));
 
     // columns in select interchanged
     hqlQuery = rewrite("select dim1, msr12, roundedmsr2 from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -197,10 +213,11 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         " group by basecube.dim1", getWhereForDailyAndHourly2days(cubeName, "C1_testFact1_BASE"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq2.msr12 msr12, mq1.msr2 msr2 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq1.msr12 msr12, mq2.msr2 msr2 from "));
+    lower = hqlQuery.toLowerCase();
+    assertTrue(lower.startsWith("select coalesce(mq1.dim1, mq2.dim1) dim1, mq2.msr12 msr12, mq1.msr2 msr2 from ")
+      || lower.startsWith("select coalesce(mq1.dim1, mq2.dim1) dim1, mq1.msr12 msr12, mq2.msr2 msr2 from "));
 
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 = mq2.dim1"));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 <=> mq2.dim1"));
 
     // query with 3 fact tables
     hqlQuery = rewrite("select dim1, msr12, roundedmsr2, msr13, msr3 from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -217,21 +234,27 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
     TestCubeRewriter.compareContains(expected3, hqlQuery);
-    Assert.assertTrue(
+    assertTrue(
       hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq1.msr12 msr12," + " mq2.msr2 msr2, mq3.msr13 msr13, mq2.msr3 msr3 from ")
-      || hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq1.msr12 msr12," + " mq3.msr2 msr2, mq2.msr13 msr13, mq3.msr3 msr3 from ")
-      || hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq2.msr12 msr12," + " mq1.msr2 msr2, mq3.msr13 msr13, mq1.msr3 msr3 from ")
-      || hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq2.msr12 msr12," + " mq3.msr2 msr2, mq1.msr13 msr13, mq3.msr3 msr3 from ")
-      || hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq3.msr12 msr12," + " mq1.msr2 msr2, mq2.msr13 msr13, mq1.msr3 msr3 from ")
-      || hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq3.msr12 msr12," + " mq2.msr2 msr2, mq1.msr13 msr13, mq2.msr3 msr3 from "));
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.contains("mq2 full outer join ")
-      && hqlQuery.endsWith("mq3 on mq1.dim1 = mq2.dim1 AND mq1.dim1 = mq3.dim1"));
+        "select coalesce(mq1.dim1, mq2.dim1, mq3.dim1) dim1, mq1.msr12 msr12,"
+          + " mq2.msr2 msr2, mq3.msr13 msr13, mq2.msr3 msr3 from ")
+        || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1, mq3.dim1) dim1, mq1.msr12 msr12,"
+          + " mq3.msr2 msr2, mq2.msr13 msr13, mq3.msr3 msr3 from ")
+        || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1, mq3.dim1) dim1, mq2.msr12 msr12,"
+          + " mq1.msr2 msr2, mq3.msr13 msr13, mq1.msr3 msr3 from ")
+        || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1, mq3.dim1) dim1, mq2.msr12 msr12,"
+          + " mq3.msr2 msr2, mq1.msr13 msr13, mq3.msr3 msr3 from ")
+        || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1, mq3.dim1) dim1, mq3.msr12 msr12,"
+          + " mq1.msr2 msr2, mq2.msr13 msr13, mq1.msr3 msr3 from ")
+        || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1, mq3.dim1) dim1, mq3.msr12 msr12,"
+          + " mq2.msr2 msr2, mq1.msr13 msr13, mq2.msr3 msr3 from "));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.contains("mq2 full outer join ")
+      && hqlQuery.endsWith("mq3 on mq1.dim1 <=> mq2.dim1 AND mq1.dim1 <=> mq3.dim1"));
 
     // query two dim attributes
     hqlQuery = rewrite("select dim1, dim11, msr12, roundedmsr2 from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -244,13 +267,15 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         " group by basecube.dim1", getWhereForDailyAndHourly2days(cubeName, "C1_testFact1_BASE"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith(
-      "select mq1.dim1 dim1, mq1.dim11 dim11," + " mq1.msr12 msr12, mq2.msr2 msr2 from ")
+    assertTrue(hqlQuery.toLowerCase().startsWith(
+      "select coalesce(mq1.dim1, mq2.dim1) dim1, coalesce(mq1.dim11, mq2.dim11) dim11,"
+        + " mq1.msr12 msr12, mq2.msr2 msr2 from ")
       || hqlQuery.toLowerCase().startsWith(
-        "select mq1.dim1 dim1, mq1.dim11 dim11," + " mq2.msr12 msr12, mq1.msr2 msr2 from "));
+        "select coalesce(mq1.dim1, mq2.dim1) dim1, coalesce(mq1.dim11, mq2.dim11) dim11,"
+        + " mq2.msr12 msr12, mq1.msr2 msr2 from "));
 
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ")
-      && hqlQuery.endsWith("mq2 on mq1.dim1 = mq2.dim1 AND mq1.dim11 = mq2.dim11"));
+    assertTrue(hqlQuery.contains("mq1 full outer join ")
+      && hqlQuery.endsWith("mq2 on mq1.dim1 <=> mq2.dim1 AND mq1.dim11 <=> mq2.dim11"));
 
     // no aggregates in the query
     hqlQuery = rewrite("select dim1, msr11, roundedmsr2 from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -262,10 +287,12 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         getWhereForHourly2days(cubeName, "C1_testfact1_raw_base"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq1.msr11 msr11, mq2.msr2 msr2 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq2.msr11 msr11, mq1.msr2 msr2 from "));
+    assertTrue(hqlQuery.toLowerCase().startsWith(
+      "select coalesce(mq1.dim1, mq2.dim1) dim1, mq1.msr11 msr11, mq2.msr2 msr2 from ")
+      || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1) dim1, mq2.msr11 msr11, mq1.msr2 msr2 from "));
 
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 = mq2.dim1"));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 <=> mq2.dim1"));
 
     // query with aliases passed
     hqlQuery =
@@ -278,9 +305,11 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         " group by basecube.dim1", getWhereForDailyAndHourly2days(cubeName, "C1_testFact1_BASE"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.d1 d1, mq2.expr2 `my msr12`, mq1.m2 m2 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.d1 d1, mq1.expr2 `my msr12`, mq2.m2 m2 from "));
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.d1 = mq2.d1"));
+    assertTrue(hqlQuery.toLowerCase().startsWith(
+      "select coalesce(mq1.d1, mq2.d1) d1, mq2.expr2 `my msr12`, mq1.m2 m2 from ")
+      ||
+      hqlQuery.toLowerCase().startsWith("select coalesce(mq1.d1, mq2.d1) d1, mq1.expr2 `my msr12`, mq2.m2 m2 from "));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.d1 <=> mq2.d1"));
 
     // query with non default aggregate
     hqlQuery = rewrite("select dim1, avg(msr12), avg(msr2) from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -292,10 +321,12 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         " group by basecube.dim1", getWhereForHourly2days(cubeName, "C1_testfact1_raw_base"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq2.msr12 msr12, mq1.msr2 msr2 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.dim1 dim1, mq1.msr12 msr12, mq2.msr2 msr2 from "));
+    assertTrue(hqlQuery.toLowerCase().startsWith(
+      "select coalesce(mq1.dim1, mq2.dim1) dim1, mq2.msr12 msr12, mq1.msr2 msr2 from ")
+      || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim1, mq2.dim1) dim1, mq1.msr12 msr12, mq2.msr2 msr2 from "));
 
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 = mq2.dim1"));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim1 <=> mq2.dim1"));
 
     // query with join
     hqlQuery = rewrite("select testdim2.name, msr12, roundedmsr2 from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -310,9 +341,11 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         getWhereForHourly2days(cubeName, "C1_testfact1_raw_base"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.name name, mq2.msr12 msr12, mq1.msr2 msr2 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.name name, mq1.msr12 msr12, mq2.msr2 msr2 from "));
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.name = mq2.name"));
+    assertTrue(hqlQuery.toLowerCase().startsWith(
+      "select coalesce(mq1.name, mq2.name) name, mq2.msr12 msr12, mq1.msr2 msr2 from ")
+      || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.name, mq2.name) name, mq1.msr12 msr12, mq2.msr2 msr2 from "));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.name <=> mq2.name"));
 
     // query with denorm variable
     hqlQuery = rewrite("select dim2, msr13, roundedmsr2 from basecube" + " where " + TWO_DAYS_RANGE, conf);
@@ -325,9 +358,11 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         " group by basecube.dim2", getWhereForHourly2days(cubeName, "C1_testfact1_raw_base"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.dim2 dim2, mq2.msr13 msr13, mq1.msr2 msr2 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.dim2 dim2, mq1.msr13 msr13, mq2.msr2 msr2 from "));
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim2 = mq2.dim2"));
+    assertTrue(hqlQuery.toLowerCase().startsWith(
+      "select coalesce(mq1.dim2, mq2.dim2) dim2, mq2.msr13 msr13, mq1.msr2 msr2 from ")
+      || hqlQuery.toLowerCase().startsWith(
+        "select coalesce(mq1.dim2, mq2.dim2) dim2, mq1.msr13 msr13, mq2.msr2 msr2 from "));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.dim2 <=> mq2.dim2"));
 
     // query with expression
     hqlQuery =
@@ -347,8 +382,10 @@ public class TestBaseCubeQueries extends TestQueryRewrite {
         getWhereForHourly2days(cubeName, "C1_testfact1_raw_base"));
     TestCubeRewriter.compareContains(expected1, hqlQuery);
     TestCubeRewriter.compareContains(expected2, hqlQuery);
-    Assert.assertTrue(hqlQuery.toLowerCase().startsWith("select mq1.expr1 expr1, mq2.msr2 msr2, mq1.expr3 expr3 from ")
-      || hqlQuery.toLowerCase().startsWith("select mq1.expr1 expr1, mq1.msr2 msr2, mq2.expr3 expr3 from "));
-    Assert.assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.expr1 = mq2.expr1"));
+    assertTrue(hqlQuery.toLowerCase()
+      .startsWith("select coalesce(mq1.expr1, mq2.expr1) expr1, mq2.msr2 msr2, mq1.expr3 expr3 from ")
+      || hqlQuery.toLowerCase()
+        .startsWith("select coalesce(mq1.expr1, mq2.expr1) expr1, mq1.msr2 msr2, mq2.expr3 expr3 from "));
+    assertTrue(hqlQuery.contains("mq1 full outer join ") && hqlQuery.endsWith("mq2 on mq1.expr1 <=> mq2.expr1"));
   }
 }