This is an automated email from the ASF dual-hosted git repository.
soumyakanti3578 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 71ac5c1d2a9 HIVE-29612: LATERAL VIEW OUTER doesn't work with CBO
enabled (#6482)
71ac5c1d2a9 is described below
commit 71ac5c1d2a90b242da6b6230fce68a088a93bb34
Author: Soumyakanti Das <[email protected]>
AuthorDate: Thu May 28 12:43:00 2026 -0700
HIVE-29612: LATERAL VIEW OUTER doesn't work with CBO enabled (#6482)
---
.../reloperators/HiveTableFunctionScan.java | 36 ++++-
.../optimizer/calcite/translator/ASTConverter.java | 15 +-
.../hadoop/hive/ql/parse/CalcitePlanner.java | 12 +-
.../hadoop/hive/ql/parse/SemanticAnalyzer.java | 22 +--
.../hive/ql/parse/relnodegen/LateralViewPlan.java | 14 +-
.../queries/clientpositive/lateral_view_outer.q | 19 +++
.../clientpositive/llap/lateral_view_outer.q.out | 160 +++++++++++++++++++++
7 files changed, 250 insertions(+), 28 deletions(-)
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/HiveTableFunctionScan.java
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/HiveTableFunctionScan.java
index 176d27e07d9..eb148dda25f 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/HiveTableFunctionScan.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/reloperators/HiveTableFunctionScan.java
@@ -25,6 +25,7 @@
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.core.TableFunctionScan;
import org.apache.calcite.rel.metadata.RelColumnMapping;
import org.apache.calcite.rel.type.RelDataType;
@@ -34,6 +35,9 @@
public class HiveTableFunctionScan extends TableFunctionScan implements
HiveRelNode {
+ // Whether this is a LATERAL VIEW OUTER
+ private final boolean outer;
+
/**
* @param cluster
* cluster - Cluster that this relational expression belongs to
@@ -49,28 +53,54 @@ public class HiveTableFunctionScan extends
TableFunctionScan implements HiveRelN
* rowType - Row type produced by function
* @param columnMappings
* columnMappings - Column mappings associated with this function
+ * @param outer
+ * outer - true if this is a LATERAL VIEW OUTER
*/
protected HiveTableFunctionScan(RelOptCluster cluster, RelTraitSet traitSet,
List<RelNode> inputs,
- RexNode rexCall, Type elementType, RelDataType rowType,
Set<RelColumnMapping> columnMappings) {
+ RexNode rexCall, Type elementType, RelDataType rowType,
Set<RelColumnMapping> columnMappings,
+ boolean outer) {
super(cluster, traitSet, inputs, rexCall, elementType, rowType,
columnMappings);
+ this.outer = outer;
}
public HiveTableFunctionScan(RelInput input) {
super(input);
+ this.outer = input.getBoolean("outer", false);
}
public static HiveTableFunctionScan create(RelOptCluster cluster,
RelTraitSet traitSet,
List<RelNode> inputs, RexNode rexCall, Type elementType, RelDataType
rowType,
Set<RelColumnMapping> columnMappings) throws CalciteSemanticException {
return new HiveTableFunctionScan(cluster, traitSet, inputs, rexCall,
elementType, rowType,
- columnMappings);
+ columnMappings, false);
+ }
+
+ public static HiveTableFunctionScan create(RelOptCluster cluster,
RelTraitSet traitSet,
+ List<RelNode> inputs, RexNode rexCall, Type elementType, RelDataType
rowType,
+ Set<RelColumnMapping> columnMappings, boolean outer) throws
CalciteSemanticException {
+ return new HiveTableFunctionScan(cluster, traitSet, inputs, rexCall,
elementType, rowType,
+ columnMappings, outer);
+ }
+
+ /** Returns true if this represents a LATERAL VIEW OUTER. */
+ public boolean isOuter() {
+ return outer;
+ }
+
+ @Override
+ public RelWriter explainTerms(RelWriter pw) {
+ super.explainTerms(pw);
+ if (outer) {
+ pw.item("outer", true);
+ }
+ return pw;
}
@Override
public TableFunctionScan copy(RelTraitSet traitSet, List<RelNode> inputs,
RexNode rexCall,
Type elementType, RelDataType rowType, Set<RelColumnMapping>
columnMappings) {
return new HiveTableFunctionScan(getCluster(), traitSet, inputs, rexCall,
- elementType, rowType, columnMappings);
+ elementType, rowType, columnMappings, outer);
}
/**
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/ASTConverter.java
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/ASTConverter.java
index 695196502ed..f3e47f01064 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/ASTConverter.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/ASTConverter.java
@@ -703,14 +703,21 @@ private static QueryBlockInfo
createASTLateralView(TableFunctionScan tfs, QueryB
sel.add(selexpr.node());
// place the SELECT clause under the LATERAL VIEW clause
- ASTBuilder lateralview = ASTBuilder.construct(HiveParser.TOK_LATERAL_VIEW,
"TOK_LATERAL_VIEW");
- lateralview.add(sel.node());
+ final boolean isOuterLateralView = tfs instanceof HiveTableFunctionScan
htfs && htfs.isOuter();
+ final int lateralViewToken = isOuterLateralView
+ ? HiveParser.TOK_LATERAL_VIEW_OUTER
+ : HiveParser.TOK_LATERAL_VIEW;
+ final String lateralViewText = isOuterLateralView
+ ? "TOK_LATERAL_VIEW_OUTER"
+ : "TOK_LATERAL_VIEW";
+ ASTBuilder lateralView = ASTBuilder.construct(lateralViewToken,
lateralViewText);
+ lateralView.add(sel.node());
// finally, add the LATERAL VIEW clause under the left side source which
is the base table.
- lateralview.add(tableFunctionSource.ast);
+ lateralView.add(tableFunctionSource.ast);
Schema outputSchema = new Schema(tableFunctionSource.schema, new
Schema(alias, lvFields));
- return new QueryBlockInfo(outputSchema, lateralview.node());
+ return new QueryBlockInfo(outputSchema, lateralView.node());
}
private boolean isLateralView(RelNode relNode) {
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
index ffc1673f367..ecc226d42a2 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java
@@ -1036,9 +1036,9 @@ boolean isCBOExecuted() {
}
@Override
- boolean isCBOSupportedLateralView(ASTNode lateralView) {
- // LATERAL VIEW OUTER not supported in CBO
- return lateralView.getToken().getType() !=
HiveParser.TOK_LATERAL_VIEW_OUTER;
+ boolean isCBOSupportedLateralView() {
+ // Both LATERAL VIEW and LATERAL VIEW OUTER are supported in CBO.
+ return !this.conf.getBoolVar(HiveConf.ConfVars.HIVE_CBO_RETPATH_HIVEOP);
}
@Override
@@ -2930,7 +2930,7 @@ private RelNode genJoinLogicalPlan(QB qb, ASTNode
joinParseTree, Map<String, Rel
leftRel = aliasToRel.get(leftTableAlias);
} else if (SemanticAnalyzer.isJoinToken(left)) {
leftRel = genJoinLogicalPlan(qb, left, aliasToRel, outerNameToPosMap,
outerRR);
- } else if (left.getToken().getType() == HiveParser.TOK_LATERAL_VIEW) {
+ } else if (isASTNodeLateralView(left)) {
leftRel = genLateralViewPlans(qb, left, aliasToRel);
} else {
assert (false);
@@ -2944,7 +2944,7 @@ private RelNode genJoinLogicalPlan(QB qb, ASTNode
joinParseTree, Map<String, Rel
|| (right.getToken().getType() == HiveParser.TOK_PTBLFUNCTION)) {
rightTableAlias = getTableAlias(right);
rightRel = aliasToRel.get(rightTableAlias);
- } else if (right.getToken().getType() == HiveParser.TOK_LATERAL_VIEW) {
+ } else if (isASTNodeLateralView(right)) {
rightRel = genLateralViewPlans(qb, right, aliasToRel);
} else {
assert (false);
@@ -3327,7 +3327,7 @@ private RelNode genLateralViewPlans(QB qb, ASTNode
lateralView, Map<String, RelN
// next token is either the table alias name or another lateral view
(which we will call
// recursively)
- RelNode inputRel = next.getToken().getType() ==
HiveParser.TOK_LATERAL_VIEW
+ RelNode inputRel = isASTNodeLateralView(next)
? genLateralViewPlans(qb, next, aliasToRel)
: aliasToRel.get(getTableAlias(next));
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 f8ec9028720..b23871278c5 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
@@ -1684,8 +1684,7 @@ private void processJoin(QB qb, ASTNode join) throws
SemanticException {
"PTF invocation in a Join must have an alias"));
}
- } else if (child.getToken().getType() == HiveParser.TOK_LATERAL_VIEW ||
- child.getToken().getType() == HiveParser.TOK_LATERAL_VIEW_OUTER) {
+ } else if (isASTNodeLateralView(child)) {
// SELECT * FROM src1 LATERAL VIEW udtf() AS myTable JOIN src2 ...
// is not supported. Instead, the lateral view must be in a subquery
// SELECT * FROM (SELECT * FROM src1 LATERAL VIEW udtf() AS myTable) a
@@ -1714,9 +1713,7 @@ private String processLateralView(QB qb, ASTNode
lateralView)
int numChildren = lateralView.getChildCount();
assert (numChildren == 2);
- if (!isCBOSupportedLateralView(lateralView)) {
- queryProperties.setCBOSupportedLateralViews(false);
- }
+ queryProperties.setCBOSupportedLateralViews(isCBOSupportedLateralView());
ASTNode next = (ASTNode) lateralView.getChild(1);
String alias = null;
@@ -1890,8 +1887,7 @@ boolean doPhase1(ASTNode ast, QB qb, Phase1Ctx ctx_1,
PlannerContext plannerCtx,
processTable(qb, frm);
} else if (frm.getToken().getType() == HiveParser.TOK_SUBQUERY) {
processSubQuery(qb, frm);
- } else if (frm.getToken().getType() == HiveParser.TOK_LATERAL_VIEW ||
- frm.getToken().getType() == HiveParser.TOK_LATERAL_VIEW_OUTER) {
+ } else if (isASTNodeLateralView(frm)) {
queryProperties.setHasLateralViews(true);
processLateralView(qb, frm);
} else if (isJoinToken(frm)) {
@@ -11124,7 +11120,7 @@ boolean isCBOExecuted() {
return false;
}
- boolean isCBOSupportedLateralView(ASTNode lateralView) {
+ boolean isCBOSupportedLateralView() {
return false;
}
@@ -15527,4 +15523,14 @@ public void startAnalysis() {
queryState.createHMSCache();
}
}
+
+ /**
+ * Utility method to determine if an AST node represents a lateral view or
lateral view outer.
+ * @param node AST node
+ * @return true if node is of lateral view or lateral view outer; false
otherwise.
+ */
+ public static boolean isASTNodeLateralView(ASTNode node) {
+ return node.getToken().getType() == HiveParser.TOK_LATERAL_VIEW
+ || node.getToken().getType() == HiveParser.TOK_LATERAL_VIEW_OUTER;
+ }
}
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/parse/relnodegen/LateralViewPlan.java
b/ql/src/java/org/apache/hadoop/hive/ql/parse/relnodegen/LateralViewPlan.java
index 1e206405eaa..2c585ce6262 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/parse/relnodegen/LateralViewPlan.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/parse/relnodegen/LateralViewPlan.java
@@ -28,7 +28,6 @@
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.ql.ErrorMsg;
import org.apache.hadoop.hive.ql.exec.ColumnInfo;
-import org.apache.hadoop.hive.ql.exec.FunctionRegistry;
import org.apache.hadoop.hive.ql.lib.Node;
import org.apache.hadoop.hive.ql.optimizer.calcite.TraitsUtil;
import
org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveTableFunctionScan;
@@ -91,14 +90,15 @@ public class LateralViewPlan {
public LateralViewPlan(ASTNode lateralView, RelOptCluster cluster, RelNode
inputRel,
RowResolver inputRR, UnparseTranslator unparseTranslator,
- HiveConf conf, FunctionHelper functionHelper
- ) throws SemanticException {
+ HiveConf conf, FunctionHelper functionHelper) throws SemanticException {
// initialize global variables containing helper information
this.cluster = cluster;
this.unparseTranslator = unparseTranslator;
this.conf = conf;
this.functionHelper = functionHelper;
+ boolean isOuter = lateralView.getToken().getType() ==
HiveParser.TOK_LATERAL_VIEW_OUTER;
+
// AST should have form of LATERAL_VIEW -> SELECT -> SELEXPR -> FUNCTION
-> function info tree
ASTNode selExprAST = (ASTNode) lateralView.getChild(0).getChild(0);
ASTNode functionAST = (ASTNode) selExprAST.getChild(0);
@@ -118,7 +118,7 @@ public LateralViewPlan(ASTNode lateralView, RelOptCluster
cluster, RelNode input
this.lateralViewRel = HiveTableFunctionScan.create(cluster,
TraitsUtil.getDefaultTraitSet(cluster), ImmutableList.of(inputRel),
udtfCall,
- null, retType, createColumnMappings(inputRel));
+ null, retType, createColumnMappings(inputRel), isOuter);
}
public static void validateLateralView(ASTNode lateralView) throws
SemanticException {
@@ -127,9 +127,9 @@ public static void validateLateralView(ASTNode lateralView)
throws SemanticExcep
" children.");
}
ASTNode next = (ASTNode) lateralView.getChild(1);
- if (!TABLE_ALIAS_TOKEN_TYPES.contains(next.getToken().getType()) &&
- HiveParser.TOK_LATERAL_VIEW != next.getToken().getType()) {
- throw new SemanticException(ASTErrorUtils.getMsg(
+ if (!TABLE_ALIAS_TOKEN_TYPES.contains(next.getToken().getType()) &&
+ !SemanticAnalyzer.isASTNodeLateralView(next)) {
+ throw new SemanticException(ASTErrorUtils.getMsg(
ErrorMsg.LATERAL_VIEW_INVALID_CHILD.getMsg(), lateralView));
}
}
diff --git a/ql/src/test/queries/clientpositive/lateral_view_outer.q
b/ql/src/test/queries/clientpositive/lateral_view_outer.q
index ddb41a8fd09..80f92cebee5 100644
--- a/ql/src/test/queries/clientpositive/lateral_view_outer.q
+++ b/ql/src/test/queries/clientpositive/lateral_view_outer.q
@@ -13,4 +13,23 @@ create table array_valued as select key, if (key > 300,
array(value, value), nul
explain
select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10;
+explain ast
select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10;
+explain cbo
+select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10;
+select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10;
+
+-- array_valued already has a nullable array column, which can be used for the
view-based test
+CREATE VIEW array_valued_view AS
+SELECT array_valued.key AS key, a
+FROM array_valued
+LATERAL VIEW OUTER explode(value) lv AS a;
+
+-- CBO plan should contain `outer=[true]` in HiveTableFunctionScan node.
+EXPLAIN CBO
+SELECT key, a FROM array_valued_view limit 10;
+-- Explain plan should contain `outer lateral view: true` in the UDTF Operator
+EXPLAIN
+SELECT key, a FROM array_valued_view limit 10;
+-- Rows with null array value should still appear with a=NULL
+SELECT key, a FROM array_valued_view limit 10;
diff --git a/ql/src/test/results/clientpositive/llap/lateral_view_outer.q.out
b/ql/src/test/results/clientpositive/llap/lateral_view_outer.q.out
index c5959dce36b..a44dddfc09e 100644
--- a/ql/src/test/results/clientpositive/llap/lateral_view_outer.q.out
+++ b/ql/src/test/results/clientpositive/llap/lateral_view_outer.q.out
@@ -187,6 +187,59 @@ STAGE PLANS:
outputColumnNames: _col0, _col1, _col2
ListSink
+PREHOOK: query: explain ast
+select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10
+PREHOOK: type: QUERY
+PREHOOK: Input: default@array_valued
+#### A masked pattern was here ####
+POSTHOOK: query: explain ast
+select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@array_valued
+#### A masked pattern was here ####
+ABSTRACT SYNTAX TREE:
+
+TOK_QUERY
+ TOK_FROM
+ TOK_LATERAL_VIEW_OUTER
+ TOK_SELECT
+ TOK_SELEXPR
+ TOK_FUNCTION
+ explode
+ TOK_TABLE_OR_COL
+ value
+ a
+ TOK_TABALIAS
+ C
+ TOK_TABREF
+ TOK_TABNAME
+ array_valued
+ TOK_INSERT
+ TOK_DESTINATION
+ TOK_DIR
+ TOK_TMP_FILE
+ TOK_SELECT
+ TOK_SELEXPR
+ TOK_ALLCOLREF
+ TOK_LIMIT
+ 10
+
+PREHOOK: query: explain cbo
+select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10
+PREHOOK: type: QUERY
+PREHOOK: Input: default@array_valued
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo
+select * from array_valued LATERAL VIEW OUTER explode(value) C AS a limit 10
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@array_valued
+#### A masked pattern was here ####
+CBO PLAN:
+HiveSortLimit(fetch=[10])
+ HiveProject(array_valued.key=[$0], array_valued.value=[$1], c.a=[$6])
+ HiveTableFunctionScan(invocation=[LATERAL(explode($1), $0, $1, $2, $3, $4,
$5)], rowType=[RecordType(VARCHAR(2147483647) key, VARCHAR(2147483647) ARRAY
value, BIGINT BLOCK__OFFSET__INSIDE__FILE, VARCHAR(2147483647)
INPUT__FILE__NAME, RecordType(BIGINT writeid, INTEGER bucketid, BIGINT rowid)
ROW__ID, BOOLEAN ROW__IS__DELETED, VARCHAR(2147483647) c.a)], outer=[true])
+ HiveTableScan(table=[[default, array_valued]],
table:alias=[array_valued])
+
PREHOOK: query: select * from array_valued LATERAL VIEW OUTER explode(value) C
AS a limit 10
PREHOOK: type: QUERY
PREHOOK: Input: default@array_valued
@@ -205,3 +258,110 @@ POSTHOOK: Input: default@array_valued
409 ["val_409","val_409"] val_409
255 NULL NULL
278 NULL NULL
+PREHOOK: query: CREATE VIEW array_valued_view AS
+SELECT array_valued.key AS key, a
+FROM array_valued
+LATERAL VIEW OUTER explode(value) lv AS a
+PREHOOK: type: CREATEVIEW
+PREHOOK: Input: default@array_valued
+PREHOOK: Output: database:default
+PREHOOK: Output: default@array_valued_view
+POSTHOOK: query: CREATE VIEW array_valued_view AS
+SELECT array_valued.key AS key, a
+FROM array_valued
+LATERAL VIEW OUTER explode(value) lv AS a
+POSTHOOK: type: CREATEVIEW
+POSTHOOK: Input: default@array_valued
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@array_valued_view
+POSTHOOK: Lineage: array_valued_view.a SCRIPT
[(array_valued)array_valued.FieldSchema(name:value, type:array<string>,
comment:null), ]
+POSTHOOK: Lineage: array_valued_view.key SIMPLE
[(array_valued)array_valued.FieldSchema(name:key, type:string, comment:null), ]
+PREHOOK: query: EXPLAIN CBO
+SELECT key, a FROM array_valued_view limit 10
+PREHOOK: type: QUERY
+PREHOOK: Input: default@array_valued
+PREHOOK: Input: default@array_valued_view
+#### A masked pattern was here ####
+POSTHOOK: query: EXPLAIN CBO
+SELECT key, a FROM array_valued_view limit 10
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@array_valued
+POSTHOOK: Input: default@array_valued_view
+#### A masked pattern was here ####
+CBO PLAN:
+HiveSortLimit(fetch=[10])
+ HiveProject(key=[$0], a=[$6])
+ HiveTableFunctionScan(invocation=[LATERAL(explode($1), $0, $1, $2, $3, $4,
$5)], rowType=[RecordType(VARCHAR(2147483647) key, VARCHAR(2147483647) ARRAY
value, BIGINT BLOCK__OFFSET__INSIDE__FILE, VARCHAR(2147483647)
INPUT__FILE__NAME, RecordType(BIGINT writeid, INTEGER bucketid, BIGINT rowid)
ROW__ID, BOOLEAN ROW__IS__DELETED, VARCHAR(2147483647) lv.a)], outer=[true])
+ HiveTableScan(table=[[default, array_valued]],
table:alias=[array_valued])
+
+PREHOOK: query: EXPLAIN
+SELECT key, a FROM array_valued_view limit 10
+PREHOOK: type: QUERY
+PREHOOK: Input: default@array_valued
+PREHOOK: Input: default@array_valued_view
+#### A masked pattern was here ####
+POSTHOOK: query: EXPLAIN
+SELECT key, a FROM array_valued_view limit 10
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@array_valued
+POSTHOOK: Input: default@array_valued_view
+#### A masked pattern was here ####
+STAGE DEPENDENCIES:
+ Stage-0 is a root stage
+
+STAGE PLANS:
+ Stage: Stage-0
+ Fetch Operator
+ limit: 10
+ Processor Tree:
+ TableScan
+ alias: array_valued
+ properties:
+ insideView TRUE
+ Lateral View Forward
+ Select Operator
+ expressions: key (type: string)
+ outputColumnNames: key
+ Lateral View Join Operator
+ outputColumnNames: _col0, _col6
+ Limit
+ Number of rows: 10
+ Select Operator
+ expressions: _col0 (type: string), _col6 (type: string)
+ outputColumnNames: _col0, _col1
+ ListSink
+ Select Operator
+ expressions: value (type: array<string>)
+ outputColumnNames: _col0
+ UDTF Operator
+ function name: explode
+ outer lateral view: true
+ Lateral View Join Operator
+ outputColumnNames: _col0, _col6
+ Limit
+ Number of rows: 10
+ Select Operator
+ expressions: _col0 (type: string), _col6 (type: string)
+ outputColumnNames: _col0, _col1
+ ListSink
+
+PREHOOK: query: SELECT key, a FROM array_valued_view limit 10
+PREHOOK: type: QUERY
+PREHOOK: Input: default@array_valued
+PREHOOK: Input: default@array_valued_view
+#### A masked pattern was here ####
+POSTHOOK: query: SELECT key, a FROM array_valued_view limit 10
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@array_valued
+POSTHOOK: Input: default@array_valued_view
+#### A masked pattern was here ####
+238 NULL
+86 NULL
+311 val_311
+311 val_311
+27 NULL
+165 NULL
+409 val_409
+409 val_409
+255 NULL
+278 NULL