You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2021/09/01 08:56:08 UTC

[shardingsphere] branch master updated: Refactor getShowLikePattern (#12140)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new e5f9841  Refactor getShowLikePattern (#12140)
e5f9841 is described below

commit e5f9841889a1bceb25de57ef1452e8e23f81cc3a
Author: Zhengqiang Duan <du...@apache.org>
AuthorDate: Wed Sep 1 16:55:35 2021 +0800

    Refactor getShowLikePattern (#12140)
    
    * Optimize name of getShowLikePattern method
    
    * optimize code
    
    * optimize sql pattern escape
    
    * optimize variable name
    
    * fix test case
    
    * optimize code
---
 .../mysql/executor/ShowDatabasesExecutor.java      |  2 +-
 .../admin/mysql/executor/ShowTablesExecutor.java   |  2 +-
 .../sql/parser/sql/common/util/SQLUtil.java        | 29 +++++++++++----
 .../sql/parser/sql/common/util/SQLUtilTest.java    | 42 ++++++++++++++++++++++
 4 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowDatabasesExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowDatabasesExecutor.java
index 272731c..594a9d8 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowDatabasesExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowDatabasesExecutor.java
@@ -65,7 +65,7 @@ public final class ShowDatabasesExecutor implements DatabaseAdminQueryExecutor {
     }
     
     private boolean checkLikePattern(final String schemaName) {
-        Optional<String> pattern = showDatabasesStatement.getLike().map(SQLUtil::getShowLikePattern);
+        Optional<String> pattern = showDatabasesStatement.getLike().map(each -> SQLUtil.convertLikePatternToRegex(each.getPattern()));
         return !pattern.isPresent() || schemaName.matches(pattern.get());
     }
     
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowTablesExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowTablesExecutor.java
index 8fe8e73..b7b0e9b 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowTablesExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/ShowTablesExecutor.java
@@ -69,7 +69,7 @@ public final class ShowTablesExecutor implements DatabaseAdminQueryExecutor {
     
     private Collection<String> getAllTableNames(final String schemaName) {
         Collection<String> allTableNames = ProxyContext.getInstance().getMetaData(schemaName).getSchema().getAllTableNames();
-        Optional<String> pattern = showTablesStatement.getLike().map(SQLUtil::getShowLikePattern);
+        Optional<String> pattern = showTablesStatement.getLike().map(each -> SQLUtil.convertLikePatternToRegex(each.getPattern()));
         return pattern.isPresent() ? allTableNames.stream().filter(each -> each.matches(pattern.get())).collect(Collectors.toList()) : allTableNames;
     }
     
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java
index 68ad3c6..f75527a 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java
@@ -23,7 +23,6 @@ import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.sql.parser.api.visitor.ASTNode;
 import org.apache.shardingsphere.sql.parser.sql.common.constant.Paren;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.ShowLikeSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
@@ -60,6 +59,7 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * SQL utility class.
@@ -73,6 +73,14 @@ public final class SQLUtil {
     
     private static final String COMMENT_SUFFIX = "*/";
     
+    private static final Pattern SINGLE_CHARACTER_PATTERN = Pattern.compile("^_|([^\\\\])_");
+    
+    private static final Pattern SINGLE_CHARACTER_ESCAPE_PATTERN = Pattern.compile("\\\\_");
+    
+    private static final Pattern ANY_CHARACTER_PATTERN = Pattern.compile("^%|([^\\\\])%");
+    
+    private static final Pattern ANY_CHARACTER_ESCAPE_PATTERN = Pattern.compile("\\\\%");
+    
     /**
      * Get exactly number value and type.
      *
@@ -280,12 +288,21 @@ public final class SQLUtil {
     }
     
     /**
-     * Get show like pattern.
+     * Convert like pattern to regex.
      * 
-     * @param showLike show like segment
-     * @return pattern
+     * @param pattern like pattern
+     * @return regex
      */
-    public static String getShowLikePattern(final ShowLikeSegment showLike) {
-        return showLike.getPattern().replaceAll("_", ".{1}").replaceAll("%", ".*");
+    public static String convertLikePatternToRegex(final String pattern) {
+        String result = pattern;
+        if (pattern.contains("_")) {
+            result = SINGLE_CHARACTER_PATTERN.matcher(result).replaceAll("$1.");    
+            result = SINGLE_CHARACTER_ESCAPE_PATTERN.matcher(result).replaceAll("_");    
+        }
+        if (pattern.contains("%")) {
+            result = ANY_CHARACTER_PATTERN.matcher(result).replaceAll("$1.*");
+            result = ANY_CHARACTER_ESCAPE_PATTERN.matcher(result).replaceAll("%");
+        }
+        return result;
     }
 }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilTest.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilTest.java
index ac8adc3..c877f13 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilTest.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilTest.java
@@ -90,4 +90,46 @@ public final class SQLUtilTest {
         assertThat(SQLUtil.getExpressionWithoutOutsideParentheses("((a + b*c))"), is("a + b*c"));
         assertThat(SQLUtil.getExpressionWithoutOutsideParentheses(""), is(""));
     }
+    
+    @Test
+    public void assertConvertLikePatternToRegexWhenEndWithPattern() {
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding_'"), is("SHOW DATABASES LIKE 'sharding.'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding%'"), is("SHOW DATABASES LIKE 'sharding.*'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding%_'"), is("SHOW DATABASES LIKE 'sharding.*.'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\_'"), is("SHOW DATABASES LIKE 'sharding_'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\%'"), is("SHOW DATABASES LIKE 'sharding%'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\%\\_'"), is("SHOW DATABASES LIKE 'sharding%_'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding_\\_'"), is("SHOW DATABASES LIKE 'sharding._'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding%\\%'"), is("SHOW DATABASES LIKE 'sharding.*%'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding_\\%'"), is("SHOW DATABASES LIKE 'sharding.%'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\_%'"), is("SHOW DATABASES LIKE 'sharding_.*'"));
+    }
+    
+    @Test
+    public void assertConvertLikePatternToRegexWhenStartWithPattern() {
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '_sharding'"), is("SHOW DATABASES LIKE '.sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '%sharding'"), is("SHOW DATABASES LIKE '.*sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '%_sharding'"), is("SHOW DATABASES LIKE '.*.sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '\\_sharding'"), is("SHOW DATABASES LIKE '_sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '\\%sharding'"), is("SHOW DATABASES LIKE '%sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '\\%\\_sharding'"), is("SHOW DATABASES LIKE '%_sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '_\\_sharding'"), is("SHOW DATABASES LIKE '._sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '%\\%sharding'"), is("SHOW DATABASES LIKE '.*%sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '_\\%sharding'"), is("SHOW DATABASES LIKE '.%sharding'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE '\\_%sharding'"), is("SHOW DATABASES LIKE '_.*sharding'"));
+    }
+    
+    @Test
+    public void assertConvertLikePatternToRegexWhenContainsPattern() {
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding_db'"), is("SHOW DATABASES LIKE 'sharding.db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding%db'"), is("SHOW DATABASES LIKE 'sharding.*db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding%_db'"), is("SHOW DATABASES LIKE 'sharding.*.db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\_db'"), is("SHOW DATABASES LIKE 'sharding_db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\%db'"), is("SHOW DATABASES LIKE 'sharding%db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\%\\_db'"), is("SHOW DATABASES LIKE 'sharding%_db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding_\\_db'"), is("SHOW DATABASES LIKE 'sharding._db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding%\\%db'"), is("SHOW DATABASES LIKE 'sharding.*%db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding_\\%db'"), is("SHOW DATABASES LIKE 'sharding.%db'"));
+        assertThat(SQLUtil.convertLikePatternToRegex("SHOW DATABASES LIKE 'sharding\\_%db'"), is("SHOW DATABASES LIKE 'sharding_.*db'"));
+    }
 }