This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.2 by this push:
new df6eb31b45f branch-4.2: [fix](statistics) Quote identifiers in
statistics queries #67703 (#70088)
df6eb31b45f is described below
commit df6eb31b45f0530084478f69a7cb7bcb8bdf7b16
Author: morrySnow <[email protected]>
AuthorDate: Wed Nov 4 08:25:48 2026 +0800
branch-4.2: [fix](statistics) Quote identifiers in statistics queries
#67703 (#70088)
picked from master #67703
---
.../apache/doris/statistics/BaseAnalysisTask.java | 73 ++++++++++----------
.../doris/statistics/ExternalAnalysisTask.java | 14 ++--
.../apache/doris/statistics/HMSAnalysisTask.java | 4 +-
.../org/apache/doris/statistics/HistogramTask.java | 17 ++---
.../apache/doris/statistics/OlapAnalysisTask.java | 25 +++----
.../org/apache/doris/statistics/AnalyzeTest.java | 11 +++
.../doris/statistics/BaseAnalysisTaskTest.java | 6 +-
.../doris/statistics/HMSAnalysisTaskTest.java | 4 ++
.../doris/statistics/OlapAnalysisTaskTest.java | 80 ++++++++++++++++------
9 files changed, 147 insertions(+), 87 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/statistics/BaseAnalysisTask.java
b/fe/fe-core/src/main/java/org/apache/doris/statistics/BaseAnalysisTask.java
index 2e0c5cc4a98..c374cccbb50 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/statistics/BaseAnalysisTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/BaseAnalysisTask.java
@@ -28,6 +28,7 @@ import org.apache.doris.catalog.Type;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.Status;
import org.apache.doris.common.util.DebugUtil;
+import org.apache.doris.common.util.SqlUtils;
import org.apache.doris.datasource.CatalogIf;
import org.apache.doris.metric.MetricRepo;
import org.apache.doris.qe.AuditLogHelper;
@@ -89,8 +90,8 @@ public abstract class BaseAnalysisTask {
public static final String ANALYZE_SKIP_LONG_STRING_COLUMN_MARKER =
"ANALYZE_SKIP_LONG_STRING_COLUMN";
protected static final String FULL_ANALYZE_TEMPLATE = "WITH cte1 AS ("
- + "SELECT `${colName}`${lengthAssert} "
- + "FROM `${catalogName}`.`${dbName}`.`${tblName}` ${index}), "
+ + "SELECT ${colName}${lengthAssert} "
+ + "FROM ${catalogName}.${dbName}.${tblName} ${index}), "
+ "cte2 AS ("
+ "SELECT CONCAT(${tblId}, '-', ${idxId}, '-', '${colId}') AS
`id`, "
+ "${catalogId} AS `catalog_id`, "
@@ -100,10 +101,10 @@ public abstract class BaseAnalysisTask {
+ "'${colId}' AS `col_id`, "
+ "NULL AS `part_id`, "
+ "COUNT(1) AS `row_count`, "
- + "NDV(`${colName}`) AS `ndv`, "
- + "COUNT(1) - COUNT(`${colName}`) AS `null_count`, "
- + "SUBSTRING(CAST(MIN(`${colName}`) AS STRING), 1, 1024) AS
`min`, "
- + "SUBSTRING(CAST(MAX(`${colName}`) AS STRING), 1, 1024) AS
`max`, "
+ + "NDV(${colName}) AS `ndv`, "
+ + "COUNT(1) - COUNT(${colName}) AS `null_count`, "
+ + "SUBSTRING(CAST(MIN(${colName}) AS STRING), 1, 1024) AS
`min`, "
+ + "SUBSTRING(CAST(MAX(${colName}) AS STRING), 1, 1024) AS
`max`, "
+ "${dataSizeFunction} AS `data_size`, "
+ "NOW() "
+ "FROM cte1), "
@@ -114,9 +115,9 @@ public abstract class BaseAnalysisTask {
+ "as `hot_value` "
+ "FROM ("
+ "SELECT ${subStringColName} as `hash_value`, "
- + "MAX(`${colName}`) as `column_key`, "
+ + "MAX(${colName}) as `column_key`, "
+ "COUNT(1) AS `count` "
- + "FROM cte1 WHERE `${colName}` IS NOT NULL "
+ + "FROM cte1 WHERE ${colName} IS NOT NULL "
+ "GROUP BY `hash_value` ORDER BY `count` DESC LIMIT
${hotValueCollectCount}) t) "
+ "SELECT * FROM cte2 CROSS JOIN cte3";
@@ -129,19 +130,19 @@ public abstract class BaseAnalysisTask {
+ "'${colId}' AS `col_id`, "
+ "NULL AS `part_id`, "
+ "COUNT(1) AS `row_count`, "
- + "NDV(`${colName}`) AS `ndv`, "
- + "COUNT(1) - COUNT(`${colName}`) AS `null_count`, "
- + "SUBSTRING(CAST(MIN(`${colName}`) AS STRING), 1, 1024) AS
`min`, "
- + "SUBSTRING(CAST(MAX(`${colName}`) AS STRING), 1, 1024) AS
`max`, "
+ + "NDV(${colName}) AS `ndv`, "
+ + "COUNT(1) - COUNT(${colName}) AS `null_count`, "
+ + "SUBSTRING(CAST(MIN(${colName}) AS STRING), 1, 1024) AS
`min`, "
+ + "SUBSTRING(CAST(MAX(${colName}) AS STRING), 1, 1024) AS
`max`, "
+ "${dataSizeFunction} AS `data_size`, "
+ "NOW() AS `update_time`, "
+ "null as `hot_value` "
- + "FROM (SELECT `${colName}`${lengthAssert} "
- + "FROM `${catalogName}`.`${dbName}`.`${tblName}` ${index})
__lc_t";
+ + "FROM (SELECT ${colName}${lengthAssert} "
+ + "FROM ${catalogName}.${dbName}.${tblName} ${index}) __lc_t";
protected static final String LINEAR_ANALYZE_TEMPLATE = "WITH cte1 AS ("
- + "SELECT `${colName}`${lengthAssert} "
- + "FROM `${catalogName}`.`${dbName}`.`${tblName}` ${index}
${sampleHints} ${limit} ${preAggHint}), "
+ + "SELECT ${colName}${lengthAssert} "
+ + "FROM ${catalogName}.${dbName}.${tblName} ${index}
${sampleHints} ${limit} ${preAggHint}), "
+ "cte2 AS ("
+ "SELECT CONCAT(${tblId}, '-', ${idxId}, '-', '${colId}') AS
`id`, "
+ "${catalogId} AS `catalog_id`, "
@@ -152,7 +153,7 @@ public abstract class BaseAnalysisTask {
+ "NULL AS `part_id`, "
+ "${rowCount} AS `row_count`, "
+ "${ndvFunction} as `ndv`, "
- + "ROUND(SUM(CASE WHEN `${colName}` IS NULL THEN 1 ELSE 0 END)
* ${scaleFactor}) AS `null_count`, "
+ + "ROUND(SUM(CASE WHEN ${colName} IS NULL THEN 1 ELSE 0 END) *
${scaleFactor}) AS `null_count`, "
+ "SUBSTRING(CAST(${min} AS STRING), 1, 1024) AS `min`, "
+ "SUBSTRING(CAST(${max} AS STRING), 1, 1024) AS `max`, "
+ "${dataSizeFunction} * ${scaleFactor} AS `data_size`, "
@@ -164,9 +165,9 @@ public abstract class BaseAnalysisTask {
+ "as `hot_value` "
+ "FROM ("
+ "SELECT ${subStringColName} as `hash_value`, "
- + "MAX(`${colName}`) as `column_key`, "
+ + "MAX(${colName}) as `column_key`, "
+ "COUNT(1) AS `count` "
- + "FROM cte1 WHERE `${colName}` IS NOT NULL "
+ + "FROM cte1 WHERE ${colName} IS NOT NULL "
+ "GROUP BY `hash_value` ORDER BY `count` DESC LIMIT
${hotValueCollectCount}) t) "
+ "SELECT * FROM cte2 CROSS JOIN cte3";
@@ -175,9 +176,9 @@ public abstract class BaseAnalysisTask {
+ "FROM "
+ "(SELECT "
+ "${subStringColName} AS `hash_value`, "
- + "`${colName}` AS `col_value`, "
- + "LENGTH(`${colName}`) as `len`${lengthAssert} "
- + "FROM `${catalogName}`.`${dbName}`.`${tblName}` ${index}
${sampleHints} ${limit}) as `t0` "
+ + "${colName} AS `col_value`, "
+ + "LENGTH(${colName}) as `len`${lengthAssert} "
+ + "FROM ${catalogName}.${dbName}.${tblName} ${index}
${sampleHints} ${limit}) as `t0` "
+ "${preAggHint} GROUP BY `t0`.`hash_value`), "
+ "cte2 AS ( "
+ "SELECT CONCAT('${tblId}', '-', '${idxId}', '-', '${colId}')
AS `id`, "
@@ -239,13 +240,13 @@ public abstract class BaseAnalysisTask {
+ "${partId} AS `part_id`, "
+ "'${colId}' AS `col_id`, "
+ "COUNT(1) AS `row_count`, "
- + "HLL_UNION(HLL_HASH(`${colName}`)) as ndv, "
- + "COUNT(1) - COUNT(`${colName}`) AS `null_count`, "
- + "SUBSTRING(CAST(MIN(`${colName}`) AS STRING), 1, 1024) AS `min`,
"
- + "SUBSTRING(CAST(MAX(`${colName}`) AS STRING), 1, 1024) AS `max`,
"
+ + "HLL_UNION(HLL_HASH(${colName})) as ndv, "
+ + "COUNT(1) - COUNT(${colName}) AS `null_count`, "
+ + "SUBSTRING(CAST(MIN(${colName}) AS STRING), 1, 1024) AS `min`, "
+ + "SUBSTRING(CAST(MAX(${colName}) AS STRING), 1, 1024) AS `max`, "
+ "${dataSizeFunction} AS `data_size`, "
+ "NOW() AS `update_time` "
- + "FROM `${catalogName}`.`${dbName}`.`${tblName}` ${index}
${partitionInfo}";
+ + "FROM ${catalogName}.${dbName}.${tblName} ${index}
${partitionInfo}";
protected static final String MERGE_PARTITION_TEMPLATE =
"SELECT CONCAT(${tblId}, '-', ${idxId}, '-', '${colId}') AS `id`, "
@@ -416,7 +417,7 @@ public abstract class BaseAnalysisTask {
}
} else {
if (column.getType().isStringType()) {
- return "SUM(LENGTH(`${colName}`))";
+ return "SUM(LENGTH(${colName}))";
} else {
return "COUNT(1) * " + column.getType().getSlotSize();
}
@@ -425,15 +426,15 @@ public abstract class BaseAnalysisTask {
protected String getStringTypeColName(Column column) {
if (column.getType().isStringType()) {
- return "xxhash_64(SUBSTRING(CAST(`${colName}` AS STRING), 1,
1024))";
+ return "xxhash_64(SUBSTRING(CAST(${colName} AS STRING), 1, 1024))";
} else {
- return "`${colName}`";
+ return "${colName}";
}
}
protected String getMinFunction() {
if (tableSample == null) {
- return "CAST(MIN(`${colName}`) as ${type}) ";
+ return "CAST(MIN(${colName}) as ${type}) ";
} else {
// Min value is not accurate while sample, so set it to NULL to
avoid optimizer generate bad plan.
return "NULL";
@@ -454,7 +455,7 @@ public abstract class BaseAnalysisTask {
// Max value is not accurate while sample, so set it to NULL to avoid
optimizer generate bad plan.
protected String getMaxFunction() {
if (tableSample == null) {
- return "CAST(MAX(`${colName}`) as ${type}) ";
+ return "CAST(MAX(${colName}) as ${type}) ";
} else {
return "NULL";
}
@@ -552,7 +553,7 @@ public abstract class BaseAnalysisTask {
}
}
}
- params.put("partName", "'" + StatisticsUtil.escapeColumnName(part)
+ "'");
+ params.put("partName",
StatisticsUtil.quote(StatisticsUtil.escapeSQL(part)));
params.put("partitionInfo", getPartitionInfo(part));
StringSubstitutor stringSubstitutor = new
StringSubstitutor(params);
sqls.add(stringSubstitutor.replace(PARTITION_ANALYZE_TEMPLATE));
@@ -636,11 +637,11 @@ public abstract class BaseAnalysisTask {
protected void addLengthAssertParam(Map<String, String> params) {
long maxLen =
org.apache.doris.common.Config.statistics_max_string_column_length;
if (col != null && col.getType().isStringType() && maxLen > 0) {
- String escapedColName =
StatisticsUtil.escapeColumnName(String.valueOf(info.colName));
+ String quotedColName =
SqlUtils.getIdentSql(String.valueOf(info.colName));
// The StringSubstitutor used by callers already has ${colName}
populated,
- // so we inline the escaped column name directly here.
+ // so we inline the quoted column name directly here.
params.put("lengthAssert",
- ", assert_true(`" + escapedColName + "` IS NULL OR
LENGTH(`" + escapedColName + "`) <= "
+ ", assert_true(" + quotedColName + " IS NULL OR LENGTH(" +
quotedColName + ") <= "
+ maxLen + ", '" +
ANALYZE_SKIP_LONG_STRING_COLUMN_MARKER + "') AS `__lc`");
} else {
params.put("lengthAssert", "");
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/statistics/ExternalAnalysisTask.java
b/fe/fe-core/src/main/java/org/apache/doris/statistics/ExternalAnalysisTask.java
index d37b3740f9d..d244201586a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/statistics/ExternalAnalysisTask.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/statistics/ExternalAnalysisTask.java
@@ -20,8 +20,10 @@ package org.apache.doris.statistics;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.FeConstants;
import org.apache.doris.common.NotImplementedException;
+import org.apache.doris.common.util.SqlUtils;
import org.apache.doris.datasource.ExternalTable;
import org.apache.doris.qe.SessionVariable;
+import org.apache.doris.statistics.util.StatisticsUtil;
import org.apache.commons.text.StringSubstitutor;
@@ -67,7 +69,7 @@ public class ExternalAnalysisTask extends BaseAnalysisTask {
if (shouldCollectHotValue()) {
params.put("hotValueCollectCount",
String.valueOf(SessionVariable.getHotValueCollectCount()));
params.put("subStringColName", getStringTypeColName(col));
- params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
`${colName}` IS NOT NULL)");
+ params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
${colName} IS NOT NULL)");
template = FULL_ANALYZE_TEMPLATE;
} else {
template = FULL_ANALYZE_WITHOUT_HOT_VALUE_TEMPLATE;
@@ -86,11 +88,11 @@ public class ExternalAnalysisTask extends BaseAnalysisTask {
params.put("dbId", String.valueOf(db.getId()));
params.put("tblId", String.valueOf(tbl.getId()));
params.put("idxId", "-1");
- params.put("colName", info.colName);
- params.put("colId", info.colName);
- params.put("catalogName", catalog.getName());
- params.put("dbName", db.getFullName());
- params.put("tblName", tbl.getName());
+ params.put("colName", SqlUtils.getIdentSql(info.colName));
+ params.put("colId", StatisticsUtil.escapeSQL(info.colName));
+ params.put("catalogName", SqlUtils.getIdentSql(catalog.getName()));
+ params.put("dbName", SqlUtils.getIdentSql(db.getFullName()));
+ params.put("tblName", SqlUtils.getIdentSql(tbl.getName()));
params.put("sampleHints", getSampleHint());
params.put("limit", "");
params.put("scaleFactor", "1");
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/statistics/HMSAnalysisTask.java
b/fe/fe-core/src/main/java/org/apache/doris/statistics/HMSAnalysisTask.java
index 3b611f60000..16bd4941223 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/statistics/HMSAnalysisTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/HMSAnalysisTask.java
@@ -250,9 +250,9 @@ public class HMSAnalysisTask extends ExternalAnalysisTask {
if (distributionColumns.size() == 1 &&
distributionColumns.contains(col.getName().toLowerCase())) {
bucketFlag = true;
sb.append(LINEAR_ANALYZE_TEMPLATE);
- params.put("ndvFunction", "ROUND(NDV(`${colName}`) *
${scaleFactor})");
+ params.put("ndvFunction", "ROUND(NDV(${colName}) *
${scaleFactor})");
params.put("rowCount", "ROUND(COUNT(1) * ${scaleFactor})");
- params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
`${colName}` IS NOT NULL)");
+ params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
${colName} IS NOT NULL)");
} else {
sb.append(DUJ1_ANALYZE_TEMPLATE);
params.put("subStringColName", getStringTypeColName(col));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/statistics/HistogramTask.java
b/fe/fe-core/src/main/java/org/apache/doris/statistics/HistogramTask.java
index aae2566700e..eeab8dc118f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/statistics/HistogramTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/HistogramTask.java
@@ -20,6 +20,7 @@ package org.apache.doris.statistics;
import org.apache.doris.catalog.Env;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.util.SqlUtils;
import org.apache.doris.statistics.AnalysisInfo.AnalysisMethod;
import org.apache.doris.statistics.util.StatisticsUtil;
@@ -43,10 +44,10 @@ public class HistogramTask extends BaseAnalysisTask {
+ " ${idxId} AS idx_id, "
+ " '${colId}' AS col_id, "
+ " ${sampleRate} AS sample_rate, "
- + " HISTOGRAM(`${colName}`, ${maxBucketNum}) AS buckets, "
+ + " HISTOGRAM(${colName}, ${maxBucketNum}) AS buckets, "
+ " NOW() AS create_time "
+ "FROM "
- + " `${dbName}`.`${tblName}`";
+ + " ${dbName}.${tblName}";
public HistogramTask(AnalysisInfo info) {
super(info);
@@ -55,16 +56,16 @@ public class HistogramTask extends BaseAnalysisTask {
@Override
public void doExecute() throws Exception {
Map<String, String> params = new HashMap<>();
- params.put("internalDB", FeConstants.INTERNAL_DB_NAME);
- params.put("histogramStatTbl", StatisticConstants.HISTOGRAM_TBL_NAME);
+ params.put("internalDB",
SqlUtils.getIdentSql(FeConstants.INTERNAL_DB_NAME));
+ params.put("histogramStatTbl",
SqlUtils.getIdentSql(StatisticConstants.HISTOGRAM_TBL_NAME));
params.put("catalogId", String.valueOf(catalog.getId()));
params.put("dbId", String.valueOf(db.getId()));
params.put("tblId", String.valueOf(tbl.getId()));
params.put("idxId", String.valueOf(info.indexId));
- params.put("colId", String.valueOf(info.colName));
- params.put("dbName", db.getFullName());
- params.put("tblName", tbl.getName());
- params.put("colName", String.valueOf(info.colName));
+ params.put("colId",
StatisticsUtil.escapeSQL(String.valueOf(info.colName)));
+ params.put("dbName", SqlUtils.getIdentSql(db.getFullName()));
+ params.put("tblName", SqlUtils.getIdentSql(tbl.getName()));
+ params.put("colName",
SqlUtils.getIdentSql(String.valueOf(info.colName)));
params.put("sampleRate", getSampleRateFunction());
params.put("maxBucketNum", String.valueOf(info.maxBucketNum));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/statistics/OlapAnalysisTask.java
b/fe/fe-core/src/main/java/org/apache/doris/statistics/OlapAnalysisTask.java
index a7ac364c984..5b1f451004a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/statistics/OlapAnalysisTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/OlapAnalysisTask.java
@@ -34,6 +34,7 @@ import org.apache.doris.common.FeConstants;
import org.apache.doris.common.Pair;
import org.apache.doris.common.util.DebugPointUtil;
import org.apache.doris.common.util.DebugUtil;
+import org.apache.doris.common.util.SqlUtils;
import org.apache.doris.qe.AutoCloseConnectContext;
import org.apache.doris.qe.SessionVariable;
import org.apache.doris.qe.StmtExecutor;
@@ -62,9 +63,9 @@ import java.util.stream.Collectors;
public class OlapAnalysisTask extends BaseAnalysisTask {
private static final String BASIC_STATS_TEMPLATE = "SELECT "
- + "SUBSTRING(CAST(MIN(`${colName}`) AS STRING), 1, 1024) as min, "
- + "SUBSTRING(CAST(MAX(`${colName}`) AS STRING), 1, 1024) as max "
- + "FROM `${dbName}`.`${tblName}` ${index}";
+ + "SUBSTRING(CAST(MIN(${colName}) AS STRING), 1, 1024) as min, "
+ + "SUBSTRING(CAST(MAX(${colName}) AS STRING), 1, 1024) as max "
+ + "FROM ${dbName}.${tblName} ${index}";
private boolean keyColumnSampleTooManyRows = false;
private boolean partitionColumnSampleTooManyRows = false;
@@ -360,12 +361,12 @@ public class OlapAnalysisTask extends BaseAnalysisTask {
params.put("dataSizeFunction", getDataSizeFunction(col, true));
params.put("rowCount2", "(SELECT SUM(`count`) FROM cte1 WHERE
`col_value` IS NOT NULL)");
} else {
- params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
`${colName}` IS NOT NULL)");
+ params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
${colName} IS NOT NULL)");
// For single unique key, use count as ndv.
if (isSingleUniqueKey()) {
params.put("ndvFunction", String.valueOf(tableRowCount));
} else {
- params.put("ndvFunction", "ROUND(NDV(`${colName}`) *
${scaleFactor})");
+ params.put("ndvFunction", "ROUND(NDV(${colName}) *
${scaleFactor})");
}
}
}
@@ -382,7 +383,7 @@ public class OlapAnalysisTask extends BaseAnalysisTask {
if (shouldCollectHotValue()) {
params.put("hotValueCollectCount",
String.valueOf(SessionVariable.getHotValueCollectCount()));
params.put("subStringColName", getStringTypeColName(col));
- params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
`${colName}` IS NOT NULL)");
+ params.put("rowCount2", "(SELECT COUNT(1) FROM cte1 WHERE
${colName} IS NOT NULL)");
runQuery(stringSubstitutor.replace(FULL_ANALYZE_TEMPLATE));
} else {
runQuery(stringSubstitutor.replace(FULL_ANALYZE_WITHOUT_HOT_VALUE_TEMPLATE));
@@ -435,7 +436,7 @@ public class OlapAnalysisTask extends BaseAnalysisTask {
@Override
protected String getPartitionInfo(String partitionName) {
- return "partition " + partitionName;
+ return "partition " + SqlUtils.getIdentSql(partitionName);
}
@Override
@@ -449,10 +450,10 @@ public class OlapAnalysisTask extends BaseAnalysisTask {
params.put("idxId", String.valueOf(info.indexId));
params.put("colId",
StatisticsUtil.escapeSQL(String.valueOf(info.colName)));
params.put("dataSizeFunction", getDataSizeFunction(col, false));
- params.put("catalogName", catalog.getName());
- params.put("dbName", db.getFullName());
- params.put("colName",
StatisticsUtil.escapeColumnName(String.valueOf(info.colName)));
- params.put("tblName", String.valueOf(tbl.getName()));
+ params.put("catalogName", SqlUtils.getIdentSql(catalog.getName()));
+ params.put("dbName", SqlUtils.getIdentSql(db.getFullName()));
+ params.put("colName",
SqlUtils.getIdentSql(String.valueOf(info.colName)));
+ params.put("tblName",
SqlUtils.getIdentSql(String.valueOf(tbl.getName())));
params.put("index", getIndex());
params.put("preAggHint", "");
addLengthAssertParam(params);
@@ -464,7 +465,7 @@ public class OlapAnalysisTask extends BaseAnalysisTask {
return "";
} else {
OlapTable olapTable = (OlapTable) this.tbl;
- return "index `" + olapTable.getIndexNameById(info.indexId) + "`";
+ return "index " +
SqlUtils.getIdentSql(olapTable.getIndexNameById(info.indexId));
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalyzeTest.java
b/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalyzeTest.java
index b41c464b9e9..a8c8f61cffb 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalyzeTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/statistics/AnalyzeTest.java
@@ -105,6 +105,17 @@ public class AnalyzeTest extends TestWithFeService {
Database database,
@Mocked OlapTable olapTable)
throws Exception {
+ new Expectations() {
+ {
+ catalog.getName();
+ result = "internal";
+ database.getFullName();
+ result = "analysis_job_test";
+ olapTable.getName();
+ result = "t1";
+ }
+ };
+
new MockUp<OlapTable>() {
@Mock
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/statistics/BaseAnalysisTaskTest.java
b/fe/fe-core/src/test/java/org/apache/doris/statistics/BaseAnalysisTaskTest.java
index 9e2ea6d3510..78418370503 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/statistics/BaseAnalysisTaskTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/statistics/BaseAnalysisTaskTest.java
@@ -36,7 +36,7 @@ public class BaseAnalysisTaskTest {
String dataSizeFunction = olapAnalysisTask.getDataSizeFunction(column,
true);
Assertions.assertEquals("SUM(`column_length`)", dataSizeFunction);
dataSizeFunction = olapAnalysisTask.getDataSizeFunction(column, false);
- Assertions.assertEquals("SUM(LENGTH(`${colName}`))", dataSizeFunction);
+ Assertions.assertEquals("SUM(LENGTH(${colName}))", dataSizeFunction);
column = new Column("int_column", PrimitiveType.INT);
dataSizeFunction = olapAnalysisTask.getDataSizeFunction(column, false);
@@ -45,14 +45,14 @@ public class BaseAnalysisTaskTest {
Assertions.assertEquals("SUM(t1.count) * 4", dataSizeFunction);
String minFunction = olapAnalysisTask.getMinFunction();
- Assertions.assertEquals("CAST(MIN(`${colName}`) as ${type}) ",
minFunction);
+ Assertions.assertEquals("CAST(MIN(${colName}) as ${type}) ",
minFunction);
olapAnalysisTask.tableSample = new TableSample(true, 20L);
minFunction = olapAnalysisTask.getMinFunction();
Assertions.assertEquals("NULL", minFunction);
olapAnalysisTask.tableSample = null;
String maxFunction = olapAnalysisTask.getMaxFunction();
- Assertions.assertEquals("CAST(MAX(`${colName}`) as ${type}) ",
maxFunction);
+ Assertions.assertEquals("CAST(MAX(${colName}) as ${type}) ",
maxFunction);
olapAnalysisTask.tableSample = new TableSample(true, 20L);
maxFunction = olapAnalysisTask.getMaxFunction();
Assertions.assertEquals("NULL", maxFunction);
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/statistics/HMSAnalysisTaskTest.java
b/fe/fe-core/src/test/java/org/apache/doris/statistics/HMSAnalysisTaskTest.java
index 33721e5f8e4..22d0f30f14c 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/statistics/HMSAnalysisTaskTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/statistics/HMSAnalysisTaskTest.java
@@ -316,12 +316,16 @@ public class HMSAnalysisTaskTest {
{
tableIf.getId();
result = 30001;
+ tableIf.getName();
+ result = "test";
catalogIf.getId();
result = 10001;
catalogIf.getName();
result = "hms";
databaseIf.getId();
result = 20001;
+ databaseIf.getFullName();
+ result = "default";
}
};
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/statistics/OlapAnalysisTaskTest.java
b/fe/fe-core/src/test/java/org/apache/doris/statistics/OlapAnalysisTaskTest.java
index dd0113bf930..26aacda24ab 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/statistics/OlapAnalysisTaskTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/statistics/OlapAnalysisTaskTest.java
@@ -40,6 +40,7 @@ import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.FeConstants;
import org.apache.doris.common.Pair;
import org.apache.doris.common.util.DebugPointUtil;
+import org.apache.doris.common.util.SqlUtils;
import org.apache.doris.datasource.CatalogIf;
import org.apache.doris.persist.gson.GsonUtils;
import org.apache.doris.qe.SessionVariable;
@@ -153,6 +154,8 @@ public class OlapAnalysisTaskTest {
result = "catalogName";
databaseIf.getId();
result = 20001;
+ databaseIf.getFullName();
+ result = "dbName";
}
};
@@ -181,7 +184,7 @@ public class OlapAnalysisTaskTest {
@Mock
public void runQuery(String sql) {
- Assertions.assertEquals("WITH cte1 AS (SELECT `null` FROM
`catalogName`.`${dbName}`.`null` "
+ Assertions.assertEquals("WITH cte1 AS (SELECT `null` FROM
`catalogName`.`dbName`.`null` "
+ "${sampleHints} ${limit} ), cte2 AS (SELECT
CONCAT(30001, '-', -1, '-', 'null') AS `id`, "
+ "10001 AS `catalog_id`, 20001 AS `db_id`, 30001 AS
`tbl_id`, -1 AS `idx_id`, "
+ "'null' AS `col_id`, NULL AS `part_id`, ${rowCount}
AS `row_count`, ${ndvFunction} as `ndv`, "
@@ -215,7 +218,7 @@ public class OlapAnalysisTaskTest {
public void runQuery(String sql) {
Assertions.assertEquals("WITH cte1 AS (SELECT
MAX(t0.`col_value`) as `col_value`, COUNT(1) as `count`,"
+ " SUM(`len`) as `column_length` FROM (SELECT
${subStringColName} AS `hash_value`, "
- + "`null` AS `col_value`, LENGTH(`null`) as `len` FROM
`catalogName`.`${dbName}`.`null` "
+ + "`null` AS `col_value`, LENGTH(`null`) as `len` FROM
`catalogName`.`dbName`.`null` "
+ "${sampleHints} ${limit}) as `t0` GROUP BY
`t0`.`hash_value`), "
+ "cte2 AS ( SELECT CONCAT('30001', '-', '-1', '-',
'null') AS `id`, 10001 AS `catalog_id`, "
+ "20001 AS `db_id`, 30001 AS `tbl_id`, -1 AS
`idx_id`, 'null' AS `col_id`, NULL AS `part_id`, "
@@ -413,9 +416,9 @@ public class OlapAnalysisTaskTest {
new
OlapAnalysisTask.SampleCollectInfo(AnalyzeSampleAlgorithm.FULL, null));
Assertions.assertEquals("1", params.get("scaleFactor"));
Assertions.assertEquals("", params.get("sampleHints"));
- Assertions.assertEquals("(SELECT COUNT(1) FROM cte1 WHERE `${colName}`
IS NOT NULL)",
+ Assertions.assertEquals("(SELECT COUNT(1) FROM cte1 WHERE ${colName}
IS NOT NULL)",
params.get("rowCount2"));
- Assertions.assertEquals("ROUND(NDV(`${colName}`) * ${scaleFactor})",
params.get("ndvFunction"));
+ Assertions.assertEquals("ROUND(NDV(${colName}) * ${scaleFactor})",
params.get("ndvFunction"));
Assertions.assertNull(params.get("preAggHint"));
Assertions.assertEquals("COUNT(1)", params.get("rowCount"));
params.clear();
@@ -425,9 +428,9 @@ public class OlapAnalysisTaskTest {
new
OlapAnalysisTask.SampleCollectInfo(AnalyzeSampleAlgorithm.LINEAR,
Pair.of(Lists.newArrayList(1L, 2L), 100L)));
Assertions.assertEquals("TABLET(1, 2)", params.get("sampleHints"));
- Assertions.assertEquals("(SELECT COUNT(1) FROM cte1 WHERE `${colName}`
IS NOT NULL)",
+ Assertions.assertEquals("(SELECT COUNT(1) FROM cte1 WHERE ${colName}
IS NOT NULL)",
params.get("rowCount2"));
- Assertions.assertEquals("ROUND(NDV(`${colName}`) * ${scaleFactor})",
params.get("ndvFunction"));
+ Assertions.assertEquals("ROUND(NDV(${colName}) * ${scaleFactor})",
params.get("ndvFunction"));
params.clear();
// DUJ1 algorithm with sample tablets: rowCount2 and ndvFunction must
reference the cte1
@@ -459,7 +462,7 @@ public class OlapAnalysisTaskTest {
Assertions.assertEquals("TABLET(1, 2)", params.get("sampleHints"));
Assertions.assertEquals("SUM(`t1`.`count`) * COUNT(`t1`.`col_value`) /
(SUM(`t1`.`count`) - SUM(IF(`t1`.`count` = 1 and `t1`.`col_value` is not null,
1, 0)) + SUM(IF(`t1`.`count` = 1 and `t1`.`col_value` is not null, 1, 0)) *
SUM(`t1`.`count`) / 1000)", params.get("ndvFunction"));
Assertions.assertEquals("SUM(t1.count) * 4",
params.get("dataSizeFunction"));
- Assertions.assertEquals("`${colName}`",
params.get("subStringColName"));
+ Assertions.assertEquals("${colName}", params.get("subStringColName"));
Assertions.assertEquals("/*+PREAGGOPEN*/", params.get("preAggHint"));
params.clear();
@@ -518,7 +521,7 @@ public class OlapAnalysisTaskTest {
Pair.of(Lists.newArrayList(1L, 2L), 100L)));
Assertions.assertEquals("10.0", params.get("scaleFactor"));
Assertions.assertEquals("TABLET(1, 2)", params.get("sampleHints"));
- Assertions.assertEquals("ROUND(NDV(`${colName}`) * ${scaleFactor})",
params.get("ndvFunction"));
+ Assertions.assertEquals("ROUND(NDV(${colName}) * ${scaleFactor})",
params.get("ndvFunction"));
params.clear();
new MockUp<OlapAnalysisTask>() {
@@ -947,6 +950,43 @@ public class OlapAnalysisTaskTest {
}
}
+ @Test
+ public void testBuildSqlParamsQuotesIdentifiers() {
+ CatalogIf catalog = Mockito.mock(CatalogIf.class);
+ DatabaseIf database = Mockito.mock(DatabaseIf.class);
+ OlapTable table = Mockito.mock(OlapTable.class);
+ Mockito.when(catalog.getId()).thenReturn(1L);
+ Mockito.when(catalog.getName()).thenReturn("cat`alog");
+ Mockito.when(database.getId()).thenReturn(2L);
+ Mockito.when(database.getFullName()).thenReturn("db`name");
+ Mockito.when(table.getId()).thenReturn(3L);
+ Mockito.when(table.getName()).thenReturn("table`name");
+ Mockito.when(table.getIndexNameById(4L)).thenReturn("index`name");
+
+ OlapAnalysisTask task = new OlapAnalysisTask();
+ task.catalog = catalog;
+ task.db = database;
+ task.tbl = table;
+ task.col = new Column("col`'name", PrimitiveType.INT);
+ task.info = new AnalysisInfoBuilder()
+ .setIndexId(4L)
+ .setColName("col`'name")
+ .build();
+
+ Map<String, String> params = task.buildSqlParams();
+ Assertions.assertEquals("`cat``alog`", params.get("catalogName"));
+ Assertions.assertEquals("`db``name`", params.get("dbName"));
+ Assertions.assertEquals("`table``name`", params.get("tblName"));
+ Assertions.assertEquals("`col``'name`", params.get("colName"));
+ Assertions.assertEquals("col`''name", params.get("colId"));
+ Assertions.assertEquals("index `index``name`", params.get("index"));
+ Assertions.assertEquals("partition `part``name`",
task.getPartitionInfo("part`name"));
+
+ String sql = new
StringSubstitutor(params).replace(BaseAnalysisTask.FULL_ANALYZE_WITHOUT_HOT_VALUE_TEMPLATE);
+ Assertions.assertTrue(sql.contains("FROM (SELECT `col``'name` FROM "
+ + "`cat``alog`.`db``name`.`table``name` index `index``name`)
__lc_t"), sql);
+ }
+
@Test
public void testFullAnalyzeTemplateRendersLengthAssert() {
// Confirm the rendered FULL_ANALYZE_TEMPLATE wraps the base table in
a subquery
@@ -960,10 +1000,10 @@ public class OlapAnalysisTaskTest {
params.put("idxId", "3");
params.put("colId", "s");
params.put("dataSizeFunction", "100");
- params.put("catalogName", "internal");
- params.put("dbName", "db1");
- params.put("colName", "s");
- params.put("tblName", "tbl1");
+ params.put("catalogName", SqlUtils.getIdentSql("internal"));
+ params.put("dbName", SqlUtils.getIdentSql("db1"));
+ params.put("colName", SqlUtils.getIdentSql("s"));
+ params.put("tblName", SqlUtils.getIdentSql("tbl1"));
params.put("index", "");
params.put("lengthAssert",
", assert_true(`s` IS NULL OR LENGTH(`s`) <= 1024, '"
@@ -987,10 +1027,10 @@ public class OlapAnalysisTaskTest {
params.put("idxId", "3");
params.put("colId", "id");
params.put("dataSizeFunction", "100");
- params.put("catalogName", "internal");
- params.put("dbName", "db1");
- params.put("colName", "id");
- params.put("tblName", "tbl1");
+ params.put("catalogName", SqlUtils.getIdentSql("internal"));
+ params.put("dbName", SqlUtils.getIdentSql("db1"));
+ params.put("colName", SqlUtils.getIdentSql("id"));
+ params.put("tblName", SqlUtils.getIdentSql("tbl1"));
params.put("index", "");
params.put("lengthAssert", "");
StringSubstitutor stringSubstitutor = new StringSubstitutor(params);
@@ -1009,11 +1049,11 @@ public class OlapAnalysisTaskTest {
params.put("tblId", "2");
params.put("idxId", "3");
params.put("colId", "col1");
- params.put("colName", "col1");
+ params.put("colName", SqlUtils.getIdentSql("col1"));
params.put("dataSizeFunction", "SUM(LENGTH(`col1`))");
- params.put("catalogName", "internal");
- params.put("dbName", "db1");
- params.put("tblName", "tbl1");
+ params.put("catalogName", SqlUtils.getIdentSql("internal"));
+ params.put("dbName", SqlUtils.getIdentSql("db1"));
+ params.put("tblName", SqlUtils.getIdentSql("tbl1"));
params.put("index", "");
params.put("hotValueCollectCount", "10");
params.put("subStringColName", "`col1`");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]