diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index de06ba04ca..fe68182ac5 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -400,6 +400,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat setKillWhenSocketReadTimeout(value); } } + { + String property = properties.getProperty("druid.connectProperties"); + if (property != null) { + this.setConnectionProperties(property); + } + } } public boolean isKillWhenSocketReadTimeout() { diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java index 39611a80d9..774e039dab 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java @@ -190,7 +190,19 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Seri } public SQLBinaryOpExpr clone() { - return new SQLBinaryOpExpr(left, operator, right, dbType); + SQLBinaryOpExpr x = new SQLBinaryOpExpr(); + + if (left != null) { + x.setLeft(left.clone()); + } + if (right != null) { + x.setRight(right.clone()); + } + x.operator = operator; + x.dbType = dbType; + x.bracket = bracket; + + return x; } public String toString() { @@ -452,4 +464,30 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Seri return null; } + + public boolean conditionContainsTable(String alias) { + if (left == null || right == null) { + return false; + } + + if (left instanceof SQLPropertyExpr) { + if (((SQLPropertyExpr) left).matchOwner(alias)) { + return true; + } + } else if (left instanceof SQLBinaryOpExpr) { + if (((SQLBinaryOpExpr) left).conditionContainsTable(alias)) { + return true; + } + } + + if (right instanceof SQLPropertyExpr) { + if (((SQLPropertyExpr) right).matchOwner(alias)) { + return true; + } + } else if (right instanceof SQLBinaryOpExpr) { + return ((SQLBinaryOpExpr) right).conditionContainsTable(alias); + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java index 4aa7fee2ba..4308fad287 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java @@ -19,7 +19,7 @@ import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { @@ -30,6 +30,7 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { private transient Boolean parameter; private transient SQLColumnDefinition resolvedColumn; + private transient SQLTableSource resolvedTableSource; public SQLIdentifierExpr(){ @@ -149,11 +150,32 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { this.resolvedColumn = resolvedColumn; } + public SQLTableSource getResolvedTableSource() { + return resolvedTableSource; + } + + public void setResolvedTableSource(SQLTableSource resolvedTableSource) { + this.resolvedTableSource = resolvedTableSource; + } + public SQLDataType computeDataType() { if (resolvedColumn != null) { return resolvedColumn.getDataType(); } + if (resolvedTableSource != null + && resolvedTableSource instanceof SQLSubqueryTableSource) { + SQLSelect select = ((SQLSubqueryTableSource) resolvedTableSource).getSelect(); + SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock(); + if (queryBlock == null) { + return null; + } + SQLSelectItem selectItem = queryBlock.findSelectItem(name); + if (selectItem != null) { + return selectItem.computeDataType(); + } + } + return null; } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java index 497675ebb7..3d9678df7e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.ast.SQLReplaceable; @@ -177,6 +178,9 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, @Override public boolean replace(SQLExpr expr, SQLExpr target) { + if (target == null) { + return false; + } for (int i = 0; i < parameters.size(); ++i) { if (parameters.get(i) == expr) { parameters.set(i, target); @@ -210,4 +214,24 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, return false; } + + public SQLDataType computeDataType() { + if (parameters.size() == 1) { + if (SQLUtils.nameEquals("trunc", methodName)) { + return parameters.get(0).computeDataType(); + } + } else if (parameters.size() == 2) { + SQLExpr param0 = parameters.get(0); + SQLExpr param1 = parameters.get(1); + if (SQLUtils.nameEquals("nvl", methodName) || SQLUtils.nameEquals("ifnull", methodName)) { + SQLDataType dataType = param0.computeDataType(); + if (dataType != null) { + return dataType; + } + + return param1.computeDataType(); + } + } + return null; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java index ed13064117..1871c6313c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java @@ -20,7 +20,7 @@ import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -30,6 +30,7 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { private String name; private transient SQLColumnDefinition resolvedColumn; + private transient SQLTableSource resolvedTableSource; public SQLPropertyExpr(String owner, String name){ this(new SQLIdentifierExpr(owner), name); @@ -170,11 +171,32 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { this.resolvedColumn = resolvedColumn; } + public SQLTableSource getResolvedTableSource() { + return resolvedTableSource; + } + + public void setResolvedTableSource(SQLTableSource resolvedTableSource) { + this.resolvedTableSource = resolvedTableSource; + } + public SQLDataType computeDataType() { if (resolvedColumn != null) { return resolvedColumn.getDataType(); } + if (resolvedTableSource != null + && resolvedTableSource instanceof SQLSubqueryTableSource) { + SQLSelect select = ((SQLSubqueryTableSource) resolvedTableSource).getSelect(); + SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock(); + if (queryBlock == null) { + return null; + } + SQLSelectItem selectItem = queryBlock.findSelectItem(name); + if (selectItem != null) { + return selectItem.computeDataType(); + } + } + return null; } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSequenceExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSequenceExpr.java index 720bfc7a07..879b14f1e1 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSequenceExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSequenceExpr.java @@ -33,6 +33,15 @@ public class SQLSequenceExpr extends SQLExprImpl { this.function = function; } + public SQLSequenceExpr clone() { + SQLSequenceExpr x = new SQLSequenceExpr(); + if (sequence != null) { + x.setSequence(sequence.clone()); + } + x.function = function; + return x; + } + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index 5c527aa66a..fa0e82b174 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -548,6 +548,27 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS } } + public boolean apply(SQLDropIndexStatement x) { + for (int i = tableElementList.size() - 1; i >= 0; i--) { + SQLTableElement e = tableElementList.get(i); + if (e instanceof SQLUniqueConstraint) { + SQLUniqueConstraint unique = (SQLUniqueConstraint) e; + if (SQLUtils.nameEquals(unique.getName(), x.getIndexName())) { + tableElementList.remove(i); + return true; + } + + } else if (e instanceof MySqlTableIndex) { + MySqlTableIndex tableIndex = (MySqlTableIndex) e; + if (SQLUtils.nameEquals(tableIndex.getName(), x.getIndexName())) { + tableElementList.remove(i); + return true; + } + } + } + return false; + } + public boolean apply(SQLAlterTableStatement alter) { if (!SQLUtils.nameEquals(alter.getName(), this.getName())) { return false; @@ -716,7 +737,16 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS } } } + + for (SQLTableElement e : tableElementList) { + if (e instanceof SQLUnique) { + ((SQLUnique) e).applyDropColumn(column); + } + } } + + + return true; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropIndexStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropIndexStatement.java index a4acb09a04..2537f760ff 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropIndexStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropIndexStatement.java @@ -16,12 +16,13 @@ package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLDropIndexStatement extends SQLStatementImpl implements SQLDDLStatement { - private SQLExpr indexName; + private SQLName indexName; private SQLExprTableSource tableName; public SQLDropIndexStatement() { @@ -32,11 +33,11 @@ public class SQLDropIndexStatement extends SQLStatementImpl implements SQLDDLSta super (dbType); } - public SQLExpr getIndexName() { + public SQLName getIndexName() { return indexName; } - public void setIndexName(SQLExpr indexName) { + public void setIndexName(SQLName indexName) { this.indexName = indexName; } @@ -44,7 +45,7 @@ public class SQLDropIndexStatement extends SQLStatementImpl implements SQLDDLSta return tableName; } - public void setTableName(SQLExpr tableName) { + public void setTableName(SQLName tableName) { this.setTableName(new SQLExprTableSource(tableName)); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java index a6ed35dea0..079b7cfa31 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java @@ -20,6 +20,7 @@ import java.util.List; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLReplaceable; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; @@ -404,4 +405,75 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace return null; } + public boolean match(String alias_a, String alias_b) { + if (left == null || right == null) { + return false; + } + + if (left.containsAlias(alias_a) && right.containsAlias(alias_b)) { + return true; + } + + return right.containsAlias(alias_a) && left.containsAlias(alias_b); + } + + /** + * a, b left join c -> + */ +// public boolean addCondition(SQLBinaryOpExpr condition, JoinType joinType) { +// if (this.left == null || this.right == null) { +// return false; +// } +// +// if (!(condition.getLeft() instanceof SQLPropertyExpr +// && condition.getRight() instanceof SQLPropertyExpr)) { +// return false; +// } +// +// SQLPropertyExpr left = (SQLPropertyExpr) condition.getLeft(); +// SQLPropertyExpr right = (SQLPropertyExpr) condition.getRight(); +// +// String leftOwner = left.getOwnernName(); +// String rightOwner = right.getOwnernName(); +// +// if (this.left.containsAlias(leftOwner) && this.right.containsAlias(rightOwner)) { +// if (this.joinType == joinType) { +// this.addConditionnIfAbsent(condition); +// return true; +// } +// +// if (this.joinType == null || this.joinType == JoinType.COMMA) { +// this.joinType = joinType; +// this.addConditionnIfAbsent(condition); +// return true; +// } +// +// if (this.joinType == JoinType.LEFT_OUTER_JOIN && joinType == JoinType.RIGHT_OUTER_JOIN) { +// if (this.left instanceof SQLJoinTableSource && ((SQLJoinTableSource) this.left).joinType == JoinType.COMMA) { +// SQLJoinTableSource leftJoin = (SQLJoinTableSource) this.left; +// +// } +// } +// } +// +// return false; +// } +// + public boolean conditionContainsTable(String alias) { + if (condition == null) { + return false; + } + + if (condition instanceof SQLBinaryOpExpr) { + return ((SQLBinaryOpExpr) condition).conditionContainsTable(alias); + } + + return false; + } + + public SQLJoinTableSource join(SQLTableSource right, JoinType joinType, SQLExpr condition) { + SQLJoinTableSource joined = new SQLJoinTableSource(this, joinType, right, condition); + return joined; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java index 6021a1dc61..60083cbecb 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java @@ -549,18 +549,4 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery return -1; } - - public SQLColumnDefinition computeColumn(SQLIdentifierExpr identExpr) { - SQLColumnDefinition column = identExpr.getResolvedColumn(); - if (column != null) { - return column; - } - - column = from.findColumn(identExpr.getName()); - if (column != null) { - identExpr.setResolvedColumn(column); - } - - return column; - } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java index ed0a0f12c5..8f232e7543 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java @@ -46,7 +46,9 @@ public class SQLSetStatement extends SQLStatementImpl { public SQLSetStatement(SQLExpr target, SQLExpr value, String dbType){ super (dbType); - this.items.add(new SQLAssignItem(target, value)); + SQLAssignItem item = new SQLAssignItem(target, value); + item.setParent(this); + this.items.add(item); } public static SQLSetStatement plus(SQLName target) { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java index 9dd4702d74..3de043c2ed 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java @@ -101,4 +101,28 @@ public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint, } } } + + public boolean applyColumnRename(SQLName columnName, SQLName to) { + for (SQLSelectOrderByItem orderByItem : columns) { + SQLExpr expr = orderByItem.getExpr(); + if (expr instanceof SQLName + && SQLUtils.nameEquals((SQLName) expr, columnName)) { + orderByItem.setExpr(to.clone()); + return true; + } + } + return false; + } + + public boolean applyDropColumn(SQLName columnName) { + for (int i = columns.size() - 1; i >= 0; i--) { + SQLExpr expr = columns.get(i).getExpr(); + if (expr instanceof SQLName + && SQLUtils.nameEquals((SQLName) expr, columnName)) { + columns.remove(i); + return true; + } + } + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java index fc6e7caec8..fd230f5953 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java @@ -16,9 +16,11 @@ package com.alibaba.druid.sql.dialect.mysql.ast; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLTableConstraint; import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableChangeColumn; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.JdbcConstants; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java index 79ac60ed86..0774614f26 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java @@ -28,6 +28,7 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLPartitionBy; import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique; @@ -295,13 +296,14 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement insertIndex = beforeIndex; } else if (afterIndex != -1) { insertIndex = afterIndex + 1; + } else if (item.isFirst()) { + insertIndex = 0; } SQLColumnDefinition column = item.getNewColumnDefinition().clone(); column.setParent(this); if (insertIndex == -1 || insertIndex == columnIndex) { tableElementList.set(columnIndex, column); - return true; } else { if (insertIndex > columnIndex) { tableElementList.add(insertIndex, column); @@ -312,6 +314,14 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement implement } } + for (SQLTableElement e : tableElementList) { + if(e instanceof MySqlTableIndex) { + ((MySqlTableIndex) e).apply(item); + } else if (e instanceof MySqlKey) { + ((MySqlKey) e).applyColumnRename(columnName, column.getName()); + } + } + return true; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlTableIndex.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlTableIndex.java index 3c9f70714d..b254b889af 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlTableIndex.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlTableIndex.java @@ -84,4 +84,8 @@ public class MySqlTableIndex extends MySqlObjectImpl implements SQLTableElement } return x; } + + public boolean apply(MySqlAlterTableChangeColumn x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java index ae633540be..b6913e75d7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java @@ -18,6 +18,7 @@ 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.SQLStatement; import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; @@ -28,6 +29,16 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; public class NameResolveVisitor extends OracleASTVisitorAdapter { public boolean visit(SQLIdentifierExpr x) { SQLObject parent = x.getParent(); + + if (parent instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent; + boolean isJoinCondition = binaryOpExpr.getLeft() instanceof SQLName + && binaryOpExpr.getRight() instanceof SQLName; + if (isJoinCondition) { + return false; + } + } + String name = x.getName(); if ("ROWNUM".equalsIgnoreCase(name)) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleOuterExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleOuterExpr.java index c024479d9e..773c5b87a3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleOuterExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleOuterExpr.java @@ -33,6 +33,14 @@ public class OracleOuterExpr extends SQLExprImpl implements OracleExpr { this.expr = expr; } + public OracleOuterExpr clone() { + OracleOuterExpr x = new OracleOuterExpr(); + if (expr != null) { + x.setExpr(expr.clone()); + } + return x; + } + public SQLExpr getExpr() { return this.expr; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java index 0bf7e49f32..69447f35c2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java @@ -145,4 +145,9 @@ public class OracleSelectJoin extends SQLJoinTableSource implements OracleSelect } this.setRight(tableSource); } + + public SQLJoinTableSource join(SQLTableSource right, JoinType joinType, SQLExpr condition) { + SQLJoinTableSource joined = new OracleSelectJoin(this, joinType, right, condition); + return joined; + } } diff --git a/src/main/java/com/alibaba/druid/sql/repository/Schema.java b/src/main/java/com/alibaba/druid/sql/repository/Schema.java index c3cb74ad92..f1eeee4802 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/Schema.java +++ b/src/main/java/com/alibaba/druid/sql/repository/Schema.java @@ -69,6 +69,7 @@ public class Schema { public SchemaObject findTable(String tableName) { + tableName = SQLUtils.normalize(tableName); String lowerName = tableName.toLowerCase(); SchemaObject object = objects.get(lowerName); @@ -80,6 +81,7 @@ public class Schema { } public SchemaObject findTableOrView(String tableName) { + tableName = SQLUtils.normalize(tableName); String lowerName = tableName.toLowerCase(); SchemaObject object = objects.get(lowerName); @@ -96,12 +98,16 @@ public class Schema { } public SchemaObject findFunction(String functionName) { + functionName = SQLUtils.normalize(functionName); String lowerName = functionName.toLowerCase(); return functions.get(lowerName); } public boolean isSequence(String name) { - SchemaObject object = objects.get(name); + name = SQLUtils.normalize(name); + String lowerName = name.toLowerCase(); + + SchemaObject object = objects.get(lowerName); return object != null && object.getType() == SchemaObjectType.Sequence; } diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java index 79faca4628..4e5693135d 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java @@ -18,7 +18,6 @@ package com.alibaba.druid.sql.repository; import com.alibaba.druid.DruidRuntimeException; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.*; -import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; @@ -27,10 +26,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStateme import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowCreateTableStatement; -import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; -import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; -import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; @@ -38,11 +34,9 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; import com.alibaba.druid.util.JdbcConstants; -import com.alibaba.druid.util.JdbcUtils; import java.io.IOException; import java.util.*; -import java.util.concurrent.ConcurrentSkipListMap; /** * Created by wenshao on 03/06/2017. @@ -51,7 +45,7 @@ public class SchemaRepository { private Schema defaultSchema; protected String dbType; protected SQLASTVisitor consoleVisitor; - protected SQLASTVisitor resolveVisitor; + public SchemaRepository() { @@ -62,10 +56,8 @@ public class SchemaRepository { if (JdbcConstants.MYSQL.equals(dbType)) { consoleVisitor = new MySqlConsoleSchemaVisitor(); - resolveVisitor = new MySqlResolveVisitor(); } else if (JdbcConstants.ORACLE.equals(dbType)) { consoleVisitor = new OracleConsoleSchemaVisitor(); - resolveVisitor = new OracleResolveVisitor(); } else { consoleVisitor = new DefaultConsoleSchemaVisitor(); } @@ -239,11 +231,36 @@ public class SchemaRepository { return getDefaultSchema().getViewCount(); } + public void resolve(SQLStatement stmt, SchemaResolveVisitor.Option... options) { + if (stmt == null) { + return; + } + + SchemaResolveVisitor resolveVisitor = createResolveVisitor(options); + stmt.accept(resolveVisitor); + } + + private SchemaResolveVisitor createResolveVisitor(SchemaResolveVisitor.Option... options) { + int optionsValue = SchemaResolveVisitor.Option.of(options); + + SchemaResolveVisitor resolveVisitor; + if (JdbcConstants.MYSQL.equals(dbType)) { + resolveVisitor = new MySqlResolveVisitor(optionsValue); + } else if (JdbcConstants.ORACLE.equals(dbType)) { + resolveVisitor = new OracleResolveVisitor(optionsValue); + } else { + throw new DruidRuntimeException("dbType not support : " + dbType); + } + return resolveVisitor; + } + public String resolve(String input) { + SchemaResolveVisitor visitor = createResolveVisitor(SchemaResolveVisitor.Option.ResolveAllColumn); + List stmtList = SQLUtils.parseStatements(input, dbType); for (SQLStatement stmt : stmtList) { - stmt.accept(resolveVisitor); + stmt.accept(visitor); } return SQLUtils.toSQLString(stmtList, dbType); @@ -284,7 +301,6 @@ public class SchemaRepository { buf.append('\n'); } } - } else { stmt.accept(consoleVisitor); } @@ -321,7 +337,12 @@ public class SchemaRepository { return null; } - public class MySqlResolveVisitor extends MySqlASTVisitorAdapter { + private class MySqlResolveVisitor extends MySqlASTVisitorAdapter implements SchemaResolveVisitor { + private int options; + + public MySqlResolveVisitor(int options) { + this.options = options; + } public boolean visit(SQLExprTableSource x) { resolve(this, x); @@ -334,9 +355,30 @@ public class SchemaRepository { resolve(this, x); return super.visit(x); } + + public boolean visit(SQLIdentifierExpr x) { + resolve(this, x); + return true; + } + + public boolean visit(SQLPropertyExpr x) { + resolve(this, x); + return true; + } + + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; + } } - public class OracleResolveVisitor extends OracleASTVisitorAdapter { + private class OracleResolveVisitor extends OracleASTVisitorAdapter implements SchemaResolveVisitor { + private int options; + + public OracleResolveVisitor(int options) { + this.options = options; + } + public boolean visit(OracleSelectTableReference x) { resolve(this, x); return false; @@ -348,8 +390,10 @@ public class SchemaRepository { } public boolean visit(OracleSelectQueryBlock x) { - x.getFrom().accept(this); - + SQLTableSource from = x.getFrom(); + if (from != null) { + from.accept(this); + } resolve(this, x); return super.visit(x); } @@ -358,22 +402,50 @@ public class SchemaRepository { resolve(this, x); return true; } - } - public class OdpsResolveVisitor extends OdpsASTVisitorAdapter { - - public boolean visit(SQLExprTableSource x) { + public boolean visit(SQLPropertyExpr x) { resolve(this, x); - return false; + return true; } - public boolean visit(OdpsSelectQueryBlock x) { - resolve(this, x); - return super.visit(x); + @Override + public boolean isEnabled(Option option) { + return (options & option.mask) != 0; } } - private void resolve(SQLASTVisitor visitor, SQLIdentifierExpr x) { + private void resolve(SchemaResolveVisitor visitor, SQLPropertyExpr x) { + String owner = x.getOwnernName(); + if (owner == null) { + return; + } + + SQLSelectQueryBlock queryBlock = null; + for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { + if (parent instanceof SQLTableSource) { + return; + } + if (parent instanceof SQLSelectQueryBlock) { + queryBlock = (SQLSelectQueryBlock) parent; + break; + } + } + + if (queryBlock == null) { + return; + } + + SQLTableSource tableSource = queryBlock.findTableSource(owner); + if (tableSource != null) { + x.setResolvedTableSource(tableSource); + SQLColumnDefinition column = tableSource.findColumn(x.getName()); + if (column != null) { + x.setResolvedColumn(column); + } + } + } + + private void resolve(SchemaResolveVisitor visitor, SQLIdentifierExpr x) { SQLSelectQueryBlock queryBlock = null; for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) { if (parent instanceof SQLTableSource) { @@ -390,15 +462,30 @@ public class SchemaRepository { } String ident = x.getName(); - SQLTableSource tableSource = queryBlock.findTableSourceWithColumn(ident); + SQLTableSource tableSource = null; + if (queryBlock.getFrom() instanceof SQLJoinTableSource) { + tableSource = queryBlock.findTableSourceWithColumn(ident); + } else { + tableSource = queryBlock.getFrom(); + } + if (tableSource != null) { - String alias = tableSource.computeAlias(); - SQLPropertyExpr propertyExpr = new SQLPropertyExpr(alias, ident); - SQLUtils.replaceInParent(x, propertyExpr); + x.setResolvedTableSource(tableSource); + + SQLColumnDefinition column = tableSource.findColumn(ident); + if (column != null) { + x.setResolvedColumn(column); + } + + if (queryBlock.getFrom() instanceof SQLJoinTableSource) { + String alias = tableSource.computeAlias(); + SQLPropertyExpr propertyExpr = new SQLPropertyExpr(alias, ident); + SQLUtils.replaceInParent(x, propertyExpr); + } } } - private void resolve(SQLASTVisitor visitor, SQLExprTableSource x) { + private void resolve(SchemaResolveVisitor visitor, SQLExprTableSource x) { if (x.getSchemaObject() != null) { return; } @@ -412,10 +499,11 @@ public class SchemaRepository { } } - private void resolve(SQLASTVisitor visitor, SQLSelectQueryBlock x) { + private void resolve(SchemaResolveVisitor visitor, SQLSelectQueryBlock x) { SQLTableSource from = x.getFrom(); - from.accept(visitor); - + if (from != null) { + from.accept(visitor); + } List selectList = x.getSelectList(); List columns = new ArrayList(); @@ -423,13 +511,17 @@ public class SchemaRepository { SQLSelectItem selectItem = selectList.get(i); SQLExpr expr = selectItem.getExpr(); if (expr instanceof SQLAllColumnExpr) { - extractColumns(from, columns); + if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) { + extractColumns(from, columns); + } } else if (expr instanceof SQLPropertyExpr) { SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; String ownerName = propertyExpr.getOwnernName(); if (propertyExpr.getName().equals("*")) { - SQLTableSource tableSource = x.findTableSource(ownerName); - extractColumns(tableSource, columns); + if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) { + SQLTableSource tableSource = x.findTableSource(ownerName); + extractColumns(tableSource, columns); + } } SQLColumnDefinition column = propertyExpr.getResolvedColumn(); @@ -542,12 +634,16 @@ public class SchemaRepository { 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 OracleConsoleSchemaVisitor extends OracleASTVisitorAdapter { @@ -601,6 +697,11 @@ public class SchemaRepository { setDefaultSchema(schema); return false; } + + public boolean visit(SQLDropIndexStatement x) { + acceptDropIndex(x); + return false; + } } public class DefaultConsoleSchemaVisitor extends SQLASTVisitorAdapter { @@ -643,6 +744,11 @@ public class SchemaRepository { acceptAlterTable(x); return false; } + + public boolean visit(SQLDropIndexStatement x) { + acceptDropIndex(x); + return false; + } } boolean acceptCreateTable(MySqlCreateTableStatement x) { @@ -668,7 +774,7 @@ public class SchemaRepository { SQLSelect select = x.getSelect(); if (select != null) { - select.accept(resolveVisitor); + select.accept(createResolveVisitor(SchemaResolveVisitor.Option.ResolveAllColumn)); SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock(); if (queryBlock != null) { @@ -714,7 +820,7 @@ public class SchemaRepository { return true; } - public boolean acceptView(SQLCreateViewStatement x) { + boolean acceptView(SQLCreateViewStatement x) { String schemaName = x.getSchema(); Schema schema = findSchema(schemaName, true); @@ -731,7 +837,22 @@ public class SchemaRepository { return true; } - public boolean acceptCreateIndex(SQLCreateIndexStatement x) { + boolean acceptDropIndex(SQLDropIndexStatement x) { + SQLName table = x.getTableName().getName(); + SchemaObject object = findTable(table); + + if (object != null) { + SQLCreateTableStatement stmt = (SQLCreateTableStatement) object.getStatement(); + if (stmt != null) { + stmt.apply(x); + return true; + } + } + + return false; + } + + boolean acceptCreateIndex(SQLCreateIndexStatement x) { String schemaName = x.getSchema(); Schema schema = findSchema(schemaName, true); @@ -744,7 +865,7 @@ public class SchemaRepository { return true; } - public boolean acceptCreateFunction(SQLCreateFunctionStatement x) { + boolean acceptCreateFunction(SQLCreateFunctionStatement x) { String schemaName = x.getSchema(); Schema schema = findSchema(schemaName, true); @@ -756,7 +877,7 @@ public class SchemaRepository { return true; } - public boolean acceptAlterTable(SQLAlterTableStatement x) { + boolean acceptAlterTable(SQLAlterTableStatement x) { String schemaName = x.getSchema(); Schema schema = findSchema(schemaName, true); diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java new file mode 100644 index 0000000000..bdf8f959a0 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java @@ -0,0 +1,50 @@ +/* + * 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.repository; + +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +/** + * Created by wenshao on 03/08/2017. + */ +public interface SchemaResolveVisitor extends SQLASTVisitor { + + boolean isEnabled(Option option); + + public static enum Option { + ResolveAllColumn + ; + private Option() { + mask = (1 << ordinal()); + } + + public final int mask; + + public static int of(Option... options) { + if (options == null) { + return 0; + } + + int value = 0; + + for (Option option : options) { + value |= option.mask; + } + + return value; + } + } +} diff --git a/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java b/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java index 797b2a19f3..04fd4ef9a8 100644 --- a/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java +++ b/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java @@ -614,7 +614,7 @@ public class MonitorDaoJdbcImpl implements MonitorDao { } protected long getSqlHash(String sql) { - return Utils.murmurhash2_64(sql); + return Utils.fnv_64(sql); } static void setParam(PreparedStatement stmt, int paramIndex, String value) throws SQLException { diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index 81a6a64276..2aa2018835 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -2505,6 +2505,10 @@ public class WallVisitorUtils { allow = config.isBlockAllow(); denyMessage = "block statement not allow"; errorCode = ErrorCode.BLOCK_NOT_ALLOW; + } else if (x instanceof SQLExplainStatement) { + allow = true; + errorCode = 0; + denyMessage = null; } else { allow = config.isNoneBaseStatementAllow(); errorCode = ErrorCode.NONE_BASE_STATEMENT_NOT_ALLOW; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/SQLJoinTest.java b/src/test/java/com/alibaba/druid/bvt/sql/SQLJoinTest.java new file mode 100644 index 0000000000..29461398fc --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/SQLJoinTest.java @@ -0,0 +1,26 @@ +package com.alibaba.druid.bvt.sql; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +/** + * Created by wenshao on 03/08/2017. + */ +public class SQLJoinTest extends TestCase { + public void test_0() throws Exception { + SQLSelectStatement stmt = (SQLSelectStatement) + SQLUtils.parseStatements("select a.* from t_user a inner join t_group b on a.gid = b.id", JdbcConstants.ORACLE) + .get(0); + + SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock(); + assertNotNull(queryBlock); + + SQLJoinTableSource join = (SQLJoinTableSource) queryBlock.getFrom(); + assertTrue(join.match("a", "b")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlCreateTable_showColumns_repository_test.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlCreateTable_showColumns_repository_test.java index 99ffafde40..d2cbb99f8b 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlCreateTable_showColumns_repository_test.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlCreateTable_showColumns_repository_test.java @@ -27,6 +27,8 @@ public class MySqlCreateTable_showColumns_repository_test extends MysqlTest { public void test_0() throws Exception { + repository.console("use sc00;"); + String sql = "CREATE TABLE `test1` (\n" + " `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + " `c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\n" + @@ -481,5 +483,176 @@ public class MySqlCreateTable_showColumns_repository_test extends MysqlTest { repository.console("DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `sc01`.`test6`;"); assertEquals("\n", repository.console("show tables from sc01")); + + assertEquals("CREATE TABLE `test1` (\n" + + "\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + + "\t`c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\n" + + "\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\n" + + "\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\n" + + "\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\n" + + "\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\n" + + "\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\n" + + "\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\n" + + "\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\n" + + "\t`c_time` time DEFAULT NULL COMMENT 'time',\n" + + "\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\n" + + "\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\n" + + "\t`c_blob` blob COMMENT 'blob',\n" + + "\t`c_text` text COMMENT 'text',\n" + + "\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\n" + + "\t`c_longblob` longblob COMMENT 'longblob',\n" + + "\tKEY `k_c` (`c_tinyint`, `c_int`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT = '10000000'" + + , repository.console("show create table test1")); + + + repository.console(" alter table test1 change c_tinyint c_tinyint_x tinyint(4) DEFAULT '1' COMMENT 'tinyint x' first;"); + + assertEquals("CREATE TABLE `test1` (\n" + + "\tc_tinyint_x tinyint(4) DEFAULT '1' COMMENT 'tinyint x',\n" + + "\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + + "\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\n" + + "\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\n" + + "\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\n" + + "\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\n" + + "\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\n" + + "\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\n" + + "\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\n" + + "\t`c_time` time DEFAULT NULL COMMENT 'time',\n" + + "\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\n" + + "\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\n" + + "\t`c_blob` blob COMMENT 'blob',\n" + + "\t`c_text` text COMMENT 'text',\n" + + "\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\n" + + "\t`c_longblob` longblob COMMENT 'longblob',\n" + + "\tKEY `k_c` (c_tinyint_x, `c_int`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT = '10000000'" + + , repository.console("show create table test1")); + + repository.console(" alter table test1 drop c_tinyint_x"); + + assertEquals("CREATE TABLE `test1` (\n" + + "\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + + "\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\n" + + "\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\n" + + "\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\n" + + "\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\n" + + "\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\n" + + "\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\n" + + "\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\n" + + "\t`c_time` time DEFAULT NULL COMMENT 'time',\n" + + "\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\n" + + "\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\n" + + "\t`c_blob` blob COMMENT 'blob',\n" + + "\t`c_text` text COMMENT 'text',\n" + + "\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\n" + + "\t`c_longblob` longblob COMMENT 'longblob',\n" + + "\tKEY `k_c` (`c_int`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT = '10000000'" + + , repository.console("show create table test1")); + + repository.console(" alter table test1 add index name_idx(c_char,c_date);"); + + assertEquals("CREATE TABLE `test1` (\n" + + "\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + + "\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\n" + + "\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\n" + + "\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\n" + + "\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\n" + + "\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\n" + + "\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\n" + + "\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\n" + + "\t`c_time` time DEFAULT NULL COMMENT 'time',\n" + + "\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\n" + + "\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\n" + + "\t`c_blob` blob COMMENT 'blob',\n" + + "\t`c_text` text COMMENT 'text',\n" + + "\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\n" + + "\t`c_longblob` longblob COMMENT 'longblob',\n" + + "\tKEY `k_c` (`c_int`),\n" + + "\tINDEX name_idx(c_char, c_date)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT = '10000000'" + + , repository.console("show create table test1")); + + + assertEquals("+--------------+--------------+------+-----+---------------------+-----------------------------+\n" + + "| Field | Type | Null | Key | Default | Extra |\n" + + "+--------------+--------------+------+-----+---------------------+-----------------------------+\n" + + "| c_decimal_1 | INT(11) | YES | | NULL | |\n" + + "| id | bigint(20) | YES | | NULL | auto_increment |\n" + + "| c_smallint | smallint(6) | NO | | 0 | |\n" + + "| c_mediumint | mediumint(9) | NO | | NULL | |\n" + + "| c_int | int(11) | NO | MUL | NULL | |\n" + + "| c_bigint | bigint(20) | NO | | NULL | |\n" + + "| c_date | date | NO | | 0000-00-00 | |\n" + + "| c_datetime | datetime | NO | | 0000-00-00 00:00:00 | |\n" + + "| c_timestamp | timestamp | NO | | NULL | on update CURRENT_TIMESTAMP |\n" + + "| c_time | time | NO | | NULL | |\n" + + "| c_char | char(10) | NO | | NULL | |\n" + + "| c_varchar | varchar(10) | NO | | hello | |\n" + + "| c_blob | blob | NO | | NULL | |\n" + + "| c_text | text | NO | | NULL | |\n" + + "| c_mediumtext | mediumtext | NO | | NULL | |\n" + + "| c_longblob | longblob | NO | | NULL | |\n" + + "+--------------+--------------+------+-----+---------------------+-----------------------------+\n" + + , repository.console("show columns from test1")); + + + repository.console(" drop index name_idx on test1"); + + assertEquals("CREATE TABLE `test1` (\n" + + "\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + + "\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\n" + + "\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\n" + + "\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\n" + + "\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\n" + + "\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\n" + + "\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\n" + + "\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\n" + + "\t`c_time` time DEFAULT NULL COMMENT 'time',\n" + + "\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\n" + + "\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\n" + + "\t`c_blob` blob COMMENT 'blob',\n" + + "\t`c_text` text COMMENT 'text',\n" + + "\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\n" + + "\t`c_longblob` longblob COMMENT 'longblob',\n" + + "\tKEY `k_c` (`c_int`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT = '10000000'" + + , repository.console("show create table test1")); + + repository.console("alter table test1 modify c_char char(32) after id"); + + assertEquals("CREATE TABLE `test1` (\n" + + "\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\n" + + "\tc_char char(32),\n" + + "\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\n" + + "\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\n" + + "\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\n" + + "\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\n" + + "\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\n" + + "\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\n" + + "\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\n" + + "\t`c_time` time DEFAULT NULL COMMENT 'time',\n" + + "\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\n" + + "\t`c_blob` blob COMMENT 'blob',\n" + + "\t`c_text` text COMMENT 'text',\n" + + "\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\n" + + "\t`c_longblob` longblob COMMENT 'longblob',\n" + + "\tKEY `k_c` (`c_int`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT = '10000000'" + + , repository.console("show create table test1")); } }