From e12d64c07b84826ba15dfdb6581d1ed9e509619e Mon Sep 17 00:00:00 2001 From: zyc Date: Fri, 3 Feb 2023 15:23:07 +0800 Subject: [PATCH 1/2] fix SQL SERVER ALTER TABLE ADD COLUMN BUG. --- .../druid/sql/parser/SQLStatementParser.java | 3 ++ .../druid/sql/parser/SqlserverAlterTest.java | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 core/src/test/java/com/alibaba/druid/sql/parser/SqlserverAlterTest.java diff --git a/core/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/core/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index c88ae88fe9..04aa03b5ca 100644 --- a/core/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -2494,6 +2494,9 @@ public class SQLStatementParser extends SQLParser { SQLConstraint constraint = this.exprParser.parseConstaint(); SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(constraint); stmt.addItem(item); + } else if (lexer.token == LITERAL_ALIAS && dbType == DbType.sqlserver) { + SQLAlterTableAddColumn item = parseAlterTableAddColumn(); + stmt.addItem(item); } else { throw new ParserException("TODO " + lexer.info()); } diff --git a/core/src/test/java/com/alibaba/druid/sql/parser/SqlserverAlterTest.java b/core/src/test/java/com/alibaba/druid/sql/parser/SqlserverAlterTest.java new file mode 100644 index 0000000000..10f3bcae17 --- /dev/null +++ b/core/src/test/java/com/alibaba/druid/sql/parser/SqlserverAlterTest.java @@ -0,0 +1,33 @@ +package com.alibaba.druid.sql.parser; + +import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import junit.framework.TestCase; +import org.junit.Assert; + +/** + * Created by zyc@byshell.org on 2016/8/16. + */ +public class SqlserverAlterTest extends TestCase { + public void testAlter1() { + String sql = "alter table alert_config_detail\n" + " add age14 int"; + SQLStatementParser parser = new SQLServerStatementParser(sql); + SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatement(); // + try { + stmt.toString(); + } catch (ClassCastException e) { + Assert.fail(e.getMessage()); + } + } + + public void testAlter2() { + String sql = "ALTER TABLE \"console\".\"dbo\".\"alert_config_detail\"\n" + "\tADD \"age14\" int"; + SQLStatementParser parser = new SQLServerStatementParser(sql); + SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatement(); // + try { + stmt.toString(); + } catch (ClassCastException e) { + Assert.fail(e.getMessage()); + } + } +} From 505fc118aef5ff6a53da839784897e7838687eeb Mon Sep 17 00:00:00 2001 From: zyc Date: Wed, 8 Feb 2023 15:10:31 +0800 Subject: [PATCH 2/2] SchemaRepository support SQL SERVER. --- .../druid/sql/parser/SQLParserUtils.java | 2 +- .../sql/repository/SchemaRepository.java | 86 ++++++++++++++++++- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java b/core/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java index 6c77d3761a..1d91227844 100644 --- a/core/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java +++ b/core/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java @@ -123,7 +123,7 @@ public class SQLParserUtils { return new PGSQLStatementParser(sql, features); case sqlserver: case jtds: - return new SQLServerStatementParser(sql); + return new SQLServerStatementParser(sql, features); case h2: return new H2StatementParser(sql, features); case blink: diff --git a/core/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java b/core/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java index af03ed671d..ebf3f4edb6 100644 --- a/core/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java +++ b/core/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java @@ -33,6 +33,8 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStateme import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter; +import com.alibaba.druid.sql.parser.SQLParserFeature; import com.alibaba.druid.sql.repository.function.Function; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; @@ -86,6 +88,9 @@ public class SchemaRepository { case oracle: consoleVisitor = new OracleConsoleSchemaVisitor(); break; + case sqlserver: + consoleVisitor = new SqlServerConsoleSchemaVisitor(); + break; default: consoleVisitor = new DefaultConsoleSchemaVisitor(); break; @@ -460,7 +465,7 @@ public class SchemaRepository { try { StringBuffer buf = new StringBuffer(); - List stmtList = SQLUtils.parseStatements(input, dbType); + List stmtList = SQLUtils.parseStatements(input, dbType, SQLParserFeature.IgnoreNameQuotes); for (SQLStatement stmt : stmtList) { if (stmt instanceof SQLShowColumnsStatement) { @@ -823,6 +828,73 @@ public class SchemaRepository { } } + public class SqlServerConsoleSchemaVisitor extends SQLServerASTVisitorAdapter { + public SqlServerConsoleSchemaVisitor() { + this.dbType = DbType.sqlserver; + } + + public boolean visit(SQLDropSequenceStatement x) { + acceptDropSequence(x); + return false; + } + + public boolean visit(SQLCreateSequenceStatement x) { + acceptCreateSequence(x); + return false; + } + + public boolean visit(OracleCreateTableStatement x) { + visit((SQLCreateTableStatement) x); + return false; + } + + public boolean visit(SQLCreateTableStatement x) { + acceptCreateTable(x); + return false; + } + + public boolean visit(SQLDropTableStatement x) { + acceptDropTable(x); + return false; + } + + public boolean visit(SQLCreateViewStatement x) { + acceptView(x); + return false; + } + + public boolean visit(SQLAlterViewStatement x) { + acceptView(x); + return false; + } + + public boolean visit(SQLCreateIndexStatement x) { + acceptCreateIndex(x); + return false; + } + + public boolean visit(SQLCreateFunctionStatement x) { + acceptCreateFunction(x); + return false; + } + + public boolean visit(SQLAlterTableStatement x) { + acceptAlterTable(x); + return false; + } + + public boolean visit(SQLUseStatement x) { + String schema = x.getDatabase().getSimpleName(); + setDefaultSchema(schema); + return false; + } + + public boolean visit(SQLDropIndexStatement x) { + acceptDropIndex(x); + return false; + } + } + public class DefaultConsoleSchemaVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLDropSequenceStatement x) { acceptDropSequence(x); @@ -1090,8 +1162,18 @@ public class SchemaRepository { boolean acceptAlterTable(SQLAlterTableStatement x) { String schemaName = x.getSchema(); - Schema schema = findSchema(schemaName, true); + if (dbType == DbType.sqlserver) { + SQLName tableName = x.getTableSource().getName(); + if (tableName instanceof SQLPropertyExpr) { + SQLExpr owner = ((SQLPropertyExpr) tableName).getOwner(); + if (owner instanceof SQLPropertyExpr) { + schemaName = ((SQLPropertyExpr) owner).getName(); + } + } + } + + Schema schema = findSchema(schemaName, true); SchemaObject object = schema.findTable(x.nameHashCode64()); if (object != null) { SQLCreateTableStatement stmt = (SQLCreateTableStatement) object.getStatement();