!477 添加 1.sqlserver 转义 scheme table colums 包装 根据 . 分割后分别包装 2.SQLserver保留字

Merge pull request !477 from macy0122/main
This commit is contained in:
Michael Yang 2024-07-23 00:02:09 +00:00 committed by Gitee
commit b03cfc6af6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 197 additions and 6 deletions

View File

@ -38,7 +38,6 @@ public class DialectFactory {
* map 用于覆盖系统的方言实现
*/
private static final Map<DbType, IDialect> dialectMap = new EnumMap<>(DbType.class);
/**
* 通过设置当前线程的数据库类型以达到在代码执行时随时切换方言的功能
*/
@ -142,9 +141,9 @@ public class DialectFactory {
case DB2_1005:
return new DB2105Dialect(KeywordWrap.NONE, DB2105Dialect.DB2105LimitOffsetProcessor.DB2105);
case SQLSERVER:
return new CommonsDialectImpl(KeywordWrap.NONE_CASE_SENSITIVE, LimitOffsetProcessor.SQLSERVER);
return new SqlserverDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER);
case SQLSERVER_2005:
return new CommonsDialectImpl(KeywordWrap.NONE_CASE_SENSITIVE, LimitOffsetProcessor.SQLSERVER_2005);
return new Sqlserver2005DialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005);
case INFORMIX:
return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.INFORMIX);
case SINODB:

View File

