diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingPreparedStatement.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingPreparedStatement.java index f2afd10e7f8341e39e71ba97b393efb9bfcca7c3..2e38b2c12a9f42bf0ecf042a5e89f00b019fd8b6 100644 --- a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingPreparedStatement.java +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingPreparedStatement.java @@ -35,6 +35,7 @@ import io.shardingjdbc.core.merger.SelectMergeEngine; import io.shardingjdbc.core.parsing.parser.context.GeneratedKey; import io.shardingjdbc.core.parsing.parser.sql.dal.DALStatement; import io.shardingjdbc.core.parsing.parser.sql.dml.insert.InsertStatement; +import io.shardingjdbc.core.parsing.parser.sql.dql.DQLStatement; import io.shardingjdbc.core.parsing.parser.sql.dql.select.SelectStatement; import io.shardingjdbc.core.routing.PreparedStatementRoutingEngine; import io.shardingjdbc.core.routing.SQLExecutionUnit; @@ -274,7 +275,7 @@ public final class ShardingPreparedStatement extends AbstractShardingPreparedSta if (null != currentResultSet) { return currentResultSet; } - if (1 == routedStatements.size()) { + if (1 == routedStatements.size() && routeResult.getSqlStatement() instanceof DQLStatement) { currentResultSet = routedStatements.iterator().next().getResultSet(); return currentResultSet; } diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingStatement.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingStatement.java index f571ee7665bcf03737f112863a3b6ce8df7e7c44..85a4f31e66ca28b04c69df69b1eaff355cd514fb 100644 --- a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingStatement.java +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/jdbc/core/statement/ShardingStatement.java @@ -31,6 +31,7 @@ import io.shardingjdbc.core.merger.SelectMergeEngine; import io.shardingjdbc.core.parsing.parser.context.GeneratedKey; import io.shardingjdbc.core.parsing.parser.sql.dal.DALStatement; import io.shardingjdbc.core.parsing.parser.sql.dml.insert.InsertStatement; +import io.shardingjdbc.core.parsing.parser.sql.dql.DQLStatement; import io.shardingjdbc.core.parsing.parser.sql.dql.select.SelectStatement; import io.shardingjdbc.core.routing.SQLExecutionUnit; import io.shardingjdbc.core.routing.SQLRouteResult; @@ -249,7 +250,7 @@ public class ShardingStatement extends AbstractStatementAdapter { if (null != currentResultSet) { return currentResultSet; } - if (1 == routedStatements.size()) { + if (1 == routedStatements.size() && routeResult.getSqlStatement() instanceof DQLStatement) { currentResultSet = routedStatements.iterator().next().getResultSet(); return currentResultSet; } diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/DALMergeEngine.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/DALMergeEngine.java index 2f2f0f58736efc8a6832eebd14bdf88b5fa064c7..98ee10a819e16948d2d11873d6118210c370c0c9 100644 --- a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/DALMergeEngine.java +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/DALMergeEngine.java @@ -17,9 +17,11 @@ package io.shardingjdbc.core.merger; +import io.shardingjdbc.core.merger.show.ShowCreateTableResultSetMerger; import io.shardingjdbc.core.merger.show.ShowDatabasesResultSetMerger; import io.shardingjdbc.core.merger.show.ShowOtherResultSetMerger; import io.shardingjdbc.core.merger.show.ShowTablesResultSetMerger; +import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowCreateTableStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowDatabasesStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowTablesStatement; import io.shardingjdbc.core.parsing.parser.sql.dal.DALStatement; @@ -52,6 +54,9 @@ public final class DALMergeEngine implements MergeEngine { if (dalStatement instanceof ShowTablesStatement) { return new ShowTablesResultSetMerger(shardingRule, resultSets); } + if (dalStatement instanceof ShowCreateTableStatement) { + return new ShowCreateTableResultSetMerger(shardingRule, resultSets); + } return new ShowOtherResultSetMerger(resultSets.get(0)); } } diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/show/ShowCreateTableResultSetMerger.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/show/ShowCreateTableResultSetMerger.java new file mode 100644 index 0000000000000000000000000000000000000000..c3dc04e186efc4615461575b4815be22a821ece2 --- /dev/null +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/merger/show/ShowCreateTableResultSetMerger.java @@ -0,0 +1,78 @@ +package io.shardingjdbc.core.merger.show; + +import com.google.common.base.Optional; +import io.shardingjdbc.core.constant.DatabaseType; +import io.shardingjdbc.core.merger.common.AbstractMemoryResultSetMerger; +import io.shardingjdbc.core.merger.common.MemoryResultSetRow; +import io.shardingjdbc.core.parsing.SQLParsingEngine; +import io.shardingjdbc.core.rule.ShardingRule; +import io.shardingjdbc.core.rule.TableRule; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * Show create table result set merger. + * + * @author zhangliang + */ +public final class ShowCreateTableResultSetMerger extends AbstractMemoryResultSetMerger { + + private static final Map LABEL_AND_INDEX_MAP = new HashMap<>(2, 1); + + private final ShardingRule shardingRule; + + private final Iterator memoryResultSetRows; + + static { + LABEL_AND_INDEX_MAP.put("Table", 1); + LABEL_AND_INDEX_MAP.put("Create Table", 2); + } + + public ShowCreateTableResultSetMerger(final ShardingRule shardingRule, final List resultSets) throws SQLException { + super(LABEL_AND_INDEX_MAP); + this.shardingRule = shardingRule; + memoryResultSetRows = init(resultSets); + } + + private Iterator init(final List resultSets) throws SQLException { + List result = new LinkedList<>(); + for (ResultSet each : resultSets) { + while (each.next()) { + MemoryResultSetRow memoryResultSetRow = new MemoryResultSetRow(each); + String tableName = memoryResultSetRow.getCell(1).toString(); + Optional tableRule = shardingRule.tryFindTableRuleByActualTable(tableName); + if (tableRule.isPresent()) { + String logicTableName = tableRule.get().getLogicTable(); + memoryResultSetRow.setCell(1, logicTableName); + String createTableDDL = memoryResultSetRow.getCell(2).toString(); + SQLParsingEngine sqlParsingEngine = new SQLParsingEngine(DatabaseType.MySQL, createTableDDL, shardingRule); + String actualTableName = sqlParsingEngine.parse().getTables().getSingleTableName(); + if (actualTableName.startsWith("`")) { + logicTableName = "`" + logicTableName + "`"; + } + memoryResultSetRow.setCell(2, createTableDDL.replaceFirst(actualTableName, logicTableName)); + result.add(memoryResultSetRow); + } + } + } + if (!result.isEmpty()) { + setCurrentResultSetRow(result.get(0)); + } + return result.iterator(); + } + + @Override + public boolean next() throws SQLException { + if (memoryResultSetRows.hasNext()) { + setCurrentResultSetRow(memoryResultSetRows.next()); + return true; + } + return false; + } +} diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/sql/MySQLShowParser.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/sql/MySQLShowParser.java index 2643560833c1ba7fb8edcc2f5d2d0e7ff2748096..285db5ea7e03fc69f2e6f30c2c91796a73655dc5 100644 --- a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/sql/MySQLShowParser.java +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/sql/MySQLShowParser.java @@ -5,6 +5,7 @@ import io.shardingjdbc.core.parsing.lexer.dialect.mysql.MySQLKeyword; import io.shardingjdbc.core.parsing.lexer.token.DefaultKeyword; import io.shardingjdbc.core.parsing.parser.clause.TableReferencesClauseParser; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowColumnsStatement; +import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowCreateTableStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowDatabasesStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowOtherStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowTablesStatement; @@ -45,9 +46,15 @@ public final class MySQLShowParser extends AbstractShowParser { DALStatement result = new ShowColumnsStatement(); lexerEngine.skipIfEqual(DefaultKeyword.FROM, DefaultKeyword.IN); tableReferencesClauseParser.parseSingleTableWithoutAlias(result); - lexerEngine.skipIfEqual(DefaultKeyword.FROM, DefaultKeyword.IN); - int beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length(); - result.getSqlTokens().add(new SchemaToken(beginPosition, lexerEngine.getCurrentToken().getLiterals(), result.getTables().getSingleTableName())); + if (lexerEngine.skipIfEqual(DefaultKeyword.FROM, DefaultKeyword.IN)) { + int beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length(); + result.getSqlTokens().add(new SchemaToken(beginPosition, lexerEngine.getCurrentToken().getLiterals(), result.getTables().getSingleTableName())); + } + return result; + } + if (lexerEngine.skipIfEqual(DefaultKeyword.CREATE) && lexerEngine.skipIfEqual(DefaultKeyword.TABLE)) { + DALStatement result = new ShowCreateTableStatement(); + tableReferencesClauseParser.parseSingleTableWithoutAlias(result); return result; } return new ShowOtherStatement(); diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/statement/ShowCreateTableStatement.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/statement/ShowCreateTableStatement.java new file mode 100644 index 0000000000000000000000000000000000000000..514bd4071ea796d460e8d1f380334c8042d66fed --- /dev/null +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/parsing/parser/dialect/mysql/statement/ShowCreateTableStatement.java @@ -0,0 +1,11 @@ +package io.shardingjdbc.core.parsing.parser.dialect.mysql.statement; + +import io.shardingjdbc.core.parsing.parser.sql.dal.DALStatement; + +/** + * Show create table statement. + * + * @author zhangliang + */ +public final class ShowCreateTableStatement extends DALStatement { +} diff --git a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/routing/router/ParsingSQLRouter.java b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/routing/router/ParsingSQLRouter.java index 0c07fcbf2fad4e030f6335292345fdde9027fbbb..936557c392a4155152b537e8de26d5f21d4557eb 100644 --- a/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/routing/router/ParsingSQLRouter.java +++ b/sharding-jdbc-core/src/main/java/io/shardingjdbc/core/routing/router/ParsingSQLRouter.java @@ -21,13 +21,11 @@ import io.shardingjdbc.core.constant.DatabaseType; import io.shardingjdbc.core.jdbc.core.ShardingContext; import io.shardingjdbc.core.parsing.SQLParsingEngine; import io.shardingjdbc.core.parsing.parser.context.GeneratedKey; -import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.DescribeStatement; -import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowColumnsStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowDatabasesStatement; -import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowOtherStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.ShowTablesStatement; import io.shardingjdbc.core.parsing.parser.dialect.mysql.statement.UseStatement; import io.shardingjdbc.core.parsing.parser.sql.SQLStatement; +import io.shardingjdbc.core.parsing.parser.sql.dal.DALStatement; import io.shardingjdbc.core.parsing.parser.sql.ddl.DDLStatement; import io.shardingjdbc.core.parsing.parser.sql.dml.insert.InsertStatement; import io.shardingjdbc.core.parsing.parser.sql.dql.select.SelectStatement; @@ -125,7 +123,7 @@ public final class ParsingSQLRouter implements SQLRouter { routingEngine = new TableBroadcastRoutingEngine(shardingRule, sqlStatement); } else if (sqlStatement instanceof ShowDatabasesStatement || sqlStatement instanceof ShowTablesStatement) { routingEngine = new DatabaseBroadcastRoutingEngine(shardingRule); - } else if (sqlStatement instanceof ShowColumnsStatement || sqlStatement instanceof ShowOtherStatement || sqlStatement instanceof DescribeStatement) { + } else if (sqlStatement instanceof DALStatement) { routingEngine = new UnicastRoutingEngine(shardingRule, sqlStatement); } else if (tableNames.isEmpty() && sqlStatement instanceof SelectStatement) { routingEngine = new UnicastRoutingEngine(shardingRule, sqlStatement);