mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser. support show columns.
This commit is contained in:
+25
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package com.alibaba.druid.sql.dialect.mysql.ast.statement;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLCommentHint;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
@@ -30,6 +32,7 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlShowColumnOutpuVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
@@ -174,4 +177,26 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
|
||||
tableOptions.clear();
|
||||
super.simplify();
|
||||
}
|
||||
|
||||
public void showCoumns(Appendable out) throws IOException {
|
||||
this.accept(new MySqlShowColumnOutpuVisitor(out));
|
||||
}
|
||||
|
||||
public boolean apply(MySqlRenameTableStatement x) {
|
||||
for (MySqlRenameTableStatement.Item item : x.getItems()) {
|
||||
if (apply(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean apply(MySqlRenameTableStatement.Item item) {
|
||||
if (!SQLUtils.nameEquals((SQLName) item.getName(), this.getName())) {
|
||||
return false;
|
||||
}
|
||||
this.setName((SQLName) item.getTo().clone());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ public class MySqlSelectParser extends SQLSelectParser {
|
||||
|
||||
queryBlock.setForUpdate(true);
|
||||
|
||||
if (identifierEquals("NO_WAIT")) {
|
||||
if (identifierEquals("NO_WAIT") || identifierEquals("NOWAIT")) {
|
||||
lexer.nextToken();
|
||||
queryBlock.setNoWait(true);
|
||||
} else if (identifierEquals("WAIT")) {
|
||||
|
||||
@@ -306,7 +306,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
println();
|
||||
print0(ucase ? "FOR UPDATE" : "for update");
|
||||
if (x.isNoWait()) {
|
||||
print0(ucase ? " NO_WAIT" : " no_wait");
|
||||
print0(ucase ? " NOWAIT" : " nowait");
|
||||
} else if (x.getWaitTime() != null) {
|
||||
print0(ucase ? " WAIT " : " wait ");
|
||||
x.getWaitTime().accept(this);
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
package com.alibaba.druid.sql.dialect.mysql.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 27/07/2017.
|
||||
*/
|
||||
public class MySqlShowColumnOutpuVisitor extends MySqlOutputVisitor {
|
||||
public MySqlShowColumnOutpuVisitor(Appendable appender) {
|
||||
super(appender);
|
||||
}
|
||||
|
||||
public boolean visit(MySqlCreateTableStatement x) {
|
||||
List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();
|
||||
List<String> dataTypes = new ArrayList<String>();
|
||||
List<String> defaultValues = new ArrayList<String>();
|
||||
|
||||
int name_len = -1, dataType_len = -1, defaultVal_len = -1, extra_len = 5;
|
||||
for (SQLTableElement element : x.getTableElementList()) {
|
||||
if (element instanceof SQLColumnDefinition) {
|
||||
SQLColumnDefinition column = (SQLColumnDefinition) element;
|
||||
columns.add(column);
|
||||
|
||||
String name = SQLUtils.normalize(column.getName().getSimpleName());
|
||||
if (name_len < name.length()) {
|
||||
name_len = name.length();
|
||||
}
|
||||
|
||||
String dataType = column.getDataType().getName();
|
||||
if (column.getDataType().getArguments().size() > 0) {
|
||||
dataType += "(";
|
||||
for (int i = 0; i < column.getDataType().getArguments().size(); i++) {
|
||||
if (i != 0) {
|
||||
dataType += ",";
|
||||
}
|
||||
SQLExpr arg = column.getDataType().getArguments().get(i);
|
||||
dataType += arg.toString();
|
||||
}
|
||||
dataType += ")";
|
||||
}
|
||||
|
||||
if (dataType_len < dataType.length()) {
|
||||
dataType_len = dataType.length();
|
||||
}
|
||||
dataTypes.add(dataType);
|
||||
|
||||
if (column.getDefaultExpr() == null) {
|
||||
defaultValues.add(null);
|
||||
} else {
|
||||
String defaultVal = SQLUtils.toMySqlString(column.getDefaultExpr());
|
||||
if (defaultVal.length() > 2 && defaultVal.charAt(0) == '\'' && defaultVal.charAt(defaultVal.length() - 1) == '\'') {
|
||||
defaultVal = defaultVal.substring(1, defaultVal.length() - 1);
|
||||
}
|
||||
defaultValues.add(defaultVal);
|
||||
|
||||
if (defaultVal_len < defaultVal.length()) {
|
||||
defaultVal_len = defaultVal.length();
|
||||
}
|
||||
}
|
||||
|
||||
if (column.isAutoIncrement()) {
|
||||
extra_len = "auto_increment".length();
|
||||
} else if (column.getOnUpdate() != null) {
|
||||
extra_len = "on update CURRENT_TIMESTAMP".length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("+-");
|
||||
print('-', name_len);
|
||||
print("-+-");
|
||||
print('-', dataType_len);
|
||||
print("-+------+-----+-");
|
||||
print('-', defaultVal_len);
|
||||
print("-+-");
|
||||
print('-', extra_len);
|
||||
print("-+\n");
|
||||
|
||||
print("| ");
|
||||
print("Field", name_len, ' ');
|
||||
print(" | ");
|
||||
print("Type", dataType_len, ' ');
|
||||
print(" | Null | Key | ");
|
||||
print("Default", defaultVal_len, ' ');
|
||||
print(" | ");
|
||||
print("Extra", extra_len, ' ');
|
||||
print(" |\n");
|
||||
|
||||
print("+-");
|
||||
print('-', name_len);
|
||||
print("-+-");
|
||||
print('-', dataType_len);
|
||||
print("-+------+-----+-");
|
||||
print('-', defaultVal_len);
|
||||
print("-+-");
|
||||
print('-', extra_len);
|
||||
print("-+\n");
|
||||
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
SQLColumnDefinition column = columns.get(i);
|
||||
String name = SQLUtils.normalize(column.getName().getSimpleName());
|
||||
|
||||
print("| ");
|
||||
print(name, name_len, ' ');
|
||||
print(" | ");
|
||||
|
||||
print(dataTypes.get(i), dataType_len, ' ');
|
||||
print(" | ");
|
||||
|
||||
if (column.containsNotNullConstaint()) {
|
||||
print("YES");
|
||||
} else {
|
||||
print("NO ");
|
||||
}
|
||||
print(" | ");
|
||||
|
||||
MySqlUnique unique = null;
|
||||
if (x.isPrimaryColumn(name)) {
|
||||
print("PRI");
|
||||
} else if (x.isUNI(name)) {
|
||||
print("UNI");
|
||||
} else if (x.isMUL(name)) {
|
||||
print("MUL");
|
||||
} else {
|
||||
print(" ");
|
||||
}
|
||||
print(" | ");
|
||||
|
||||
String defaultVal = defaultValues.get(i);
|
||||
if (defaultVal == null) {
|
||||
print("NULL", defaultVal_len, ' ');
|
||||
} else {
|
||||
print(defaultVal, defaultVal_len, ' ');
|
||||
}
|
||||
print(" | ");
|
||||
|
||||
if (column.isAutoIncrement()) {
|
||||
print("auto_increment", extra_len, ' ');
|
||||
} else if (column.getOnUpdate() != null) {
|
||||
print("on update CURRENT_TIMESTAMP", extra_len, ' ');
|
||||
} else {
|
||||
print(' ', extra_len);
|
||||
}
|
||||
print(" |");
|
||||
print("\n");
|
||||
}
|
||||
print("+-");
|
||||
print('-', name_len);
|
||||
print("-+-");
|
||||
print('-', dataType_len);
|
||||
print("-+------+-----+-");
|
||||
print('-', defaultVal_len);
|
||||
print("-+-");
|
||||
print('-', extra_len);
|
||||
print("-+\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void print(char ch, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
print(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void print(String text, int columnSize, char ch) {
|
||||
print(text);
|
||||
print(' ', columnSize - text.length());
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 1999-2017 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.sql.dialect.mysql.visitor.transform;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.expr.*;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 26/07/2017.
|
||||
*/
|
||||
public class NameResolveVisitor extends OracleASTVisitorAdapter {
|
||||
public boolean visit(SQLIdentifierExpr x) {
|
||||
SQLObject parent = x.getParent();
|
||||
String name = x.getName();
|
||||
|
||||
if ("ROWNUM".equalsIgnoreCase(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent instanceof SQLPropertyExpr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (; parent != null; parent = parent.getParent()) {
|
||||
if (parent instanceof SQLTableSource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent instanceof SQLSelectQueryBlock) {
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;
|
||||
|
||||
if (queryBlock.getInto() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (queryBlock.getParent() instanceof SQLSelect) {
|
||||
SQLObject pp = queryBlock.getParent().getParent();
|
||||
if (pp instanceof SQLInSubQueryExpr || pp instanceof SQLExistsExpr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SQLTableSource from = queryBlock.getFrom();
|
||||
if (from instanceof SQLExprTableSource || from instanceof SQLSubqueryTableSource) {
|
||||
String alias = from.getAlias();
|
||||
if (alias != null) {
|
||||
SQLUtils.replaceInParent(x, new SQLPropertyExpr(alias, name));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 1999-2017 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.sql.dialect.mysql.visitor.transform;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderBy;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 27/07/2017.
|
||||
*/
|
||||
public class OrderByResolve extends OracleASTVisitorAdapter {
|
||||
public boolean visit(SQLSelect x) {
|
||||
SQLSelectQueryBlock queryBlock = x.getQueryBlock();
|
||||
if (queryBlock == null) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
if (x.getOrderBy() != null && queryBlock.isForUpdate() && queryBlock.getOrderBy() == null) {
|
||||
queryBlock.setOrderBy(x.getOrderBy());
|
||||
x.setOrderBy(null);
|
||||
}
|
||||
|
||||
SQLOrderBy orderBy = queryBlock.getOrderBy();
|
||||
if (orderBy == null) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
List<SQLSelectOrderByItem> notContainsOrderBy = new ArrayList<SQLSelectOrderByItem>();
|
||||
for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) {
|
||||
SQLExpr orderByExpr = orderByItem.getExpr();
|
||||
if (queryBlock.selectIndexOf(orderByExpr) == -1) {
|
||||
notContainsOrderBy.add(orderByItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (notContainsOrderBy.size() > 0) {
|
||||
for (SQLSelectOrderByItem orderByItem : notContainsOrderBy) {
|
||||
queryBlock.addSelectItem(orderByItem.getExpr());
|
||||
}
|
||||
|
||||
OracleSelectQueryBlock queryBlock1 = new OracleSelectQueryBlock();
|
||||
queryBlock1.setFrom(queryBlock, "x");
|
||||
x.setQuery(queryBlock1);
|
||||
}
|
||||
|
||||
return super.visit(x);
|
||||
}
|
||||
}
|
||||
@@ -134,6 +134,10 @@ public class PGExprParser extends SQLExprParser {
|
||||
|
||||
if (expr.getClass() == SQLIdentifierExpr.class) {
|
||||
String ident = ((SQLIdentifierExpr)expr).getName();
|
||||
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
return super.primaryRest(expr);
|
||||
}
|
||||
|
||||
if ("TIMESTAMP".equalsIgnoreCase(ident)) {
|
||||
if (lexer.token() != Token.LITERAL_ALIAS //
|
||||
|
||||
Reference in New Issue
Block a user