Skip to content

Commit 81886fa

Browse files
authored
[Enhancement] (nereids) support show column histogram command (apache#48587)
1 parent b4f8fcd commit 81886fa

File tree

6 files changed

+199
-3
lines changed

6 files changed

+199
-3
lines changed

fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4

+2-2
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,8 @@ supportedStatsStatement
731731
(WHERE (stateKey=identifier) EQ (stateValue=STRING_LITERAL))? #showAnalyze
732732
| SHOW QUEUED ANALYZE JOBS tableName=multipartIdentifier?
733733
(WHERE (stateKey=identifier) EQ (stateValue=STRING_LITERAL))? #showQueuedAnalyzeJobs
734+
| SHOW COLUMN HISTOGRAM tableName=multipartIdentifier
735+
columnList=identifierList #showColumnHistogramStats
734736
| ANALYZE DATABASE name=multipartIdentifier
735737
(WITH analyzeProperties)* propertyClause? #analyzeDatabase
736738
| ANALYZE TABLE name=multipartIdentifier partitionSpec?
@@ -755,8 +757,6 @@ unsupportedStatsStatement
755757
| SHOW INDEX STATS tableName=multipartIdentifier indexId=identifier #showIndexStats
756758
| SHOW COLUMN CACHED? STATS tableName=multipartIdentifier
757759
columnList=identifierList? partitionSpec? #showColumnStats
758-
| SHOW COLUMN HISTOGRAM tableName=multipartIdentifier
759-
columnList=identifierList #showColumnHistogramStats
760760
| SHOW ANALYZE TASK STATUS jobId=INTEGER_VALUE #showAnalyzeTask
761761
;
762762

fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java

+9
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@
300300
import org.apache.doris.nereids.DorisParser.ShowBrokerContext;
301301
import org.apache.doris.nereids.DorisParser.ShowCharsetContext;
302302
import org.apache.doris.nereids.DorisParser.ShowCollationContext;
303+
import org.apache.doris.nereids.DorisParser.ShowColumnHistogramStatsContext;
303304
import org.apache.doris.nereids.DorisParser.ShowConfigContext;
304305
import org.apache.doris.nereids.DorisParser.ShowConstraintContext;
305306
import org.apache.doris.nereids.DorisParser.ShowConvertLscContext;
@@ -603,6 +604,7 @@
603604
import org.apache.doris.nereids.trees.plans.commands.ShowCatalogCommand;
604605
import org.apache.doris.nereids.trees.plans.commands.ShowCharsetCommand;
605606
import org.apache.doris.nereids.trees.plans.commands.ShowCollationCommand;
607+
import org.apache.doris.nereids.trees.plans.commands.ShowColumnHistogramStatsCommand;
606608
import org.apache.doris.nereids.trees.plans.commands.ShowConfigCommand;
607609
import org.apache.doris.nereids.trees.plans.commands.ShowConstraintsCommand;
608610
import org.apache.doris.nereids.trees.plans.commands.ShowConvertLSCCommand;
@@ -6055,6 +6057,13 @@ public Map<String, String> visitAnalyzeProperties(DorisParser.AnalyzePropertiesC
60556057
return properties;
60566058
}
60576059

6060+
@Override
6061+
public LogicalPlan visitShowColumnHistogramStats(ShowColumnHistogramStatsContext ctx) {
6062+
TableNameInfo tableNameInfo = new TableNameInfo(visitMultipartIdentifier(ctx.tableName));
6063+
List<String> columnNames = visitIdentifierList(ctx.columnList);
6064+
return new ShowColumnHistogramStatsCommand(tableNameInfo, columnNames);
6065+
}
6066+
60586067
@Override
60596068
public LogicalPlan visitDescribeTableAll(DorisParser.DescribeTableAllContext ctx) {
60606069
TableNameInfo tableName = new TableNameInfo(visitMultipartIdentifier(ctx.multipartIdentifier()));

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java

+1
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ public enum PlanType {
226226
SHOW_CATALOG_COMMAND,
227227
SHOW_CHARSET_COMMAND,
228228
SHOW_COLLATION_COMMAND,
229+
SHOW_COLUMN_HISTOGRAM,
229230
SHOW_CONFIG_COMMAND,
230231
SHOW_CREATE_CATALOG_COMMAND,
231232
SHOW_CREATE_DATABASE_COMMAND,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.doris.nereids.trees.plans.commands;
19+
20+
import org.apache.doris.catalog.Column;
21+
import org.apache.doris.catalog.DatabaseIf;
22+
import org.apache.doris.catalog.Env;
23+
import org.apache.doris.catalog.ScalarType;
24+
import org.apache.doris.catalog.TableIf;
25+
import org.apache.doris.catalog.Type;
26+
import org.apache.doris.common.ErrorCode;
27+
import org.apache.doris.common.ErrorReport;
28+
import org.apache.doris.common.Pair;
29+
import org.apache.doris.common.UserException;
30+
import org.apache.doris.common.util.Util;
31+
import org.apache.doris.datasource.CatalogIf;
32+
import org.apache.doris.mysql.privilege.PrivPredicate;
33+
import org.apache.doris.nereids.trees.plans.PlanType;
34+
import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo;
35+
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
36+
import org.apache.doris.qe.ConnectContext;
37+
import org.apache.doris.qe.ShowResultSet;
38+
import org.apache.doris.qe.ShowResultSetMetaData;
39+
import org.apache.doris.qe.StmtExecutor;
40+
import org.apache.doris.statistics.Histogram;
41+
42+
import com.google.common.collect.ImmutableList;
43+
import com.google.common.collect.Lists;
44+
import com.google.common.collect.Sets;
45+
46+
import java.util.List;
47+
import java.util.Objects;
48+
import java.util.Optional;
49+
import java.util.Set;
50+
import java.util.stream.Collectors;
51+
52+
/**
53+
* Represents the command for SHOW COLUMN HISTOGRAM
54+
*/
55+
public class ShowColumnHistogramStatsCommand extends ShowCommand {
56+
/**
57+
* TITLE_NAMES
58+
*/
59+
private static final ImmutableList<String> TITLE_NAMES =
60+
new ImmutableList.Builder<String>()
61+
.add("column_name")
62+
.add("data_type")
63+
.add("sample_rate")
64+
.add("num_buckets")
65+
.add("buckets")
66+
.build();
67+
68+
private TableNameInfo tableNameInfo;
69+
70+
private final List<String> columnNames;
71+
72+
private TableIf table;
73+
74+
public ShowColumnHistogramStatsCommand(TableNameInfo tableNameInfo, List<String> columnNames) {
75+
super(PlanType.SHOW_COLUMN_HISTOGRAM);
76+
this.tableNameInfo = tableNameInfo;
77+
this.columnNames = columnNames;
78+
}
79+
80+
/**
81+
* validate
82+
*/
83+
public void validate(ConnectContext ctx) throws UserException {
84+
tableNameInfo.analyze(ctx);
85+
86+
// disallow external catalog
87+
Util.prohibitExternalCatalog(tableNameInfo.getCtl(), this.getClass().getSimpleName());
88+
CatalogIf<DatabaseIf> catalog = Env.getCurrentEnv().getCatalogMgr().getCatalog(tableNameInfo.getCtl());
89+
if (catalog == null) {
90+
ErrorReport.reportAnalysisException("Catalog: {} not exists", tableNameInfo.getCtl());
91+
}
92+
DatabaseIf<TableIf> db = catalog.getDb(tableNameInfo.getDb()).orElse(null);
93+
if (db == null) {
94+
ErrorReport.reportAnalysisException("DB: {} not exists", tableNameInfo.getDb());
95+
}
96+
table = db.getTable(tableNameInfo.getTbl()).orElse(null);
97+
if (table == null) {
98+
ErrorReport.reportAnalysisException("Table: {} not exists", tableNameInfo.getTbl());
99+
}
100+
101+
if (!Env.getCurrentEnv().getAccessManager()
102+
.checkTblPriv(ConnectContext.get(), tableNameInfo.getCtl(), tableNameInfo.getDb(),
103+
tableNameInfo.getTbl(), PrivPredicate.SHOW)) {
104+
ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "Permission denied",
105+
ConnectContext.get().getQualifiedUser(), ConnectContext.get().getRemoteIP(),
106+
tableNameInfo.getDb() + ": " + tableNameInfo.getTbl());
107+
}
108+
109+
if (columnNames != null) {
110+
Optional<Column> nullColumn = columnNames.stream()
111+
.map(table::getColumn)
112+
.filter(Objects::isNull)
113+
.findFirst();
114+
if (nullColumn.isPresent()) {
115+
ErrorReport.reportAnalysisException("Column: {} not exists", nullColumn.get());
116+
}
117+
}
118+
}
119+
120+
/**
121+
* getMetaData
122+
*/
123+
public ShowResultSetMetaData getMetaData() {
124+
ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder();
125+
126+
for (String title : TITLE_NAMES) {
127+
builder.addColumn(new Column(title, ScalarType.createVarchar(30)));
128+
}
129+
return builder.build();
130+
}
131+
132+
public TableIf getTable() {
133+
return table;
134+
}
135+
136+
/**
137+
* constructResultSet
138+
*/
139+
public ShowResultSet constructResultSet(List<Pair<String, Histogram>> columnStatistics) {
140+
List<List<String>> result = Lists.newArrayList();
141+
columnStatistics.forEach(p -> {
142+
if (p.second == null || p.second.dataType == Type.NULL) {
143+
return;
144+
}
145+
List<String> row = Lists.newArrayList();
146+
row.add(p.first);
147+
row.add(String.valueOf(p.second.dataType));
148+
row.add(String.valueOf(p.second.sampleRate));
149+
row.add(String.valueOf(p.second.numBuckets));
150+
row.add(Histogram.getBucketsJson(p.second.buckets).toString());
151+
result.add(row);
152+
});
153+
154+
return new ShowResultSet(getMetaData(), result);
155+
}
156+
157+
/**
158+
* getColumnNames
159+
*/
160+
public Set<String> getColumnNames() {
161+
if (columnNames != null) {
162+
return Sets.newHashSet(columnNames);
163+
}
164+
return table.getColumns().stream()
165+
.map(Column::getName).collect(Collectors.toSet());
166+
}
167+
168+
@Override
169+
public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
170+
validate(ctx);
171+
List<Pair<String, Histogram>> columnStatistics = Lists.newArrayList();
172+
// TODO: support histogram in the future.
173+
return constructResultSet(columnStatistics);
174+
}
175+
176+
@Override
177+
public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
178+
return visitor.visitShowColumnHistogramStatsCommand(this, context);
179+
}
180+
}

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
import org.apache.doris.nereids.trees.plans.commands.ShowCatalogCommand;
105105
import org.apache.doris.nereids.trees.plans.commands.ShowCharsetCommand;
106106
import org.apache.doris.nereids.trees.plans.commands.ShowCollationCommand;
107+
import org.apache.doris.nereids.trees.plans.commands.ShowColumnHistogramStatsCommand;
107108
import org.apache.doris.nereids.trees.plans.commands.ShowConfigCommand;
108109
import org.apache.doris.nereids.trees.plans.commands.ShowConstraintsCommand;
109110
import org.apache.doris.nereids.trees.plans.commands.ShowConvertLSCCommand;
@@ -821,6 +822,11 @@ default R visitShowQueuedAnalyzeJobsCommand(ShowQueuedAnalyzeJobsCommand showQue
821822
return visitCommand(showQueuedAnalyzeJobsCommand, context);
822823
}
823824

825+
default R visitShowColumnHistogramStatsCommand(ShowColumnHistogramStatsCommand showColumnHistogramStatCommand,
826+
C context) {
827+
return visitCommand(showColumnHistogramStatCommand, context);
828+
}
829+
824830
default R visitDescribeCommand(DescribeCommand describeCommand, C context) {
825831
return visitCommand(describeCommand, context);
826832
}

fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsRepository.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ private static ResultRow queryColumnStatisticById(long ctlId, long dbId, long tb
198198
return size == 0 ? null : rows.get(0);
199199
}
200200

201-
private static Histogram queryColumnHistogramByName(
201+
public static Histogram queryColumnHistogramByName(
202202
long ctlId, long dbId, long tableId, long indexId, String colName) {
203203
ResultRow resultRow = queryColumnHistogramById(ctlId, dbId, tableId, indexId, colName);
204204
if (resultRow == null) {

0 commit comments

Comments
 (0)