mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-06 16:48:24 +08:00
!477 添加 1.sqlserver 转义 scheme table colums 包装 根据 . 分割后分别包装 2.SQLserver保留字
Merge pull request !477 from macy0122/main
This commit is contained in:
commit
b03cfc6af6
@ -38,7 +38,6 @@ public class DialectFactory {
|
|||||||
* 此 map 中,用于覆盖系统的方言实现
|
* 此 map 中,用于覆盖系统的方言实现
|
||||||
*/
|
*/
|
||||||
private static final Map<DbType, IDialect> dialectMap = new EnumMap<>(DbType.class);
|
private static final Map<DbType, IDialect> dialectMap = new EnumMap<>(DbType.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过设置当前线程的数据库类型,以达到在代码执行时随时切换方言的功能
|
* 通过设置当前线程的数据库类型,以达到在代码执行时随时切换方言的功能
|
||||||
*/
|
*/
|
||||||
@ -142,9 +141,9 @@ public class DialectFactory {
|
|||||||
case DB2_1005:
|
case DB2_1005:
|
||||||
return new DB2105Dialect(KeywordWrap.NONE, DB2105Dialect.DB2105LimitOffsetProcessor.DB2105);
|
return new DB2105Dialect(KeywordWrap.NONE, DB2105Dialect.DB2105LimitOffsetProcessor.DB2105);
|
||||||
case SQLSERVER:
|
case SQLSERVER:
|
||||||
return new CommonsDialectImpl(KeywordWrap.NONE_CASE_SENSITIVE, LimitOffsetProcessor.SQLSERVER);
|
return new SqlserverDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER);
|
||||||
case SQLSERVER_2005:
|
case SQLSERVER_2005:
|
||||||
return new CommonsDialectImpl(KeywordWrap.NONE_CASE_SENSITIVE, LimitOffsetProcessor.SQLSERVER_2005);
|
return new Sqlserver2005DialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005);
|
||||||
case INFORMIX:
|
case INFORMIX:
|
||||||
return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.INFORMIX);
|
return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.INFORMIX);
|
||||||
case SINODB:
|
case SINODB:
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package com.mybatisflex.core.dialect;
|
|||||||
import com.mybatisflex.core.constant.SqlConsts;
|
import com.mybatisflex.core.constant.SqlConsts;
|
||||||
import com.mybatisflex.core.util.StringUtil;
|
import com.mybatisflex.core.util.StringUtil;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -88,6 +89,7 @@ public class KeywordWrap {
|
|||||||
this(false, Collections.emptySet(), prefix, suffix);
|
this(false, Collections.emptySet(), prefix, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public KeywordWrap(boolean caseSensitive, String prefix, String suffix) {
|
public KeywordWrap(boolean caseSensitive, String prefix, String suffix) {
|
||||||
this(caseSensitive, Collections.emptySet(), prefix, suffix);
|
this(caseSensitive, Collections.emptySet(), prefix, suffix);
|
||||||
}
|
}
|
||||||
@ -103,7 +105,8 @@ public class KeywordWrap {
|
|||||||
this.suffix = suffix;
|
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.caseSensitive = caseSensitive;
|
||||||
this.keywordsToUpperCase = keywordsToUpperCase;
|
this.keywordsToUpperCase = keywordsToUpperCase;
|
||||||
this.keywords = keywords.stream().map(String::toUpperCase).collect(Collectors.toSet());
|
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() {
|
public boolean isCaseSensitive() {
|
||||||
return caseSensitive;
|
return caseSensitive;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -20,6 +20,8 @@ import com.mybatisflex.core.dialect.IDialect;
|
|||||||
import com.mybatisflex.core.dialect.KeywordWrap;
|
import com.mybatisflex.core.dialect.KeywordWrap;
|
||||||
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
|
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
|
||||||
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
|
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 com.mybatisflex.core.query.QueryWrapper;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -42,11 +44,65 @@ public class SqlServer2005DialectTester {
|
|||||||
IDialect dialect = new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005);
|
IDialect dialect = new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005);
|
||||||
String sql = dialect.forSelectByQuery(query);
|
String sql = dialect.forSelectByQuery(query);
|
||||||
System.out.println(sql);
|
System.out.println(sql);
|
||||||
Assert.assertEquals("WITH temp_datas AS(" +
|
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 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);
|
"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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user