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

kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new 969dd9b4f45 [feat](Nereids) Support tablesample syntax (#23717) 
(#25135)
969dd9b4f45 is described below

commit 969dd9b4f451acbc0b5d7ccff477913eab44b3bc
Author: AKIRA <[email protected]>
AuthorDate: Thu Oct 12 00:05:30 2023 +0900

    [feat](Nereids) Support tablesample syntax (#23717) (#25135)
    
    Add table sample support like such SQL:
    
    ```sql
    select * from test_table_sample_tbl tablesample(4 rows);
    select * from test_table_sample_tbl t tablesample(20 percent);
    select * from test_table_sample_tbl t tablesample(20 percent) repeatable 2;
    ```
    
    This function has already been implemented in legacy planner, more detailed 
description could be found here: https://github.com/apache/doris/pull/10170
---
 .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 11 +++-
 .../doris/nereids/analyzer/UnboundRelation.java    | 28 +++++++---
 .../glue/translator/PhysicalPlanTranslator.java    |  6 +++
 .../doris/nereids/parser/LogicalPlanBuilder.java   | 23 +++++++-
 .../doris/nereids/rules/analysis/BindRelation.java |  6 ++-
 .../LogicalOlapScanToPhysicalOlapScan.java         |  3 +-
 .../apache/doris/nereids/trees/TableSample.java    | 61 ++++++++++++++++++++++
 .../trees/copier/LogicalPlanDeepCopier.java        |  4 +-
 .../trees/plans/logical/LogicalOlapScan.java       | 53 ++++++++++++-------
 .../trees/plans/physical/PhysicalOlapScan.java     | 21 +++++---
 .../translator/PhysicalPlanTranslatorTest.java     |  2 +-
 .../postprocess/MergeProjectPostProcessTest.java   |  2 +-
 .../PushdownFilterThroughProjectTest.java          |  3 +-
 .../doris/nereids/trees/plans/PlanEqualsTest.java  |  9 ++--
 .../apache/doris/nereids/util/PlanConstructor.java |  3 +-
 .../suites/nereids_p0/tablesample.groovy           | 45 ++++++++++++++++
 16 files changed, 235 insertions(+), 45 deletions(-)

diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index bb2188e6fa6..6b1f5f742e3 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -259,7 +259,7 @@ identifierSeq
     ;
 
 relationPrimary
-    : multipartIdentifier specifiedPartition? tableAlias relationHint? 
lateralView*           #tableName
+    : multipartIdentifier specifiedPartition? tableAlias sample? relationHint? 
lateralView*           #tableName
     | LEFT_PAREN query RIGHT_PAREN tableAlias lateralView*                     
               #aliasedQuery
     | tvfName=identifier LEFT_PAREN
       (properties+=tvfProperty (COMMA properties+=tvfProperty)*)?
@@ -494,6 +494,15 @@ primitiveColType:
     | type=ALL
     ;
 
+sample
+    : TABLESAMPLE LEFT_PAREN sampleMethod? RIGHT_PAREN (REPEATABLE 
seed=INTEGER_VALUE)?
+    ;
+
+sampleMethod
+    : percentage=INTEGER_VALUE PERCENT                              
#sampleByPercentile
+    | INTEGER_VALUE ROWS                                            
#sampleByRows
+    ;
+
 // this rule is used for explicitly capturing wrong identifiers such as 
test-table, which should actually be `test-table`
 // replace identifier with errorCapturingIdentifier where the immediate follow 
symbol is not an expression, otherwise
 // valid expressions such as "a-b" can be recognized as an identifier
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java
index 6d625f7068e..30485fe66f8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java
@@ -21,6 +21,7 @@ import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.LogicalProperties;
 import org.apache.doris.nereids.properties.UnboundLogicalProperties;
+import org.apache.doris.nereids.trees.TableSample;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.plans.Plan;
@@ -48,28 +49,36 @@ public class UnboundRelation extends LogicalRelation 
implements Unbound {
     private final List<String> partNames;
     private final boolean isTempPart;
     private final List<String> hints;
+    private final Optional<TableSample> tableSample;
 
     public UnboundRelation(RelationId id, List<String> nameParts) {
-        this(id, nameParts, Optional.empty(), Optional.empty(), 
ImmutableList.of(), false, ImmutableList.of());
+        this(id, nameParts, Optional.empty(), Optional.empty(), 
ImmutableList.of(), false,
+                ImmutableList.of(), Optional.empty());
     }
 
     public UnboundRelation(RelationId id, List<String> nameParts, List<String> 
partNames, boolean isTempPart) {
-        this(id, nameParts, Optional.empty(), Optional.empty(), partNames, 
isTempPart, ImmutableList.of());
+        this(id, nameParts, Optional.empty(), Optional.empty(), partNames, 
isTempPart,
+                ImmutableList.of(), Optional.empty());
     }
 
     public UnboundRelation(RelationId id, List<String> nameParts, List<String> 
partNames, boolean isTempPart,
-            List<String> hints) {
-        this(id, nameParts, Optional.empty(), Optional.empty(), partNames, 
isTempPart, hints);
+            List<String> hints, Optional<TableSample> tableSample) {
+        this(id, nameParts, Optional.empty(), Optional.empty(),
+                partNames, isTempPart, hints, tableSample);
     }
 
+    /**
+     * Constructor.
+     */
     public UnboundRelation(RelationId id, List<String> nameParts, 
Optional<GroupExpression> groupExpression,
             Optional<LogicalProperties> logicalProperties, List<String> 
partNames, boolean isTempPart,
-            List<String> hints) {
+            List<String> hints, Optional<TableSample> tableSample) {
         super(id, PlanType.LOGICAL_UNBOUND_RELATION, groupExpression, 
logicalProperties);
         this.nameParts = 
ImmutableList.copyOf(Objects.requireNonNull(nameParts, "nameParts should not 
null"));
         this.partNames = 
ImmutableList.copyOf(Objects.requireNonNull(partNames, "partNames should not 
null"));
         this.isTempPart = isTempPart;
         this.hints = ImmutableList.copyOf(Objects.requireNonNull(hints, "hints 
should not be null."));
+        this.tableSample = tableSample;
     }
 
     public List<String> getNameParts() {
@@ -90,14 +99,15 @@ public class UnboundRelation extends LogicalRelation 
implements Unbound {
     public Plan withGroupExpression(Optional<GroupExpression> groupExpression) 
{
         return new UnboundRelation(relationId, nameParts,
                 groupExpression, Optional.of(getLogicalProperties()),
-                partNames, isTempPart, hints);
+                partNames, isTempPart, hints, tableSample);
+
     }
 
     @Override
     public Plan withGroupExprLogicalPropChildren(Optional<GroupExpression> 
groupExpression,
             Optional<LogicalProperties> logicalProperties, List<Plan> 
children) {
         return new UnboundRelation(relationId, nameParts, groupExpression, 
logicalProperties, partNames,
-                isTempPart, hints);
+                isTempPart, hints, tableSample);
     }
 
     @Override
@@ -139,4 +149,8 @@ public class UnboundRelation extends LogicalRelation 
implements Unbound {
     public List<String> getHints() {
         return hints;
     }
+
+    public Optional<TableSample> getTableSample() {
+        return tableSample;
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java
index 12f4a5a8bd7..049619eb209 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java
@@ -36,6 +36,7 @@ import org.apache.doris.analysis.SlotRef;
 import org.apache.doris.analysis.SortInfo;
 import org.apache.doris.analysis.TableName;
 import org.apache.doris.analysis.TableRef;
+import org.apache.doris.analysis.TableSample;
 import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.analysis.TupleId;
 import org.apache.doris.catalog.Column;
@@ -604,6 +605,11 @@ public class PhysicalPlanTranslator extends 
DefaultPlanVisitor<PlanFragment, Pla
         tupleDescriptor.setRef(tableRef);
         
olapScanNode.setSelectedPartitionIds(olapScan.getSelectedPartitionIds());
         olapScanNode.setSampleTabletIds(olapScan.getSelectedTabletIds());
+        if (olapScan.getTableSample().isPresent()) {
+            olapScanNode.setTableSample(new 
TableSample(olapScan.getTableSample().get().isPercent,
+                    olapScan.getTableSample().get().sampleValue, 
olapScan.getTableSample().get().seek));
+            olapScanNode.computeSampleTabletIds();
+        }
 
         // TODO:  remove this switch?
         switch (olapScan.getTable().getKeysType()) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index 0fe54f9069b..f6e0cd117d2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -83,6 +83,9 @@ import 
org.apache.doris.nereids.DorisParser.QueryOrganizationContext;
 import org.apache.doris.nereids.DorisParser.QueryTermContext;
 import org.apache.doris.nereids.DorisParser.RegularQuerySpecificationContext;
 import org.apache.doris.nereids.DorisParser.RelationContext;
+import org.apache.doris.nereids.DorisParser.SampleByPercentileContext;
+import org.apache.doris.nereids.DorisParser.SampleByRowsContext;
+import org.apache.doris.nereids.DorisParser.SampleContext;
 import org.apache.doris.nereids.DorisParser.SelectClauseContext;
 import org.apache.doris.nereids.DorisParser.SelectColumnClauseContext;
 import org.apache.doris.nereids.DorisParser.SelectHintContext;
@@ -129,6 +132,7 @@ import 
org.apache.doris.nereids.analyzer.UnboundVariable.VariableType;
 import org.apache.doris.nereids.exceptions.ParseException;
 import org.apache.doris.nereids.properties.OrderKey;
 import org.apache.doris.nereids.properties.SelectHint;
+import org.apache.doris.nereids.trees.TableSample;
 import org.apache.doris.nereids.trees.expressions.Add;
 import org.apache.doris.nereids.trees.expressions.And;
 import org.apache.doris.nereids.trees.expressions.BitAnd;
@@ -632,9 +636,11 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
             relationHints = ImmutableList.of();
         }
 
+        TableSample tableSample = ctx.sample() == null ? null : (TableSample) 
visit(ctx.sample());
         LogicalPlan checkedRelation = withCheckPolicy(
                 new UnboundRelation(StatementScopeIdGenerator.newRelationId(),
-                        tableId, partitionNames, isTempPart, relationHints));
+                        tableId, partitionNames, isTempPart, relationHints,
+                        Optional.ofNullable(tableSample)));
         LogicalPlan plan = withTableAlias(checkedRelation, ctx.tableAlias());
         for (LateralViewContext lateralViewContext : ctx.lateralView()) {
             plan = withGenerate(plan, lateralViewContext);
@@ -2016,4 +2022,19 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
         }
         return context.getText();
     }
+
+    @Override
+    public Object visitSample(SampleContext ctx) {
+        long seek = ctx.seed == null ? -1L : 
Long.parseLong(ctx.seed.getText());
+        DorisParser.SampleMethodContext sampleContext = ctx.sampleMethod();
+        if (sampleContext instanceof SampleByPercentileContext) {
+            SampleByPercentileContext sampleByPercentileContext = 
(SampleByPercentileContext) sampleContext;
+            long percent = 
Long.parseLong(sampleByPercentileContext.INTEGER_VALUE().getText());
+            return new TableSample(percent, true, seek);
+        }
+        SampleByRowsContext sampleByRowsContext = (SampleByRowsContext) 
sampleContext;
+        long rows = Long.parseLong(sampleByRowsContext.ROWS().getText());
+        return new TableSample(rows, false, seek);
+    }
+
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
index 054c882b158..cffe32df5b0 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
@@ -170,10 +170,12 @@ public class BindRelation extends OneAnalysisRuleFactory {
         List<Long> partIds = getPartitionIds(table, unboundRelation);
         if (!CollectionUtils.isEmpty(partIds)) {
             scan = new LogicalOlapScan(unboundRelation.getRelationId(),
-                    (OlapTable) table, 
ImmutableList.of(tableQualifier.get(1)), partIds, unboundRelation.getHints());
+                    (OlapTable) table, 
ImmutableList.of(tableQualifier.get(1)), partIds,
+                    unboundRelation.getHints(), 
unboundRelation.getTableSample());
         } else {
             scan = new LogicalOlapScan(unboundRelation.getRelationId(),
-                    (OlapTable) table, 
ImmutableList.of(tableQualifier.get(1)), unboundRelation.getHints());
+                    (OlapTable) table, 
ImmutableList.of(tableQualifier.get(1)), unboundRelation.getHints(),
+                    unboundRelation.getTableSample());
         }
         if (!Util.showHiddenColumns() && scan.getTable().hasDeleteSign()
                 && !ConnectContext.get().getSessionVariable()
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
index b578247d06c..6bcf22a9adc 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
@@ -60,7 +60,8 @@ public class LogicalOlapScanToPhysicalOlapScan extends 
OneImplementationRuleFact
                         olapScan.getPreAggStatus(),
                         
olapScan.getOutputByIndex(olapScan.getTable().getBaseIndexId()),
                         Optional.empty(),
-                        olapScan.getLogicalProperties())
+                        olapScan.getLogicalProperties(),
+                        olapScan.getTableSample())
         ).toRule(RuleType.LOGICAL_OLAP_SCAN_TO_PHYSICAL_OLAP_SCAN_RULE);
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TableSample.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TableSample.java
new file mode 100644
index 00000000000..da300cd442d
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TableSample.java
@@ -0,0 +1,61 @@
+// 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.doris.nereids.trees;
+
+import java.util.Objects;
+
+/**
+ * To represent following stmt:
+ *      TABLESAMPLE (10 PERCENT)
+ *      TABLESAMPLE (100 ROWS)
+ *      TABLESAMPLE (10 PERCENT) REPEATABLE 2
+ *      TABLESAMPLE (100 ROWS) REPEATABLE 2
+ */
+public class TableSample {
+
+    public final long sampleValue;
+
+    public final boolean isPercent;
+
+    public final long seek;
+
+    public TableSample(long sampleValue, boolean isPercent, long seek) {
+        this.sampleValue = sampleValue;
+        this.isPercent = isPercent;
+        this.seek = seek;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof TableSample)) {
+            return false;
+        }
+        TableSample tableSample = (TableSample) obj;
+        return this.sampleValue == tableSample.sampleValue
+                && this.isPercent == tableSample.isPercent
+                && this.seek == tableSample.seek;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(sampleValue, isPercent, seek);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java
index 2e52c582d91..12455b66f2e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java
@@ -160,11 +160,11 @@ public class LogicalPlanDeepCopier extends 
DefaultPlanRewriter<DeepCopierContext
         LogicalOlapScan newOlapScan;
         if (olapScan.getManuallySpecifiedPartitions().isEmpty()) {
             newOlapScan = new 
LogicalOlapScan(StatementScopeIdGenerator.newRelationId(),
-                    olapScan.getTable(), olapScan.getQualifier(), 
olapScan.getHints());
+                    olapScan.getTable(), olapScan.getQualifier(), 
olapScan.getHints(), olapScan.getTableSample());
         } else {
             newOlapScan = new 
LogicalOlapScan(StatementScopeIdGenerator.newRelationId(),
                     olapScan.getTable(), olapScan.getQualifier(),
-                    olapScan.getManuallySpecifiedPartitions(), 
olapScan.getHints());
+                    olapScan.getManuallySpecifiedPartitions(), 
olapScan.getHints(), olapScan.getTableSample());
         }
         newOlapScan.getOutput();
         context.putRelation(olapScan.getRelationId(), newOlapScan);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapScan.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapScan.java
index 0759162116f..71b68fdd7fa 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapScan.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapScan.java
@@ -23,6 +23,7 @@ import org.apache.doris.catalog.Table;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.LogicalProperties;
 import 
org.apache.doris.nereids.rules.rewrite.mv.AbstractSelectMaterializedIndexRule;
+import org.apache.doris.nereids.trees.TableSample;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.expressions.SlotReference;
 import org.apache.doris.nereids.trees.plans.Plan;
@@ -103,6 +104,8 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
     ///////////////////////////////////////////////////////////////////////////
     private final List<String> hints;
 
+    private final Optional<TableSample> tableSample;
+
     public LogicalOlapScan(RelationId id, OlapTable table) {
         this(id, table, ImmutableList.of());
     }
@@ -111,22 +114,25 @@ public class LogicalOlapScan extends 
LogicalCatalogRelation implements OlapScan
         this(id, table, qualifier, Optional.empty(), Optional.empty(),
                 table.getPartitionIds(), false,
                 ImmutableList.of(),
-                -1, false, PreAggStatus.on(), ImmutableList.of(), 
ImmutableList.of(), Maps.newHashMap());
+                -1, false, PreAggStatus.on(), ImmutableList.of(), 
ImmutableList.of(),
+                Maps.newHashMap(), Optional.empty());
     }
 
-    public LogicalOlapScan(RelationId id, OlapTable table, List<String> 
qualifier, List<String> hints) {
+    public LogicalOlapScan(RelationId id, OlapTable table, List<String> 
qualifier,
+            List<String> hints, Optional<TableSample> tableSample) {
         this(id, table, qualifier, Optional.empty(), Optional.empty(),
-                table.getPartitionIds(), false,
-                ImmutableList.of(),
-                -1, false, PreAggStatus.on(), ImmutableList.of(), hints, 
Maps.newHashMap());
+                table.getPartitionIds(), false, ImmutableList.of(),
+                -1, false, PreAggStatus.on(), ImmutableList.of(), hints, 
Maps.newHashMap(),
+                tableSample);
     }
 
     public LogicalOlapScan(RelationId id, OlapTable table, List<String> 
qualifier, List<Long> specifiedPartitions,
-            List<String> hints) {
+            List<String> hints, Optional<TableSample> tableSample) {
         this(id, table, qualifier, Optional.empty(), Optional.empty(),
                 // must use specifiedPartitions here for prune partition by 
sql like 'select * from t partition p1'
                 specifiedPartitions, false, ImmutableList.of(),
-                -1, false, PreAggStatus.on(), specifiedPartitions, hints, 
Maps.newHashMap());
+                -1, false, PreAggStatus.on(), specifiedPartitions, hints, 
Maps.newHashMap(),
+                tableSample);
     }
 
     /**
@@ -137,10 +143,12 @@ public class LogicalOlapScan extends 
LogicalCatalogRelation implements OlapScan
             List<Long> selectedPartitionIds, boolean partitionPruned,
             List<Long> selectedTabletIds, long selectedIndexId, boolean 
indexSelected,
             PreAggStatus preAggStatus, List<Long> specifiedPartitions,
-            List<String> hints, Map<Pair<Long, String>, Slot> 
cacheSlotWithSlotName) {
+            List<String> hints, Map<Pair<Long, String>, Slot> 
cacheSlotWithSlotName,
+            Optional<TableSample> tableSample) {
         super(id, PlanType.LOGICAL_OLAP_SCAN, table, qualifier,
                 groupExpression, logicalProperties);
-        Preconditions.checkArgument(selectedPartitionIds != null, 
"selectedPartitionIds can not be null");
+        Preconditions.checkArgument(selectedPartitionIds != null,
+                "selectedPartitionIds can not be null");
         this.selectedTabletIds = ImmutableList.copyOf(selectedTabletIds);
         this.partitionPruned = partitionPruned;
         this.selectedIndexId = selectedIndexId <= 0 ? 
getTable().getBaseIndexId() : selectedIndexId;
@@ -152,7 +160,9 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
                 .filter(partitionId -> 
this.getTable().getPartition(partitionId).hasData())
                 .collect(Collectors.toList());
         this.hints = Objects.requireNonNull(hints, "hints can not be null");
-        this.cacheSlotWithSlotName = 
Objects.requireNonNull(cacheSlotWithSlotName, "mvNameToSlot can not be null");
+        this.cacheSlotWithSlotName = 
Objects.requireNonNull(cacheSlotWithSlotName,
+                "mvNameToSlot can not be null");
+        this.tableSample = tableSample;
     }
 
     public List<Long> getSelectedPartitionIds() {
@@ -192,13 +202,15 @@ public class LogicalOlapScan extends 
LogicalCatalogRelation implements OlapScan
                 && Objects.equals(selectedTabletIds, that.selectedTabletIds)
                 && Objects.equals(manuallySpecifiedPartitions, 
that.manuallySpecifiedPartitions)
                 && Objects.equals(selectedPartitionIds, 
that.selectedPartitionIds)
-                && Objects.equals(hints, that.hints);
+                && Objects.equals(hints, that.hints)
+                && Objects.equals(tableSample, tableSample);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(super.hashCode(), selectedIndexId, indexSelected, 
preAggStatus, cacheSlotWithSlotName,
-                selectedTabletIds, partitionPruned, 
manuallySpecifiedPartitions, selectedPartitionIds, hints);
+                selectedTabletIds, partitionPruned, 
manuallySpecifiedPartitions, selectedPartitionIds, hints,
+                tableSample);
     }
 
     @Override
@@ -207,7 +219,7 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
                 groupExpression, Optional.of(getLogicalProperties()),
                 selectedPartitionIds, partitionPruned, selectedTabletIds,
                 selectedIndexId, indexSelected, preAggStatus, 
manuallySpecifiedPartitions,
-                hints, cacheSlotWithSlotName);
+                hints, cacheSlotWithSlotName, tableSample);
     }
 
     @Override
@@ -216,7 +228,7 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
         return new LogicalOlapScan(relationId, (Table) table, qualifier, 
groupExpression, logicalProperties,
                 selectedPartitionIds, partitionPruned, selectedTabletIds,
                 selectedIndexId, indexSelected, preAggStatus, 
manuallySpecifiedPartitions,
-                hints, cacheSlotWithSlotName);
+                hints, cacheSlotWithSlotName, tableSample);
     }
 
     public LogicalOlapScan withSelectedPartitionIds(List<Long> 
selectedPartitionIds) {
@@ -224,14 +236,15 @@ public class LogicalOlapScan extends 
LogicalCatalogRelation implements OlapScan
                 Optional.empty(), Optional.of(getLogicalProperties()),
                 selectedPartitionIds, true, selectedTabletIds,
                 selectedIndexId, indexSelected, preAggStatus, 
manuallySpecifiedPartitions,
-                hints, cacheSlotWithSlotName);
+                hints, cacheSlotWithSlotName, tableSample);
     }
 
     public LogicalOlapScan withMaterializedIndexSelected(PreAggStatus preAgg, 
long indexId) {
         return new LogicalOlapScan(relationId, (Table) table, qualifier,
                 Optional.empty(), Optional.of(getLogicalProperties()),
                 selectedPartitionIds, partitionPruned, selectedTabletIds,
-                indexId, true, preAgg, manuallySpecifiedPartitions, hints, 
cacheSlotWithSlotName);
+                indexId, true, preAgg, manuallySpecifiedPartitions, hints, 
cacheSlotWithSlotName,
+                tableSample);
     }
 
     public LogicalOlapScan withSelectedTabletIds(List<Long> selectedTabletIds) 
{
@@ -239,7 +252,7 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
                 Optional.empty(), Optional.of(getLogicalProperties()),
                 selectedPartitionIds, partitionPruned, selectedTabletIds,
                 selectedIndexId, indexSelected, preAggStatus, 
manuallySpecifiedPartitions,
-                hints, cacheSlotWithSlotName);
+                hints, cacheSlotWithSlotName, tableSample);
     }
 
     public LogicalOlapScan withPreAggStatus(PreAggStatus preAggStatus) {
@@ -247,7 +260,7 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
                 Optional.empty(), Optional.of(getLogicalProperties()),
                 selectedPartitionIds, partitionPruned, selectedTabletIds,
                 selectedIndexId, indexSelected, preAggStatus, 
manuallySpecifiedPartitions,
-                hints, cacheSlotWithSlotName);
+                hints, cacheSlotWithSlotName, tableSample);
     }
 
     @Override
@@ -334,4 +347,8 @@ public class LogicalOlapScan extends LogicalCatalogRelation 
implements OlapScan
     public List<String> getHints() {
         return hints;
     }
+
+    public Optional<TableSample> getTableSample() {
+        return tableSample;
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapScan.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapScan.java
index 57292551a91..47433c3389a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapScan.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapScan.java
@@ -22,6 +22,7 @@ import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.DistributionSpec;
 import org.apache.doris.nereids.properties.LogicalProperties;
 import org.apache.doris.nereids.properties.PhysicalProperties;
+import org.apache.doris.nereids.trees.TableSample;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.plans.AbstractPlan;
 import org.apache.doris.nereids.trees.plans.Plan;
@@ -52,15 +53,19 @@ public class PhysicalOlapScan extends 
PhysicalCatalogRelation implements OlapSca
     private final PreAggStatus preAggStatus;
     private final List<Slot> baseOutputs;
 
+    private final Optional<TableSample> tableSample;
+
     /**
      * Constructor for PhysicalOlapScan.
      */
     public PhysicalOlapScan(RelationId id, OlapTable olapTable, List<String> 
qualifier, long selectedIndexId,
             List<Long> selectedTabletIds, List<Long> selectedPartitionIds, 
DistributionSpec distributionSpec,
             PreAggStatus preAggStatus, List<Slot> baseOutputs,
-            Optional<GroupExpression> groupExpression, LogicalProperties 
logicalProperties) {
+            Optional<GroupExpression> groupExpression, LogicalProperties 
logicalProperties,
+            Optional<TableSample> tableSample) {
         this(id, olapTable, qualifier, selectedIndexId, selectedTabletIds, 
selectedPartitionIds, distributionSpec,
-                preAggStatus, baseOutputs, groupExpression, logicalProperties, 
null, null);
+                preAggStatus, baseOutputs, groupExpression, logicalProperties, 
null, null,
+                tableSample);
     }
 
     /**
@@ -70,7 +75,7 @@ public class PhysicalOlapScan extends PhysicalCatalogRelation 
implements OlapSca
             List<Long> selectedTabletIds, List<Long> selectedPartitionIds, 
DistributionSpec distributionSpec,
             PreAggStatus preAggStatus, List<Slot> baseOutputs,
             Optional<GroupExpression> groupExpression, LogicalProperties 
logicalProperties,
-            PhysicalProperties physicalProperties, Statistics statistics) {
+            PhysicalProperties physicalProperties, Statistics statistics, 
Optional<TableSample> tableSample) {
         super(id, PlanType.PHYSICAL_OLAP_SCAN, olapTable, qualifier,
                 groupExpression, logicalProperties, physicalProperties, 
statistics);
         this.selectedIndexId = selectedIndexId;
@@ -79,6 +84,7 @@ public class PhysicalOlapScan extends PhysicalCatalogRelation 
implements OlapSca
         this.distributionSpec = distributionSpec;
         this.preAggStatus = preAggStatus;
         this.baseOutputs = ImmutableList.copyOf(baseOutputs);
+        this.tableSample = tableSample;
     }
 
     @Override
@@ -155,7 +161,7 @@ public class PhysicalOlapScan extends 
PhysicalCatalogRelation implements OlapSca
     public PhysicalOlapScan withGroupExpression(Optional<GroupExpression> 
groupExpression) {
         return new PhysicalOlapScan(relationId, getTable(), qualifier, 
selectedIndexId, selectedTabletIds,
                 selectedPartitionIds, distributionSpec, preAggStatus, 
baseOutputs,
-                groupExpression, getLogicalProperties());
+                groupExpression, getLogicalProperties(), tableSample);
     }
 
     @Override
@@ -163,7 +169,7 @@ public class PhysicalOlapScan extends 
PhysicalCatalogRelation implements OlapSca
             Optional<LogicalProperties> logicalProperties, List<Plan> 
children) {
         return new PhysicalOlapScan(relationId, getTable(), qualifier, 
selectedIndexId, selectedTabletIds,
                 selectedPartitionIds, distributionSpec, preAggStatus, 
baseOutputs, groupExpression,
-                logicalProperties.get());
+                logicalProperties.get(), tableSample);
     }
 
     @Override
@@ -171,7 +177,7 @@ public class PhysicalOlapScan extends 
PhysicalCatalogRelation implements OlapSca
             PhysicalProperties physicalProperties, Statistics statistics) {
         return new PhysicalOlapScan(relationId, getTable(), qualifier, 
selectedIndexId, selectedTabletIds,
                 selectedPartitionIds, distributionSpec, preAggStatus, 
baseOutputs, groupExpression,
-                getLogicalProperties(), physicalProperties, statistics);
+                getLogicalProperties(), physicalProperties, statistics, 
tableSample);
     }
 
     @Override
@@ -193,4 +199,7 @@ public class PhysicalOlapScan extends 
PhysicalCatalogRelation implements OlapSca
         return olapScan;
     }
 
+    public Optional<TableSample> getTableSample() {
+        return tableSample;
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslatorTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslatorTest.java
index be5a14343da..ad8ed9b6bf1 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslatorTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslatorTest.java
@@ -66,7 +66,7 @@ public class PhysicalPlanTranslatorTest {
         LogicalProperties t1Properties = new LogicalProperties(() -> t1Output);
         PhysicalOlapScan scan = new 
PhysicalOlapScan(StatementScopeIdGenerator.newRelationId(), t1, qualifier, 
t1.getBaseIndexId(),
                 Collections.emptyList(), Collections.emptyList(), null, 
PreAggStatus.on(),
-                ImmutableList.of(), Optional.empty(), t1Properties);
+                ImmutableList.of(), Optional.empty(), t1Properties, 
Optional.empty());
         Literal t1FilterRight = new IntegerLiteral(1);
         Expression t1FilterExpr = new GreaterThan(col1, t1FilterRight);
         PhysicalFilter<PhysicalOlapScan> filter =
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/MergeProjectPostProcessTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/MergeProjectPostProcessTest.java
index 74822d8fe59..729d988d93d 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/MergeProjectPostProcessTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/MergeProjectPostProcessTest.java
@@ -77,7 +77,7 @@ public class MergeProjectPostProcessTest {
         LogicalProperties t1Properties = new LogicalProperties(() -> t1Output);
         PhysicalOlapScan scan = new 
PhysicalOlapScan(RelationId.createGenerator().getNextId(), t1, qualifier, 0L,
                 Collections.emptyList(), Collections.emptyList(), null, 
PreAggStatus.on(), ImmutableList.of(),
-                Optional.empty(), t1Properties);
+                Optional.empty(), t1Properties, Optional.empty());
         Alias x = new Alias(a, "x");
         List<NamedExpression> projList3 = Lists.newArrayList(x, b, c);
         PhysicalProject proj3 = new PhysicalProject(projList3, placeHolder, 
scan);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/PushdownFilterThroughProjectTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/PushdownFilterThroughProjectTest.java
index ccbed847c32..46130efbcbd 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/PushdownFilterThroughProjectTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/PushdownFilterThroughProjectTest.java
@@ -88,7 +88,8 @@ public class PushdownFilterThroughProjectTest {
         LogicalProperties t1Properties = new LogicalProperties(() -> t1Output);
         PhysicalOlapScan scan = new 
PhysicalOlapScan(RelationId.createGenerator().getNextId(), t1,
                 qualifier, 0L, Collections.emptyList(), 
Collections.emptyList(), null,
-                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
t1Properties);
+                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
t1Properties,
+                Optional.empty());
         Alias x = new Alias(a, "x");
         List<NamedExpression> projList3 = Lists.newArrayList(x, b, c);
         PhysicalProject proj3 = new PhysicalProject(projList3, placeHolder, 
scan);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanEqualsTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanEqualsTest.java
index c018c0d6dfe..c43ecd6872e 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanEqualsTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanEqualsTest.java
@@ -265,16 +265,19 @@ class PlanEqualsTest {
 
         PhysicalOlapScan actual = new PhysicalOlapScan(id, olapTable, 
Lists.newArrayList("a"),
                 1L, selectedTabletId, olapTable.getPartitionIds(), 
distributionSpecHash,
-                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
logicalProperties);
+                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
logicalProperties,
+                Optional.empty());
 
         PhysicalOlapScan expected = new PhysicalOlapScan(id, olapTable, 
Lists.newArrayList("a"),
                 1L, selectedTabletId, olapTable.getPartitionIds(), 
distributionSpecHash,
-                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
logicalProperties);
+                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
logicalProperties,
+                Optional.empty());
         Assertions.assertEquals(expected, actual);
 
         PhysicalOlapScan unexpected = new PhysicalOlapScan(id, olapTable, 
Lists.newArrayList("b"),
                 12345L, selectedTabletId, olapTable.getPartitionIds(), 
distributionSpecHash,
-                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
logicalProperties);
+                PreAggStatus.on(), ImmutableList.of(), Optional.empty(), 
logicalProperties,
+                Optional.empty());
         Assertions.assertNotEquals(unexpected, actual);
     }
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanConstructor.java 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanConstructor.java
index 9bb48837754..3866ce98bf3 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanConstructor.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanConstructor.java
@@ -32,6 +32,7 @@ import org.apache.doris.thrift.TStorageType;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
+import java.util.Optional;
 
 public class PlanConstructor {
 
@@ -112,7 +113,7 @@ public class PlanConstructor {
             int hashColumn, List<Long> selectedPartitions) {
         return new LogicalOlapScan(RelationId.createGenerator().getNextId(),
                 newOlapTable(tableId, tableName, hashColumn), 
ImmutableList.of("db"),
-                selectedPartitions, ImmutableList.of());
+                selectedPartitions, ImmutableList.of(), Optional.empty());
     }
 
     public static RelationId getNextRelationId() {
diff --git a/regression-test/suites/nereids_p0/tablesample.groovy 
b/regression-test/suites/nereids_p0/tablesample.groovy
new file mode 100644
index 00000000000..52203bed232
--- /dev/null
+++ b/regression-test/suites/nereids_p0/tablesample.groovy
@@ -0,0 +1,45 @@
+// 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.
+
+suite("test_table_sample") {
+    sql "SET enable_nereids_planner=false"
+    sql "SET enable_fallback_to_original_planner=false"
+    sql """DROP TABLE IF EXISTS test_table_sample_tbl"""
+    sql """
+        CREATE TABLE `test_table_sample_tbl` (
+          `col1` varchar(11451) NOT NULL,
+          `col2` int(11) NOT NULL,
+          `col3` int(11) NOT NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(`col1`)
+        COMMENT 'OLAP'
+        DISTRIBUTED BY HASH(`col1`) BUCKETS 3
+        PROPERTIES (
+        "replication_allocation" = "tag.location.default: 1",
+        "is_being_synced" = "false",
+        "storage_format" = "V2",
+        "light_schema_change" = "true",
+        "disable_auto_compaction" = "false",
+        "enable_single_replica_compaction" = "false"
+        ); 
+    """
+
+    // result is random, couldn't check it
+    sql """ select * from test_table_sample_tbl tablesample(4 rows);"""
+    sql """select * from test_table_sample_tbl t tablesample(20 percent);"""
+    sql """select * from test_table_sample_tbl t tablesample(20 percent) 
repeatable 2;"""
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to