diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java index 6249475beb94fd9c854d9787cb5d315877d99d34..d1e13a2b3580c884d05301cb620b69e823f48f97 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -2005,6 +2005,10 @@ private void getMetaData(QB qb, ReadEntity parentInput) replaceViewReferenceWithDefinition(qb, tab, tabName, alias); // This is the last time we'll see the Table objects for views, so add it to the inputs // now. isInsideView will tell if this view is embedded in another view. + // If the view is Inside another view, it should have at least one parent + if (qb.isInsideView() && parentInput == null) { + parentInput = PlanUtils.getParentViewInfo(getAliasId(alias, qb), viewAliasToInput); + } ReadEntity viewInput = new ReadEntity(tab, parentInput, !qb.isInsideView()); viewInput = PlanUtils.addInput(inputs, viewInput); aliasToViewInfo.put(alias, new ObjectPair(fullViewName, viewInput)); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java b/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java index b2c586507483eb5588e07a9ceba3caf395b4d607..05d2c8138a0c019d4b4fd748cebba9512118b07b 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java @@ -1127,7 +1127,8 @@ public static ReadEntity getParentViewInfo(String alias_id, // For eg: for a query like 'select * from V3', where V3 -> V2, V2 -> V1, V1 -> T // -> implies depends on. // T's parent would be V1 - for (int pos = 0; pos < aliases.length; pos++) { + // do not check last alias in the array for parent can not be itself. + for (int pos = 0; pos < aliases.length -1; pos++) { currentAlias = currentAlias == null ? aliases[pos] : currentAlias + ":" + aliases[pos]; currentAlias = currentAlias.replace(SemanticAnalyzer.SUBQUERY_TAG_1, "") diff --git a/ql/src/test/org/apache/hadoop/hive/ql/plan/TestViewEntity.java b/ql/src/test/org/apache/hadoop/hive/ql/plan/TestViewEntity.java index fa01416e5d811e26a866e18c0c45d77a7acbfd60..4cc9d7293ce71935fdfe92e2c1e60dde1a57efc2 100644 --- a/ql/src/test/org/apache/hadoop/hive/ql/plan/TestViewEntity.java +++ b/ql/src/test/org/apache/hadoop/hive/ql/plan/TestViewEntity.java @@ -168,8 +168,45 @@ public void testSubQueryInSubView() throws Exception { // table1 and view1 as second read entity assertEquals("default@" + view1, CheckInputReadEntity.readEntities[1].getName()); assertFalse("Table is not direct input", CheckInputReadEntity.readEntities[1].isDirect()); + Set parents = CheckInputReadEntity.readEntities[1].getParents(); + assertTrue("Table does not have parent", parents != null && parents.size() > 0); assertEquals("default@" + tab1, CheckInputReadEntity.readEntities[2].getName()); assertFalse("Table is not direct input", CheckInputReadEntity.readEntities[2].isDirect()); } + + /** + * Verify that the the query with the subquery inside a view will have the correct + * direct and indirect inputs. + * @throws Exception + */ + @Test + public void testUnionAllInSubView() throws Exception { + String prefix = "tvunionallinsubview" + NAME_PREFIX; + final String tab1 = prefix + "t"; + final String view1 = prefix + "v"; + final String view2 = prefix + "v2"; + + int ret = driver.run("create table " + tab1 + "(id int)").getResponseCode(); + assertEquals("Checking command success", 0, ret); + ret = driver.run("create view " + view1 + " as select * from " + tab1).getResponseCode(); + assertEquals("Checking command success", 0, ret); + + ret = driver.run("create view " + view2 + " as select * from (select * from " + view1 + " union all select * from " + view1 + ") x").getResponseCode(); + assertEquals("Checking command success", 0, ret); + + driver.compile("select * from " + view2); + // view entity + assertEquals("default@" + view2, CheckInputReadEntity.readEntities[0].getName()); + + // table1 and view1 as second read entity + assertEquals("default@" + view1, CheckInputReadEntity.readEntities[1].getName()); + assertFalse("Table is not direct input", CheckInputReadEntity.readEntities[1].isDirect()); + Set parents = CheckInputReadEntity.readEntities[1].getParents(); + assertTrue("Table does not have parent", parents != null && parents.size() > 0); + assertEquals("default@" + tab1, CheckInputReadEntity.readEntities[2].getName()); + assertFalse("Table is not direct input", CheckInputReadEntity.readEntities[2].isDirect()); + + } + }