You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2023/06/09 03:34:58 UTC
[shardingsphere] branch master updated: Support table name backquote parse (#26079)
This is an automated email from the ASF dual-hosted git repository.
jianglongtao 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 0ad2e2237ef Support table name backquote parse (#26079)
0ad2e2237ef is described below
commit 0ad2e2237ef5ce6e41308f0f71fc8c3f663b9717
Author: niu niu <zi...@aliyun.com>
AuthorDate: Fri Jun 9 11:34:50 2023 +0800
Support table name backquote parse (#26079)
* Support table name backquote parse (#26035)
* Add method Handle the actual table name enclosed in backticks (#26035)
* Format code (#26035)
---
.../src/main/antlr4/imports/mysql/BaseRule.g4 | 1 +
.../src/main/antlr4/imports/mysql/Literals.g4 | 4 ++
.../sql/parser/sql/common/util/SQLUtils.java | 54 +++++++++++++++++-----
.../sql/parser/sql/common/util/SQLUtilsTest.java | 16 +++++++
.../src/main/resources/case/ddl/create-table.xml | 12 +++++
.../resources/sql/supported/ddl/create-table.xml | 2 +
6 files changed, 78 insertions(+), 11 deletions(-)
diff --git a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4 b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
index f92077d5075..41e4331fd13 100644
--- a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
+++ b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
@@ -113,6 +113,7 @@ identifier
| customKeyword
| DOUBLE_QUOTED_TEXT
| UNDERSCORE_CHARSET
+ | BQUOTA_STRING
;
identifierKeywordsUnambiguous
diff --git a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4 b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4
index fe0b64e9cc1..ae3814a59a5 100644
--- a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4
+++ b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/Literals.g4
@@ -31,6 +31,10 @@ DOUBLE_QUOTED_TEXT
: DQ_ ( '\\'. | '""' | ~('"'| '\\') )* DQ_
;
+BQUOTA_STRING
+ : BQ_ ( '\\'. | '``' | ~('`'|'\\'))* BQ_
+ ;
+
NCHAR_TEXT
: N SINGLE_QUOTED_TEXT
;
diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtils.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtils.java
index 3149587f9e6..84914583e0a 100644
--- a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtils.java
+++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtils.java
@@ -47,13 +47,15 @@ import java.util.regex.Pattern;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class SQLUtils {
+ private static final String BACKTICK = "`";
+
private static final String SQL_END = ";";
private static final String COMMENT_PREFIX = "/*";
private static final String COMMENT_SUFFIX = "*/";
- private static final String EXCLUDED_CHARACTERS = "[]`'\"";
+ private static final String EXCLUDED_CHARACTERS = "[]'\"";
private static final Pattern SINGLE_CHARACTER_PATTERN = Pattern.compile("([^\\\\])_|^_");
@@ -91,14 +93,14 @@ public final class SQLUtils {
/**
* Get exactly value for SQL expression.
- *
+ *
* <p>remove special char for SQL expression</p>
- *
+ *
* @param value SQL expression
* @return exactly SQL expression
*/
public static String getExactlyValue(final String value) {
- return null == value ? null : CharMatcher.anyOf(EXCLUDED_CHARACTERS).removeFrom(value);
+ return null == value ? null : tryGetRealContentInBackticks(CharMatcher.anyOf(EXCLUDED_CHARACTERS).removeFrom(value));
}
/**
@@ -106,7 +108,7 @@ public final class SQLUtils {
*
* <p>remove special char for SQL expression</p>
*
- * @param value SQL expression
+ * @param value SQL expression
* @param reservedCharacters characters to be reserved
* @return exactly SQL expression
*/
@@ -118,6 +120,36 @@ public final class SQLUtils {
return CharMatcher.anyOf(toBeExcludedCharacters).removeFrom(value);
}
+ /**
+ * Try get exactly value for backticks string.
+ *
+ * <p>try get content containing backticks exactly value</p>
+ *
+ * @param value SQL expression
+ * @return exactly SQL expression
+ */
+ public static String tryGetRealContentInBackticks(final String value) {
+ if (null == value) {
+ return null;
+ }
+ if (value.startsWith(BACKTICK) && value.endsWith(BACKTICK)) {
+ int startIndex = 1;
+ int stopIndex = value.length() - 1;
+ StringBuilder exactlyTableName = new StringBuilder();
+ while (startIndex < stopIndex) {
+ if (value.charAt(startIndex) == '`' && (startIndex + 1 >= stopIndex || value.charAt(startIndex + 1) != '`')) {
+ return value;
+ } else if (value.charAt(startIndex) == '`' && value.charAt(startIndex + 1) == '`') {
+ startIndex++;
+ }
+ exactlyTableName.append(value.charAt(startIndex));
+ startIndex++;
+ }
+ return 0 == exactlyTableName.length() ? value : exactlyTableName.toString();
+ }
+ return value;
+ }
+
/**
* Get exactly SQL expression.
*
@@ -132,7 +164,7 @@ public final class SQLUtils {
/**
* Get exactly SQL expression without outside parentheses.
- *
+ *
* @param value SQL expression
* @return exactly SQL expression
*/
@@ -186,11 +218,11 @@ public final class SQLUtils {
/**
* Create literal expression.
- *
- * @param astNode AST node
+ *
+ * @param astNode AST node
* @param startIndex start index
- * @param stopIndex stop index
- * @param text text
+ * @param stopIndex stop index
+ * @param text text
* @return literal expression segment
*/
public static ExpressionSegment createLiteralExpression(final ASTNode astNode, final int startIndex, final int stopIndex, final String text) {
@@ -241,7 +273,7 @@ public final class SQLUtils {
/**
* Convert like pattern to regex.
- *
+ *
* @param pattern like pattern
* @return regex
*/
diff --git a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilsTest.java b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilsTest.java
index edf9e76527d..e42168eab41 100644
--- a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilsTest.java
+++ b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtilsTest.java
@@ -63,6 +63,8 @@ class SQLUtilsTest {
assertThat(SQLUtils.getExactlyValue("[xxx]"), is("xxx"));
assertThat(SQLUtils.getExactlyValue("\"xxx\""), is("xxx"));
assertThat(SQLUtils.getExactlyValue("'xxx'"), is("xxx"));
+ assertThat(SQLUtils.getExactlyValue("`[xxx`"), is("xxx"));
+ assertThat(SQLUtils.getExactlyValue("```[xxx```"), is("`xxx`"));
}
@Test
@@ -153,4 +155,18 @@ class SQLUtilsTest {
assertThat(SQLUtils.trimComment("/* This is a query with a semicolon */ SHOW DATABASES;"), is("SHOW DATABASES"));
assertThat(SQLUtils.trimComment("/* This is a query with spaces */ SHOW DATABASES "), is("SHOW DATABASES"));
}
+
+ @Test
+ void assertTryGetRealContentInBackticks() {
+ assertThat(SQLUtils.tryGetRealContentInBackticks("`"), is("`"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("``"), is("``"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("```"), is("```"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("t_order"), is("t_order"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("````"), is("`"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("`t_order`"), is("t_order"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("```t_order`"), is("`t_order"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("```````t_order```````"), is("```t_order```"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("``t_order`"), is("``t_order`"));
+ assertThat(SQLUtils.tryGetRealContentInBackticks("`````t_o``r``d``e``r```"), is("``t_o`r`d`e`r`"));
+ }
}
diff --git a/test/it/parser/src/main/resources/case/ddl/create-table.xml b/test/it/parser/src/main/resources/case/ddl/create-table.xml
index 3a9e2d2e587..3830944e75f 100644
--- a/test/it/parser/src/main/resources/case/ddl/create-table.xml
+++ b/test/it/parser/src/main/resources/case/ddl/create-table.xml
@@ -17,6 +17,18 @@
-->
<sql-parser-test-cases>
+ <create-table sql-case-id="create_table_with_backtick">
+ <table name="`t_order" start-delimiter="`" end-delimiter="`" start-index="13" stop-index="23" />
+ <column-definition type="int" start-index="26" stop-index="30">
+ <column name="i" />
+ </column-definition>
+ </create-table>
+ <create-table sql-case-id="create_table_column_with_backtick">
+ <table name="``t_o`r`d`e`r`" start-delimiter="`" end-delimiter="`" start-index="13" stop-index="35" />
+ <column-definition type="int" start-delimiter="`" end-delimiter="`" start-index="38" stop-index="46">
+ <column name="`i" />
+ </column-definition>
+ </create-table>
<create-table sql-case-id="create_table_with_like">
<table name="t_log" start-index="13" stop-index="17" />
<like-table name="t_old_log" start-index="24" stop-index="32" />
diff --git a/test/it/parser/src/main/resources/sql/supported/ddl/create-table.xml b/test/it/parser/src/main/resources/sql/supported/ddl/create-table.xml
index e87dab54f58..c67da6bc605 100644
--- a/test/it/parser/src/main/resources/sql/supported/ddl/create-table.xml
+++ b/test/it/parser/src/main/resources/sql/supported/ddl/create-table.xml
@@ -17,6 +17,8 @@
-->
<sql-cases>
+ <sql-case id="create_table_with_backtick" value="CREATE TABLE ```t_order` (i int)" db-types="MySQL" />
+ <sql-case id="create_table_column_with_backtick" value="create table `````t_o``r``d``e``r``` (```i` int)" db-types="MySQL" />
<sql-case id="create_table_with_like" value="CREATE TABLE t_log LIKE t_old_log" db-types="MySQL" />
<sql-case id="create_table" value="CREATE TABLE t_log(id int PRIMARY KEY, status varchar(10))" />
<sql-case id="create_table_with_engin_charset" value="CREATE TABLE t_log(id int PRIMARY KEY, status varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" db-types="MySQL" />