This is an automated email from the ASF dual-hosted git repository.

deniskuzZ 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 89ea0b1b5ed HIVE-29262: [Addendum] Fix VectorPTFGroupBatches partition 
key copy when partition and order columns overlap (#6597)
89ea0b1b5ed is described below

commit 89ea0b1b5edb8528c3be08588017216fbcc27beb
Author: Raghav Aggarwal <[email protected]>
AuthorDate: Sat Jul 11 19:58:36 2026 +0530

    HIVE-29262: [Addendum] Fix VectorPTFGroupBatches partition key copy when 
partition and order columns overlap (#6597)
---
 .../ql/exec/vector/ptf/VectorPTFGroupBatches.java  |  19 +-
 .../hive/ql/exec/vector/ptf/VectorPTFOperator.java |   1 +
 .../hive/ql/optimizer/physical/Vectorizer.java     |  59 ------
 .../exec/vector/ptf/TestVectorPTFGroupBatches.java |   1 +
 .../vector_ptf_spill_partition_order_overlap.q     |  39 ++++
 .../vector_ptf_spill_partition_order_overlap.q.out | 226 +++++++++++++++++++++
 6 files changed, 284 insertions(+), 61 deletions(-)

diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFGroupBatches.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFGroupBatches.java
index f05683eb301..8fee32a569c 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFGroupBatches.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFGroupBatches.java
@@ -26,6 +26,7 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.common.type.HiveIntervalDayTime;
 import org.apache.hadoop.hive.ql.exec.PTFPartition;
@@ -64,6 +65,7 @@ public class VectorPTFGroupBatches extends PTFPartition {
   private int[] bufferedColumnMap;
   private int[] orderColumnMap;
   private int[] keyWithoutOrderColumnMap;
+  private int[] partitionKeyIndices;
 
   private int spillLimitBufferedBatchCount;
   private String spillLocalDirs;
@@ -289,13 +291,21 @@ public VectorPTFGroupBatches(Configuration hconf, int 
vectorizedPTFMaxMemoryBuff
 
   public void init(VectorPTFEvaluatorBase[] evaluators, int[] 
outputProjectionColumnMap,
       int[] bufferedColumnMap, TypeInfo[] bufferedTypeInfos, int[] 
orderColumnMap,
-      int[] keyWithoutOrderColumnMap, VectorizedRowBatch overflowBatch) {
+      int[] keyWithoutOrderColumnMap, int[] partitionColumnMap, 
VectorizedRowBatch overflowBatch) {
     this.evaluators = evaluators;
     this.outputProjectionColumnMap = outputProjectionColumnMap;
     this.bufferedColumnMap = bufferedColumnMap;
     this.orderColumnMap = orderColumnMap;
     this.keyWithoutOrderColumnMap = keyWithoutOrderColumnMap;
 
+    partitionKeyIndices = new int[keyWithoutOrderColumnMap.length];
+    for (int i = 0; i < keyWithoutOrderColumnMap.length; i++) {
+      partitionKeyIndices[i] = ArrayUtils.indexOf(partitionColumnMap, 
keyWithoutOrderColumnMap[i]);
+      Preconditions.checkState(partitionKeyIndices[i] != 
ArrayUtils.INDEX_NOT_FOUND,
+          "Key input column %s not found among partition columns %s",
+          keyWithoutOrderColumnMap[i], Arrays.toString(partitionColumnMap));
+    }
+
     this.overflowBatch = overflowBatch;
     bufferedBatches = new ArrayList<BufferedVectorizedRowBatch>(0);
 
@@ -775,6 +785,11 @@ private void forwardSpilledBatches(VectorPTFOperator 
vecPTFOperator, Object[] pa
     }
   }
 
+  /**
+   * Sets the partition key values as repeating columns in the overflowBatch. 
Key columns are in
+   * output projection order, partitionKey values in PARTITION BY order; 
partitionKeyIndices maps
+   * between the two.
+   */
   private void copyPartitionColumnToOverflow(Object[] partitionKey) {
     // Set partition column in overflowBatch.
     // We can set by ref since our last batch is held by us.
@@ -782,7 +797,7 @@ private void copyPartitionColumnToOverflow(Object[] 
partitionKey) {
     for (int i = 0; i < keyInputColumnCount; i++) {
       final int keyColumnNum = keyWithoutOrderColumnMap[i];
       Preconditions.checkState(overflowBatch.cols[keyColumnNum] != null);
-      setRepeatingColumn(partitionKey[i], overflowBatch, keyColumnNum);
+      setRepeatingColumn(partitionKey[partitionKeyIndices[i]], overflowBatch, 
keyColumnNum);
     }
   }
 
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFOperator.java 
b/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFOperator.java
index 6d03bb5ea5d..5accf6950c3 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFOperator.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFOperator.java
@@ -349,6 +349,7 @@ protected void initializeOp(Configuration hconf) throws 
HiveException {
         bufferedTypeInfos,
         orderColumnMap,
         keyWithoutOrderColumnMap,
+        vectorPTFInfo.getPartitionColumnMap(),
         overflowBatch);
 
     isFirstPartition = true;
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java
index 8e041351ef3..82f81861a4d 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/physical/Vectorizer.java
@@ -40,7 +40,6 @@
 import java.util.TreeSet;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.lang3.StringUtils;
@@ -5077,59 +5076,6 @@ private static void createVectorPTFDesc(Operator<? 
extends OperatorDesc> ptfOp,
         vectorizedPTFMaxMemoryBufferingBatchCount);
   }
 
-  /**
-   * Reorders partitionColumnMap and partitionColumnVectorTypes in-place so 
that projected
-   * partition-only columns come first in SELECT output order. Any partition 
columns not found in
-   * the output are appended at the end in their original plan order.
-   */
-  private static void 
reorderPartitionColumnsToMatchOutputOrder(List<ColumnInfo> outputSignature,
-      int evaluatorCount, int[] outputColumnProjectionMap, int[] 
orderColumnMap,
-      ExprNodeDesc[] partitionExprNodeDescs, int[] partitionColumnMap,
-      Type[] partitionColumnVectorTypes) {
-    final int count = partitionColumnMap.length;
-    final int[] orderedMap = new int[count];
-    final Type[] orderedTypes = new Type[count];
-    final boolean[] placed = new boolean[count];
-
-    int idx = 0;
-    final int outputSize = outputSignature.size();
-
-    for (int outputIdx = evaluatorCount; outputIdx < outputSize && idx < 
count; outputIdx++) {
-      final int outputColumn = outputColumnProjectionMap[outputIdx];
-      final String colName = outputSignature.get(outputIdx).getInternalName();
-      int matchedPartitionIdx = IntStream.range(0, count)
-          .filter(p -> !placed[p])
-          .filter(p -> partitionExprNodeDescs[p] instanceof ExprNodeColumnDesc 
colDesc &&
-              colDesc.getColumn().equals(colName))
-          .findFirst()
-          .orElse(-1);
-      
-      if (matchedPartitionIdx == -1) {
-        matchedPartitionIdx = IntStream.range(0, count)
-            .filter(p -> !placed[p] && partitionColumnMap[p] == outputColumn)
-            .findFirst()
-            .orElse(-1);
-      }
-
-      if (matchedPartitionIdx != -1 && !ArrayUtils.contains(orderColumnMap, 
outputColumn)) {
-        orderedMap[idx] = outputColumn;
-        orderedTypes[idx] = partitionColumnVectorTypes[matchedPartitionIdx];
-        placed[matchedPartitionIdx] = true;
-        idx++;
-      }
-    }
-
-    for (int p = 0; p < count; p++) {
-      if (!placed[p]) {
-        orderedMap[idx] = partitionColumnMap[p];
-        orderedTypes[idx] = partitionColumnVectorTypes[p];
-        idx++;
-      }
-    }
-    System.arraycopy(orderedMap, 0, partitionColumnMap, 0, count);
-    System.arraycopy(orderedTypes, 0, partitionColumnVectorTypes, 0, count);
-  }
-
   private static void determineKeyAndNonKeyInputColumnMap(int[] 
outputColumnProjectionMap,
       boolean isPartitionOrderBy, int[] orderColumnMap, int[] 
partitionColumnMap,
       int evaluatorCount, ArrayList<Integer> keyInputColumns,
@@ -5244,11 +5190,6 @@ private static VectorPTFInfo 
createVectorPTFInfo(Operator<? extends OperatorDesc
     int[] keyInputColumnMap = 
ArrayUtils.toPrimitive(keyInputColumns.toArray(new Integer[0]));
     int[] nonKeyInputColumnMap = 
ArrayUtils.toPrimitive(nonKeyInputColumns.toArray(new Integer[0]));
 
-    if (isPartitionOrderBy && partitionKeyCount > 1) {
-      reorderPartitionColumnsToMatchOutputOrder(outputSignature, 
evaluatorCount, outputColumnProjectionMap,
-          orderColumnMap, partitionExprNodeDescs, partitionColumnMap, 
partitionColumnVectorTypes);
-    }
-
     VectorExpression[][] evaluatorInputExpressions = new 
VectorExpression[evaluatorCount][];
     Type[][] evaluatorInputColumnVectorTypes = new Type[evaluatorCount][];
     for (int i = 0; i < evaluatorCount; i++) {
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/ptf/TestVectorPTFGroupBatches.java
 
b/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/ptf/TestVectorPTFGroupBatches.java
index 30395858177..c74d407c146 100644
--- 
a/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/ptf/TestVectorPTFGroupBatches.java
+++ 
b/ql/src/test/org/apache/hadoop/hive/ql/exec/vector/ptf/TestVectorPTFGroupBatches.java
@@ -588,6 +588,7 @@ private void init(VectorPTFGroupBatches groupBatches) 
throws HiveException {
         /* bufferedTypeInfos */ new TypeInfo[] { getTypeInfo("int"), 
getTypeInfo("string") },
         /* orderColumnMap */ new int[] { 1 }, // p_date
         /* keyWithoutOrderColumnMap */ new int[] { 0 }, // p_mfgr
+        /* partitionColumnMap */ new int[] { 0 },
         getFakeOperator().setupOverflowBatch(3, new String[] { "bigint", 
"bigint" },
             outputProjectionColumnMap, outputTypeInfos));
   }
diff --git 
a/ql/src/test/queries/clientpositive/vector_ptf_spill_partition_order_overlap.q 
b/ql/src/test/queries/clientpositive/vector_ptf_spill_partition_order_overlap.q
new file mode 100644
index 00000000000..05de81530ea
--- /dev/null
+++ 
b/ql/src/test/queries/clientpositive/vector_ptf_spill_partition_order_overlap.q
@@ -0,0 +1,39 @@
+SET hive.vectorized.execution.enabled=true;
+SET hive.vectorized.execution.reduce.enabled=true;
+SET hive.vectorized.execution.ptf.enabled=true;
+SET hive.vectorized.testing.reducer.batch.size=2;
+SET hive.vectorized.ptf.max.memory.buffering.batch.count=1;
+
+SET hive.fetch.task.conversion=none;
+
+CREATE TABLE t1 (
+  dept STRING,
+  region BIGINT,
+  emp_id BIGINT,
+  salary DOUBLE
+) STORED AS ORC;
+
+INSERT INTO t1 values
+  ('engineering', 10, 1, 50000.0),
+  ('engineering', 10, 2, 55000.0),
+  ('engineering', 10, 3, 60000.0),
+  ('engineering', 10, 4, 45000.0),
+  ('engineering', 10, 5, 70000.0);
+
+EXPLAIN VECTORIZATION DETAIL
+SELECT dept, region, emp_id,
+  SUM(salary) OVER (
+    PARTITION BY dept, region
+    ORDER BY dept
+    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  ) AS total
+FROM t1;
+
+SELECT dept, region, emp_id,
+  SUM(salary) OVER (
+    PARTITION BY dept, region
+    ORDER BY dept
+    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  ) AS total
+FROM t1
+order by emp_id;
diff --git 
a/ql/src/test/results/clientpositive/llap/vector_ptf_spill_partition_order_overlap.q.out
 
b/ql/src/test/results/clientpositive/llap/vector_ptf_spill_partition_order_overlap.q.out
new file mode 100644
index 00000000000..c785412cc56
--- /dev/null
+++ 
b/ql/src/test/results/clientpositive/llap/vector_ptf_spill_partition_order_overlap.q.out
@@ -0,0 +1,226 @@
+PREHOOK: query: CREATE TABLE t1 (
+  dept STRING,
+  region BIGINT,
+  emp_id BIGINT,
+  salary DOUBLE
+) STORED AS ORC
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t1
+POSTHOOK: query: CREATE TABLE t1 (
+  dept STRING,
+  region BIGINT,
+  emp_id BIGINT,
+  salary DOUBLE
+) STORED AS ORC
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t1
+PREHOOK: query: INSERT INTO t1 values
+  ('engineering', 10, 1, 50000.0),
+  ('engineering', 10, 2, 55000.0),
+  ('engineering', 10, 3, 60000.0),
+  ('engineering', 10, 4, 45000.0),
+  ('engineering', 10, 5, 70000.0)
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t1
+POSTHOOK: query: INSERT INTO t1 values
+  ('engineering', 10, 1, 50000.0),
+  ('engineering', 10, 2, 55000.0),
+  ('engineering', 10, 3, 60000.0),
+  ('engineering', 10, 4, 45000.0),
+  ('engineering', 10, 5, 70000.0)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t1
+POSTHOOK: Lineage: t1.dept SCRIPT []
+POSTHOOK: Lineage: t1.emp_id SCRIPT []
+POSTHOOK: Lineage: t1.region SCRIPT []
+POSTHOOK: Lineage: t1.salary SCRIPT []
+PREHOOK: query: EXPLAIN VECTORIZATION DETAIL
+SELECT dept, region, emp_id,
+  SUM(salary) OVER (
+    PARTITION BY dept, region
+    ORDER BY dept
+    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  ) AS total
+FROM t1
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t1
+#### A masked pattern was here ####
+POSTHOOK: query: EXPLAIN VECTORIZATION DETAIL
+SELECT dept, region, emp_id,
+  SUM(salary) OVER (
+    PARTITION BY dept, region
+    ORDER BY dept
+    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  ) AS total
+FROM t1
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t1
+#### A masked pattern was here ####
+PLAN VECTORIZATION:
+  enabled: true
+  enabledConditionsMet: [hive.vectorized.execution.enabled IS true]
+
+STAGE DEPENDENCIES:
+  Stage-1 is a root stage
+  Stage-0 depends on stages: Stage-1
+
+STAGE PLANS:
+  Stage: Stage-1
+    Tez
+#### A masked pattern was here ####
+      Edges:
+        Reducer 2 <- Map 1 (SIMPLE_EDGE)
+#### A masked pattern was here ####
+      Vertices:
+        Map 1 
+            Map Operator Tree:
+                TableScan
+                  alias: t1
+                  Statistics: Num rows: 5 Data size: 595 Basic stats: COMPLETE 
Column stats: COMPLETE
+                  TableScan Vectorization:
+                      native: true
+                      vectorizationSchemaColumns: [0:dept:string, 
1:region:bigint, 2:emp_id:bigint, 3:salary:double, 
4:ROW__ID:struct<writeid:bigint,bucketid:int,rowid:bigint>, 
5:ROW__IS__DELETED:boolean]
+                  Reduce Output Operator
+                    key expressions: dept (type: string), region (type: bigint)
+                    null sort order: za
+                    sort order: ++
+                    Map-reduce partition columns: dept (type: string), region 
(type: bigint)
+                    Reduce Sink Vectorization:
+                        className: VectorReduceSinkMultiKeyOperator
+                        keyColumns: 0:string, 1:bigint
+                        native: true
+                        nativeConditionsMet: 
hive.vectorized.execution.reducesink.new.enabled IS true, hive.execution.engine 
tez IN [tez] IS true, No PTF TopN IS true, No DISTINCT columns IS true, 
BinarySortableSerDe for keys IS true, LazyBinarySerDe for values IS true
+                        valueColumns: 2:bigint, 3:double
+                    Statistics: Num rows: 5 Data size: 595 Basic stats: 
COMPLETE Column stats: COMPLETE
+                    value expressions: emp_id (type: bigint), salary (type: 
double)
+            Execution mode: vectorized, llap
+            LLAP IO: all inputs
+            Map Vectorization:
+                enabled: true
+                enabledConditionsMet: 
hive.vectorized.use.vectorized.input.format IS true
+                inputFormatFeatureSupport: [DECIMAL_64]
+                featureSupportInUse: [DECIMAL_64]
+                inputFileFormats: 
org.apache.hadoop.hive.ql.io.orc.OrcInputFormat
+                allNative: true
+                usesVectorUDFAdaptor: false
+                vectorized: true
+                rowBatchContext:
+                    dataColumnCount: 4
+                    includeColumns: [0, 1, 2, 3]
+                    dataColumns: dept:string, region:bigint, emp_id:bigint, 
salary:double
+                    partitionColumnCount: 0
+                    scratchColumnTypeNames: []
+        Reducer 2 
+            Execution mode: vectorized, llap
+            Reduce Vectorization:
+                enabled: true
+                enableConditionsMet: hive.vectorized.execution.reduce.enabled 
IS true, hive.execution.engine tez IN [tez] IS true
+                reduceColumnNullOrder: za
+                reduceColumnSortOrder: ++
+                allNative: false
+                usesVectorUDFAdaptor: false
+                vectorized: true
+                rowBatchContext:
+                    dataColumnCount: 4
+                    dataColumns: KEY.reducesinkkey0:string, 
KEY.reducesinkkey1:bigint, VALUE._col0:bigint, VALUE._col1:double
+                    partitionColumnCount: 0
+                    scratchColumnTypeNames: [double]
+            Reduce Operator Tree:
+              Select Operator
+                expressions: KEY.reducesinkkey0 (type: string), 
KEY.reducesinkkey1 (type: bigint), VALUE._col0 (type: bigint), VALUE._col1 
(type: double)
+                outputColumnNames: _col0, _col1, _col2, _col3
+                Select Vectorization:
+                    className: VectorSelectOperator
+                    native: true
+                    projectedOutputColumnNums: [0, 1, 2, 3]
+                Statistics: Num rows: 5 Data size: 595 Basic stats: COMPLETE 
Column stats: COMPLETE
+                PTF Operator
+                  Function definitions:
+                      Input definition
+                        input alias: ptf_0
+                        output shape: _col0: string, _col1: bigint, _col2: 
bigint, _col3: double
+                        type: WINDOWING
+                      Windowing table definition
+                        input alias: ptf_1
+                        name: windowingtablefunction
+                        order by: _col0 ASC NULLS LAST
+                        partition by: _col0, _col1
+                        raw input shape:
+                        window functions:
+                            window function definition
+                              alias: sum_window_0
+                              arguments: _col3
+                              name: sum
+                              window function: GenericUDAFSumDouble
+                              window frame: ROWS PRECEDING(MAX)~FOLLOWING(MAX)
+                  PTF Vectorization:
+                      allEvaluatorsAreStreaming: false
+                      className: VectorPTFOperator
+                      evaluatorClasses: [VectorPTFEvaluatorDoubleSum]
+                      functionInputExpressions: [col 3:double]
+                      functionNames: [sum]
+                      keyInputColumns: [0, 1]
+                      native: true
+                      nonKeyInputColumns: [2, 3]
+                      orderExpressions: [col 0:string]
+                      outputColumns: [4, 0, 1, 2, 3]
+                      outputTypes: [double, string, bigint, bigint, double]
+                      partitionExpressions: [col 0:string, col 1:bigint]
+                      streamingColumns: []
+                  Statistics: Num rows: 5 Data size: 595 Basic stats: COMPLETE 
Column stats: COMPLETE
+                  Select Operator
+                    expressions: _col0 (type: string), _col1 (type: bigint), 
_col2 (type: bigint), sum_window_0 (type: double)
+                    outputColumnNames: _col0, _col1, _col2, _col3
+                    Select Vectorization:
+                        className: VectorSelectOperator
+                        native: true
+                        projectedOutputColumnNums: [0, 1, 2, 4]
+                    Statistics: Num rows: 5 Data size: 595 Basic stats: 
COMPLETE Column stats: COMPLETE
+                    File Output Operator
+                      compressed: false
+                      File Sink Vectorization:
+                          className: VectorFileSinkOperator
+                          native: false
+                      Statistics: Num rows: 5 Data size: 595 Basic stats: 
COMPLETE Column stats: COMPLETE
+                      table:
+                          input format: 
org.apache.hadoop.mapred.SequenceFileInputFormat
+                          output format: 
org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat
+                          serde: 
org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
+
+  Stage: Stage-0
+    Fetch Operator
+      limit: -1
+      Processor Tree:
+        ListSink
+
+PREHOOK: query: SELECT dept, region, emp_id,
+  SUM(salary) OVER (
+    PARTITION BY dept, region
+    ORDER BY dept
+    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  ) AS total
+FROM t1
+order by emp_id
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t1
+#### A masked pattern was here ####
+POSTHOOK: query: SELECT dept, region, emp_id,
+  SUM(salary) OVER (
+    PARTITION BY dept, region
+    ORDER BY dept
+    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+  ) AS total
+FROM t1
+order by emp_id
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t1
+#### A masked pattern was here ####
+engineering    10      1       280000.0
+engineering    10      2       280000.0
+engineering    10      3       280000.0
+engineering    10      4       280000.0
+engineering    10      5       280000.0

Reply via email to