From ffddd072e5604f5f9afd9334b53d12b4a53fa972 Mon Sep 17 00:00:00 2001 From: yanhuqing Date: Fri, 22 Sep 2017 17:16:24 +0800 Subject: [PATCH] set stament #78 --- pom.xml | 1 - .../dble/backend/BackendConnection.java | 2 +- .../backend/mysql/nio/MySQLConnection.java | 199 ++- .../FetchStoreNodeOfChildTableHandler.java | 6 +- .../mysql/nio/handler/LockTablesHandler.java | 2 +- .../nio/handler/MultiNodeDdlHandler.java | 20 +- .../mysql/nio/handler/MultiNodeHandler.java | 18 +- .../nio/handler/MultiNodeQueryHandler.java | 8 +- .../mysql/nio/handler/ResetConnHandler.java | 80 ++ .../mysql/nio/handler/SingleNodeHandler.java | 2 +- .../nio/handler/UnLockTablesHandler.java | 2 +- .../handler/query/impl/BaseSelectHandler.java | 2 +- .../com/actiontech/dble/config/Versions.java | 2 +- .../dble/manager/response/ShowBackend.java | 14 +- .../dble/manager/response/ShowConnection.java | 29 +- .../manager/response/ShowDirectMemory.java | 6 +- .../dble/net/AbstractConnection.java | 89 +- .../actiontech/dble/net/mysql/OkPacket.java | 3 +- .../dble/net/mysql/ResetConnectionPacket.java | 20 + .../handler/FetchMySQLSequnceHandler.java | 2 +- .../dble/server/ServerConnection.java | 106 +- .../dble/server/handler/SetCallBack.java | 28 + .../dble/server/handler/SetHandler.java | 867 +++++++++--- .../dble/server/parser/ServerParseSet.java | 1195 ----------------- .../com/actiontech/dble/sqlengine/SQLJob.java | 11 +- .../actiontech/dble/sqlengine/SetTestJob.java | 141 ++ .../actiontech/dble/util/SetIgnoreUtil.java | 55 - .../dble/parser/ServerParseTest.java | 6 +- .../dble/parser/ServerParserTest.java | 223 +-- .../dble/parser/ServerParserTestPerf.java | 39 - .../server/handler/ServerHandlerTest.java | 10 - .../dble/server/handler/SetHandlerTest.java | 26 + src/test/java/demo/test/Testparser.java | 85 +- version.txt | 4 +- 34 files changed, 1416 insertions(+), 1887 deletions(-) create mode 100644 src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ResetConnHandler.java create mode 100644 src/main/java/com/actiontech/dble/net/mysql/ResetConnectionPacket.java create mode 100644 src/main/java/com/actiontech/dble/server/handler/SetCallBack.java delete mode 100644 src/main/java/com/actiontech/dble/server/parser/ServerParseSet.java create mode 100644 src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java delete mode 100644 src/main/java/com/actiontech/dble/util/SetIgnoreUtil.java delete mode 100644 src/test/java/com/actiontech/dble/parser/ServerParserTestPerf.java delete mode 100644 src/test/java/com/actiontech/dble/server/handler/ServerHandlerTest.java create mode 100644 src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java diff --git a/pom.xml b/pom.xml index 5fdb9ba34d..d84f18646e 100644 --- a/pom.xml +++ b/pom.xml @@ -414,7 +414,6 @@ maven-source-plugin 2.1.2 - ${app.encoding} true diff --git a/src/main/java/com/actiontech/dble/backend/BackendConnection.java b/src/main/java/com/actiontech/dble/backend/BackendConnection.java index 8384ee98f7..49301c4f5e 100644 --- a/src/main/java/com/actiontech/dble/backend/BackendConnection.java +++ b/src/main/java/com/actiontech/dble/backend/BackendConnection.java @@ -49,7 +49,7 @@ public interface BackendConnection extends ClosableConnection { void execute(RouteResultsetNode node, ServerConnection source, boolean autocommit); - boolean syncAndExcute(); + boolean syncAndExecute(); void rollback(); diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/MySQLConnection.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/MySQLConnection.java index 06d34b93d0..867a01bf48 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/MySQLConnection.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/MySQLConnection.java @@ -15,10 +15,12 @@ import com.actiontech.dble.net.BackendAIOConnection; import com.actiontech.dble.net.mysql.*; 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.ServerConnection; import com.actiontech.dble.server.SystemVariables; import com.actiontech.dble.server.parser.ServerParse; +import com.actiontech.dble.util.StringUtil; import com.actiontech.dble.util.TimeUtil; import com.actiontech.dble.util.exception.UnknownTxIsolationException; import org.slf4j.Logger; @@ -27,6 +29,7 @@ import java.io.UnsupportedEncodingException; import java.nio.channels.NetworkChannel; import java.security.NoSuchAlgorithmException; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -44,7 +47,7 @@ public class MySQLConnection extends BackendAIOConnection { private volatile boolean isDDL = false; private volatile boolean isRunning; private volatile StatusSync statusSync; - private volatile boolean metaDataSyned = true; + private volatile boolean metaDataSynced = true; private volatile TxState xaStatus = TxState.TX_INITIALIZE_STATE; private volatile int txIsolation; private volatile boolean autocommit; @@ -137,8 +140,18 @@ public MySQLConnection(NetworkChannel channel, boolean fromSlaveDB) { * it need to sync the status firstly for new idle connection*/ this.txIsolation = -1; this.complexQuery = false; + this.usrVariables = new LinkedHashMap<>(); + this.sysVariables = new LinkedHashMap<>(); } + public void resetContextStatus() { + this.txIsolation = -1; + this.autocommit = true; + //TODO:CHECK + this.setCharacterSet(SystemVariables.getDefaultValue("character_set_server")); + this.usrVariables.clear(); + this.sysVariables.clear(); + } public void setRunning(boolean running) { isRunning = running; } @@ -211,7 +224,7 @@ public void setThreadId(long threadId) { this.threadId = threadId; } - public void setAuthenticated(boolean authenticated) { + void setAuthenticated(boolean authenticated) { isAuthenticated = authenticated; } @@ -219,7 +232,7 @@ public String getPassword() { return password; } - public void authenticate() { + void authenticate() { AuthPacket packet = new AuthPacket(); packet.setPacketId(1); packet.setClientFlags(clientFlags); @@ -254,7 +267,7 @@ public boolean isClosedOrQuit() { return isClosed() || isQuit.get(); } - protected void sendQueryCmd(String query, CharsetNames clientCharset) { + public void sendQueryCmd(String query, CharsetNames clientCharset) { CommandPacket packet = new CommandPacket(); packet.setPacketId(0); packet.setCommand(MySQLPacket.COM_QUERY); @@ -316,7 +329,7 @@ public void execute(RouteResultsetNode rrn, ServerConnection sc, if (!sc.isAutocommit() && !sc.isTxstart() && modifiedSQLExecuted) { sc.setTxstart(true); } - synAndDoExecute(xaTxId, rrn, sc.getCharset(), sc.getTxIsolation(), isAutoCommit); + synAndDoExecute(xaTxId, rrn, sc.getCharset(), sc.getTxIsolation(), isAutoCommit, sc.getUsrVariables(), sc.getSysVariables()); } public String getConnXID(NonBlockingSession session) { @@ -329,23 +342,26 @@ public String getConnXID(NonBlockingSession session) { } private void synAndDoExecute(String xaTxID, RouteResultsetNode rrn, - CharsetNames clientCharset, int clientTxIsoLation, - boolean expectAutocommit) { + CharsetNames clientCharset, int clientTxIsolation, + boolean expectAutocommit, Map usrVariables, Map sysVariables) { String xaCmd = null; - boolean conAutoComit = this.autocommit; + boolean conAutoCommit = this.autocommit; String conSchema = this.schema; int xaSyn = 0; if (!expectAutocommit && xaTxID != null && xaStatus == TxState.TX_INITIALIZE_STATE) { - // clientTxIsoLation = Isolations.SERIALIZABLE; + // clientTxIsolation = Isolation.SERIALIZABLE;TODO:NEEDED? xaCmd = "XA START " + xaTxID + ';'; this.xaStatus = TxState.TX_STARTED_STATE; xaSyn = 1; } + Set toResetSys = new HashSet(); + String setSql = getSetSQL(usrVariables, sysVariables, toResetSys); + int setSqlFlag = setSql == null ? 0 : 1; int schemaSyn = conSchema.equals(oldSchema) ? 0 : 1; int charsetSyn = (charsetName.equals(clientCharset)) ? 0 : 1; - int txIsoLationSyn = (txIsolation == clientTxIsoLation) ? 0 : 1; - int autoCommitSyn = (conAutoComit == expectAutocommit) ? 0 : 1; - int synCount = schemaSyn + charsetSyn + txIsoLationSyn + autoCommitSyn + xaSyn; + int txIsolationSyn = (txIsolation == clientTxIsolation) ? 0 : 1; + int autoCommitSyn = (conAutoCommit == expectAutocommit) ? 0 : 1; + int synCount = schemaSyn + charsetSyn + txIsolationSyn + autoCommitSyn + xaSyn + setSqlFlag; if (synCount == 0) { // not need syn connection sendQueryCmd(rrn.getStatement(), clientCharset); @@ -355,18 +371,19 @@ private void synAndDoExecute(String xaTxID, RouteResultsetNode rrn, StringBuilder sb = new StringBuilder(); if (schemaSyn == 1) { schemaCmd = getChangeSchemaCommand(conSchema); - // getChangeSchemaCommand(sb, conSchema); } - if (charsetSyn == 1) { getCharsetCommand(sb, clientCharset); } - if (txIsoLationSyn == 1) { - getTxIsolationCommand(sb, clientTxIsoLation); + if (txIsolationSyn == 1) { + getTxIsolationCommand(sb, clientTxIsolation); } if (autoCommitSyn == 1) { getAutocommitCommand(sb, expectAutocommit); } + if (setSqlFlag == 1) { + sb.append(setSql); + } if (xaCmd != null) { sb.append(xaCmd); } @@ -375,22 +392,73 @@ private void synAndDoExecute(String xaTxID, RouteResultsetNode rrn, " commands " + sb.toString() + "schema change:" + (schemaCmd != null) + " con:" + this); } - metaDataSyned = false; + metaDataSynced = false; statusSync = new StatusSync(conSchema, - clientCharset, clientTxIsoLation, expectAutocommit, - synCount); + clientCharset, clientTxIsolation, expectAutocommit, + synCount, usrVariables, sysVariables, toResetSys); // syn schema if (schemaCmd != null) { schemaCmd.write(this); } // and our query sql to multi command at last - sb.append(rrn.getStatement() + ";"); + sb.append(rrn.getStatement()).append(";"); // syn and execute others this.sendQueryCmd(sb.toString(), clientCharset); // waiting syn result... } + private String getSetSQL(Map usrVars, Map sysVars, Set toResetSys) { + //new final var + List> setVars = new ArrayList<>(); + Map tmpSysVars = new HashMap<>(); + //tmp add all backend sysVariables + tmpSysVars.putAll(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())); + } + } + } + //tmp now = backend -(backend &&frontend) + for (Map.Entry entry : tmpSysVars.entrySet()) { + String value = SystemVariables.getDefaultValue(entry.getKey()); + 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(); + } private static CommandPacket getChangeSchemaCommand(String schema) { CommandPacket cmd = new CommandPacket(); cmd.setPacketId(0); @@ -402,14 +470,11 @@ private static CommandPacket getChangeSchemaCommand(String schema) { /** * by wuzh ,execute a query and ignore transaction settings for performance * - * @param query - * @throws UnsupportedEncodingException */ - public void query(String query) throws UnsupportedEncodingException { + public void query(String query) { RouteResultsetNode rrn = new RouteResultsetNode("default", ServerParse.SELECT, query); - - synAndDoExecute(null, rrn, this.charsetName, this.txIsolation, true); + synAndDoExecute(null, rrn, this.charsetName, this.txIsolation, true, this.getUsrVariables(), this.getSysVariables()); } @@ -432,7 +497,7 @@ public void quit() { } - public boolean isComplexQuery() { + boolean isComplexQuery() { return complexQuery; } @@ -472,18 +537,23 @@ public void rollback() { } public void release() { - if (!metaDataSyned) { // indicate connection not normalfinished + if (!metaDataSynced) { // indicate connection not normal finished // ,and // we can't know it's syn status ,so // close // it LOGGER.warn("can't sure connection syn result,so close it " + this); this.respHandler = null; - this.close("syn status unkown "); + this.close("syn status unknown "); + return; + } + if (this.usrVariables.size() > 0) { + this.respHandler = null; + this.close("close for clear usrVariables"); return; } complexQuery = false; - metaDataSyned = true; + metaDataSynced = true; attachment = null; statusSync = null; modifiedSQLExecuted = false; @@ -541,12 +611,53 @@ public void setBorrowed(boolean borrowed) { @Override public String toString() { - return "MySQLConnection [id=" + id + ", lastTime=" + lastTime + ", user=" + user + ", schema=" + schema + - ", old shema=" + oldSchema + ", borrowed=" + borrowed + ", fromSlaveDB=" + fromSlaveDB + ", threadId=" + - threadId + "," + charsetName.toString() + ", txIsolation=" + txIsolation + ", autocommit=" + autocommit + - ", attachment=" + attachment + ", respHandler=" + respHandler + ", host=" + host + ", port=" + port + - ", statusSync=" + statusSync + ", writeQueue=" + this.getWriteQueue().size() + - ", modifiedSQLExecuted=" + modifiedSQLExecuted + "]"; + StringBuilder result = new StringBuilder(); + result.append("MySQLConnection [id="); + result.append(id); + result.append(", lastTime="); + result.append(lastTime); + result.append(", user="); + result.append(user); + result.append(", schema="); + result.append(schema); + result.append(", old schema="); + result.append(oldSchema); + result.append(", borrowed="); + result.append(borrowed); + result.append(", fromSlaveDB="); + result.append(fromSlaveDB); + result.append(", threadId="); + result.append(threadId); + result.append(","); + result.append(charsetName.toString()); + result.append(", txIsolation="); + result.append(txIsolation); + result.append(", autocommit="); + result.append(autocommit); + result.append(", attachment="); + result.append(attachment); + result.append(", respHandler="); + result.append(respHandler); + result.append(", host="); + result.append(host); + result.append(", port="); + result.append(port); + result.append(", statusSync="); + result.append(statusSync); + result.append(", writeQueue="); + result.append(this.getWriteQueue().size()); + result.append(", modifiedSQLExecuted="); + result.append(modifiedSQLExecuted); + if (sysVariables.size() > 0) { + result.append(", "); + result.append(getStringOfSysVariables()); + } + if (usrVariables.size() > 0) { + result.append(", "); + result.append(getStringOfUsrVariables()); + } + result.append("]"); + return result.toString(); } public String compactInfo() { @@ -572,7 +683,7 @@ public int getTxIsolation() { * @return if synchronization finished and execute-sql has already been sent * before */ - public boolean syncAndExcute() { + public boolean syncAndExecute() { StatusSync sync = this.statusSync; if (sync == null) { return true; @@ -592,23 +703,30 @@ private static class StatusSync { private final Integer txtIsolation; private final Boolean autocommit; private final AtomicInteger synCmdCount; + private final Map usrVariables = new LinkedHashMap<>(); + private final Map sysVariables = new LinkedHashMap<>(); StatusSync(String schema, CharsetNames clientCharset, Integer txtIsolation, Boolean autocommit, - int synCount) { + int synCount, Map usrVariables, Map sysVariables, Set toResetSys) { super(); this.schema = schema; this.clientCharset = clientCharset; this.txtIsolation = txtIsolation; this.autocommit = autocommit; this.synCmdCount = new AtomicInteger(synCount); + this.usrVariables.putAll(usrVariables); + this.sysVariables.putAll(sysVariables); + for (String sysVariable : toResetSys) { + this.sysVariables.remove(sysVariable); + } } - public boolean synAndExecuted(MySQLConnection conn) { + boolean synAndExecuted(MySQLConnection conn) { int remains = synCmdCount.decrementAndGet(); if (remains == 0) { // syn command finished this.updateConnectionInfo(conn); - conn.metaDataSyned = true; + conn.metaDataSynced = true; return false; } else if (remains < 0) { return true; @@ -630,7 +748,8 @@ private void updateConnectionInfo(MySQLConnection conn) { if (autocommit != null) { conn.autocommit = autocommit; } + conn.sysVariables = sysVariables; + conn.usrVariables = usrVariables; } - } } diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/FetchStoreNodeOfChildTableHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/FetchStoreNodeOfChildTableHandler.java index 187d47f07b..fa044ce415 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/FetchStoreNodeOfChildTableHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/FetchStoreNodeOfChildTableHandler.java @@ -29,7 +29,7 @@ /** * company where id=(select company_id from customer where id=3); the one which - * return data (id) is the datanode to store child table's records + * return data (id) is the data node to store child table's records * * @author wuzhih, huqing.yan */ @@ -73,7 +73,7 @@ public String execute(String schema, ArrayList dataNodes) { PhysicalDBNode mysqlDN = conf.getDataNodes().get(dn); try { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("execute in datanode " + dn); + LOGGER.debug("execute in data_node " + dn); } RouteResultsetNode node = new RouteResultsetNode(dn, ServerParse.SELECT, sql); node.setRunOnSlave(false); // get child node from master @@ -161,7 +161,7 @@ public void okResponse(byte[] ok, BackendConnection conn) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("okResponse " + conn); } - boolean executeResponse = conn.syncAndExcute(); + boolean executeResponse = conn.syncAndExecute(); if (executeResponse) { finished.incrementAndGet(); if (canReleaseConn()) { diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/LockTablesHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/LockTablesHandler.java index 2f8b64d28c..61444e3433 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/LockTablesHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/LockTablesHandler.java @@ -73,7 +73,7 @@ public void connectionAcquired(BackendConnection conn) { @Override public void okResponse(byte[] data, BackendConnection conn) { - boolean executeResponse = conn.syncAndExcute(); + boolean executeResponse = conn.syncAndExecute(); if (executeResponse) { if (clearIfSessionClosed(session)) { return; diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeDdlHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeDdlHandler.java index fe73f558ac..536f9acbb9 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeDdlHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeDdlHandler.java @@ -56,7 +56,7 @@ public MultiNodeDdlHandler(int sqlType, RouteResultset rrs, NonBlockingSession s } if (LOGGER.isDebugEnabled()) { - LOGGER.debug("execute mutinode query " + rrs.getStatement()); + LOGGER.debug("execute multiNode query " + rrs.getStatement()); } this.rrs = RouteResultCopy.rrCopy(rrs, ServerParse.SELECT, STMT); @@ -138,7 +138,7 @@ public void connectionClose(BackendConnection conn, String reason) { errConnection = new ArrayList<>(); } errConnection.add(conn); - if (!conn.syncAndExcute()) { + if (!conn.syncAndExecute()) { return; } if (--nodeCount <= 0) { @@ -167,7 +167,7 @@ public void connectionError(Throwable e, BackendConnection conn) { errConnection = new ArrayList<>(); } errConnection.add(conn); - if (!conn.syncAndExcute()) { + if (!conn.syncAndExecute()) { return; } if (--nodeCount <= 0) { @@ -196,7 +196,7 @@ public void errorResponse(byte[] data, BackendConnection conn) { try { if (!isFail()) setFail(err.toString()); - if (!conn.syncAndExcute()) { + if (!conn.syncAndExecute()) { return; } if (--nodeCount > 0) @@ -210,7 +210,7 @@ public void errorResponse(byte[] data, BackendConnection conn) { /* arriving here is impossible */ @Override public void okResponse(byte[] data, BackendConnection conn) { - if (!conn.syncAndExcute()) { + if (!conn.syncAndExecute()) { LOGGER.debug("MultiNodeDdlHandler should not arrive here(okResponse) !"); } } @@ -218,10 +218,10 @@ public void okResponse(byte[] data, BackendConnection conn) { @Override public void rowEofResponse(final byte[] eof, boolean isLeft, BackendConnection conn) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("on row end reseponse " + conn); + LOGGER.debug("on row end response " + conn); } - if (errorRepsponsed.get()) { + if (errorResponsed.get()) { return; } @@ -262,14 +262,14 @@ public void rowEofResponse(final byte[] eof, boolean isLeft, BackendConnection c } @Override - public void fieldEofResponse(byte[] header, List fields, List fieldPacketsnull, byte[] eof, + public void fieldEofResponse(byte[] header, List fields, List fieldPacketsNull, byte[] eof, boolean isLeft, BackendConnection conn) { } @Override - public boolean rowResponse(final byte[] row, RowDataPacket rowPacketnull, boolean isLeft, BackendConnection conn) { + public boolean rowResponse(final byte[] row, RowDataPacket rowPacketNull, boolean isLeft, BackendConnection conn) { /* It is impossible arriving here, because we set limit to 0 */ - return errorRepsponsed.get(); + return errorResponsed.get(); } @Override diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeHandler.java index f3386a1b5c..687c6abe93 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeHandler.java @@ -26,7 +26,7 @@ public abstract class MultiNodeHandler implements ResponseHandler { private AtomicBoolean isFailed = new AtomicBoolean(false); protected volatile String error; protected byte packetId; - protected final AtomicBoolean errorRepsponsed = new AtomicBoolean(false); + protected final AtomicBoolean errorResponsed = new AtomicBoolean(false); public MultiNodeHandler(NonBlockingSession session) { if (session == null) { @@ -48,7 +48,7 @@ public boolean isFail() { protected boolean canClose(BackendConnection conn, boolean tryErrorFinish) { - // realse this connection if safe + // release this connection if safe session.releaseConnectionIfSafe(conn, false); boolean allFinished = false; if (tryErrorFinish) { @@ -69,9 +69,9 @@ public void errorResponse(byte[] data, BackendConnection conn) { session.releaseConnectionIfSafe(conn, false); ErrorPacket err = new ErrorPacket(); err.read(data); - String errmsg = new String(err.getMessage()); - this.setFail(errmsg); - LOGGER.warn("error response from " + conn + " err " + errmsg + " code:" + err.getErrno()); + String errMsg = new String(err.getMessage()); + this.setFail(errMsg); + LOGGER.warn("error response from " + conn + " err " + errMsg + " code:" + err.getErrno()); this.tryErrorFinished(this.decrementCountBy(1)); } @@ -109,7 +109,7 @@ protected void reset(int initCount) { packetId = 0; } - protected ErrorPacket createErrPkg(String errmgs) { + protected ErrorPacket createErrPkg(String errMsg) { ErrorPacket err = new ErrorPacket(); lock.lock(); try { @@ -118,13 +118,13 @@ protected ErrorPacket createErrPkg(String errmgs) { lock.unlock(); } err.setErrno(ErrorCode.ER_UNKNOWN_ERROR); - err.setMessage(StringUtil.encode(errmgs, session.getSource().getCharset().getResults())); + err.setMessage(StringUtil.encode(errMsg, session.getSource().getCharset().getResults())); return err; } protected void tryErrorFinished(boolean allEnd) { if (allEnd && !session.closed()) { - if (errorRepsponsed.compareAndSet(false, true)) { + if (errorResponsed.compareAndSet(false, true)) { createErrPkg(this.error).write(session.getSource()); } // clear session resources,release all @@ -135,7 +135,7 @@ protected void tryErrorFinished(boolean allEnd) { session.closeAndClearResources(error); } else { session.getSource().setTxInterrupt(this.error); - // clear resouces + // clear resources clearResources(); } } diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeQueryHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeQueryHandler.java index 4464dd77a5..3f6fdc4df4 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeQueryHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/MultiNodeQueryHandler.java @@ -263,7 +263,7 @@ public void errorResponse(byte[] data, BackendConnection conn) { @Override public void okResponse(byte[] data, BackendConnection conn) { this.netOutBytes += data.length; - boolean executeResponse = conn.syncAndExcute(); + boolean executeResponse = conn.syncAndExecute(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("received ok response ,executeResponse:" + executeResponse + " from " + conn); } @@ -321,7 +321,7 @@ public void rowEofResponse(final byte[] eof, boolean isLeft, BackendConnection c this.netOutBytes += eof.length; - if (errorRepsponsed.get()) { + if (errorResponsed.get()) { return; } @@ -645,7 +645,7 @@ private void mergeFieldEof(List fields, byte[] eof) throws IOException { } public void handleDataProcessException(Exception e) { - if (!errorRepsponsed.get()) { + if (!errorResponsed.get()) { this.error = e.toString(); LOGGER.warn("caught exception ", e); setFail(e.toString()); @@ -656,7 +656,7 @@ public void handleDataProcessException(Exception e) { @Override public boolean rowResponse(final byte[] row, RowDataPacket rowPacketnull, boolean isLeft, BackendConnection conn) { - if (errorRepsponsed.get()) { + if (errorResponsed.get()) { // the connection has been closed or set to "txInterrupt" properly //in tryErrorFinished() method! If we close it here, it can // lead to tx error such as blocking rollback tx for ever. diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ResetConnHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ResetConnHandler.java new file mode 100644 index 0000000000..2f39378bf6 --- /dev/null +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ResetConnHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016-2017 ActionTech. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ + +package com.actiontech.dble.backend.mysql.nio.handler; + +import com.actiontech.dble.backend.BackendConnection; +import com.actiontech.dble.backend.mysql.nio.MySQLConnection; +import com.actiontech.dble.net.mysql.ErrorPacket; +import com.actiontech.dble.net.mysql.FieldPacket; +import com.actiontech.dble.net.mysql.RowDataPacket; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class ResetConnHandler implements ResponseHandler { + public static final Logger LOGGER = LoggerFactory.getLogger(ResetConnHandler.class); + @Override + public void connectionError(Throwable e, BackendConnection conn) { + String msg = e.getMessage() == null ? e.toString() : e.getMessage(); + LOGGER.warn(msg); + } + + + @Override + public void errorResponse(byte[] err, BackendConnection conn) { + ErrorPacket errPg = new ErrorPacket(); + errPg.read(err); + conn.close(new String(errPg.getMessage())); + } + + @Override + public void okResponse(byte[] ok, BackendConnection conn) { + MySQLConnection mysqlConn = (MySQLConnection) conn; + mysqlConn.resetContextStatus(); + conn.release(); + } + + @Override + public void connectionAcquired(BackendConnection conn) { + //not happen + } + @Override + public void connectionClose(BackendConnection conn, String reason) { + LOGGER.warn(reason); + } + @Override + public void fieldEofResponse(byte[] header, List fields, List fieldPackets, byte[] eof, boolean isLeft, BackendConnection conn) { + //not happen + } + + @Override + public boolean rowResponse(byte[] rownull, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) { + //not happen + return false; + } + + @Override + public void rowEofResponse(byte[] eof, boolean isLeft, BackendConnection conn) { + //not happen + } + + @Override + public void relayPacketResponse(byte[] relayPacket, BackendConnection conn) { + //not happen + } + + @Override + public void endPacketResponse(byte[] endPacket, BackendConnection conn) { + //not happen + } + + @Override + public void writeQueueAvailable() { + //not happen + } + +} diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/SingleNodeHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/SingleNodeHandler.java index d2a5eec106..eb0d5c2e97 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/SingleNodeHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/SingleNodeHandler.java @@ -176,7 +176,7 @@ public void okResponse(byte[] data, BackendConnection conn) { // this.netOutBytes += data.length; - boolean executeResponse = conn.syncAndExcute(); + boolean executeResponse = conn.syncAndExecute(); if (executeResponse) { session.handleSpecial(rrs, session.getSource().getSchema(), true); ServerConnection source = session.getSource(); diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/UnLockTablesHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/UnLockTablesHandler.java index 395d49c1de..a11e0cf762 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/UnLockTablesHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/UnLockTablesHandler.java @@ -84,7 +84,7 @@ public void errorResponse(byte[] err, BackendConnection conn) { @Override public void okResponse(byte[] data, BackendConnection conn) { - boolean executeResponse = conn.syncAndExcute(); + boolean executeResponse = conn.syncAndExecute(); if (executeResponse) { boolean isEndPack = decrementCountBy(1); session.releaseConnection(conn); diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/query/impl/BaseSelectHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/query/impl/BaseSelectHandler.java index f910b0eb17..c6f81522b3 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/query/impl/BaseSelectHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/query/impl/BaseSelectHandler.java @@ -81,7 +81,7 @@ public RouteResultsetNode getRrss() { @Override public void okResponse(byte[] ok, BackendConnection conn) { - conn.syncAndExcute(); + conn.syncAndExecute(); } @Override diff --git a/src/main/java/com/actiontech/dble/config/Versions.java b/src/main/java/com/actiontech/dble/config/Versions.java index 4d278a0ad1..97f615e95e 100644 --- a/src/main/java/com/actiontech/dble/config/Versions.java +++ b/src/main/java/com/actiontech/dble/config/Versions.java @@ -12,7 +12,7 @@ public abstract class Versions { public static final byte PROTOCOL_VERSION = 10; - private static byte[] serverVersion = "5.6.29-dble-2.17.08.0-dev-20170904220535".getBytes(); + private static byte[] serverVersion = "5.6.29-dble-2.17.08.0-20170922131413".getBytes(); public static final byte[] VERSION_COMMENT = "dble Server (ActionTech)".getBytes(); public static final String ANNOTATION_NAME = "dble:"; public static final String ROOT_PREFIX = "dble"; diff --git a/src/main/java/com/actiontech/dble/manager/response/ShowBackend.java b/src/main/java/com/actiontech/dble/manager/response/ShowBackend.java index e69a82caa6..31d84b4433 100644 --- a/src/main/java/com/actiontech/dble/manager/response/ShowBackend.java +++ b/src/main/java/com/actiontech/dble/manager/response/ShowBackend.java @@ -32,7 +32,7 @@ public final class ShowBackend { private ShowBackend() { } - private static final int FIELD_COUNT = 18; + private static final int FIELD_COUNT = 20; private static final ResultSetHeaderPacket HEADER = PacketUtil.getHeader(FIELD_COUNT); private static final FieldPacket[] FIELDS = new FieldPacket[FIELD_COUNT]; private static final EOFPacket EOF = new EOFPacket(); @@ -41,8 +41,7 @@ private ShowBackend() { int i = 0; byte packetId = 0; HEADER.setPacketId(++packetId); - FIELDS[i] = PacketUtil.getField("processor", - Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i] = PacketUtil.getField("processor", Fields.FIELD_TYPE_VAR_STRING); FIELDS[i++].setPacketId(++packetId); FIELDS[i] = PacketUtil.getField("ID", Fields.FIELD_TYPE_LONG); FIELDS[i++].setPacketId(++packetId); @@ -76,10 +75,15 @@ private ShowBackend() { FIELDS[i++].setPacketId(++packetId); FIELDS[i] = PacketUtil.getField("CHARACTER_SET_RESULTS", Fields.FIELD_TYPE_VAR_STRING); FIELDS[i++].setPacketId(++packetId); - FIELDS[i] = PacketUtil.getField("TXLEVEL", Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i] = PacketUtil.getField("TX_ISOLATION_LEVEL", Fields.FIELD_TYPE_VAR_STRING); FIELDS[i++].setPacketId(++packetId); FIELDS[i] = PacketUtil.getField("AUTOCOMMIT", Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i++].setPacketId(++packetId); + FIELDS[i] = PacketUtil.getField("SYS_VARIABLES", Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i++].setPacketId(++packetId); + FIELDS[i] = PacketUtil.getField("USER_VARIABLES", Fields.FIELD_TYPE_VAR_STRING); FIELDS[i].setPacketId(++packetId); + EOF.setPacketId(++packetId); } @@ -132,6 +136,8 @@ private static RowDataPacket getRow(BackendConnection c, String charset) { row.add(conn.getCharset().getResults().getBytes()); row.add((conn.getTxIsolation() + "").getBytes()); row.add((conn.isAutocommit() + "").getBytes()); + row.add(StringUtil.encode(conn.getStringOfSysVariables(), charset)); + row.add(StringUtil.encode(conn.getStringOfUsrVariables(), charset)); return row; } } diff --git a/src/main/java/com/actiontech/dble/manager/response/ShowConnection.java b/src/main/java/com/actiontech/dble/manager/response/ShowConnection.java index d00451bdbe..6e56976e86 100644 --- a/src/main/java/com/actiontech/dble/manager/response/ShowConnection.java +++ b/src/main/java/com/actiontech/dble/manager/response/ShowConnection.java @@ -33,7 +33,7 @@ public final class ShowConnection { private ShowConnection() { } - private static final int FIELD_COUNT = 17; + private static final int FIELD_COUNT = 19; private static final ResultSetHeaderPacket HEADER = PacketUtil.getHeader(FIELD_COUNT); private static final FieldPacket[] FIELDS = new FieldPacket[FIELD_COUNT]; private static final EOFPacket EOF = new EOFPacket(); @@ -80,8 +80,7 @@ private ShowConnection() { FIELDS[i] = PacketUtil.getField("NET_OUT", Fields.FIELD_TYPE_LONGLONG); FIELDS[i++].setPacketId(++packetId); - FIELDS[i] = PacketUtil.getField("ALIVE_TIME(S)", - Fields.FIELD_TYPE_LONGLONG); + FIELDS[i] = PacketUtil.getField("ALIVE_TIME(S)", Fields.FIELD_TYPE_LONGLONG); FIELDS[i++].setPacketId(++packetId); FIELDS[i] = PacketUtil.getField("RECV_BUFFER", Fields.FIELD_TYPE_LONG); @@ -90,11 +89,16 @@ private ShowConnection() { FIELDS[i] = PacketUtil.getField("SEND_QUEUE", Fields.FIELD_TYPE_LONG); FIELDS[i++].setPacketId(++packetId); - FIELDS[i] = PacketUtil.getField("TXLEVEL", Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i] = PacketUtil.getField("TX_ISOLATION_LEVEL", Fields.FIELD_TYPE_VAR_STRING); FIELDS[i++].setPacketId(++packetId); - FIELDS[i] = PacketUtil.getField("AUTOCOMMIT", - Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i] = PacketUtil.getField("AUTOCOMMIT", Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i++].setPacketId(++packetId); + + FIELDS[i] = PacketUtil.getField("SYS_VARIABLES", Fields.FIELD_TYPE_VAR_STRING); + FIELDS[i++].setPacketId(++packetId); + + FIELDS[i] = PacketUtil.getField("USER_VARIABLES", Fields.FIELD_TYPE_VAR_STRING); FIELDS[i].setPacketId(++packetId); EOF.setPacketId(++packetId); @@ -156,15 +160,16 @@ private static RowDataPacket getRow(FrontendConnection c, String charset) { row.add(IntegerUtil.toBytes(c.getWriteQueue().size())); String txLevel = ""; - String txAutommit = ""; + String autocommit = ""; if (c instanceof ServerConnection) { - ServerConnection mysqlC = (ServerConnection) c; - txLevel = mysqlC.getTxIsolation() + ""; - txAutommit = mysqlC.isAutocommit() + ""; + ServerConnection serverConn = (ServerConnection) c; + txLevel = serverConn.getTxIsolation() + ""; + autocommit = serverConn.isAutocommit() + ""; } row.add(txLevel.getBytes()); - row.add(txAutommit.getBytes()); - + row.add(autocommit.getBytes()); + row.add(StringUtil.encode(c.getStringOfSysVariables(), charset)); + row.add(StringUtil.encode(c.getStringOfUsrVariables(), charset)); return row; } diff --git a/src/main/java/com/actiontech/dble/manager/response/ShowDirectMemory.java b/src/main/java/com/actiontech/dble/manager/response/ShowDirectMemory.java index 869ac9b762..cf32e57b7d 100644 --- a/src/main/java/com/actiontech/dble/manager/response/ShowDirectMemory.java +++ b/src/main/java/com/actiontech/dble/manager/response/ShowDirectMemory.java @@ -18,7 +18,6 @@ import com.actiontech.dble.net.mysql.RowDataPacket; import com.actiontech.dble.util.StringUtil; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Map; import java.util.concurrent.ConcurrentMap; @@ -176,8 +175,6 @@ public static void showDirectMemoryTotal(ManagerConnection c) { } // write eof buffer = TOTAL_EOF.write(buffer, c, true); - // write rows - byte packetId = TOTAL_EOF.getPacketId(); int useOffHeapForMerge = DbleServer.getInstance().getConfig(). getSystem().getUseOffHeapForMerge(); @@ -250,7 +247,8 @@ public static void showDirectMemoryTotal(ManagerConnection c) { } row.add(StringUtil.encode(resevedForOs > 0 ? JavaUtils.bytesToString2(resevedForOs) : "0", c.getCharset().getResults())); - + // write rows + byte packetId = TOTAL_EOF.getPacketId(); row.setPacketId(++packetId); buffer = row.write(buffer, c, true); diff --git a/src/main/java/com/actiontech/dble/net/AbstractConnection.java b/src/main/java/com/actiontech/dble/net/AbstractConnection.java index bc40a9d60d..9212d62bd9 100644 --- a/src/main/java/com/actiontech/dble/net/AbstractConnection.java +++ b/src/main/java/com/actiontech/dble/net/AbstractConnection.java @@ -5,7 +5,6 @@ */ package com.actiontech.dble.net; -import com.actiontech.dble.backend.mysql.CharsetUtil; import com.actiontech.dble.net.mysql.CharsetNames; import com.actiontech.dble.net.mysql.MySQLPacket; import com.actiontech.dble.server.SystemVariables; @@ -20,6 +19,7 @@ import java.nio.channels.AsynchronousChannel; import java.nio.channels.NetworkChannel; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; @@ -58,6 +58,8 @@ public abstract class AbstractConnection implements NIOConnection { protected volatile boolean isSupportCompress = false; protected final ConcurrentLinkedQueue decompressUnfinishedDataQueue = new ConcurrentLinkedQueue<>(); protected final ConcurrentLinkedQueue compressUnfinishedDataQueue = new ConcurrentLinkedQueue<>(); + protected volatile Map usrVariables; + protected volatile Map sysVariables; private long idleTimeout; @@ -83,31 +85,16 @@ public AbstractConnection() { this.isClosed = new AtomicBoolean(false); this.socketWR = null; } - public boolean setCollationConnection(String collation) { - int ci = CharsetUtil.getCollationIndex(collation); - if (ci <= 0) { - return false; - } + public void setCollationConnection(String collation) { charsetName.setCollation(collation); - return true; } - public boolean setCharacterConnection(String charset) { - String collationName = CharsetUtil.getDefaultCollation(charset); - if (collationName == null) { - return false; - } + public void setCharacterConnection(String collationName) { charsetName.setCollation(collationName); - return true; } - public boolean setCharacterResults(String name) { - int ci = CharsetUtil.getCharsetDefaultIndex(name); - if (ci <= 0 && !name.equals("null")) { - return false; - } + public void setCharacterResults(String name) { charsetName.setResults(name); - return true; } @@ -115,36 +102,17 @@ public void setCharsetName(CharsetNames charsetName) { this.charsetName = charsetName.clone(); } - public boolean setCharacterClient(String name) { - int ci = CharsetUtil.getCharsetDefaultIndex(name); - if (ci <= 0) { - return false; - } + public void setCharacterClient(String name) { charsetName.setClient(name); - return true; } - public boolean setCharacterSet(String name) { - int ci = CharsetUtil.getCharsetDefaultIndex(name); - if (ci <= 0) { - return false; - } + public void setCharacterSet(String name) { charsetName.setClient(name); charsetName.setResults(name); charsetName.setCollation(SystemVariables.getDefaultValue("collation_database")); - return true; } public boolean setNames(String name, String collationName) { - int ci = CharsetUtil.getCharsetDefaultIndex(name); - if (ci <= 0) { - return false; - } - if (collationName == null) { - collationName = CharsetUtil.getDefaultCollation(name); - } else if (CharsetUtil.getCollationIndex(collationName) <= 0) { - return false; - } charsetName.setNames(name, collationName); return true; } @@ -198,6 +166,14 @@ public boolean isIdleTimeout() { return TimeUtil.currentTimeMillis() > Math.max(lastWriteTime, lastReadTime) + idleTimeout; } + public Map getUsrVariables() { + return usrVariables; + } + + public Map getSysVariables() { + return sysVariables; + } + public NetworkChannel getChannel() { return channel; } @@ -583,6 +559,39 @@ private void closeSocket() { } } + public String getStringOfSysVariables() { + StringBuilder sbSysVariables = new StringBuilder(); + int cnt = 0; + if (sysVariables != null) { + for (Map.Entry sysVariable : sysVariables.entrySet()) { + if (cnt > 0) { + sbSysVariables.append(","); + } + sbSysVariables.append(sysVariable.getKey()); + sbSysVariables.append("="); + sbSysVariables.append(sysVariable.getValue()); + cnt++; + } + } + return sbSysVariables.toString(); + } + + public String getStringOfUsrVariables() { + StringBuilder sbUsrVariables = new StringBuilder(); + int cnt = 0; + if (usrVariables != null) { + for (Map.Entry usrVariable : usrVariables.entrySet()) { + if (cnt > 0) { + sbUsrVariables.append(","); + } + sbUsrVariables.append(usrVariable.getKey()); + sbUsrVariables.append("="); + sbUsrVariables.append(usrVariable.getValue()); + cnt++; + } + } + return sbUsrVariables.toString(); + } public void onConnectfinish() { LOGGER.debug("The backend conntinon has finished connecting"); } diff --git a/src/main/java/com/actiontech/dble/net/mysql/OkPacket.java b/src/main/java/com/actiontech/dble/net/mysql/OkPacket.java index 0c37bbeedd..b6c4d9bde9 100644 --- a/src/main/java/com/actiontech/dble/net/mysql/OkPacket.java +++ b/src/main/java/com/actiontech/dble/net/mysql/OkPacket.java @@ -32,8 +32,7 @@ */ public class OkPacket extends MySQLPacket { public static final byte FIELD_COUNT = 0x00; - public static final byte[] OK = new byte[]{7, 0, 0, 1, 0, 0, 0, 2, 0, 0, - 0}; + public static final byte[] OK = new byte[]{7, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0}; private byte fieldCount = FIELD_COUNT; private long affectedRows; diff --git a/src/main/java/com/actiontech/dble/net/mysql/ResetConnectionPacket.java b/src/main/java/com/actiontech/dble/net/mysql/ResetConnectionPacket.java new file mode 100644 index 0000000000..e23538ffa9 --- /dev/null +++ b/src/main/java/com/actiontech/dble/net/mysql/ResetConnectionPacket.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016-2017 ActionTech. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ + +package com.actiontech.dble.net.mysql; + +public class ResetConnectionPacket extends MySQLPacket { + public static final byte[] RESET = new byte[]{1, 0, 0, 0, 31}; + + @Override + public int calcPacketSize() { + return 1; + } + + @Override + protected String getPacketInfo() { + return "MySQL Reset Connection Packet"; + } +} diff --git a/src/main/java/com/actiontech/dble/route/sequence/handler/FetchMySQLSequnceHandler.java b/src/main/java/com/actiontech/dble/route/sequence/handler/FetchMySQLSequnceHandler.java index 9f6a87b454..fcd2610bc5 100644 --- a/src/main/java/com/actiontech/dble/route/sequence/handler/FetchMySQLSequnceHandler.java +++ b/src/main/java/com/actiontech/dble/route/sequence/handler/FetchMySQLSequnceHandler.java @@ -82,7 +82,7 @@ public void errorResponse(byte[] data, BackendConnection conn) { @Override public void okResponse(byte[] ok, BackendConnection conn) { - boolean executeResponse = conn.syncAndExcute(); + boolean executeResponse = conn.syncAndExecute(); if (executeResponse) { ((SequenceVal) conn.getAttachment()).dbfinished = true; conn.release(); diff --git a/src/main/java/com/actiontech/dble/server/ServerConnection.java b/src/main/java/com/actiontech/dble/server/ServerConnection.java index 283f58fe54..075334e61d 100644 --- a/src/main/java/com/actiontech/dble/server/ServerConnection.java +++ b/src/main/java/com/actiontech/dble/server/ServerConnection.java @@ -16,7 +16,9 @@ import com.actiontech.dble.log.transaction.TxnLogHelper; import com.actiontech.dble.net.FrontendConnection; import com.actiontech.dble.route.RouteResultset; +import com.actiontech.dble.route.parser.util.Pair; import com.actiontech.dble.route.util.RouterUtil; +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; @@ -31,6 +33,9 @@ import java.nio.channels.NetworkChannel; import java.sql.SQLException; import java.sql.SQLNonTransientException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.LockSupport; @@ -53,11 +58,12 @@ public class ServerConnection extends FrontendConnection { private NonBlockingSession session; private volatile boolean isLocked = false; private AtomicLong txID; - + private List>> contextTask = new ArrayList<>(); public long getAndIncrementXid() { return txID.getAndIncrement(); } + public long getXid() { return txID.get(); } @@ -68,6 +74,8 @@ public ServerConnection(NetworkChannel channel) this.txInterrupted = false; this.autocommit = true; this.txID = new AtomicLong(1); + this.usrVariables = new LinkedHashMap<>(); + this.sysVariables = new LinkedHashMap<>(); } public ServerConnection() { @@ -131,7 +139,7 @@ public NonBlockingSession getSession2() { return session; } - public void setSession2(NonBlockingSession session2) { + void setSession2(NonBlockingSession session2) { this.session = session2; } @@ -139,10 +147,64 @@ public boolean isLocked() { return isLocked; } - public void setLocked(boolean locked) { + void setLocked(boolean locked) { this.isLocked = locked; } + + public List>> getContextTask() { + return contextTask; + } + + public void setContextTask(List>> contextTask) { + this.contextTask = contextTask; + } + + public void executeTask() { + 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: + this.sysVariables.put(task.getValue().getKey(), task.getValue().getValue()); + break; + case USER_VARIABLES: + this.usrVariables.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; + } + } + } @Override public void ping() { Ping.response(this); @@ -319,10 +381,7 @@ public void rollback() { session.rollback(); } - /** - * @param sql - */ - public void lockTable(String sql) { + void lockTable(String sql) { // lock table is disable in transaction if (!autocommit) { writeErrMessage(ErrorCode.ER_YES, "can't lock table in transaction!"); @@ -339,10 +398,7 @@ public void lockTable(String sql) { } } - /** - * @param sql - */ - public void unLockTable(String sql) { + void unLockTable(String sql) { sql = sql.replaceAll("\n", " ").replaceAll("\t", " "); String[] words = SplitUtil.split(sql, ' ', true); if (words.length == 2 && ("table".equalsIgnoreCase(words[1]) || "tables".equalsIgnoreCase(words[1]))) { @@ -395,9 +451,31 @@ public void killAndClose(String reason) { @Override public String toString() { - return "ServerConnection [id=" + id + ", schema=" + schema + ", host=" + host + - ", user=" + user + ",txIsolation=" + txIsolation + ", autocommit=" + autocommit + - ", schema=" + schema + "]"; + StringBuilder result = new StringBuilder(); + result.append("ServerConnection [id="); + result.append(id); + result.append(", schema="); + result.append(schema); + result.append(", host="); + result.append(host); + result.append(", user="); + result.append(user); + result.append(",txIsolation="); + result.append(txIsolation); + result.append(", autocommit="); + result.append(autocommit); + result.append(", schema="); + result.append(schema); + if (sysVariables.size() > 0) { + result.append(", "); + result.append(getStringOfSysVariables()); + } + if (usrVariables.size() > 0) { + result.append(", "); + result.append(getStringOfUsrVariables()); + } + result.append("]"); + return result.toString(); } } diff --git a/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java b/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java new file mode 100644 index 0000000000..038da36281 --- /dev/null +++ b/src/main/java/com/actiontech/dble/server/handler/SetCallBack.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016-2017 ActionTech. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ + +package com.actiontech.dble.server.handler; + +import com.actiontech.dble.server.ServerConnection; +import com.actiontech.dble.sqlengine.SQLQueryResult; +import com.actiontech.dble.sqlengine.SQLQueryResultListener; + +import java.util.Map; + +public class SetCallBack implements SQLQueryResultListener>> { + private ServerConnection sc; + + SetCallBack(ServerConnection sc) { + this.sc = sc; + } + @Override + public void onResult(SQLQueryResult> result) { + if (result.isSuccess()) { + sc.executeTask(); + } else { + sc.getContextTask().clear(); + } + } +} 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 88193b8c7c..da59472d0d 100644 --- a/src/main/java/com/actiontech/dble/server/handler/SetHandler.java +++ b/src/main/java/com/actiontech/dble/server/handler/SetHandler.java @@ -11,15 +11,27 @@ import com.actiontech.dble.config.Isolations; import com.actiontech.dble.log.transaction.TxnLogHelper; import com.actiontech.dble.net.mysql.OkPacket; +import com.actiontech.dble.route.parser.util.Pair; import com.actiontech.dble.route.parser.util.ParseUtil; import com.actiontech.dble.server.ServerConnection; -import com.actiontech.dble.server.parser.ServerParseSet; -import com.actiontech.dble.util.SetIgnoreUtil; +import com.actiontech.dble.server.SystemVariables; +import com.actiontech.dble.sqlengine.OneRawSQLQueryResultHandler; +import com.actiontech.dble.sqlengine.SetTestJob; import com.actiontech.dble.util.StringUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +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.statement.MySqlSetCharSetStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement; +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 static com.actiontech.dble.server.parser.ServerParseSet.*; +import java.sql.SQLSyntaxErrorException; +import java.util.ArrayList; +import java.util.List; /** * SetHandler @@ -31,259 +43,712 @@ public final class SetHandler { private SetHandler() { } - private static final Logger LOGGER = LoggerFactory.getLogger(SetHandler.class); - private static final byte[] AC_OFF = new byte[]{7, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}; + public enum KeyType { + SYNTAX_ERROR, + XA, + AUTOCOMMIT, + NAMES, + CHARSET, + CHARACTER_SET_CLIENT, + CHARACTER_SET_CONNECTION, + CHARACTER_SET_RESULTS, + COLLATION_CONNECTION, + SYSTEM_VARIABLES, + USER_VARIABLES, + TX_READ_ONLY, + TX_ISOLATION + } + public static void handle(String stmt, ServerConnection c, int offset) { if (!ParseUtil.isSpace(stmt.charAt(offset))) { c.writeErrMessage(ErrorCode.ERR_WRONG_USED, stmt + " is not supported"); } - int rs = ServerParseSet.parse(stmt, offset); - switch (rs & 0xff) { - case MULTI_SET: - //set split with ',' - if (!parserMultiSet(stmt.substring(offset), c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } - break; - case AUTOCOMMIT_ON: - if (c.isAutocommit()) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + try { + String smt = convertCharsetKeyWord(stmt); + List>> contextTask = new ArrayList<>(); + if (handleSetStatement(smt, c, contextTask) && contextTask.size() > 0) { + setStmtCallback(stmt, c, contextTask); + } + } catch (SQLSyntaxErrorException e) { + c.writeErrMessage(ErrorCode.ER_PARSE_ERROR, e.toString()); + } + } + + private static SQLStatement parseSQL(String stmt) throws SQLSyntaxErrorException { + SQLStatementParser parser = new MySqlStatementParser(stmt); + try { + return parser.parseStatement(); + } catch (Exception t) { + if (t.getMessage() != null) { + throw new SQLSyntaxErrorException(t.getMessage()); + } else { + throw new SQLSyntaxErrorException(t); + } + } + } + private static boolean handleSetStatement(String stmt, ServerConnection c, List>> contextTask) throws SQLSyntaxErrorException { + SQLStatement statement = parseSQL(stmt); + if (statement instanceof SQLSetStatement) { + List assignItems = ((SQLSetStatement) statement).getItems(); + if (assignItems.size() == 1 && contextTask.size() == 0) { + return handleSingleVariable(stmt, assignItems.get(0), c, contextTask); + } else { + return handleSetMultiStatement(assignItems, c, contextTask); + } + } else if (statement instanceof MySqlSetNamesStatement) { + MySqlSetNamesStatement setNamesStatement = (MySqlSetNamesStatement) statement; + if (contextTask.size() > 0 || stmt.contains(",")) { + if (handleSetNamesInMultiStmt(c, setNamesStatement.getCharSet(), setNamesStatement.getCollate(), contextTask)) { + int index = stmt.indexOf(","); + String newStmt = "set " + stmt.substring(index + 1); + return handleSetStatement(newStmt, c, contextTask); } else { - c.commit("commit[because of " + stmt + "]"); - c.setAutocommit(true); + return false; } - break; - case AUTOCOMMIT_OFF: { - if (c.isAutocommit()) { - c.setAutocommit(false); - TxnLogHelper.putTxnLog(c, stmt); - } - c.write(c.writeToBuffer(AC_OFF, c.allocate())); - break; + } else { + return handleSingleSetNames(stmt, c, setNamesStatement); } - case XA_FLAG_ON: { - if (c.isTxstart() && c.getSession2().getSessionXaID() == null) { - c.writeErrMessage(ErrorCode.ERR_WRONG_USED, "set xa cmd on can't used before ending a transaction"); - return; + } else if (statement instanceof MySqlSetCharSetStatement) { + MySqlSetCharSetStatement setCharSetStatement = (MySqlSetCharSetStatement) statement; + if (contextTask.size() > 0 || stmt.contains(",")) { + if (handleCharsetInMultiStmt(c, setCharSetStatement.getCharSet(), contextTask)) { + int index = stmt.indexOf(","); + String newStmt = "set " + stmt.substring(index + 1); + return handleSetStatement(newStmt, c, contextTask); + } else { + return false; } - c.getSession2().setXaTxEnabled(true); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - break; + } else { + return handleSingleSetCharset(stmt, c, setCharSetStatement); } - case XA_FLAG_OFF: { - if (c.isTxstart() && c.getSession2().getSessionXaID() != null) { - c.writeErrMessage(ErrorCode.ERR_WRONG_USED, "set xa cmd off can't used before ending a transaction"); - return; - } - c.getSession2().setXaTxEnabled(false); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - return; + } else if (statement instanceof MySqlSetTransactionStatement) { + return handleTransaction(c, (MySqlSetTransactionStatement) statement); + } else { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, stmt + " is not recognized and ignored"); + return false; + } + } + + private static boolean handleSetNamesInMultiStmt(ServerConnection c, String charset, String collate, List>> contextTask) { + String[] charsetInfo = checkSetNames(charset, collate); + if (charsetInfo != null) { + contextTask.add(new Pair<>(KeyType.NAMES, new Pair<>(charsetInfo[0], charsetInfo[1]))); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charset + " or collate '" + collate + "'"); + return false; + } + } + + private static boolean handleSingleSetNames(String stmt, ServerConnection c, MySqlSetNamesStatement statement) { + String[] charsetInfo = checkSetNames(statement.getCharSet(), statement.getCollate()); + if (charsetInfo != null) { + c.setNames(charsetInfo[0], charsetInfo[1]); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set in statement '" + stmt + ""); + return false; + } + } + + private static boolean handleSingleSetCharset(String stmt, ServerConnection c, MySqlSetCharSetStatement statement) { + String charset = getCharset(statement.getCharSet()); + if (charset != null) { + c.setCharacterSet(charset); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set in statement '" + stmt + ""); + return false; + } + } + + private static boolean handleSetMultiStatement(List assignItems, ServerConnection c, List>> contextTask) { + for (SQLAssignItem assignItem : assignItems) { + if (!handleVariableInMultiStmt(assignItem, c, contextTask)) { + return false; } - case TX_READ_UNCOMMITTED: { - c.setTxIsolation(Isolations.READ_UNCOMMITTED); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + } + return true; + } + + //execute multiStmt and callback to reset conn + private static void setStmtCallback(String multiStmt, ServerConnection c, List>> contextTask) { + c.setContextTask(contextTask); + OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler(new String[0], new SetCallBack(c)); + SetTestJob sqlJob = new SetTestJob(multiStmt, resultHandler, c); + sqlJob.run(); + } + + private static boolean handleVariableInMultiStmt(SQLAssignItem assignItem, ServerConnection c, List>> contextTask) { + String key = handleSetKey(assignItem, c); + if (key == null) { + return false; + } + SQLExpr valueExpr = assignItem.getValue(); + if (!checkValue(valueExpr)) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + assignItem.getValue() + "'"); + return false; + } + KeyType keyType = parseKeyType(key, true, KeyType.SYSTEM_VARIABLES); + switch (keyType) { + case XA: + c.writeErrMessage(ErrorCode.ERR_WRONG_USED, "set xa cmd can't used in multi-set statement"); + return false; + case AUTOCOMMIT: + c.writeErrMessage(ErrorCode.ERR_WRONG_USED, "set autocommit cmd can't used in multi-set statement"); + return false; + case NAMES: { + String charset = parseStringValue(valueExpr); + //TODO:druid lost collation info + if (!handleSetNamesInMultiStmt(c, charset, null, contextTask)) return false; break; } - case TX_READ_COMMITTED: { - c.setTxIsolation(Isolations.READ_COMMITTED); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + case CHARSET: { + String charset = parseStringValue(valueExpr); + if (!handleCharsetInMultiStmt(c, charset, contextTask)) return false; break; } - case TX_REPEATED_READ: { - c.setTxIsolation(Isolations.REPEATED_READ); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + case CHARACTER_SET_CLIENT: + if (!handleCharsetClientInMultiStmt(c, contextTask, valueExpr)) return false; break; - } - case TX_SERIALIZABLE: { - c.setTxIsolation(Isolations.SERIALIZABLE); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + case CHARACTER_SET_CONNECTION: + if (!handleCharsetConnInMultiStmt(c, contextTask, valueExpr)) return false; break; - } - case TX_READ_WRITE: - c.setSessionReadOnly(false); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + case CHARACTER_SET_RESULTS: + if (!handleCharsetResultsInMultiStmt(c, contextTask, valueExpr)) return false; + break; + case COLLATION_CONNECTION: + if (!handleCollationConnInMultiStmt(c, contextTask, valueExpr)) return false; break; case TX_READ_ONLY: - c.setSessionReadOnly(true); - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + if (!handleReadOnlyInMultiStmt(c, contextTask, valueExpr)) return false; break; - case NAMES: { - String names = stmt.substring(rs >>> 8).trim(); - if (handleSetNames(names, c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } else { - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set" + names + ""); - } + case TX_ISOLATION: + if (!handleTxIsolationInMultiStmt(c, contextTask, valueExpr)) return false; break; - } - case CHARACTER_SET_CLIENT: - String charsetClient = stmt.substring(rs >>> 8).trim().toLowerCase(); - if (charsetClient.equals("null")) { - c.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_client' can't be set to the value of 'NULL'"); - } - if (handleCharSetClient(charsetClient, c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } else { - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set " + charsetClient + ""); + case SYSTEM_VARIABLES: + if (SystemVariables.getDefaultValue(key) == null) { + c.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 CHARACTER_SET_CONNECTION: - String charsetConnection = stmt.substring(rs >>> 8).trim().toLowerCase(); - if (charsetConnection.equals("null")) { - c.writeErrMessage(ErrorCode.ER_WRONG_VALUE_FOR_VAR, "Variable 'character_set_connection' can't be set to the value of 'NULL'"); - } - if (handleCharSetConnection(charsetConnection, c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } else { - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set " + charsetConnection + ""); - } + case USER_VARIABLES: + contextTask.add(new Pair<>(KeyType.USER_VARIABLES, new Pair<>(key, parseVariablesValue(valueExpr)))); break; + default: + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, key + " is not supported"); + return false; + } + return true; + } + + private static boolean handleCharsetInMultiStmt(ServerConnection c, String charset, List>> contextTask) { + String charsetInfo = getCharset(charset); + if (charsetInfo != null) { + contextTask.add(new Pair<>(KeyType.CHARSET, new Pair(charsetInfo, null))); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charset + "'"); + return false; + } + } + + private static boolean handleTxIsolationInMultiStmt(ServerConnection c, List>> contextTask, SQLExpr valueExpr) { + String value = parseStringValue(valueExpr); + Integer txIsolation = getIsolationLevel(value); + if (txIsolation == null) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "Variable 'tx_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(ServerConnection c, List>> contextTask, SQLExpr valueExpr) { + Boolean switchStatus = isSwitchOn(valueExpr); + if (switchStatus == null) { + c.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(ServerConnection c, List>> contextTask, SQLExpr valueExpr) { + String collation = parseStringValue(valueExpr); + if (checkCollation(collation)) { + contextTask.add(new Pair<>(KeyType.COLLATION_CONNECTION, new Pair(collation, null))); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_COLLATION, "Unknown collation '" + collation + "'"); + return false; + } + } + + private static boolean handleCharsetResultsInMultiStmt(ServerConnection c, List>> contextTask, SQLExpr valueExpr) { + String charsetResult = parseStringValue(valueExpr); + if (charsetResult.equals("null") || checkCharset(charsetResult)) { + contextTask.add(new Pair<>(KeyType.CHARACTER_SET_RESULTS, new Pair(charsetResult, null))); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetResult + "'"); + return false; + } + } + + private static boolean handleCharsetConnInMultiStmt(ServerConnection c, List>> contextTask, SQLExpr valueExpr) { + String charsetConnection = parseStringValue(valueExpr); + if (charsetConnection.equals("null")) { + c.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 { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetConnection + "'"); + return false; + } + } + + private static boolean handleCharsetClientInMultiStmt(ServerConnection c, List>> contextTask, SQLExpr valueExpr) { + String charsetClient = parseStringValue(valueExpr); + if (charsetClient.equals("null")) { + c.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)) { + contextTask.add(new Pair<>(KeyType.CHARACTER_SET_CLIENT, new Pair(charsetClient, null))); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetClient + "'"); + return false; + } + } + + private static boolean handleSingleVariable(String stmt, SQLAssignItem assignItem, ServerConnection c, List>> contextTask) { + String key = handleSetKey(assignItem, c); + if (key == null) return false; + SQLExpr valueExpr = assignItem.getValue(); + if (!checkValue(valueExpr)) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + assignItem.getValue() + "'"); + return false; + } + KeyType keyType = parseKeyType(key, true, KeyType.SYSTEM_VARIABLES); + switch (keyType) { + case XA: + return handleSingleXA(c, valueExpr); + case AUTOCOMMIT: + return handleSingleAutocommit(stmt, c, valueExpr); + case CHARACTER_SET_CLIENT: + return handleSingleCharsetClient(c, valueExpr); + case CHARACTER_SET_CONNECTION: + return handleSingleCharsetConnection(c, valueExpr); case CHARACTER_SET_RESULTS: - String charsetResult = stmt.substring(rs >>> 8).trim(); - if (handleCharSetResults(charsetResult, c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } else { - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set " + charsetResult + ""); - } - break; - case CHARACTER_SET_NAME: { - String charset = stmt.substring(rs >>> 8).trim(); - if (handleCharSetName(charset, c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } else { - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set " + charset + ""); + return handleSingleCharsetResults(c, valueExpr); + case COLLATION_CONNECTION: + return handleCollationConnection(c, valueExpr); + case TX_READ_ONLY: + return handleTxReadOnly(c, valueExpr); + case TX_ISOLATION: + return handleTxIsolation(c, valueExpr); + case SYSTEM_VARIABLES: + if (SystemVariables.getDefaultValue(key) == null) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "system variable " + key + " is not supported"); + return false; } - break; + 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, parseVariablesValue(valueExpr)))); + return true; + default: + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, stmt + " is not supported"); + return false; + } + } + + private static boolean handleTxReadOnly(ServerConnection c, SQLExpr valueExpr) { + Boolean switchStatus = isSwitchOn(valueExpr); + if (switchStatus == null) { + c.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'tx_read_only|transaction_read_only'"); + return false; + } else if (switchStatus) { + c.setSessionReadOnly(true); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + } else { + c.setSessionReadOnly(false); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + } + return true; + } + + private static boolean handleTxIsolation(ServerConnection c, SQLExpr valueExpr) { + String value = parseStringValue(valueExpr); + Integer txIsolation = getIsolationLevel(value); + if (txIsolation == null) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "Variable 'tx_isolation' can't be set to the value of '" + value + "'"); + return false; + } + c.setTxIsolation(txIsolation); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + 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.REPEATED_READ; + case "serializable": + return Isolations.SERIALIZABLE; + default: + return null; + } + } + + private static boolean handleCollationConnection(ServerConnection c, SQLExpr valueExpr) { + String collation = parseStringValue(valueExpr); + if (checkCollation(collation)) { + c.setCollationConnection(collation); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_COLLATION, "Unknown collation '" + collation + "'"); + return false; + } + } + + private static boolean handleSingleCharsetResults(ServerConnection c, SQLExpr valueExpr) { + String charsetResult = parseStringValue(valueExpr); + if (charsetResult.equals("null") || checkCharset(charsetResult)) { + c.setCharacterResults(charsetResult); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetResult + "'"); + return false; + } + } + + private static boolean handleSingleCharsetConnection(ServerConnection c, SQLExpr valueExpr) { + String charsetConnection = parseStringValue(valueExpr); + if (charsetConnection.equals("null")) { + c.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) { + c.setCharacterConnection(collationName); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetConnection + "'"); + return false; + } + } + + private static boolean handleSingleCharsetClient(ServerConnection c, SQLExpr valueExpr) { + String charsetClient = parseStringValue(valueExpr); + if (charsetClient.equals("null")) { + c.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)) { + c.setCharacterClient(charsetClient); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set '" + charsetClient + "'"); + return false; + } + } + + private static boolean handleSingleAutocommit(String stmt, ServerConnection c, SQLExpr valueExpr) { + Boolean switchStatus = isSwitchOn(valueExpr); + if (switchStatus == null) { + c.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'AUTOCOMMIT'"); + return false; + } else if (switchStatus) { + if (c.isAutocommit()) { + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + } else { + c.commit("commit[because of " + stmt + "]"); + c.setAutocommit(true); } - case COLLATION_CONNECTION: { - String collation = stmt.substring(rs >>> 8).trim(); - if (handleCollationConn(collation, c)) { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); - } else { - c.writeErrMessage(ErrorCode.ER_UNKNOWN_COLLATION, "Unknown collation " + collation + ""); - } - break; + } else { + if (c.isAutocommit()) { + c.setAutocommit(false); + TxnLogHelper.putTxnLog(c, stmt); + } + c.write(c.writeToBuffer(AC_OFF, c.allocate())); + } + return true; + } + + private static boolean handleSingleXA(ServerConnection c, SQLExpr valueExpr) { + Boolean switchStatus = isSwitchOn(valueExpr); + if (switchStatus == null) { + c.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, "Incorrect argument type to variable 'XA'"); + return false; + } else if (switchStatus) { + if (c.isTxstart() && c.getSession2().getSessionXaID() == null) { + c.writeErrMessage(ErrorCode.ERR_WRONG_USED, "set xa cmd on can't used before ending a transaction"); + return false; + } + c.getSession2().setXaTxEnabled(true); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + if (c.isTxstart() && c.getSession2().getSessionXaID() != null) { + c.writeErrMessage(ErrorCode.ERR_WRONG_USED, "set xa cmd off can't used before ending a transaction"); + return false; } - case GLOBAL: + c.getSession2().setXaTxEnabled(false); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } + } + + // druid not support 'set charset' ,change to 'set character set' + private static String convertCharsetKeyWord(String stmt) { + StringBuilder result = new StringBuilder(); + String toCheck = stmt.toLowerCase(); + int index = toCheck.indexOf("charset"); + int tailStart = 0; + while (index > 0) { + 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("character set"); + } + tailStart = index + 7; + index = toCheck.indexOf("charset", tailStart); + } + if (result.length() > 0) { + result.append(stmt.substring(tailStart)); + return result.toString(); + } + return stmt; + } + + private static String handleSetKey(SQLAssignItem assignItem, ServerConnection c) { + if (assignItem.getTarget() instanceof SQLPropertyExpr) { + SQLPropertyExpr target = (SQLPropertyExpr) assignItem.getTarget(); + if (!(target.getOwner() instanceof SQLVariantRefExpr)) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + target + "'"); + return null; + } + SQLVariantRefExpr owner = (SQLVariantRefExpr) target.getOwner(); + if (owner.isGlobal()) { c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting GLOBAL value is not supported"); - break; + return null; + } + return target.getName(); + } else if (assignItem.getTarget() instanceof SQLVariantRefExpr) { + SQLVariantRefExpr target = (SQLVariantRefExpr) assignItem.getTarget(); + if (target.isGlobal()) { + c.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 { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting target is not supported for '" + assignItem.getTarget() + "'"); + return null; + } + } + + private static boolean checkValue(SQLExpr valueExpr) { + return (valueExpr instanceof SQLCharExpr) || (valueExpr instanceof SQLIdentifierExpr) || + (valueExpr instanceof SQLIntegerExpr); + } + + private static KeyType parseKeyType(String key, boolean origin, KeyType defaultVariables) { + switch (key.toLowerCase()) { + case "xa": + return KeyType.XA; + 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 "transaction_isolation": + case "tx_isolation": + return KeyType.TX_ISOLATION; + case "transaction_read_only": + case "tx_read_only": + return KeyType.TX_READ_ONLY; + case "names": + return KeyType.NAMES; + case "character set": + return KeyType.CHARSET; default: - boolean ignore = SetIgnoreUtil.isIgnoreStmt(stmt); - if (!ignore) { - StringBuilder s = new StringBuilder(); - String warn = stmt + " is not recognized and ignored"; - LOGGER.warn(s.append(c).append(warn).toString()); - c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, warn); + 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 { - c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return defaultVariables; } } } - //TODO: - private static boolean parserMultiSet(String setSQL, ServerConnection c) { - String[] setStatements = setSQL.split(","); - for (String statement : setStatements) { - boolean setError = false; - int rs = ServerParseSet.parse(statement, 0); - switch (rs & 0xff) { - case AUTOCOMMIT_ON: + private 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); + } + String strValue = parseStringValue(valueExpr); + switch (strValue) { + case "on": + return true; + case "off": + return false; + default: + return null; + } + } - break; - case AUTOCOMMIT_OFF: { - break; - } - case XA_FLAG_ON: { + 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(); + } + return strValue; + } - break; - } - case XA_FLAG_OFF: { + private 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(); + } + return strValue; + } + + private static boolean handleTransaction(ServerConnection c, MySqlSetTransactionStatement setStatement) { + //always single + if (setStatement.getGlobal() == null) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting transaction without any SESSION or GLOBAL keyword is not supported now"); + return false; + } else if (setStatement.getGlobal()) { + c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting GLOBAL value is not supported"); + return false; + } else if (setStatement.getAccessModel() != null) { + if (setStatement.getAccessModel().equals("ONLY")) { + c.setSessionReadOnly(true); + } else { + c.setSessionReadOnly(false); + } + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; + } else { + int txIsolation = Isolations.REPEATED_READ; + switch (setStatement.getIsolationLevel()) { + case "READ UNCOMMITTED": + txIsolation = Isolations.READ_UNCOMMITTED; break; - } - case NAMES: { - String names = statement.substring(rs >>> 8).trim(); - if (!handleSetNames(names, c)) { - setError = true; - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set " + names + ""); - } - break; - } - case CHARACTER_SET_CLIENT: - case CHARACTER_SET_CONNECTION: - case CHARACTER_SET_RESULTS: - //TODO: - break; - case CHARACTER_SET_NAME: { - String charset = statement.substring(rs >>> 8).trim(); - if (!handleCharSetName(charset, c)) { - setError = true; - c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown character set " + charset + ""); - } + case "READ COMMITTED": + txIsolation = Isolations.READ_COMMITTED; break; - } - case GLOBAL: - c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "setting GLOBAL value is not supported"); + case "REPEATABLE READ": + txIsolation = Isolations.REPEATED_READ; break; - case TX_READ_UNCOMMITTED: - case TX_READ_COMMITTED: - case TX_REPEATED_READ: - case TX_SERIALIZABLE: { + case "SERIALIZABLE": + txIsolation = Isolations.SERIALIZABLE; break; - } default: - //TODO - } - if (setError) { - return true; + // can't be happened + break; } + c.setTxIsolation(txIsolation); + c.write(c.writeToBuffer(OkPacket.OK, c.allocate())); + return true; } - return false; - } - private static boolean handleCollationConn(String collation, ServerConnection c) { - collation = StringUtil.removeApostropheOrBackQuote(collation); - return c.setCollationConnection(collation); - } - private static boolean handleCharSetConnection(String charset, ServerConnection c) { - charset = StringUtil.removeApostropheOrBackQuote(charset); - return c.setCharacterConnection(charset); } - private static boolean handleCharSetResults(String charset, ServerConnection c) { - charset = StringUtil.removeApostropheOrBackQuote(charset); - return c.setCharacterResults(charset); + + private static boolean checkCollation(String collation) { + int ci = CharsetUtil.getCollationIndex(collation); + return ci > 0; } - private static boolean handleCharSetClient(String charset, ServerConnection c) { - charset = StringUtil.removeApostropheOrBackQuote(charset); - return c.setCharacterClient(charset); + + private static boolean checkCharset(String name) { + int ci = CharsetUtil.getCharsetDefaultIndex(name); + return ci > 0; } - private static boolean handleCharSetName(String charset, ServerConnection c) { + + private static String getCharset(String charset) { charset = charset.toLowerCase(); if (charset.equals("default")) { charset = DbleServer.getInstance().getConfig().getSystem().getCharset(); } charset = StringUtil.removeApostropheOrBackQuote(charset); - return c.setCharacterSet(charset); - } - - private static boolean handleSetNames(String names, ServerConnection c) { - String charset = names.toLowerCase(); - int collateIndex = charset.indexOf("collate"); - String collate = null; - if (collateIndex > 0) { - charset = names.substring(0, collateIndex).trim(); - collate = names.substring(collateIndex + 7).trim(); - if (collate.toLowerCase().equals("default")) { - String defaultCharset = DbleServer.getInstance().getConfig().getSystem().getCharset(); - collate = CharsetUtil.getDefaultCollation(defaultCharset); - } + if (checkCharset(charset)) { + return charset; } + return null; + } + + private static String[] checkSetNames(String charset, String collate) { + charset = charset.toLowerCase(); if (charset.equals("default")) { charset = DbleServer.getInstance().getConfig().getSystem().getCharset(); + } else { + charset = StringUtil.removeApostropheOrBackQuote(charset); + if (!checkCharset(charset)) { + return null; + } } - charset = StringUtil.removeApostropheOrBackQuote(charset); - return c.setNames(charset, collate); - + if (collate == null) { + collate = CharsetUtil.getDefaultCollation(charset); + } else { + collate = collate.toLowerCase(); + if (collate.equals("default")) { + collate = CharsetUtil.getDefaultCollation(charset); + } else if (CharsetUtil.getCollationIndex(collate) <= 0) { + return null; + } + } + return new String[]{charset, collate}; } } diff --git a/src/main/java/com/actiontech/dble/server/parser/ServerParseSet.java b/src/main/java/com/actiontech/dble/server/parser/ServerParseSet.java deleted file mode 100644 index 5bfa64d118..0000000000 --- a/src/main/java/com/actiontech/dble/server/parser/ServerParseSet.java +++ /dev/null @@ -1,1195 +0,0 @@ -/* -* Copyright (C) 2016-2017 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.parser; - -import com.actiontech.dble.route.parser.util.ParseUtil; - -/** - * @author mycat - */ -public final class ServerParseSet { - private ServerParseSet() { - } - - public static final int SYNTAX_ERROR = -99; - public static final int TX_WITHOUT_KEYWORD = -3; - public static final int GLOBAL = -2; - //TODO: DELETE OTHER - public static final int OTHER = -1; - public static final int AUTOCOMMIT_ON = 1; - public static final int AUTOCOMMIT_OFF = 2; - public static final int TX_READ_UNCOMMITTED = 3; - public static final int TX_READ_COMMITTED = 4; - public static final int TX_REPEATED_READ = 5; - public static final int TX_SERIALIZABLE = 6; - public static final int NAMES = 7; - public static final int CHARACTER_SET_CLIENT = 8; - public static final int CHARACTER_SET_CONNECTION = 9; - public static final int CHARACTER_SET_RESULTS = 10; - public static final int XA_FLAG_ON = 11; - public static final int XA_FLAG_OFF = 12; - public static final int CHARACTER_SET_NAME = 13; - public static final int TX_READ_WRITE = 14; - public static final int TX_READ_ONLY = 15; - public static final int COLLATION_CONNECTION = 16; - - public static final int SYSTEM_VARIABLES = 97; - public static final int USER_VARIABLES = 98; - public static final int MULTI_SET = 99; - - private static final int VALUE_ON = 1; - private static final int VALUE_OFF = 0; - - public static int parse(String stmt, int offset) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case '/': - case '#': - //TODO:DELETE COMMENT? - offset = ParseUtil.comment(stmt, offset); - continue; - case 'C': - case 'c': - return checkC(stmt, offset); - case 'N': - case 'n': - return names(stmt, offset); - case 'X': - case 'x': - return xaFlag(stmt, offset); - case 'A': - case 'a': - return autocommit(stmt, offset); - case 'T': - case 't': - int res = parseT(stmt, offset); - if (res != SYNTAX_ERROR && res != SYSTEM_VARIABLES) { - res = TX_WITHOUT_KEYWORD; - } - return res; - case 'S': - case 's': - return session(stmt, offset); - case 'G': - case 'g': - return global(stmt, offset); - case '@': - return parseAt(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - return SYNTAX_ERROR; - } - - // set xa=1 - private static int xaFlag(String stmt, int offset) { - if (stmt.length() > offset + 1) { - char c1 = stmt.charAt(++offset); - if ((c1 == 'A' || c1 == 'a')) { - return checkSwitchForExpect(stmt, offset, XA_FLAG_ON, XA_FLAG_OFF); - } - } - return checkSystemVariables(stmt); - } - - //AUTOCOMMIT(' '=) - private static int autocommit(String stmt, int offset) { - if (stmt.length() > offset + 9) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - char c9 = stmt.charAt(++offset); - if ((c1 == 'U' || c1 == 'u') && (c2 == 'T' || c2 == 't') && - (c3 == 'O' || c3 == 'o') && (c4 == 'C' || c4 == 'c') && - (c5 == 'O' || c5 == 'o') && (c6 == 'M' || c6 == 'm') && - (c7 == 'M' || c7 == 'm') && (c8 == 'I' || c8 == 'i') && - (c9 == 'T' || c9 == 't')) { - return checkSwitchForExpect(stmt, offset, AUTOCOMMIT_ON, AUTOCOMMIT_OFF); - } - } - return checkSystemVariables(stmt); - } - - // check value is "=on/off/0/1" - private static int checkSwitchForExpect(String stmt, int offset, int expectOn, int expectOff) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case '=': - int value = parserSwitchValue(stmt, offset); - if (value == VALUE_ON) { - return expectOn; - } else if (value == VALUE_OFF) { - return expectOff; - } else { - return value; - } - default: - return SYNTAX_ERROR; - } - } - return SYNTAX_ERROR; - } - - private static int parserSwitchValue(String stmt, int offset) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case '1': - return parseValueForExpected(stmt, offset, VALUE_ON); - case '0': - return parseValueForExpected(stmt, offset, VALUE_OFF); - case 'O': - case 'o': - return parseValueO(stmt, offset); - default: - return SYNTAX_ERROR; - } - } - return SYNTAX_ERROR; - } - - private static int parseValueForExpected(String stmt, int offset, int expectValue) { - if (stmt.length() == ++offset) { - return expectValue; - } - int pos = offset; - if (ParseUtil.isEOF(stmt, pos)) { - return expectValue; - } else if (isMultiSet(stmt, pos)) { - return MULTI_SET; - } else { - return SYNTAX_ERROR; - } - } - - private static boolean isMultiSet(String stmt, int offset) { - for (; offset < stmt.length(); offset++) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case ',': - return true; - default: - return false; - } - } - return false; - } - - //ON/OFF - private static int parseValueO(String stmt, int offset) { - if (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case 'N': - case 'n': - return parseValueForExpected(stmt, offset, VALUE_ON); - case 'F': - case 'f': - return parseValueOff(stmt, offset); - default: - return SYNTAX_ERROR; - } - } - return SYNTAX_ERROR; - } - - // SET AUTOCOMMIT = OFF - private static int parseValueOff(String stmt, int offset) { - if (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case 'F': - case 'f': - return parseValueForExpected(stmt, offset, VALUE_OFF); - default: - return SYNTAX_ERROR; - } - } - return SYNTAX_ERROR; - } - - // SET NAMES' ' - private static int names(String stmt, int offset) { - if (stmt.length() > offset + 5) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - if ((c1 == 'A' || c1 == 'a') && (c2 == 'M' || c2 == 'm') && - (c3 == 'E' || c3 == 'e') && (c4 == 'S' || c4 == 's') && - ParseUtil.isSpace(c5)) { - if (stmt.indexOf(',', offset) >= 0) { - return MULTI_SET; - } else { - return (offset << 8) | NAMES; - } - } - } - return checkSystemVariables(stmt); - } - - // SET C - private static int checkC(String stmt, int offset) { - if (stmt.length() > offset + 1) { - char c1 = stmt.charAt(++offset); - if ((c1 == 'H' || c1 == 'h')) { - return checkChar(stmt, offset); - } - if ((c1 == 'O' || c1 == 'o')) { - return checkCollation(stmt, offset); - } else { - return checkSystemVariables(stmt); - } - } - return checkSystemVariables(stmt); - } - - // SET Collation_connection - private static int checkCollation(String stmt, int offset) { - if (stmt.substring(offset).toLowerCase().startsWith("ollation_connection")) { - return checkEqualFormat(stmt, offset + 19, COLLATION_CONNECTION); - } - return checkSystemVariables(stmt); - } - - // SET CHAR - private static int checkChar(String stmt, int offset) { - if (stmt.length() > offset + 3) { - char c3 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - if ((c3 == 'A' || c3 == 'a') && (c2 == 'R' || c2 == 'r')) { - switch (c4) { - case 'a': - case 'A': - return character(stmt, offset); - case 'S': - case 's': - return checkCharSet(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } else { - return checkSystemVariables(stmt); - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER - private static int character(String stmt, int offset) { - if (stmt.length() > offset + 5) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - if ((c1 == 'C' || c1 == 'c') && (c2 == 'T' || c2 == 't') && - (c3 == 'E' || c3 == 'e') && (c4 == 'R' || c4 == 'r')) { - switch (c5) { - case ' ': - case '\r': - case '\n': - case '\t': - return characterS(stmt, offset); - case '_': - return characterSetDetail(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER S - private static int characterS(String stmt, int offset) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'S': - case 's': - return checkCharSet(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - return checkSystemVariables(stmt); - } - - //SET {CHARACTER SET | CHARSET} _ - private static int checkCharSet(String stmt, int offset) { - if (stmt.length() > offset + 4) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'T' || c2 == 't') && ParseUtil.isSpace(c3)) { - if (stmt.indexOf(',', offset) >= 0) { - return MULTI_SET; - } else { - return (offset << 8) | CHARACTER_SET_NAME; - } - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER_SET_ - private static int characterSetDetail(String stmt, int offset) { - if (stmt.length() > offset + 5) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - if ((c1 == 'S' || c1 == 's') && (c2 == 'E' || c2 == 'e') && - (c3 == 'T' || c3 == 't') && (c4 == '_')) { - switch (c5) { - case 'R': - case 'r': - return characterSetResults(stmt, offset); - case 'C': - case 'c': - return characterSetC(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER_SET_RESULTS = - private static int characterSetResults(String stmt, int offset) { - if (stmt.length() > offset + 6) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'S' || c2 == 's') && (c3 == 'U' || c3 == 'u') && - (c4 == 'L' || c4 == 'l') && (c5 == 'T' || c5 == 't') && (c6 == 'S' || c6 == 's')) { - return checkEqualFormat(stmt, offset, CHARACTER_SET_RESULTS); - } - } - return checkSystemVariables(stmt); - } - - private static int checkEqualFormat(String stmt, int offset, int expectValue) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case '=': - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - default: - if (stmt.indexOf(',', offset) >= 0) { - return MULTI_SET; - } else { - return (offset << 8) | expectValue; - } - } - } - return checkSystemVariables(stmt); - default: - return checkSystemVariables(stmt); - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER_SET_C - private static int characterSetC(String stmt, int offset) { - if (stmt.length() > offset + 1) { - char c1 = stmt.charAt(++offset); - switch (c1) { - case 'o': - case 'O': - return characterSetConnection(stmt, offset); - case 'l': - case 'L': - return characterSetClient(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER_SET_CONNECTION = - private static int characterSetConnection(String stmt, int offset) { - if (stmt.length() > offset + 8) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - if ((c1 == 'N' || c1 == 'n') && (c2 == 'N' || c2 == 'n') && - (c3 == 'E' || c3 == 'e') && (c4 == 'C' || c4 == 'c') && - (c5 == 'T' || c5 == 't') && (c6 == 'I' || c6 == 'i') && - (c7 == 'O' || c7 == 'o') && (c8 == 'N' || c8 == 'n')) { - return checkEqualFormat(stmt, offset, CHARACTER_SET_CONNECTION); - } - } - return checkSystemVariables(stmt); - } - - // SET CHARACTER_SET_CLIENT = - private static int characterSetClient(String stmt, int offset) { - if (stmt.length() > offset + 4) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - if ((c1 == 'I' || c1 == 'i') && (c2 == 'E' || c2 == 'e') && - (c3 == 'N' || c3 == 'n') && (c4 == 'T' || c4 == 't')) { - return checkEqualFormat(stmt, offset, CHARACTER_SET_CLIENT); - } - } - return checkSystemVariables(stmt); - } - - //GLOBAL +space - private static int global(String stmt, int offset) { - if (stmt.length() > offset + 6) { - if (isGlobal(stmt, offset)) { - offset = offset + 5; - if (!ParseUtil.isSpace(stmt.charAt(++offset))) { - return SYNTAX_ERROR; // SE GLOBAL(NO WHITESPACE) - } - return GLOBAL; - } - } - return checkSystemVariables(stmt); - } - - //SESSION +space - private static int session(String stmt, int offset) { - if (stmt.length() > offset + 7) { - if (isSession(stmt, offset)) { - offset = offset + 6; - if (!ParseUtil.isSpace(stmt.charAt(++offset))) { - return checkSystemVariables(stmt); - } - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'T': - case 't': - return parseT(stmt, offset); - case 'A': - case 'a': - return autocommit(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - } - } - return checkSystemVariables(stmt); - } - - // set @@ - private static int parseAt(String stmt, int offset) { - if (stmt.length() <= offset + 2) { - return SYNTAX_ERROR; // SET @;||SET @X; - } - if (stmt.charAt(++offset) != '@') { - return checkUserVariables(stmt); - } - //System variables - switch (stmt.charAt(++offset)) { - case 'S': - case 's': - return sessionDot(stmt, offset); - case 'A': - case 'a': - return autocommit(stmt, offset); - case 'G': - case 'g': - return globalDot(stmt, offset); - case 'T': - case 't': - int res = parseAtT(stmt, offset); - if (res != SYNTAX_ERROR && res != SYSTEM_VARIABLES) { - res = TX_WITHOUT_KEYWORD; - } - return res; - default: - return checkSystemVariables(stmt); - } - } - - // SET @@SESSION. - private static int sessionDot(String stmt, int offset) { - if (stmt.length() > offset + 8) { - if (isSession(stmt, offset)) { - offset = offset + 6; - if (stmt.charAt(++offset) == '.') { - switch (stmt.charAt(++offset)) { - case 'T': - case 't': - return parseAtT(stmt, offset); - case 'A': - case 'a': - return autocommit(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } else { - return SYNTAX_ERROR; - } - } - } - return checkSystemVariables(stmt); - } - - // SET @@GLOBAL. - private static int globalDot(String stmt, int offset) { - if (stmt.length() > offset + 6) { - if (isGlobal(stmt, offset)) { - offset = offset + 5; - if (stmt.charAt(++offset) == '.') { - return GLOBAL; - } else { - return SYNTAX_ERROR; - } - } - } - return checkSystemVariables(stmt); - } - - // @@session.tx_ || @@session.transaction_ || @@x_ || @@transaction_ - private static int parseAtT(String stmt, int offset) { - if (stmt.length() > offset + 1) { - switch (stmt.charAt(++offset)) { - case 'x': - case 'X': - return parseTx(stmt, offset); - case 'r': - case 'R': - return parseTransaction(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - return SYNTAX_ERROR; //SET @@[SESSION.]T - } - - private static int parseTransaction(String stmt, int offset) { - if (stmt.length() > offset + 10) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - char c9 = stmt.charAt(++offset); - char c10 = stmt.charAt(++offset); - if ((c1 == 'A' || c1 == 'a') && (c2 == 'N' || c2 == 'n') && - (c3 == 'S' || c3 == 's') && (c4 == 'A' || c4 == 'a') && (c5 == 'C' || c5 == 'c') && - (c6 == 'T' || c6 == 't') && (c7 == 'I' || c7 == 'i') && (c8 == 'O' || c8 == 'o') && - (c9 == 'N' || c9 == 'n') && (c10 == '_')) { - return parseTxContent(stmt, offset); - } - } - return checkSystemVariables(stmt); - } - - private static int parseTx(String stmt, int offset) { - if (stmt.length() > offset + 1) { - if ((stmt.charAt(++offset) == '_')) { - return parseTxContent(stmt, offset); - } - } - return checkSystemVariables(stmt); - } - - private static int parseTxContent(String stmt, int offset) { - if (stmt.length() > offset + 1) { - switch (stmt.charAt(++offset)) { - case 'i': - case 'I': - return checkIsolationVariables(stmt, offset); - case 'r': - case 'R': - return checkReadOnlyVariables(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - return SYNTAX_ERROR; - } - - private static int checkReadOnlyVariables(String stmt, int offset) { - if (stmt.length() > offset + 8) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'A' || c2 == 'a') && (c3 == 'D' || c3 == 'd') && - (c4 == '_') && (c5 == 'O' || c5 == 'o') && isOnly(stmt, offset)) { - offset = offset + 3; - return checkSwitchForExpect(stmt, offset, TX_READ_ONLY, TX_READ_WRITE); - } - } - return checkSystemVariables(stmt); - } - - private static int checkIsolationVariables(String stmt, int offset) { - if (stmt.length() > offset + 8 && isIsolation(stmt, offset)) { - offset = offset + 8; - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case '=': - return parserIsolationValue(stmt, offset); - default: - return SYNTAX_ERROR; - } - } - } - return checkSystemVariables(stmt); - } - - private static int parserIsolationValue(String stmt, int offset) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case '\'': - case '`': - return parserLevel(stmt, offset + 1, true, stmt.charAt(offset)); - case 'S': - case 's': - return serializable(stmt, offset, false, ' '); - default: - return SYNTAX_ERROR; - } - } - return SYNTAX_ERROR; - } - - private static int parseT(String stmt, int offset) { - if (stmt.length() > offset + 1) { - switch (stmt.charAt(++offset)) { - case 'x': - case 'X': - return parseTx(stmt, offset); - case 'r': - case 'R': - return transaction(stmt, offset); - default: - return checkSystemVariables(stmt); - } - } - return SYNTAX_ERROR; //SET @@[SESSION.]T - } - // SET [SESSION] TRANSACTION ISOLATION LEVEL||SET [SESSION] TRANSACTION_ISOLATION = - private static int transaction(String stmt, int offset) { - if (stmt.length() > offset + 11) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - char c9 = stmt.charAt(++offset); - if ((c1 == 'A' || c1 == 'a') && (c2 == 'N' || c2 == 'n') && - (c3 == 'S' || c3 == 's') && (c4 == 'A' || c4 == 'a') && (c5 == 'C' || c5 == 'c') && - (c6 == 'T' || c6 == 't') && (c7 == 'I' || c7 == 'i') && (c8 == 'O' || c8 == 'o') && - (c9 == 'N' || c9 == 'n')) { - char flag = stmt.charAt(++offset); - boolean horizontal; - if (ParseUtil.isSpace(flag)) { - horizontal = false; - } else if (flag == '_') { - horizontal = true; - } else { - return checkSystemVariables(stmt); - } - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'I': - case 'i': - if (horizontal) { - return checkIsolationVariables(stmt, offset); - } - return isolation(stmt, offset); - case 'R': - case 'r': - return readOnlyOrWrite(stmt, offset, horizontal); - default: - return SYNTAX_ERROR; - } - } - } - } - return checkSystemVariables(stmt); - } - - // SET SESSION TRANSACTION ISOLATION , if child check failed ,return SYNTAX_ERROR - private static int isolation(String stmt, int offset) { - if (stmt.length() > offset + 9) { - if (isIsolation(stmt, offset)) { - offset = offset + 8; - if (!ParseUtil.isSpace(stmt.charAt(++offset))) { - return checkSystemVariables(stmt); - } - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'L': - case 'l': - return level(stmt, offset); - default: - return SYNTAX_ERROR; - } - } - } - } - return SYNTAX_ERROR; - } - - // SET SESSION TRANSACTION READ ONLY/WRITE - private static int readOnlyOrWrite(String stmt, int offset, boolean horizontal) { - if (stmt.length() > offset + 4) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'A' || c2 == 'a') && (c3 == 'D' || c3 == 'd')) { - char flag = stmt.charAt(++offset); - if ((horizontal && flag != '_') || (!horizontal && !ParseUtil.isSpace(flag))) { - return SYNTAX_ERROR; - } - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'O': - case 'o': - if (isOnly(stmt, offset)) { - if (horizontal) { - return checkSwitchForExpect(stmt, offset + 4, TX_READ_ONLY, TX_READ_WRITE); - } else if (!horizontal && ParseUtil.isEOF(stmt, offset + 4)) { - return TX_READ_ONLY; - } - } - return SYNTAX_ERROR; - case 'W': - case 'w': - if (horizontal) { - return SYNTAX_ERROR; - } - return isWrite(stmt, offset); - default: - return SYNTAX_ERROR; - } - } - } - } - return SYNTAX_ERROR; - } - - private static boolean isOnly(String stmt, int offset) { - if (stmt.length() > offset + 3) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - if ((c1 == 'N' || c1 == 'n') && (c2 == 'L' || c2 == 'l') && (c3 == 'Y' || c3 == 'y')) { - return true; - } - } - return false; - } - - private static int isWrite(String stmt, int offset) { - if (stmt.length() > offset + 3) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - if ((c1 == 'R' || c1 == 'r') && (c2 == 'I' || c2 == 'i') && (c3 == 'T' || c3 == 't') && (c4 == 'E' || c4 == 'e') && ParseUtil.isEOF(stmt, ++offset)) { - return TX_READ_WRITE; - } - } - return SYNTAX_ERROR; - } - - // SET SESSION TRANSACTION ISOLATION LEVEL' ' - private static int level(String stmt, int offset) { - if (stmt.length() > offset + 5) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'V' || c2 == 'v') && (c3 == 'E' || c3 == 'e') && - (c4 == 'L' || c4 == 'l') && ParseUtil.isSpace(stmt.charAt(++offset))) { - while (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'r': - case 'R': - case 's': - case 'S': - stmt = stmt.toUpperCase(); - return parserLevel(stmt, offset, false, ' '); - default: - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL +OTHER SYNTAX - } - } - } - } - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION L +OTHER SYNTAX - } - - private static int parserLevel(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - switch (stmt.charAt(offset)) { - case 'R': - case 'r': - return rCheck(stmt, offset, checkApostrophe, apostrophe); - case 'S': - case 's': - return serializable(stmt, offset, checkApostrophe, apostrophe); - default: - return SYNTAX_ERROR; // Will not happen - } - } - - // SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE - private static int serializable(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > offset + 11) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - char c9 = stmt.charAt(++offset); - char c10 = stmt.charAt(++offset); - char c11 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'R' || c2 == 'r') && (c3 == 'I' || c3 == 'i') && - (c4 == 'A' || c4 == 'a') && (c5 == 'L' || c5 == 'l') && (c6 == 'I' || c6 == 'i') && - (c7 == 'Z' || c7 == 'z') && (c8 == 'A' || c8 == 'a') && (c9 == 'B' || c9 == 'b') && - (c10 == 'L' || c10 == 'l') && (c11 == 'E' || c11 == 'e')) { - if (checkApostrophe && stmt.charAt(++offset) != apostrophe) { - return SYNTAX_ERROR; - } - return parseValueForExpected(stmt, offset, TX_SERIALIZABLE); - } - } - return SYNTAX_ERROR; - } - - // READ' '|REPEATABLE - private static int rCheck(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case 'E': - case 'e': - return eCheck(stmt, offset, checkApostrophe, apostrophe); - default: - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL R +OTHER - } - } - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL R; - } - - // READ' '|REPEATABLE - private static int eCheck(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case 'A': - case 'a': - return aCheck(stmt, offset, checkApostrophe, apostrophe); - case 'P': - case 'p': - return pCheck(stmt, offset, checkApostrophe, apostrophe); - default: - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL RE +OTHER - } - } - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL RE; - } - - // READ' '||READ- - private static int aCheck(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if ((stmt.length() > offset + 2) && (stmt.charAt(++offset) == 'D' || stmt.charAt(offset) == 'd')) { - if (checkApostrophe) { - if (stmt.charAt(++offset) != '-') { - return SYNTAX_ERROR; - } - offset++; - } else if (!ParseUtil.isSpace(stmt.charAt(++offset))) { - return SYNTAX_ERROR; - } else { - boolean find = false; - while (!find && stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'C': - case 'c': - case 'U': - case 'u': - find = true; - break; - default: - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL READ +OTHER; - } - } - } - switch (stmt.charAt(offset)) { - case 'C': - case 'c': - return committed(stmt, offset, checkApostrophe, apostrophe); - case 'U': - case 'u': - return uncommitted(stmt, offset, checkApostrophe, apostrophe); - default: - return SYNTAX_ERROR; - } - } - return SYNTAX_ERROR; //SET SESSION TRANSACTION ISOLATION LEVEL REA +OTHER; - } - - // COMMITTED - private static int committed(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > offset + 8) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - if ((c1 == 'O' || c1 == 'o') && (c2 == 'M' || c2 == 'm') && (c3 == 'M' || c3 == 'm') && - (c4 == 'I' || c4 == 'i') && (c5 == 'T' || c5 == 't') && (c6 == 'T' || c6 == 't') && - (c7 == 'E' || c7 == 'e') && (c8 == 'D' || c8 == 'd')) { - if (checkApostrophe && stmt.charAt(++offset) != apostrophe) { - return SYNTAX_ERROR; - } - return parseValueForExpected(stmt, offset, TX_READ_COMMITTED); - } - } - return SYNTAX_ERROR; - } - - // UNCOMMITTED - private static int uncommitted(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > offset + 10) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - char c9 = stmt.charAt(++offset); - char c10 = stmt.charAt(++offset); - if ((c1 == 'N' || c1 == 'n') && (c2 == 'C' || c2 == 'c') && (c3 == 'O' || c3 == 'o') && - (c4 == 'M' || c4 == 'm') && (c5 == 'M' || c5 == 'm') && (c6 == 'I' || c6 == 'i') && - (c7 == 'T' || c7 == 't') && (c8 == 'T' || c8 == 't') && (c9 == 'E' || c9 == 'e') && - (c10 == 'D' || c10 == 'd')) { - if (checkApostrophe && stmt.charAt(++offset) != apostrophe) { - return SYNTAX_ERROR; - } - return parseValueForExpected(stmt, offset, TX_READ_UNCOMMITTED); - } - } - return SYNTAX_ERROR; - } - - // REPEATABLE - private static int pCheck(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > offset + 8) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'A' || c2 == 'a') && (c3 == 'T' || c3 == 't') && - (c4 == 'A' || c4 == 'a') && (c5 == 'B' || c5 == 'b') && (c6 == 'L' || c6 == 'l') && - (c7 == 'E' || c7 == 'e')) { - if (checkApostrophe) { - if (stmt.charAt(++offset) != '-') { - return SYNTAX_ERROR; - } - offset++; - } else if (!ParseUtil.isSpace(stmt.charAt(++offset))) { - return SYNTAX_ERROR; - } else { - boolean find = false; - while (!find && stmt.length() > ++offset) { - switch (stmt.charAt(offset)) { - case ' ': - case '\r': - case '\n': - case '\t': - continue; - case 'R': - case 'r': - find = true; - break; - default: - return SYNTAX_ERROR; - } - } - } - switch (stmt.charAt(offset)) { - case 'R': - case 'r': - return prCheck(stmt, offset, checkApostrophe, apostrophe); - default: - return SYNTAX_ERROR; - } - } - } - return SYNTAX_ERROR; - } - - // READ - private static int prCheck(String stmt, int offset, boolean checkApostrophe, char apostrophe) { - if (stmt.length() > offset + 3) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - if ((c1 == 'E' || c1 == 'e') && (c2 == 'A' || c2 == 'a') && (c3 == 'D' || c3 == 'd')) { - if (checkApostrophe && stmt.charAt(++offset) != apostrophe) { - return SYNTAX_ERROR; - } - return parseValueForExpected(stmt, offset, TX_REPEATED_READ); - } - } - return SYNTAX_ERROR; - } - - private static boolean isIsolation(String stmt, int offset) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - char c7 = stmt.charAt(++offset); - char c8 = stmt.charAt(++offset); - return (c1 == 'S' || c1 == 's') && (c2 == 'O' || c2 == 'o') && (c3 == 'L' || c3 == 'l') && (c4 == 'A' || c4 == 'a') && - (c5 == 'T' || c5 == 't') && (c6 == 'I' || c6 == 'i') && (c7 == 'O' || c7 == 'o') && - (c8 == 'N' || c8 == 'n'); - } - - private static boolean isSession(String stmt, int offset) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - char c6 = stmt.charAt(++offset); - return (c1 == 'E' || c1 == 'e') && (c2 == 'S' || c2 == 's') && (c3 == 'S' || c3 == 's') && (c4 == 'I' || c4 == 'i') && - (c5 == 'O' || c5 == 'o') && (c6 == 'N' || c6 == 'n'); - } - - private static boolean isGlobal(String stmt, int offset) { - char c1 = stmt.charAt(++offset); - char c2 = stmt.charAt(++offset); - char c3 = stmt.charAt(++offset); - char c4 = stmt.charAt(++offset); - char c5 = stmt.charAt(++offset); - return (c1 == 'L' || c1 == 'l') && (c2 == 'O' || c2 == 'o') && (c3 == 'B' || c3 == 'b') && (c4 == 'A' || c4 == 'a') && - (c5 == 'L' || c5 == 'l'); - } - - private static int checkSystemVariables(String stmt) { - //TODO: - return OTHER; - } - - private static int checkUserVariables(String stmt) { - //TODO: - return OTHER; - } -} diff --git a/src/main/java/com/actiontech/dble/sqlengine/SQLJob.java b/src/main/java/com/actiontech/dble/sqlengine/SQLJob.java index 3a9b70c4ea..5eeabe09ff 100644 --- a/src/main/java/com/actiontech/dble/sqlengine/SQLJob.java +++ b/src/main/java/com/actiontech/dble/sqlengine/SQLJob.java @@ -36,14 +36,12 @@ public class SQLJob implements ResponseHandler, Runnable { private BackendConnection connection; private final SQLJobHandler jobHandler; private final PhysicalDatasource ds; - private final int id; private volatile boolean finished; public SQLJob(String sql, String databaseName, SQLJobHandler jobHandler, PhysicalDatasource ds) { super(); - this.id = 0; this.sql = sql; this.dataNodeOrDatabase = databaseName; this.jobHandler = jobHandler; @@ -132,7 +130,7 @@ public void errorResponse(byte[] err, BackendConnection conn) { @Override public void okResponse(byte[] ok, BackendConnection conn) { - if (conn.syncAndExcute()) { + if (conn.syncAndExecute()) { conn.release(); doFinished(false); } @@ -170,14 +168,9 @@ public void writeQueueAvailable() { public void connectionClose(BackendConnection conn, String reason) { doFinished(true); } - - public int getId() { - return id; - } - @Override public String toString() { - return "SQLJob [ id=" + id + ",dataNodeOrDatabase=" + + return "SQLJob [dataNodeOrDatabase=" + dataNodeOrDatabase + ",sql=" + sql + ", jobHandler=" + jobHandler + "]"; } diff --git a/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java b/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java new file mode 100644 index 0000000000..ce11019338 --- /dev/null +++ b/src/main/java/com/actiontech/dble/sqlengine/SetTestJob.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2016-2017 ActionTech. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ + +package com.actiontech.dble.sqlengine; + +import com.actiontech.dble.DbleServer; +import com.actiontech.dble.backend.BackendConnection; +import com.actiontech.dble.backend.datasource.PhysicalDBPool; +import com.actiontech.dble.backend.mysql.nio.MySQLConnection; +import com.actiontech.dble.backend.mysql.nio.handler.ResetConnHandler; +import com.actiontech.dble.backend.mysql.nio.handler.ResponseHandler; +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.server.ServerConnection; +import com.actiontech.dble.server.util.SchemaUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +public class SetTestJob implements ResponseHandler, Runnable { + public static final Logger LOGGER = LoggerFactory.getLogger(SQLJob.class); + + private final String sql; + private final String dataNodeOrDatabase; + private final SQLJobHandler jobHandler; + private final ServerConnection sc; + + public SetTestJob(String sql, SQLJobHandler jobHandler, ServerConnection sc) { + super(); + this.sql = sql; + String schema = sc.getSchema(); + if (schema == null) { + schema = SchemaUtil.getRandomDb(); + } + this.dataNodeOrDatabase = schema; + this.jobHandler = jobHandler; + this.sc = sc; + } + + public void run() { + try { + Map dataHosts = DbleServer.getInstance().getConfig().getDataHosts(); + for (PhysicalDBPool dn : dataHosts.values()) { + dn.getSource().getConnection(dataNodeOrDatabase, true, this, null); + break; + } + } catch (Exception e) { + String reason = "can't get backend connection for sql :" + sql; + LOGGER.warn(reason, e); + sc.close(reason); + } + } + + @Override + public void connectionAcquired(final BackendConnection conn) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("con query sql:" + sql + " to con:" + conn); + } + conn.setResponseHandler(this); + ((MySQLConnection) conn).sendQueryCmd(sql, sc.getCharset()); + } + + private void doFinished(boolean failed) { + jobHandler.finished(dataNodeOrDatabase, failed); + } + + @Override + public void connectionError(Throwable e, BackendConnection conn) { + String reason = "can't get backend connection for sql :" + sql; + LOGGER.warn(reason); + sc.close(reason); + } + + @Override + public void connectionClose(BackendConnection conn, String reason) { + LOGGER.warn("connectionClose sql :" + sql); + sc.close(reason); + } + + @Override + public void errorResponse(byte[] err, BackendConnection conn) { + ErrorPacket errPg = new ErrorPacket(); + errPg.read(err); + doFinished(true); + conn.release(); //conn context not change + sc.writeErrMessage(errPg.getErrno(), new String(errPg.getMessage())); + } + + @Override + public void okResponse(byte[] ok, BackendConnection conn) { + doFinished(false); + sc.write(ok); + ResetConnHandler handler = new ResetConnHandler(); + conn.setResponseHandler(handler); + MySQLConnection connection = (MySQLConnection) conn; + connection.write(connection.writeToBuffer(ResetConnectionPacket.RESET, connection.allocate())); + } + + @Override + public void fieldEofResponse(byte[] header, List fields, List fieldPackets, byte[] eof, + boolean isLeft, BackendConnection conn) { + //will not happen + + } + + @Override + public boolean rowResponse(byte[] row, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) { + //will not happen + return false; + } + + @Override + public void rowEofResponse(byte[] eof, boolean isLeft, BackendConnection conn) { + //will not happen + } + + @Override + public void writeQueueAvailable() { + } + + @Override + public String toString() { + return "SQLJob [dataNodeOrDatabase=" + + dataNodeOrDatabase + ",sql=" + sql + ", jobHandler=" + + jobHandler + "]"; + } + + @Override + public void relayPacketResponse(byte[] relayPacket, BackendConnection conn) { + } + + @Override + public void endPacketResponse(byte[] endPacket, BackendConnection conn) { + } +} diff --git a/src/main/java/com/actiontech/dble/util/SetIgnoreUtil.java b/src/main/java/com/actiontech/dble/util/SetIgnoreUtil.java deleted file mode 100644 index 9cf90c09fa..0000000000 --- a/src/main/java/com/actiontech/dble/util/SetIgnoreUtil.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2016-2017 ActionTech. - * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. - */ - -package com.actiontech.dble.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * SetIgnoreUtil - *