@ -18,6 +18,7 @@ package com.mybatisflex.core.dialect;
import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.util.StringUtil;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
@ -88,6 +89,7 @@ public class KeywordWrap {
this(false, Collections.emptySet(), prefix, suffix);
}
public KeywordWrap(boolean caseSensitive, String prefix, String suffix) {
this(caseSensitive, Collections.emptySet(), prefix, suffix);
}
@ -103,7 +105,8 @@ public class KeywordWrap {
this.suffix = suffix;
}
public KeywordWrap(boolean caseSensitive, boolean keywordsToUpperCase, Set<String> keywords, String prefix, String suffix) {
public KeywordWrap(boolean caseSensitive, boolean keywordsToUpperCase, Set<String> keywords, String prefix,
String suffix) {
this.caseSensitive = caseSensitive;
this.keywordsToUpperCase = keywordsToUpperCase;
this.keywords = keywords.stream().map(String::toUpperCase).collect(Collectors.toSet());
@ -128,6 +131,37 @@ public class KeywordWrap {
}
}
//数据scheme table 包装 根据 . 分割后分别包装
public String wrapKeyword(String keyword) {
StringBuilder resultBuilder = new StringBuilder();
String[] split = keyword.split("\\.");
if (split != null && split.length > 0) {
Arrays.asList(split)
.forEach(f -> resultBuilder.append(prefix).append(f).append(suffix).append("."));
return resultBuilder.toString().substring(0, resultBuilder.length() - 1);
} else {
return prefix + keyword + suffix;
}
}
//sqlserver 转义 scheme table colums 包装 根据 . 分割后分别包装
public String wrap4Sqlserver(String keyword) {
if (StringUtil.isBlank(keyword) || SqlConsts.ASTERISK.equals(keyword.trim())) {
return keyword;
}
if (caseSensitive || keywords.isEmpty()) {
return wrapKeyword(keyword);
}
if (keywordsToUpperCase) {
keyword = keyword.toUpperCase();
return keywords.contains(keyword) ? wrapKeyword(keyword) : keyword;
} else {
return keywords.contains(keyword.toUpperCase()) ? wrapKeyword(keyword) : keyword;
}
}
public boolean isCaseSensitive() {
return caseSensitive;
}

View File

@ -0,0 +1,51 @@
package com.mybatisflex.core.dialect.impl;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.util.CollectionUtil;
import java.util.Set;
import static com.mybatisflex.core.constant.SqlConsts.ASTERISK;
public class Sqlserver2005DialectImpl extends CommonsDialectImpl {
public static final Set<String> keywords = CollectionUtil.newHashSet("ADD", "ALL", "ALTER", "AND", "ANY", "AS",
"ASC", "AUTHORIZATION", "BACKUP", "BEGIN", "BETWEEN", "BREAK", "BROWSE", "BULK", "BY", "CASCADE", "CASE",
"CHECK", "CHECKPOINT", "CLOSE", "CLUSTERED", "COALESCE", "COLLATE", "COLUMN", "COMMIT", "COMPUTE", "CONSTRAINT",
"CONTAINS", "CONTAINSTABLE", "CONTINUE", "CONVERT", "CREATE", "CROSS", "CURRENT", "CURRENT_DATE",
"CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DATABASE", "DBCC", "DEALLOCATE", "DECLARE",
"DEFAULT", "DELETE", "DENY", "DESC", "DISTINCT", "DISTRIBUTED", "DOUBLE", "DROP", "DUMP", "ELSE", "END",
"ERRLVL", "ESCAPE", "EXCEPT", "EXEC", "EXECUTE", "EXISTS", "EXIT", "EXTERNAL", "FETCH", "FILE", "FILLFACTOR",
"FOR", "FOREIGN", "FREETEXT", "FREETEXTTABLE", "FROM", "FULL", "FUNCTION", "GOTO", "GRANT", "GROUP", "HAVING",
"HOLDLOCK", "IDENTITY", "IDENTITY_INSERT", "IDENTITYCOL", "IF", "IN", "INDEX", "INNER", "INSERT", "INTERSECT",
"INTO", "IS", "JOIN", "KEY", "KILL", "LEFT", "LIKE", "LINENO", "LOAD", "MAX", "MIN", "NATIONAL", "NOCHECK",
"NONCLUSTERED", "NOT", "NULL", "NULLIF", "OF", "OFF", "OFFSETS", "ON", "OPEN", "OPENDATASOURCE", "OPENQUERY",
"OPENROWSET", "OPTION", "OR", "ORDER", "OUTER", "OVER", "PERCENT", "PLAN", "PRECISION", "PREPARE", "PRIMARY",
"PRINT", "PROC", "PROCEDURE", "PUBLIC", "RAISERROR", "READ", "READTEXT", "RECONFIGURE", "REFERENCES",
"REPEATABLE", "RESTORE", "RESTRICT", "RETURN", "REVOKE", "RIGHT", "ROLLBACK", "ROWCOUNT", "ROWGUIDCOL", "RULE",
"SAVE", "SCHEMA", "SECURITYAUDIT", "SELECT", "SESSION_USER", "SET", "SETUSER", "SHUTDOWN", "SOME", "STATISTICS",
"SYSTEM_USER", "TABLE", "TABLESAMPLE", "TEXTSIZE", "THEN", "TO", "TOP", "TRAN", "TRANSACTION", "TRIGGER",
"TRUNCATE", "TSEQUAL", "UNION", "UNIQUE", "UNPIVOT", "UPDATE", "UPDATETEXT", "USE", "USER", "USING", "VALUES",
"VARYING", "VIEW", "WAITFOR", "WHEN", "WHERE", "WHILE", "WITH", "WITHIN GROUP", "WRITETEXT", "XACT_ABORT",
"XLOCK");
public Sqlserver2005DialectImpl() {
this(LimitOffsetProcessor.SQLSERVER_2005);
}
public Sqlserver2005DialectImpl(LimitOffsetProcessor limitOffsetProcessor) {
this(new KeywordWrap(true, false, keywords, "[", "]"), limitOffsetProcessor);
}
public Sqlserver2005DialectImpl(KeywordWrap keywordWrap, LimitOffsetProcessor limitOffsetProcessor) {
super(keywordWrap, limitOffsetProcessor);
}
@Override
public String wrap(String keyword) {
return ASTERISK.equals(keyword) ? keyword : keywordWrap.wrap4Sqlserver(keyword);
}
}

View File

@ -0,0 +1,51 @@
package com.mybatisflex.core.dialect.impl;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.util.CollectionUtil;
import java.util.Set;
import static com.mybatisflex.core.constant.SqlConsts.ASTERISK;
public class SqlserverDialectImpl extends CommonsDialectImpl {
public static final Set<String> keywords = CollectionUtil.newHashSet("ADD", "ALL", "ALTER", "AND", "ANY", "AS",
"ASC", "BACKUP", "BEGIN", "BETWEEN", "BREAK", "BROWSE", "BULK", "BY", "CASCADE", "CASE", "CHECK", "CHECKPOINT",
"CLOSE", "CLUSTERED", "COALESCE", "COLUMN", "COMMIT", "COMMITTED", "COMPUTE", "CONFIRM", "CONNECT",
"CONSTRAINT", "CONTAINS", "CONTAINSTABLE", "CONTINUE", "CONVERT", "CREATE", "CROSS", "CURRENT", "CURRENT_DATE",
"CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DATABASE", "DBCC", "DEALLOCATE", "DECLARE",
"DEFAULT", "DELETE", "DENY", "DESC", "DISTINCT", "DISTRIBUTED", "DOUBLE", "DROP", "DUMP", "ELSE", "END",
"ERRLVL", "ESCAPE", "EXCEPT", "EXEC", "EXECUTE", "EXISTS", "EXIT", "EXTERNAL", "FETCH", "FILE", "FILLFACTOR",
"FOR", "FOREIGN", "FREETEXT", "FREETEXTTABLE", "FROM", "FULL", "FUNCTION", "GOTO", "GRANT", "GROUP", "HAVING",
"HOLDLOCK", "IDENTITY", "IDENTITY_INSERT", "IDENTITYCOL", "IF", "IN", "INDEX", "INNER", "INSERT", "INTERSECT",
"INTO", "IS", "JOIN", "KEY", "KILL", "LEFT", "LIKE", "LINENO", "LOAD", "MAX", "MIN", "NATIONAL", "NOCHECK",
"NONCLUSTERED", "NOT", "NULL", "NULLIF", "OF", "OFF", "OFFSETS", "ON", "OPEN", "OPENDATASOURCE", "OPENQUERY",
"OPENROWSET", "OPTION", "OR", "ORDER", "OUTER", "OVER", "PERCENT", "PIPE", "PLAN", "PRECISION", "PREPARE",
"PRIMARY", "PRINT", "PRIVILEGES", "PROC", "PROCEDURE", "PUBLIC", "RAISERROR", "READ", "READTEXT", "RECONFIGURE",
"REFERENCES", "REPEATABLE", "RESTORE", "RESTRICT", "RETURN", "REVOKE", "RIGHT", "ROLLBACK", "ROWCOUNT",
"ROWGUIDCOL", "RULE", "SAVE", "SCHEMA", "SECURITYAUDIT", "SELECT", "SEMANTICKEYPHRASETABLE",
"SEMANTICSIMILARITYDETAILSTABLE", "SEMANTICSIMILARITYTABLE", "SESSION_USER", "SET", "SETUSER", "SHUTDOWN",
"SOME", "STATISTICS", "SYSTEM_USER", "TABLE", "TABLESAMPLE", "TEXTSIZE", "THEN", "TO", "TOP", "TRAN",
"TRANSACTION", "TRIGGER", "TRUNCATE", "TSEQUAL", "UNION", "UNIQUE", "UNPIVOT", "UPDATE", "UPDATETEXT", "USE",
"USER", "USING", "VALUES", "VARYING", "VIEW", "WAITFOR", "WHEN", "WHERE", "WHILE", "WITH", "WITHIN GROUP",
"WRITETEXT", "XACT_ABORT", "XLOCK");
public SqlserverDialectImpl() {
this(LimitOffsetProcessor.SQLSERVER);
}
public SqlserverDialectImpl(LimitOffsetProcessor limitOffsetProcessor) {
this(new KeywordWrap(true, false, keywords, "[", "]"), limitOffsetProcessor);
}
public SqlserverDialectImpl(KeywordWrap keywordWrap, LimitOffsetProcessor limitOffsetProcessor) {
super(keywordWrap, limitOffsetProcessor);
}
@Override
public String wrap(String keyword) {
return ASTERISK.equals(keyword) ? keyword : keywordWrap.wrap4Sqlserver(keyword);
}
}

View File

@ -20,6 +20,8 @@ import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
import com.mybatisflex.core.dialect.impl.Sqlserver2005DialectImpl;
import com.mybatisflex.core.dialect.impl.SqlserverDialectImpl;
import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Assert;
import org.junit.Test;
@ -42,11 +44,65 @@ public class SqlServer2005DialectTester {
IDialect dialect = new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005);
String sql = dialect.forSelectByQuery(query);
System.out.println(sql);
Assert.assertEquals("WITH temp_datas AS(" +
"SELECT ROW_NUMBER() OVER ( ORDER BY [id] DESC) as __rn, * FROM [tb_account] WHERE [id] IN (?, ?) AND [sex] = ?" +
Assert.assertEquals("WITH temp_datas AS("
+ "SELECT ROW_NUMBER() OVER ( ORDER BY [id] DESC) as __rn, * FROM [tb_account] WHERE [id] IN (?, ?) AND [sex] = ?"
+
") " +
"SELECT * FROM temp_datas WHERE __rn BETWEEN 11 AND 20 ORDER BY __rn", sql);
}
@Test
public void testSelectSqlSqlserver2005() {
QueryWrapper query = new QueryWrapper().select()
.from("TEST.dbo.tb_account")
.where(ACCOUNT.ID.in("100", "200"))
.and(ACCOUNT.SEX.eq(1))
.orderBy(ACCOUNT.ID.desc())
.limit(0, 10);
IDialect dialect = new Sqlserver2005DialectImpl(KeywordWrap.SQUARE_BRACKETS,
LimitOffsetProcessor.SQLSERVER_2005);
String sql = dialect.forSelectByQuery(query);
System.out.println(sql);
Assert.assertEquals(
"WITH temp_datas AS(SELECT ROW_NUMBER() OVER ( ORDER BY [tb_account].[id] DESC) as __rn, * FROM [TEST].[dbo].[tb_account] WHERE [tb_account].[id] IN (?, ?) AND [tb_account].[sex] = ?) SELECT * FROM temp_datas WHERE __rn BETWEEN 1 AND 10 ORDER BY __rn",
sql);
}
@Test
public void testSelectSqlSqlserver() {
QueryWrapper query = new QueryWrapper().select()
.from("TEST.dbo.tb_account")
.where(ACCOUNT.ID.in("100", "200"))
.and(ACCOUNT.SEX.eq(1))
.orderBy(ACCOUNT.ID.desc())
.limit(0, 10);
IDialect dialect = new SqlserverDialectImpl(KeywordWrap.SQUARE_BRACKETS,
LimitOffsetProcessor.SQLSERVER);
String sql = dialect.forSelectByQuery(query);
System.out.println(sql);
Assert.assertEquals(
"SELECT * FROM [TEST].[dbo].[tb_account] WHERE [tb_account].[id] IN (?, ?) AND [tb_account].[sex] = ? ORDER BY [tb_account].[id] DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY",
sql);
}
@Test
public void testSelectSqlSqlserver1() {
QueryWrapper query = new QueryWrapper().select()
.from("tb_account")
.where(ACCOUNT.ID.in("100", "200"))
.and(ACCOUNT.SEX.eq(1))
.orderBy(ACCOUNT.ID.desc())
.limit(0, 10);
IDialect dialect = new SqlserverDialectImpl(KeywordWrap.SQUARE_BRACKETS,
LimitOffsetProcessor.SQLSERVER);
String sql = dialect.forSelectByQuery(query);
System.out.println(sql);
Assert.assertEquals(
"SELECT * FROM [tb_account] WHERE [id] IN (?, ?) AND [sex] = ? ORDER BY [id] DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY",
sql);
}
}