mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser. add new feature JdbcUtils.getCreateTableScript, for issue #1342
This commit is contained in:
@@ -42,9 +42,7 @@ import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import com.alibaba.druid.util.StringUtils;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import com.alibaba.druid.util.*;
|
||||
|
||||
public class SQLUtils {
|
||||
public static FormatOption DEFAULT_FORMAT_OPTION = new FormatOption(true, true);
|
||||
@@ -774,6 +772,10 @@ public class SQLUtils {
|
||||
}
|
||||
|
||||
public static String normalize(String name) {
|
||||
return normalize(name, null);
|
||||
}
|
||||
|
||||
public static String normalize(String name, String dbType) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -782,7 +784,19 @@ public class SQLUtils {
|
||||
char c0 = name.charAt(0);
|
||||
char x0 = name.charAt(name.length() - 1);
|
||||
if ((c0 == '"' && x0 == '"') || (c0 == '`' && x0 == '`')) {
|
||||
name = name.substring(1, name.length() - 1);
|
||||
String normalizeName = name.substring(1, name.length() - 1);
|
||||
|
||||
if (JdbcConstants.ORACLE.equals(dbType)) {
|
||||
if (OracleUtils.isKeyword(normalizeName)) {
|
||||
return name;
|
||||
}
|
||||
} else if (JdbcConstants.MYSQL.equals(dbType)) {
|
||||
if (MySqlUtils.isKeyword(normalizeName)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return normalizeName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public abstract class SQLStatementImpl extends SQLObjectImpl implements SQLStatement {
|
||||
|
||||
private String dbType;
|
||||
protected String dbType;
|
||||
|
||||
private boolean afterSemi;
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@ import com.alibaba.druid.sql.ast.SQLObjectImpl;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement {
|
||||
protected String dbType;
|
||||
|
||||
protected SQLName name;
|
||||
protected SQLDataType dataType;
|
||||
@@ -287,6 +289,7 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen
|
||||
|
||||
public SQLColumnDefinition clone() {
|
||||
SQLColumnDefinition x = new SQLColumnDefinition();
|
||||
x.setDbType(dbType);
|
||||
|
||||
if(name != null) {
|
||||
x.setName(name.clone());
|
||||
@@ -341,4 +344,26 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
public void setDbType(String dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public void simplify() {
|
||||
enable = null;
|
||||
validate = null;
|
||||
rely = null;
|
||||
|
||||
|
||||
if (this.name instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr identExpr = (SQLIdentifierExpr) this.name;
|
||||
String columnName = identExpr.getName();
|
||||
columnName = SQLUtils.normalize(columnName, dbType);
|
||||
identExpr.setName(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,6 @@ public interface SQLConstraint extends SQLObject {
|
||||
SQLName getName();
|
||||
|
||||
void setName(SQLName value);
|
||||
|
||||
void simplify();
|
||||
}
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package com.alibaba.druid.sql.ast.statement;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLCommentHint;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObjectImpl;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class SQLConstraintImpl extends SQLObjectImpl implements SQLConstraint {
|
||||
protected String dbType;
|
||||
|
||||
protected SQLName name;
|
||||
private Boolean enable;
|
||||
@@ -90,4 +93,21 @@ public abstract class SQLConstraintImpl extends SQLObjectImpl implements SQLCons
|
||||
public void setRely(Boolean rely) {
|
||||
this.rely = rely;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
public void setDbType(String dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public void simplify() {
|
||||
if (this.name instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr identExpr = (SQLIdentifierExpr) this.name;
|
||||
String columnName = identExpr.getName();
|
||||
columnName = SQLUtils.normalize(columnName, dbType);
|
||||
identExpr.setName(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ import java.util.*;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.*;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import com.alibaba.druid.util.ListDG;
|
||||
import com.alibaba.druid.util.lang.Consumer;
|
||||
import org.apache.ibatis.jdbc.SQL;
|
||||
|
||||
public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLStatement {
|
||||
|
||||
@@ -59,6 +61,10 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
|
||||
this.setTableSource(new SQLExprTableSource(name));
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.setName(new SQLIdentifierExpr(name));
|
||||
}
|
||||
|
||||
public SQLExprTableSource getTableSource() {
|
||||
return tableSource;
|
||||
}
|
||||
@@ -414,4 +420,37 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void simplify() {
|
||||
SQLName name = getName();
|
||||
if (name instanceof SQLPropertyExpr) {
|
||||
String tableName = ((SQLPropertyExpr) name).getName();
|
||||
tableName = SQLUtils.normalize(tableName);
|
||||
setName(tableName);
|
||||
name = getName();
|
||||
}
|
||||
|
||||
if (name instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr identExpr = (SQLIdentifierExpr) name;
|
||||
String tableName = identExpr.getName();
|
||||
tableName = SQLUtils.normalize(tableName, dbType);
|
||||
identExpr.setName(tableName);
|
||||
}
|
||||
|
||||
if (name instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr identExpr = (SQLIdentifierExpr) name;
|
||||
String tableName = identExpr.getName();
|
||||
tableName = SQLUtils.normalize(tableName);
|
||||
identExpr.setName(tableName);
|
||||
}
|
||||
|
||||
for (SQLTableElement element : this.tableElementList) {
|
||||
if (element instanceof SQLColumnDefinition) {
|
||||
SQLColumnDefinition column = (SQLColumnDefinition) element;
|
||||
column.simplify();
|
||||
} else if (element instanceof SQLConstraint) {
|
||||
((SQLConstraint) element).simplify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ package com.alibaba.druid.sql.ast.statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint, SQLTableElement {
|
||||
@@ -58,4 +60,17 @@ public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint,
|
||||
x.addColumn(columnClone);
|
||||
}
|
||||
}
|
||||
|
||||
public void simplify() {
|
||||
super.simplify();
|
||||
|
||||
for (SQLExpr column : columns) {
|
||||
if (column instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr identExpr = (SQLIdentifierExpr) column;
|
||||
String columnName = identExpr.getName();
|
||||
columnName = SQLUtils.normalize(columnName, dbType);
|
||||
identExpr.setName(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,17 +21,17 @@ import com.alibaba.druid.sql.ast.statement.SQLUnique;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
public class MySqlKey extends SQLUnique implements SQLUniqueConstraint, SQLTableConstraint {
|
||||
|
||||
private SQLName indexName;
|
||||
|
||||
private String indexType;
|
||||
|
||||
private boolean hasConstaint;
|
||||
|
||||
public MySqlKey(){
|
||||
|
||||
dbType = JdbcConstants.MYSQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,7 +45,7 @@ public class MySqlKey extends SQLUnique implements SQLUniqueConstraint, SQLTable
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, this.getName());
|
||||
acceptChild(visitor, this.getColumns());
|
||||
acceptChild(visitor, indexName);
|
||||
acceptChild(visitor, name);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
@@ -58,14 +58,6 @@ public class MySqlKey extends SQLUnique implements SQLUniqueConstraint, SQLTable
|
||||
this.indexType = indexType;
|
||||
}
|
||||
|
||||
public SQLName getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public void setIndexName(SQLName indexName) {
|
||||
this.indexName = indexName;
|
||||
}
|
||||
|
||||
public boolean isHasConstaint() {
|
||||
return hasConstaint;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,12 @@ package com.alibaba.druid.sql.dialect.mysql.ast;
|
||||
|
||||
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
public class MySqlPrimaryKey extends MySqlKey implements SQLPrimaryKey {
|
||||
|
||||
public MySqlPrimaryKey(){
|
||||
|
||||
dbType = JdbcConstants.MYSQL;
|
||||
}
|
||||
|
||||
protected void accept0(MySqlASTVisitor visitor) {
|
||||
|
||||
@@ -28,7 +28,6 @@ public class MySqlUnique extends MySqlKey implements SQLPrimaryKey {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, this.getName());
|
||||
acceptChild(visitor, this.getColumns());
|
||||
acceptChild(visitor, this.getIndexName());
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
/**
|
||||
* @author kiki
|
||||
@@ -34,6 +35,10 @@ public class MysqlForeignKey extends SQLForeignKeyImpl {
|
||||
protected Option onUpdate;
|
||||
protected Option onDelete;
|
||||
|
||||
public MysqlForeignKey() {
|
||||
dbType = JdbcConstants.MYSQL;
|
||||
}
|
||||
|
||||
public SQLName getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
+6
-1
@@ -165,8 +165,13 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
|
||||
public void setTableGroup(SQLName tableGroup) {
|
||||
this.tableGroup = tableGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
tableOptions.clear();
|
||||
super.simplify();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -774,7 +774,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
|
||||
if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.LITERAL_ALIAS) {
|
||||
SQLName indexName = this.exprParser.name();
|
||||
if (indexName != null) {
|
||||
key.setIndexName(indexName);
|
||||
key.setName(indexName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -542,6 +542,7 @@ public class MySqlExprParser extends SQLExprParser {
|
||||
|
||||
public SQLColumnDefinition parseColumn() {
|
||||
SQLColumnDefinition column = new SQLColumnDefinition();
|
||||
column.setDbType(dbType);
|
||||
column.setName(name());
|
||||
column.setDataType(parseDataType());
|
||||
|
||||
@@ -813,7 +814,7 @@ public class MySqlExprParser extends SQLExprParser {
|
||||
|
||||
if (lexer.token() != Token.LPAREN) {
|
||||
SQLName indexName = name();
|
||||
unique.setIndexName(indexName);
|
||||
unique.setName(indexName);
|
||||
}
|
||||
|
||||
//5.5语法 USING BTREE 放在index 名字后
|
||||
|
||||
@@ -585,9 +585,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
|
||||
print0(ucase ? "KEY" : "key");
|
||||
|
||||
if (x.getIndexName() != null) {
|
||||
SQLName name = x.getName();
|
||||
if (name != null) {
|
||||
print(' ');
|
||||
x.getIndexName().accept(this);
|
||||
name.accept(this);
|
||||
}
|
||||
|
||||
if (x.getIndexType() != null) {
|
||||
@@ -2844,9 +2845,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
|
||||
print0(ucase ? "UNIQUE" : "unique");
|
||||
|
||||
if (x.getIndexName() != null) {
|
||||
SQLName name = x.getName();
|
||||
if (name != null) {
|
||||
print(' ');
|
||||
x.getIndexName().accept(this);
|
||||
name.accept(this);
|
||||
}
|
||||
|
||||
if (x.getIndexType() != null) {
|
||||
|
||||
+24
@@ -78,6 +78,29 @@ public class OracleCreateTableStatement extends SQLCreateTableStatement implemen
|
||||
private SQLName of;
|
||||
private OIDIndex oidIndex;
|
||||
private boolean monitoring;
|
||||
|
||||
|
||||
public void simplify() {
|
||||
tablespace = null;
|
||||
storage = null;
|
||||
lobStorage = null;
|
||||
|
||||
pctfree = null;
|
||||
pctused = null;
|
||||
initrans = null;
|
||||
maxtrans = null;
|
||||
pctincrease = null;
|
||||
|
||||
logging = null;
|
||||
compress = null;
|
||||
compressLevel = null;
|
||||
compressForOltp = false;
|
||||
|
||||
onCommitPreserveRows = false;
|
||||
onCommitDeleteRows = false;
|
||||
|
||||
super.simplify();
|
||||
}
|
||||
|
||||
public OracleCreateTableStatement() {
|
||||
super (JdbcConstants.ORACLE);
|
||||
@@ -466,4 +489,5 @@ public class OracleCreateTableStatement extends SQLCreateTableStatement implemen
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ public class SQLServerExprParser extends SQLExprParser {
|
||||
|
||||
public SQLColumnDefinition createColumnDefinition() {
|
||||
SQLColumnDefinition column = new SQLColumnDefinition();
|
||||
column.setDbType(dbType);
|
||||
return column;
|
||||
}
|
||||
|
||||
|
||||
@@ -1980,6 +1980,7 @@ public class SQLExprParser extends SQLParser {
|
||||
|
||||
public SQLColumnDefinition createColumnDefinition() {
|
||||
SQLColumnDefinition column = new SQLColumnDefinition();
|
||||
column.setDbType(dbType);
|
||||
return column;
|
||||
}
|
||||
|
||||
|
||||
@@ -1012,13 +1012,14 @@ public class SQLStatementParser extends SQLParser {
|
||||
lexer.nextToken();
|
||||
SQLExpr comment = this.exprParser.primary();
|
||||
|
||||
SQLColumnDefinition columnDefinition = new SQLColumnDefinition();
|
||||
columnDefinition.setName(columnName);
|
||||
columnDefinition.setComment(comment);
|
||||
SQLColumnDefinition column = new SQLColumnDefinition();
|
||||
column.setDbType(dbType);
|
||||
column.setName(columnName);
|
||||
column.setComment(comment);
|
||||
|
||||
SQLAlterTableAlterColumn changeColumn = new SQLAlterTableAlterColumn();
|
||||
|
||||
changeColumn.setColumn(columnDefinition);
|
||||
changeColumn.setColumn(column);
|
||||
|
||||
stmt.addItem(changeColumn);
|
||||
} else {
|
||||
@@ -2232,6 +2233,7 @@ public class SQLStatementParser extends SQLParser {
|
||||
createView.addColumn(constraint);
|
||||
} else {
|
||||
SQLColumnDefinition column = new SQLColumnDefinition();
|
||||
column.setDbType(dbType);
|
||||
SQLName expr = this.exprParser.name();
|
||||
column.setName(expr);
|
||||
|
||||
|
||||
@@ -1311,8 +1311,11 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
|
||||
if (aliasMap != null) {
|
||||
String alias = x.getAlias();
|
||||
if (alias != null && !aliasMap.containsKey(alias)) {
|
||||
putAliasMap(aliasMap, alias, ident);
|
||||
if (alias != null) {
|
||||
String table = aliasMap.get(alias);
|
||||
if (!(ident.equals(table) || alias.equals(table))) {
|
||||
putAliasMap(aliasMap, alias, ident);
|
||||
}
|
||||
}
|
||||
if (!aliasMap.containsKey(ident)) {
|
||||
putAliasMap(aliasMap, ident, ident);
|
||||
|
||||
@@ -766,4 +766,20 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
close(conn);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(String dbType, Connection conn) throws SQLException {
|
||||
return getCreateTableScript(dbType, conn, true, true);
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(String dbType, Connection conn, boolean sorted, boolean simplify) throws SQLException {
|
||||
if (JdbcConstants.MYSQL.equals(dbType)) {
|
||||
return MySqlUtils.getCreateTableScript(conn, sorted, simplify);
|
||||
}
|
||||
|
||||
if (JdbcConstants.ORACLE.equals(dbType)) {
|
||||
return OracleUtils.getCreateTableScript(conn, sorted, simplify);
|
||||
}
|
||||
|
||||
throw new SQLException("getCreateTableScript dbType not support for " + dbType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.alibaba.druid.util;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.mysql.jdbc.ConnectionImpl;
|
||||
import com.mysql.jdbc.MySQLConnection;
|
||||
import com.mysql.jdbc.MysqlIO;
|
||||
@@ -25,11 +27,10 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MySqlUtils {
|
||||
@@ -126,4 +127,91 @@ public class MySqlUtils {
|
||||
|
||||
return words.contains(name_lower);
|
||||
}
|
||||
|
||||
public static List<String> showTables(Connection conn) throws SQLException {
|
||||
List<String> tables = new ArrayList<String>();
|
||||
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
stmt = conn.createStatement();
|
||||
rs = stmt.executeQuery("show tables");
|
||||
while (rs.next()) {
|
||||
String tableName = rs.getString(1);
|
||||
tables.add(tableName);
|
||||
}
|
||||
} finally {
|
||||
JdbcUtils.close(rs);
|
||||
JdbcUtils.close(stmt);
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
public static List<String> getTableDDL(Connection conn, List<String> tables) throws SQLException {
|
||||
List<String> ddlList = new ArrayList<String>();
|
||||
|
||||
Statement stmt = null;
|
||||
try {
|
||||
for (String table : tables) {
|
||||
if (stmt == null) {
|
||||
stmt = conn.createStatement();
|
||||
}
|
||||
|
||||
if (isKeyword(table)) {
|
||||
table = "`" + table + "`";
|
||||
}
|
||||
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
rs = stmt.executeQuery("show create table " + table);
|
||||
if (rs.next()) {
|
||||
String ddl = rs.getString(2);
|
||||
ddlList.add(ddl);
|
||||
}
|
||||
} finally {
|
||||
JdbcUtils.close(rs);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
JdbcUtils.close(stmt);
|
||||
}
|
||||
|
||||
|
||||
return ddlList;
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(Connection conn) throws SQLException {
|
||||
return getCreateTableScript(conn, true, true);
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(Connection conn, boolean sorted, boolean simplify) throws SQLException {
|
||||
List<String> tables = showTables(conn);
|
||||
List<String> ddlList = getTableDDL(conn, tables);
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (String ddl : ddlList) {
|
||||
buf.append(ddl);
|
||||
buf.append(';');
|
||||
}
|
||||
String ddlScript = buf.toString();
|
||||
|
||||
if (! (sorted || simplify)) {
|
||||
return ddlScript;
|
||||
}
|
||||
|
||||
List stmtList = SQLUtils.parseStatements(ddlScript, JdbcConstants.MYSQL);
|
||||
if (simplify) {
|
||||
for (Object o : stmtList) {
|
||||
if (o instanceof SQLCreateTableStatement) {
|
||||
SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) o;
|
||||
createTableStmt.simplify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sorted) {
|
||||
SQLCreateTableStatement.sort(stmtList);
|
||||
}
|
||||
return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
package com.alibaba.druid.util;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import javax.sql.XAConnection;
|
||||
import javax.transaction.xa.XAException;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import oracle.jdbc.OracleConnection;
|
||||
import oracle.jdbc.OracleResultSet;
|
||||
import oracle.jdbc.OracleStatement;
|
||||
import oracle.jdbc.driver.DatabaseError;
|
||||
import oracle.jdbc.internal.OraclePreparedStatement;
|
||||
import oracle.jdbc.xa.client.OracleXAConnection;
|
||||
import oracle.sql.ROWID;
|
||||
@@ -222,4 +222,99 @@ public class OracleUtils {
|
||||
|
||||
return words.contains(name_lower);
|
||||
}
|
||||
|
||||
public static List<String> showTables(Connection conn) throws SQLException {
|
||||
List<String> tables = new ArrayList<String>();
|
||||
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
stmt = conn.createStatement();
|
||||
rs = stmt.executeQuery("select table_name from user_tables");
|
||||
while (rs.next()) {
|
||||
String tableName = rs.getString(1);
|
||||
tables.add(tableName);
|
||||
}
|
||||
} finally {
|
||||
JdbcUtils.close(rs);
|
||||
JdbcUtils.close(stmt);
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
public static List<String> getTableDDL(Connection conn, String... tables) throws SQLException {
|
||||
return getTableDDL(conn, Arrays.asList(tables));
|
||||
}
|
||||
|
||||
public static List<String> getTableDDL(Connection conn, List<String> tables) throws SQLException {
|
||||
List<String> ddlList = new ArrayList<String>();
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "select DBMS_METADATA.GET_DDL('TABLE', TABLE_NAME) FROM user_tables";
|
||||
|
||||
if (tables.size() > 0) {
|
||||
sql += "IN (";
|
||||
for (int i = 0; i < tables.size(); ++i) {
|
||||
if (i != 0) {
|
||||
sql += ", ?";
|
||||
} else {
|
||||
sql += "?";
|
||||
}
|
||||
}
|
||||
sql += ")";
|
||||
}
|
||||
pstmt = conn.prepareStatement(sql);
|
||||
for (int i = 0; i < tables.size(); ++i) {
|
||||
pstmt.setString(i + 1, tables.get(i));
|
||||
}
|
||||
rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
String ddl = rs.getString(1);
|
||||
ddlList.add(ddl);
|
||||
}
|
||||
} finally {
|
||||
JdbcUtils.close(rs);
|
||||
JdbcUtils.close(pstmt);
|
||||
}
|
||||
|
||||
return ddlList;
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(Connection conn) throws SQLException {
|
||||
return getCreateTableScript(conn, true, true);
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(Connection conn, boolean sorted, boolean simplify) throws SQLException {
|
||||
List<String> ddlList = OracleUtils.getTableDDL(conn);
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (String ddl : ddlList) {
|
||||
buf.append(ddl);
|
||||
buf.append(';');
|
||||
}
|
||||
|
||||
String ddlScript = buf.toString();
|
||||
|
||||
if (! (sorted || simplify)) {
|
||||
return ddlScript;
|
||||
}
|
||||
|
||||
List stmtList = SQLUtils.parseStatements(ddlScript, JdbcConstants.ORACLE);
|
||||
if (simplify) {
|
||||
for (Object o : stmtList) {
|
||||
if (o instanceof SQLCreateTableStatement) {
|
||||
SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) o;
|
||||
createTableStmt.simplify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sorted) {
|
||||
SQLCreateTableStatement.sort(stmtList);
|
||||
}
|
||||
return SQLUtils.toSQLString(stmtList, JdbcConstants.ORACLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.alibaba.druid;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 18/05/2017.
|
||||
*/
|
||||
public abstract class DbTestCase extends TestCase {
|
||||
protected DruidDataSource dataSource;
|
||||
|
||||
protected final String resource;
|
||||
|
||||
public DbTestCase(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
this.dataSource = createDataSourceFromResource(resource);
|
||||
}
|
||||
|
||||
static DruidDataSource createDataSourceFromResource(String resource) throws IOException {
|
||||
Properties properties = new Properties();
|
||||
|
||||
InputStream configStream = null;
|
||||
try {
|
||||
configStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
|
||||
properties.load(configStream);
|
||||
} finally {
|
||||
JdbcUtils.close(configStream);
|
||||
}
|
||||
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
dataSource.configFromPropety(properties);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
dataSource.close();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class MySqlDeleteTest_1 extends MysqlTest {
|
||||
stmt.accept(visitor);
|
||||
|
||||
// System.out.println("Tables : " + visitor.getTables());
|
||||
// System.out.println("fields : " + visitor.getColumns());
|
||||
System.out.println("fields : " + visitor.getColumns());
|
||||
// System.out.println("coditions : " + visitor.getConditions());
|
||||
// System.out.println("orderBy : " + visitor.getOrderByColumns());
|
||||
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.bvt.sql.mysql.select;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MySqlSelectTest_48_union extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "select sum(hd.paid_amount) from\n" +
|
||||
"(\n" +
|
||||
"SELECT 'fl',cast(a.hosted_ymd as date) as hosted_ymd,a.user_id,'boss1',a.paid_amount,m.user_id,m.create_date,m.pmcode,n.type_name,n.product_name,n.acctype_id,n.acctype_name,n.account_name,n.plan\n" +
|
||||
"FROM hive.bdc_dwd.dw_mk_copyright_order a\n" +
|
||||
"left join hive.bdc_dwd.dw_mk_chance b on (a.chance_id=b.chance_id and b.acct_day='03')\n" +
|
||||
"left join hive.bdc_dwd.dw_lg_stat_user m on (a.user_id =m.user_id and m.acct_day='03')\n" +
|
||||
"left join hive.bdc_dwd.dw_lg_pmcode n on (m.pmcode=n.id and n.acct_day='03')\n" +
|
||||
"where a.hosted_ymd between '2016-01-01' and '2017-06-30' and b.chance_type_group=3\n" +
|
||||
"and a.acct_day='03'\n" +
|
||||
"union\n" +
|
||||
"select 'fl',b.paid_date as hosted_ymd,b.user_id,'boss2',b.paid_amount,m.user_id,m.create_date,m.pmcode,n.type_name,n.product_name,n.acctype_id,n.acctype_name,n.account_name,n.plan\n" +
|
||||
"from hive.bdc_dwd.dw_fx_chance a\n" +
|
||||
"left join hive.bdc_dwd.dw_fx_chance_order b on (a.chance_id=b.chance_id and b.acct_day='03')\n" +
|
||||
"left join hive.bdc_dwd.dw_lg_stat_user m on (a.user_id =m.user_id and m.acct_day='03')\n" +
|
||||
"left join hive.bdc_dwd.dw_lg_pmcode n on (m.pmcode=n.id and n.acct_day='03')\n" +
|
||||
"where a.project_id=1 and b.paid_amount>0 and cast(b.paid_date as varchar(10))>='2016-01-01' and\n" +
|
||||
"cast(b.paid_date as varchar(10))<='2017-06-30' and b.state=1 and a.acct_day='03'\n" +
|
||||
")hd";
|
||||
|
||||
|
||||
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
|
||||
assertEquals(1, statementList.size());
|
||||
|
||||
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
|
||||
stmt.accept(visitor);
|
||||
|
||||
// System.out.println("Tables : " + visitor.getTables());
|
||||
System.out.println("fields : " + visitor.getColumns());
|
||||
// System.out.println("coditions : " + visitor.getConditions());
|
||||
// System.out.println("orderBy : " + visitor.getOrderByColumns());
|
||||
|
||||
// assertEquals(1, visitor.getTables().size());
|
||||
// assertEquals(1, visitor.getColumns().size());
|
||||
// assertEquals(0, visitor.getConditions().size());
|
||||
// assertEquals(0, visitor.getOrderByColumns().size());
|
||||
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt);
|
||||
assertEquals("SELECT SUM(hd.paid_amount)\n" +
|
||||
"FROM (\n" +
|
||||
"\t(SELECT 'fl', CAST(a.hosted_ymd AS date) AS hosted_ymd, a.user_id, 'boss1', a.paid_amount\n" +
|
||||
"\t\t, m.user_id, m.create_date, m.pmcode, n.type_name, n.product_name\n" +
|
||||
"\t\t, n.acctype_id, n.acctype_name, n.account_name, n.plan\n" +
|
||||
"\tFROM hive.bdc_dwd.dw_mk_copyright_order a\n" +
|
||||
"\t\tLEFT JOIN hive.bdc_dwd.dw_mk_chance b\n" +
|
||||
"\t\tON a.chance_id = b.chance_id\n" +
|
||||
"\t\t\tAND b.acct_day = '03'\n" +
|
||||
"\t\tLEFT JOIN hive.bdc_dwd.dw_lg_stat_user m\n" +
|
||||
"\t\tON a.user_id = m.user_id\n" +
|
||||
"\t\t\tAND m.acct_day = '03'\n" +
|
||||
"\t\tLEFT JOIN hive.bdc_dwd.dw_lg_pmcode n\n" +
|
||||
"\t\tON m.pmcode = n.id\n" +
|
||||
"\t\t\tAND n.acct_day = '03'\n" +
|
||||
"\tWHERE a.hosted_ymd BETWEEN '2016-01-01' AND '2017-06-30'\n" +
|
||||
"\t\tAND b.chance_type_group = 3\n" +
|
||||
"\t\tAND a.acct_day = '03'\n" +
|
||||
"\tUNION\n" +
|
||||
"\tSELECT 'fl', b.paid_date AS hosted_ymd, b.user_id, 'boss2', b.paid_amount\n" +
|
||||
"\t\t, m.user_id, m.create_date, m.pmcode, n.type_name, n.product_name\n" +
|
||||
"\t\t, n.acctype_id, n.acctype_name, n.account_name, n.plan\n" +
|
||||
"\tFROM hive.bdc_dwd.dw_fx_chance a\n" +
|
||||
"\t\tLEFT JOIN hive.bdc_dwd.dw_fx_chance_order b\n" +
|
||||
"\t\tON a.chance_id = b.chance_id\n" +
|
||||
"\t\t\tAND b.acct_day = '03'\n" +
|
||||
"\t\tLEFT JOIN hive.bdc_dwd.dw_lg_stat_user m\n" +
|
||||
"\t\tON a.user_id = m.user_id\n" +
|
||||
"\t\t\tAND m.acct_day = '03'\n" +
|
||||
"\t\tLEFT JOIN hive.bdc_dwd.dw_lg_pmcode n\n" +
|
||||
"\t\tON m.pmcode = n.id\n" +
|
||||
"\t\t\tAND n.acct_day = '03'\n" +
|
||||
"\tWHERE a.project_id = 1\n" +
|
||||
"\t\tAND b.paid_amount > 0\n" +
|
||||
"\t\tAND CAST(b.paid_date AS varchar(10)) >= '2016-01-01'\n" +
|
||||
"\t\tAND CAST(b.paid_date AS varchar(10)) <= '2017-06-30'\n" +
|
||||
"\t\tAND b.state = 1\n" +
|
||||
"\t\tAND a.acct_day = '03')\n" +
|
||||
") hd", //
|
||||
output);
|
||||
}
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
|
||||
assertEquals("select sum(hd.paid_amount)\n" +
|
||||
"from (\n" +
|
||||
"\t(select 'fl', cast(a.hosted_ymd as date) as hosted_ymd, a.user_id, 'boss1', a.paid_amount\n" +
|
||||
"\t\t, m.user_id, m.create_date, m.pmcode, n.type_name, n.product_name\n" +
|
||||
"\t\t, n.acctype_id, n.acctype_name, n.account_name, n.plan\n" +
|
||||
"\tfrom hive.bdc_dwd.dw_mk_copyright_order a\n" +
|
||||
"\t\tleft join hive.bdc_dwd.dw_mk_chance b\n" +
|
||||
"\t\ton a.chance_id = b.chance_id\n" +
|
||||
"\t\t\tand b.acct_day = '03'\n" +
|
||||
"\t\tleft join hive.bdc_dwd.dw_lg_stat_user m\n" +
|
||||
"\t\ton a.user_id = m.user_id\n" +
|
||||
"\t\t\tand m.acct_day = '03'\n" +
|
||||
"\t\tleft join hive.bdc_dwd.dw_lg_pmcode n\n" +
|
||||
"\t\ton m.pmcode = n.id\n" +
|
||||
"\t\t\tand n.acct_day = '03'\n" +
|
||||
"\twhere a.hosted_ymd between '2016-01-01' and '2017-06-30'\n" +
|
||||
"\t\tand b.chance_type_group = 3\n" +
|
||||
"\t\tand a.acct_day = '03'\n" +
|
||||
"\tunion\n" +
|
||||
"\tselect 'fl', b.paid_date as hosted_ymd, b.user_id, 'boss2', b.paid_amount\n" +
|
||||
"\t\t, m.user_id, m.create_date, m.pmcode, n.type_name, n.product_name\n" +
|
||||
"\t\t, n.acctype_id, n.acctype_name, n.account_name, n.plan\n" +
|
||||
"\tfrom hive.bdc_dwd.dw_fx_chance a\n" +
|
||||
"\t\tleft join hive.bdc_dwd.dw_fx_chance_order b\n" +
|
||||
"\t\ton a.chance_id = b.chance_id\n" +
|
||||
"\t\t\tand b.acct_day = '03'\n" +
|
||||
"\t\tleft join hive.bdc_dwd.dw_lg_stat_user m\n" +
|
||||
"\t\ton a.user_id = m.user_id\n" +
|
||||
"\t\t\tand m.acct_day = '03'\n" +
|
||||
"\t\tleft join hive.bdc_dwd.dw_lg_pmcode n\n" +
|
||||
"\t\ton m.pmcode = n.id\n" +
|
||||
"\t\t\tand n.acct_day = '03'\n" +
|
||||
"\twhere a.project_id = 1\n" +
|
||||
"\t\tand b.paid_amount > 0\n" +
|
||||
"\t\tand cast(b.paid_date as varchar(10)) >= '2016-01-01'\n" +
|
||||
"\t\tand cast(b.paid_date as varchar(10)) <= '2017-06-30'\n" +
|
||||
"\t\tand b.state = 1\n" +
|
||||
"\t\tand a.acct_day = '03')\n" +
|
||||
") hd", //
|
||||
output);
|
||||
}
|
||||
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
|
||||
assertEquals("SELECT student_name, GROUP_CONCAT(DISTINCT test_score ORDER BY test_score DESC SEPARATOR ' ')\n" +
|
||||
"FROM student\n" +
|
||||
"GROUP BY student_name;", //
|
||||
output);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.alibaba.druid.mysql;
|
||||
|
||||
import com.alibaba.druid.DbTestCase;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import com.alibaba.druid.util.MySqlUtils;
|
||||
import com.alibaba.druid.util.OracleUtils;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 23/07/2017.
|
||||
*/
|
||||
public class MySql_getCreateTableScriptTest extends DbTestCase {
|
||||
public MySql_getCreateTableScriptTest() {
|
||||
super("pool_config/mysql_db.properties");
|
||||
}
|
||||
|
||||
public void test_oracle() throws Exception {
|
||||
Connection conn = getConnection();
|
||||
|
||||
String createTableScript = JdbcUtils.getCreateTableScript(JdbcConstants.MYSQL, conn);
|
||||
System.out.println(createTableScript);
|
||||
|
||||
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.alibaba.druid.oracle;
|
||||
|
||||
import com.alibaba.druid.DbTestCase;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import com.alibaba.druid.util.OracleUtils;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 23/07/2017.
|
||||
*/
|
||||
public class Oracle_getCreateTableScriptTest extends DbTestCase {
|
||||
public Oracle_getCreateTableScriptTest() {
|
||||
super("pool_config/oracle_db.properties");
|
||||
}
|
||||
|
||||
public void test_oracle() throws Exception {
|
||||
Connection conn = getConnection();
|
||||
|
||||
// 从Oracle通过DBMS_METADATA.GET_DDL获取CreateTable语句列表
|
||||
String createTableScript = JdbcUtils.getCreateTableScript(JdbcConstants.ORACLE, conn);
|
||||
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user