- * PHP user use multi SET - * - * @author zhuam - */ -public final class SetIgnoreUtil { - private SetIgnoreUtil() { - } - - private static List ptrnIgnoreList = new ArrayList<>(); - - static { - - //TODO: ignore SET - String[] ignores = new String[]{ - "(?i)set (sql_mode)", - "(?i)set (interactive_timeout|wait_timeout|net_read_timeout|net_write_timeout|lock_wait_timeout|slave_net_timeout)", - "(?i)set (connect_timeout|delayed_insert_timeout|innodb_lock_wait_timeout|innodb_rollback_on_timeout)", - "(?i)set (profiling|profiling_history_size)", - "(?i)set (sql_safe_updates)", - }; - - for (String ignore : ignores) { - ptrnIgnoreList.add(Pattern.compile(ignore)); - } - } - - public static boolean isIgnoreStmt(String stmt) { - boolean ignore = false; - Matcher matcherIgnore; - for (Pattern ptrnIgnore : ptrnIgnoreList) { - matcherIgnore = ptrnIgnore.matcher(stmt); - if (matcherIgnore.find()) { - ignore = true; - break; - } - } - return ignore; - } - -} diff --git a/src/test/java/com/actiontech/dble/parser/ServerParseTest.java b/src/test/java/com/actiontech/dble/parser/ServerParseTest.java index b0e8248948..2b3941b0b0 100644 --- a/src/test/java/com/actiontech/dble/parser/ServerParseTest.java +++ b/src/test/java/com/actiontech/dble/parser/ServerParseTest.java @@ -6,7 +6,7 @@ package com.actiontech.dble.parser; import com.actiontech.dble.server.parser.ServerParse; -import junit.framework.Assert; +import org.junit.Assert; import org.junit.Test; public class ServerParseTest { @@ -201,8 +201,6 @@ public void testBegin() { public void testCommit() { String sql = "COMMIT 'nihao'"; int result = ServerParse.parse(sql); - int sqlType = result & 0xff; - Assert.assertEquals(ServerParse.COMMIT, sqlType); + Assert.assertEquals(ServerParse.OTHER, result); } - } diff --git a/src/test/java/com/actiontech/dble/parser/ServerParserTest.java b/src/test/java/com/actiontech/dble/parser/ServerParserTest.java index 69a85a7657..b87c40a8d0 100644 --- a/src/test/java/com/actiontech/dble/parser/ServerParserTest.java +++ b/src/test/java/com/actiontech/dble/parser/ServerParserTest.java @@ -5,7 +5,10 @@ */ package com.actiontech.dble.parser; -import com.actiontech.dble.server.parser.*; +import com.actiontech.dble.server.parser.ServerParse; +import com.actiontech.dble.server.parser.ServerParseSelect; +import com.actiontech.dble.server.parser.ServerParseShow; +import com.actiontech.dble.server.parser.ServerParseStart; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -133,108 +136,6 @@ public void testIsShowOther() { Assert.assertEquals(ServerParseShow.OTHER, ServerParseShow.parse("SHOW ... ", 4)); } - @Test - public void testIsSetAutocommitOn() { - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set autocommit=1", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set autoCOMMIT = 1", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("SET AUTOCOMMIT=on", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set autoCOMMIT = ON", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set @@autocommit=1", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set @@autoCOMMIT = 1", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("SET @@AUTOCOMMIT=on", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set @@autoCOMMIT = ON", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set @@session.autocommit=1", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set @@session.autoCOMMIT = 1", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("SET @@SESSION.AUTOCOMMIT=on", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set @@session.autoCOMMIT = ON", 3)); - } - - @Test - public void testIsSetAutocommitOff() { - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set autocommit=0", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("SET AUTOCOMMIT= 0", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set autoCOMMIT =OFF", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set autoCOMMIT = off", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set @@autocommit=0", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set @@autoCOMMIT = 0", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("SET @@AUTOCOMMIT=oFF", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set @@autoCOMMIT = OFF", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set @@session.autocommit=0", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set @@session.autoCOMMIT = 0", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("SET @@SESSION.AUTOCOMMIT=off", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set @@session.autoCOMMIT = OFF", 3)); - } - - @Test - public void testIsSetAutocommit() { - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set autocommit = 0;", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set autocommit=0;", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set autocommit=1;", 3)); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, ServerParseSet.parse("set autocommit=10;", 3)); - //diff from mysql - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, ServerParseSet.parse("set autocommit=01;", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_ON, ServerParseSet.parse("set autocommit=ON;", 3)); - Assert.assertEquals(ServerParseSet.AUTOCOMMIT_OFF, ServerParseSet.parse("set autocommit=OFF;", 3)); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, ServerParseSet.parse("set autocommit=ON2;", 3)); - } - - @Test - public void testIsSetDouble() { - //not supported - Assert.assertEquals(ServerParseSet.MULTI_SET, ServerParseSet.parse("set @@autocommit=0,@@session.TX_ISOLATION = 'READ-UNCOMMITTED'", 3)); - } - - @Test - public void testIsSetNames() { - Assert.assertEquals(ServerParseSet.NAMES, 0xff & ServerParseSet.parse("set names utf8", 3)); - Assert.assertEquals(ServerParseSet.NAMES, 0xff & ServerParseSet.parse("SET NAMES UTF8", 3)); - Assert.assertEquals(ServerParseSet.NAMES, 0xff & ServerParseSet.parse("set NAMES utf8", 3)); - Assert.assertEquals(ServerParseSet.NAMES, 0xff & ServerParseSet.parse("SET NAMES 'utf8' COLLATE 'utf8_general_ci';", 3)); - Assert.assertEquals(ServerParseSet.NAMES, 0xff & ServerParseSet.parse("SET NAMES 'utf8' COLLATE DEFAULT;", 3)); - Assert.assertEquals(ServerParseSet.NAMES, 0xff & ServerParseSet.parse("SET NAMES DEFAULT COLLATE DEFAULT;", 3)); - - } - - @Test - public void testIsCharacterSetResults() { - Assert.assertEquals(ServerParseSet.CHARACTER_SET_RESULTS, - 0xff & ServerParseSet.parse("SET character_set_results = NULL", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_RESULTS, - 0xff & ServerParseSet.parse("SET CHARACTER_SET_RESULTS= NULL", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_RESULTS, - 0xff & ServerParseSet.parse("Set chARActer_SET_RESults = NULL", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_CONNECTION, - 0xff & ServerParseSet.parse("Set chARActer_SET_Connection = NULL", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_CLIENT, - 0xff & ServerParseSet.parse("Set chARActer_SET_client = NULL", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_CLIENT, - 0xff & ServerParseSet.parse("Set chARActer_SET_client = NULL", 3)); - Assert.assertEquals(ServerParseSet.COLLATION_CONNECTION, - 0xff & ServerParseSet.parse("set collation_connection = gbk_bin;", 3)); - } - @Test - public void testIsCharacterSet() { - Assert.assertEquals(ServerParseSet.OTHER, - ServerParseSet.parse("set CHARACTER", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_NAME, - 0xff & ServerParseSet.parse("set CHARACTER SET utf8", 3)); - Assert.assertEquals(ServerParseSet.OTHER, - ServerParseSet.parse("set CHARSET", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_NAME, - 0xff & ServerParseSet.parse("set CHARSET utf8", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_NAME, - 0xff & ServerParseSet.parse("set CHARSET 'utf8'", 3)); - Assert.assertEquals(ServerParseSet.CHARACTER_SET_NAME, - 0xff & ServerParseSet.parse("set CHARSET DEFAULT", 3)); - } - - @Test - public void testIsSetOther() { - Assert.assertEquals(ServerParseSet.OTHER, ServerParseSet.parse("set ...", 3)); - Assert.assertEquals(ServerParseSet.OTHER, ServerParseSet.parse("SET ...", 3)); - Assert.assertEquals(ServerParseSet.OTHER, ServerParseSet.parse("sEt ...", 3)); - } - @Test public void testIsKill() { Assert.assertEquals(ServerParse.KILL, 0xff & ServerParse.parse(" kill ...")); @@ -300,122 +201,6 @@ public void testIsSelectUser() { Assert.assertEquals(ServerParseSelect.USER, ServerParseSelect.parse("SELECT USER()", 6)); Assert.assertEquals(ServerParseSelect.USER, ServerParseSelect.parse(" selECT USER() ", 7)); } - @Test - public void testTxReadOnly() { - Assert.assertEquals(ServerParseSet.TX_READ_WRITE, - ServerParseSet.parse(" SET SESSION TRANSACTION READ write ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET SESSION TRANSACTION READ ONLY ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" SET TRANSACTION READ ONLY ", " SET".length())); - Assert.assertEquals(ServerParseSet.GLOBAL, - ServerParseSet.parse(" SET GLOBAL TRANSACTION READ ONLY ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET SESSION transaction_read_only =1; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET SESSION tx_read_only =1; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET @@SESSION.tx_read_only =1; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET @@SESSION.transaction_read_only =1; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET SESSION tx_read_only =on; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET @@SESSION.tx_read_only =on; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_ONLY, - ServerParseSet.parse(" SET @@SESSION.transaction_read_only =on; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" SET tx_read_only =1; ", " SET".length())); - } - @Test - public void testTxReadUncommitted() { - Assert.assertEquals(ServerParseSet.TX_READ_UNCOMMITTED, - ServerParseSet.parse(" SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_UNCOMMITTED, - ServerParseSet.parse(" set session transaction isolation level read uncommitted ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_UNCOMMITTED, - ServerParseSet.parse(" set session transaCTION ISOLATION LEvel read uncommitteD ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ", " SET".length())); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'UNCOMMITTED' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_UNCOMMITTED, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'READ-UNCOMMITTED' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_UNCOMMITTED, - ServerParseSet.parse(" set @@session.tx_isolation = 'read-uncommitted' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" set @@TX_ISOLATION = 'READ-UNCOMMITTED' ", " SET".length())); - } - - @Test - public void testTxReadCommitted() { - Assert.assertEquals(ServerParseSet.TX_READ_COMMITTED, - ServerParseSet.parse(" SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_COMMITTED, - ServerParseSet.parse(" set session transaction isolation level read committed ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_COMMITTED, - ServerParseSet.parse(" set session transaCTION ISOLATION LEVel read committed ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" SET TRANSACTION ISOLATION LEVEL READ COMMITTED ", " SET".length())); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'COMMITTED' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_COMMITTED, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'READ-COMMITTED' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_READ_COMMITTED, - ServerParseSet.parse(" set @@session.tx_isolation = 'read-committed' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" set @@TX_ISOLATION = 'READ-COMMITTED' ", " SET".length())); - } - - @Test - public void testTxRepeatedRead() { - Assert.assertEquals(ServerParseSet.TX_REPEATED_READ, - ServerParseSet.parse(" SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_REPEATED_READ, - ServerParseSet.parse(" set session transaction isolation level repeatable read ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_REPEATED_READ, - ServerParseSet.parse(" set session transaction isOLATION LEVEL REPEatable read ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" SET TRANSACTION ISOLATION LEVEL READ COMMITTED ", " SET".length())); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'REPEATABLE READ' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_REPEATED_READ, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'REPEATABLE-READ' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_REPEATED_READ, - ServerParseSet.parse(" set @@session.tx_isolation = 'repeatable-read' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" set @@TX_ISOLATION = 'REPEATABLE-READ' ", " SET".length())); - } - - @Test - public void testTxSerializable() { - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" SET SESSION transaction_isolation='SERIALIZABLE'; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" SET SESSION tx_isolation='SERIALIZABLE'; ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" set session transaction isolation level serializable ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" set session transaction isOLATION LEVEL SERIAlizable ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ", " SET".length())); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'SERIALIZABLE ' ", " SET".length())); - Assert.assertEquals(ServerParseSet.SYNTAX_ERROR, - ServerParseSet.parse(" set @@session.TX_ISOLATION = ' SERIALIZABLE' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" set @@session.TX_ISOLATION = SERIALIZABLE ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" set @@session.TX_ISOLATION = 'SERIALIZABLE' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" set @@session.tx_isolation = 'serializable' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_SERIALIZABLE, - ServerParseSet.parse(" set @@session.transaction_isolation = 'serializable' ", " SET".length())); - Assert.assertEquals(ServerParseSet.TX_WITHOUT_KEYWORD, - ServerParseSet.parse(" set @@TX_ISOLATION = 'SERIALIZABLE' ", " SET".length())); - } @Test public void testIdentity() { diff --git a/src/test/java/com/actiontech/dble/parser/ServerParserTestPerf.java b/src/test/java/com/actiontech/dble/parser/ServerParserTestPerf.java deleted file mode 100644 index 44463dc2bd..0000000000 --- a/src/test/java/com/actiontech/dble/parser/ServerParserTestPerf.java +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright (C) 2016-2017 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.parser; - -import com.actiontech.dble.server.parser.ServerParseSet; - -/** - * @author mycat - */ -public final class ServerParserTestPerf { - - private static void parseSetPerf() { - // ServerParse.parse("show databases"); - // ServerParseSet.parse("set autocommit=1"); - // ServerParseSet.parse("set names=1"); - ServerParseSet.parse("SET character_set_results = NULL", 4); - // ServerParse.parse("select id,name,value from t"); - // ServerParse.parse("select * from offer where member_id='abc'"); - } - - public static void main(String[] args) { - parseSetPerf(); - int count = 10000000; - - System.currentTimeMillis(); - long t1 = System.currentTimeMillis(); - for (int i = 0; i < count; i++) { - parseSetPerf(); - } - long t2 = System.currentTimeMillis(); - - // print time - System.out.println("take:" + ((t2 - t1) * 1000 * 1000) / count + " ns."); - } - -} \ No newline at end of file diff --git a/src/test/java/com/actiontech/dble/server/handler/ServerHandlerTest.java b/src/test/java/com/actiontech/dble/server/handler/ServerHandlerTest.java deleted file mode 100644 index 09e2d4bd34..0000000000 --- a/src/test/java/com/actiontech/dble/server/handler/ServerHandlerTest.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2016-2017 ActionTech. - * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. - */ - -package com.actiontech.dble.server.handler; - -public class ServerHandlerTest { - -} diff --git a/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java b/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java new file mode 100644 index 0000000000..8942438999 --- /dev/null +++ b/src/test/java/com/actiontech/dble/server/handler/SetHandlerTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016-2017 ActionTech. + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher. + */ + +package com.actiontech.dble.server.handler; + +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class SetHandlerTest { + + + @Test + public void testConvertCharsetKeyWord() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Method convertCharsetKeyWord = SetHandler.class.getDeclaredMethod("convertCharsetKeyWord", String.class); + convertCharsetKeyWord.setAccessible(true); + Assert.assertEquals("set character set utf8", convertCharsetKeyWord.invoke(null, "set charset utf8")); + Assert.assertEquals("SET character set UTF8", convertCharsetKeyWord.invoke(null, "SET CHARSET UTF8")); + 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")); + 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")); + } +} diff --git a/src/test/java/demo/test/Testparser.java b/src/test/java/demo/test/Testparser.java index 1753768064..db0d7bd4ff 100644 --- a/src/test/java/demo/test/Testparser.java +++ b/src/test/java/demo/test/Testparser.java @@ -25,8 +25,75 @@ public static void main(String args[]) { // obj.test("truncate table char_columns_test;"); String 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); + 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\";"; + 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;"; + obj.test(strSetSql); +// strSetSql = "set @@tx_read_only =0,names utf8,charset 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 charset utf8;"; +// 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;"; @@ -556,16 +623,28 @@ public void test(String sql) { System.out.println("change to 1->" + mySqlShowKeysStatement.toString()); System.out.println("change to 2->" + SQLUtils.toMySqlString(mySqlShowKeysStatement)); } else if (statement instanceof SQLSetStatement) { - SQLSetStatement mySqlSetStatement = (SQLSetStatement) statement; - for(SQLAssignItem assignItem:mySqlSetStatement.getItems()){ + SQLSetStatement setStatement = (SQLSetStatement) statement; + for(SQLAssignItem assignItem:setStatement.getItems()){ System.out.println("value is "+assignItem.getValue()+", class is "+assignItem.getValue().getClass()); if(assignItem.getTarget() instanceof SQLVariantRefExpr){ SQLVariantRefExpr target = (SQLVariantRefExpr)assignItem.getTarget(); System.out.println("target is " + target + ", global is " + target.isGlobal()); - }else { + }else if(assignItem.getTarget() instanceof SQLPropertyExpr){ + SQLPropertyExpr target = (SQLPropertyExpr)assignItem.getTarget(); + System.out.println("target is " + target.getName() + ", Owner is " + target.getOwner()); + } else { System.out.println("target is " + assignItem.getTarget() + ", class is " + assignItem.getTarget().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()); } diff --git a/version.txt b/version.txt index c8d4cc853c..2b9b829e56 100644 --- a/version.txt +++ b/version.txt @@ -1,5 +1,5 @@ -BuildTime 2017-09-04 14:05:32 -MavenVersion 2.17.08.0-dev +BuildTime 2017-09-22 05:14:11 +MavenVersion 2.17.08.0 GitUrl https://github.com/actiontech/dble WebSite http://dble.cloud/ QQGroup 669663113