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

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new ea2a21dc751 [fix](cache) fix same sql return wrong result when switch 
database with `use db` and enable sql cache (#44782)
ea2a21dc751 is described below

commit ea2a21dc7519142ffcb4af893c88e1dfd4215556
Author: htyoung <hty551...@hotmail.com>
AuthorDate: Sat Nov 30 22:48:56 2024 +0800

    [fix](cache) fix same sql return wrong result when switch database with 
`use db` and enable sql cache (#44782)
    
    ### What problem does this PR solve?
    
    It will return wrong result when running same sql in different db with
    `enable_sql_cache=true`
    
    for example, the `db1` and `db2` has the same table `tbl` but the data
    are not equals,
    if execute the below sql in `db1` and cache the result, then execute it
    in `db2`, it will return the wrong result
    ```sql
    select count(*) from tbl
    ```
    Co-authored-by: tongyang.han <tongyang....@jiduauto.com>
---
 .../doris/common/NereidsSqlCacheManager.java       | 49 ++++++++------
 .../cache/parse_sql_from_sql_cache.groovy          | 74 ++++++++++++++++++++++
 2 files changed, 105 insertions(+), 18 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/NereidsSqlCacheManager.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/NereidsSqlCacheManager.java
index 1317fdaefc7..cd32b52034a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/NereidsSqlCacheManager.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/NereidsSqlCacheManager.java
@@ -74,9 +74,11 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 
-/** NereidsSqlCacheManager */
+/**
+ * NereidsSqlCacheManager
+ */
 public class NereidsSqlCacheManager {
-    // key: <user>:<sql>
+    // key: <ctl.db>:<user>:<sql>
     // value: SqlCacheContext
     private volatile Cache<String, SqlCacheContext> sqlCaches;
 
@@ -110,7 +112,7 @@ public class NereidsSqlCacheManager {
                 // auto evict cache when jvm memory too low
                 .softValues();
         if (sqlCacheNum > 0) {
-            cacheBuilder = cacheBuilder.maximumSize(sqlCacheNum);
+            cacheBuilder.maximumSize(sqlCacheNum);
         }
         if (expireAfterAccessSeconds > 0) {
             cacheBuilder = 
cacheBuilder.expireAfterAccess(Duration.ofSeconds(expireAfterAccessSeconds));
@@ -119,7 +121,9 @@ public class NereidsSqlCacheManager {
         return cacheBuilder.build();
     }
 
-    /** tryAddFeCache */
+    /**
+     * tryAddFeCache
+     */
     public void tryAddFeSqlCache(ConnectContext connectContext, String sql) {
         Optional<SqlCacheContext> sqlCacheContextOpt = 
connectContext.getStatementContext().getSqlCacheContext();
         if (!sqlCacheContextOpt.isPresent()) {
@@ -127,17 +131,18 @@ public class NereidsSqlCacheManager {
         }
 
         SqlCacheContext sqlCacheContext = sqlCacheContextOpt.get();
-        UserIdentity currentUserIdentity = 
connectContext.getCurrentUserIdentity();
         String key = sqlCacheContext.getCacheKeyType() == CacheKeyType.SQL
-                ? currentUserIdentity.toString() + ":" + 
normalizeSql(sql.trim())
-                : currentUserIdentity.toString() + ":" + 
DebugUtil.printId(sqlCacheContext.getOrComputeCacheKeyMd5());
+                ? generateCacheKey(connectContext, normalizeSql(sql))
+                : generateCacheKey(connectContext, 
DebugUtil.printId(sqlCacheContext.getOrComputeCacheKeyMd5()));
         if (sqlCaches.getIfPresent(key) == null && 
sqlCacheContext.getOrComputeCacheKeyMd5() != null
                 && sqlCacheContext.getResultSetInFe().isPresent()) {
             sqlCaches.put(key, sqlCacheContext);
         }
     }
 
-    /** tryAddBeCache */
+    /**
+     * tryAddBeCache
+     */
     public void tryAddBeCache(ConnectContext connectContext, String sql, 
CacheAnalyzer analyzer) {
         Optional<SqlCacheContext> sqlCacheContextOpt = 
connectContext.getStatementContext().getSqlCacheContext();
         if (!sqlCacheContextOpt.isPresent()) {
@@ -147,10 +152,9 @@ public class NereidsSqlCacheManager {
             return;
         }
         SqlCacheContext sqlCacheContext = sqlCacheContextOpt.get();
-        UserIdentity currentUserIdentity = 
connectContext.getCurrentUserIdentity();
         String key = sqlCacheContext.getCacheKeyType() == CacheKeyType.SQL
-                ? currentUserIdentity.toString() + ":" + 
normalizeSql(sql.trim())
-                : currentUserIdentity.toString() + ":" + 
DebugUtil.printId(sqlCacheContext.getOrComputeCacheKeyMd5());
+                ? generateCacheKey(connectContext, normalizeSql(sql))
+                : generateCacheKey(connectContext, 
DebugUtil.printId(sqlCacheContext.getOrComputeCacheKeyMd5()));
         if (sqlCaches.getIfPresent(key) == null && 
sqlCacheContext.getOrComputeCacheKeyMd5() != null) {
             SqlCache cache = (SqlCache) analyzer.getCache();
             sqlCacheContext.setSumOfPartitionNum(cache.getSumOfPartitionNum());
@@ -167,23 +171,23 @@ public class NereidsSqlCacheManager {
         }
     }
 
-    /** tryParseSql */
+    /**
+     * tryParseSql
+     */
     public Optional<LogicalSqlCache> tryParseSql(ConnectContext 
connectContext, String sql) {
-        UserIdentity currentUserIdentity = 
connectContext.getCurrentUserIdentity();
-        String key = currentUserIdentity + ":" + normalizeSql(sql.trim());
+        String key = generateCacheKey(connectContext, 
normalizeSql(sql.trim()));
         SqlCacheContext sqlCacheContext = sqlCaches.getIfPresent(key);
         if (sqlCacheContext == null) {
             return Optional.empty();
         }
 
         // LOG.info("Total size: " + 
GraphLayout.parseInstance(sqlCacheContext).totalSize());
-
+        UserIdentity currentUserIdentity = 
connectContext.getCurrentUserIdentity();
         List<Variable> currentVariables = 
resolveUserVariables(sqlCacheContext);
         if (usedVariablesChanged(currentVariables, sqlCacheContext)) {
             String md5 = DebugUtil.printId(
                     
sqlCacheContext.doComputeCacheKeyMd5(Utils.fastToImmutableSet(currentVariables)));
-
-            String md5CacheKey = currentUserIdentity + ":" + md5;
+            String md5CacheKey = generateCacheKey(connectContext, md5);
             SqlCacheContext sqlCacheContextWithVariable = 
sqlCaches.getIfPresent(md5CacheKey);
 
             // already exist cache in the fe, but the variable is different to 
this query,
@@ -203,6 +207,15 @@ public class NereidsSqlCacheManager {
         }
     }
 
+    private String generateCacheKey(ConnectContext connectContext, String 
sqlOrMd5) {
+        CatalogIf<?> currentCatalog = connectContext.getCurrentCatalog();
+        String currentCatalogName = currentCatalog != null ? 
currentCatalog.getName() : "";
+        String currentDatabase = connectContext.getDatabase();
+        String currentDatabaseName = currentDatabase != null ? currentDatabase 
: "";
+        return currentCatalogName + "." + currentDatabaseName + ":" + 
connectContext.getCurrentUserIdentity().toString()
+                + ":" + sqlOrMd5;
+    }
+
     private String normalizeSql(String sql) {
         return NereidsParser.removeCommentAndTrimBlank(sql);
     }
@@ -402,7 +415,7 @@ public class NereidsSqlCacheManager {
             Variable cachedVariable = cachedUsedVariables.get(i);
             if (!Objects.equals(currentVariable, cachedVariable)
                     || cachedVariable.getRealExpression().anyMatch(
-                            expr -> !((ExpressionTrait) 
expr).isDeterministic())) {
+                        expr -> !((ExpressionTrait) expr).isDeterministic())) {
                 return true;
             }
         }
diff --git 
a/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy 
b/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy
index 54ab7028888..3635936e8be 100644
--- a/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy
+++ b/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy
@@ -827,6 +827,80 @@ suite("parse_sql_from_sql_cache") {
                 def result = sql "select FROM_UNIXTIME(UNIX_TIMESTAMP(), 
'yyyy-MM-dd HH:mm:ss')"
                 assertNotEquals("yyyy-MM-dd HH:mm:ss", result[0][0])
             }
+        }),
+        extraThread("test_same_sql_with_different_db", {
+            def dbName1 = "test_db1"
+            def dbName2 = "test_db2"
+            def tableName = "test_cache_table"
+
+            sql "CREATE DATABASE IF NOT EXISTS ${dbName1}"
+            sql "DROP TABLE IF EXISTS ${dbName1}.${tableName}"
+            sql """
+                CREATE TABLE IF NOT EXISTS ${dbName1}.${tableName} (
+                  `k1` date NOT NULL COMMENT "",
+                  `k2` int(11) NOT NULL COMMENT ""
+                ) ENGINE=OLAP
+                DUPLICATE KEY(`k1`, `k2`)
+                COMMENT "OLAP"
+                PARTITION BY RANGE(`k1`)
+                (PARTITION p202411 VALUES [('2024-11-01'), ('2024-12-01')))
+                DISTRIBUTED BY HASH(`k1`, `k2`) BUCKETS 1
+                PROPERTIES (
+                "replication_allocation" = "tag.location.default: 1",
+                "in_memory" = "false",
+                "storage_format" = "V2"
+                )
+            """
+            sql "CREATE DATABASE IF NOT EXISTS ${dbName2}"
+            sql "DROP TABLE IF EXISTS ${dbName2}.${tableName}"
+            sql """
+                CREATE TABLE IF NOT EXISTS ${dbName2}.${tableName} (
+                  `k1` date NOT NULL COMMENT "",
+                  `k2` int(11) NOT NULL COMMENT ""
+                ) ENGINE=OLAP
+                DUPLICATE KEY(`k1`, `k2`)
+                COMMENT "OLAP"
+                PARTITION BY RANGE(`k1`)
+                (PARTITION p202411 VALUES [('2024-11-01'), ('2024-12-01')))
+                DISTRIBUTED BY HASH(`k1`, `k2`) BUCKETS 1
+                PROPERTIES (
+                "replication_allocation" = "tag.location.default: 1",
+                "in_memory" = "false",
+                "storage_format" = "V2"
+                )
+            """
+
+            sql """
+                INSERT INTO ${dbName1}.${tableName} VALUES 
+                        ("2024-11-29",0),
+                        ("2024-11-30",0)
+            """
+            // after partition changed 10s, the sql cache can be used
+            sleep(10000)
+            sql """
+                INSERT INTO ${dbName2}.${tableName} VALUES 
+                        ("2024-11-29",0)
+            """
+            // after partition changed 10s, the sql cache can be used
+            sleep(10000)
+
+            sql "set enable_sql_cache=true"
+            sql "use ${dbName1}"
+            List<List<Object>> result1 = sql """
+                SELECT COUNT(*) FROM ${tableName}
+            """
+            assertEquals(result1[0][0],2)
+
+            sql "use ${dbName2}"
+            List<List<Object>> result2 = sql """
+                SELECT COUNT(*) FROM ${tableName}
+            """
+            assertEquals(result2[0][0],1)
+
+            sql "DROP TABLE IF EXISTS ${dbName1}.${tableName}"
+            sql "DROP TABLE IF EXISTS ${dbName2}.${tableName}"
+            sql "DROP DATABASE IF EXISTS ${dbName1}"
+            sql "DROP DATABASE IF EXISTS ${dbName2}"
         })
     ).get()
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to