diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowTablesHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowTablesHandler.java index 3a5a60353..edabd4136 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowTablesHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowTablesHandler.java @@ -74,7 +74,7 @@ public class ShowTablesHandler extends SingleNodeHandler { bufInf = ShowTables.writeFullTablesHeader(buffer, shardingService, schemaColumn, fieldPackets); buffer = bufInf.getBuffer(); if (info.getWhere() != null) { - MySQLItemVisitor mev = new MySQLItemVisitor(shardingService.getSchema(), shardingService.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), shardingService.equivalentUsrVarMap()); + MySQLItemVisitor mev = new MySQLItemVisitor(shardingService.getSchema(), shardingService.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), shardingService.getUsrVariables()); info.getWhereExpr().accept(mev); sourceFields = HandlerTool.createFields(fieldPackets); whereItem = HandlerTool.createItem(mev.getItem(), sourceFields, 0, false, DMLResponseHandler.HandlerType.WHERE); diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowVariablesHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowVariablesHandler.java index ecf7e7e76..ab88e6302 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowVariablesHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ShowVariablesHandler.java @@ -18,7 +18,7 @@ public class ShowVariablesHandler extends SingleNodeHandler { public ShowVariablesHandler(RouteResultset rrs, NonBlockingSession session) { super(rrs, session); - shadowVars = session.getShardingService().equivalentSysVarMap(); + shadowVars = session.getShardingService().getSysVariables(); } @Override diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/CommitStage.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/CommitStage.java index 475b5f115..49876f330 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/CommitStage.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/CommitStage.java @@ -51,7 +51,11 @@ public class CommitStage implements TransactionStage { } else { session.setFinishedCommitTime(); session.setResponseTime(true); - session.getShardingService().write(sendData != null ? sendData : session.getShardingService().getSession2().getOKPacket()); + if (sendData != null) { + session.getShardingService().write(sendData); + } else { + session.getShardingService().writeOkPacket(); + } } session.clearSavepoint(); return null; diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/RollbackStage.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/RollbackStage.java index 8d990acbf..cf452b628 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/RollbackStage.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/normal/stage/RollbackStage.java @@ -52,7 +52,7 @@ public class RollbackStage implements TransactionStage { if (sendData != null) { sendData.write(session.getSource()); } else { - session.getShardingService().write(session.getShardingService().getSession2().getOKPacket()); + session.getShardingService().writeOkPacket(); } session.clearSavepoint(); return null; diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/savepoint/SavePointHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/savepoint/SavePointHandler.java index a0097ea09..3980f564f 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/savepoint/SavePointHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/savepoint/SavePointHandler.java @@ -58,7 +58,7 @@ public class SavePointHandler extends MultiNodeHandler { SavePoint newSp = new SavePoint(spName); if (session.getTargetCount() <= 0) { addSavePoint(newSp); - session.getSource().write(OkPacket.OK); + session.getShardingService().writeOkPacket(); return; } @@ -94,7 +94,7 @@ public class SavePointHandler extends MultiNodeHandler { if (session.getTargetCount() <= 0) { rollbackToSavepoint(sp); - session.getSource().write(OkPacket.OK); + session.getShardingService().writeOkPacket(); return; } @@ -132,7 +132,7 @@ public class SavePointHandler extends MultiNodeHandler { savepoints.setPrev(sp.getPrev()); sp.setPrev(null); } - session.getSource().write(OkPacket.OK); + session.getShardingService().writeOkPacket(); } // find savepoint after named savepoint diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/handler/XAHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/handler/XAHandler.java index 785337403..98b638688 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/handler/XAHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/handler/XAHandler.java @@ -32,7 +32,7 @@ public class XAHandler extends AbstractXAHandler implements TransactionHandler { implicitCommitHandler.next(); return; } - session.getShardingService().write(session.getShardingService().getSession2().getOKPacket()); + session.getShardingService().writeOkPacket(); return; } @@ -55,7 +55,7 @@ public class XAHandler extends AbstractXAHandler implements TransactionHandler { @Override public void rollback() { if (session.getTargetCount() <= 0) { - session.getShardingService().write(session.getShardingService().getSession2().getOKPacket()); + session.getShardingService().writeOkPacket(); return; } diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/stage/XAStage.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/stage/XAStage.java index bbba2eee7..bbe4dec2a 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/stage/XAStage.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/transaction/xa/stage/XAStage.java @@ -63,7 +63,7 @@ public abstract class XAStage implements TransactionStage { if (sendData != null) { sendData.write(session.getSource()); } else { - session.getShardingService().write(session.getShardingService().getSession2().getOKPacket()); + session.getShardingService().writeOkPacket(); } xaHandler.clearResources(); } diff --git a/src/main/java/com/actiontech/dble/config/Versions.java b/src/main/java/com/actiontech/dble/config/Versions.java index f86fd9c36..5efd28115 100644 --- a/src/main/java/com/actiontech/dble/config/Versions.java +++ b/src/main/java/com/actiontech/dble/config/Versions.java @@ -1,12 +1,13 @@ /* -* Copyright (C) 2016-2020 ActionTech. -* based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. -* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. -*/ + * Copyright (C) 2016-2020 ActionTech. + * based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ package com.actiontech.dble.config; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * @author */ diff --git a/src/main/java/com/actiontech/dble/net/handler/FrontendQueryHandler.java b/src/main/java/com/actiontech/dble/net/handler/FrontendQueryHandler.java index e7078c2c8..2a8cb5110 100644 --- a/src/main/java/com/actiontech/dble/net/handler/FrontendQueryHandler.java +++ b/src/main/java/com/actiontech/dble/net/handler/FrontendQueryHandler.java @@ -1,8 +1,8 @@ /* -* Copyright (C) 2016-2020 ActionTech. -* based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. -* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. -*/ + * Copyright (C) 2016-2020 ActionTech. + * based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ package com.actiontech.dble.net.handler; /** @@ -14,7 +14,4 @@ public interface FrontendQueryHandler { void query(String sql); - void setReadOnly(Boolean readOnly); - - void setSessionReadOnly(boolean sessionReadOnly); } diff --git a/src/main/java/com/actiontech/dble/route/parser/druid/impl/DruidModifyParser.java b/src/main/java/com/actiontech/dble/route/parser/druid/impl/DruidModifyParser.java index 57cb48f9f..52f8b7bb2 100644 --- a/src/main/java/com/actiontech/dble/route/parser/druid/impl/DruidModifyParser.java +++ b/src/main/java/com/actiontech/dble/route/parser/druid/impl/DruidModifyParser.java @@ -240,7 +240,7 @@ abstract class DruidModifyParser extends DefaultDruidParser { String tableName = schemaInfo.getTable(); String schemaName = schema == null ? null : schema.getName(); - MySQLPlanNodeVisitor pvisitor = new MySQLPlanNodeVisitor(service.getSchema(), service.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), false, service.equivalentUsrVarMap()); + MySQLPlanNodeVisitor pvisitor = new MySQLPlanNodeVisitor(service.getSchema(), service.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), false, service.getUsrVariables()); pvisitor.visit(select); PlanNode node = pvisitor.getTableNode(); node.setSql(rrs.getStatement()); diff --git a/src/main/java/com/actiontech/dble/rwsplit/RWSplitNonBlockingSession.java b/src/main/java/com/actiontech/dble/rwsplit/RWSplitNonBlockingSession.java index 8d0330316..39b86999a 100644 --- a/src/main/java/com/actiontech/dble/rwsplit/RWSplitNonBlockingSession.java +++ b/src/main/java/com/actiontech/dble/rwsplit/RWSplitNonBlockingSession.java @@ -2,6 +2,7 @@ package com.actiontech.dble.rwsplit; import com.actiontech.dble.backend.datasource.PhysicalDbGroup; import com.actiontech.dble.backend.datasource.PhysicalDbInstance; +import com.actiontech.dble.config.ErrorCode; import com.actiontech.dble.net.connection.BackendConnection; import com.actiontech.dble.services.rwsplit.Callback; import com.actiontech.dble.services.rwsplit.RWSplitHandler; @@ -10,6 +11,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.sql.SQLSyntaxErrorException; public class RWSplitNonBlockingSession { @@ -23,21 +25,49 @@ public class RWSplitNonBlockingSession { this.rwSplitService = service; } - public void execute(boolean master, Callback callback) throws IOException { + public void execute(boolean master, Callback callback) { execute(master, null, callback); } - public void execute(boolean master, byte[] originPacket, Callback callback) throws IOException { - RWSplitHandler handler = new RWSplitHandler(rwSplitService, originPacket, callback); - if (conn != null && !conn.isClosed()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("select bind conn[id={}]", conn.getId()); + public void execute(boolean master, byte[] originPacket, Callback callback) { + try { + RWSplitHandler handler = new RWSplitHandler(rwSplitService, originPacket, callback); + if (conn != null && !conn.isClosed()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("select bind conn[id={}]", conn.getId()); + } + checkDest(!conn.getInstance().isReadInstance()); + handler.execute(conn); + return; } - handler.execute(conn); + + PhysicalDbInstance instance = rwGroup.select(master); + checkDest(!instance.isReadInstance()); + instance.getConnection(rwSplitService.getSchema(), handler, null, false); + } catch (IOException e) { + LOGGER.warn("select conn error", e); + rwSplitService.writeErrMessage(ErrorCode.ER_UNKNOWN_ERROR, e.getMessage()); + } catch (SQLSyntaxErrorException se) { + rwSplitService.writeErrMessage(ErrorCode.ER_UNKNOWN_ERROR, se.getMessage()); + } + } + + private void checkDest(boolean isMaster) throws SQLSyntaxErrorException { + String dest = rwSplitService.getExpectedDest(); + if (dest == null) { return; } - PhysicalDbInstance instance = rwGroup.select(master); - instance.getConnection(rwSplitService.getSchema(), handler, null, false); + if (dest.equalsIgnoreCase("M") && isMaster) { + return; + } + if (dest.equalsIgnoreCase("S") && !isMaster) { + return; + } + throw new SQLSyntaxErrorException("unexpected dble_dest_expect,real[" + (isMaster ? "M" : "S") + "],expect[" + dest + "]"); + } + + public PhysicalDbGroup getRwGroup() { + return rwGroup; } public void setRwGroup(PhysicalDbGroup rwGroup) { @@ -51,8 +81,17 @@ public class RWSplitNonBlockingSession { this.conn = bindConn; } + public void unbindIfSafe(boolean safe) { + if (safe) { + this.conn.release(); + this.conn = null; + } else { + unbindIfSafe(); + } + } + public void unbindIfSafe() { - if (rwSplitService.isAutocommit() && !rwSplitService.isLocked() && + if (rwSplitService.isAutocommit() && !rwSplitService.isTxStart() && !rwSplitService.isLocked() && !rwSplitService.isTxStart() && !rwSplitService.isInLoadData() && !rwSplitService.isInPrepare()) { diff --git a/src/main/java/com/actiontech/dble/server/NonBlockingSession.java b/src/main/java/com/actiontech/dble/server/NonBlockingSession.java index 97006a65c..ff669851a 100644 --- a/src/main/java/com/actiontech/dble/server/NonBlockingSession.java +++ b/src/main/java/com/actiontech/dble/server/NonBlockingSession.java @@ -27,7 +27,6 @@ import com.actiontech.dble.net.connection.BackendConnection; import com.actiontech.dble.net.connection.FrontendConnection; import com.actiontech.dble.net.handler.BackEndDataCleaner; import com.actiontech.dble.net.mysql.MySQLPacket; -import com.actiontech.dble.net.mysql.OkPacket; import com.actiontech.dble.net.mysql.StatusFlags; import com.actiontech.dble.plan.common.exception.MySQLOutPutException; import com.actiontech.dble.plan.node.PlanNode; @@ -608,7 +607,7 @@ public class NonBlockingSession extends Session { TraceManager.TraceObject traceObject = TraceManager.serviceTrace(shardingService, "try-complex-query"); try { SQLSelectStatement ast = (SQLSelectStatement) rrs.getSqlStatement(); - MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(shardingService.getSchema(), shardingService.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), false, shardingService.equivalentUsrVarMap()); + MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(shardingService.getSchema(), shardingService.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), false, shardingService.getUsrVariables()); visitor.visit(ast); PlanNode node = visitor.getTableNode(); if (node.isCorrelatedSubQuery()) { @@ -1030,15 +1029,6 @@ public class NonBlockingSession extends Session { return false; } - public OkPacket getOKPacket() { - OkPacket ok = new OkPacket(); - byte packet = (byte) this.getPacketId().incrementAndGet(); - ok.read(OkPacket.OK); - ok.setPacketId(packet); - return ok; - } - - public void queryCount() { queriesCounter.incrementAndGet(); } diff --git a/src/main/java/com/actiontech/dble/server/ServerQueryHandler.java b/src/main/java/com/actiontech/dble/server/ServerQueryHandler.java index aa1839957..eca8bff25 100644 --- a/src/main/java/com/actiontech/dble/server/ServerQueryHandler.java +++ b/src/main/java/com/actiontech/dble/server/ServerQueryHandler.java @@ -1,8 +1,8 @@ /* -* Copyright (C) 2016-2020 ActionTech. -* based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. -* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. -*/ + * Copyright (C) 2016-2020 ActionTech. + * based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ package com.actiontech.dble.server; import com.actiontech.dble.config.ErrorCode; @@ -27,12 +27,10 @@ public class ServerQueryHandler implements FrontendQueryHandler { private Boolean readOnly = true; private boolean sessionReadOnly = true; - @Override public void setReadOnly(Boolean readOnly) { this.readOnly = readOnly; } - @Override public void setSessionReadOnly(boolean sessionReadOnly) { this.sessionReadOnly = sessionReadOnly; } @@ -143,10 +141,8 @@ public class ServerQueryHandler implements FrontendQueryHandler { service.writeErrMessage(ErrorCode.ER_SYNTAX_ERROR, "Unsupported command"); break; case ServerParse.MYSQL_CMD_COMMENT: - service.write(service.getSession2().getOKPacket()); - break; case ServerParse.MYSQL_COMMENT: - service.write(service.getSession2().getOKPacket()); + service.writeOkPacket(); break; case ServerParse.LOAD_DATA_INFILE_SQL: service.loadDataInfileStart(sql); diff --git a/src/main/java/com/actiontech/dble/server/ServerSptPrepare.java b/src/main/java/com/actiontech/dble/server/ServerSptPrepare.java index 6542757cd..74d12163c 100644 --- a/src/main/java/com/actiontech/dble/server/ServerSptPrepare.java +++ b/src/main/java/com/actiontech/dble/server/ServerSptPrepare.java @@ -1,8 +1,8 @@ /* -* Copyright (C) 2016-2020 ActionTech. -* based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. -* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. -*/ + * Copyright (C) 2016-2020 ActionTech. + * based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ package com.actiontech.dble.server; import com.actiontech.dble.services.mysqlsharding.ShardingService; @@ -57,7 +57,7 @@ public final class ServerSptPrepare { /* In user variable, the string is primordial, so we have to truncate the quotes */ private String getStmtFromUserVar() { String key = "@" + sptStmt; - String stmt = service.equivalentUsrVarMap().get(key); + String stmt = service.getUsrVariables().get(key); String rstmt = null; if (stmt != null) { diff --git a/src/main/java/com/actiontech/dble/server/handler/BeginHandler.java b/src/main/java/com/actiontech/dble/server/handler/BeginHandler.java index c38c496a0..06a1fc402 100644 --- a/src/main/java/com/actiontech/dble/server/handler/BeginHandler.java +++ b/src/main/java/com/actiontech/dble/server/handler/BeginHandler.java @@ -1,8 +1,8 @@ /* -* Copyright (C) 2016-2020 ActionTech. -* based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. -* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. -*/ + * Copyright (C) 2016-2020 ActionTech. + * based on code by MyCATCopyrightHolder Copyright (c) 2013, OpenCloudDB/MyCAT. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ package com.actiontech.dble.server.handler; import com.actiontech.dble.log.transaction.TxnLogHelper; @@ -18,7 +18,7 @@ public final class BeginHandler { } else { service.setTxStarted(true); TxnLogHelper.putTxnLog(service, stmt); - service.write(service.getSession2().getOKPacket()); + service.writeOkPacket(); } } } diff --git a/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java b/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java index 8eaa3d807..7486ce493 100644 --- a/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java +++ b/src/main/java/com/actiontech/dble/server/handler/ExplainHandler.java @@ -80,7 +80,7 @@ public final class ExplainHandler { private static BaseHandlerBuilder buildNodes(RouteResultset rrs, ShardingService service) { SQLSelectStatement ast = (SQLSelectStatement) rrs.getSqlStatement(); - MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(service.getSchema(), service.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), false, service.equivalentUsrVarMap()); + MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(service.getSchema(), service.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), false, service.getUsrVariables()); visitor.visit(ast); PlanNode node = visitor.getTableNode(); node.setSql(rrs.getStatement()); diff --git a/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java b/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java index 797cda429..a986ea900 100644 --- a/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java +++ b/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java @@ -5,32 +5,27 @@ package com.actiontech.dble.server.handler; -import com.actiontech.dble.services.mysqlsharding.ShardingService; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.sqlengine.SQLQueryResult; import com.actiontech.dble.sqlengine.SQLQueryResultListener; import java.util.Map; public class SetCallBack implements SQLQueryResultListener>> { - private ShardingService service; - private boolean backToOtherThread; + private final MySQLVariablesService service; + private final SetHandler.SetItem[] items; - SetCallBack(ShardingService service) { + SetCallBack(MySQLVariablesService service, SetHandler.SetItem[] items) { this.service = service; + this.items = items; + } @Override public void onResult(SQLQueryResult> result) { if (result.isSuccess()) { - service.executeContextSetTask(); - backToOtherThread = service.executeInnerSetTask(); - } else { - service.getContextTask().clear(); - service.getInnerSetTask().clear(); + service.executeContextSetTask(items); } } - public boolean isBackToOtherThread() { - return backToOtherThread; - } } diff --git a/src/main/java/com/actiontech/dble/server/handler/SetHandler.java b/src/main/java/com/actiontech/dble/server/handler/SetHandler.java index 5526db538..9644b8de7 100644 --- a/src/main/java/com/actiontech/dble/server/handler/SetHandler.java +++ b/src/main/java/com/actiontech/dble/server/handler/SetHandler.java @@ -5,36 +5,26 @@ */ package com.actiontech.dble.server.handler; -import com.actiontech.dble.DbleServer; -import com.actiontech.dble.backend.mysql.CharsetUtil; import com.actiontech.dble.backend.mysql.VersionUtil; import com.actiontech.dble.config.ErrorCode; -import com.actiontech.dble.config.Isolations; -import com.actiontech.dble.config.model.SystemConfig; -import com.actiontech.dble.route.parser.util.Pair; import com.actiontech.dble.route.parser.util.ParseUtil; +import com.actiontech.dble.server.util.SetItemUtil; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.services.mysqlsharding.ShardingService; import com.actiontech.dble.sqlengine.OneRawSQLQueryResultHandler; import com.actiontech.dble.sqlengine.SetTestJob; -import com.actiontech.dble.util.StringUtil; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetTransactionStatement; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.parser.SQLStatementParser; import java.sql.SQLSyntaxErrorException; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** @@ -66,25 +56,166 @@ public final class SetHandler { TRACE } - public static void handle(String stmt, ShardingService shardingService, int offset) { + public static void handle(String stmt, MySQLVariablesService frontService, int offset) { if (!ParseUtil.isSpace(stmt.charAt(offset))) { - shardingService.writeErrMessage(ErrorCode.ERR_WRONG_USED, stmt + " is not supported"); + frontService.writeErrMessage(ErrorCode.ERR_WRONG_USED, stmt + " is not supported"); + return; } + + stmt = convertCharsetKeyWord(stmt); + try { - String smt = convertCharsetKeyWord(stmt); - List>> contextTask = new ArrayList<>(); - List>> innerSetTask = new ArrayList<>(); - StringBuilder contextSetSQL = new StringBuilder(); - if (handleSetStatement(smt, shardingService, contextTask, innerSetTask, contextSetSQL) && contextTask.size() > 0) { - setStmtCallback(contextSetSQL.toString(), shardingService, contextTask, innerSetTask); - } else if (innerSetTask.size() > 0) { - shardingService.setInnerSetTask(innerSetTask); - if (!shardingService.executeInnerSetTask()) { - shardingService.write(shardingService.getSession2().getOKPacket()); + SetItem[] items; + StringBuilder setSQL = new StringBuilder("set "); + StringBuilder selectSQL = new StringBuilder("select "); + int userVariableSize = 0; + // parse set sql + SQLStatement statement = parseSQL(stmt); + if (statement instanceof SQLSetStatement) { + List assignItems = ((SQLSetStatement) statement).getItems(); + String key; + int systemVariableIndex = assignItems.size() - 1; + items = new SetItem[assignItems.size()]; + + for (SQLAssignItem sqlAssignItem : assignItems) { + // new set item + key = handleSetKey(sqlAssignItem.getTarget()); + SetItem item = newSetItem(key, sqlAssignItem.getValue()); + if (item.getType() == KeyType.USER_VARIABLES) { + if (setSQL.length() > 4) { + setSQL.append(","); + } + if (selectSQL.length() > 7) { + selectSQL.append(","); + } + setSQL.append(SQLUtils.toMySqlString(sqlAssignItem)); + selectSQL.append(item.getName()); + + items[userVariableSize++] = item; + } else if (item.getType() == KeyType.SYSTEM_VARIABLES) { + if (setSQL.length() > 4) { + setSQL.append(","); + } + setSQL.append(SQLUtils.toMySqlString(sqlAssignItem)); + items[systemVariableIndex--] = item; + } else if (item.getType() == KeyType.XA) { + if (frontService instanceof ShardingService) { + boolean val = Boolean.parseBoolean(item.getValue()); + ((ShardingService) frontService).checkXaStatus(val); + items[systemVariableIndex--] = item; + } else { + throw new SQLSyntaxErrorException("unsupported set xa"); + } + } else { + items[systemVariableIndex--] = item; + } } + } else if (statement instanceof MySqlSetTransactionStatement) { + items = new SetItem[1]; + items[0] = handleTransaction((MySqlSetTransactionStatement) statement); + } else { + frontService.writeErrMessage(ErrorCode.ERR_WRONG_USED, stmt + " is not supported"); + return; } + + // check user variables and system variables unused in dble + if (setSQL.length() > 4) { + if (userVariableSize > 0) { + setSQL.append(";").append(selectSQL); + } + checkVariables(frontService, setSQL.toString(), items, userVariableSize); + } else { + frontService.executeContextSetTask(items); + } + } catch (SQLSyntaxErrorException e) { - shardingService.writeErrMessage(ErrorCode.ER_PARSE_ERROR, e.toString()); + frontService.writeErrMessage(ErrorCode.ER_PARSE_ERROR, e.toString()); + } + } + + private static SetItem handleTransaction(MySqlSetTransactionStatement setStatement) throws SQLSyntaxErrorException { + //always single + SetItem item; + if (setStatement.getGlobal() == null) { + throw new SQLSyntaxErrorException("setting transaction without any SESSION or GLOBAL keyword is not supported now"); + } else if (setStatement.getGlobal()) { + throw new SQLSyntaxErrorException("setting GLOBAL value is not supported"); + } else if (setStatement.getAccessModel() != null) { + if (setStatement.getAccessModel().equals("ONLY")) { + item = newSetItem(VersionUtil.TX_READ_ONLY, new SQLBooleanExpr(true)); + } else { + item = newSetItem(VersionUtil.TX_READ_ONLY, new SQLBooleanExpr(false)); + } + } else { + item = newSetItem(VersionUtil.TRANSACTION_ISOLATION, new SQLCharExpr(setStatement.getIsolationLevel())); + } + return item; + } + + //execute multiStmt and callback to reset conn + private static void checkVariables(MySQLVariablesService service, String setSql, SetItem[] items, int userVariableSize) { + OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler(new String[0], new SetCallBack(service, items)); + SetTestJob sqlJob = new SetTestJob(setSql, resultHandler, items, userVariableSize, service); + sqlJob.run(); + } + + private static String handleSetKey(SQLExpr key) throws SQLSyntaxErrorException { + if (key instanceof SQLPropertyExpr) { + SQLPropertyExpr target = (SQLPropertyExpr) key; + if (!(target.getOwner() instanceof SQLVariantRefExpr)) { + throw new SQLSyntaxErrorException("unsupport global"); + } + SQLVariantRefExpr owner = (SQLVariantRefExpr) target.getOwner(); + if (owner.isGlobal()) { + throw new SQLSyntaxErrorException("unsupport global"); + } + return target.getName(); + } else if (key instanceof SQLVariantRefExpr) { + SQLVariantRefExpr target = (SQLVariantRefExpr) key; + if (target.isGlobal()) { + throw new SQLSyntaxErrorException("unsupport global"); + } + return target.getName(); + } else if (key instanceof SQLIdentifierExpr) { + SQLIdentifierExpr target = (SQLIdentifierExpr) key; + return target.getLowerName(); + } + throw new SQLSyntaxErrorException("unknown key type"); + } + + private static SetItem newSetItem(String key, SQLExpr valueExpr) throws SQLSyntaxErrorException { + switch (key.toLowerCase()) { + case "xa": + return new SetItem("xa", SetItemUtil.getBooleanVal(valueExpr), SetHandler.KeyType.XA); + case "trace": + return new SetItem("trace", SetItemUtil.getBooleanVal(valueExpr), SetHandler.KeyType.TRACE); + case "autocommit": + return new SetItem("autocommit", SetItemUtil.getBooleanVal(valueExpr), SetHandler.KeyType.AUTOCOMMIT); + case "collation_connection": + return new SetItem("collation_connection", SetItemUtil.getCollationVal(valueExpr), SetHandler.KeyType.COLLATION_CONNECTION); + case "character_set_client": + return new SetItem("character_set_client", SetItemUtil.getCharsetClientVal(valueExpr), SetHandler.KeyType.CHARACTER_SET_CLIENT); + case "character_set_results": + return new SetItem("character_set_results", SetItemUtil.getCharsetResultsVal(valueExpr), SetHandler.KeyType.CHARACTER_SET_RESULTS); + case "character_set_connection": + return new SetItem("character_set_connection", SetItemUtil.getCharsetConnectionVal(valueExpr), SetHandler.KeyType.CHARACTER_SET_CONNECTION); + case "character set": + return new SetItem(key, SetItemUtil.getCharsetVal(valueExpr), SetHandler.KeyType.CHARSET); + case "names": + return new SetItem(key, SetItemUtil.getNamesVal(valueExpr), SetHandler.KeyType.NAMES); + case VersionUtil.TRANSACTION_ISOLATION: + case VersionUtil.TX_ISOLATION: + return new SetItem(key, SetItemUtil.getIsolationVal(valueExpr), SetHandler.KeyType.TX_ISOLATION); + case VersionUtil.TRANSACTION_READ_ONLY: + case VersionUtil.TX_READ_ONLY: + return new SetItem(key, SetItemUtil.getBooleanVal(valueExpr), SetHandler.KeyType.TX_READ_ONLY); + default: + if (key.startsWith("@@")) { + return new SetItem(key.substring(2), SetItemUtil.parseVariablesValue(valueExpr), KeyType.SYSTEM_VARIABLES); + } else if (key.startsWith("@")) { + return new SetItem(key.toUpperCase(), null, KeyType.USER_VARIABLES); + } + return new SetItem(key, SetItemUtil.parseVariablesValue(valueExpr), KeyType.SYSTEM_VARIABLES); } } @@ -93,465 +224,10 @@ public final class SetHandler { try { return parser.parseStatement(); } catch (Exception t) { - if (t.getMessage() != null) { - throw new SQLSyntaxErrorException(t.getMessage()); - } else { - throw new SQLSyntaxErrorException(t); - } + throw new SQLSyntaxErrorException(t); } } - private static boolean handleSetStatement(String stmt, ShardingService service, List>> contextTask, - List>> innerSetTask, StringBuilder contextSetSQL) throws SQLSyntaxErrorException { - SQLStatement statement = parseSQL(stmt); - if (statement instanceof SQLSetStatement) { - List assignItems = ((SQLSetStatement) statement).getItems(); - if (assignItems.size() == 1) { - contextSetSQL.append(statement.toString()); - return handleSingleVariable(stmt, assignItems.get(0), service, contextTask); - } else { - boolean result = handleSetMultiStatement(assignItems, service, contextTask, innerSetTask); - contextSetSQL.append(statement.toString()); - return result; - } - } else if (statement instanceof MySqlSetTransactionStatement) { - return handleTransaction(service, (MySqlSetTransactionStatement) statement); - } else { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, stmt + " is not recognized and ignored"); - return false; - } - } - - private static boolean handleSetNamesInMultiStmt(ShardingService service, String stmt, String charset, String collate, List>> contextTask) { - NamesInfo charsetInfo = checkSetNames(stmt, charset, collate); - if (charsetInfo != null) { - if (charsetInfo.charset == null) { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charset + " or collate '" + collate + "'"); - return false; - } else if (charsetInfo.collation == null) { - service.writeErrMessage(ErrorCode.ER_COLLATION_CHARSET_MISMATCH, "COLLATION '" + collate + "' is not valid for CHARACTER SET '" + charset + "'"); - return false; - } else if (!charsetInfo.isSupport) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of '" + charsetInfo.charset + "'"); - return false; - } else { - contextTask.add(new Pair<>(KeyType.NAMES, new Pair<>(charsetInfo.charset, charsetInfo.collation))); - return true; - } - } else { - service.writeErrMessage(ErrorCode.ER_PARSE_ERROR, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the SQL: " + stmt); - return false; - } - } - - private static boolean handleSingleSetNames(String stmt, ShardingService shardingService, SQLExpr valueExpr) { - String[] charsetAndCollate = parseNamesValue(valueExpr); - NamesInfo charsetInfo = checkSetNames(stmt, charsetAndCollate[0], charsetAndCollate[1]); - if (charsetInfo != null) { - if (charsetInfo.charset == null) { - shardingService.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set in statement '" + stmt + "'"); - return false; - } else if (charsetInfo.collation == null) { - shardingService.writeErrMessage(ErrorCode.ER_COLLATION_CHARSET_MISMATCH, "COLLATION '" + charsetAndCollate[1] + "' is not valid for CHARACTER SET '" + charsetAndCollate[0] + "'"); - return false; - } else if (!charsetInfo.isSupport) { - shardingService.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of '" + charsetInfo.charset + "'"); - return false; - } else { - shardingService.setNames(charsetInfo.charset, charsetInfo.collation); - shardingService.write(shardingService.getSession2().getOKPacket()); - return true; - } - } else { - shardingService.writeErrMessage(ErrorCode.ER_PARSE_ERROR, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the SQL: " + stmt); - return false; - } - } - - private static boolean handleSingleSetCharset(String stmt, ShardingService shardingService, SQLExpr valueExpr) { - String charsetValue = SetInnerHandler.parseStringValue(valueExpr); - if (charsetValue == null || charsetValue.equalsIgnoreCase("null")) { - shardingService.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set null"); - return false; - } - String charset = getCharset(charsetValue); - if (charset != null) { - if (!CharsetUtil.checkCharsetClient(charset)) { - shardingService.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of '" + charset + "'"); - return false; - } else { - shardingService.setCharacterSet(charset); - shardingService.write(shardingService.getSession2().getOKPacket()); - return true; - } - } else { - shardingService.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set in statement '" + stmt + "'"); - return false; - } - } - - private static boolean handleSetMultiStatement(List assignItems, ShardingService service, List>> contextTask, List>> innerSetTask) { - Set objSet = new HashSet<>(); - for (SQLAssignItem assignItem : assignItems) { - if (!handleVariableInMultiStmt(assignItem, service, contextTask, innerSetTask, objSet)) { - return false; - } - } - for (SQLAssignItem assignItem : objSet) { - assignItems.remove(assignItem); - } - return true; - } - - //execute multiStmt and callback to reset conn - private static void setStmtCallback(String multiStmt, ShardingService service, List>> contextTask, List>> innerSetTask) { - service.setContextTask(contextTask); - service.setInnerSetTask(innerSetTask); - OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler(new String[0], new SetCallBack(service)); - SetTestJob sqlJob = new SetTestJob(multiStmt, null, resultHandler, service); - sqlJob.run(); - } - - private static boolean handleVariableInMultiStmt(SQLAssignItem assignItem, ShardingService service, List>> contextTask, List>> innerSetTask, Set objSet) { - String key = handleSetKey(assignItem, service); - if (key == null) { - return false; - } - SQLExpr valueExpr = assignItem.getValue(); - KeyType keyType = parseKeyType(key, true, KeyType.SYSTEM_VARIABLES); - if (!checkValue(valueExpr, keyType)) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + assignItem.getValue() + "'"); - return false; - } - switch (keyType) { - case XA: - if (!SetInnerHandler.preHandleSingleXA(service, valueExpr, innerSetTask)) { - return false; - } - objSet.add(assignItem); - break; - case TRACE: - if (!SetInnerHandler.preHandleSingleTrace(service, valueExpr, innerSetTask)) { - return false; - } - objSet.add(assignItem); - break; - case AUTOCOMMIT: - if (!SetInnerHandler.preHandleAutocommit(service, valueExpr, innerSetTask)) { - return false; - } - objSet.add(assignItem); - break; - case NAMES: { - String charset = SetInnerHandler.parseStringValue(valueExpr); - //TODO:druid lost collation info - if (!handleSetNamesInMultiStmt(service, "SET NAMES " + charset, charset, null, contextTask)) - return false; - break; - } - case CHARSET: { - String charset = SetInnerHandler.parseStringValue(valueExpr); - if (!handleCharsetInMultiStmt(service, charset, contextTask)) return false; - break; - } - case CHARACTER_SET_CLIENT: - if (!handleCharsetClientInMultiStmt(service, contextTask, valueExpr)) return false; - break; - case CHARACTER_SET_CONNECTION: - if (!handleCharsetConnInMultiStmt(service, contextTask, valueExpr)) return false; - break; - case CHARACTER_SET_RESULTS: - if (!handleCharsetResultsInMultiStmt(service, contextTask, valueExpr)) return false; - break; - case COLLATION_CONNECTION: - if (!handleCollationConnInMultiStmt(service, contextTask, valueExpr)) return false; - break; - case TX_READ_ONLY: - if (!handleReadOnlyInMultiStmt(service, contextTask, valueExpr)) return false; - break; - case TX_ISOLATION: - if (!handleTxIsolationInMultiStmt(service, contextTask, valueExpr)) return false; - break; - case SYSTEM_VARIABLES: - if (key.startsWith("@@")) { - key = key.substring(2); - } - if (DbleServer.getInstance().getSystemVariables().getDefaultValue(key) == null) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "system variable " + key + " is not supported"); - } - contextTask.add(new Pair<>(KeyType.SYSTEM_VARIABLES, new Pair<>(key, parseVariablesValue(valueExpr)))); - break; - case USER_VARIABLES: - contextTask.add(new Pair<>(KeyType.USER_VARIABLES, new Pair<>(key.toUpperCase(), parseVariablesValue(valueExpr)))); - break; - default: - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, key + " is not supported"); - return false; - } - return true; - } - - private static boolean handleCharsetInMultiStmt(ShardingService service, String charset, List>> contextTask) { - String charsetInfo = getCharset(charset); - if (charsetInfo != null) { - if (!CharsetUtil.checkCharsetClient(charsetInfo)) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of '" + charsetInfo + "'"); - return false; - } else { - contextTask.add(new Pair<>(KeyType.CHARSET, new Pair(charsetInfo, null))); - return true; - } - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charset + "'"); - return false; - } - } - - private static boolean handleTxIsolationInMultiStmt(ShardingService service, List>> contextTask, SQLExpr valueExpr) { - String value = SetInnerHandler.parseStringValue(valueExpr); - Integer txIsolation = getIsolationLevel(value); - if (txIsolation == null) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "Variable 'tx_isolation|transaction_isolation' can't be set to the value of '" + value + "'"); - return false; - } - contextTask.add(new Pair<>(KeyType.TX_ISOLATION, new Pair(String.valueOf(txIsolation), null))); - return true; - } - - private static boolean handleReadOnlyInMultiStmt(ShardingService service, List>> contextTask, SQLExpr valueExpr) { - Boolean switchStatus = SetInnerHandler.isSwitchOn(valueExpr); - if (switchStatus == null) { - service.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'tx_read_only|transaction_read_only'"); - return false; - } else if (switchStatus) { - contextTask.add(new Pair<>(KeyType.TX_READ_ONLY, new Pair("true", null))); - } else { - contextTask.add(new Pair<>(KeyType.TX_READ_ONLY, new Pair("false", null))); - } - return true; - } - - private static boolean handleCollationConnInMultiStmt(ShardingService service, List>> contextTask, SQLExpr valueExpr) { - String collation = SetInnerHandler.parseStringValue(valueExpr); - if (checkCollation(collation)) { - contextTask.add(new Pair<>(KeyType.COLLATION_CONNECTION, new Pair(collation, null))); - return true; - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_COLLATION, "Unknown collation '" + collation + "'"); - return false; - } - } - - private static boolean handleCharsetResultsInMultiStmt(ShardingService service, List>> contextTask, SQLExpr valueExpr) { - String charsetResult = SetInnerHandler.parseStringValue(valueExpr); - if (charsetResult.equalsIgnoreCase("NULL") || checkCharset(charsetResult)) { - contextTask.add(new Pair<>(KeyType.CHARACTER_SET_RESULTS, new Pair(charsetResult, null))); - return true; - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetResult + "'"); - return false; - } - } - - private static boolean handleCharsetConnInMultiStmt(ShardingService service, List>> contextTask, SQLExpr valueExpr) { - String charsetConnection = SetInnerHandler.parseStringValue(valueExpr); - if (charsetConnection.equals("null")) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_connection' can't be set to the value of 'NULL'"); - return false; - } - String collationName = CharsetUtil.getDefaultCollation(charsetConnection); - if (collationName != null) { - contextTask.add(new Pair<>(KeyType.CHARACTER_SET_CONNECTION, new Pair(collationName, null))); - return true; - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetConnection + "'"); - return false; - } - } - - private static boolean handleCharsetClientInMultiStmt(ShardingService service, List>> contextTask, SQLExpr valueExpr) { - String charsetClient = SetInnerHandler.parseStringValue(valueExpr); - if (charsetClient.equalsIgnoreCase("null")) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of 'NULL'"); - return false; - } else if (checkCharset(charsetClient)) { - if (!CharsetUtil.checkCharsetClient(charsetClient)) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of '" + charsetClient + "'"); - return false; - } else { - contextTask.add(new Pair<>(KeyType.CHARACTER_SET_CLIENT, new Pair(charsetClient, null))); - return true; - } - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetClient + "'"); - return false; - } - } - - private static boolean handleSingleVariable(String stmt, SQLAssignItem assignItem, ShardingService shardingService, List>> contextTask) { - String key = handleSetKey(assignItem, shardingService); - if (key == null) return false; - SQLExpr valueExpr = assignItem.getValue(); - KeyType keyType = parseKeyType(key, true, KeyType.SYSTEM_VARIABLES); - if (!checkValue(valueExpr, keyType)) { - shardingService.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + SQLUtils.toMySqlString(assignItem.getValue()) + "'"); - return false; - } - switch (keyType) { - case NAMES: - return handleSingleSetNames(stmt, shardingService, valueExpr); - case CHARSET: - return handleSingleSetCharset(stmt, shardingService, valueExpr); - case XA: - return SetInnerHandler.handleSingleXA(shardingService, valueExpr); - case TRACE: - return SetInnerHandler.handleSingleTrace(shardingService, valueExpr); - case AUTOCOMMIT: - return SetInnerHandler.handleSingleAutocommit(stmt, shardingService, valueExpr); - case CHARACTER_SET_CLIENT: - return handleSingleCharsetClient(shardingService, valueExpr); - case CHARACTER_SET_CONNECTION: - return handleSingleCharsetConnection(shardingService, valueExpr); - case CHARACTER_SET_RESULTS: - return handleSingleCharsetResults(shardingService, valueExpr); - case COLLATION_CONNECTION: - return handleCollationConnection(shardingService, valueExpr); - case TX_READ_ONLY: - if (!stmt.toLowerCase().contains("session")) { - shardingService.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting transaction without any SESSION or GLOBAL keyword is not supported now"); - return false; - } - return handleTxReadOnly(shardingService, valueExpr); - case TX_ISOLATION: - if (!stmt.toLowerCase().contains("session")) { - shardingService.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting transaction without any SESSION or GLOBAL keyword is not supported now"); - return false; - } - return handleTxIsolation(shardingService, valueExpr); - case SYSTEM_VARIABLES: - if (key.startsWith("@@")) { - key = key.substring(2); - } - if (DbleServer.getInstance().getSystemVariables().getDefaultValue(key) == null) { - shardingService.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "system variable " + key + " is not supported"); - return false; - } - contextTask.add(new Pair<>(KeyType.SYSTEM_VARIABLES, new Pair<>(key, parseVariablesValue(valueExpr)))); - return true; - case USER_VARIABLES: - contextTask.add(new Pair<>(KeyType.USER_VARIABLES, new Pair<>(key.toUpperCase(), parseVariablesValue(valueExpr)))); - return true; - default: - shardingService.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, stmt + " is not supported"); - return false; - } - } - - private static boolean handleTxReadOnly(ShardingService shardingService, SQLExpr valueExpr) { - Boolean switchStatus = SetInnerHandler.isSwitchOn(valueExpr); - if (switchStatus == null) { - shardingService.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'tx_read_only|transaction_read_only'"); - return false; - } else if (switchStatus) { - shardingService.setSessionReadOnly(true); - shardingService.write(shardingService.getSession2().getOKPacket()); - } else { - shardingService.setSessionReadOnly(false); - shardingService.write(shardingService.getSession2().getOKPacket()); - } - return true; - } - - private static boolean handleTxIsolation(ShardingService service, SQLExpr valueExpr) { - String value = SetInnerHandler.parseStringValue(valueExpr); - Integer txIsolation = getIsolationLevel(value); - if (txIsolation == null) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "Variable 'tx_isolation|transaction_isolation' can't be set to the value of '" + value + "'"); - return false; - } - service.setTxIsolation(txIsolation); - service.write(service.getSession2().getOKPacket()); - return true; - } - - private static Integer getIsolationLevel(String value) { - switch (value) { - case "read-uncommitted": - return Isolations.READ_UNCOMMITTED; - case "read-committed": - return Isolations.READ_COMMITTED; - case "repeatable-read": - return Isolations.REPEATABLE_READ; - case "serializable": - return Isolations.SERIALIZABLE; - default: - return null; - } - } - - private static boolean handleCollationConnection(ShardingService service, SQLExpr valueExpr) { - String collation = SetInnerHandler.parseStringValue(valueExpr); - if (checkCollation(collation)) { - service.setCollationConnection(collation); - service.write(service.getSession2().getOKPacket()); - return true; - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_COLLATION, "Unknown collation '" + collation + "'"); - return false; - } - } - - private static boolean handleSingleCharsetResults(ShardingService shardingService, SQLExpr valueExpr) { - String charsetResult = SetInnerHandler.parseStringValue(valueExpr); - if (charsetResult.equalsIgnoreCase("NULL") || checkCharset(charsetResult)) { - shardingService.setCharacterResults(charsetResult); - shardingService.write(shardingService.getSession2().getOKPacket()); - return true; - } else { - shardingService.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetResult + "'"); - return false; - } - } - - private static boolean handleSingleCharsetConnection(ShardingService shardingService, SQLExpr valueExpr) { - String charsetConnection = SetInnerHandler.parseStringValue(valueExpr); - if (charsetConnection.equals("null")) { - shardingService.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_connection' can't be set to the value of 'NULL'"); - return false; - } - String collationName = CharsetUtil.getDefaultCollation(charsetConnection); - if (collationName != null) { - shardingService.setCharacterConnection(collationName); - shardingService.write(shardingService.getSession2().getOKPacket()); - return true; - } else { - shardingService.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetConnection + "'"); - return false; - } - } - - private static boolean handleSingleCharsetClient(ShardingService service, SQLExpr valueExpr) { - String charsetClient = SetInnerHandler.parseStringValue(valueExpr); - if (charsetClient.equalsIgnoreCase("null")) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of 'NULL'"); - return false; - } - if (checkCharset(charsetClient)) { - if (!CharsetUtil.checkCharsetClient(charsetClient)) { - service.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of '" + charsetClient + "'"); - return false; - } else { - service.setCharacterClient(charsetClient); - service.write(service.getSession2().getOKPacket()); - return true; - } - } else { - service.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetClient + "'"); - return false; - } - } - - // druid not support 'set charset' ,change to 'set character set' private static String convertCharsetKeyWord(String stmt) { StringBuilder result = new StringBuilder(); @@ -562,7 +238,7 @@ public final class SetHandler { char before = toCheck.charAt(index - 1); char after = toCheck.charAt(index + 7); if ((ParseUtil.isSpace(before) || ',' == before) && ParseUtil.isSpace(after)) { - result.append(stmt.substring(tailStart, index)); + result.append(stmt, tailStart, index); result.append("character set"); } tailStart = index + 7; @@ -575,234 +251,40 @@ public final class SetHandler { return stmt; } - private static String handleSetKey(SQLAssignItem assignItem, ShardingService service) { - if (assignItem.getTarget() instanceof SQLPropertyExpr) { - SQLPropertyExpr target = (SQLPropertyExpr) assignItem.getTarget(); - if (!(target.getOwner() instanceof SQLVariantRefExpr)) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + target + "'"); - return null; - } - SQLVariantRefExpr owner = (SQLVariantRefExpr) target.getOwner(); - if (owner.isGlobal()) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting GLOBAL value is not supported"); - return null; - } - return target.getName(); - } else if (assignItem.getTarget() instanceof SQLVariantRefExpr) { - SQLVariantRefExpr target = (SQLVariantRefExpr) assignItem.getTarget(); - if (target.isGlobal()) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting GLOBAL value is not supported"); - return null; - } - return target.getName(); - } else if (assignItem.getTarget() instanceof SQLIdentifierExpr) { - SQLIdentifierExpr target = (SQLIdentifierExpr) assignItem.getTarget(); - return target.getLowerName(); - } else { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + assignItem.getTarget() + "'"); - return null; + public static class SetItem { + private String name; + private String value; + private SetHandler.KeyType type; + + public SetItem(String name, String value, SetHandler.KeyType type) { + this.name = name; + this.value = value; + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public KeyType getType() { + return type; + } + + public void setType(KeyType type) { + this.type = type; } } - private static boolean checkValue(SQLExpr valueExpr, KeyType keyType) { - if (keyType == KeyType.USER_VARIABLES) { - return !(valueExpr instanceof SQLQueryExpr); - } - return (valueExpr instanceof MySqlCharExpr) || (valueExpr instanceof SQLCharExpr) || - (valueExpr instanceof SQLIdentifierExpr) || (valueExpr instanceof SQLIntegerExpr) || - (valueExpr instanceof SQLNumberExpr) || (valueExpr instanceof SQLBooleanExpr) || - (valueExpr instanceof SQLDefaultExpr) || (valueExpr instanceof SQLNullExpr); - } - - private static KeyType parseKeyType(String key, boolean origin, KeyType defaultVariables) { - switch (key.toLowerCase()) { - case "xa": - return KeyType.XA; - case "trace": - return KeyType.TRACE; - case "autocommit": - return KeyType.AUTOCOMMIT; - case "collation_connection": - return KeyType.COLLATION_CONNECTION; - case "character_set_client": - return KeyType.CHARACTER_SET_CLIENT; - case "character_set_results": - return KeyType.CHARACTER_SET_RESULTS; - case "character_set_connection": - return KeyType.CHARACTER_SET_CONNECTION; - case VersionUtil.TRANSACTION_ISOLATION: - case VersionUtil.TX_ISOLATION: - return KeyType.TX_ISOLATION; - case VersionUtil.TRANSACTION_READ_ONLY: - case VersionUtil.TX_READ_ONLY: - return KeyType.TX_READ_ONLY; - case "names": - return KeyType.NAMES; - case "character set": - return KeyType.CHARSET; - default: - if (!origin && key.startsWith("@")) { - return KeyType.SYNTAX_ERROR; - } else if (key.startsWith("@@")) { - return parseKeyType(key.substring(2), false, KeyType.SYSTEM_VARIABLES); - } else if (key.startsWith("@")) { - return parseKeyType(key.substring(1), false, KeyType.USER_VARIABLES); - } else { - return defaultVariables; - } - } - } - - - private static String parseVariablesValue(SQLExpr valueExpr) { - String strValue; - if (valueExpr instanceof SQLIdentifierExpr) { - SQLIdentifierExpr value = (SQLIdentifierExpr) valueExpr; - strValue = "'" + StringUtil.removeBackQuote(value.getSimpleName().toLowerCase()) + "'"; - } else if (valueExpr instanceof SQLCharExpr) { - SQLCharExpr value = (SQLCharExpr) valueExpr; - strValue = "'" + value.getText().toLowerCase() + "'"; - } else if (valueExpr instanceof SQLIntegerExpr) { - SQLIntegerExpr value = (SQLIntegerExpr) valueExpr; - strValue = value.getNumber().toString(); - } else if (valueExpr instanceof SQLNumberExpr) { - SQLNumberExpr value = (SQLNumberExpr) valueExpr; - strValue = value.getNumber().toString(); - } else if (valueExpr instanceof SQLBooleanExpr) { - SQLBooleanExpr value = (SQLBooleanExpr) valueExpr; - strValue = String.valueOf(value.getValue()); - } else if (valueExpr instanceof SQLDefaultExpr || valueExpr instanceof SQLNullExpr) { - strValue = valueExpr.toString(); - } else { - strValue = SQLUtils.toMySqlString(valueExpr); - } - return strValue; - } - - private static String[] parseNamesValue(SQLExpr valueExpr) { - if (valueExpr instanceof MySqlCharExpr) { - MySqlCharExpr value = (MySqlCharExpr) valueExpr; - return new String[]{value.getText().toLowerCase(), StringUtil.removeBackQuote(value.getCollate()).toLowerCase()}; - } else { - String charset = SetInnerHandler.parseStringValue(valueExpr); - return new String[]{charset, null}; - } - } - - - private static boolean handleTransaction(ShardingService service, MySqlSetTransactionStatement setStatement) { - //always single - if (setStatement.getGlobal() == null) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting transaction without any SESSION or GLOBAL keyword is not supported now"); - return false; - } else if (setStatement.getGlobal()) { - service.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting GLOBAL value is not supported"); - return false; - } else if (setStatement.getAccessModel() != null) { - if (setStatement.getAccessModel().equals("ONLY")) { - service.setSessionReadOnly(true); - } else { - service.setSessionReadOnly(false); - } - service.write(service.getSession2().getOKPacket()); - return true; - } else { - int txIsolation = Isolations.REPEATABLE_READ; - switch (setStatement.getIsolationLevel()) { - case "READ UNCOMMITTED": - txIsolation = Isolations.READ_UNCOMMITTED; - break; - case "READ COMMITTED": - txIsolation = Isolations.READ_COMMITTED; - break; - case "REPEATABLE READ": - txIsolation = Isolations.REPEATABLE_READ; - break; - case "SERIALIZABLE": - txIsolation = Isolations.SERIALIZABLE; - break; - default: - // can't be happened - break; - } - service.setTxIsolation(txIsolation); - service.write(service.getSession2().getOKPacket()); - return true; - } - } - - private static boolean checkCollation(String collation) { - int ci = CharsetUtil.getCollationIndex(collation); - return ci > 0; - } - - private static boolean checkCharset(String name) { - int ci = CharsetUtil.getCharsetDefaultIndex(name); - return ci > 0; - } - - private static String getCharset(String charset) { - if (charset.toLowerCase().equals("default")) { - charset = SystemConfig.getInstance().getCharset(); - } - charset = StringUtil.removeApostropheOrBackQuote(charset.toLowerCase()); - if (checkCharset(charset)) { - return charset; - } - return null; - } - - - private static boolean checkSetNamesSyntax(String stmt) { - //druid parser can't find syntax error,use regex to check again, but it is not strict - String regex = "set\\s+names\\s+[`']?[a-zA-Z_0-9]+[`']?(\\s+collate\\s+[`']?[a-zA-Z_0-9]+[`']?)?;?\\s*$"; - Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); - Matcher ma = pattern.matcher(stmt); - return ma.find(); - } - - private static NamesInfo checkSetNames(String stmt, String charset, String collate) { - if (collate == null && !(checkSetNamesSyntax(stmt))) { - return null; - } - if (charset.toLowerCase().equals("default")) { - charset = SystemConfig.getInstance().getCharset(); - } else { - charset = StringUtil.removeApostropheOrBackQuote(charset.toLowerCase()); - if (!checkCharset(charset)) { - return new NamesInfo(null, null); - } - } - if (collate == null) { - collate = CharsetUtil.getDefaultCollation(charset); - } else { - collate = collate.toLowerCase(); - if (collate.equals("default")) { - collate = CharsetUtil.getDefaultCollation(charset); - } else { - int collateIndex = CharsetUtil.getCollationIndexByCharset(charset, collate); - if (collateIndex == 0) { - return new NamesInfo(null, null); - } else if (collateIndex < 0) { - return new NamesInfo(charset, null); - } - } - } - NamesInfo namesInfo = new NamesInfo(charset, collate); - if (!CharsetUtil.checkCharsetClient(charset)) { - namesInfo.isSupport = false; - } - return namesInfo; - } - - private static class NamesInfo { - private String charset; - private String collation; - private boolean isSupport = true; - - NamesInfo(String charset, String collation) { - this.charset = charset; - this.collation = collation; - } - } } diff --git a/src/main/java/com/actiontech/dble/server/handler/SetInnerHandler.java b/src/main/java/com/actiontech/dble/server/handler/SetInnerHandler.java deleted file mode 100644 index bb82763c7..000000000 --- a/src/main/java/com/actiontech/dble/server/handler/SetInnerHandler.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.actiontech.dble.server.handler; - -import com.actiontech.dble.config.ErrorCode; -import com.actiontech.dble.log.transaction.TxnLogHelper; -import com.actiontech.dble.route.parser.util.Pair; -import com.actiontech.dble.services.mysqlsharding.ShardingService; -import com.actiontech.dble.util.StringUtil; -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.expr.*; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by szf on 2020/3/24. - */ -public final class SetInnerHandler { - - - private SetInnerHandler() { - - } - - public static boolean handleSingleXA(ShardingService shardingService, SQLExpr valueExpr) { - List>> innerSetTask = new ArrayList<>(); - if (preHandleSingleXA(shardingService, valueExpr, innerSetTask)) { - String key = innerSetTask.get(0).getValue().getKey(); - shardingService.getSession2().getTransactionManager().setXaTxEnabled(Boolean.valueOf(key), shardingService); - shardingService.write(shardingService.getSession2().getOKPacket()); - return true; - } - return false; - } - - public static boolean preHandleSingleXA(ShardingService shardingService, SQLExpr valueExpr, List>> innerSetTask) { - Boolean switchStatus = isSwitchOn(valueExpr); - if (switchStatus == null) { - shardingService.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'XA'"); - return false; - } else if (switchStatus) { - if (shardingService.getSession2().getTargetMap().size() > 0 && shardingService.getSession2().getSessionXaID() == null) { - shardingService.writeErrMessage(ErrorCode.ERR_WRONG_USED, "you can't set xa cmd on when there are unfinished operation in the session."); - return false; - } - innerSetTask.add(new Pair<>(SetHandler.KeyType.XA, new Pair("true", null))); - return true; - } else { - if (shardingService.getSession2().getTargetMap().size() > 0 && shardingService.getSession2().getSessionXaID() != null) { - shardingService.writeErrMessage(ErrorCode.ERR_WRONG_USED, "you can't set xa cmd off when a transaction is in progress."); - return false; - } - innerSetTask.add(new Pair<>(SetHandler.KeyType.XA, new Pair("false", null))); - return true; - } - } - - - public static boolean handleSingleTrace(ShardingService shardingService, SQLExpr valueExpr) { - List>> innerSetTask = new ArrayList<>(); - if (preHandleSingleTrace(shardingService, valueExpr, innerSetTask)) { - String key = innerSetTask.get(0).getValue().getKey(); - shardingService.getSession2().setTrace(Boolean.valueOf(key)); - shardingService.write(shardingService.getSession2().getOKPacket()); - return true; - } - return false; - } - - - public static boolean preHandleSingleTrace(ShardingService service, SQLExpr valueExpr, List>> innerSetTask) { - Boolean switchStatus = isSwitchOn(valueExpr); - if (switchStatus == null) { - service.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'TRACE'"); - return false; - } else { - innerSetTask.add(new Pair<>(SetHandler.KeyType.TRACE, new Pair("" + switchStatus, null))); - return true; - } - } - - - public static boolean handleSingleAutocommit(String stmt, ShardingService service, SQLExpr valueExpr) { - List>> innerSetTask = new ArrayList<>(); - if (preHandleAutocommit(service, valueExpr, innerSetTask)) { - String key = innerSetTask.get(0).getValue().getKey(); - if (!execSetAutoCommit(stmt, service, Boolean.valueOf(key))) { - service.write(service.getSession2().getOKPacket()); - } - return true; - } - return false; - } - - - public static boolean preHandleAutocommit(ShardingService service, SQLExpr valueExpr, List>> innerSetTask) { - Boolean switchStatus = isSwitchOn(valueExpr); - if (switchStatus == null) { - service.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'AUTOCOMMIT'"); - return false; - } else { - innerSetTask.add(new Pair<>(SetHandler.KeyType.AUTOCOMMIT, new Pair("" + switchStatus, null))); - return true; - } - } - - public static boolean execSetAutoCommit(String stmt, ShardingService shardingService, boolean setValue) { - if (setValue) { - if (!shardingService.isAutocommit() && shardingService.getSession2().getTargetCount() > 0) { - shardingService.getSession2().implicitCommit(() -> { - shardingService.setAutocommit(true); - shardingService.write(shardingService.getSession2().getOKPacket()); - }); - return true; - } - shardingService.setAutocommit(true); - } else { - if (shardingService.isAutocommit()) { - shardingService.setAutocommit(false); - TxnLogHelper.putTxnLog(shardingService, stmt); - } - return false; - } - return false; - } - - - public static Boolean isSwitchOn(SQLExpr valueExpr) { - if (valueExpr instanceof SQLIntegerExpr) { - SQLIntegerExpr value = (SQLIntegerExpr) valueExpr; - int iValue = value.getNumber().intValue(); - if (iValue < 0 || iValue > 1) { - return null; - } - return (iValue == 1); - } else if (valueExpr instanceof SQLBooleanExpr) { - SQLBooleanExpr value = (SQLBooleanExpr) valueExpr; - return value.getValue(); - } - String strValue = parseStringValue(valueExpr); - switch (strValue) { - case "on": - return true; - case "off": - return false; - default: - return null; - } - } - - public static String parseStringValue(SQLExpr valueExpr) { - String strValue = ""; - if (valueExpr instanceof SQLIdentifierExpr) { - SQLIdentifierExpr value = (SQLIdentifierExpr) valueExpr; - strValue = StringUtil.removeBackQuote(value.getSimpleName().toLowerCase()); - } else if (valueExpr instanceof SQLCharExpr) { - SQLCharExpr value = (SQLCharExpr) valueExpr; - strValue = value.getText().toLowerCase(); - } else if (valueExpr instanceof SQLIntegerExpr) { - SQLIntegerExpr value = (SQLIntegerExpr) valueExpr; - strValue = value.getNumber().toString(); - } else if (valueExpr instanceof SQLDefaultExpr || valueExpr instanceof SQLNullExpr) { - strValue = valueExpr.toString(); - } - return strValue; - } -} diff --git a/src/main/java/com/actiontech/dble/server/handler/UseHandler.java b/src/main/java/com/actiontech/dble/server/handler/UseHandler.java index f6b24ceeb..b77d4baf6 100644 --- a/src/main/java/com/actiontech/dble/server/handler/UseHandler.java +++ b/src/main/java/com/actiontech/dble/server/handler/UseHandler.java @@ -36,7 +36,7 @@ public final class UseHandler { service.setSchema(schema); service.getSession2().setRowCount(0); - service.write(service.getSession2().getOKPacket()); + service.writeOkPacket(); } public static String getSchemaName(String sql, int offset) { diff --git a/src/main/java/com/actiontech/dble/server/response/ShowTables.java b/src/main/java/com/actiontech/dble/server/response/ShowTables.java index bdd6fe4c7..61879ff7f 100644 --- a/src/main/java/com/actiontech/dble/server/response/ShowTables.java +++ b/src/main/java/com/actiontech/dble/server/response/ShowTables.java @@ -126,7 +126,7 @@ public final class ShowTables { List fieldPackets = new ArrayList<>(2); bufInf = writeFullTablesHeader(buffer, shardingService, schemaColumn, fieldPackets); if (info.getWhere() != null) { - MySQLItemVisitor mev = new MySQLItemVisitor(shardingService.getSchema(), shardingService.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), shardingService.equivalentUsrVarMap()); + MySQLItemVisitor mev = new MySQLItemVisitor(shardingService.getSchema(), shardingService.getCharset().getResultsIndex(), ProxyMeta.getInstance().getTmManager(), shardingService.getUsrVariables()); info.getWhereExpr().accept(mev); List sourceFields = HandlerTool.createFields(fieldPackets); Item whereItem = HandlerTool.createItem(mev.getItem(), sourceFields, 0, false, DMLResponseHandler.HandlerType.WHERE); diff --git a/src/main/java/com/actiontech/dble/server/response/SptExecute.java b/src/main/java/com/actiontech/dble/server/response/SptExecute.java index ce190e09f..b1e8c4278 100644 --- a/src/main/java/com/actiontech/dble/server/response/SptExecute.java +++ b/src/main/java/com/actiontech/dble/server/response/SptExecute.java @@ -17,7 +17,7 @@ public final class SptExecute { public static String queryUserVar(String name, ShardingService service) { String key = "@" + name; - return service.equivalentUsrVarMap().get(key); + return service.getUsrVariables().get(key); } public static void response(ShardingService service) { diff --git a/src/main/java/com/actiontech/dble/server/util/SetItemUtil.java b/src/main/java/com/actiontech/dble/server/util/SetItemUtil.java new file mode 100644 index 000000000..aa53673da --- /dev/null +++ b/src/main/java/com/actiontech/dble/server/util/SetItemUtil.java @@ -0,0 +1,227 @@ +package com.actiontech.dble.server.util; + +import com.actiontech.dble.backend.mysql.CharsetUtil; +import com.actiontech.dble.config.Isolations; +import com.actiontech.dble.config.model.SystemConfig; +import com.actiontech.dble.util.StringUtil; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.expr.*; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; + +import java.sql.SQLSyntaxErrorException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class SetItemUtil { + + private SetItemUtil() { + } + + public static String getBooleanVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String strValue = parseStringValue(valueExpr); + switch (strValue) { + case "1": + case "on": + return "true"; + case "0": + case "off": + return "false"; + default: + throw new SQLSyntaxErrorException("illegal value[" + strValue + "]"); + } + } + + public static String getIsolationVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String value = parseStringValue(valueExpr); + switch (value) { + case "read-uncommitted": + case "read uncommitted": + return Isolations.READ_UNCOMMITTED + ""; + case "read-committed": + case "read committed": + return Isolations.READ_COMMITTED + ""; + case "repeatable-read": + case "repeatable read": + return Isolations.REPEATABLE_READ + ""; + case "serializable": + return Isolations.SERIALIZABLE + ""; + default: + throw new SQLSyntaxErrorException("Variable 'tx_isolation|transaction_isolation' can't be set to the value of '" + value + "'"); + } + } + + public static String getCharsetClientVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String charsetClient = parseStringValue(valueExpr); + if (charsetClient == null || charsetClient.equalsIgnoreCase("null")) { + throw new SQLSyntaxErrorException("Variable 'character_set_client' can't be set to the value of 'NULL'"); + } else if (checkCharset(charsetClient)) { + if (!CharsetUtil.checkCharsetClient(charsetClient)) { + throw new SQLSyntaxErrorException("Variable 'character_set_client' can't be set to the value of '" + charsetClient + "'"); + } + } else { + throw new SQLSyntaxErrorException("Unknown character set '" + charsetClient + "'"); + } + return charsetClient; + } + + public static String getCharsetResultsVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String charsetResult = parseStringValue(valueExpr); + if (!charsetResult.equalsIgnoreCase("NULL") && !checkCharset(charsetResult)) { + throw new SQLSyntaxErrorException("Unknown character set '" + charsetResult + "'"); + } + return charsetResult; + } + + public static String getCollationVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String collation = parseStringValue(valueExpr); + if (!checkCollation(collation)) { + throw new SQLSyntaxErrorException("Unknown collation '" + collation + "'"); + } + return collation; + } + + public static String getCharsetConnectionVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String charsetConnection = parseStringValue(valueExpr); + if (charsetConnection.equals("null")) { + throw new SQLSyntaxErrorException("Variable 'character_set_connection' can't be set to the value of 'NULL'"); + } + String collationName = CharsetUtil.getDefaultCollation(charsetConnection); + if (collationName == null) { + throw new SQLSyntaxErrorException("Unknown character set '" + charsetConnection + "'"); + } + return charsetConnection; + } + + public static String getCharsetVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String charsetValue = parseStringValue(valueExpr); + if (charsetValue == null || charsetValue.equalsIgnoreCase("null")) { + throw new SQLSyntaxErrorException("Unknown character set null"); + } + String charset = getCharset(charsetValue); + if (charset != null) { + if (!CharsetUtil.checkCharsetClient(charset)) { + throw new SQLSyntaxErrorException("Variable 'character set' can't be set to the value of '" + charset + "'"); + } + } else { + throw new SQLSyntaxErrorException("Unknown character set"); + } + return charset; + } + + private static boolean checkSetNamesSyntax(String stmt) { + //druid parser can't find syntax error,use regex to check again, but it is not strict + String regex = "set\\s+names\\s+[`']?[a-zA-Z_0-9]+[`']?(\\s+collate\\s+[`']?[a-zA-Z_0-9]+[`']?)?;?\\s*$"; + Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + Matcher ma = pattern.matcher(stmt); + return ma.find(); + } + + public static String getNamesVal(SQLExpr valueExpr) throws SQLSyntaxErrorException { + String charset; + String collate = null; + if (valueExpr instanceof MySqlCharExpr) { + MySqlCharExpr value = (MySqlCharExpr) valueExpr; + charset = value.getText().toLowerCase(); + collate = StringUtil.removeBackQuote(value.getCollate()).toLowerCase(); + } else { + charset = parseStringValue(valueExpr); + } + + if (charset.toLowerCase().equals("default")) { + charset = SystemConfig.getInstance().getCharset(); + } else { + charset = StringUtil.removeApostropheOrBackQuote(charset.toLowerCase()); + if (!checkCharset(charset)) { + throw new SQLSyntaxErrorException("Unknown character set '" + charset + " or collate '" + collate + "'"); + } + } + if (collate == null) { + collate = CharsetUtil.getDefaultCollation(charset); + } else { + collate = collate.toLowerCase(); + if (collate.equals("default")) { + collate = CharsetUtil.getDefaultCollation(charset); + } else { + int collateIndex = CharsetUtil.getCollationIndexByCharset(charset, collate); + if (collateIndex == 0) { + throw new SQLSyntaxErrorException("Unknown character set '" + charset + " or collate '" + collate + "'"); + } else if (collateIndex < 0) { + throw new SQLSyntaxErrorException("COLLATION '" + collate + "' is not valid for CHARACTER SET '" + charset + "'"); + } + } + } + + if (!CharsetUtil.checkCharsetClient(charset)) { + throw new SQLSyntaxErrorException("Variable 'names' can't be set to the value of '" + charset + "'"); + } + + return charset + ":" + collate; + } + + private static String getCharset(String charset) { + if (charset.toLowerCase().equals("default")) { + charset = SystemConfig.getInstance().getCharset(); + } + charset = StringUtil.removeApostropheOrBackQuote(charset.toLowerCase()); + if (checkCharset(charset)) { + return charset; + } + return null; + } + + private static boolean checkCharset(String name) { + int ci = CharsetUtil.getCharsetDefaultIndex(name); + return ci > 0; + } + + private static boolean checkCollation(String collation) { + int ci = CharsetUtil.getCollationIndex(collation); + return ci > 0; + } + + private static String parseStringValue(SQLExpr valueExpr) { + String strValue = null; + if (valueExpr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr value = (SQLIdentifierExpr) valueExpr; + strValue = StringUtil.removeBackQuote(value.getSimpleName().toLowerCase()); + } else if (valueExpr instanceof SQLCharExpr) { + SQLCharExpr value = (SQLCharExpr) valueExpr; + strValue = value.getText().toLowerCase(); + } else if (valueExpr instanceof SQLIntegerExpr) { + SQLIntegerExpr value = (SQLIntegerExpr) valueExpr; + strValue = value.getNumber().toString(); + } else if (valueExpr instanceof SQLDefaultExpr || valueExpr instanceof SQLNullExpr) { + strValue = valueExpr.toString(); + } else if (valueExpr instanceof SQLBooleanExpr) { + strValue = valueExpr.toString(); + } + return strValue; + } + + public static String parseVariablesValue(SQLExpr valueExpr) { + String strValue; + if (valueExpr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr value = (SQLIdentifierExpr) valueExpr; + strValue = "'" + StringUtil.removeBackQuote(value.getSimpleName().toLowerCase()) + "'"; + } else if (valueExpr instanceof SQLCharExpr) { + SQLCharExpr value = (SQLCharExpr) valueExpr; + strValue = "'" + value.getText().toLowerCase() + "'"; + } else if (valueExpr instanceof SQLIntegerExpr) { + SQLIntegerExpr value = (SQLIntegerExpr) valueExpr; + strValue = value.getNumber().toString(); + } else if (valueExpr instanceof SQLNumberExpr) { + SQLNumberExpr value = (SQLNumberExpr) valueExpr; + strValue = value.getNumber().toString(); + } else if (valueExpr instanceof SQLBooleanExpr) { + SQLBooleanExpr value = (SQLBooleanExpr) valueExpr; + strValue = String.valueOf(value.getValue()); + } else if (valueExpr instanceof SQLDefaultExpr || valueExpr instanceof SQLNullExpr) { + strValue = valueExpr.toString(); + } else { + strValue = SQLUtils.toMySqlString(valueExpr); + } + return strValue; + } + +} diff --git a/src/main/java/com/actiontech/dble/services/MySQLBasedService.java b/src/main/java/com/actiontech/dble/services/MySQLBasedService.java index f9b990680..a4cdb303f 100644 --- a/src/main/java/com/actiontech/dble/services/MySQLBasedService.java +++ b/src/main/java/com/actiontech/dble/services/MySQLBasedService.java @@ -3,17 +3,14 @@ package com.actiontech.dble.services; import com.actiontech.dble.DbleServer; import com.actiontech.dble.config.model.user.UserConfig; import com.actiontech.dble.net.connection.AbstractConnection; -import com.actiontech.dble.net.mysql.CharsetNames; import com.actiontech.dble.net.mysql.ErrorPacket; +import com.actiontech.dble.net.mysql.OkPacket; import com.actiontech.dble.net.service.AbstractService; import com.actiontech.dble.net.service.ServiceTask; import com.actiontech.dble.util.CompressUtil; import com.actiontech.dble.util.StringUtil; -import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; /** @@ -23,9 +20,6 @@ public abstract class MySQLBasedService extends AbstractService { protected UserConfig userConfig; - protected volatile List> usrVariables = new ArrayList<>(); - protected volatile List> sysVariables = new ArrayList<>(); - public MySQLBasedService(AbstractConnection connection) { super(connection); } @@ -40,7 +34,6 @@ public abstract class MySQLBasedService extends AbstractService { DbleServer.getInstance().getFrontHandlerQueue().offer(task); } - @Override public void handleData(ServiceTask task) { ServiceTask executeTask = null; @@ -87,8 +80,12 @@ public abstract class MySQLBasedService extends AbstractService { return userConfig; } - public CharsetNames getCharset() { - return connection.getCharsetName(); + public void writeOkPacket() { + OkPacket ok = new OkPacket(); + byte packet = (byte) this.getPacketId().incrementAndGet(); + ok.read(OkPacket.OK); + ok.setPacketId(packet); + write(ok); } public void writeErrMessage(String code, String msg, int vendorCode) { @@ -113,62 +110,4 @@ public abstract class MySQLBasedService extends AbstractService { err.write(connection); } - public String getStringOfSysVariables() { - StringBuilder sbSysVariables = new StringBuilder(); - int cnt = 0; - if (sysVariables != null) { - for (Map oneLineVar : sysVariables) { - for (Map.Entry sysVariable : oneLineVar.entrySet()) { - if (cnt > 0) { - sbSysVariables.append(","); - } - sbSysVariables.append(sysVariable.getKey()); - sbSysVariables.append("="); - sbSysVariables.append(sysVariable.getValue()); - cnt++; - } - sbSysVariables.append(";"); - } - } - return sbSysVariables.toString(); - } - - public String getStringOfUsrVariables() { - StringBuilder sbUsrVariables = new StringBuilder(); - int cnt = 0; - if (usrVariables != null) { - for (Map oneLineVar : usrVariables) { - for (Map.Entry usrVariable : oneLineVar.entrySet()) { - if (cnt > 0) { - sbUsrVariables.append(","); - } - sbUsrVariables.append(usrVariable.getKey()); - sbUsrVariables.append("="); - sbUsrVariables.append(usrVariable.getValue()); - cnt++; - } - sbUsrVariables.append(";"); - } - } - return sbUsrVariables.toString(); - } - - - public Map equivalentUsrVarMap() { - Map result = new LinkedHashMap<>(); - for (int i = 0; i < usrVariables.size(); i++) { - result.putAll(usrVariables.get(i)); - } - return result; - } - - - public Map equivalentSysVarMap() { - Map result = new LinkedHashMap<>(); - for (int i = 0; i < sysVariables.size(); i++) { - result.putAll(sysVariables.get(i)); - } - return result; - } - } diff --git a/src/main/java/com/actiontech/dble/services/MySQLVariablesService.java b/src/main/java/com/actiontech/dble/services/MySQLVariablesService.java new file mode 100644 index 000000000..303e5bed8 --- /dev/null +++ b/src/main/java/com/actiontech/dble/services/MySQLVariablesService.java @@ -0,0 +1,170 @@ +package com.actiontech.dble.services; + +import com.actiontech.dble.net.connection.AbstractConnection; +import com.actiontech.dble.net.mysql.CharsetNames; +import com.actiontech.dble.server.handler.SetHandler; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Created by szf on 2020/6/28. + */ +public abstract class MySQLVariablesService extends MySQLBasedService { + + protected volatile Map usrVariables = new LinkedHashMap<>(); + protected volatile Map sysVariables = new LinkedHashMap<>(); + + protected volatile int txIsolation; + protected volatile boolean autocommit; + + public MySQLVariablesService(AbstractConnection connection) { + super(connection); + } + + public void executeContextSetTask(SetHandler.SetItem[] contextTask) { + SetHandler.SetItem autocommitItem = null; + for (SetHandler.SetItem setItem : contextTask) { + switch (setItem.getType()) { + case CHARACTER_SET_CLIENT: + String charsetClient = setItem.getValue(); + this.setCharacterClient(charsetClient); + break; + case CHARACTER_SET_CONNECTION: + String collationName = setItem.getValue(); + this.setCharacterConnection(collationName); + break; + case CHARACTER_SET_RESULTS: + String charsetResult = setItem.getValue(); + this.setCharacterResults(charsetResult); + break; + case COLLATION_CONNECTION: + String collation = setItem.getValue(); + this.setCollationConnection(collation); + break; + case TX_ISOLATION: + String isolationLevel = setItem.getValue(); + this.setTxIsolation(Integer.parseInt(isolationLevel)); + break; + case SYSTEM_VARIABLES: + this.sysVariables.put(setItem.getName(), setItem.getValue()); + break; + case USER_VARIABLES: + if (setItem.getValue() != null) { + this.usrVariables.put(setItem.getName(), setItem.getValue()); + } + break; + case CHARSET: + this.setCharacterSet(setItem.getValue()); + break; + case NAMES: + String[] charsetAndCollate = setItem.getValue().split(":"); + this.setNames(charsetAndCollate[0], charsetAndCollate[1]); + break; + case AUTOCOMMIT: + autocommitItem = setItem; + break; + default: + handleSetItem(setItem); + break; + } + } + + if (autocommitItem == null) { + writeOkPacket(); + } else { + handleSetItem(autocommitItem); + } + } + + public abstract void handleSetItem(SetHandler.SetItem setItem); + + public void setCollationConnection(String collation) { + connection.getCharsetName().setCollation(collation); + } + + public void setCharacterResults(String name) { + connection.getCharsetName().setResults(name); + } + + public void setCharacterConnection(String collationName) { + connection.getCharsetName().setCollation(collationName); + } + + public void setNames(String name, String collationName) { + connection.getCharsetName().setNames(name, collationName); + } + + public void setCharacterClient(String name) { + connection.getCharsetName().setClient(name); + } + + public int getTxIsolation() { + return txIsolation; + } + + public void setTxIsolation(int txIsolation) { + this.txIsolation = txIsolation; + } + + public void setCharacterSet(String name) { + connection.setCharacterSet(name); + } + + public CharsetNames getCharset() { + return connection.getCharsetName(); + } + + public boolean isAutocommit() { + return autocommit; + } + + public void setAutocommit(boolean autocommit) { + this.autocommit = autocommit; + } + + public Map getSysVariables() { + return sysVariables; + } + + public Map getUsrVariables() { + return usrVariables; + } + + public String getStringOfSysVariables() { + StringBuilder sbSysVariables = new StringBuilder(); + int cnt = 0; + if (sysVariables != null) { + for (Map.Entry entry : sysVariables.entrySet()) { + if (cnt > 0) { + sbSysVariables.append(","); + } + sbSysVariables.append(entry.getKey()); + sbSysVariables.append("="); + sbSysVariables.append(entry.getValue()); + cnt++; + } + } + return sbSysVariables.toString(); + } + + public String getStringOfUsrVariables() { + StringBuilder sbUsrVariables = new StringBuilder(); + int cnt = 0; + if (usrVariables != null) { + for (Map.Entry entry : usrVariables.entrySet()) { + if (cnt > 0) { + sbUsrVariables.append(","); + } + sbUsrVariables.append(entry.getKey()); + sbUsrVariables.append("="); + sbUsrVariables.append(entry.getValue()); + cnt++; + + } + } + return sbUsrVariables.toString(); + } + + +} diff --git a/src/main/java/com/actiontech/dble/services/manager/ManagerService.java b/src/main/java/com/actiontech/dble/services/manager/ManagerService.java index f8dc36342..fc0704879 100644 --- a/src/main/java/com/actiontech/dble/services/manager/ManagerService.java +++ b/src/main/java/com/actiontech/dble/services/manager/ManagerService.java @@ -12,7 +12,8 @@ import com.actiontech.dble.net.connection.FrontendConnection; import com.actiontech.dble.net.mysql.*; import com.actiontech.dble.net.service.AuthResultInfo; import com.actiontech.dble.net.service.FrontEndService; -import com.actiontech.dble.services.MySQLBasedService; +import com.actiontech.dble.server.handler.SetHandler; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.services.manager.information.ManagerSchemaInfo; import com.actiontech.dble.singleton.FrontendUserManager; import com.actiontech.dble.singleton.TraceManager; @@ -23,7 +24,7 @@ import java.io.UnsupportedEncodingException; /** * Created by szf on 2020/6/28. */ -public class ManagerService extends MySQLBasedService implements FrontEndService { +public class ManagerService extends MySQLVariablesService implements FrontEndService { private final ManagerQueryHandler handler; @@ -44,6 +45,11 @@ public class ManagerService extends MySQLBasedService implements FrontEndService this.commands = connection.getProcessor().getCommands(); } + @Override + public void handleSetItem(SetHandler.SetItem setItem) { + return; + } + public void initFromAuthInfo(AuthResultInfo info) { AuthPacket auth = info.getMysqlAuthPacket(); this.user = new UserName(auth.getUser(), auth.getTenant()); diff --git a/src/main/java/com/actiontech/dble/services/manager/response/ShowConnection.java b/src/main/java/com/actiontech/dble/services/manager/response/ShowConnection.java index 2dedeae6b..a580e3cf1 100644 --- a/src/main/java/com/actiontech/dble/services/manager/response/ShowConnection.java +++ b/src/main/java/com/actiontech/dble/services/manager/response/ShowConnection.java @@ -12,10 +12,9 @@ import com.actiontech.dble.config.Fields; import com.actiontech.dble.net.IOProcessor; import com.actiontech.dble.net.connection.FrontendConnection; import com.actiontech.dble.net.mysql.*; -import com.actiontech.dble.services.MySQLBasedService; -import com.actiontech.dble.services.manager.ManagerService; import com.actiontech.dble.route.factory.RouteStrategyFactory; - +import com.actiontech.dble.services.MySQLVariablesService; +import com.actiontech.dble.services.manager.ManagerService; import com.actiontech.dble.services.mysqlsharding.ShardingService; import com.actiontech.dble.util.IntegerUtil; import com.actiontech.dble.util.LongUtil; @@ -247,8 +246,8 @@ public final class ShowConnection { } row.add(txLevel.getBytes()); row.add(autocommit.getBytes()); - row.add(StringUtil.encode(((MySQLBasedService) c.getService()).getStringOfSysVariables(), charset)); - row.add(StringUtil.encode(((MySQLBasedService) c.getService()).getStringOfUsrVariables(), charset)); + row.add(StringUtil.encode(((MySQLVariablesService) c.getService()).getStringOfSysVariables(), charset)); + row.add(StringUtil.encode(((MySQLVariablesService) c.getService()).getStringOfUsrVariables(), charset)); return row; } diff --git a/src/main/java/com/actiontech/dble/services/mysqlsharding/MySQLResponseService.java b/src/main/java/com/actiontech/dble/services/mysqlsharding/MySQLResponseService.java index 869a110c9..98b9132f0 100644 --- a/src/main/java/com/actiontech/dble/services/mysqlsharding/MySQLResponseService.java +++ b/src/main/java/com/actiontech/dble/services/mysqlsharding/MySQLResponseService.java @@ -18,8 +18,9 @@ import com.actiontech.dble.net.service.ServiceTask; import com.actiontech.dble.route.RouteResultsetNode; import com.actiontech.dble.route.parser.util.Pair; import com.actiontech.dble.server.NonBlockingSession; +import com.actiontech.dble.server.handler.SetHandler; import com.actiontech.dble.server.parser.ServerParse; -import com.actiontech.dble.services.MySQLBasedService; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.services.rwsplit.MysqlPrepareLogicHandler; import com.actiontech.dble.services.rwsplit.RWSplitService; import com.actiontech.dble.singleton.TraceManager; @@ -33,6 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; @@ -45,7 +47,7 @@ import java.util.concurrent.locks.LockSupport; /** * Created by szf on 2020/6/29. */ -public class MySQLResponseService extends MySQLBasedService { +public class MySQLResponseService extends MySQLVariablesService { private static final Logger LOGGER = LoggerFactory.getLogger(MySQLResponseService.class); private ResponseHandler responseHandler; @@ -66,8 +68,6 @@ public class MySQLResponseService extends MySQLBasedService { private volatile boolean prepareOK = false; private volatile boolean testing = false; private volatile StatusSync statusSync; - private volatile boolean autocommit; - private volatile int txIsolation; private volatile boolean isRowDataFlowing = false; private volatile BackEndCleaner recycler = null; private volatile TxState xaStatus = TxState.TX_INITIALIZE_STATE; @@ -101,6 +101,10 @@ public class MySQLResponseService extends MySQLBasedService { this.prepareLogicHandler = new MysqlPrepareLogicHandler(this); } + @Override + public void handleSetItem(SetHandler.SetItem setItem) { + } + private void initFromConfig() { this.autocommitSynced = connection.getInstance().isAutocommitSynced(); boolean sysAutocommit = SystemConfig.getInstance().getAutocommit() == 1; @@ -112,8 +116,8 @@ public class MySQLResponseService extends MySQLBasedService { this.txIsolation = -1; } this.complexQuery = false; - this.usrVariables = new ArrayList<>(); - this.sysVariables = new ArrayList<>(); + this.usrVariables = new LinkedHashMap<>(); + this.sysVariables = new LinkedHashMap<>(); this.dbuser = connection.getInstance().getConfig().getUser(); } @@ -327,44 +331,8 @@ public class MySQLResponseService extends MySQLBasedService { } } - private StringBuilder getSynSql(CharsetNames clientCharset, int clientTxIsolation, boolean expectAutocommit) { - int schemaSyn = StringUtil.equals(connection.getSchema(), connection.getOldSchema()) || connection.getSchema() == null ? 0 : 1; - int charsetSyn = (this.getConnection().getCharsetName().equals(clientCharset)) ? 0 : 1; - int txIsolationSyn = (this.txIsolation == clientTxIsolation) ? 0 : 1; - int autoCommitSyn = (this.autocommit == expectAutocommit) ? 0 : 1; - int synCount = schemaSyn + charsetSyn + txIsolationSyn + autoCommitSyn; - if (synCount == 0) { - return null; - } - - StringBuilder sb = new StringBuilder(); - if (schemaSyn == 1) { - getChangeSchemaCommand(sb, connection.getSchema()); - } - if (charsetSyn == 1) { - getCharsetCommand(sb, clientCharset); - } - if (txIsolationSyn == 1) { - getTxIsolationCommand(sb, clientTxIsolation); - } - if (autoCommitSyn == 1) { - getAutocommitCommand(sb, expectAutocommit); - } - - metaDataSynced = false; - statusSync = new StatusSync(connection.getSchema(), - clientCharset, clientTxIsolation, expectAutocommit, - synCount, Collections.emptyList(), Collections.emptyList()); - - return sb; - } - - private StringBuilder getSynSql(String xaTxID, RouteResultsetNode rrn, - CharsetNames clientCharset, int clientTxIsolation, - boolean expectAutocommit, List> usrVariables, List> sysVariables) { - if (rrn.getSqlType() == ServerParse.DDL) { - isDDL = true; - } + private StringBuilder getSynSql(String xaTxID, RouteResultsetNode rrn, CharsetNames clientCharset, int clientTxIsolation, + boolean expectAutocommit, Map usrVariables, Map sysVariables) { int xaSyn = 0; if (!expectAutocommit && xaTxID != null && xaStatus == TxState.TX_INITIALIZE_STATE && !isDDL) { @@ -372,10 +340,11 @@ public class MySQLResponseService extends MySQLBasedService { xaSyn = 1; } - StringBuilder setSql = new StringBuilder(); - int setSqlFlag = getSetSQL(usrVariables, sysVariables, setSql); + Set toResetSys = new HashSet<>(); + String setSql = getSetSQL(usrVariables, sysVariables, toResetSys); + int setSqlFlag = setSql == null ? 0 : 1; int schemaSyn = StringUtil.equals(connection.getSchema(), connection.getOldSchema()) || connection.getSchema() == null ? 0 : 1; - int charsetSyn = (this.getConnection().getCharsetName().equals(clientCharset)) ? 0 : 1; + int charsetSyn = this.getConnection().getCharsetName().equals(clientCharset) ? 0 : 1; int txIsolationSyn = (this.txIsolation == clientTxIsolation) ? 0 : 1; int autoCommitSyn = (this.autocommit == expectAutocommit) ? 0 : 1; int synCount = schemaSyn + charsetSyn + txIsolationSyn + autoCommitSyn + xaSyn + setSqlFlag; @@ -396,7 +365,7 @@ public class MySQLResponseService extends MySQLBasedService { if (autoCommitSyn == 1) { getAutocommitCommand(sb, expectAutocommit); } - if (setSqlFlag > 0) { + if (setSqlFlag == 1) { sb.append(setSql); } if (xaSyn == 1) { @@ -412,7 +381,7 @@ public class MySQLResponseService extends MySQLBasedService { metaDataSynced = false; statusSync = new StatusSync(connection.getSchema(), clientCharset, clientTxIsolation, expectAutocommit, - synCount, usrVariables, sysVariables); + synCount, usrVariables, sysVariables, toResetSys); return sb; } @@ -461,61 +430,60 @@ public class MySQLResponseService extends MySQLBasedService { } } - private int getSetSQL(List> usrVars, List> sysVars, StringBuilder setSQL) { - int totalSize = 0; - Map tmpSysVars = new HashMap<>(this.equivalentSysVarMap()); - for (int i = 0; i < usrVars.size(); i++) { - //new final var for single set statement from sharding service - List> setVars = new ArrayList<>(); - - Map singleStatementSysVar = sysVars.get(i); - Map singleStatementUsrVar = usrVars.get(i); - if (usrVariables.size() <= i) { - //if the backend service has the userVars, means that the connection is hold by the front session till now - //the index of the object in the usrVariables must has the same order - for (Map.Entry entry : singleStatementUsrVar.entrySet()) { + private String getSetSQL(Map usrVars, Map sysVars, Set toResetSys) { + //new final var + List> setVars = new ArrayList<>(); + //tmp add all backend sysVariables + Map tmpSysVars = new HashMap<>(sysVariables); + //for all front end sysVariables + for (Map.Entry entry : sysVars.entrySet()) { + if (!tmpSysVars.containsKey(entry.getKey())) { + setVars.add(new Pair<>(entry.getKey(), entry.getValue())); + } else { + String value = tmpSysVars.remove(entry.getKey()); + //if backend is not equal frontend, need to reset + if (!StringUtil.equalsIgnoreCase(entry.getValue(), value)) { setVars.add(new Pair<>(entry.getKey(), entry.getValue())); } } - - if (sysVariables.size() <= i || sysVariables.get(i) != singleStatementSysVar) { - //if the sysVariables object has the same, means that the sysVar has been Synchronized - //otherwise the all sysVariables should be set to the backend - //the benchmark is the tmpSysVars, statement-level-system-vars - for (Map.Entry entry : singleStatementSysVar.entrySet()) { - if (!tmpSysVars.containsKey(entry.getKey())) { - setVars.add(new Pair<>(entry.getKey(), entry.getValue())); - tmpSysVars.put(entry.getKey(), entry.getValue()); - } else { - String value = tmpSysVars.get(entry.getKey()); - //if backend is not equal frontend, need to reset - if (!StringUtil.equalsIgnoreCase(entry.getValue(), value)) { - setVars.add(new Pair<>(entry.getKey(), entry.getValue())); - } - tmpSysVars.put(entry.getKey(), entry.getValue()); - } - } - } - - if (setVars.size() == 0) { - continue; - } - - totalSize++; - setSQL.append("set "); - int cnt = 0; - for (Pair var : setVars) { - if (cnt > 0) { - setSQL.append(","); - } - setSQL.append(var.getKey()); - setSQL.append("="); - setSQL.append(var.getValue()); - cnt++; - } - setSQL.append(";"); } - return totalSize; + //tmp now = backend -(backend &&frontend) + for (Map.Entry entry : tmpSysVars.entrySet()) { + String value = DbleServer.getInstance().getSystemVariables().getDefaultValue(entry.getKey()); + try { + BigDecimal vl = new BigDecimal(value); + } catch (NumberFormatException e) { + value = "`" + value + "`"; + } + setVars.add(new Pair<>(entry.getKey(), value)); + toResetSys.add(entry.getKey()); + } + + for (Map.Entry entry : usrVars.entrySet()) { + if (!usrVariables.containsKey(entry.getKey())) { + setVars.add(new Pair<>(entry.getKey(), entry.getValue())); + } else { + if (!StringUtil.equalsIgnoreCase(entry.getValue(), usrVariables.get(entry.getKey()))) { + setVars.add(new Pair<>(entry.getKey(), entry.getValue())); + } + } + } + + if (setVars.size() == 0) + return null; + StringBuilder sb = new StringBuilder("set "); + int cnt = 0; + for (Pair var : setVars) { + if (cnt > 0) { + sb.append(","); + } + sb.append(var.getKey()); + sb.append("="); + sb.append(var.getValue()); + cnt++; + } + sb.append(";"); + return sb.toString(); } @@ -587,8 +555,7 @@ public class MySQLResponseService extends MySQLBasedService { return "MySQLConnection host=" + connection.getHost() + ", port=" + connection.getPort() + ", schema=" + connection.getSchema(); } - public void executeMultiNode(RouteResultsetNode rrn, ShardingService service, - boolean isAutoCommit) { + public void executeMultiNode(RouteResultsetNode rrn, ShardingService service, boolean isAutoCommit) { TraceManager.TraceObject traceObject = TraceManager.serviceTrace(this, "execute-route-multi-result"); TraceManager.log(ImmutableMap.of("route-result-set", rrn.toString(), "service-detail", this.toString()), traceObject); try { @@ -596,7 +563,11 @@ public class MySQLResponseService extends MySQLBasedService { if (!service.isAutocommit() && !service.isTxStart() && rrn.isModifySQL()) { service.setTxStarted(true); } - StringBuilder synSQL = getSynSql(xaTxId, rrn, service.getCharset(), service.getTxIsolation(), isAutoCommit, service.getUsrVariables(), service.getSysVariables()); + if (rrn.getSqlType() == ServerParse.DDL) { + isDDL = true; + } + StringBuilder synSQL = getSynSql(xaTxId, rrn, service.getCharset(), + service.getTxIsolation(), isAutoCommit, service.getUsrVariables(), service.getSysVariables()); synAndDoExecuteMultiNode(synSQL, rrn, service.getCharset()); } finally { TraceManager.finishSpan(this, traceObject); @@ -611,30 +582,31 @@ public class MySQLResponseService extends MySQLBasedService { if (!service.isAutocommit() && !service.isTxStart() && rrn.isModifySQL()) { service.setTxStarted(true); } - StringBuilder synSQL = getSynSql(xaTxId, rrn, service.getCharset(), service.getTxIsolation(), isAutoCommit, service.getUsrVariables(), service.getSysVariables()); + if (rrn.getSqlType() == ServerParse.DDL) { + isDDL = true; + } + StringBuilder synSQL = getSynSql(xaTxId, rrn, + service.getCharset(), service.getTxIsolation(), isAutoCommit, service.getUsrVariables(), service.getSysVariables()); synAndDoExecute(synSQL, rrn.getStatement(), service.getCharset()); } finally { TraceManager.finishSpan(this, traceObject); } } - public void execute(RWSplitService service) { - StringBuilder synSQL = getSynSql(service.getCharset(), service.getTxIsolation(), service.isAutocommit()); - synAndDoExecute(synSQL, service.getExecuteSql(), service.getCharset()); + public void execute(MySQLVariablesService service, String sql) { + StringBuilder synSQL = getSynSql(null, null, + service.getCharset(), service.getTxIsolation(), service.isAutocommit(), service.getUsrVariables(), service.getSysVariables()); + synAndDoExecute(synSQL, sql, service.getCharset()); } public void execute(RWSplitService service, byte[] originPacket) { - if (service != null) { - StringBuilder synSQL = getSynSql(service.getCharset(), service.getTxIsolation(), service.isAutocommit()); - if (synSQL != null) { - sendQueryCmd(synSQL.toString(), service.getCharset()); - } - } - if (originPacket[4] == MySQLPacket.COM_STMT_PREPARE) { - prepareOK = true; - } else { - prepareOK = false; + StringBuilder synSQL = getSynSql(null, null, + service.getCharset(), service.getTxIsolation(), service.isAutocommit(), service.getUsrVariables(), service.getSysVariables()); + if (synSQL != null) { + sendQueryCmd(synSQL.toString(), service.getCharset()); } + + prepareOK = originPacket[4] == MySQLPacket.COM_STMT_PREPARE; writeDirectly(originPacket); } @@ -675,11 +647,8 @@ public class MySQLResponseService extends MySQLBasedService { this.autocommit = sysAutocommit == autocommitSynced; // T + T-> T, T + F-> F, F +T ->F, F + F->T this.connection.initCharacterSet(SystemConfig.getInstance().getCharset()); this.usrVariables.clear(); - this.usrVariables.add(new LinkedHashMap<>()); this.sysVariables.clear(); - Map sysRest = new LinkedHashMap<>(); - sysRest.put("sql_mode", null); - this.sysVariables.add(sysRest); + this.sysVariables.put("sql_mode", null); } private WriteToBackendTask sendQueryCmdTask(String query, CharsetNames clientCharset) { @@ -711,14 +680,13 @@ public class MySQLResponseService extends MySQLBasedService { } public BackendConnection getConnection() { - return (BackendConnection) connection; + return connection; } public void setResponseHandler(ResponseHandler handler) { this.responseHandler = handler; } - public Object getAttachment() { return attachment; } @@ -727,7 +695,6 @@ public class MySQLResponseService extends MySQLBasedService { this.attachment = attachment; } - public NonBlockingSession getSession() { return session; } @@ -736,12 +703,10 @@ public class MySQLResponseService extends MySQLBasedService { this.session = session; } - public ResponseHandler getResponseHandler() { return responseHandler; } - public boolean isRowDataFlowing() { return isRowDataFlowing; } @@ -790,22 +755,6 @@ public class MySQLResponseService extends MySQLBasedService { this.statusSync = statusSync; } - public boolean isAutocommit() { - return autocommit; - } - - public void setAutocommit(boolean autocommit) { - this.autocommit = autocommit; - } - - public int getTxIsolation() { - return txIsolation; - } - - public void setTxIsolation(int txIsolation) { - this.txIsolation = txIsolation; - } - public void setRecycler(BackEndCleaner recycler) { this.recycler = recycler; } @@ -847,20 +796,22 @@ public class MySQLResponseService extends MySQLBasedService { private final Integer txtIsolation; private final Boolean autocommit; private final AtomicInteger synCmdCount; - private final List> usrVariables = new ArrayList<>(); - private final List> sysVariables = new ArrayList<>(); + private final Map usrVariables = new LinkedHashMap<>(); + private final Map sysVariables = new LinkedHashMap<>(); StatusSync(String schema, CharsetNames clientCharset, Integer txtIsolation, Boolean autocommit, - int synCount, List> usrVariables, List> sysVariables) { - super(); + int synCount, Map usrVariables, Map sysVariables, Set toResetSys) { this.schema = schema; this.clientCharset = clientCharset; this.txtIsolation = txtIsolation; this.autocommit = autocommit; this.synCmdCount = new AtomicInteger(synCount); - this.usrVariables.addAll(usrVariables); - this.sysVariables.addAll(sysVariables); + this.usrVariables.putAll(usrVariables); + this.sysVariables.putAll(sysVariables); + for (String sysVariable : toResetSys) { + this.sysVariables.remove(sysVariable); + } } boolean synAndExecuted(MySQLResponseService service) { diff --git a/src/main/java/com/actiontech/dble/services/mysqlsharding/ShardingService.java b/src/main/java/com/actiontech/dble/services/mysqlsharding/ShardingService.java index 0c46c1643..2989d8d95 100644 --- a/src/main/java/com/actiontech/dble/services/mysqlsharding/ShardingService.java +++ b/src/main/java/com/actiontech/dble/services/mysqlsharding/ShardingService.java @@ -20,20 +20,18 @@ import com.actiontech.dble.net.service.AuthResultInfo; import com.actiontech.dble.net.service.FrontEndService; import com.actiontech.dble.net.service.ServiceTask; import com.actiontech.dble.route.RouteResultset; -import com.actiontech.dble.route.parser.util.Pair; import com.actiontech.dble.server.NonBlockingSession; import com.actiontech.dble.server.ServerQueryHandler; import com.actiontech.dble.server.ServerSptPrepare; import com.actiontech.dble.server.handler.ServerLoadDataInfileHandler; import com.actiontech.dble.server.handler.ServerPrepareHandler; import com.actiontech.dble.server.handler.SetHandler; -import com.actiontech.dble.server.handler.SetInnerHandler; import com.actiontech.dble.server.parser.ServerParse; import com.actiontech.dble.server.response.Heartbeat; import com.actiontech.dble.server.response.InformationSchemaProfiling; import com.actiontech.dble.server.response.Ping; import com.actiontech.dble.server.util.SchemaUtil; -import com.actiontech.dble.services.MySQLBasedService; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.services.mysqlsharding.handler.LoadDataProtoHandlerImpl; import com.actiontech.dble.singleton.*; import com.actiontech.dble.statistic.CommandCount; @@ -47,7 +45,9 @@ import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.sql.SQLException; -import java.util.*; +import java.sql.SQLSyntaxErrorException; +import java.util.Iterator; +import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; @@ -55,7 +55,7 @@ import java.util.concurrent.atomic.AtomicLong; /** * Created by szf on 2020/6/18. */ -public class ShardingService extends MySQLBasedService implements FrontEndService { +public class ShardingService extends MySQLVariablesService implements FrontEndService { protected static final Logger LOGGER = LoggerFactory.getLogger(ShardingService.class); @@ -76,33 +76,19 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic protected String executeSql; protected UserName user; private long clientFlags; - private volatile boolean autocommit; private volatile boolean txStarted; private volatile boolean txChainBegin; private volatile boolean txInterrupted; private volatile String txInterruptMsg = ""; protected long lastReadTime; - - private volatile int txIsolation; - private AtomicLong txID = new AtomicLong(1); - private volatile boolean isLocked = false; - private long lastInsertId; - protected String schema; - private volatile boolean multiStatementAllow = false; - private final NonBlockingSession session; - private boolean sessionReadOnly = false; - - private List>> contextTask = new ArrayList<>(); - private List>> innerSetTask = new ArrayList<>(); - private ServerSptPrepare sptprepare; public ShardingService(AbstractConnection connection) { @@ -120,6 +106,54 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic this.autocommit = SystemConfig.getInstance().getAutocommit() == 1; } + @Override + public void handleSetItem(SetHandler.SetItem setItem) { + String val = setItem.getValue(); + switch (setItem.getType()) { + case XA: + session.getTransactionManager().setXaTxEnabled(Boolean.parseBoolean(val), this); + break; + case TRACE: + session.setTrace(Boolean.parseBoolean(val)); + break; + case TX_READ_ONLY: + sessionReadOnly = Boolean.parseBoolean(val); + break; + case AUTOCOMMIT: + if (Boolean.parseBoolean(val)) { + if (!autocommit && session.getTargetCount() > 0) { + session.implicitCommit(() -> { + autocommit = true; + writeOkPacket(); + }); + return; + } + autocommit = true; + } else { + if (autocommit) { + autocommit = false; + TxnLogHelper.putTxnLog(this, executeSql); + } + } + writeOkPacket(); + break; + default: + // IGNORE + } + } + + public void checkXaStatus(boolean val) throws SQLSyntaxErrorException { + if (val) { + if (session.getTargetMap().size() > 0 && session.getSessionXaID() == null) { + throw new SQLSyntaxErrorException("you can't set xa cmd on when there are unfinished operation in the session."); + } + } else { + if (session.getTargetMap().size() > 0 && session.getSessionXaID() != null) { + throw new SQLSyntaxErrorException("you can't set xa cmd off when a transaction is in progress."); + } + } + } + public void query(String sql) { sql = sql.trim(); // remove last ';' @@ -145,7 +179,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic readOnly = ((ShardingUserConfig) userConfig).isReadOnly(); } - this.handler.setReadOnly(readOnly); this.handler.setSessionReadOnly(sessionReadOnly); this.handler.query(sql); @@ -391,7 +424,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic } } - @Override protected void writeErrMessage(byte id, int vendorCode, String sqlState, String msg) { markFinished(); @@ -404,84 +436,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic } } - public void executeContextSetTask() { - Map singleUsrVariables = new LinkedHashMap<>(); - Map singleSysVariables = new LinkedHashMap<>(); - for (Pair> task : contextTask) { - switch (task.getKey()) { - case CHARACTER_SET_CLIENT: - String charsetClient = task.getValue().getKey(); - this.setCharacterClient(charsetClient); - break; - case CHARACTER_SET_CONNECTION: - String collationName = task.getValue().getKey(); - this.setCharacterConnection(collationName); - break; - case CHARACTER_SET_RESULTS: - String charsetResult = task.getValue().getKey(); - this.setCharacterResults(charsetResult); - break; - case COLLATION_CONNECTION: - String collation = task.getValue().getKey(); - this.setCollationConnection(collation); - break; - case TX_ISOLATION: - String isolationLevel = task.getValue().getKey(); - this.setTxIsolation(Integer.parseInt(isolationLevel)); - break; - case TX_READ_ONLY: - String enable = task.getValue().getKey(); - this.setSessionReadOnly(Boolean.parseBoolean(enable)); - break; - case SYSTEM_VARIABLES: - singleSysVariables.put(task.getValue().getKey(), task.getValue().getValue()); - break; - case USER_VARIABLES: - singleUsrVariables.put(task.getValue().getKey(), task.getValue().getValue()); - break; - case CHARSET: - this.setCharacterSet(task.getValue().getKey()); - break; - case NAMES: - this.setNames(task.getValue().getKey(), task.getValue().getValue()); - break; - default: - //can't happen - break; - } - } - - if (singleUsrVariables.size() > 0 || singleSysVariables.size() > 0) { - //make sure the var map appear as pair - this.usrVariables.add(singleUsrVariables); - this.sysVariables.add(singleSysVariables); - } - - } - - public boolean executeInnerSetTask() { - Pair> autoCommitTask = null; - for (Pair> task : innerSetTask) { - switch (task.getKey()) { - case XA: - session.getTransactionManager().setXaTxEnabled(Boolean.valueOf(task.getValue().getKey()), this); - break; - case AUTOCOMMIT: - autoCommitTask = task; - break; - case TRACE: - session.setTrace(Boolean.valueOf(task.getValue().getKey())); - break; - default: - } - } - - if (autoCommitTask != null) { - return SetInnerHandler.execSetAutoCommit(executeSql, this, Boolean.valueOf(autoCommitTask.getValue().getKey())); - } - return false; - } - public void beginInTx(String stmt) { if (txInterrupted) { writeErrMessage(ErrorCode.ER_YES, txInterruptMsg); @@ -604,7 +558,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic } } - @Override public void write(MySQLPacket packet) { boolean multiQueryFlag = session.multiStatementPacket(packet); @@ -687,35 +640,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic TraceManager.sessionStart(this, "sharding-server-start"); } - - public void setCollationConnection(String collation) { - connection.getCharsetName().setCollation(collation); - } - - public void setCharacterResults(String name) { - connection.getCharsetName().setResults(name); - } - - public void setCharacterConnection(String collationName) { - connection.getCharsetName().setCollation(collationName); - } - - public void setNames(String name, String collationName) { - connection.getCharsetName().setNames(name, collationName); - } - - public void setCharacterClient(String name) { - connection.getCharsetName().setClient(name); - } - - public int getTxIsolation() { - return txIsolation; - } - - public void setTxIsolation(int txIsolation) { - this.txIsolation = txIsolation; - } - public boolean isTxStarted() { return txStarted; } @@ -748,14 +672,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic this.txInterruptMsg = txInterruptMsg; } - public boolean isAutocommit() { - return autocommit; - } - - public void setAutocommit(boolean autocommit) { - this.autocommit = autocommit; - } - public boolean isTxStart() { return txStarted; } @@ -797,7 +713,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic return (ShardingUserConfig) userConfig; } - public String getSchema() { return schema; } @@ -806,11 +721,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic this.schema = schema; } - public void setCharacterSet(String name) { - connection.setCharacterSet(name); - } - - public boolean isLocked() { return isLocked; } @@ -827,12 +737,6 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic return txID.get(); } - - public List> getUsrVariables() { - return usrVariables; - } - - public long getLastInsertId() { return lastInsertId; } @@ -853,31 +757,10 @@ public class ShardingService extends MySQLBasedService implements FrontEndServic return sessionReadOnly; } - public ServerLoadDataInfileHandler getLoadDataInfileHandler() { return loadDataInfileHandler; } - public List> getSysVariables() { - return sysVariables; - } - - public List>> getContextTask() { - return contextTask; - } - - public void setContextTask(List>> contextTask) { - this.contextTask = contextTask; - } - - public List>> getInnerSetTask() { - return innerSetTask; - } - - public void setInnerSetTask(List>> innerSetTask) { - this.innerSetTask = innerSetTask; - } - public ServerSptPrepare getSptPrepare() { return sptprepare; } diff --git a/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitHandler.java b/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitHandler.java index 001020a0a..d81e52fc0 100644 --- a/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitHandler.java +++ b/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitHandler.java @@ -39,7 +39,7 @@ public class RWSplitHandler implements ResponseHandler, LoadDataResponseHandler, if (originPacket != null) { mysqlService.execute(rwSplitService, originPacket); } else { - mysqlService.execute(rwSplitService); + mysqlService.execute(rwSplitService, rwSplitService.getExecuteSql()); } } diff --git a/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitQueryHandler.java b/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitQueryHandler.java index 1275aff41..3bc1e4231 100644 --- a/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitQueryHandler.java +++ b/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitQueryHandler.java @@ -2,41 +2,21 @@ package com.actiontech.dble.services.rwsplit; import com.actiontech.dble.config.ErrorCode; import com.actiontech.dble.net.handler.FrontendQueryHandler; -import com.actiontech.dble.net.mysql.OkPacket; import com.actiontech.dble.rwsplit.RWSplitNonBlockingSession; import com.actiontech.dble.server.ServerQueryHandler; +import com.actiontech.dble.server.handler.SetHandler; import com.actiontech.dble.server.handler.UseHandler; import com.actiontech.dble.server.parser.ServerParse; import com.actiontech.dble.singleton.TraceManager; -import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.statement.SQLAssignItem; -import com.alibaba.druid.sql.ast.statement.SQLSetStatement; -import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; -import com.alibaba.druid.sql.parser.SQLStatementParser; import com.google.common.collect.ImmutableMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.List; - public class RWSplitQueryHandler implements FrontendQueryHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ServerQueryHandler.class); private final RWSplitNonBlockingSession session; - //private Boolean readOnly = true; - //private boolean sessionReadOnly = true; - - @Override - public void setReadOnly(Boolean readOnly) { - //this.readOnly = readOnly; - } - - @Override - public void setSessionReadOnly(boolean sessionReadOnly) { - // this.sessionReadOnly = sessionReadOnly; - } public RWSplitQueryHandler(RWSplitNonBlockingSession session) { this.session = session; @@ -59,7 +39,7 @@ public class RWSplitQueryHandler implements FrontendQueryHandler { session.execute(false, null); break; case ServerParse.SET: - parseSet(sql); + SetHandler.handle(sql, session.getService(), rs >>> 8); break; case ServerParse.LOCK: session.execute(true, rwSplitService -> rwSplitService.setLocked(true)); @@ -74,8 +54,7 @@ public class RWSplitQueryHandler implements FrontendQueryHandler { case ServerParse.COMMIT: case ServerParse.ROLLBACK: session.execute(true, rwSplitService -> { - rwSplitService.getSession().unbindIfSafe(); - rwSplitService.setTxStart(false); + rwSplitService.getSession().unbindIfSafe(true); }); break; case ServerParse.LOAD_DATA_INFILE_SQL: @@ -98,46 +77,4 @@ public class RWSplitQueryHandler implements FrontendQueryHandler { } } - // private boolean parseSelectQuery(String sql) { - // boolean canSelectSlave = true; - // SQLStatementParser parser = new MySqlStatementParser(sql); - // SQLStatement statement = parser.parseStatement(true); - // if (statement instanceof SQLSelectStatement) { - // if (!((SQLSelectStatement) statement).getSelect().getQueryBlock().isForUpdate()) { - // canSelectSlave = true; - // } - // } else { - // LOGGER.warn("unknown select"); - // throw new UnsupportedOperationException("unknown"); - // } - // - // return canSelectSlave; - // } - - private void parseSet(String sql) throws IOException { - SQLStatementParser parser = new MySqlStatementParser(sql); - SQLStatement statement = parser.parseStatement(true); - if (statement instanceof SQLSetStatement) { - List assignItems = ((SQLSetStatement) statement).getItems(); - if (assignItems.size() == 1) { - SQLAssignItem item = assignItems.get(0); - if (item.getTarget().toString().equalsIgnoreCase("autocommit")) { - if (session.getService().isAutocommit() && item.getValue().toString().equalsIgnoreCase("0")) { - session.getService().setAutocommit(false); - session.getService().writeDirectly(OkPacket.OK); - } - if (!session.getService().isAutocommit() && item.getValue().toString().equalsIgnoreCase("1")) { - session.execute(false, rwSplitService -> rwSplitService.setAutocommit(true)); - } - } - session.execute(true, null); - } else { - // throw new UnsupportedOperationException("unknown"); - session.execute(true, null); - } - } else { - session.execute(true, null); - } - } - } diff --git a/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitService.java b/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitService.java index f076b2c83..221845d94 100644 --- a/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitService.java +++ b/src/main/java/com/actiontech/dble/services/rwsplit/RWSplitService.java @@ -14,10 +14,11 @@ import com.actiontech.dble.net.service.AuthResultInfo; import com.actiontech.dble.net.service.FrontEndService; import com.actiontech.dble.net.service.ServiceTask; import com.actiontech.dble.rwsplit.RWSplitNonBlockingSession; +import com.actiontech.dble.server.handler.SetHandler; import com.actiontech.dble.server.parser.ServerParse; import com.actiontech.dble.server.response.Heartbeat; import com.actiontech.dble.server.response.Ping; -import com.actiontech.dble.services.MySQLBasedService; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.singleton.FrontendUserManager; import com.actiontech.dble.statistic.CommandCount; import org.slf4j.Logger; @@ -25,20 +26,23 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -public class RWSplitService extends MySQLBasedService implements FrontEndService { +public class RWSplitService extends MySQLVariablesService implements FrontEndService { - protected static final Logger LOGGER = LoggerFactory.getLogger(RWSplitService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RWSplitService.class); + private static final Pattern HINT_DEST = Pattern.compile(".*/\\*\\s*dble_dest_expect\\s*:\\s*([M|S])\\s*\\*/", Pattern.CASE_INSENSITIVE); private volatile String schema; - private volatile int txIsolation; - private volatile boolean autocommit; private volatile boolean isLocked; private volatile boolean txStart; private volatile boolean inLoadData; private volatile boolean inPrepare; private volatile String executeSql; + // only for test + private volatile String expectedDest; private UserName user; private final CommandCount commands; @@ -52,6 +56,26 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService this.queryHandler = new RWSplitQueryHandler(session); } + @Override + public void handleSetItem(SetHandler.SetItem setItem) { + switch (setItem.getType()) { + case AUTOCOMMIT: + String ac = setItem.getValue(); + if (autocommit && !Boolean.parseBoolean(ac)) { + autocommit = false; + writeOkPacket(); + } + if (!autocommit && Boolean.parseBoolean(ac)) { + session.execute(false, rwSplitService -> { + rwSplitService.setAutocommit(true); + }); + } + break; + default: + break; + } + } + public void initFromAuthInfo(AuthResultInfo info) { AuthPacket auth = info.getMysqlAuthPacket(); this.user = new UserName(auth.getUser(), auth.getTenant()); @@ -86,11 +110,7 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService protected void handleInnerData(byte[] data) { // if the statement is load data, directly push down if (inLoadData) { - try { - session.execute(true, data, null); - } catch (IOException e) { - writeErrMessage(ErrorCode.ER_UNKNOWN_COM_ERROR, e.getMessage()); - } + session.execute(true, data, null); return; } @@ -122,12 +142,7 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService break; case MySQLPacket.COM_STMT_CLOSE: commands.doStmtClose(); - try { - session.getService().setInPrepare(false); - session.execute(true, data, null); - } catch (IOException e) { - writeErrMessage(ErrorCode.ER_UNKNOWN_COM_ERROR, e.getMessage()); - } + session.execute(true, data, rwSplitService -> rwSplitService.setInPrepare(false)); break; // connection case MySQLPacket.COM_QUIT: @@ -163,8 +178,6 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService session.execute(true, data, rwSplitService -> rwSplitService.setSchema(switchSchema)); } catch (UnsupportedEncodingException e) { writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown charset '" + getCharset().getClient() + "'"); - } catch (IOException e) { - writeErrMessage(ErrorCode.ER_UNKNOWN_ERROR, e.getMessage()); } } @@ -173,6 +186,14 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService mm.position(5); try { String sql = mm.readString(getCharset().getClient()); + if (LOGGER.isDebugEnabled()) { + Matcher match = HINT_DEST.matcher(sql); + if (match.matches()) { + expectedDest = match.group(1); + } else { + expectedDest = null; + } + } executeSql = sql; queryHandler.query(sql); } catch (UnsupportedEncodingException e) { @@ -202,11 +223,7 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService } private void execute(byte[] data) { - try { - session.execute(true, data, null); - } catch (IOException e) { - writeErrMessage(ErrorCode.ER_UNKNOWN_COM_ERROR, e.getMessage()); - } + session.execute(true, data, null); } @Override @@ -244,18 +261,6 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService isLocked = locked; } - public int getTxIsolation() { - return txIsolation; - } - - public boolean isAutocommit() { - return autocommit; - } - - public void setAutocommit(boolean autocommit) { - this.autocommit = autocommit; - } - public boolean isTxStart() { return txStart; } @@ -280,6 +285,10 @@ public class RWSplitService extends MySQLBasedService implements FrontEndService this.inPrepare = inPrepare; } + public String getExpectedDest() { + return expectedDest; + } + @Override public void killAndClose(String reason) { session.close(reason); diff --git a/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java b/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java index 602e5e069..dfd5f38a0 100644 --- a/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java +++ b/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java @@ -10,18 +10,22 @@ import com.actiontech.dble.backend.datasource.PhysicalDbGroup; import com.actiontech.dble.backend.mysql.nio.handler.ResetConnHandler; import com.actiontech.dble.backend.mysql.nio.handler.ResponseHandler; import com.actiontech.dble.config.ErrorCode; +import com.actiontech.dble.config.Fields; import com.actiontech.dble.net.connection.BackendConnection; import com.actiontech.dble.net.mysql.ErrorPacket; import com.actiontech.dble.net.mysql.FieldPacket; import com.actiontech.dble.net.mysql.ResetConnectionPacket; import com.actiontech.dble.net.mysql.RowDataPacket; import com.actiontech.dble.net.service.AbstractService; -import com.actiontech.dble.server.handler.SetCallBack; +import com.actiontech.dble.server.handler.SetHandler; +import com.actiontech.dble.services.MySQLVariablesService; import com.actiontech.dble.services.mysqlsharding.MySQLResponseService; import com.actiontech.dble.services.mysqlsharding.ShardingService; +import com.actiontech.dble.services.rwsplit.RWSplitService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; @@ -30,43 +34,54 @@ public class SetTestJob implements ResponseHandler, Runnable { public static final Logger LOGGER = LoggerFactory.getLogger(SQLJob.class); private final String sql; - private final String databaseName; private final SQLJobHandler jobHandler; - private final ShardingService shardingService; - private final AtomicBoolean hasReturn = new AtomicBoolean(false); + private final MySQLVariablesService frontService; + private final SetHandler.SetItem[] setItems; + private volatile List fieldPackets; + private final int userVariableSize; + private final AtomicBoolean hasReturn; - public SetTestJob(String sql, String databaseName, SQLJobHandler jobHandler, ShardingService service) { - super(); + public SetTestJob(String sql, SQLJobHandler jobHandler, SetHandler.SetItem[] setItems, int userVariableSize, MySQLVariablesService frontService) { this.sql = sql; - this.databaseName = databaseName; this.jobHandler = jobHandler; - this.shardingService = service; + this.frontService = frontService; + this.setItems = setItems; + this.userVariableSize = userVariableSize; + this.fieldPackets = new ArrayList<>(userVariableSize); + this.hasReturn = new AtomicBoolean(false); } public void run() { boolean sendTest = false; try { - Map dbGroups = DbleServer.getInstance().getConfig().getDbGroups(); - for (PhysicalDbGroup dbGroup : dbGroups.values()) { - if (dbGroup.getWriteDbInstance().isAlive()) { - dbGroup.getWriteDbInstance().getConnection(databaseName, this, null, false); - sendTest = true; - break; + + if (frontService instanceof ShardingService) { + Map dbGroups = DbleServer.getInstance().getConfig().getDbGroups(); + for (PhysicalDbGroup dbGroup : dbGroups.values()) { + if (dbGroup.getWriteDbInstance().isAlive()) { + dbGroup.getWriteDbInstance().getConnection(null, this, null, false); + sendTest = true; + break; + } } + } else { + ((RWSplitService) frontService).getSession().getRwGroup().getWriteDbInstance().getConnection(null, this, null, false); + sendTest = true; } + } catch (Exception e) { if (hasReturn.compareAndSet(false, true)) { String reason = "can't get backend connection for sql :" + sql + " " + e.getMessage(); - LOGGER.info(reason, e); + LOGGER.warn(reason, e); doFinished(true); - shardingService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, reason); + frontService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, reason); } } if (!sendTest && hasReturn.compareAndSet(false, true)) { - String reason = "can't get backend connection for sql :" + sql + " all datasrouce dead"; - LOGGER.info(reason); + String reason = "can't get backend connection for sql[" + sql + "],because all dbInstances are dead."; + LOGGER.warn(reason); doFinished(true); - shardingService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, reason); + frontService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, reason); } } @@ -77,11 +92,11 @@ public class SetTestJob implements ResponseHandler, Runnable { } conn.getBackendService().setResponseHandler(this); conn.getBackendService().setComplexQuery(true); - conn.getBackendService().sendQueryCmd(sql, shardingService.getCharset()); + conn.getBackendService().execute(frontService, sql); } private void doFinished(boolean failed) { - jobHandler.finished(databaseName, failed); + jobHandler.finished(null, failed); } @Override @@ -90,7 +105,7 @@ public class SetTestJob implements ResponseHandler, Runnable { String reason = "can't get backend connection for sql :" + sql + " " + e.getMessage(); LOGGER.info(reason); doFinished(true); - shardingService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, reason); + frontService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, reason); } } @@ -99,7 +114,7 @@ public class SetTestJob implements ResponseHandler, Runnable { if (hasReturn.compareAndSet(false, true)) { LOGGER.info("connectionClose sql :" + sql); doFinished(true); - this.shardingService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, "connectionClose:" + reason); + this.frontService.writeErrMessage(ErrorCode.ERR_HANDLE_DATA, "connectionClose:" + reason); } } @@ -110,18 +125,19 @@ public class SetTestJob implements ResponseHandler, Runnable { errPg.read(err); doFinished(true); ((MySQLResponseService) service).release(); //conn context not change - this.shardingService.writeErrMessage(errPg.getErrNo(), new String(errPg.getMessage())); + this.frontService.writeErrMessage(errPg.getErrNo(), new String(errPg.getMessage())); } } @Override public void okResponse(byte[] ok, AbstractService service) { + if (userVariableSize > 0) { + return; + } + MySQLResponseService responseService = (MySQLResponseService) service; if (hasReturn.compareAndSet(false, true)) { doFinished(false); - if (!((SetCallBack) ((OneRawSQLQueryResultHandler) jobHandler).getCallback()).isBackToOtherThread()) { - shardingService.write(shardingService.getSession2().getOKPacket()); - } ResetConnHandler handler = new ResetConnHandler(); responseService.setResponseHandler(handler); responseService.setComplexQuery(true); @@ -130,27 +146,50 @@ public class SetTestJob implements ResponseHandler, Runnable { } @Override - public void fieldEofResponse(byte[] header, List fields, List fieldPackets, byte[] eof, + public void fieldEofResponse(byte[] header, List fields, List fps, byte[] eof, boolean isLeft, AbstractService service) { - //will not happen - + for (byte[] field : fields) { + // save field + FieldPacket fieldPk = new FieldPacket(); + fieldPk.read(field); + fieldPackets.add(fieldPk); + } } @Override public boolean rowResponse(byte[] row, RowDataPacket rowPacket, boolean isLeft, AbstractService service) { - //will not happen + RowDataPacket rowDataPk = new RowDataPacket(fieldPackets.size()); + rowDataPk.read(row); + for (int i = 0; i < userVariableSize; i++) { + if (rowDataPk.getValue(i) == null) { + continue; + } + int type = fieldPackets.get(i).getType(); + if (type == Fields.FIELD_TYPE_LONG || type == Fields.FIELD_TYPE_LONGLONG || type == Fields.FIELD_TYPE_NEW_DECIMAL || + type == Fields.FIELD_TYPE_FLOAT | type == Fields.FIELD_TYPE_DOUBLE) { + setItems[i].setValue(new String(rowDataPk.getValue(i))); + } else { + setItems[i].setValue("'" + new String(rowDataPk.getValue(i)) + "'"); + } + } return false; } @Override public void rowEofResponse(byte[] eof, boolean isLeft, AbstractService service) { - //will not happen + MySQLResponseService responseService = (MySQLResponseService) service; + if (hasReturn.compareAndSet(false, true)) { + doFinished(false); + ResetConnHandler handler = new ResetConnHandler(); + responseService.setResponseHandler(handler); + responseService.setComplexQuery(true); + responseService.writeDirectly(responseService.writeToBuffer(ResetConnectionPacket.RESET, responseService.allocate())); + } } @Override public String toString() { - return "SQLJob [Database=" + - databaseName + ",sql=" + sql + ", jobHandler=" + + return "SQLJob [sql=" + sql + ", jobHandler=" + jobHandler + "]"; } } diff --git a/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java b/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java index ad0da778e..cd5fd14be 100644 --- a/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java +++ b/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java @@ -22,24 +22,24 @@ public class SetHandlerTest { Assert.assertEquals("SET names utf8,character set UTF8,character set gbk,@@tx_readonly=1", convertCharsetKeyWord.invoke(null, "SET names utf8,CHARSET UTF8,CHARSET gbk,@@tx_readonly=1")); } - @Test - public void testCheckSetNamesSyntax() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Method checkSetNamesSyntax = SetHandler.class.getDeclaredMethod("checkSetNamesSyntax", String.class); - checkSetNamesSyntax.setAccessible(true); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "SET NAMES utf8")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names 'utf8'")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names `utf8`")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names DEFAULT")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE utf8_bin")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE default")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names 'utf8' COLLATE utf8_bin")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names `utf8` COLLATE default")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE 'utf8_bin'")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE `utf8_bin`")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names 'utf8' COLLATE 'utf8_bin'")); - Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names `utf8` COLLATE `utf8_bin`")); - Assert.assertEquals(false, checkSetNamesSyntax.invoke(null, "set names utf8 2")); - Assert.assertEquals(false, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATION utf8_bin")); - } +// @Test + // public void testCheckSetNamesSyntax() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + // Method checkSetNamesSyntax = SetHandler.class.getDeclaredMethod("checkSetNamesSyntax", String.class); + // checkSetNamesSyntax.setAccessible(true); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "SET NAMES utf8")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names 'utf8'")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names `utf8`")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names DEFAULT")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE utf8_bin")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE default")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names 'utf8' COLLATE utf8_bin")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names `utf8` COLLATE default")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE 'utf8_bin'")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATE `utf8_bin`")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names 'utf8' COLLATE 'utf8_bin'")); + // Assert.assertEquals(true, checkSetNamesSyntax.invoke(null, "set names `utf8` COLLATE `utf8_bin`")); + // Assert.assertEquals(false, checkSetNamesSyntax.invoke(null, "set names utf8 2")); + // Assert.assertEquals(false, checkSetNamesSyntax.invoke(null, "set names utf8 COLLATION utf8_bin")); + // } } diff --git a/src/test/java/demo/test/Testparser.java b/src/test/java/demo/test/Testparser.java index 087337340..398e2db7b 100644 --- a/src/test/java/demo/test/Testparser.java +++ b/src/test/java/demo/test/Testparser.java @@ -1,744 +1,36 @@ package demo.test; -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.SQLStatement; -import com.alibaba.druid.sql.ast.expr.*; -import com.alibaba.druid.sql.ast.statement.*; -import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; -import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique; -import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey; -import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; -import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.*; -import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; -import com.alibaba.druid.sql.parser.SQLStatementParser; +import java.sql.*; public class Testparser { - public static void main(String args[]) { + public static void main(String args[]) throws ClassNotFoundException, SQLException { - Testparser obj = new Testparser(); - // obj.test("CREATE TABLE `char_columns_test` (`id` int(11) NOT NULL,`c_char` char(255) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); - // obj.test("CREATE TABLE `xx`.`char_columns_test` (`id` int(11) NOT NULL,`c_char` char(255) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); - obj.test("CREATE TABLE `xx`.`char_columns_test` (`id` int(11) NOT NULL,`c_char` char(255) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY c_charx (c_char) COMMENT '唯一性' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); - // obj.test("drop table char_columns_test;"); - // obj.test("truncate table char_columns_test;"); - String strSetSql = "SELECT\n" + - "\t@@SESSION .auto_increment_increment AS auto_increment_increment,\n" + - "\t@@character_set_client AS character_set_client,\n" + - "\t@@character_set_connection AS character_set_connection,\n" + - "\t@@character_set_results AS character_set_results,\n" + - "\t@@character_set_server AS character_set_server,\n" + - "\t@@init_connect AS init_connect,\n" + - "\t@@interactive_timeout AS interactive_timeout,\n" + - "\t@@license AS license,\n" + - "\t@@lower_case_table_names AS lower_case_table_names,\n" + - "\t@@max_allowed_packet AS max_allowed_packet,\n" + - "\t@@net_buffer_length AS net_buffer_length,\n" + - "\t@@net_write_timeout AS net_write_timeout,\n" + - "\t@@query_cache_size AS query_cache_size,\n" + - "\t@@query_cache_type AS query_cache_type,\n" + - "\t@@sql_mode AS sql_mode,\n" + - "\t@@system_time_zone AS system_time_zone,\n" + - "\t@@time_zone AS time_zone,\n" + - "\t@@tx_isolation AS tx_isolation,\n" + - "\t@@wait_timeout AS wait_timeout;"; -// obj.test(strSetSql); -// strSetSql = "SET SESSION sql_mode = 'TRADITIONAL';"; -// obj.test(strSetSql); -// strSetSql = "SET SESSION sql_mode = `TRADITIONAL`;"; -// obj.test(strSetSql); -// strSetSql = "SET SESSION sql_mode = \"TRADITIONAL\";"; -// obj.test(strSetSql); - //todo not support -// strSetSql = "SET CHARSET utf8;"; -// obj.test(strSetSql); -// strSetSql = "SET CHARSET `utf8`;"; -// obj.test(strSetSql); -// strSetSql = "SET CHARSET 'UTF8';"; -// obj.test(strSetSql); -// strSetSql = "SET CHARSET \"UTF8\";"; -// obj.test(strSetSql); -// strSetSql = "SET CHARSET DEFAULT;"; -// obj.test(strSetSql); -// strSetSql = "SET names \"UTF8\";"; -// obj.test(strSetSql); - -// strSetSql = "set @@tx_read_only =0,names utf8,charset utf8;"; -// obj.test(strSetSql); - - strSetSql = "SET CHARACTER SET utf8;"; - obj.test(strSetSql); - strSetSql = "SET CHARACTER SET `utf8`;"; - obj.test(strSetSql); - strSetSql = "SET CHARACTER SET 'UTF8';"; - obj.test(strSetSql); - strSetSql = "SET CHARACTER SET \"UTF8\";"; - obj.test(strSetSql); - strSetSql = "SET CHARACTER SET DEFAULT;"; - obj.test(strSetSql); - strSetSql = "SET names utf8;"; - obj.test(strSetSql); - strSetSql = "SET names `utf8`;"; - obj.test(strSetSql); - strSetSql = "SET names 'UTF8';"; - obj.test(strSetSql); - strSetSql = "SET names utf8 COLLATE default;"; - obj.test(strSetSql); - strSetSql = "SET names utf8 COLLATE utf8_general_ci;"; - obj.test(strSetSql); - strSetSql = "SET names utf8 COLLATE `utf8_general_ci`;"; - obj.test(strSetSql); - strSetSql = "SET names utf8 COLLATE 'utf8_general_ci';"; - obj.test(strSetSql); - strSetSql = "SET names default;"; - obj.test(strSetSql); - strSetSql = "set names utf8,@@tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set @@tx_read_only =0,names utf8,character set utf8;"; - obj.test(strSetSql); - strSetSql = "set @@tx_read_only =0,names utf8;"; - obj.test(strSetSql); - strSetSql = "set @@tx_read_only =0,names utf8 collation default;"; - obj.test(strSetSql); - strSetSql = "set @@tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set @@GLOBAL.tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set @@session.tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set GLOBAL tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set Session tx_read_only =0;"; - obj.test(strSetSql); - strSetSql = "set Session tx_isolation ='READ-COMMITTED';"; - obj.test(strSetSql); - strSetSql = "set Session tx_isolation =`READ-COMMITTED`;"; - obj.test(strSetSql); - strSetSql = "set Session tx_isolation =\"READ-COMMITTED\";"; - obj.test(strSetSql); - strSetSql = "SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;"; - obj.test(strSetSql); - strSetSql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;"; - obj.test(strSetSql); - strSetSql = "SET TRANSACTION ISOLATION LEVEL READ COMMITTED ;"; - obj.test(strSetSql); - strSetSql = "SET TRANSACTION READ WRITE;"; - obj.test(strSetSql); - strSetSql = "SET TRANSACTION read only;"; - obj.test(strSetSql); - strSetSql = "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;"; - obj.test(strSetSql); -// strSetSql = "SET @total_tax = (SELECT SUM(tax) FROM taxable_transactions);"; -// obj.test(strSetSql); -// -// strSetSql = "SET @@session.sql_mode = 'TRADITIONAL';"; -// obj.test(strSetSql); -// strSetSql = "SET @@global.sql_mode = 'TRADITIONAL';"; -// obj.test(strSetSql); -// strSetSql = "SET @@sql_mode = 'TRADITIONAL';"; -// obj.test(strSetSql); -// strSetSql = "SET GLOBAL sql_log_bin = ON;"; -// obj.test(strSetSql); -// strSetSql = "SET max_connections = 1000;"; -// obj.test(strSetSql); -// strSetSql = "SET @x = 1;"; -// obj.test(strSetSql); -// strSetSql = "SET @x = 1, SESSION sql_mode = '';"; -// obj.test(strSetSql); -// strSetSql = "SET GLOBAL sort_buffer_size = 1000000, SESSION sort_buffer_size = 1000000;"; -// obj.test(strSetSql); -// strSetSql = "SET GLOBAL max_connections = 1000, sort_buffer_size = 1000000;"; -// obj.test(strSetSql); -// strSetSql = "SET xa =0 ;"; -// obj.test(strSetSql); -// strSetSql = "SET xa = off ;"; -// obj.test(strSetSql); - //String strShowSql = ""; - //strShowSql = "show create table a;"; - //obj.test(strShowSql); - // strShowSql ="show full columns from char_columns2 from ares_test like 'i%';"; - // obj.test(strShowSql); - // strShowSql ="show full columns from char_columns2 from ares_test where Field='id';"; - // obj.test(strShowSql); - // strShowSql ="show full fields from char_columns2 from ares_test like 'i%';"; - // obj.test(strShowSql); - // strShowSql ="show full columns from ares_test.char_columns2;"; - // obj.test(strShowSql); - // - // strShowSql ="show index from char_columns2 from ares_test where Key_name = 'PRIMARY';"; - // obj.test(strShowSql); - // strShowSql ="show indexes from char_columns2 from ares_test where Key_name = 'PRIMARY';"; - // obj.test(strShowSql); - // strShowSql ="show keys from char_columns2 from ares_test where Key_name = 'PRIMARY';"; - // obj.test(strShowSql); - // strShowSql ="show keys from ares_test.char_columns2 where Key_name = 'PRIMARY';"; - // obj.test(strShowSql); - // String strULSql =""; - // strULSql ="desc a;"; - // obj.test(strULSql); - // strULSql ="describe a;"; - // obj.test(strULSql); - // strULSql ="describe a.b;"; - // obj.test(strULSql); - // strULSql ="desc a b;"; - // obj.test(strULSql); - // - // strULSql ="explain a;"; - // obj.test(strULSql); - // - // strULSql ="explain select * from a;"; - // obj.test(strULSql); - - // obj.test("create index idx_test on char_columns_test(id) ;"); - // obj.test("drop index idx_test on char_columns_test;"); - String strAlterSql = ""; - strAlterSql ="alter table char_columns_test add column id2 int(11) NOT NULL after x ALGORITHM = default LOCK =default;"; -// obj.test(strAlterSql); - // strAlterSql ="alter table char_columns_test add column id2 int(11) NOT NULL after x;"; - // obj.test(strAlterSql); - // strAlterSql ="alter table char_columns_test add column id2 int(11) NOT NULL,id3 int(11) NOT NULL;"; - // obj.test(strAlterSql); - // strAlterSql="alter table char_columns_test add index idx_test(id) ;"; - // obj.test(strAlterSql); - // strAlterSql="alter table char_columns_test add key idx_test(id) ;"; - // obj.test(strAlterSql); - // strAlterSql="alter table char_columns_test unique key idx_test(id) ;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 ADD CONSTRAINT MyPrimaryKey PRIMARY KEY (id);"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 ADD CONSTRAINT MyUniqueConstraint UNIQUE(c_char);"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 drop index idex_test;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 drop key idex_test;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 CHANGE COLUMN c_char c_varchar varchar(255) DEFAULT NULL ;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 CHANGE COLUMN c_char c_varchar varchar(255) DEFAULT NULL FIRST;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 CHANGE COLUMN c_char c_varchar varchar(255) DEFAULT NULL AFTER id ;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 modify COLUMN c_char varchar(255) DEFAULT NULL ;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 modify COLUMN c_char varchar(255) DEFAULT NULL FIRST;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 modify COLUMN c_char varchar(255) DEFAULT NULL AFTER id ;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 DROP COLUMN c_char;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 DROP PRIMARY KEY;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE char_columns1 RENAME TO char_columns1_1;"; - // obj.test(strAlterSql); - // strAlterSql = "ALTER TABLE test_yhq.char_columns1 RENAME AS test_yhq2.char_columns1_1;"; - // obj.test(strAlterSql); - - String strDeleteSql = ""; - // strDeleteSql = "delete a from test_yhq.char_columns1 a where 1=1;"; - // obj.test(strDeleteSql); - // strDeleteSql = "delete from test_yhq.char_columns1 where 1=1;"; - // obj.test(strDeleteSql); - // strDeleteSql = "delete a from test_yhq.char_columns1 a inner join test_yhq.char_columns1 b on a.id =b.id where 1=1;"; - // obj.test(strDeleteSql); - // strDeleteSql = "delete a,b from test_yhq.char_columns1 a inner join test_yhq.char_columns1 b on a.id =b.id where 1=1;"; - // obj.test(strDeleteSql); - // strDeleteSql = "DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;"; - // obj.test(strDeleteSql); - // strDeleteSql = "DELETE a, b FROM t1 a INNER JOIN t2 b INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;"; - // obj.test(strDeleteSql); - // strDeleteSql = "DELETE t1, t2 FROM t1 ,t2 using(id) where 1=1;"; - // obj.test(strDeleteSql); + Class.forName("com.mysql.jdbc.Driver"); + Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:8066/test?useServerPrepStmts=true&&useAffectedRows=true", "rw", "123456"); - // String strUpdateSql = ""; - // strUpdateSql = "UPDATE t1 SET col1 = col1 + 1,col2 = col1 ;"; - // obj.test(strUpdateSql); - // strUpdateSql = "UPDATE t SET id = id + 1 ORDER BY id DESC;"; - // obj.test(strUpdateSql); - // strUpdateSql = "UPDATE items,month SET items.price=month.price WHERE items.id=month.id;"; - // obj.test(strUpdateSql); - // strUpdateSql = "UPDATE items inner join month on items.id=month.id SET items.price=month.price;"; - // obj.test(strUpdateSql); - // strUpdateSql = "UPDATE EmployeeS AS P SET P.LEAGUENO = '2000' WHERE P.EmployeeNO = 95;"; - // obj.test(strUpdateSql); - // String strCreateIndex = ""; - // strCreateIndex = "CREATE INDEX part_of_name ON customer (name(10));"; - // obj.test(strCreateIndex); - // strCreateIndex = "CREATE UNIQUE INDEX part_of_name ON customer (name(10));"; - // obj.test(strCreateIndex); - String selectSQl = "select avg(char_columns.id), BIT_AND(char_columns.ID),BIT_OR(char_columns.ID),bit_xor(char_columns.ID)," - + "COUNT(char_columns.ID),MAX(distinct char_columns.ID),MIN(distinct char_columns.ID)," - + "STD(char_columns.ID),STDDEV(char_columns.ID),STDDEV_POP(char_columns.ID),STDDEV_SAMP(char_columns.ID), " - + "sum(id),VAR_POP(char_columns.ID),VAR_SAMP(char_columns.ID),VARIANCE(char_columns.ID)" - + " from char_columns where id =1 and name = 'x';"; + // Connection conn = DriverManager.getConnection("jdbc:mysql://10.186.61.151:33306/test?useServerPrepStmts=true&&useAffectedRows=true", "root", "123456"); - // obj.test(selectSQl); -// selectSQl = "select * from constant_one where id > SOME(select name from constant_two);"; -// obj.test(selectSQl); -// selectSQl = "select * from constant_one where id > ANY(select name from constant_two);"; -// obj.test(selectSQl); -// selectSQl = "select * from constant_one where id > ALL(select name from constant_two);"; -// obj.test(selectSQl); -// selectSQl = "select * from constant_one where id <> ALL(select name from constant_two);"; -// obj.test(selectSQl); - // selectSQl = "SELECT BINARY 'a' = 'A';"; - // obj.test(selectSQl); -// selectSQl = "SELECT b'1000001';"; -// obj.test(selectSQl); - // selectSQl = "SELECT GET_FORMAT(DATE);"; - // obj.test(selectSQl); - // selectSQl = "select CURRENT_DATE;";//not support - // obj.test(selectSQl); - // selectSQl = "SELECT student_name, GROUP_CONCAT(test_score) " - // + "FROM student GROUP BY student_name;"; - // obj.test(selectSQl); - // selectSQl = "select @@tx_read_only;"; - // obj.test(selectSQl); - // selectSQl = "SELECT ABS(-1);"; - // obj.test(selectSQl); - // selectSQl = "SELECT NOT 10,1 AND 1,IF(1<2,'yes','no'),'Monty!' REGEXP '.*';"; - // obj.test(selectSQl); - // selectSQl = "select 'David_' LIKE 'David|_' ESCAPE '|','a' LIKE 'ae' COLLATE utf8_general_ci"; - // obj.test(selectSQl); - // selectSQl = "SELECT 1 IS NULL,1 IS NOT UNKNOWN,1 IS TRUE, 0 IS FALSE,2 IN (0,3,5,7), 2 >= 2,1 = 0,2 BETWEEN 1 AND 3;"; - // obj.test(selectSQl); - // selectSQl = "select CAST(expr AS datetime(6) ), CAST(expr AS date ), CAST(expr AS time(6) ) from char_columns where id =1 and name = 'x';"; - selectSQl = "SELECT CHARSET(CHAR(X'65')), CHARSET(CHAR(X'65' USING utf8));"; - obj.test(selectSQl); - selectSQl = "select CAST(expr AS nchar(2) CHARACTER SET utf8),CAST(expr AS char(2)), CAST(expr AS char(2) CHARACTER SET utf8 ),CAST(expr AS char(2) CHARACTER SET latin1 ) from char_columns where id =1 and name = 'x';"; - obj.test(selectSQl); - selectSQl = "select CAST(expr AS char(2) CHARACTER SET utf8 ),CAST(expr AS SIGNED ),CAST(expr AS unSIGNED ) from char_columns where id =1 and name = 'x';"; - obj.test(selectSQl); -// // TODO:NOT SUPPORTED -// selectSQl = "select CAST(expr AS char(2) CHARACTER SET utf8 ),CAST(expr AS SIGNED INT ),CAST(expr AS unSIGNED INT ) from char_columns where id =1 and name = 'x';"; -// obj.test(selectSQl); - selectSQl = "select CONVERT(expr , char(2)) from char_columns where id =1 and name = 'x';"; - obj.test(selectSQl); - // selectSQl = "SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END, CASE WHEN 1>0 THEN 'true' ELSE 'false' END;"; - // obj.test(selectSQl); - // selectSQl = "SELECT 3 DIV 5, - (2), 3/5;"; - // obj.test(selectSQl); - // selectSQl = "SELECT ~5 , SELECT 29 & 15;"; - // obj.test(selectSQl); - selectSQl = "SELECT LTRIM(' barbar'),TRIM(LEADING 'x' FROM 'xxxbarxxx'),TRIM('x' FROM 'xxxbarxxx'),SOUNDEX('Hello'), CONVERT('abc' USING utf8);"; - obj.test(selectSQl); - // selectSQl = "SELECT SOUNDEX('Hello'),CHAR(77,121,83,81,'76');"; - // obj.test(selectSQl); - // selectSQl = "SELECT student_name, GROUP_CONCAT(DISTINCT test_score order by id asc,test_score2 DESC SEPARATOR \",,\") FROM student GROUP BY student_name;"; - // obj.test(selectSQl); - // selectSQl = "select char_columns.id from char_columns where id =1 order by id desc;"; - // obj.test(selectSQl); - // selectSQl = "select * from (select * from char_columns where id =1 order by id) x;"; - // obj.test(selectSQl); - // selectSQl = "select * from char_columns where id in(select id from char_columns where id =1 ) ;"; - // obj.test(selectSQl); - // selectSQl = "SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;"; - // obj.test(selectSQl); - // selectSQl = "SELECT * FROM t1 inner join t2 on t1.id =t2.id WHERE t1.f1 > 30;"; - // obj.test(selectSQl); + // Statement stmt = conn.createStatement(); + // stmt.execute("/*#dble:db_type=master*/select * from testdb.tb_enum_sharding;"); + // stmt.close(); + // conn.close(); - // selectSQl = "SELECT id,sum(x),(select * from id) FROM t1 group by id desc having count(*)<3 limit 1;"; - // obj.test(selectSQl); - // selectSQl = "SELECT id FROM (select id,name from tb) x where id =1;"; - // obj.test(selectSQl); - // selectSQl = "SELECT id FROM x where id =1 union all SELECT id FROM y where id =1 ;"; - // obj.test(selectSQl); - // - // selectSQl = "SELECT TIMESTAMPADD(WEEK,1,'2003-01-02'), TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01'),DATE_ADD(OrderDate,INTERVAL 2 DAY) AS OrderPayDate,ADDDATE('2008-01-02', INTERVAL 31 DAY),ADDDATE('2008-01-02', 31),EXTRACT(YEAR FROM '2009-07-02') FROM Orders;"; - // obj.test(selectSQl); - // selectSQl = "SELECT * FROM Orders as t;"; - // obj.test(selectSQl); - // selectSQl = "select 1,null,'x','xxx';"; - // obj.test(selectSQl); - // selectSQl = "select * from table1 a inner join table2 b on a.id =b.id " - // + "inner join table3 c on b.id =c.id;"; - // obj.test(selectSQl); - // selectSQl = "select * from table1 a inner join table2 b on a.id =b.id " - // + "inner join table3 c on a.id =c.id;"; - // obj.test(selectSQl); - // selectSQl = "select * from table1 a left join table2 b on a.id =b.id " - // + "left join table3 c on a.id =c.id;"; - // obj.test(selectSQl); - // selectSQl = "select * from table1 a left join table2 b on a.id =b.id " - // + "inner join table3 c on a.id =c.id;"; - // obj.test(selectSQl); - // selectSQl = "select CONCAT(A,b),count(*) from table1 GROUP BY CONCAT(A,b);"; - // obj.test(selectSQl); - // selectSQl = "select id,count(*) from table1 GROUP BY id having count(*)>1;"; - // obj.test(selectSQl); - // selectSQl = "select id,count(*) from table1 GROUP BY table.id having count(*)>1;"; - // obj.test(selectSQl); - // selectSQl = "select id,count(*) from table1 GROUP BY id order by count(*);"; - // obj.test(selectSQl); - // selectSQl = "select id from db.table1 GROUP BY db.table1.id;"; - // obj.test(selectSQl); + PreparedStatement stmt = conn.prepareStatement("select * from test where id=?"); + stmt.setInt(1, 1); - // selectSQl = "select id,'abc' from db.table1 GROUP BY db.table1.id;"; - // selectSQl = "select * from sharding_two_node a natural join sharding_four_node b ;"; - // obj.test(selectSQl); - // selectSQl = "select * from sharding_two_node a where id = (select min(id) from sharding_two_node) ;"; - // obj.test(selectSQl); - // selectSQl = "SELECT column1 FROM t1 AS x WHERE x.column1 = (SELECT column1 FROM t2 AS x " - // + "WHERE x.column1 = (SELECT column1 FROM t3 " - // + "WHERE x.column2 = t3.column1));"; - // obj.test(selectSQl); - // selectSQl = "SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);"; - // obj.test(selectSQl); - // selectSQl = "SELECT s1 FROM t1 WHERE s1 = SOME (SELECT s1 FROM t2);"; - // obj.test(selectSQl); - // selectSQl = "SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);"; - // obj.test(selectSQl); - // selectSQl = "SELECT * FROM t1 WHERE (col1,col2) = (SELECT col3, col4 FROM t2 WHERE id = 10);"; - // obj.test(selectSQl); - // selectSQl = "SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);"; - // obj.test(selectSQl); - // selectSQl = "SELECT column1 FROM t1 WHERE Not EXISTS (SELECT * FROM t2);"; - // obj.test(selectSQl); - // selectSQl = "SELECT (SELECT s2 FROM t1);"; - // obj.test(selectSQl); - // selectSQl = "SELECT 1 + 1 FROM DUAL;"; - // obj.test(selectSQl); - // selectSQl = "select * from sharding_two_node where id in(select id from sharding_four_node);"; - // obj.test(selectSQl); - // selectSQl = "select * from t1 where s1 in(1,(select s1 from t2));"; - // obj.test(selectSQl); - // selectSQl = "select distinct pad from sbtest1;"; - // obj.test(selectSQl); - // selectSQl = "select distinctrow pad from sbtest1;"; - // obj.test(selectSQl); - // selectSQl = "select distinct sql_big_result pad from sbtest1;"; - // obj.test(selectSQl); - // //not support - // selectSQl = "select sql_big_result distinct pad from sbtest1;"; - // obj.test(selectSQl); - String insertSQl = "insert into test_shard values(1,1,'a\\%string','test001');"; - obj.test(insertSQl); - - } - - public void test(String sql) { - System.out.println("-----------------------------------------------------------"); - System.out.println("-----------------------------------------------------------"); - System.out.println(sql); - SQLStatementParser parser = new MySqlStatementParser(sql); - SQLStatement statement = parser.parseStatement(); - if (statement instanceof MySqlExplainStatement) { - System.out.println("MySqlExplainStatement" + statement.toString()); - } else if (statement instanceof MySqlCreateTableStatement) { - MySqlCreateTableStatement createStment = (MySqlCreateTableStatement) statement; - SQLExpr expr = createStment.getTableSource().getExpr(); - if (expr instanceof SQLPropertyExpr) { - SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; - System.out.println((propertyExpr.getOwner().toString())); - System.out.println(propertyExpr.getName()); - } else if (expr instanceof SQLIdentifierExpr) { - SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr; - System.out.println(identifierExpr.getName()); - } else { - System.out.println(expr.getClass() + "\n"); - } - - } else if (statement instanceof SQLAlterTableStatement) { - SQLAlterTableStatement alterStatement = (SQLAlterTableStatement) statement; - SQLExprTableSource tableSource = alterStatement.getTableSource(); - for (SQLAlterTableItem alterItem : alterStatement.getItems()) { - if (alterItem instanceof SQLAlterTableAddColumn) { - SQLAlterTableAddColumn addColumn = (SQLAlterTableAddColumn) alterItem; - boolean isFirst = addColumn.isFirst(); - SQLName afterColumn = addColumn.getAfterColumn(); - if (afterColumn != null) { - System.out.println(sql + ": afterColumns:\n" + afterColumn.getClass().toString() + "\n"); - } - for (SQLColumnDefinition columnDef : addColumn.getColumns()) { - - } - } else if (alterItem instanceof SQLAlterTableAddIndex) { - SQLAlterTableAddIndex addIndex = (SQLAlterTableAddIndex) alterItem; - SQLName name = addIndex.getName(); - System.out.println(sql + ":indexname:\n" + name.getClass().toString() + "\n"); - String type = addIndex.getType(); - addIndex.isUnique();// ?? - for (SQLSelectOrderByItem item : addIndex.getItems()) { - System.out.println(sql + ": item.getExpr():\n" + item.getExpr().getClass().toString() + "\n"); - } - } else if (alterItem instanceof SQLAlterTableAddConstraint) { - SQLAlterTableAddConstraint addConstraint = (SQLAlterTableAddConstraint) alterItem; - SQLConstraint constraint = addConstraint.getConstraint(); - if (constraint instanceof MySqlUnique) { - MySqlUnique unique = (MySqlUnique) constraint; - unique.getName(); - } else if (constraint instanceof MySqlPrimaryKey) { - - } else if (constraint instanceof MysqlForeignKey) { - System.out.println("NOT SUPPORT\n"); - } - - System.out.println(sql + ": constraint:\n" + constraint.getClass().toString() + "\n"); - } else if (alterItem instanceof SQLAlterTableDropIndex) { - SQLAlterTableDropIndex dropIndex = (SQLAlterTableDropIndex) alterItem; - SQLIdentifierExpr indexName = (SQLIdentifierExpr) dropIndex.getIndexName(); - String strIndexName = indexName.getName(); - } else if (alterItem instanceof SQLAlterTableDropKey) { - SQLAlterTableDropKey dropIndex = (SQLAlterTableDropKey) alterItem; - SQLIdentifierExpr indexName = (SQLIdentifierExpr) dropIndex.getKeyName(); - String strIndexName = indexName.getName(); - } else if (alterItem instanceof MySqlAlterTableChangeColumn) { - MySqlAlterTableChangeColumn changeColumn = (MySqlAlterTableChangeColumn) alterItem; - boolean isFirst = changeColumn.isFirst(); - SQLIdentifierExpr afterColumn = (SQLIdentifierExpr) changeColumn.getAfterColumn(); - // SQLExpr afterColumn = changeColumn.getAfterColumn(); - if (afterColumn != null) { - String strAfterColumn = afterColumn.getName(); - } - SQLColumnDefinition columnDef = changeColumn.getNewColumnDefinition(); - } else if (alterItem instanceof MySqlAlterTableModifyColumn) { - MySqlAlterTableModifyColumn modifyColumn = (MySqlAlterTableModifyColumn) alterItem; - boolean isFirst = modifyColumn.isFirst(); - SQLExpr afterColumn = modifyColumn.getAfterColumn(); - if (afterColumn != null) { - System.out.println(sql + ": afterColumns:\n" + afterColumn.getClass().toString() + "\n"); - } - SQLColumnDefinition columnDef = modifyColumn.getNewColumnDefinition(); - } else if (alterItem instanceof SQLAlterTableDropColumnItem) { - SQLAlterTableDropColumnItem dropColumn = (SQLAlterTableDropColumnItem) alterItem; - for (SQLName dropName : dropColumn.getColumns()) { - System.out.println(sql + ":dropName:\n" + dropName.getClass().toString() + "\n"); - } - } else if (alterItem instanceof SQLAlterTableDropPrimaryKey) { - SQLAlterTableDropPrimaryKey dropPrimary = (SQLAlterTableDropPrimaryKey) alterItem; - } else { - System.out.println(sql + ":\n" + alterItem.getClass().toString() + "\n"); - } - System.out.println("\n" + statement.toString()); - } - } else if (statement instanceof SQLDropTableStatement) { - } else if (statement instanceof SQLTruncateStatement) { - //TODO:Sequence? - } else if (statement instanceof SQLDropIndexStatement) { - //TODO - } else if (statement instanceof MySqlDeleteStatement) { - MySqlDeleteStatement deleteStatement = (MySqlDeleteStatement) statement; - SQLTableSource tableSource = deleteStatement.getTableSource(); - - System.out.println(sql + ":getTableSource:" + tableSource.getClass().toString() + "\n"); - if (deleteStatement.getFrom() != null) { - System.out.println(sql + ":getSchema:" + deleteStatement.getFrom().getClass().toString() + "\n"); - } - System.out.println("\n"); - } else if (statement instanceof MySqlUpdateStatement) { - MySqlUpdateStatement updateStatement = (MySqlUpdateStatement) statement; - SQLTableSource tableSource = updateStatement.getTableSource(); - - System.out.println(sql + ":getTableSource:" + tableSource.getClass().toString() + "\n"); - System.out.println("\n" + statement.toString()); - - } else if (statement instanceof SQLCreateIndexStatement) { - SQLCreateIndexStatement stament = (SQLCreateIndexStatement) statement; - SQLTableSource tableSource = stament.getTable(); - System.out.println(sql + ":getTableSource:" + tableSource.getClass().toString() + "\n"); - System.out.println(sql + stament.getType()); - } else if (statement instanceof SQLSelectStatement) { - SQLSelectStatement stament = (SQLSelectStatement) statement; - SQLSelectQuery sqlSelectQuery = stament.getSelect().getQuery(); - if (sqlSelectQuery instanceof MySqlSelectQueryBlock) { - MySqlSelectQueryBlock selectQueryBlock = (MySqlSelectQueryBlock) sqlSelectQuery; - SQLTableSource fromSource = selectQueryBlock.getFrom(); - if (fromSource instanceof SQLJoinTableSource) { - SQLJoinTableSource fromJoinSource = (SQLJoinTableSource) fromSource; - System.out.println("SQLJoinTableSource:"); - System.out.println("all:" + fromJoinSource.toString()); - System.out.println("left:" + fromJoinSource.getLeft().toString() + ",class" + fromJoinSource.getLeft().getClass()); - System.out.println("right:" + fromJoinSource.getRight().toString() + ",class" + fromJoinSource.getRight().getClass()); - System.out.println("---------------------------"); - } - for (SQLSelectItem item : selectQueryBlock.getSelectList()) { - if (item.getExpr() != null) { - SQLExpr func = item.getExpr(); - if (func instanceof SQLAggregateExpr) { - System.out.println("SQLAggregateExpr:"); - SQLAggregateExpr agg = (SQLAggregateExpr) func; - System.out.println("MethodName:" + agg.getMethodName() + ",getArguments size =" + agg.getArguments().size() + ",Option:" + agg.getOption()); - System.out.println("---------------------------"); - } else if (func instanceof SQLMethodInvokeExpr) { - System.out.println("SQLMethodInvokeExpr:"); - SQLMethodInvokeExpr method = (SQLMethodInvokeExpr) func; - System.out.println("MethodName:" + method.getMethodName() + ",getArguments size =" + method.getParameters().size() + ",OWNER:" + method.getOwner()); - System.out.println("---------------------------"); - } else if (func instanceof SQLCastExpr) { - SQLCastExpr cast = (SQLCastExpr) func; - System.out.println("SQLCastExpr:"); - System.out.println("Expr:" + cast.getExpr().getClass() + ",getDataType:" + cast.getDataType()); - System.out.println("---------------------------"); - } else if (func instanceof SQLBinaryOpExpr) { - SQLBinaryOpExpr Op = (SQLBinaryOpExpr) func; - System.out.println("SQLBinaryOpExpr:"); - System.out.println("left:" + Op.getLeft().getClass()); - System.out.println("right:" + Op.getRight().getClass()); - System.out.println("operator:" + Op.getOperator().getClass()); - System.out.println("dbtype:" + Op.getDbType()); - System.out.println("---------------------------"); - } else if (func instanceof SQLUnaryExpr) { - SQLUnaryExpr Op = (SQLUnaryExpr) func; - System.out.println("SQLUnaryExpr:"); - System.out.println("EXPR:" + Op.getExpr().getClass()); - System.out.println("operator:" + Op.getOperator().getClass()); - System.out.println("---------------------------"); - } else if (func instanceof SQLBetweenExpr) { - SQLBetweenExpr between = (SQLBetweenExpr) func; - System.out.println("SQLBetweenExpr:"); - System.out.println("begin EXPR:" + between.getBeginExpr()); - System.out.println("end EXPR:" + between.getEndExpr()); - System.out.println("isnot :" + between.isNot()); - System.out.println("test :" + between.getTestExpr()); - System.out.println("---------------------------"); - } else if (func instanceof SQLInListExpr) { - SQLInListExpr in = (SQLInListExpr) func; - System.out.println("SQLInListExpr:"); - System.out.println("EXPR:" + in.getExpr()); - System.out.println("isnot :" + in.isNot()); - System.out.println("getTargetList size :" + in.getTargetList().size()); - System.out.println("---------------------------"); - } else if (func instanceof SQLNotExpr) { - SQLNotExpr not = (SQLNotExpr) func; - System.out.println("SQLNotExpr:"); - System.out.println("EXPR:" + not.getExpr()); - System.out.println("---------------------------"); - } else if (func instanceof MySqlExtractExpr) { - MySqlExtractExpr extract = (MySqlExtractExpr) func; - System.out.println("MySqlExtractExpr:"); - System.out.println("value:" + extract.getValue()); - System.out.println("unit:" + extract.getUnit()); - System.out.println("---------------------------"); - } else if (func instanceof SQLCaseExpr) { - SQLCaseExpr Case = (SQLCaseExpr) func; - System.out.println("SQLCaseExpr:"); - System.out.println("value:" + Case.getValueExpr()); - System.out.println("else:" + Case.getElseExpr()); - System.out.println("items size:" + Case.getItems().size()); - System.out.println("---------------------------"); - } else if (func instanceof SQLVariantRefExpr) { - SQLVariantRefExpr variant = (SQLVariantRefExpr) func; - System.out.println("SQLVariantRefExpr:"); - System.out.println("name:" + variant.getName()); - System.out.println("Global:" + variant.isGlobal()); - System.out.println("index:" + variant.getIndex()); - System.out.println("---------------------------"); - } - // SQLAllColumnExpr - else { - // MySqlOutputVisitor - System.out.println("item.getExpr(): :" + item.getExpr().getClass().toString() + "\n"); - } - } - } - // SQLBinaryOpExpr - // MySqlIntervalUnit - // SQLIntegerExpr - // SQLOrderBy - // SQLSelect - // SQLInSubQueryExpr - if (selectQueryBlock.getGroupBy() != null) { - SQLSelectGroupByClause groupBy = selectQueryBlock.getGroupBy(); - for (SQLExpr groupByItem : groupBy.getItems()) { - System.out.println("groupByItem:"); - System.out.println("class :" + groupByItem.getClass()); - System.out.println("---------------------------"); - } - - if (groupBy.getHaving() != null) { - SQLExpr having = groupBy.getHaving(); - System.out.println("having:"); - System.out.println("class :" + having.getClass()); - System.out.println("---------------------------"); - } - //with rollup... - } - if (selectQueryBlock.getOrderBy() != null) { - for (SQLSelectOrderByItem orderItem : selectQueryBlock.getOrderBy().getItems()) { - System.out.println("OrderBy:"); - System.out.println("class :" + orderItem.getExpr().getClass()); - System.out.println("---------------------------"); - } - } - if (selectQueryBlock.getWhere() != null) { - if(selectQueryBlock.getWhere() instanceof SQLBinaryOpExpr){ - SQLBinaryOpExpr where = (SQLBinaryOpExpr)(selectQueryBlock.getWhere()); - System.out.println("where right:"); - System.out.println("class :" + where.getRight().getClass()); - System.out.println("---------------------------"); - } - else{ - System.out.println("where:"); - System.out.println("class :" + selectQueryBlock.getWhere().getClass()); - System.out.println("---------------------------"); - } - } - } else if (sqlSelectQuery instanceof SQLUnionQuery) { - } - - } else if (statement instanceof MySqlShowColumnsStatement) { - MySqlShowColumnsStatement showColumnsStatement = (MySqlShowColumnsStatement) statement; - showColumnsStatement.setDatabase(null); - showColumnsStatement.toString(); - System.out.println("change to->" + showColumnsStatement.toString()); - } else if (statement instanceof MySqlShowIndexesStatement) { - MySqlShowIndexesStatement mySqlShowIndexesStatement = (MySqlShowIndexesStatement) statement; - mySqlShowIndexesStatement.setDatabase(null); - mySqlShowIndexesStatement.toString(); - System.out.println("change to 1->" + mySqlShowIndexesStatement.toString()); - System.out.println("change to 2->" + SQLUtils.toMySqlString(mySqlShowIndexesStatement)); - } else if (statement instanceof MySqlShowKeysStatement) { - MySqlShowKeysStatement mySqlShowKeysStatement = (MySqlShowKeysStatement) statement; - mySqlShowKeysStatement.setDatabase(null); - mySqlShowKeysStatement.toString(); - System.out.println("change to 1->" + mySqlShowKeysStatement.toString()); - System.out.println("change to 2->" + SQLUtils.toMySqlString(mySqlShowKeysStatement)); - } else if (statement instanceof SQLSetStatement) { - SQLSetStatement setStatement = (SQLSetStatement) statement; - for(SQLAssignItem assignItem:setStatement.getItems()){ - if(assignItem.getTarget() instanceof SQLVariantRefExpr){ - SQLVariantRefExpr target = (SQLVariantRefExpr)assignItem.getTarget(); - System.out.println("target is " + target + ", global is " + target.isGlobal() + ", session is " + target.isSession()); - }else if(assignItem.getTarget() instanceof SQLPropertyExpr){ - SQLPropertyExpr target = (SQLPropertyExpr)assignItem.getTarget(); - System.out.println("target is " + target.getName() + ", Owner is " + target.getOwner()); - } else if(assignItem.getTarget() instanceof SQLIdentifierExpr){ - SQLIdentifierExpr target = (SQLIdentifierExpr)assignItem.getTarget(); - System.out.println("target is " + target.getName()); - } else { - System.out.println("target is " + assignItem.getTarget() + ", class is " + assignItem.getTarget().getClass()); - } - if(assignItem.getValue() instanceof SQLIdentifierExpr ){ - SQLIdentifierExpr value = (SQLIdentifierExpr)assignItem.getValue(); - System.out.println("value is " + value.getName() + ", class is " + assignItem.getValue().getClass()); - } else if (assignItem.getValue() instanceof MySqlCharExpr) { - MySqlCharExpr value = (MySqlCharExpr) assignItem.getValue(); - System.out.println("value is " + value.getText() + ",charset is " + value.getCharset() + ",collate is " + value.getCollate() + ", class is " + assignItem.getValue().getClass()); - } else if (assignItem.getValue() instanceof SQLCharExpr) { - SQLCharExpr value = (SQLCharExpr) assignItem.getValue(); - System.out.println("value is " + value.getText() + ", class is " + assignItem.getValue().getClass()); - } else if (assignItem.getValue() instanceof SQLDefaultExpr) { - SQLDefaultExpr value = (SQLDefaultExpr) assignItem.getValue(); - System.out.println("value is " + value.toString() + ", class is " + assignItem.getValue().getClass()); - }else { - System.out.println("value is " + assignItem.getValue() + ", class is " + assignItem.getValue().getClass()); - } - } -// } else if (statement instanceof MySqlSetNamesStatement) { -// MySqlSetNamesStatement setStatement = (MySqlSetNamesStatement) statement; -// System.out.println("charset ="+setStatement.getCharSet()+ ",Collate ="+setStatement.getCollate()+",default ="+setStatement.isDefault()); -// } else if (statement instanceof MySqlSetCharSetStatement) { -// MySqlSetCharSetStatement setStatement = (MySqlSetCharSetStatement) statement; -// System.out.println("charset ="+setStatement.getCharSet()+ ",Collate ="+setStatement.getCollate()+",default ="+setStatement.isDefault()); - } else if (statement instanceof MySqlSetTransactionStatement) { - MySqlSetTransactionStatement setStatement = (MySqlSetTransactionStatement) statement; - System.out.println("global"+setStatement.getGlobal()+",IsolationLevel="+ setStatement.getIsolationLevel()+",access mode"+setStatement.getAccessModel()); - } else { - System.out.println("statement:" + statement + "," + statement.getClass().toString()); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) { + System.out.println(rs.getInt(1)); } + rs = stmt.executeQuery(); + while (rs.next()) { + System.out.println(rs.getInt(1)); + } + + rs.close(); + stmt.close(); + conn.close(); + } } diff --git a/version.txt b/version.txt index 0f317e485..3dcf5d917 100644 --- a/version.txt +++ b/version.txt @@ -1,10 +1,5 @@ -<<<<<<< HEAD GitVersion xxxxxx BuildTime yyyyMMddHHmmss -======= -GitVersion 1d36a5b3fc33294e3318343411bb9d2517733a1d -BuildTime 20200724174006 ->>>>>>> #1880 fix packetId usage in show tables MavenVersion 9.9.9.9 GitUrl https://github.com/actiontech/dble WebSite https://opensource.actionsky.com/