mirror of
https://github.com/actiontech/dble.git
synced 2026-05-08 07:21:00 -05:00
Merge branch 'master' into issue-303
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
Reason:(Fixes #. or Improve #.)
|
||||
Type:
|
||||
Influences:
|
||||
@@ -45,6 +45,9 @@ Read the [Roadmap](./docs/ROADMAP.md).
|
||||
## Quick start
|
||||
Read the [Quick Start](./docs/QUICKSTART.md).
|
||||
|
||||
## Documentation
|
||||
+ [简体中文](https://github.com/actiontech/dble/wiki)
|
||||
+ English(Comming soon)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
+2
-1
@@ -4,7 +4,8 @@ Get package from https://github.com/actiontech/dble/releases
|
||||
|
||||
## 2.Prepare
|
||||
### 2.1 MySQL
|
||||
Make sure there is at least one MySQL Instance with url $url(e.g., localhost:3306) ,$user(e.g., test) and $password(e.g., testPsw) in your machine.
|
||||
Make sure there is at least one MySQL Instance with url $url(e.g., localhost:3306) ,$user(e.g., test) and $password(e.g., testPsw) in your machine.
|
||||
You also need to make sure that the url(localhost/127.0.0.1/other IP) can connect to MySQL, otherwise,you will get an error "NO ROUTE TO HOST" later. So Check your configurations of “/etc/hosts” ,“/etc/hosts.allow” ,“/etc/hosts.deny”
|
||||
Add 4 database ,the SQL as below:
|
||||
|
||||
```
|
||||
|
||||
@@ -47,16 +47,16 @@
|
||||
|
||||
<!-- subquery need to refactor -->
|
||||
<Match>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemSinglerowSubselect"/>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemScalarSubQuery"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemAllanySubselect"/>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemAllAnySubQuery"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemExistsSubselect"/>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemExistsSubQuery"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemMaxminSubselect"/>
|
||||
<Class name="com.actiontech.dble.plan.common.item.subquery.ItemMaxminSubQuery"/>
|
||||
</Match>
|
||||
<!-- subquery need to refactor end -->
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ import com.actiontech.dble.net.*;
|
||||
import com.actiontech.dble.route.RouteService;
|
||||
import com.actiontech.dble.route.sequence.handler.*;
|
||||
import com.actiontech.dble.server.ServerConnectionFactory;
|
||||
import com.actiontech.dble.server.variables.SysVarsExtractor;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.server.util.GlobalTableUtil;
|
||||
import com.actiontech.dble.sqlengine.OneRawSQLQueryResultHandler;
|
||||
import com.actiontech.dble.sqlengine.SQLJob;
|
||||
@@ -127,7 +129,7 @@ public final class DbleServer {
|
||||
this.isOnline = new AtomicBoolean(true);
|
||||
|
||||
//initialized the cache service
|
||||
cacheService = new CacheService(config.getSystem().isLowerCaseTableNames());
|
||||
cacheService = new CacheService(SystemVariables.getSysVars().isLowerCaseTableNames());
|
||||
|
||||
//initialized the router cache and primary cache
|
||||
routerService = new RouteService(cacheService);
|
||||
@@ -268,6 +270,27 @@ public final class DbleServer {
|
||||
SystemConfig.getHomePath();
|
||||
}
|
||||
|
||||
/* the function is only for Cyclomatic complexity of startup() */
|
||||
private void pullVarAndMeta() throws IOException {
|
||||
SysVarsExtractor extractor = new SysVarsExtractor(config);
|
||||
try {
|
||||
extractor.extract();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
this.config.reviseSchemas();
|
||||
|
||||
tmManager = new ProxyMetaManager();
|
||||
if (!this.getConfig().isDataHostWithoutWR()) {
|
||||
//init tmManager
|
||||
try {
|
||||
tmManager.init(this.getConfig());
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void startup() throws IOException {
|
||||
SystemConfig system = config.getSystem();
|
||||
|
||||
@@ -385,17 +408,7 @@ public final class DbleServer {
|
||||
txnLogProcessor.start();
|
||||
}
|
||||
|
||||
|
||||
tmManager = new ProxyMetaManager();
|
||||
if (!this.getConfig().isDataHostWithoutWR()) {
|
||||
//init tmManager
|
||||
try {
|
||||
tmManager.init(this.getConfig());
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
pullVarAndMeta();
|
||||
|
||||
//XA Init recovery Log
|
||||
LOGGER.info("===============================================");
|
||||
|
||||
@@ -18,8 +18,8 @@ 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.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
import com.actiontech.dble.util.TimeUtil;
|
||||
import com.actiontech.dble.util.exception.UnknownTxIsolationException;
|
||||
@@ -148,7 +148,7 @@ public class MySQLConnection extends BackendAIOConnection {
|
||||
this.txIsolation = -1;
|
||||
this.autocommit = true;
|
||||
//TODO:CHECK
|
||||
this.setCharacterSet(SystemVariables.getDefaultValue("character_set_server"));
|
||||
this.setCharacterSet(SystemVariables.getSysVars().getDefaultValue("character_set_server"));
|
||||
this.usrVariables.clear();
|
||||
this.sysVariables.clear();
|
||||
}
|
||||
@@ -238,7 +238,7 @@ public class MySQLConnection extends BackendAIOConnection {
|
||||
packet.setClientFlags(clientFlags);
|
||||
packet.setMaxPacketSize(maxPacketSize);
|
||||
//TODO:CHECK
|
||||
int charsetIndex = CharsetUtil.getCharsetDefaultIndex(SystemVariables.getDefaultValue("character_set_server"));
|
||||
int charsetIndex = CharsetUtil.getCharsetDefaultIndex(SystemVariables.getSysVars().getDefaultValue("character_set_server"));
|
||||
packet.setCharsetIndex(charsetIndex);
|
||||
|
||||
packet.setUser(user);
|
||||
@@ -428,7 +428,12 @@ public class MySQLConnection extends BackendAIOConnection {
|
||||
}
|
||||
//tmp now = backend -(backend &&frontend)
|
||||
for (Map.Entry<String, String> entry : tmpSysVars.entrySet()) {
|
||||
String value = SystemVariables.getDefaultValue(entry.getKey());
|
||||
String value = SystemVariables.getSysVars().getDefaultValue(entry.getKey());
|
||||
try {
|
||||
Long.parseLong(value);
|
||||
} catch (NumberFormatException e) {
|
||||
value = "`" + value + "`";
|
||||
}
|
||||
setVars.add(new Pair<>(entry.getKey(), value));
|
||||
toResetSys.add(entry.getKey());
|
||||
}
|
||||
|
||||
+13
-4
@@ -11,6 +11,7 @@ import com.actiontech.dble.net.mysql.RowDataPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -21,16 +22,19 @@ public class NewConnectionRespHandler implements ResponseHandler {
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
private Condition initiated = lock.newCondition();
|
||||
|
||||
public BackendConnection getBackConn() {
|
||||
public BackendConnection getBackConn() throws IOException {
|
||||
lock.lock();
|
||||
try {
|
||||
while (backConn == null) {
|
||||
if (backConn == null) {
|
||||
initiated.await();
|
||||
}
|
||||
if (backConn == null) {
|
||||
throw new IOException("get backend connection error ");
|
||||
}
|
||||
return backConn;
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.warn("getBackConn " + e);
|
||||
return null;
|
||||
throw new IOException(e.getMessage());
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@@ -39,7 +43,12 @@ public class NewConnectionRespHandler implements ResponseHandler {
|
||||
@Override
|
||||
public void connectionError(Throwable e, BackendConnection conn) {
|
||||
LOGGER.warn(conn + " connectionError " + e);
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
initiated.signal();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package com.actiontech.dble.backend.mysql.nio.handler;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.BackendConnection;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.HandlerTool;
|
||||
@@ -40,7 +40,7 @@ public class ShowTablesHandler extends SingleNodeHandler {
|
||||
this.info = info;
|
||||
ServerConnection source = session.getSource();
|
||||
String showSchema = info.getSchema();
|
||||
if (showSchema != null && DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (showSchema != null && SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
showSchema = showSchema.toLowerCase();
|
||||
}
|
||||
showTableSchema = showSchema == null ? source.getSchema() : showSchema;
|
||||
|
||||
+138
-3
@@ -11,16 +11,26 @@ import com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.*;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.groupby.DirectGroupByHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.groupby.OrderedGroupByHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.AllAnySubQueryHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.InSubQueryHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.SingleRowSubQueryHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.SubQueryHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.CallBackHandler;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.config.ServerConfig;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.config.model.TableConfig;
|
||||
import com.actiontech.dble.net.mysql.ErrorPacket;
|
||||
import com.actiontech.dble.plan.Order;
|
||||
import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.PlanNode.PlanNodeType;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemAllAnySubQuery;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemInSubQuery;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSingleRowSubQuery;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubQuery;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.node.QueryNode;
|
||||
import com.actiontech.dble.plan.node.TableNode;
|
||||
@@ -29,13 +39,21 @@ import com.actiontech.dble.route.RouteResultsetNode;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
import com.actiontech.dble.server.parser.ServerParse;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
abstract class BaseHandlerBuilder {
|
||||
public abstract class BaseHandlerBuilder {
|
||||
private static final Logger LOGGER = Logger.getLogger(BaseHandlerBuilder.class);
|
||||
private static AtomicLong sequenceId = new AtomicLong(0);
|
||||
protected NonBlockingSession session;
|
||||
protected HandlerBuilder hBuilder;
|
||||
@@ -53,11 +71,15 @@ abstract class BaseHandlerBuilder {
|
||||
/* it's no need to send maker if sql is just the same as the client origin query */
|
||||
protected boolean needSendMaker = true;
|
||||
|
||||
protected BaseHandlerBuilder(NonBlockingSession session, PlanNode node, HandlerBuilder hBuilder) {
|
||||
protected boolean isExplain = false;
|
||||
protected List<BaseHandlerBuilder> subQueryBuilderList = new ArrayList<>(1);
|
||||
|
||||
protected BaseHandlerBuilder(NonBlockingSession session, PlanNode node, HandlerBuilder hBuilder, boolean isExplain) {
|
||||
this.session = session;
|
||||
this.node = node;
|
||||
this.hBuilder = hBuilder;
|
||||
this.config = DbleServer.getInstance().getConfig();
|
||||
this.isExplain = isExplain;
|
||||
if (config.getSchemas().isEmpty())
|
||||
throw new MySQLOutPutException(ErrorCode.ER_QUERYHANDLER, "", "current router config is empty!");
|
||||
}
|
||||
@@ -66,6 +88,10 @@ abstract class BaseHandlerBuilder {
|
||||
return currentLast;
|
||||
}
|
||||
|
||||
public List<BaseHandlerBuilder> getSubQueryBuilderList() {
|
||||
return subQueryBuilderList;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a handler chain
|
||||
*/
|
||||
@@ -82,6 +108,7 @@ abstract class BaseHandlerBuilder {
|
||||
// the query can be send to some certain nodes .eg: ER tables, GLOBAL*NORMAL GLOBAL*ER
|
||||
mergeBuild();
|
||||
} else {
|
||||
handleSubQueries();
|
||||
//need to split to simple query
|
||||
preHandlers = buildPre();
|
||||
buildOwn();
|
||||
@@ -89,7 +116,7 @@ abstract class BaseHandlerBuilder {
|
||||
if (needCommon)
|
||||
buildCommon();
|
||||
if (needSendMaker) {
|
||||
// view subalias
|
||||
// view sub alias
|
||||
String tbAlias = node.getAlias();
|
||||
if (node.getParent() != null && node.getParent().getSubAlias() != null)
|
||||
tbAlias = node.getParent().getSubAlias();
|
||||
@@ -116,6 +143,8 @@ abstract class BaseHandlerBuilder {
|
||||
//
|
||||
}
|
||||
|
||||
protected abstract void handleSubQueries();
|
||||
|
||||
protected abstract List<DMLResponseHandler> buildPre();
|
||||
|
||||
/**
|
||||
@@ -396,4 +425,110 @@ abstract class BaseHandlerBuilder {
|
||||
return schemaConfig.getTables().get(table);
|
||||
}
|
||||
|
||||
protected void handleBlockingSubQuery() {
|
||||
if (node.getSubQueries().size() == 0) {
|
||||
return;
|
||||
}
|
||||
final ReentrantLock lock = new ReentrantLock();
|
||||
final Condition finishSubQuery = lock.newCondition();
|
||||
final AtomicBoolean finished = new AtomicBoolean(false);
|
||||
final AtomicInteger subNodes = new AtomicInteger(node.getSubQueries().size());
|
||||
final CopyOnWriteArrayList<ErrorPacket> errorPackets = new CopyOnWriteArrayList<>();
|
||||
for (ItemSubQuery itemSubQuery : node.getSubQueries()) {
|
||||
if (itemSubQuery instanceof ItemSingleRowSubQuery) {
|
||||
final SubQueryHandler tempHandler = new SingleRowSubQueryHandler(getSequenceId(), session, (ItemSingleRowSubQuery) itemSubQuery);
|
||||
if (isExplain) {
|
||||
handleSubQueryForExplain(lock, finishSubQuery, finished, subNodes, itemSubQuery.getPlanNode(), tempHandler);
|
||||
} else {
|
||||
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
|
||||
}
|
||||
} else if (itemSubQuery instanceof ItemInSubQuery) {
|
||||
final SubQueryHandler tempHandler = new InSubQueryHandler(getSequenceId(), session, (ItemInSubQuery) itemSubQuery);
|
||||
if (isExplain) {
|
||||
handleSubQueryForExplain(lock, finishSubQuery, finished, subNodes, itemSubQuery.getPlanNode(), tempHandler);
|
||||
} else {
|
||||
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
|
||||
}
|
||||
} else if (itemSubQuery instanceof ItemAllAnySubQuery) {
|
||||
final SubQueryHandler tempHandler = new AllAnySubQueryHandler(getSequenceId(), session, (ItemAllAnySubQuery) itemSubQuery);
|
||||
if (isExplain) {
|
||||
handleSubQueryForExplain(lock, finishSubQuery, finished, subNodes, itemSubQuery.getPlanNode(), tempHandler);
|
||||
} else {
|
||||
handleSubQuery(lock, finishSubQuery, finished, subNodes, errorPackets, itemSubQuery.getPlanNode(), tempHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
while (!finished.get()) {
|
||||
finishSubQuery.await();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.warn("execute ScalarSubQuery " + e);
|
||||
ErrorPacket errorPackage = new ErrorPacket();
|
||||
errorPackage.setErrNo(ErrorCode.ER_UNKNOWN_ERROR);
|
||||
String errorMsg = e.getMessage() == null ? e.toString() : e.getMessage();
|
||||
errorPackage.setMessage(errorMsg.getBytes(StandardCharsets.UTF_8));
|
||||
errorPackets.add(errorPackage);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
if (errorPackets.size() > 0) {
|
||||
throw new MySQLOutPutException(errorPackets.get(0).getErrNo(), "", new String(errorPackets.get(0).getMessage(), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSubQueryForExplain(final ReentrantLock lock, final Condition finishSubQuery, final AtomicBoolean finished,
|
||||
final AtomicInteger subNodes, final PlanNode planNode, final SubQueryHandler tempHandler) {
|
||||
tempHandler.setForExplain();
|
||||
BaseHandlerBuilder builder = hBuilder.getBuilder(session, planNode, true);
|
||||
DMLResponseHandler endHandler = builder.getEndHandler();
|
||||
endHandler.setNextHandler(tempHandler);
|
||||
this.getSubQueryBuilderList().add(builder);
|
||||
subQueryFinished(subNodes, lock, finished, finishSubQuery);
|
||||
return;
|
||||
}
|
||||
private void handleSubQuery(final ReentrantLock lock, final Condition finishSubQuery, final AtomicBoolean finished,
|
||||
final AtomicInteger subNodes, final CopyOnWriteArrayList<ErrorPacket> errorPackets, final PlanNode planNode, final SubQueryHandler tempHandler) {
|
||||
DbleServer.getInstance().getComplexQueryExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DMLResponseHandler endHandler = hBuilder.buildNode(session, planNode, false);
|
||||
endHandler.setNextHandler(tempHandler);
|
||||
CallBackHandler tempDone = new CallBackHandler() {
|
||||
@Override
|
||||
public void call() throws Exception {
|
||||
if (tempHandler.getErrorPacket() != null) {
|
||||
errorPackets.add(tempHandler.getErrorPacket());
|
||||
}
|
||||
subQueryFinished(subNodes, lock, finished, finishSubQuery);
|
||||
}
|
||||
};
|
||||
tempHandler.setTempDoneCallBack(tempDone);
|
||||
HandlerBuilder.startHandler(endHandler);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("execute ItemScalarSubQuery error", e);
|
||||
ErrorPacket errorPackage = new ErrorPacket();
|
||||
errorPackage.setErrNo(ErrorCode.ER_UNKNOWN_ERROR);
|
||||
String errorMsg = e.getMessage() == null ? e.toString() : e.getMessage();
|
||||
errorPackage.setMessage(errorMsg.getBytes(StandardCharsets.UTF_8));
|
||||
errorPackets.add(errorPackage);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void subQueryFinished(AtomicInteger subNodes, ReentrantLock lock, AtomicBoolean finished, Condition finishSubQuery) {
|
||||
if (subNodes.decrementAndGet() == 0) {
|
||||
lock.lock();
|
||||
try {
|
||||
finished.set(true);
|
||||
finishSubQuery.signal();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-10
@@ -54,15 +54,20 @@ public class HandlerBuilder {
|
||||
* @param planNode
|
||||
* @return
|
||||
*/
|
||||
public DMLResponseHandler buildNode(NonBlockingSession nonBlockingSession, PlanNode planNode) {
|
||||
BaseHandlerBuilder builder = createBuilder(nonBlockingSession, planNode);
|
||||
builder.build();
|
||||
public DMLResponseHandler buildNode(NonBlockingSession nonBlockingSession, PlanNode planNode, boolean isExplain) {
|
||||
BaseHandlerBuilder builder = getBuilder(nonBlockingSession, planNode, isExplain);
|
||||
return builder.getEndHandler();
|
||||
}
|
||||
|
||||
public BaseHandlerBuilder getBuilder(NonBlockingSession nonBlockingSession, PlanNode planNode, boolean isExplain) {
|
||||
BaseHandlerBuilder builder = createBuilder(nonBlockingSession, planNode, isExplain);
|
||||
builder.build();
|
||||
return builder;
|
||||
}
|
||||
|
||||
public void build(boolean hasNext) throws Exception {
|
||||
final long startTime = System.nanoTime();
|
||||
DMLResponseHandler endHandler = buildNode(session, node);
|
||||
DMLResponseHandler endHandler = buildNode(session, node, false);
|
||||
OutputHandler fh = new OutputHandler(BaseHandlerBuilder.getSequenceId(), session, hasNext);
|
||||
endHandler.setNextHandler(fh);
|
||||
HandlerBuilder.startHandler(fh);
|
||||
@@ -70,18 +75,18 @@ public class HandlerBuilder {
|
||||
logger.info("HandlerBuilder.build cost:" + (endTime - startTime));
|
||||
}
|
||||
|
||||
private BaseHandlerBuilder createBuilder(final NonBlockingSession nonBlockingSession, PlanNode planNode) {
|
||||
private BaseHandlerBuilder createBuilder(final NonBlockingSession nonBlockingSession, PlanNode planNode, boolean isExplain) {
|
||||
PlanNode.PlanNodeType i = planNode.type();
|
||||
if (i == PlanNode.PlanNodeType.TABLE) {
|
||||
return new TableNodeHandlerBuilder(nonBlockingSession, (TableNode) planNode, this);
|
||||
return new TableNodeHandlerBuilder(nonBlockingSession, (TableNode) planNode, this, isExplain);
|
||||
} else if (i == PlanNode.PlanNodeType.JOIN) {
|
||||
return new JoinNodeHandlerBuilder(nonBlockingSession, (JoinNode) planNode, this);
|
||||
return new JoinNodeHandlerBuilder(nonBlockingSession, (JoinNode) planNode, this, isExplain);
|
||||
} else if (i == PlanNode.PlanNodeType.MERGE) {
|
||||
return new MergeNodeHandlerBuilder(nonBlockingSession, (MergeNode) planNode, this);
|
||||
return new MergeNodeHandlerBuilder(nonBlockingSession, (MergeNode) planNode, this, isExplain);
|
||||
} else if (i == PlanNode.PlanNodeType.QUERY) {
|
||||
return new QueryNodeHandlerBuilder(nonBlockingSession, (QueryNode) planNode, this);
|
||||
return new QueryNodeHandlerBuilder(nonBlockingSession, (QueryNode) planNode, this, isExplain);
|
||||
} else if (i == PlanNode.PlanNodeType.NONAME) {
|
||||
return new NoNameNodeHandlerBuilder(nonBlockingSession, (NoNameNode) planNode, this);
|
||||
return new NoNameNodeHandlerBuilder(nonBlockingSession, (NoNameNode) planNode, this, isExplain);
|
||||
}
|
||||
throw new RuntimeException("not supported tree node type:" + planNode.type());
|
||||
}
|
||||
|
||||
+29
-3
@@ -29,11 +29,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.actiontech.dble.plan.optimizer.JoinStrategyProcessor.NEED_REPLACE;
|
||||
|
||||
class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
private JoinNode node;
|
||||
|
||||
protected JoinNodeHandlerBuilder(NonBlockingSession session, JoinNode node, HandlerBuilder hBuilder) {
|
||||
super(session, node, hBuilder);
|
||||
protected JoinNodeHandlerBuilder(NonBlockingSession session, JoinNode node, HandlerBuilder hBuilder, boolean isExplain) {
|
||||
super(session, node, hBuilder, isExplain);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@@ -42,6 +44,11 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
return PlanUtil.isGlobalOrER(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleSubQueries() {
|
||||
handleBlockingSubQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeBuild() {
|
||||
try {
|
||||
@@ -99,6 +106,11 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
HandlerBuilder.startHandler(bigLh);
|
||||
}
|
||||
};
|
||||
if (isExplain) {
|
||||
buildNestFiltersForExplain(tnBig, keyToPass);
|
||||
DMLResponseHandler bigLh = buildJoinChild(tnBig, !isLeftSmall);
|
||||
tempHandler.setCreatedHandler(bigLh);
|
||||
}
|
||||
tempHandler.setTempDoneCallBack(tempDone);
|
||||
|
||||
} else if (node.getStrategy() == JoinNode.Strategy.SORTMERGE) {
|
||||
@@ -114,7 +126,11 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
}
|
||||
|
||||
private DMLResponseHandler buildJoinChild(PlanNode child, boolean isLeft) {
|
||||
DMLResponseHandler endHandler = hBuilder.buildNode(session, child);
|
||||
BaseHandlerBuilder builder = hBuilder.getBuilder(session, child, isExplain);
|
||||
if (builder.getSubQueryBuilderList().size() > 0) {
|
||||
this.getSubQueryBuilderList().addAll(builder.getSubQueryBuilderList());
|
||||
}
|
||||
DMLResponseHandler endHandler = builder.getEndHandler();
|
||||
if (isLeft) {
|
||||
if (!node.isLeftOrderMatch()) {
|
||||
OrderByHandler oh = new OrderByHandler(getSequenceId(), session, node.getLeftJoinOnOrders());
|
||||
@@ -145,6 +161,16 @@ class JoinNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private void buildNestFiltersForExplain(PlanNode tnBig, Item keyToPass) {
|
||||
Item keyInBig = PlanUtil.pushDownItem(node, keyToPass);
|
||||
List<Item> strategyFilters = tnBig.getNestLoopFilters();
|
||||
List<Item> argList = new ArrayList<>();
|
||||
argList.add(keyInBig);
|
||||
argList.add(new ItemString(NEED_REPLACE));
|
||||
ItemFuncIn filter = new ItemFuncIn(argList, false);
|
||||
strategyFilters.add(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate filter for big table according to tmp(small) table's result
|
||||
*
|
||||
|
||||
+11
-3
@@ -18,16 +18,24 @@ import java.util.List;
|
||||
class MergeNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
private MergeNode node;
|
||||
|
||||
protected MergeNodeHandlerBuilder(NonBlockingSession session, MergeNode node, HandlerBuilder hBuilder) {
|
||||
super(session, node, hBuilder);
|
||||
protected MergeNodeHandlerBuilder(NonBlockingSession session, MergeNode node, HandlerBuilder hBuilder, boolean isExplain) {
|
||||
super(session, node, hBuilder, isExplain);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleSubQueries() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<DMLResponseHandler> buildPre() {
|
||||
List<DMLResponseHandler> pres = new ArrayList<>();
|
||||
for (PlanNode child : node.getChildren()) {
|
||||
DMLResponseHandler ch = hBuilder.buildNode(session, child);
|
||||
BaseHandlerBuilder builder = hBuilder.getBuilder(session, child, isExplain);
|
||||
if (builder.getSubQueryBuilderList().size() > 0) {
|
||||
this.getSubQueryBuilderList().addAll(builder.getSubQueryBuilderList());
|
||||
}
|
||||
DMLResponseHandler ch = builder.getEndHandler();
|
||||
pres.add(ch);
|
||||
}
|
||||
return pres;
|
||||
|
||||
+7
-2
@@ -25,13 +25,18 @@ import java.util.List;
|
||||
class NoNameNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
private NoNameNode node;
|
||||
|
||||
protected NoNameNodeHandlerBuilder(NonBlockingSession session, NoNameNode node, HandlerBuilder hBuilder) {
|
||||
super(session, node, hBuilder);
|
||||
protected NoNameNodeHandlerBuilder(NonBlockingSession session, NoNameNode node, HandlerBuilder hBuilder, boolean isExplain) {
|
||||
super(session, node, hBuilder, isExplain);
|
||||
this.node = node;
|
||||
this.needWhereHandler = false;
|
||||
this.needCommon = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleSubQueries() {
|
||||
handleBlockingSubQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DMLResponseHandler> buildPre() {
|
||||
return new ArrayList<>();
|
||||
|
||||
+11
-3
@@ -18,16 +18,24 @@ class QueryNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
private QueryNode node;
|
||||
|
||||
protected QueryNodeHandlerBuilder(NonBlockingSession session,
|
||||
QueryNode node, HandlerBuilder hBuilder) {
|
||||
super(session, node, hBuilder);
|
||||
QueryNode node, HandlerBuilder hBuilder, boolean isExplain) {
|
||||
super(session, node, hBuilder, isExplain);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleSubQueries() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DMLResponseHandler> buildPre() {
|
||||
List<DMLResponseHandler> pres = new ArrayList<>();
|
||||
PlanNode subNode = node.getChild();
|
||||
DMLResponseHandler subHandler = hBuilder.buildNode(session, subNode);
|
||||
BaseHandlerBuilder builder = hBuilder.getBuilder(session, subNode, isExplain);
|
||||
if (builder.getSubQueryBuilderList().size() > 0) {
|
||||
this.getSubQueryBuilderList().addAll(builder.getSubQueryBuilderList());
|
||||
}
|
||||
DMLResponseHandler subHandler = builder.getEndHandler();
|
||||
pres.add(subHandler);
|
||||
return pres;
|
||||
}
|
||||
|
||||
+8
-4
@@ -24,14 +24,19 @@ class TableNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
private TableNode node;
|
||||
private TableConfig tableConfig = null;
|
||||
|
||||
protected TableNodeHandlerBuilder(NonBlockingSession session, TableNode node, HandlerBuilder hBuilder) {
|
||||
super(session, node, hBuilder);
|
||||
protected TableNodeHandlerBuilder(NonBlockingSession session, TableNode node, HandlerBuilder hBuilder, boolean isExplain) {
|
||||
super(session, node, hBuilder, isExplain);
|
||||
this.node = node;
|
||||
this.canPushDown = !node.existUnPushDownGroup();
|
||||
this.needWhereHandler = false;
|
||||
this.tableConfig = getTableConfig(node.getSchema(), node.getTableName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleSubQueries() {
|
||||
handleBlockingSubQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DMLResponseHandler> buildPre() {
|
||||
return new ArrayList<>();
|
||||
@@ -47,7 +52,7 @@ class TableNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
this.needSendMaker = mergeBuilder.getNeedSendMakerFlag();
|
||||
buildMergeHandler(node, rrssArray);
|
||||
} catch (Exception e) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_QUERYHANDLER, "", "tablenode buildOwn exception!", e);
|
||||
throw new MySQLOutPutException(ErrorCode.ER_QUERYHANDLER, "", "table node buildOwn exception!", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,5 +95,4 @@ class TableNodeHandlerBuilder extends BaseHandlerBuilder {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_QUERYHANDLER, "", "", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-15
@@ -74,6 +74,8 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
buildHaving(query);
|
||||
buildOrderBy(query);
|
||||
buildLimit(query);
|
||||
} else {
|
||||
whereFilter = query.getWhereFilter();
|
||||
}
|
||||
|
||||
if (query.isSubQuery() && !parentIsQuery && !isTopQuery) {
|
||||
@@ -146,10 +148,9 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
if (!isTopQuery) {
|
||||
sqlBuilder.append(" ( ");
|
||||
}
|
||||
if (join.isSubQuery() || isTopQuery) {
|
||||
buildSelect(join);
|
||||
sqlBuilder.append(" from ");
|
||||
}
|
||||
|
||||
buildSelect(join);
|
||||
sqlBuilder.append(" from ");
|
||||
|
||||
PlanNode left = join.getLeftNode();
|
||||
MysqlVisitor leftVisitor = new GlobalVisitor(left, false);
|
||||
@@ -182,31 +183,27 @@ public class GlobalVisitor extends MysqlVisitor {
|
||||
}
|
||||
|
||||
if (join.getOtherJoinOnFilter() != null) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
if (!first) {
|
||||
joinOnFilterStr.append(" and ");
|
||||
}
|
||||
|
||||
joinOnFilterStr.append(join.getOtherJoinOnFilter());
|
||||
}
|
||||
sqlBuilder.append(joinOnFilterStr.toString());
|
||||
if (join.isSubQuery() || isTopQuery) {
|
||||
buildWhere(join);
|
||||
buildGroupBy(join);
|
||||
buildHaving(join);
|
||||
buildOrderBy(join);
|
||||
buildLimit(join);
|
||||
}
|
||||
buildWhere(join);
|
||||
buildGroupBy(join);
|
||||
buildHaving(join);
|
||||
buildOrderBy(join);
|
||||
buildLimit(join);
|
||||
|
||||
if (!isTopQuery) {
|
||||
sqlBuilder.append(" ) ");
|
||||
if (join.getAlias() != null)
|
||||
sqlBuilder.append(" ").append(join.getAlias()).append(" ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void buildSelect(PlanNode query) {
|
||||
sqlBuilder.append("select ");
|
||||
boolean hasDistinct = query.isDistinct();
|
||||
|
||||
+93
-2
@@ -9,11 +9,19 @@ import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.PlanNode.PlanNodeType;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.Item.ItemType;
|
||||
import com.actiontech.dble.plan.common.item.ItemInt;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncIn;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondAnd;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondOr;
|
||||
import com.actiontech.dble.plan.common.item.subquery.*;
|
||||
import com.actiontech.dble.plan.common.ptr.StringPtr;
|
||||
import com.actiontech.dble.plan.node.TableNode;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
import com.alibaba.druid.sql.ast.SQLHint;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -40,8 +48,7 @@ public abstract class MysqlVisitor {
|
||||
// tmp sql
|
||||
protected StringBuilder sqlBuilder;
|
||||
protected StringPtr replaceableWhere = new StringPtr("");
|
||||
|
||||
|
||||
protected Item whereFilter = null;
|
||||
public MysqlVisitor(PlanNode query, boolean isTopQuery) {
|
||||
this.query = query;
|
||||
this.isTopQuery = isTopQuery;
|
||||
@@ -89,6 +96,7 @@ public abstract class MysqlVisitor {
|
||||
String pdName = visitUnSelPushDownName(filter, false);
|
||||
whereBuilder.append(" where ").append(pdName);
|
||||
}
|
||||
|
||||
replaceableWhere.set(whereBuilder.toString());
|
||||
// refresh sqlbuilder
|
||||
sqlBuilder = replaceableSqlBuilder.getCurrentElement().getSb();
|
||||
@@ -108,8 +116,86 @@ public abstract class MysqlVisitor {
|
||||
*/
|
||||
protected abstract String visitPushDownNameSel(Item o);
|
||||
|
||||
private Item genBoolItem(boolean isTrue) {
|
||||
if (isTrue) {
|
||||
return new ItemFuncEqual(new ItemInt(1), new ItemInt(1));
|
||||
} else {
|
||||
return new ItemFuncEqual(new ItemInt(1), new ItemInt(0));
|
||||
}
|
||||
}
|
||||
|
||||
private Item rebuildSubQueryItem(Item item) {
|
||||
if (PlanUtil.isCmpFunc(item)) {
|
||||
Item res1 = rebuildBoolSubQuery(item, 0);
|
||||
if (res1 != null) {
|
||||
return res1;
|
||||
}
|
||||
Item res2 = rebuildBoolSubQuery(item, 1);
|
||||
if (res2 != null) {
|
||||
return res2;
|
||||
}
|
||||
} else if (item instanceof ItemInSubQuery) {
|
||||
ItemInSubQuery inSubItem = (ItemInSubQuery) item;
|
||||
if (inSubItem.getValue().size() == 0) {
|
||||
return genBoolItem(inSubItem.isNeg());
|
||||
} else {
|
||||
List<Item> args = new ArrayList<>(inSubItem.getValue().size() + 1);
|
||||
args.add(inSubItem.getLeftOperand());
|
||||
args.addAll(inSubItem.getValue());
|
||||
return new ItemFuncIn(args, inSubItem.isNeg());
|
||||
}
|
||||
} else if (item instanceof ItemExistsSubQuery) {
|
||||
ItemExistsSubQuery existsSubQuery = (ItemExistsSubQuery) item;
|
||||
Item result = existsSubQuery.getValue();
|
||||
if (result == null) {
|
||||
return genBoolItem(existsSubQuery.isNot());
|
||||
} else {
|
||||
return genBoolItem(!existsSubQuery.isNot());
|
||||
}
|
||||
} else if (item instanceof ItemCondAnd || item instanceof ItemCondOr) {
|
||||
for (int index = 0; index < item.getArgCount(); index++) {
|
||||
Item rebuildItem = rebuildSubQueryItem(item.arguments().get(index));
|
||||
item.arguments().set(index, rebuildItem);
|
||||
item.setItemName(null);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
private Item rebuildBoolSubQuery(Item item, int index) {
|
||||
Item arg = item.arguments().get(index);
|
||||
if (arg.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (arg instanceof ItemScalarSubQuery) {
|
||||
Item result = ((ItemScalarSubQuery) arg).getValue();
|
||||
if (result == null || result.getResultItem() == null) {
|
||||
return new ItemFuncEqual(new ItemInt(1), new ItemInt(0));
|
||||
}
|
||||
item.arguments().set(index, result.getResultItem());
|
||||
item.setItemName(null);
|
||||
} else if (arg instanceof ItemAllAnySubQuery) {
|
||||
ItemAllAnySubQuery allAnySubItem = (ItemAllAnySubQuery) arg;
|
||||
if (allAnySubItem.getValue().size() == 0) {
|
||||
return genBoolItem(allAnySubItem.isAll());
|
||||
} else if (allAnySubItem.getValue().size() == 1) {
|
||||
Item value = allAnySubItem.getValue().get(0);
|
||||
if (value == null) {
|
||||
return new ItemFuncEqual(new ItemInt(1), new ItemInt(0));
|
||||
}
|
||||
item.arguments().set(index, value.getResultItem());
|
||||
item.setItemName(null);
|
||||
} else {
|
||||
return genBoolItem(!allAnySubItem.isAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// pushDown's name of not in select list
|
||||
public final String visitUnSelPushDownName(Item item, boolean canUseAlias) {
|
||||
if (item.isWithSubQuery()) {
|
||||
item = rebuildSubQueryItem(item);
|
||||
}
|
||||
String selName = item.getItemName();
|
||||
if (item.type().equals(ItemType.FIELD_ITEM)) {
|
||||
selName = "`" + item.getTableName() + "`.`" + selName + "`";
|
||||
@@ -125,4 +211,9 @@ public abstract class MysqlVisitor {
|
||||
}
|
||||
return selName;
|
||||
}
|
||||
|
||||
public Item getWhereFilter() {
|
||||
return whereFilter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+83
-22
@@ -10,6 +10,7 @@ import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.node.NoNameNode;
|
||||
import com.actiontech.dble.plan.node.TableNode;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
@@ -44,6 +45,9 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
} else if (i == PlanNode.PlanNodeType.JOIN) {
|
||||
visit((JoinNode) query);
|
||||
|
||||
} else if (i == PlanNode.PlanNodeType.NONAME) {
|
||||
visit((NoNameNode) query);
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("not implement yet!");
|
||||
}
|
||||
@@ -54,6 +58,9 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
protected void visit(NoNameNode query) {
|
||||
buildSelect(query);
|
||||
}
|
||||
|
||||
protected void visit(TableNode query) {
|
||||
if (query.isSubQuery() && !isTopQuery) {
|
||||
@@ -112,29 +119,10 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
rightVisitor.visit();
|
||||
replaceableSqlBuilder.append(rightVisitor.getSql());
|
||||
sqlBuilder = replaceableSqlBuilder.getCurrentElement().getSb();
|
||||
StringBuilder joinOnFilterStr = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (int i = 0; i < join.getJoinFilter().size(); i++) {
|
||||
Item filter = join.getJoinFilter().get(i);
|
||||
if (first) {
|
||||
sqlBuilder.append(" on ");
|
||||
first = false;
|
||||
} else
|
||||
joinOnFilterStr.append(" and ");
|
||||
joinOnFilterStr.append(filter);
|
||||
}
|
||||
|
||||
if (join.getOtherJoinOnFilter() != null) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
joinOnFilterStr.append(" and ");
|
||||
}
|
||||
joinOnFilterStr.append(join.getOtherJoinOnFilter());
|
||||
}
|
||||
StringBuilder joinOnFilterStr = getJoinOn(join, leftVisitor, rightVisitor);
|
||||
sqlBuilder.append(joinOnFilterStr.toString());
|
||||
if (join.isSubQuery() || isTopQuery) {
|
||||
buildWhere(join);
|
||||
buildWhere(join, leftVisitor.getWhereFilter(), rightVisitor.getWhereFilter());
|
||||
buildGroupBy(join);
|
||||
// having may contains aggregate function, so it need to calc by middle-ware
|
||||
buildOrderBy(join);
|
||||
@@ -149,12 +137,85 @@ public class PushDownVisitor extends MysqlVisitor {
|
||||
|
||||
}
|
||||
|
||||
private StringBuilder getJoinOn(JoinNode join, MysqlVisitor leftVisitor, MysqlVisitor rightVisitor) {
|
||||
StringBuilder joinOnFilterStr = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (int i = 0; i < join.getJoinFilter().size(); i++) {
|
||||
Item filter = join.getJoinFilter().get(i);
|
||||
if (first) {
|
||||
sqlBuilder.append(" on ");
|
||||
first = false;
|
||||
} else
|
||||
joinOnFilterStr.append(" and ");
|
||||
joinOnFilterStr.append(filter);
|
||||
}
|
||||
|
||||
if (join.getOtherJoinOnFilter() != null) {
|
||||
if (!first) {
|
||||
joinOnFilterStr.append(" and ");
|
||||
}
|
||||
joinOnFilterStr.append(join.getOtherJoinOnFilter());
|
||||
}
|
||||
// is not left join
|
||||
if (leftVisitor.getWhereFilter() != null && !join.getLeftOuter()) {
|
||||
if (!first) {
|
||||
joinOnFilterStr.append(" and ");
|
||||
}
|
||||
joinOnFilterStr.append("(");
|
||||
joinOnFilterStr.append(leftVisitor.getWhereFilter());
|
||||
joinOnFilterStr.append(")");
|
||||
}
|
||||
// is not right join
|
||||
if (rightVisitor.getWhereFilter() != null && !join.getRightOuter()) {
|
||||
if (!first) {
|
||||
joinOnFilterStr.append(" and ");
|
||||
}
|
||||
joinOnFilterStr.append("(");
|
||||
joinOnFilterStr.append(rightVisitor.getWhereFilter());
|
||||
joinOnFilterStr.append(")");
|
||||
}
|
||||
return joinOnFilterStr;
|
||||
}
|
||||
|
||||
protected void buildWhere(JoinNode planNode, Item leftFilter, Item rightFilter) {
|
||||
if (!visited)
|
||||
replaceableSqlBuilder.getCurrentElement().setRepString(replaceableWhere);
|
||||
StringBuilder whereBuilder = new StringBuilder();
|
||||
Item filter = planNode.getWhereFilter();
|
||||
if (filter != null) {
|
||||
String pdName = visitUnSelPushDownName(filter, false);
|
||||
whereBuilder.append(" where ").append(pdName);
|
||||
} else {
|
||||
whereBuilder.append(" where 1=1 ");
|
||||
}
|
||||
// left join
|
||||
if (leftFilter != null && !planNode.getRightOuter() && planNode.getLeftOuter()) {
|
||||
String pdName = visitUnSelPushDownName(leftFilter, false);
|
||||
whereBuilder.append(" and (");
|
||||
whereBuilder.append(pdName);
|
||||
whereBuilder.append(")");
|
||||
}
|
||||
//right join
|
||||
if (rightFilter != null && !planNode.getLeftOuter() && planNode.getRightOuter()) {
|
||||
String pdName = visitUnSelPushDownName(rightFilter, false);
|
||||
whereBuilder.append(" and (");
|
||||
whereBuilder.append(pdName);
|
||||
whereBuilder.append(")");
|
||||
}
|
||||
replaceableWhere.set(whereBuilder.toString());
|
||||
// refresh sqlbuilder
|
||||
sqlBuilder = replaceableSqlBuilder.getCurrentElement().getSb();
|
||||
}
|
||||
protected void buildSelect(PlanNode query) {
|
||||
sqlBuilder.append("select ");
|
||||
List<Item> columns = query.getColumnsRefered();
|
||||
if (query.isDistinct()) {
|
||||
sqlBuilder.append("DISTINCT ");
|
||||
}
|
||||
List<Item> columns = query.getColumnsRefered();
|
||||
if (columns.size() == 0) {
|
||||
sqlBuilder.append("1");
|
||||
return;
|
||||
}
|
||||
for (Item col : columns) {
|
||||
if (existUnPushDownGroup && col.type().equals(Item.ItemType.SUM_FUNC_ITEM))
|
||||
continue;
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import java.util.Set;
|
||||
|
||||
public interface DMLResponseHandler extends ResponseHandler {
|
||||
enum HandlerType {
|
||||
DIRECT, TEMPTABLE, BASESEL, REFRESHFP, MERGE, JOIN, WHERE, GROUPBY, HAVING, ORDERBY, LIMIT, UNION, DISTINCT, SENDMAKER, FINAL
|
||||
DIRECT, TEMPTABLE, BASESEL, REFRESHFP, MERGE, JOIN, WHERE, GROUPBY, HAVING, ORDERBY, LIMIT, UNION, DISTINCT, SENDMAKER, FINAL, SCALAR_SUB_QUERY, IN_SUB_QUERY, ALL_ANY_SUB_QUERY
|
||||
}
|
||||
|
||||
HandlerType type();
|
||||
|
||||
+4
@@ -42,6 +42,10 @@ public abstract class OwnThreadDMLHandler extends BaseDMLHandler {
|
||||
}
|
||||
}
|
||||
|
||||
protected final void startEasyMerge() {
|
||||
ownJobFlag.compareAndSet(false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param objects
|
||||
*/
|
||||
|
||||
+1
-2
@@ -135,8 +135,7 @@ public class BaseSelectHandler extends BaseDMLHandler {
|
||||
public void connectionError(Throwable e, BackendConnection conn) {
|
||||
if (terminate.get())
|
||||
return;
|
||||
LOGGER.warn(
|
||||
conn.toString() + "|connectionError()|" + e.getMessage());
|
||||
LOGGER.warn(conn.toString() + "|connectionError()|" + e.getMessage());
|
||||
session.onQueryError(e.getMessage().getBytes());
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -109,7 +109,9 @@ public class MultiNodeMergeHandler extends OwnThreadDMLHandler {
|
||||
rowComparator = makeRowDataSorter((MySQLConnection) conn);
|
||||
nextHandler.fieldEofResponse(null, null, fieldPackets, null, this.isLeft, conn);
|
||||
}
|
||||
if (!isEasyMerge) {
|
||||
if (isEasyMerge) {
|
||||
startEasyMerge();
|
||||
} else {
|
||||
if (++reachedConCount == route.length) {
|
||||
startOwnThread();
|
||||
}
|
||||
|
||||
+5
@@ -172,6 +172,11 @@ public class TempTableHandler extends BaseDMLHandler {
|
||||
return maxPartSize;
|
||||
}
|
||||
|
||||
|
||||
public DMLResponseHandler getCreatedHandler() {
|
||||
return createdHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerType type() {
|
||||
return HandlerType.TEMPTABLE;
|
||||
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.query.impl.subquery;
|
||||
|
||||
import com.actiontech.dble.backend.BackendConnection;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.HandlerTool;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.RowDataComparator;
|
||||
import com.actiontech.dble.net.mysql.FieldPacket;
|
||||
import com.actiontech.dble.net.mysql.RowDataPacket;
|
||||
import com.actiontech.dble.plan.Order;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemString;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemAllAnySubQuery;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class AllAnySubQueryHandler extends SubQueryHandler {
|
||||
private ItemAllAnySubQuery itemSubQuery;
|
||||
private Field sourceField;
|
||||
private RowDataPacket tmpRow;
|
||||
private RowDataComparator rowComparator;
|
||||
public AllAnySubQueryHandler(long id, NonBlockingSession session, ItemAllAnySubQuery itemSubQuery) {
|
||||
super(id, session);
|
||||
this.itemSubQuery = itemSubQuery;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldEofResponse(byte[] headerNull, List<byte[]> fieldsNull, List<FieldPacket> fieldPackets,
|
||||
byte[] eofNull, boolean isLeft, BackendConnection conn) {
|
||||
if (terminate.get()) {
|
||||
return;
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
// create field for first time
|
||||
if (this.fieldPackets.isEmpty()) {
|
||||
this.fieldPackets = fieldPackets;
|
||||
sourceField = HandlerTool.createField(this.fieldPackets.get(0));
|
||||
Item select = itemSubQuery.getSelect();
|
||||
select.setPushDownName(select.getAlias());
|
||||
Item tmpItem = HandlerTool.createItem(select, Collections.singletonList(this.sourceField), 0, isAllPushDown(), type());
|
||||
itemSubQuery.setFiled(tmpItem);
|
||||
rowComparator = new RowDataComparator(this.fieldPackets, Collections.singletonList(new Order(select)), this.isAllPushDown(), this.type());
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (terminate.get()) {
|
||||
return true;
|
||||
}
|
||||
RowDataPacket row = rowPacket;
|
||||
if (row == null) {
|
||||
row = new RowDataPacket(this.fieldPackets.size());
|
||||
row.read(rowNull);
|
||||
}
|
||||
sourceField.setPtr(row.getValue(0));
|
||||
Item value = itemSubQuery.getFiled().getResultItem();
|
||||
if (itemSubQuery.getValue().size() == 0) {
|
||||
itemSubQuery.getValue().add(value);
|
||||
tmpRow = row;
|
||||
} else if (itemSubQuery.getValue().size() == 1) {
|
||||
handleNewRow(row, value);
|
||||
} else {
|
||||
// ignore row
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerType type() {
|
||||
return HandlerType.ALL_ANY_SUB_QUERY;
|
||||
}
|
||||
|
||||
private void handleNewRow(RowDataPacket row, Item value) {
|
||||
int result = rowComparator.compare(tmpRow, row);
|
||||
switch (itemSubQuery.getOperator()) {
|
||||
case Equality:
|
||||
if (itemSubQuery.isAll() && result != 0) {
|
||||
itemSubQuery.getValue().add(value);
|
||||
}
|
||||
break;
|
||||
case NotEqual:
|
||||
case LessThanOrGreater:
|
||||
if (!itemSubQuery.isAll() && result != 0) {
|
||||
itemSubQuery.getValue().add(value);
|
||||
}
|
||||
break;
|
||||
case LessThan:
|
||||
case LessThanOrEqual:
|
||||
if (itemSubQuery.isAll() && result > 0) {
|
||||
//row < tmpRow
|
||||
itemSubQuery.getValue().set(0, value);
|
||||
tmpRow = row;
|
||||
} else if (!itemSubQuery.isAll() && result < 0) {
|
||||
//row > tmpRow
|
||||
itemSubQuery.getValue().set(0, value);
|
||||
tmpRow = row;
|
||||
}
|
||||
break;
|
||||
case GreaterThan:
|
||||
case GreaterThanOrEqual:
|
||||
if (itemSubQuery.isAll() && result < 0) {
|
||||
//row > tmpRow
|
||||
itemSubQuery.getValue().set(0, value);
|
||||
tmpRow = row;
|
||||
} else if (!itemSubQuery.isAll() && result > 0) {
|
||||
//row < tmpRow
|
||||
itemSubQuery.getValue().set(0, value);
|
||||
tmpRow = row;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setForExplain() {
|
||||
switch (itemSubQuery.getOperator()) {
|
||||
case Equality:
|
||||
if (itemSubQuery.isAll()) {
|
||||
itemSubQuery.getValue().add(new ItemString("{ALL_SUB_QUERY_RESULTS}"));
|
||||
}
|
||||
break;
|
||||
case NotEqual:
|
||||
case LessThanOrGreater:
|
||||
if (!itemSubQuery.isAll()) {
|
||||
itemSubQuery.getValue().add(new ItemString("{ALL_SUB_QUERY_RESULTS}"));
|
||||
}
|
||||
break;
|
||||
case LessThan:
|
||||
case LessThanOrEqual:
|
||||
if (itemSubQuery.isAll()) {
|
||||
//row < tmpRow
|
||||
itemSubQuery.getValue().add(new ItemString("{MIN_SUB_QUERY_RESULTS}"));
|
||||
} else if (!itemSubQuery.isAll()) {
|
||||
//row > tmpRow
|
||||
itemSubQuery.getValue().add(new ItemString("{MAX_SUB_QUERY_RESULTS}"));
|
||||
}
|
||||
break;
|
||||
case GreaterThan:
|
||||
case GreaterThanOrEqual:
|
||||
if (itemSubQuery.isAll()) {
|
||||
//row > tmpRow
|
||||
itemSubQuery.getValue().add(new ItemString("{MAX_SUB_QUERY_RESULTS}"));
|
||||
} else if (!itemSubQuery.isAll()) {
|
||||
//row < tmpRow
|
||||
itemSubQuery.getValue().add(new ItemString("{MIN_SUB_QUERY_RESULTS}"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.query.impl.subquery;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.backend.BackendConnection;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.HandlerTool;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.net.mysql.FieldPacket;
|
||||
import com.actiontech.dble.net.mysql.RowDataPacket;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemString;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemInSubQuery;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.actiontech.dble.plan.optimizer.JoinStrategyProcessor.NEED_REPLACE;
|
||||
|
||||
public class InSubQueryHandler extends SubQueryHandler {
|
||||
private int maxPartSize = 2000;
|
||||
private int maxConnSize = 4;
|
||||
private int rowCount = 0;
|
||||
private Field sourceField;
|
||||
private ItemInSubQuery itemSubQuery;
|
||||
public InSubQueryHandler(long id, NonBlockingSession session, ItemInSubQuery itemSubQuery) {
|
||||
super(id, session);
|
||||
this.itemSubQuery = itemSubQuery;
|
||||
this.maxPartSize = DbleServer.getInstance().getConfig().getSystem().getNestLoopRowsSize();
|
||||
this.maxConnSize = DbleServer.getInstance().getConfig().getSystem().getNestLoopConnSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldEofResponse(byte[] headerNull, List<byte[]> fieldsNull, List<FieldPacket> fieldPackets,
|
||||
byte[] eofNull, boolean isLeft, BackendConnection conn) {
|
||||
if (terminate.get()) {
|
||||
return;
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
// create field for first time
|
||||
if (this.fieldPackets.isEmpty()) {
|
||||
this.fieldPackets = fieldPackets;
|
||||
sourceField = HandlerTool.createField(this.fieldPackets.get(0));
|
||||
Item select = itemSubQuery.getSelect();
|
||||
select.setPushDownName(select.getAlias());
|
||||
Item tmpItem = HandlerTool.createItem(select, Collections.singletonList(this.sourceField), 0, isAllPushDown(), type());
|
||||
itemSubQuery.setFiled(tmpItem);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (terminate.get()) {
|
||||
return true;
|
||||
}
|
||||
if (++rowCount > maxPartSize * maxConnSize) {
|
||||
String errMessage = "sub query too much rows!";
|
||||
LOGGER.warn(errMessage);
|
||||
genErrorPackage(ErrorCode.ER_UNKNOWN_ERROR, errMessage);
|
||||
conn.close(errMessage);
|
||||
try {
|
||||
tempDoneCallBack.call();
|
||||
} catch (Exception callback) {
|
||||
LOGGER.warn("callback exception!", callback);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
RowDataPacket row = rowPacket;
|
||||
if (row == null) {
|
||||
row = new RowDataPacket(this.fieldPackets.size());
|
||||
row.read(rowNull);
|
||||
}
|
||||
sourceField.setPtr(row.getValue(0));
|
||||
Item value = itemSubQuery.getFiled().getResultItem();
|
||||
if (value != null) {
|
||||
itemSubQuery.getValue().add(value);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HandlerType type() {
|
||||
return HandlerType.IN_SUB_QUERY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForExplain() {
|
||||
itemSubQuery.getValue().add(new ItemString(NEED_REPLACE));
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.query.impl.subquery;
|
||||
|
||||
import com.actiontech.dble.backend.BackendConnection;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.HandlerTool;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.net.mysql.FieldPacket;
|
||||
import com.actiontech.dble.net.mysql.RowDataPacket;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemString;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSingleRowSubQuery;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.actiontech.dble.plan.optimizer.JoinStrategyProcessor.NEED_REPLACE;
|
||||
|
||||
public class SingleRowSubQueryHandler extends SubQueryHandler {
|
||||
private int rowCount = 0;
|
||||
private Field sourceField;
|
||||
private ItemSingleRowSubQuery itemSubQuery;
|
||||
public SingleRowSubQueryHandler(long id, NonBlockingSession session, ItemSingleRowSubQuery itemSubQuery) {
|
||||
super(id, session);
|
||||
this.itemSubQuery = itemSubQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldEofResponse(byte[] headerNull, List<byte[]> fieldsNull, List<FieldPacket> fieldPackets,
|
||||
byte[] eofNull, boolean isLeft, BackendConnection conn) {
|
||||
if (terminate.get()) {
|
||||
return;
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
// create field for first time
|
||||
if (this.fieldPackets.isEmpty()) {
|
||||
this.fieldPackets = fieldPackets;
|
||||
sourceField = HandlerTool.createField(this.fieldPackets.get(0));
|
||||
if (itemSubQuery.isField()) {
|
||||
setSubQueryFiled();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (terminate.get()) {
|
||||
return true;
|
||||
}
|
||||
if (++rowCount > 1) {
|
||||
String errMessage = "Subquery returns more than 1 row";
|
||||
LOGGER.warn(errMessage);
|
||||
genErrorPackage(ErrorCode.ER_SUBQUERY_NO_1_ROW, errMessage);
|
||||
return true;
|
||||
}
|
||||
RowDataPacket row = rowPacket;
|
||||
if (row == null) {
|
||||
row = new RowDataPacket(this.fieldPackets.size());
|
||||
row.read(rowNull);
|
||||
}
|
||||
if (!itemSubQuery.isField()) {
|
||||
setSubQueryFiled();
|
||||
}
|
||||
sourceField.setPtr(row.getValue(0));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HandlerType type() {
|
||||
return HandlerType.SCALAR_SUB_QUERY;
|
||||
}
|
||||
|
||||
private void setSubQueryFiled() {
|
||||
Item select = itemSubQuery.getSelect();
|
||||
select.setPushDownName(select.getAlias());
|
||||
Item tmpItem = HandlerTool.createItem(select, Collections.singletonList(this.sourceField), 0, isAllPushDown(), type());
|
||||
itemSubQuery.setValue(tmpItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForExplain() {
|
||||
itemSubQuery.setValue(new ItemString(NEED_REPLACE));
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.query.impl.subquery;
|
||||
|
||||
import com.actiontech.dble.backend.BackendConnection;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.BaseDMLHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.CallBackHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.util.HandlerTool;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.net.mysql.ErrorPacket;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public abstract class SubQueryHandler extends BaseDMLHandler {
|
||||
protected static final Logger LOGGER = Logger.getLogger(SubQueryHandler.class);
|
||||
protected final ReentrantLock lock;
|
||||
protected CallBackHandler tempDoneCallBack;
|
||||
protected ErrorPacket errorPacket;
|
||||
public abstract void setForExplain();
|
||||
public SubQueryHandler(long id, NonBlockingSession session) {
|
||||
super(id, session);
|
||||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rowEofResponse(byte[] eof, boolean isLeft, BackendConnection conn) {
|
||||
lock.lock();
|
||||
try {
|
||||
// callBack after terminated
|
||||
if (terminate.get()) {
|
||||
return;
|
||||
}
|
||||
HandlerTool.terminateHandlerTree(this);
|
||||
// locked onTerminate, because terminated may sync with start
|
||||
tempDoneCallBack.call();
|
||||
} catch (Exception callback) {
|
||||
LOGGER.warn("callback exception!", callback);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void connectionError(Throwable e, BackendConnection conn) {
|
||||
lock.lock();
|
||||
try {
|
||||
String errorMsg = e.getMessage() == null ? e.toString() : e.getMessage();
|
||||
LOGGER.warn(errorMsg);
|
||||
genErrorPackage(ErrorCode.ER_UNKNOWN_ERROR, errorMsg);
|
||||
HandlerTool.terminateHandlerTree(this);
|
||||
tempDoneCallBack.call();
|
||||
} catch (Exception callback) {
|
||||
LOGGER.warn("callback exception!", callback);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTerminate() {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void errorResponse(byte[] err, BackendConnection conn) {
|
||||
lock.lock();
|
||||
try {
|
||||
ErrorPacket errPacket = new ErrorPacket();
|
||||
errPacket.read(err);
|
||||
String errorMsg = new String(errPacket.getMessage(), StandardCharsets.UTF_8);
|
||||
LOGGER.warn(errorMsg);
|
||||
genErrorPackage(errPacket.getErrNo(), errorMsg);
|
||||
HandlerTool.terminateHandlerTree(this);
|
||||
tempDoneCallBack.call();
|
||||
} catch (Exception callback) {
|
||||
LOGGER.warn("callback exception!", callback);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
protected void genErrorPackage(int errorNum, String msg) {
|
||||
if (errorPacket == null) {
|
||||
errorPacket = new ErrorPacket();
|
||||
errorPacket.setErrNo(errorNum);
|
||||
errorPacket.setMessage(msg.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
public void setTempDoneCallBack(CallBackHandler tempDoneCallBack) {
|
||||
this.tempDoneCallBack = tempDoneCallBack;
|
||||
}
|
||||
public ErrorPacket getErrorPacket() {
|
||||
return errorPacket;
|
||||
}
|
||||
}
|
||||
+28
-5
@@ -17,9 +17,15 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public abstract class AbstractCommitNodesHandler extends MultiNodeHandler implements CommitNodesHandler {
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractCommitNodesHandler.class);
|
||||
protected Lock lockForErrorHandle = new ReentrantLock();
|
||||
protected Condition sendFinished = lockForErrorHandle.newCondition();
|
||||
protected volatile boolean sendFinishedFlag = true;
|
||||
|
||||
public AbstractCommitNodesHandler(NonBlockingSession session) {
|
||||
super(session);
|
||||
@@ -45,13 +51,25 @@ public abstract class AbstractCommitNodesHandler extends MultiNodeHandler implem
|
||||
}
|
||||
}
|
||||
|
||||
for (RouteResultsetNode rrn : session.getTargetKeys()) {
|
||||
final BackendConnection conn = session.getTarget(rrn);
|
||||
conn.setResponseHandler(this);
|
||||
if (!executeCommit((MySQLConnection) conn, position++)) {
|
||||
break;
|
||||
try {
|
||||
sendFinishedFlag = false;
|
||||
for (RouteResultsetNode rrn : session.getTargetKeys()) {
|
||||
final BackendConnection conn = session.getTarget(rrn);
|
||||
conn.setResponseHandler(this);
|
||||
if (!executeCommit((MySQLConnection) conn, position++)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lockForErrorHandle.lock();
|
||||
try {
|
||||
sendFinishedFlag = true;
|
||||
sendFinished.signalAll();
|
||||
} finally {
|
||||
lockForErrorHandle.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,6 +105,11 @@ public abstract class AbstractCommitNodesHandler extends MultiNodeHandler implem
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(int initCount) {
|
||||
nodeCount = initCount;
|
||||
packetId = 0;
|
||||
}
|
||||
|
||||
public void debugCommitDelay() {
|
||||
|
||||
|
||||
+49
-2
@@ -19,6 +19,8 @@ import com.actiontech.dble.net.mysql.OkPacket;
|
||||
import com.actiontech.dble.server.NonBlockingSession;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
|
||||
import static com.actiontech.dble.config.ErrorCode.ER_ERROR_DURING_COMMIT;
|
||||
|
||||
public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
private static final int COMMIT_TIMES = 5;
|
||||
private int tryCommitTimes = 0;
|
||||
@@ -39,6 +41,7 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
@Override
|
||||
protected boolean executeCommit(MySQLConnection mysqlCon, int position) {
|
||||
TxState state = session.getXaState();
|
||||
|
||||
if (state == TxState.TX_STARTED_STATE) {
|
||||
if (participantLogEntry == null) {
|
||||
participantLogEntry = new ParticipantLogEntry[nodeCount];
|
||||
@@ -77,6 +80,20 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
XAStateLog.saveXARecoveryLog(session.getSessionXaID(), TxState.TX_COMMIT_FAILED_STATE);
|
||||
}
|
||||
commitPhase(mysqlCon);
|
||||
} else if (state == TxState.TX_PREPARE_UNCONNECT_STATE) {
|
||||
final String errorMsg = this.error;
|
||||
if (decrementCountBy(1)) {
|
||||
DbleServer.getInstance().getBusinessExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ErrorPacket error = new ErrorPacket();
|
||||
error.setErrNo(ER_ERROR_DURING_COMMIT);
|
||||
error.setMessage(errorMsg == null ? "unknow error".getBytes() : errorMsg.getBytes());
|
||||
XAAutoRollbackNodesHandler nextHandler = new XAAutoRollbackNodesHandler(session, error.toBytes(), null, null);
|
||||
nextHandler.rollback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -114,6 +131,7 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
|
||||
@Override
|
||||
public void okResponse(byte[] ok, BackendConnection conn) {
|
||||
this.waitUntilSendFinish();
|
||||
MySQLConnection mysqlCon = (MySQLConnection) conn;
|
||||
TxState state = mysqlCon.getXaStatus();
|
||||
if (state == TxState.TX_STARTED_STATE) {
|
||||
@@ -151,6 +169,7 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
|
||||
@Override
|
||||
public void errorResponse(byte[] err, BackendConnection conn) {
|
||||
this.waitUntilSendFinish();
|
||||
ErrorPacket errPacket = new ErrorPacket();
|
||||
errPacket.read(err);
|
||||
String errMsg = new String(errPacket.getMessage());
|
||||
@@ -193,6 +212,7 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
|
||||
@Override
|
||||
public void connectionError(Throwable e, BackendConnection conn) {
|
||||
this.waitUntilSendFinish();
|
||||
LOGGER.warn("backend connect", e);
|
||||
String errMsg = new String(StringUtil.encode(e.getMessage(), session.getSource().getCharset().getResults()));
|
||||
this.setFail(errMsg);
|
||||
@@ -230,7 +250,19 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionClose(BackendConnection conn, String reason) {
|
||||
public void connectionClose(final BackendConnection conn, final String reason) {
|
||||
final XACommitNodesHandler thisHandler = this;
|
||||
DbleServer.getInstance().getBusinessExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
thisHandler.connectionCloseLocal(conn, reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void connectionCloseLocal(BackendConnection conn, String reason) {
|
||||
this.waitUntilSendFinish();
|
||||
this.setFail(reason);
|
||||
sendData = makeErrorPacket(reason);
|
||||
if (conn instanceof MySQLConnection) {
|
||||
@@ -265,8 +297,9 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void nextParse() {
|
||||
if (this.isFail()) {
|
||||
if (this.isFail() && session.getXaState() != TxState.TX_PREPARE_UNCONNECT_STATE) {
|
||||
session.getSource().setTxInterrupt(error);
|
||||
session.getSource().write(sendData);
|
||||
LOGGER.warn("nextParse failed:" + error);
|
||||
@@ -347,4 +380,18 @@ public class XACommitNodesHandler extends AbstractCommitNodesHandler {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void waitUntilSendFinish() {
|
||||
try {
|
||||
this.lockForErrorHandle.lock();
|
||||
if (!this.sendFinishedFlag) {
|
||||
this.sendFinished.await();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.info("back Response is closed by thread interrupted");
|
||||
} finally {
|
||||
lockForErrorHandle.unlock();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -341,7 +341,8 @@ public class XARollbackNodesHandler extends AbstractRollbackNodesHandler {
|
||||
session.getSource().write(send);
|
||||
|
||||
//partitionly commited,must commit again
|
||||
} else if (session.getXaState() == TxState.TX_ROLLBACK_FAILED_STATE || session.getXaState() == TxState.TX_PREPARED_STATE) {
|
||||
} else if (session.getXaState() == TxState.TX_ROLLBACK_FAILED_STATE || session.getXaState() == TxState.TX_PREPARED_STATE ||
|
||||
session.getXaState() == TxState.TX_PREPARE_UNCONNECT_STATE) {
|
||||
MySQLConnection errConn = session.releaseExcept(session.getXaState());
|
||||
if (errConn != null) {
|
||||
XAStateLog.saveXARecoveryLog(session.getSessionXaID(), session.getXaState());
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.actiontech.dble.plan.common.item.ItemInt;
|
||||
import com.actiontech.dble.plan.common.item.ItemRef;
|
||||
import com.actiontech.dble.plan.common.item.function.ItemFunc;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemScalarSubQuery;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
import org.apache.log4j.Logger;
|
||||
@@ -82,6 +83,9 @@ public final class HandlerTool {
|
||||
Item ret;
|
||||
if (sel.basicConstItem())
|
||||
return sel;
|
||||
if (sel instanceof ItemScalarSubQuery) {
|
||||
return ((ItemScalarSubQuery) sel).getValue();
|
||||
}
|
||||
Item.ItemType i = sel.type();
|
||||
if (i == Item.ItemType.FUNC_ITEM || i == Item.ItemType.COND_ITEM) {
|
||||
ItemFunc func = (ItemFunc) sel;
|
||||
|
||||
+1
-2
@@ -84,7 +84,6 @@ public class FileSystemRepository implements Repository {
|
||||
private synchronized void writeToFile(ByteBuffer buff, boolean force)
|
||||
throws IOException {
|
||||
rwChannel.write(buff);
|
||||
rwChannel.force(force);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +99,7 @@ public class FileSystemRepository implements Repository {
|
||||
} catch (FileNotFoundException firstStart) {
|
||||
// the file could not be opened for reading;
|
||||
// merely return the default empty vector
|
||||
LOGGER.warn("FileSystemRepository.getAllCoordinatorLogEntries error", firstStart);
|
||||
LOGGER.debug("Only For debug FileSystemRepository.getAllCoordinatorLogEntries error", firstStart);
|
||||
}
|
||||
if (fis != null) {
|
||||
return readFromInputStream(fis);
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
package com.actiontech.dble.config;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDBNode;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDBPool;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDatasource;
|
||||
import com.actiontech.dble.backend.mysql.nio.MySQLDataSource;
|
||||
import com.actiontech.dble.config.loader.SchemaLoader;
|
||||
import com.actiontech.dble.config.loader.xml.XMLConfigLoader;
|
||||
import com.actiontech.dble.config.loader.xml.XMLServerLoader;
|
||||
import com.actiontech.dble.config.loader.xml.XMLSchemaLoader;
|
||||
import com.actiontech.dble.config.model.*;
|
||||
import com.actiontech.dble.config.util.ConfigException;
|
||||
@@ -44,11 +45,12 @@ public class ConfigInitializer {
|
||||
|
||||
public ConfigInitializer(boolean loadDataHost) {
|
||||
//load server.xml
|
||||
XMLConfigLoader configLoader = new XMLConfigLoader();
|
||||
XMLServerLoader serverloader = new XMLServerLoader();
|
||||
|
||||
//load rule.xml and schema.xml
|
||||
SchemaLoader schemaLoader = new XMLSchemaLoader(configLoader.getSystemConfig().isLowerCaseTableNames());
|
||||
this.system = configLoader.getSystemConfig();
|
||||
this.users = configLoader.getUserConfigs();
|
||||
SchemaLoader schemaLoader = new XMLSchemaLoader(SystemVariables.getSysVars().isLowerCaseTableNames());
|
||||
this.system = serverloader.getSystem();
|
||||
this.users = serverloader.getUsers();
|
||||
this.schemas = schemaLoader.getSchemas();
|
||||
this.erRelations = schemaLoader.getErRelations();
|
||||
// need reload DataHost and DataNode?
|
||||
@@ -62,11 +64,34 @@ public class ConfigInitializer {
|
||||
this.dataHostWithoutWH = DbleServer.getInstance().getConfig().isDataHostWithoutWR();
|
||||
}
|
||||
|
||||
this.firewall = configLoader.getFirewallConfig();
|
||||
this.firewall = serverloader.getFirewall();
|
||||
|
||||
loadSequence();
|
||||
/**
|
||||
* check config
|
||||
*/
|
||||
this.selfChecking0();
|
||||
}
|
||||
|
||||
public ConfigInitializer() {
|
||||
XMLServerLoader serverloader = new XMLServerLoader();
|
||||
this.system = serverloader.getSystem();
|
||||
this.users = serverloader.getUsers();
|
||||
this.firewall = serverloader.getFirewall();
|
||||
|
||||
SchemaLoader schemaLoader = new XMLSchemaLoader(SystemVariables.getSysVars().isLowerCaseTableNames());
|
||||
this.schemas = schemaLoader.getSchemas();
|
||||
this.erRelations = schemaLoader.getErRelations();
|
||||
this.dataHosts = DbleServer.getInstance().getConfig().getDataHosts();
|
||||
this.dataNodes = initDataNodes(schemaLoader);
|
||||
|
||||
loadSequence();
|
||||
}
|
||||
|
||||
private void loadSequence() {
|
||||
//load global sequence
|
||||
if (system.getSequnceHandlerType() == SystemConfig.SEQUENCE_HANDLER_MYSQL) {
|
||||
IncrSequenceMySQLHandler.getInstance().load(system.isLowerCaseTableNames());
|
||||
IncrSequenceMySQLHandler.getInstance().load(SystemVariables.getSysVars().isLowerCaseTableNames());
|
||||
}
|
||||
|
||||
if (system.getSequnceHandlerType() == SystemConfig.SEQUENCE_HANDLER_LOCAL_TIME) {
|
||||
@@ -78,13 +103,8 @@ public class ConfigInitializer {
|
||||
}
|
||||
|
||||
if (system.getSequnceHandlerType() == SystemConfig.SEQUENCE_HANDLER_ZK_GLOBAL_INCREMENT) {
|
||||
IncrSequenceZKHandler.getInstance().load(system.isLowerCaseTableNames());
|
||||
IncrSequenceZKHandler.getInstance().load(SystemVariables.getSysVars().isLowerCaseTableNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* check config
|
||||
*/
|
||||
this.selfChecking0();
|
||||
}
|
||||
|
||||
private void selfChecking0() throws ConfigException {
|
||||
|
||||
@@ -70,9 +70,7 @@ public class ServerConfig {
|
||||
this.dataNodes = confInit.getDataNodes();
|
||||
this.erRelations = confInit.getErRelations();
|
||||
this.dataHostWithoutWR = confInit.isDataHostWithoutWH();
|
||||
for (PhysicalDBPool dbPool : dataHosts.values()) {
|
||||
dbPool.setSchemas(getDataNodeSchemasOfDataHost(dbPool.getHostName()));
|
||||
}
|
||||
setSchemasForPool();
|
||||
|
||||
this.firewall = confInit.getFirewall();
|
||||
|
||||
@@ -83,6 +81,23 @@ public class ServerConfig {
|
||||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
private void setSchemasForPool() {
|
||||
for (PhysicalDBPool dbPool : dataHosts.values()) {
|
||||
dbPool.setSchemas(getDataNodeSchemasOfDataHost(dbPool.getHostName()));
|
||||
}
|
||||
}
|
||||
|
||||
public void reviseSchemas() {
|
||||
ConfigInitializer confInit = new ConfigInitializer();
|
||||
this.system = confInit.getSystem();
|
||||
this.users = confInit.getUsers();
|
||||
this.firewall = confInit.getFirewall();
|
||||
this.schemas = confInit.getSchemas();
|
||||
this.dataNodes = confInit.getDataNodes();
|
||||
this.erRelations = confInit.getErRelations();
|
||||
setSchemasForPool();
|
||||
}
|
||||
|
||||
public SystemConfig getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
@@ -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-20170922131413".getBytes();
|
||||
private static byte[] serverVersion = "5.6.29-dble-2.17.09.0-dev-20171017161450".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";
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.config.loader.xml;
|
||||
|
||||
import com.actiontech.dble.config.model.FirewallConfig;
|
||||
import com.actiontech.dble.config.model.UserConfig;
|
||||
import com.actiontech.dble.config.util.ParameterMapping;
|
||||
import com.actiontech.dble.config.util.ConfigException;
|
||||
import com.actiontech.dble.config.util.ConfigUtil;
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import java.util.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class FirewallConfigLoader implements Loader<FirewallConfig, XMLServerLoader> {
|
||||
public void load(Element root, XMLServerLoader xsl) throws IllegalAccessException, InvocationTargetException {
|
||||
FirewallConfig firewall = xsl.getFirewall();
|
||||
Map<String, UserConfig> users = xsl.getUsers();
|
||||
NodeList list = root.getElementsByTagName("host");
|
||||
Map<String, List<UserConfig>> whitehost = new HashMap<>();
|
||||
|
||||
for (int i = 0, n = list.getLength(); i < n; i++) {
|
||||
Node node = list.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element e = (Element) node;
|
||||
String host = e.getAttribute("host").trim();
|
||||
String userStr = e.getAttribute("user").trim();
|
||||
if (firewall.existsHost(host)) {
|
||||
throw new ConfigException("host duplicated : " + host);
|
||||
}
|
||||
String[] arrayUsers = userStr.split(",");
|
||||
List<UserConfig> userConfigs = new ArrayList<>();
|
||||
for (String user : arrayUsers) {
|
||||
UserConfig uc = users.get(user);
|
||||
if (null == uc) {
|
||||
throw new ConfigException("[user: " + user + "] doesn't exist in [host: " + host + "]");
|
||||
}
|
||||
if (!uc.isManager() && (uc.getSchemas() == null || uc.getSchemas().size() == 0)) {
|
||||
throw new ConfigException("[host: " + host + "] contains one root privileges user: " + user);
|
||||
}
|
||||
userConfigs.add(uc);
|
||||
}
|
||||
whitehost.put(host, userConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
firewall.setWhitehost(whitehost);
|
||||
|
||||
WallConfig wallConfig = new WallConfig();
|
||||
NodeList blacklist = root.getElementsByTagName("blacklist");
|
||||
for (int i = 0, n = blacklist.getLength(); i < n; i++) {
|
||||
Node node = blacklist.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element e = (Element) node;
|
||||
String check = e.getAttribute("check");
|
||||
if (null != check) {
|
||||
firewall.setBlackListCheck(Boolean.parseBoolean(check));
|
||||
}
|
||||
|
||||
Map<String, Object> props = ConfigUtil.loadElements((Element) node);
|
||||
ParameterMapping.mapping(wallConfig, props);
|
||||
}
|
||||
}
|
||||
firewall.setWallConfig(wallConfig);
|
||||
firewall.init();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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.config.loader.xml;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public interface Loader<P, T> {
|
||||
void load(Element root, T t) throws IllegalAccessException, InvocationTargetException;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.config.loader.xml;
|
||||
|
||||
import com.actiontech.dble.config.Versions;
|
||||
import com.actiontech.dble.config.model.SystemConfig;
|
||||
import com.actiontech.dble.config.util.ConfigException;
|
||||
import com.actiontech.dble.config.util.ConfigUtil;
|
||||
import com.actiontech.dble.config.util.ParameterMapping;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import java.util.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class SystemConfigLoader implements Loader<SystemConfig, XMLServerLoader> {
|
||||
public void load(Element root, XMLServerLoader xsl) throws IllegalAccessException, InvocationTargetException {
|
||||
SystemConfig system = xsl.getSystem();
|
||||
NodeList list = root.getElementsByTagName("system");
|
||||
|
||||
for (int i = 0, n = list.getLength(); i < n; i++) {
|
||||
Node node = list.item(i);
|
||||
if (node instanceof Element) {
|
||||
Map<String, Object> props = ConfigUtil.loadElements((Element) node);
|
||||
ParameterMapping.mapping(system, props);
|
||||
}
|
||||
}
|
||||
|
||||
if (system.getFakeMySQLVersion() != null) {
|
||||
boolean validVersion = false;
|
||||
String majorMySQLVersion = system.getFakeMySQLVersion();
|
||||
int pos = majorMySQLVersion.indexOf(".") + 1;
|
||||
majorMySQLVersion = majorMySQLVersion.substring(0, majorMySQLVersion.indexOf(".", pos));
|
||||
for (String ver : SystemConfig.MYSQL_VERSIONS) {
|
||||
// version is x.y.z ,just compare the x.y
|
||||
if (majorMySQLVersion.equals(ver)) {
|
||||
validVersion = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (validVersion) {
|
||||
Versions.setServerVersion(system.getFakeMySQLVersion());
|
||||
} else {
|
||||
throw new ConfigException("The specified MySQL Version (" + system.getFakeMySQLVersion() + ") is not valid.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.config.loader.xml;
|
||||
|
||||
import com.actiontech.dble.config.model.UserConfig;
|
||||
import com.actiontech.dble.config.model.SystemConfig;
|
||||
import com.actiontech.dble.config.model.UserPrivilegesConfig;
|
||||
import com.actiontech.dble.config.util.ConfigException;
|
||||
import com.actiontech.dble.config.util.ConfigUtil;
|
||||
import com.actiontech.dble.util.DecryptUtil;
|
||||
import com.actiontech.dble.util.SplitUtil;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import java.util.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class UserConfigLoader implements Loader<UserConfig, XMLServerLoader> {
|
||||
public void load(Element root, XMLServerLoader xsl) throws IllegalAccessException, InvocationTargetException {
|
||||
SystemConfig system = xsl.getSystem();
|
||||
Map<String, UserConfig> users = xsl.getUsers();
|
||||
NodeList list = root.getElementsByTagName("user");
|
||||
|
||||
for (int i = 0, n = list.getLength(); i < n; i++) {
|
||||
Node node = list.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element e = (Element) node;
|
||||
String name = e.getAttribute("name");
|
||||
UserConfig user = new UserConfig();
|
||||
Map<String, Object> props = ConfigUtil.loadElements(e);
|
||||
String password = (String) props.get("password");
|
||||
String usingDecrypt = (String) props.get("usingDecrypt");
|
||||
String passwordDecrypt = DecryptUtil.decrypt(usingDecrypt, name, password);
|
||||
user.setName(name);
|
||||
user.setPassword(passwordDecrypt);
|
||||
user.setEncryptPassword(password);
|
||||
|
||||
String benchmark = (String) props.get("benchmark");
|
||||
if (null != benchmark) {
|
||||
user.setBenchmark(Integer.parseInt(benchmark));
|
||||
}
|
||||
|
||||
String readOnly = (String) props.get("readOnly");
|
||||
if (null != readOnly) {
|
||||
user.setReadOnly(Boolean.parseBoolean(readOnly));
|
||||
}
|
||||
|
||||
String manager = (String) props.get("manager");
|
||||
if (null != manager) {
|
||||
user.setManager(Boolean.parseBoolean(manager));
|
||||
}
|
||||
String schemas = (String) props.get("schemas");
|
||||
if (user.isManager() && schemas != null) {
|
||||
throw new ConfigException("manager user can't set any schema!");
|
||||
} else if (!user.isManager()) {
|
||||
if (schemas != null) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
schemas = schemas.toLowerCase();
|
||||
}
|
||||
String[] strArray = SplitUtil.split(schemas, ',', true);
|
||||
user.setSchemas(new HashSet<>(Arrays.asList(strArray)));
|
||||
}
|
||||
// load DML
|
||||
loadPrivileges(user, system, e);
|
||||
}
|
||||
if (users.containsKey(name)) {
|
||||
throw new ConfigException("user " + name + " duplicated!");
|
||||
}
|
||||
users.put(name, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPrivileges(UserConfig userConfig, SystemConfig system, Element node) {
|
||||
UserPrivilegesConfig privilegesConfig = new UserPrivilegesConfig();
|
||||
|
||||
NodeList privilegesNodes = node.getElementsByTagName("privileges");
|
||||
int privilegesNodesLength = privilegesNodes.getLength();
|
||||
for (int i = 0; i < privilegesNodesLength; i++) {
|
||||
Element privilegesNode = (Element) privilegesNodes.item(i);
|
||||
String check = privilegesNode.getAttribute("check");
|
||||
if (null != check) {
|
||||
privilegesConfig.setCheck(Boolean.valueOf(check));
|
||||
}
|
||||
|
||||
NodeList schemaNodes = privilegesNode.getElementsByTagName("schema");
|
||||
int schemaNodeLength = schemaNodes.getLength();
|
||||
for (int j = 0; j < schemaNodeLength; j++) {
|
||||
Element schemaNode = (Element) schemaNodes.item(j);
|
||||
String name1 = schemaNode.getAttribute("name");
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
name1 = name1.toLowerCase();
|
||||
}
|
||||
|
||||
String dml1 = schemaNode.getAttribute("dml");
|
||||
int[] dml1Array = new int[dml1.length()];
|
||||
for (int offset1 = 0; offset1 < dml1.length(); offset1++) {
|
||||
dml1Array[offset1] = Character.getNumericValue(dml1.charAt(offset1));
|
||||
}
|
||||
|
||||
UserPrivilegesConfig.SchemaPrivilege schemaPrivilege = new UserPrivilegesConfig.SchemaPrivilege();
|
||||
schemaPrivilege.setDml(dml1Array);
|
||||
|
||||
NodeList tableNodes = schemaNode.getElementsByTagName("table");
|
||||
int tableNodeLength = tableNodes.getLength();
|
||||
for (int z = 0; z < tableNodeLength; z++) {
|
||||
UserPrivilegesConfig.TablePrivilege tablePrivilege = new UserPrivilegesConfig.TablePrivilege();
|
||||
Element tableNode = (Element) tableNodes.item(z);
|
||||
String name2 = tableNode.getAttribute("name");
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
name2 = name2.toLowerCase();
|
||||
}
|
||||
|
||||
String dml2 = tableNode.getAttribute("dml");
|
||||
int[] dml2Array = new int[dml2.length()];
|
||||
for (int offset2 = 0; offset2 < dml2.length(); offset2++) {
|
||||
dml2Array[offset2] = Character.getNumericValue(dml2.charAt(offset2));
|
||||
}
|
||||
tablePrivilege.setDml(dml2Array);
|
||||
|
||||
schemaPrivilege.addTablePrivilege(name2, tablePrivilege);
|
||||
}
|
||||
|
||||
privilegesConfig.addSchemaPrivilege(name1, schemaPrivilege);
|
||||
}
|
||||
}
|
||||
userConfig.setPrivilegesConfig(privilegesConfig);
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,16 @@
|
||||
*/
|
||||
package com.actiontech.dble.config.loader.xml;
|
||||
|
||||
import com.actiontech.dble.config.Versions;
|
||||
import com.actiontech.dble.config.model.FirewallConfig;
|
||||
import com.actiontech.dble.config.model.SystemConfig;
|
||||
import com.actiontech.dble.config.model.UserConfig;
|
||||
import com.actiontech.dble.config.model.UserPrivilegesConfig;
|
||||
import com.actiontech.dble.config.util.ConfigException;
|
||||
import com.actiontech.dble.config.util.ConfigUtil;
|
||||
import com.actiontech.dble.config.util.ParameterMapping;
|
||||
import com.actiontech.dble.util.DecryptUtil;
|
||||
import com.actiontech.dble.util.ResourceUtil;
|
||||
import com.actiontech.dble.util.SplitUtil;
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -39,7 +30,10 @@ public class XMLServerLoader {
|
||||
this.system = new SystemConfig();
|
||||
this.users = new HashMap<>();
|
||||
this.firewall = new FirewallConfig();
|
||||
this.load();
|
||||
|
||||
this.load(new SystemConfigLoader());
|
||||
this.load(new UserConfigLoader());
|
||||
this.load(new FirewallConfigLoader());
|
||||
}
|
||||
|
||||
public SystemConfig getSystem() {
|
||||
@@ -48,15 +42,15 @@ public class XMLServerLoader {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, UserConfig> getUsers() {
|
||||
return (Map<String, UserConfig>) (users.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(users));
|
||||
//return (Map<String, UserConfig>) (users.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(users));
|
||||
return users;
|
||||
}
|
||||
|
||||
public FirewallConfig getFirewall() {
|
||||
return firewall;
|
||||
}
|
||||
|
||||
|
||||
private void load() {
|
||||
public void load(Loader loader) {
|
||||
//read server.xml
|
||||
InputStream dtd = null;
|
||||
InputStream xml = null;
|
||||
@@ -64,10 +58,7 @@ public class XMLServerLoader {
|
||||
dtd = ResourceUtil.getResourceAsStream("/server.dtd");
|
||||
xml = ResourceUtil.getResourceAsStream("/server.xml");
|
||||
Element root = ConfigUtil.getDocument(dtd, xml).getDocumentElement();
|
||||
|
||||
loadSystem(root);
|
||||
loadUsers(root);
|
||||
loadFirewall(root);
|
||||
loader.load(root, this);
|
||||
} catch (ConfigException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
@@ -89,200 +80,4 @@ public class XMLServerLoader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFirewall(Element root) throws IllegalAccessException, InvocationTargetException {
|
||||
NodeList list = root.getElementsByTagName("host");
|
||||
Map<String, List<UserConfig>> whitehost = new HashMap<>();
|
||||
|
||||
for (int i = 0, n = list.getLength(); i < n; i++) {
|
||||
Node node = list.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element e = (Element) node;
|
||||
String host = e.getAttribute("host").trim();
|
||||
String userStr = e.getAttribute("user").trim();
|
||||
if (this.firewall.existsHost(host)) {
|
||||
throw new ConfigException("host duplicated : " + host);
|
||||
}
|
||||
String[] arrayUsers = userStr.split(",");
|
||||
List<UserConfig> userConfigs = new ArrayList<>();
|
||||
for (String user : arrayUsers) {
|
||||
UserConfig uc = this.users.get(user);
|
||||
if (null == uc) {
|
||||
throw new ConfigException("[user: " + user + "] doesn't exist in [host: " + host + "]");
|
||||
}
|
||||
if (!uc.isManager() && (uc.getSchemas() == null || uc.getSchemas().size() == 0)) {
|
||||
throw new ConfigException("[host: " + host + "] contains one root privileges user: " + user);
|
||||
}
|
||||
userConfigs.add(uc);
|
||||
}
|
||||
whitehost.put(host, userConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
firewall.setWhitehost(whitehost);
|
||||
|
||||
WallConfig wallConfig = new WallConfig();
|
||||
NodeList blacklist = root.getElementsByTagName("blacklist");
|
||||
for (int i = 0, n = blacklist.getLength(); i < n; i++) {
|
||||
Node node = blacklist.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element e = (Element) node;
|
||||
String check = e.getAttribute("check");
|
||||
if (null != check) {
|
||||
firewall.setBlackListCheck(Boolean.parseBoolean(check));
|
||||
}
|
||||
|
||||
Map<String, Object> props = ConfigUtil.loadElements((Element) node);
|
||||
ParameterMapping.mapping(wallConfig, props);
|
||||
}
|
||||
}
|
||||
firewall.setWallConfig(wallConfig);
|
||||
firewall.init();
|
||||
|
||||
}
|
||||
|
||||
private void loadUsers(Element root) {
|
||||
NodeList list = root.getElementsByTagName("user");
|
||||
for (int i = 0, n = list.getLength(); i < n; i++) {
|
||||
Node node = list.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element e = (Element) node;
|
||||
String name = e.getAttribute("name");
|
||||
UserConfig user = new UserConfig();
|
||||
Map<String, Object> props = ConfigUtil.loadElements(e);
|
||||
String password = (String) props.get("password");
|
||||
String usingDecrypt = (String) props.get("usingDecrypt");
|
||||
String passwordDecrypt = DecryptUtil.decrypt(usingDecrypt, name, password);
|
||||
user.setName(name);
|
||||
user.setPassword(passwordDecrypt);
|
||||
user.setEncryptPassword(password);
|
||||
|
||||
String benchmark = (String) props.get("benchmark");
|
||||
if (null != benchmark) {
|
||||
user.setBenchmark(Integer.parseInt(benchmark));
|
||||
}
|
||||
|
||||
String readOnly = (String) props.get("readOnly");
|
||||
if (null != readOnly) {
|
||||
user.setReadOnly(Boolean.parseBoolean(readOnly));
|
||||
}
|
||||
|
||||
String manager = (String) props.get("manager");
|
||||
if (null != manager) {
|
||||
user.setManager(Boolean.parseBoolean(manager));
|
||||
}
|
||||
String schemas = (String) props.get("schemas");
|
||||
if (user.isManager() && schemas != null) {
|
||||
throw new ConfigException("manager user can't set any schema!");
|
||||
} else if (!user.isManager()) {
|
||||
if (schemas != null) {
|
||||
if (system.isLowerCaseTableNames()) {
|
||||
schemas = schemas.toLowerCase();
|
||||
}
|
||||
String[] strArray = SplitUtil.split(schemas, ',', true);
|
||||
user.setSchemas(new HashSet<>(Arrays.asList(strArray)));
|
||||
}
|
||||
// load DML
|
||||
loadPrivileges(user, e);
|
||||
}
|
||||
if (users.containsKey(name)) {
|
||||
throw new ConfigException("user " + name + " duplicated!");
|
||||
}
|
||||
users.put(name, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPrivileges(UserConfig userConfig, Element node) {
|
||||
|
||||
UserPrivilegesConfig privilegesConfig = new UserPrivilegesConfig();
|
||||
|
||||
NodeList privilegesNodes = node.getElementsByTagName("privileges");
|
||||
int privilegesNodesLength = privilegesNodes.getLength();
|
||||
for (int i = 0; i < privilegesNodesLength; i++) {
|
||||
Element privilegesNode = (Element) privilegesNodes.item(i);
|
||||
String check = privilegesNode.getAttribute("check");
|
||||
if (null != check) {
|
||||
privilegesConfig.setCheck(Boolean.valueOf(check));
|
||||
}
|
||||
|
||||
|
||||
NodeList schemaNodes = privilegesNode.getElementsByTagName("schema");
|
||||
int schemaNodeLength = schemaNodes.getLength();
|
||||
|
||||
for (int j = 0; j < schemaNodeLength; j++) {
|
||||
Element schemaNode = (Element) schemaNodes.item(j);
|
||||
String name1 = schemaNode.getAttribute("name");
|
||||
if (system.isLowerCaseTableNames()) {
|
||||
name1 = name1.toLowerCase();
|
||||
}
|
||||
String dml1 = schemaNode.getAttribute("dml");
|
||||
|
||||
int[] dml1Array = new int[dml1.length()];
|
||||
for (int offset1 = 0; offset1 < dml1.length(); offset1++) {
|
||||
dml1Array[offset1] = Character.getNumericValue(dml1.charAt(offset1));
|
||||
}
|
||||
|
||||
UserPrivilegesConfig.SchemaPrivilege schemaPrivilege = new UserPrivilegesConfig.SchemaPrivilege();
|
||||
schemaPrivilege.setDml(dml1Array);
|
||||
|
||||
NodeList tableNodes = schemaNode.getElementsByTagName("table");
|
||||
int tableNodeLength = tableNodes.getLength();
|
||||
for (int z = 0; z < tableNodeLength; z++) {
|
||||
|
||||
UserPrivilegesConfig.TablePrivilege tablePrivilege = new UserPrivilegesConfig.TablePrivilege();
|
||||
|
||||
Element tableNode = (Element) tableNodes.item(z);
|
||||
String name2 = tableNode.getAttribute("name");
|
||||
if (system.isLowerCaseTableNames()) {
|
||||
name2 = name2.toLowerCase();
|
||||
}
|
||||
String dml2 = tableNode.getAttribute("dml");
|
||||
|
||||
int[] dml2Array = new int[dml2.length()];
|
||||
for (int offset2 = 0; offset2 < dml2.length(); offset2++) {
|
||||
dml2Array[offset2] = Character.getNumericValue(dml2.charAt(offset2));
|
||||
}
|
||||
tablePrivilege.setDml(dml2Array);
|
||||
|
||||
schemaPrivilege.addTablePrivilege(name2, tablePrivilege);
|
||||
}
|
||||
|
||||
privilegesConfig.addSchemaPrivilege(name1, schemaPrivilege);
|
||||
}
|
||||
}
|
||||
|
||||
userConfig.setPrivilegesConfig(privilegesConfig);
|
||||
}
|
||||
|
||||
private void loadSystem(Element root) throws IllegalAccessException, InvocationTargetException {
|
||||
NodeList list = root.getElementsByTagName("system");
|
||||
for (int i = 0, n = list.getLength(); i < n; i++) {
|
||||
Node node = list.item(i);
|
||||
if (node instanceof Element) {
|
||||
Map<String, Object> props = ConfigUtil.loadElements((Element) node);
|
||||
ParameterMapping.mapping(system, props);
|
||||
}
|
||||
}
|
||||
|
||||
if (system.getFakeMySQLVersion() != null) {
|
||||
boolean validVersion = false;
|
||||
String majorMySQLVersion = system.getFakeMySQLVersion();
|
||||
int pos = majorMySQLVersion.indexOf(".") + 1;
|
||||
majorMySQLVersion = majorMySQLVersion.substring(0, majorMySQLVersion.indexOf(".", pos));
|
||||
for (String ver : SystemConfig.MYSQL_VERSIONS) {
|
||||
// version is x.y.z ,just compare the x.y
|
||||
if (majorMySQLVersion.equals(ver)) {
|
||||
validVersion = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (validVersion) {
|
||||
Versions.setServerVersion(system.getFakeMySQLVersion());
|
||||
} else {
|
||||
throw new ConfigException("The specified MySQL Version (" + system.getFakeMySQLVersion() + ") is not valid.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ public final class SystemConfig {
|
||||
private static final String DEFAULT_CLUSTER_HEARTBEAT_PASS = "_HEARTBEAT_PASS_";
|
||||
private static final int DEFAULT_SQL_RECORD_COUNT = 10;
|
||||
private static final boolean DEFAULT_USE_ZK_SWITCH = true;
|
||||
private static final boolean DEFAULT_LOWER_CASE = true;
|
||||
private static final String DEFAULT_TRANSACTION_BASE_DIR = "txlogs";
|
||||
private static final String DEFAULT_TRANSACTION_BASE_NAME = "server-tx";
|
||||
private static final int DEFAULT_TRANSACTION_ROTATE_SIZE = 16;
|
||||
@@ -146,8 +145,6 @@ public final class SystemConfig {
|
||||
private int mappedFileSize;
|
||||
private boolean useZKSwitch = DEFAULT_USE_ZK_SWITCH;
|
||||
|
||||
private boolean lowerCaseTableNames = DEFAULT_LOWER_CASE;
|
||||
|
||||
private boolean useJoinStrategy;
|
||||
|
||||
public SystemConfig() {
|
||||
@@ -277,17 +274,6 @@ public final class SystemConfig {
|
||||
this.useJoinStrategy = useJoinStrategy;
|
||||
}
|
||||
|
||||
|
||||
public boolean isLowerCaseTableNames() {
|
||||
return lowerCaseTableNames;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setLowerCaseTableNames(boolean lowerCaseTableNames) {
|
||||
this.lowerCaseTableNames = lowerCaseTableNames;
|
||||
}
|
||||
|
||||
|
||||
public String getXaRecoveryLogBaseDir() {
|
||||
return xaRecoveryLogBaseDir;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.meta.table;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDBNode;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.sqlengine.MultiRowSQLQueryResultHandler;
|
||||
@@ -62,7 +63,7 @@ public class ShowTablesHandler {
|
||||
List<Map<String, String>> rows = result.getResult();
|
||||
for (Map<String, String> row : rows) {
|
||||
String table = row.get(mysqlShowTableCol);
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
table = table.toLowerCase();
|
||||
}
|
||||
if (!config.getTables().containsKey(table)) {
|
||||
|
||||
@@ -7,7 +7,7 @@ package com.actiontech.dble.net;
|
||||
|
||||
import com.actiontech.dble.net.mysql.CharsetNames;
|
||||
import com.actiontech.dble.net.mysql.MySQLPacket;
|
||||
import com.actiontech.dble.server.SystemVariables;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.util.CompressUtil;
|
||||
import com.actiontech.dble.util.TimeUtil;
|
||||
import com.google.common.base.Strings;
|
||||
@@ -109,7 +109,7 @@ public abstract class AbstractConnection implements NIOConnection {
|
||||
public void setCharacterSet(String name) {
|
||||
charsetName.setClient(name);
|
||||
charsetName.setResults(name);
|
||||
charsetName.setCollation(SystemVariables.getDefaultValue("collation_database"));
|
||||
charsetName.setCollation(SystemVariables.getSysVars().getDefaultValue("collation_database"));
|
||||
}
|
||||
|
||||
public boolean setNames(String name, String collationName) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.net;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.mysql.CharsetUtil;
|
||||
import com.actiontech.dble.backend.mysql.MySQLMessage;
|
||||
import com.actiontech.dble.config.Capabilities;
|
||||
@@ -16,7 +17,6 @@ import com.actiontech.dble.net.mysql.ErrorPacket;
|
||||
import com.actiontech.dble.net.mysql.HandshakeV10Packet;
|
||||
import com.actiontech.dble.net.mysql.MySQLPacket;
|
||||
import com.actiontech.dble.net.mysql.OkPacket;
|
||||
import com.actiontech.dble.server.SystemVariables;
|
||||
import com.actiontech.dble.util.CompressUtil;
|
||||
import com.actiontech.dble.util.RandomUtil;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
@@ -162,7 +162,7 @@ public abstract class FrontendConnection extends AbstractConnection {
|
||||
}
|
||||
|
||||
public void setSchema(String schema) {
|
||||
if (schema != null && DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (schema != null && SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
schema = schema.toLowerCase();
|
||||
}
|
||||
this.schema = schema;
|
||||
@@ -184,7 +184,7 @@ public abstract class FrontendConnection extends AbstractConnection {
|
||||
String name = CharsetUtil.getCharset(ci);
|
||||
charsetName.setClient(name);
|
||||
charsetName.setResults(name);
|
||||
charsetName.setCollation(SystemVariables.getDefaultValue("collation_database"));
|
||||
charsetName.setCollation(SystemVariables.getSysVars().getDefaultValue("collation_database"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ public abstract class FrontendConnection extends AbstractConnection {
|
||||
writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown charset '" + charsetName.getClient() + "'");
|
||||
return;
|
||||
}
|
||||
if (db != null && DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (db != null && SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
db = db.toLowerCase();
|
||||
}
|
||||
// check schema
|
||||
@@ -425,7 +425,7 @@ public abstract class FrontendConnection extends AbstractConnection {
|
||||
hs.setSeed(rand1);
|
||||
hs.setServerCapabilities(getServerCapabilities());
|
||||
//TODO:CHECK
|
||||
int charsetIndex = CharsetUtil.getCharsetDefaultIndex(SystemVariables.getDefaultValue("character_set_server"));
|
||||
int charsetIndex = CharsetUtil.getCharsetDefaultIndex(SystemVariables.getSysVars().getDefaultValue("character_set_server"));
|
||||
hs.setServerCharsetIndex((byte) (charsetIndex & 0xff));
|
||||
hs.setServerStatus(2);
|
||||
hs.setRestOfScrambleBuff(rand2);
|
||||
|
||||
@@ -60,7 +60,7 @@ public class FrontendAuthenticator implements NIOHandler {
|
||||
auth.read(data);
|
||||
|
||||
//check mysql_native_password
|
||||
if (!"mysql_native_password".equals(auth.getAuthPlugin())) {
|
||||
if (auth.getAuthPlugin() != null && !"mysql_native_password".equals(auth.getAuthPlugin())) {
|
||||
failure(ErrorCode.ER_ACCESS_DENIED_ERROR, "only mysql_native_password auth check is supported");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package com.actiontech.dble.net.mysql;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.mysql.BufferUtil;
|
||||
import com.actiontech.dble.backend.mysql.MySQLMessage;
|
||||
import com.actiontech.dble.backend.mysql.StreamUtil;
|
||||
@@ -70,7 +70,7 @@ public class AuthPacket extends MySQLPacket {
|
||||
password = mm.readBytesWithLength();
|
||||
if (((clientFlags & Capabilities.CLIENT_CONNECT_WITH_DB) != 0) && mm.hasRemaining()) {
|
||||
database = mm.readStringWithNull();
|
||||
if (database != null && DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (database != null && SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
database = database.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package com.actiontech.dble.net.mysql;
|
||||
|
||||
import com.actiontech.dble.backend.mysql.CharsetUtil;
|
||||
import com.actiontech.dble.server.SystemVariables;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
public class CharsetNames {
|
||||
@@ -15,9 +15,9 @@ public class CharsetNames {
|
||||
private volatile String collation;
|
||||
|
||||
public CharsetNames() {
|
||||
this.client = SystemVariables.getDefaultValue("character_set_client");
|
||||
this.results = SystemVariables.getDefaultValue("character_set_results");
|
||||
this.collation = SystemVariables.getDefaultValue("collation_connection");
|
||||
this.client = SystemVariables.getSysVars().getDefaultValue("character_set_client");
|
||||
this.results = SystemVariables.getSysVars().getDefaultValue("character_set_results");
|
||||
this.collation = SystemVariables.getSysVars().getDefaultValue("collation_connection");
|
||||
}
|
||||
|
||||
public void setNames(String name, String collationName) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemField;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubselect;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubQuery;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.node.TableNode;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
@@ -39,14 +39,10 @@ public abstract class PlanNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* subQuery list
|
||||
* select subQuery list
|
||||
*/
|
||||
public List<ItemSubselect> getSubSelects() {
|
||||
return subSelects;
|
||||
}
|
||||
|
||||
public void setSubSelects(List<ItemSubselect> subSelects) {
|
||||
this.subSelects = subSelects;
|
||||
public List<ItemSubQuery> getSubQueries() {
|
||||
return subQueries;
|
||||
}
|
||||
|
||||
public enum PlanNodeType {
|
||||
@@ -120,12 +116,13 @@ public abstract class PlanNode {
|
||||
* is this node is subQuery
|
||||
*/
|
||||
protected boolean subQuery;
|
||||
protected boolean correlatedSubQuery;
|
||||
|
||||
protected boolean exsitView = false;
|
||||
|
||||
private HashSet<ItemSum> sumFuncs = new HashSet<>();
|
||||
|
||||
private List<ItemSubselect> subSelects = new ArrayList<>();
|
||||
private List<ItemSubQuery> subQueries = new ArrayList<>();
|
||||
|
||||
protected List<TableNode> referedTableNodes = new ArrayList<>();
|
||||
|
||||
@@ -295,6 +292,7 @@ public abstract class PlanNode {
|
||||
to.setLimitTo(this.limitTo);
|
||||
to.setSql(this.getSql());
|
||||
to.setSubQuery(subQuery);
|
||||
to.setCorrelatedSubQuery(correlatedSubQuery);
|
||||
to.setUnGlobalTableCount(unGlobalTableCount);
|
||||
to.setNoshardNode(noshardNode);
|
||||
}
|
||||
@@ -590,6 +588,15 @@ public abstract class PlanNode {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCorrelatedSubQuery() {
|
||||
return correlatedSubQuery;
|
||||
}
|
||||
|
||||
public void setCorrelatedSubQuery(boolean correlatedSubQuery) {
|
||||
this.correlatedSubQuery = correlatedSubQuery;
|
||||
}
|
||||
|
||||
public PlanNode having(Item having) {
|
||||
this.havingFilter = having;
|
||||
return this;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package com.actiontech.dble.plan.common.exception;
|
||||
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
|
||||
/**
|
||||
* MySQLOutPutException
|
||||
*
|
||||
@@ -23,7 +25,11 @@ public class MySQLOutPutException extends RuntimeException {
|
||||
public MySQLOutPutException(int errorCode, String sqlState, String msg) {
|
||||
super(msg);
|
||||
this.errorCode = errorCode;
|
||||
this.sqlState = sqlState;
|
||||
if (StringUtil.isEmpty(sqlState)) {
|
||||
this.sqlState = "HY000";
|
||||
} else {
|
||||
this.sqlState = sqlState;
|
||||
}
|
||||
}
|
||||
|
||||
public MySQLOutPutException(int errorCode, String sqlState, String msg, Throwable cause) {
|
||||
|
||||
@@ -90,6 +90,14 @@ public abstract class Item {
|
||||
this.withSubQuery = withSubQuery;
|
||||
}
|
||||
|
||||
public boolean isCorrelatedSubQuery() {
|
||||
return correlatedSubQuery;
|
||||
}
|
||||
|
||||
public void setCorrelatedSubQuery(boolean correlatedSubQuery) {
|
||||
this.correlatedSubQuery = correlatedSubQuery;
|
||||
}
|
||||
|
||||
public boolean isWithUnValAble() {
|
||||
return withUnValAble;
|
||||
}
|
||||
@@ -141,6 +149,7 @@ public abstract class Item {
|
||||
protected boolean withSumFunc;
|
||||
protected boolean withIsNull;
|
||||
protected boolean withSubQuery;
|
||||
protected boolean correlatedSubQuery;
|
||||
protected boolean withUnValAble;
|
||||
protected boolean fixed;
|
||||
protected ItemResult cmpContext;
|
||||
@@ -325,6 +334,50 @@ public abstract class Item {
|
||||
return result;
|
||||
}
|
||||
|
||||
public Item getResultItem() {
|
||||
FieldTypes fType;
|
||||
|
||||
FieldTypes i = fType = fieldType();
|
||||
if (i == FieldTypes.MYSQL_TYPE_TINY || i == FieldTypes.MYSQL_TYPE_SHORT || i == FieldTypes.MYSQL_TYPE_YEAR || i == FieldTypes.MYSQL_TYPE_INT24 || i == FieldTypes.MYSQL_TYPE_LONG || i == FieldTypes.MYSQL_TYPE_LONGLONG) {
|
||||
BigInteger bi = valInt();
|
||||
if (!nullValue) {
|
||||
return new ItemInt(bi.longValue());
|
||||
}
|
||||
} else if (i == FieldTypes.MYSQL_TYPE_FLOAT || i == FieldTypes.MYSQL_TYPE_DOUBLE) {
|
||||
BigDecimal bd = valReal();
|
||||
if (!nullValue) {
|
||||
return new ItemFloat(bd);
|
||||
}
|
||||
} else if (i == FieldTypes.MYSQL_TYPE_DATETIME || i == FieldTypes.MYSQL_TYPE_DATE || i == FieldTypes.MYSQL_TYPE_TIMESTAMP) {
|
||||
MySQLTime tm = new MySQLTime();
|
||||
getDate(tm, MyTime.TIME_FUZZY_DATE);
|
||||
if (!nullValue) {
|
||||
if (fType == FieldTypes.MYSQL_TYPE_DATE) {
|
||||
return new ItemString(MyTime.myDateToStr(tm));
|
||||
} else {
|
||||
return new ItemString(MyTime.myDatetimeToStr(tm, decimals));
|
||||
}
|
||||
}
|
||||
} else if (i == FieldTypes.MYSQL_TYPE_TIME) {
|
||||
MySQLTime tm = new MySQLTime();
|
||||
getTime(tm);
|
||||
if (!nullValue)
|
||||
return new ItemString(MyTime.myTimeToStrL(tm, decimals));
|
||||
} else {
|
||||
String res;
|
||||
if ((res = valStr()) != null) {
|
||||
return new ItemString(res);
|
||||
} else {
|
||||
assert (nullValue);
|
||||
BigInteger bi = valInt();
|
||||
if (!nullValue) {
|
||||
return new ItemInt(bi.longValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean valBool() {
|
||||
ItemResult i = resultType();
|
||||
if (i == ItemResult.INT_RESULT) {
|
||||
@@ -940,6 +993,7 @@ public abstract class Item {
|
||||
clone.withSumFunc = withSumFunc;
|
||||
clone.withIsNull = withIsNull;
|
||||
clone.withSubQuery = withSubQuery;
|
||||
clone.correlatedSubQuery = correlatedSubQuery;
|
||||
clone.withUnValAble = withUnValAble;
|
||||
clone.pushDownName = pushDownName;
|
||||
clone.getReferTables().addAll(getReferTables());
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ALL/ANY/SOME sub Query
|
||||
*/
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAllExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAnyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemAllAnySubQuery extends ItemMultiRowSubQuery {
|
||||
private boolean isAll;
|
||||
private SQLBinaryOperator operator;
|
||||
public ItemAllAnySubQuery(String currentDb, SQLBinaryOperator operator, SQLSelectQuery query, boolean isAll) {
|
||||
super(currentDb, query);
|
||||
this.isAll = isAll;
|
||||
this.operator = operator;
|
||||
if (this.planNode.getColumnsSelected().size() > 1) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPERAND_COLUMNS, "", "Operand should contain 1 column(s)");
|
||||
}
|
||||
this.select = this.planNode.getColumnsSelected().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubSelectType subType() {
|
||||
return isAll ? SubSelectType.ALL_SUBS : SubSelectType.ANY_SUBS;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
SQLSelect sqlSelect = new SQLSelect(query);
|
||||
if (isAll) {
|
||||
return new SQLAllExpr(sqlSelect);
|
||||
} else {
|
||||
return new SQLAnyExpr(sqlSelect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
|
||||
return new ItemAllAnySubQuery(this.currentDb, this.operator, this.query, this.isAll);
|
||||
}
|
||||
|
||||
public boolean isAll() {
|
||||
return isAll;
|
||||
}
|
||||
|
||||
public SQLBinaryOperator getOperator() {
|
||||
return operator;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ALL/ANY/SOME subselect
|
||||
*/
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.time.MySQLTime;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemAllanySubselect extends ItemSubselect {
|
||||
private boolean isAll;
|
||||
|
||||
/**
|
||||
* @param currentDb
|
||||
* @param query
|
||||
*/
|
||||
public ItemAllanySubselect(String currentDb, Item left, SQLSelectQuery query, boolean all) {
|
||||
super(currentDb, query);
|
||||
Item leftOprand = left;
|
||||
this.isAll = all;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubSelectType substype() {
|
||||
return isAll ? SubSelectType.ALL_SUBS : SubSelectType.ANY_SUBS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLengthAndDec() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal valReal() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger valInt() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String valStr() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal valDecimal() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDate(MySQLTime ltime, long fuzzydate) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTime(MySQLTime ltime) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+27
-52
@@ -2,21 +2,16 @@
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.common.context.NameResolutionContext;
|
||||
import com.actiontech.dble.plan.common.context.ReferContext;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemInt;
|
||||
import com.actiontech.dble.plan.common.time.MySQLTime;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLExistsExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
@@ -24,39 +19,24 @@ import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemInSubselect extends ItemSubselect {
|
||||
private boolean isNeg;
|
||||
private Item leftOprand;
|
||||
|
||||
/**
|
||||
* @param currentDb
|
||||
* @param query
|
||||
*/
|
||||
public ItemInSubselect(String currentDb, Item leftOprand, SQLSelectQuery query, boolean isNeg) {
|
||||
super(currentDb, query);
|
||||
this.leftOprand = leftOprand;
|
||||
this.isNeg = isNeg;
|
||||
public class ItemExistsSubQuery extends ItemSingleRowSubQuery {
|
||||
private boolean isNot;
|
||||
public ItemExistsSubQuery(String currentDb, SQLSelectQuery query, boolean isNot) {
|
||||
super(currentDb, query, false);
|
||||
this.isNot = isNot;
|
||||
if (!this.correlatedSubQuery) {
|
||||
if ((this.planNode.getLimitFrom() == -1)) {
|
||||
this.planNode.setLimitFrom(0);
|
||||
this.planNode.setLimitTo(1);
|
||||
} else if (this.planNode.getLimitTo() > 1) {
|
||||
this.planNode.setLimitTo(1);
|
||||
}
|
||||
this.select = new ItemInt(1L);
|
||||
this.planNode.getColumnsSelected().add(select);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLengthAndDec() {
|
||||
|
||||
}
|
||||
|
||||
public Item fixFields(NameResolutionContext context) {
|
||||
super.fixFields(context);
|
||||
leftOprand = leftOprand.fixFields(context);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* added to construct all refers in an item
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public void fixRefer(ReferContext context) {
|
||||
super.fixRefer(context);
|
||||
leftOprand.fixRefer(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,27 +69,22 @@ public class ItemInSubselect extends ItemSubselect {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
public Item getLeftOprand() {
|
||||
return leftOprand;
|
||||
}
|
||||
|
||||
public boolean isNeg() {
|
||||
return isNeg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
SQLExpr expr = leftOprand.toExpression();
|
||||
SQLSelect select = new SQLSelect(query);
|
||||
SQLInSubQueryExpr insub = new SQLInSubQueryExpr(select);
|
||||
insub.setExpr(expr);
|
||||
insub.setNot(isNeg);
|
||||
return insub;
|
||||
return new SQLExistsExpr(new SQLSelect(query), isNot);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "unexpected!");
|
||||
return new ItemExistsSubQuery(this.currentDb, this.query, this.isNot);
|
||||
}
|
||||
@Override
|
||||
public SubSelectType subType() {
|
||||
return SubSelectType.EXISTS_SUBS;
|
||||
}
|
||||
|
||||
public boolean isNot() {
|
||||
return isNot;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.common.context.NameResolutionContext;
|
||||
import com.actiontech.dble.plan.common.context.ReferContext;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemInSubQuery extends ItemMultiRowSubQuery {
|
||||
private boolean isNeg;
|
||||
protected Item leftOperand;
|
||||
|
||||
public ItemInSubQuery(String currentDb, Item leftOperand, SQLSelectQuery query, boolean isNeg) {
|
||||
super(currentDb, query);
|
||||
this.leftOperand = leftOperand;
|
||||
this.isNeg = isNeg;
|
||||
if (this.planNode.getColumnsSelected().size() > 1) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPERAND_COLUMNS, "", "Operand should contain 1 column(s)");
|
||||
}
|
||||
this.select = this.planNode.getColumnsSelected().get(0);
|
||||
}
|
||||
|
||||
public Item fixFields(NameResolutionContext context) {
|
||||
super.fixFields(context);
|
||||
leftOperand = leftOperand.fixFields(context);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* added to construct all refers in an item
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public void fixRefer(ReferContext context) {
|
||||
super.fixRefer(context);
|
||||
leftOperand.fixRefer(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubSelectType subType() {
|
||||
return SubSelectType.IN_SUBS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
SQLExpr expr = leftOperand.toExpression();
|
||||
SQLSelect sqlSelect = new SQLSelect(query);
|
||||
SQLInSubQueryExpr inSub = new SQLInSubQueryExpr(sqlSelect);
|
||||
inSub.setExpr(expr);
|
||||
inSub.setNot(isNeg);
|
||||
return inSub;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
|
||||
return new ItemInSubQuery(this.currentDb, this.leftOperand.cloneItem(), this.query, this.isNeg);
|
||||
}
|
||||
|
||||
public Item getLeftOperand() {
|
||||
return leftOperand;
|
||||
}
|
||||
|
||||
public boolean isNeg() {
|
||||
return isNeg;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
public class ItemMaxminSubselect extends ItemSinglerowSubselect {
|
||||
|
||||
/**
|
||||
* @param currentDb
|
||||
* @param query
|
||||
*/
|
||||
public ItemMaxminSubselect(String currentDb, SQLSelectQuery query, boolean max) {
|
||||
super(currentDb, query);
|
||||
boolean max1 = max;
|
||||
}
|
||||
|
||||
}
|
||||
+29
-29
@@ -10,80 +10,80 @@ package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.time.MySQLTime;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemExistsSubselect extends ItemSubselect {
|
||||
|
||||
public abstract class ItemMultiRowSubQuery extends ItemSubQuery {
|
||||
protected List<Item> value = new ArrayList<>();
|
||||
protected Item filed;
|
||||
protected Item select;
|
||||
/**
|
||||
* @param currentDb
|
||||
* @param query
|
||||
*/
|
||||
public ItemExistsSubselect(String currentDb, SQLSelectQuery query, boolean isNot) {
|
||||
public ItemMultiRowSubQuery(String currentDb, SQLSelectQuery query) {
|
||||
super(currentDb, query);
|
||||
boolean isNot1 = isNot;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLengthAndDec() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal valReal() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger valInt() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String valStr() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal valDecimal() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDate(MySQLTime ltime, long fuzzydate) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTime(MySQLTime ltime) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
|
||||
|
||||
public Item getSelect() {
|
||||
return select;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public void setSelect(Item select) {
|
||||
this.select = select;
|
||||
}
|
||||
|
||||
public Item getFiled() {
|
||||
return filed;
|
||||
}
|
||||
|
||||
public void setFiled(Item filed) {
|
||||
this.filed = filed;
|
||||
}
|
||||
|
||||
public List<Item> getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemScalarSubQuery extends ItemSingleRowSubQuery {
|
||||
|
||||
public ItemScalarSubQuery(String currentDb, SQLSelectQuery query) {
|
||||
super(currentDb, query, false);
|
||||
if (this.planNode.getColumnsSelected().size() > 1) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPERAND_COLUMNS, "", "Operand should contain 1 column(s)");
|
||||
}
|
||||
if (!this.correlatedSubQuery) {
|
||||
if ((this.planNode.getLimitFrom() == -1)) {
|
||||
this.planNode.setLimitFrom(0);
|
||||
this.planNode.setLimitTo(2);
|
||||
} else if (this.planNode.getLimitTo() > 2) {
|
||||
this.planNode.setLimitTo(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubSelectType subType() {
|
||||
return SubSelectType.SINGLEROW_SUBS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLengthAndDec() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
SQLSelect sqlSelect = new SQLSelect(query);
|
||||
SQLQueryExpr expr = new SQLQueryExpr(sqlSelect);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fieldList) {
|
||||
return new ItemScalarSubQuery(this.currentDb, this.query);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+35
-40
@@ -3,36 +3,26 @@
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.plan.common.field.Field;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.time.MySQLTime;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
private List<Item> row;
|
||||
/* row item fields*/
|
||||
private List<Field> fields;
|
||||
private Item value;
|
||||
private boolean noRows;
|
||||
public abstract class ItemSingleRowSubQuery extends ItemSubQuery {
|
||||
protected Item value;
|
||||
protected Item select;
|
||||
protected boolean isField;
|
||||
|
||||
public ItemSinglerowSubselect(String currentDb, SQLSelectQuery query) {
|
||||
public ItemSingleRowSubQuery(String currentDb, SQLSelectQuery query, boolean isField) {
|
||||
super(currentDb, query);
|
||||
this.select = this.planNode.getColumnsSelected().get(0);
|
||||
this.isField = isField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubSelectType substype() {
|
||||
return SubSelectType.SINGLEROW_SUBS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
@@ -43,7 +33,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public BigDecimal valReal() {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.valReal();
|
||||
} else {
|
||||
@@ -54,7 +44,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public BigInteger valInt() {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.valInt();
|
||||
} else {
|
||||
@@ -65,7 +55,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public String valStr() {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.valStr();
|
||||
} else {
|
||||
@@ -76,7 +66,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public BigDecimal valDecimal() {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.valDecimal();
|
||||
} else {
|
||||
@@ -87,7 +77,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public boolean getDate(MySQLTime ltime, long fuzzydate) {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.getDate(ltime, fuzzydate);
|
||||
} else {
|
||||
@@ -98,7 +88,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public boolean getTime(MySQLTime ltime) {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.getTime(ltime);
|
||||
} else {
|
||||
@@ -109,7 +99,7 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
@Override
|
||||
public boolean valBool() {
|
||||
if (!noRows && !execute() && !value.isNullValue()) {
|
||||
if (!execute() && !value.isNullValue()) {
|
||||
nullValue = false;
|
||||
return value.valBool();
|
||||
} else {
|
||||
@@ -123,25 +113,30 @@ public class ItemSinglerowSubselect extends ItemSubselect {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpr toExpression() {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fieldList) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/*--------------------------------------getter/setter-----------------------------------*/
|
||||
public List<Field> getFields() {
|
||||
return fields;
|
||||
|
||||
public Item getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setFields(List<Field> fields) {
|
||||
this.fields = fields;
|
||||
public void setValue(Item value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Item getSelect() {
|
||||
return select;
|
||||
}
|
||||
|
||||
public void setSelect(Item select) {
|
||||
this.select = select;
|
||||
}
|
||||
|
||||
public boolean isField() {
|
||||
return isField;
|
||||
}
|
||||
|
||||
public void setField(boolean field) {
|
||||
isField = field;
|
||||
}
|
||||
|
||||
}
|
||||
+12
-14
@@ -8,31 +8,29 @@
|
||||
*/
|
||||
package com.actiontech.dble.plan.common.item.subquery;
|
||||
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.PlanNode.PlanNodeType;
|
||||
import com.actiontech.dble.plan.common.context.NameResolutionContext;
|
||||
import com.actiontech.dble.plan.common.context.ReferContext;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemResultField;
|
||||
import com.actiontech.dble.plan.visitor.MySQLPlanNodeVisitor;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
|
||||
public abstract class ItemSubselect extends ItemResultField {
|
||||
public abstract class ItemSubQuery extends ItemResultField {
|
||||
protected SQLSelectQuery query;
|
||||
private String currentDb;
|
||||
private PlanNode planNode;
|
||||
protected String currentDb;
|
||||
protected PlanNode planNode;
|
||||
|
||||
public enum SubSelectType {
|
||||
UNKNOWN_SUBS, SINGLEROW_SUBS, EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS
|
||||
}
|
||||
|
||||
public SubSelectType substype() {
|
||||
public SubSelectType subType() {
|
||||
return SubSelectType.UNKNOWN_SUBS;
|
||||
}
|
||||
|
||||
public ItemSubselect(String currentDb, SQLSelectQuery query) {
|
||||
public ItemSubQuery(String currentDb, SQLSelectQuery query) {
|
||||
this.query = query;
|
||||
this.currentDb = currentDb;
|
||||
init();
|
||||
@@ -49,6 +47,12 @@ public abstract class ItemSubselect extends ItemResultField {
|
||||
this.planNode = pv.getTableNode();
|
||||
if (planNode.type() != PlanNodeType.NONAME) {
|
||||
this.withSubQuery = true;
|
||||
PlanNode test = this.planNode.copy();
|
||||
try {
|
||||
test.setUpFields();
|
||||
} catch (Exception e) {
|
||||
this.correlatedSubQuery = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +68,7 @@ public abstract class ItemSubselect extends ItemResultField {
|
||||
|
||||
@Override
|
||||
public boolean fixFields() {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_QUERYHANDLER, "", "not supported!");
|
||||
return false;
|
||||
}
|
||||
|
||||
public Item fixFields(NameResolutionContext context) {
|
||||
@@ -80,8 +84,6 @@ public abstract class ItemSubselect extends ItemResultField {
|
||||
public void fixRefer(ReferContext context) {
|
||||
if (context.isPushDownNode())
|
||||
return;
|
||||
else
|
||||
context.getPlanNode().getSubSelects().add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,8 +104,4 @@ public abstract class ItemSubselect extends ItemResultField {
|
||||
this.planNode = planNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not supported!");
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,8 @@ import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.util.ToStringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NoNameNode eg:select 1,only exists selecteditems
|
||||
@@ -48,10 +46,6 @@ public class NoNameNode extends PlanNode {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TableNode> getReferedTableNodes() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public String getCatalog() {
|
||||
return this.catalog;
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.util.ToStringUtil;
|
||||
|
||||
/*
|
||||
* query a logic table
|
||||
* query a logic table ,in fact, it is derived sub query
|
||||
*/
|
||||
public class QueryNode extends PlanNode {
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.plan.node;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.config.ServerConfig;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.config.model.TableConfig;
|
||||
@@ -40,7 +41,7 @@ public class TableNode extends PlanNode {
|
||||
this.schema = catalog;
|
||||
this.tableName = tableName;
|
||||
ServerConfig config = DbleServer.getInstance().getConfig();
|
||||
if (config.getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
this.schema = this.schema.toLowerCase();
|
||||
this.tableName = this.tableName.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@ public final class ViewUtil {
|
||||
boolean selectsAllowMerge = viewSelNode.type() != PlanNode.PlanNodeType.MERGE;
|
||||
// TODO as the same as LEX::can_be_merged();
|
||||
boolean existAggr = PlanUtil.existAggr(viewSelNode);
|
||||
return selectsAllowMerge && viewSelNode.getReferedTableNodes().size() >= 1 && !existAggr;
|
||||
return selectsAllowMerge && viewSelNode.getReferedTableNodes().size() == 1 && !existAggr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,10 +524,10 @@ public class ERJoinChooser {
|
||||
//TODO:performance
|
||||
|
||||
private boolean isGlobalTree(PlanNode tn) {
|
||||
if (tn instanceof TableNode) {
|
||||
if (tn instanceof TableNode && tn.getSubQueries().size() == 0) {
|
||||
return tn.getUnGlobalTableCount() == 0;
|
||||
} else if (tn.type() == PlanNode.PlanNodeType.NONAME) {
|
||||
return true;
|
||||
return tn.getSubQueries().size() == 0;
|
||||
} else {
|
||||
for (TableNode leaf : tn.getReferedTableNodes()) {
|
||||
if (leaf.getUnGlobalTableCount() != 0)
|
||||
|
||||
@@ -185,6 +185,8 @@ public final class FilterPreProcessor {
|
||||
if (!inMap.containsKey(a))
|
||||
inMap.put(a, new HashSet<Item>());
|
||||
inMap.get(a).add(b);
|
||||
} else { // stop convert
|
||||
return filter;
|
||||
}
|
||||
} else {
|
||||
Item subNew = convertOrToIn(subFilter);
|
||||
|
||||
@@ -7,6 +7,7 @@ package com.actiontech.dble.plan.optimizer;
|
||||
|
||||
import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.PlanNode.PlanNodeType;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubQuery;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
|
||||
@@ -27,18 +28,24 @@ public final class GlobalTableProcessor {
|
||||
* @return true:parent node maybe is global;false parent node must not be global
|
||||
*/
|
||||
private static boolean initGlobalStatus(PlanNode tn) {
|
||||
if (tn == null || tn.type() == PlanNodeType.TABLE)
|
||||
if (tn == null || ((tn.type() == PlanNodeType.TABLE || tn.type() == PlanNodeType.NONAME) && tn.getSubQueries().size() == 0)) {
|
||||
return true;
|
||||
}
|
||||
boolean status = true;
|
||||
|
||||
for (PlanNode child : tn.getChildren()) {
|
||||
boolean ret = initGlobalStatus(child);
|
||||
if (status) {
|
||||
status = ret;
|
||||
}
|
||||
}
|
||||
for (ItemSubQuery subQuery : tn.getSubQueries()) {
|
||||
boolean ret = initGlobalStatus(subQuery.getPlanNode());
|
||||
if (status) {
|
||||
status = ret;
|
||||
}
|
||||
}
|
||||
if (PlanUtil.isERNode(tn)) {
|
||||
// treat erjoin as an unglobaltable
|
||||
// treat er join as an un global table
|
||||
tn.setUnGlobalTableCount(1);
|
||||
Set<String> newSet = new HashSet<>();
|
||||
newSet.addAll(tn.getReferedTableNodes().get(0).getNoshardNode());
|
||||
@@ -90,38 +97,51 @@ public final class GlobalTableProcessor {
|
||||
|
||||
private static int calcUnGlobalCount(PlanNode tn) {
|
||||
int unGlobalCount = 0;
|
||||
for (ItemSubQuery subQuery : tn.getSubQueries()) {
|
||||
PlanNode subNode = subQuery.getPlanNode();
|
||||
resetNoShardNode(tn, subNode);
|
||||
unGlobalCount += subNode.getUnGlobalTableCount();
|
||||
}
|
||||
for (PlanNode tnChild : tn.getChildren()) {
|
||||
if (tnChild != null) {
|
||||
if (tn.getNoshardNode() == null) {
|
||||
if (tnChild.getNoshardNode() != null) {
|
||||
Set<String> parentSet = new HashSet<>();
|
||||
parentSet.addAll(tnChild.getNoshardNode());
|
||||
tn.setNoshardNode(parentSet);
|
||||
}
|
||||
}
|
||||
if (tn.getNoshardNode() != null) {
|
||||
tn.getNoshardNode().retainAll(tnChild.getNoshardNode());
|
||||
}
|
||||
resetNoShardNode(tn, tnChild);
|
||||
unGlobalCount += tnChild.getUnGlobalTableCount();
|
||||
}
|
||||
}
|
||||
return unGlobalCount;
|
||||
}
|
||||
|
||||
private static void resetNoShardNode(PlanNode tn, PlanNode tnChild) {
|
||||
if (tn.getNoshardNode() == null) {
|
||||
if (tnChild.getNoshardNode() != null) {
|
||||
Set<String> parentSet = new HashSet<>();
|
||||
parentSet.addAll(tnChild.getNoshardNode());
|
||||
tn.setNoshardNode(parentSet);
|
||||
}
|
||||
}
|
||||
if (tn.getNoshardNode() != null) {
|
||||
if (tnChild.getNoshardNode() != null) {
|
||||
tn.getNoshardNode().retainAll(tnChild.getNoshardNode());
|
||||
} else {
|
||||
tn.setNoshardNode(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGlobalTableBigEnough(JoinNode jn) {
|
||||
PlanNode left = jn.getLeftNode();
|
||||
PlanNode right = jn.getRightNode();
|
||||
PlanNode global, noraml;
|
||||
PlanNode global, normal;
|
||||
if (left.getUnGlobalTableCount() == 0) {
|
||||
global = left;
|
||||
noraml = right;
|
||||
normal = right;
|
||||
} else {
|
||||
global = right;
|
||||
noraml = left;
|
||||
normal = left;
|
||||
}
|
||||
Set<String> result = new HashSet<>();
|
||||
result.addAll(global.getNoshardNode());
|
||||
Set<String> normalSet = noraml.getNoshardNode();
|
||||
Set<String> normalSet = normal.getNoshardNode();
|
||||
result.retainAll(normalSet);
|
||||
return result.size() == normalSet.size();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
|
||||
public final class JoinStrategyProcessor {
|
||||
public static final String NEED_REPLACE = "{NEED_TO_REPLACE}";
|
||||
private JoinStrategyProcessor() {
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,15 @@ import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.plan.PlanNode;
|
||||
import com.actiontech.dble.plan.common.exception.MySQLOutPutException;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubQuery;
|
||||
import com.actiontech.dble.plan.node.TableNode;
|
||||
import com.actiontech.dble.route.util.RouterUtil;
|
||||
import com.actiontech.dble.server.util.SchemaUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class MyOptimizer {
|
||||
@@ -26,7 +29,8 @@ public final class MyOptimizer {
|
||||
try {
|
||||
// PreProcessor SubQuery
|
||||
node = SubQueryPreProcessor.optimize(node);
|
||||
int existGlobal = checkGlobalTable(node);
|
||||
updateReferedTableNodes(node);
|
||||
int existGlobal = checkGlobalTable(node, new HashSet<String>());
|
||||
if (node.isExsitView() || existGlobal != 1) {
|
||||
// optimizer subquery
|
||||
node = SubQueryProcessor.optimize(node);
|
||||
@@ -64,6 +68,20 @@ public final class MyOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<TableNode> updateReferedTableNodes(PlanNode node) {
|
||||
List<TableNode> subTables = new ArrayList<>();
|
||||
for (PlanNode childNode : node.getChildren()) {
|
||||
List<TableNode> childSubTables = updateReferedTableNodes(childNode);
|
||||
node.getReferedTableNodes().addAll(childSubTables);
|
||||
subTables.addAll(childSubTables);
|
||||
}
|
||||
for (ItemSubQuery subQuery : node.getSubQueries()) {
|
||||
List<TableNode> childSubTables = subQuery.getPlanNode().getReferedTableNodes();
|
||||
node.getReferedTableNodes().addAll(childSubTables);
|
||||
subTables.addAll(childSubTables);
|
||||
}
|
||||
return subTables;
|
||||
}
|
||||
/**
|
||||
* existShardTable
|
||||
*
|
||||
@@ -72,7 +90,10 @@ public final class MyOptimizer {
|
||||
* return -1 if all the table is not global table,need not global optimizer;
|
||||
* return 0 for other ,may need to global optimizer ;
|
||||
*/
|
||||
public static int checkGlobalTable(PlanNode node) {
|
||||
public static int checkGlobalTable(PlanNode node, Set<String> resultDataNodes) {
|
||||
if (node.isSubQuery()) {
|
||||
return 0;
|
||||
}
|
||||
Set<String> dataNodes = null;
|
||||
boolean isAllGlobal = true;
|
||||
boolean isContainGlobal = false;
|
||||
@@ -102,9 +123,11 @@ public final class MyOptimizer {
|
||||
String db = SchemaUtil.getRandomDb();
|
||||
SchemaConfig schemaConfig = DbleServer.getInstance().getConfig().getSchemas().get(db);
|
||||
node.setNoshardNode(schemaConfig.getAllDataNodes());
|
||||
resultDataNodes.addAll(schemaConfig.getAllDataNodes());
|
||||
return 1;
|
||||
} else if (dataNodes.size() > 0) { //all global table
|
||||
node.setNoshardNode(dataNodes);
|
||||
resultDataNodes.addAll(dataNodes);
|
||||
String sql = node.getSql();
|
||||
for (TableNode tn : node.getReferedTableNodes()) {
|
||||
sql = RouterUtil.removeSchema(sql, tn.getSchema());
|
||||
@@ -115,10 +138,7 @@ public final class MyOptimizer {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!isContainGlobal) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.actiontech.dble.plan.common.item.ItemField;
|
||||
import com.actiontech.dble.plan.common.item.ItemInt;
|
||||
import com.actiontech.dble.plan.common.item.function.ItemFunc;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubQuery;
|
||||
import com.actiontech.dble.plan.node.MergeNode;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
|
||||
@@ -58,6 +59,11 @@ public final class SelectedProcessor {
|
||||
if (qtn.type() == PlanNode.PlanNodeType.MERGE) {
|
||||
return mergePushSelected((MergeNode) qtn, toPushColumns);
|
||||
} else {
|
||||
if (qtn.getSubQueries().size() > 0) {
|
||||
for (ItemSubQuery itemSubQuery : qtn.getSubQueries()) {
|
||||
pushSelected(itemSubQuery.getPlanNode(), new HashSet<Item>());
|
||||
}
|
||||
}
|
||||
if (toPushColumns.isEmpty()) {
|
||||
qtn.setUpRefers(isPushDownNode);
|
||||
} else if (qtn.isDistinct()) {
|
||||
|
||||
@@ -14,13 +14,14 @@ import com.actiontech.dble.plan.common.item.Item.ItemType;
|
||||
import com.actiontech.dble.plan.common.item.ItemField;
|
||||
import com.actiontech.dble.plan.common.item.ItemInt;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.ItemBoolFunc2;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.*;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondAnd;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondOr;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemInSubselect;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSubselect;
|
||||
import com.actiontech.dble.plan.common.item.subquery.*;
|
||||
import com.actiontech.dble.plan.common.ptr.BoolPtr;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
import com.actiontech.dble.plan.util.FilterUtils;
|
||||
import com.actiontech.dble.plan.util.PlanUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -35,78 +36,109 @@ public final class SubQueryPreProcessor {
|
||||
|
||||
public static PlanNode optimize(PlanNode qtn) {
|
||||
MergeHavingFilter.optimize(qtn);
|
||||
qtn = findComparisonsSubQueryToJoinNode(qtn);
|
||||
qtn = findComparisonsSubQueryToJoinNode(qtn, new BoolPtr(false));
|
||||
return qtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* http://dev.mysql.com/doc/refman/5.0/en/comparisons-using-subqueries.html
|
||||
*/
|
||||
private static PlanNode findComparisonsSubQueryToJoinNode(PlanNode qtn) {
|
||||
private static PlanNode findComparisonsSubQueryToJoinNode(PlanNode qtn, BoolPtr childTransform) {
|
||||
for (int i = 0; i < qtn.getChildren().size(); i++) {
|
||||
PlanNode child = qtn.getChildren().get(i);
|
||||
qtn.getChildren().set(i, findComparisonsSubQueryToJoinNode(child));
|
||||
qtn.getChildren().set(i, findComparisonsSubQueryToJoinNode(child, childTransform));
|
||||
}
|
||||
|
||||
SubQueryAndFilter find = new SubQueryAndFilter();
|
||||
SubQueryFilter find = new SubQueryFilter();
|
||||
find.query = qtn;
|
||||
find.filter = null;
|
||||
Item where = qtn.getWhereFilter();
|
||||
SubQueryAndFilter result = buildSubQuery(find, where);
|
||||
SubQueryFilter result = buildSubQuery(qtn, find, where, false, childTransform);
|
||||
if (result != find) {
|
||||
// that means where filter only contains subquery,just replace it
|
||||
// that means where filter only contains sub query,just replace it
|
||||
result.query.query(result.filter);
|
||||
qtn.query(null);
|
||||
// change result.filter and rebuild
|
||||
result.query.setUpFields();
|
||||
childTransform.set(true);
|
||||
return result.query;
|
||||
} else {
|
||||
if (childTransform.get()) {
|
||||
qtn.setUpFields();
|
||||
}
|
||||
return qtn;
|
||||
}
|
||||
}
|
||||
|
||||
private static SubQueryAndFilter buildSubQuery(SubQueryAndFilter qtn, Item filter) {
|
||||
private static SubQueryFilter buildSubQuery(PlanNode node, SubQueryFilter qtn, Item filter, boolean isOrChild, BoolPtr childTransform) {
|
||||
if (filter == null)
|
||||
return qtn;
|
||||
if (!filter.isWithSubQuery()) {
|
||||
qtn.filter = filter;
|
||||
} else if (filter instanceof ItemCondOr) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support 'or' when condition subquery");
|
||||
return buildSubQueryWithOrFilter(node, qtn, (ItemCondOr) filter, childTransform);
|
||||
} else if (filter instanceof ItemCondAnd) {
|
||||
return buildSubQueryWithAndFilter(qtn, (ItemCondAnd) filter);
|
||||
return buildSubQueryWithAndFilter(node, qtn, (ItemCondAnd) filter, isOrChild, childTransform);
|
||||
} else {
|
||||
return buildSubQueryByFilter(qtn, filter);
|
||||
return buildSubQueryByFilter(node, qtn, filter, isOrChild, childTransform);
|
||||
}
|
||||
return qtn;
|
||||
}
|
||||
|
||||
private static SubQueryAndFilter buildSubQueryByFilter(SubQueryAndFilter qtn, Item filter) {
|
||||
Item leftColumn;
|
||||
PlanNode query;
|
||||
boolean isNotIn = false;
|
||||
boolean needExchange = false;
|
||||
if (isCmpFunc(filter)) {
|
||||
private static SubQueryFilter buildSubQueryByFilter(PlanNode node, SubQueryFilter qtn, Item filter, boolean isOrChild, BoolPtr childTransform) {
|
||||
if (filter instanceof ItemInSubQuery && !isOrChild) {
|
||||
return transformInSubQuery(qtn, (ItemInSubQuery) filter, childTransform);
|
||||
} else if (filter instanceof ItemInSubQuery) {
|
||||
addSubQuey(node, (ItemInSubQuery) filter, childTransform);
|
||||
return qtn;
|
||||
} else if (PlanUtil.isCmpFunc(filter)) {
|
||||
ItemBoolFunc2 eqFilter = (ItemBoolFunc2) filter;
|
||||
Item arg0 = eqFilter.arguments().get(0);
|
||||
Item arg1 = eqFilter.arguments().get(1);
|
||||
boolean arg0IsSubQuery = arg0.type().equals(ItemType.SUBSELECT_ITEM);
|
||||
boolean arg1IsSubQuery = arg1.type().equals(ItemType.SUBSELECT_ITEM);
|
||||
if (arg0IsSubQuery && arg1IsSubQuery) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "",
|
||||
"left and right both condition subquery,not supported...");
|
||||
if (arg0.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (arg0 instanceof ItemScalarSubQuery) {
|
||||
addSubQuey(node, (ItemScalarSubQuery) arg0, childTransform);
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
}
|
||||
}
|
||||
needExchange = arg0IsSubQuery;
|
||||
leftColumn = arg0IsSubQuery ? arg1 : arg0;
|
||||
query = arg0IsSubQuery ? ((ItemSubselect) arg0).getPlanNode() : ((ItemSubselect) arg1).getPlanNode();
|
||||
} else if (filter instanceof ItemInSubselect) {
|
||||
ItemInSubselect inSub = (ItemInSubselect) filter;
|
||||
leftColumn = inSub.getLeftOprand();
|
||||
query = inSub.getPlanNode();
|
||||
isNotIn = inSub.isNeg();
|
||||
|
||||
Item arg1 = eqFilter.arguments().get(1);
|
||||
if (arg1.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (arg1 instanceof ItemScalarSubQuery) {
|
||||
addSubQuey(node, (ItemScalarSubQuery) arg1, childTransform);
|
||||
} else if (arg1 instanceof ItemAllAnySubQuery) {
|
||||
addSubQuey(node, (ItemAllAnySubQuery) arg1, childTransform);
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
}
|
||||
}
|
||||
return qtn;
|
||||
} else if (filter.type().equals(ItemType.SUBSELECT_ITEM)) {
|
||||
if (filter instanceof ItemExistsSubQuery) {
|
||||
addSubQuey(node, (ItemExistsSubQuery) filter, childTransform);
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
}
|
||||
return qtn;
|
||||
} else {
|
||||
//todo: when happened?
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not support subquery of:" + filter.type());
|
||||
}
|
||||
query = findComparisonsSubQueryToJoinNode(query);
|
||||
}
|
||||
|
||||
private static void addSubQuey(PlanNode node, ItemSubQuery subQuery, BoolPtr childTransform) {
|
||||
node.getSubQueries().add(subQuery);
|
||||
PlanNode subNode = findComparisonsSubQueryToJoinNode(subQuery.getPlanNode(), childTransform);
|
||||
subQuery.setPlanNode(subNode);
|
||||
}
|
||||
|
||||
private static SubQueryFilter transformInSubQuery(SubQueryFilter qtn, ItemInSubQuery filter, BoolPtr childTransform) {
|
||||
Item leftColumn = filter.getLeftOperand();
|
||||
PlanNode query = filter.getPlanNode();
|
||||
query = findComparisonsSubQueryToJoinNode(query, childTransform);
|
||||
if (StringUtils.isEmpty(query.getAlias()))
|
||||
query.alias(AUTOALIAS + query.getPureName());
|
||||
if (query.getColumnsSelected().size() != 1)
|
||||
@@ -114,7 +146,7 @@ public final class SubQueryPreProcessor {
|
||||
query.setSubQuery(true).setDistinct(true);
|
||||
|
||||
final List<Item> newSelects = qtn.query.getColumnsSelected();
|
||||
SubQueryAndFilter result = new SubQueryAndFilter();
|
||||
SubQueryFilter result = new SubQueryFilter();
|
||||
Item rightColumn = query.getColumnsSelected().get(0);
|
||||
qtn.query.setColumnsSelected(new ArrayList<Item>());
|
||||
String rightJoinName = rightColumn.getAlias();
|
||||
@@ -130,7 +162,7 @@ public final class SubQueryPreProcessor {
|
||||
ItemField rightJoinColumn = new ItemField(null, query.getAlias(), rightJoinName);
|
||||
// rename the left column's table name
|
||||
result.query = new JoinNode(qtn.query, query);
|
||||
// leave origin sqlto new join node
|
||||
// leave origin sql to new join node
|
||||
result.query.setSql(qtn.query.getSql());
|
||||
qtn.query.setSql(null);
|
||||
result.query.select(newSelects);
|
||||
@@ -154,13 +186,13 @@ public final class SubQueryPreProcessor {
|
||||
result.query.setLimitTo(qtn.query.getLimitTo());
|
||||
qtn.query.setLimitTo(-1);
|
||||
}
|
||||
if (isNotIn) {
|
||||
if (filter.isNeg()) {
|
||||
((JoinNode) result.query).setLeftOuterJoin().setNotIn(true);
|
||||
ItemFuncEqual joinFilter = FilterUtils.equal(leftColumn, rightJoinColumn);
|
||||
((JoinNode) result.query).addJoinFilter(joinFilter);
|
||||
result.filter = null;
|
||||
} else {
|
||||
Item joinFilter = calcJoinFilter(filter, leftColumn, needExchange, rightJoinColumn);
|
||||
Item joinFilter = FilterUtils.equal(leftColumn, rightJoinColumn);
|
||||
result.query.query(joinFilter);
|
||||
result.filter = joinFilter;
|
||||
}
|
||||
@@ -178,54 +210,31 @@ public final class SubQueryPreProcessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isCmpFunc(Item filter) {
|
||||
return filter instanceof ItemFuncEqual || filter instanceof ItemFuncGt || filter instanceof ItemFuncGe ||
|
||||
filter instanceof ItemFuncLt || filter instanceof ItemFuncLe || filter instanceof ItemFuncNe ||
|
||||
filter instanceof ItemFuncStrictEqual;
|
||||
}
|
||||
|
||||
private static Item calcJoinFilter(Item filter, Item leftColumn, boolean needExchange, ItemField rightJoinColumn) {
|
||||
Item joinFilter;
|
||||
if (((filter instanceof ItemFuncGt) && !needExchange) ||
|
||||
((filter instanceof ItemFuncLt) && needExchange)) {
|
||||
joinFilter = FilterUtils.greaterThan(leftColumn, rightJoinColumn);
|
||||
} else if (((filter instanceof ItemFuncLt) && !needExchange) ||
|
||||
((filter instanceof ItemFuncGt) && needExchange)) {
|
||||
joinFilter = FilterUtils.lessThan(leftColumn, rightJoinColumn);
|
||||
} else if (((filter instanceof ItemFuncGe) && !needExchange) ||
|
||||
((filter instanceof ItemFuncLe) && needExchange)) {
|
||||
joinFilter = FilterUtils.greaterEqual(leftColumn, rightJoinColumn);
|
||||
} else if (((filter instanceof ItemFuncLe) && !needExchange) ||
|
||||
((filter instanceof ItemFuncGe) && needExchange)) {
|
||||
joinFilter = FilterUtils.lessEqual(leftColumn, rightJoinColumn);
|
||||
} else if (filter instanceof ItemFuncNe) {
|
||||
joinFilter = FilterUtils.notEqual(leftColumn, rightJoinColumn);
|
||||
} else {
|
||||
//equal or in
|
||||
joinFilter = FilterUtils.equal(leftColumn, rightJoinColumn);
|
||||
private static SubQueryFilter buildSubQueryWithOrFilter(PlanNode node, SubQueryFilter qtn, ItemCondOr filter, BoolPtr childTransform) {
|
||||
for (int index = 0; index < filter.getArgCount(); index++) {
|
||||
buildSubQuery(node, qtn, filter.arguments().get(index), true, childTransform);
|
||||
}
|
||||
return joinFilter;
|
||||
return qtn;
|
||||
}
|
||||
|
||||
private static SubQueryAndFilter buildSubQueryWithAndFilter(SubQueryAndFilter qtn, ItemCondAnd filter) {
|
||||
ItemCondAnd andFilter = filter;
|
||||
for (int index = 0; index < andFilter.getArgCount(); index++) {
|
||||
SubQueryAndFilter result = buildSubQuery(qtn, andFilter.arguments().get(index));
|
||||
private static SubQueryFilter buildSubQueryWithAndFilter(PlanNode node, SubQueryFilter qtn, ItemCondAnd filter, boolean isOrChild, BoolPtr childTransform) {
|
||||
for (int index = 0; index < filter.getArgCount(); index++) {
|
||||
SubQueryFilter result = buildSubQuery(node, qtn, filter.arguments().get(index), isOrChild, childTransform);
|
||||
if (result != qtn) {
|
||||
if (result.filter == null) {
|
||||
result.filter = new ItemInt(1);
|
||||
}
|
||||
andFilter.arguments().set(index, result.filter);
|
||||
filter.arguments().set(index, result.filter);
|
||||
qtn = result;
|
||||
}
|
||||
}
|
||||
qtn.filter = andFilter;
|
||||
qtn.filter = filter;
|
||||
return qtn;
|
||||
}
|
||||
|
||||
private static class SubQueryAndFilter {
|
||||
private static class SubQueryFilter {
|
||||
|
||||
PlanNode query; // subQuery may change querynode to join node
|
||||
PlanNode query; // subQuery may change query node to join node
|
||||
Item filter; // sub query's filter
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,8 @@ public final class SubQueryProcessor {
|
||||
private static void mergeWhere(PlanNode parent, PlanNode child) {
|
||||
Item pWhere = parent.getWhereFilter();
|
||||
Item pWhere0 = PlanUtil.pushDownItem(parent, pWhere, true);
|
||||
Item mWhere = FilterUtils.and(pWhere0, child.getWhereFilter());
|
||||
Item childWhere = PlanUtil.pushDownItem(child, child.getWhereFilter(), true);
|
||||
Item mWhere = FilterUtils.and(pWhere0, childWhere);
|
||||
child.setWhereFilter(mWhere);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.actiontech.dble.plan.common.item.ItemBasicConstant;
|
||||
import com.actiontech.dble.plan.common.item.ItemField;
|
||||
import com.actiontech.dble.plan.common.item.function.ItemFunc;
|
||||
import com.actiontech.dble.plan.common.item.function.ItemFunc.Functype;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.*;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum;
|
||||
import com.actiontech.dble.plan.common.item.function.sumfunc.ItemSum.SumFuncType;
|
||||
import com.actiontech.dble.plan.node.JoinNode;
|
||||
@@ -356,4 +356,10 @@ public final class PlanUtil {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public static boolean isCmpFunc(Item filter) {
|
||||
return filter instanceof ItemFuncEqual || filter instanceof ItemFuncGt || filter instanceof ItemFuncGe ||
|
||||
filter instanceof ItemFuncLt || filter instanceof ItemFuncLe || filter instanceof ItemFuncNe ||
|
||||
filter instanceof ItemFuncStrictEqual;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,13 +36,12 @@ import com.actiontech.dble.plan.common.item.function.timefunc.ItemDateAddInterva
|
||||
import com.actiontech.dble.plan.common.item.function.timefunc.ItemExtract;
|
||||
import com.actiontech.dble.plan.common.item.function.timefunc.ItemFuncTimestampDiff;
|
||||
import com.actiontech.dble.plan.common.item.function.unknown.ItemFuncUnknown;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemInSubselect;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemSinglerowSubselect;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemAllAnySubQuery;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemExistsSubQuery;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemInSubQuery;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemScalarSubQuery;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
import com.alibaba.druid.sql.ast.SQLDataType;
|
||||
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderBy;
|
||||
import com.alibaba.druid.sql.ast.*;
|
||||
import com.alibaba.druid.sql.ast.expr.*;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
@@ -92,7 +91,9 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
@Override
|
||||
public void endVisit(SQLQueryExpr x) {
|
||||
SQLSelectQuery sqlSelect = x.getSubQuery().getQuery();
|
||||
item = new ItemSinglerowSubselect(currentDb, sqlSelect);
|
||||
item = new ItemScalarSubQuery(currentDb, sqlSelect);
|
||||
initName(x);
|
||||
item.setItemName(item.getItemName().replaceAll("\n\\t", " "));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,7 +106,7 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
public void endVisit(SQLInSubQueryExpr x) {
|
||||
boolean isNeg = x.isNot();
|
||||
Item left = getItem(x.getExpr());
|
||||
item = new ItemInSubselect(currentDb, left, x.getSubQuery().getQuery(), isNeg);
|
||||
item = new ItemInSubQuery(currentDb, left, x.getSubQuery().getQuery(), isNeg);
|
||||
initName(x);
|
||||
}
|
||||
|
||||
@@ -123,6 +124,10 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
public void endVisit(SQLBinaryOpExpr x) {
|
||||
Item itemLeft = getItem(x.getLeft());
|
||||
Item itemRight = getItem(x.getRight());
|
||||
if (itemRight instanceof ItemInSubQuery) {
|
||||
item = itemRight;
|
||||
return;
|
||||
}
|
||||
switch (x.getOperator()) {
|
||||
case Is:
|
||||
// is null, or is unknown
|
||||
@@ -258,6 +263,8 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
default:
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not supported kind expression:" + x.getOperator());
|
||||
}
|
||||
item.setWithSubQuery(itemLeft.isWithSubQuery() || itemRight.isWithSubQuery());
|
||||
item.setCorrelatedSubQuery(itemLeft.isCorrelatedSubQuery() || itemRight.isCorrelatedSubQuery());
|
||||
initName(x);
|
||||
}
|
||||
|
||||
@@ -285,6 +292,8 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "",
|
||||
"not supported kind expression:" + x.getOperator());
|
||||
}
|
||||
item.setWithSubQuery(a.isWithSubQuery());
|
||||
item.setCorrelatedSubQuery(a.isCorrelatedSubQuery());
|
||||
initName(x);
|
||||
}
|
||||
|
||||
@@ -616,25 +625,42 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLAllExpr x) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "Subqueries with All is not supported");
|
||||
SQLObject parent = x.getParent();
|
||||
if (parent instanceof SQLBinaryOpExpr) {
|
||||
handleAnySubQuery((SQLBinaryOpExpr) parent, x.getSubQuery().getQuery(), true);
|
||||
} else {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "",
|
||||
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near all");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLSomeExpr x) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "Subqueries with Some is not supported");
|
||||
SQLObject parent = x.getParent();
|
||||
if (parent instanceof SQLBinaryOpExpr) {
|
||||
handleAnySubQuery((SQLBinaryOpExpr) parent, x.getSubQuery().getQuery(), false);
|
||||
} else {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "",
|
||||
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near all");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLAnyExpr x) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "Subqueries with Any is not supported");
|
||||
SQLObject parent = x.getParent();
|
||||
if (parent instanceof SQLBinaryOpExpr) {
|
||||
handleAnySubQuery((SQLBinaryOpExpr) parent, x.getSubQuery().getQuery(), false);
|
||||
} else {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "",
|
||||
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near all");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLExistsExpr x) {
|
||||
// TODO
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "not supported exists!");
|
||||
SQLSelectQuery sqlSelect = x.getSubQuery().getQuery();
|
||||
item = new ItemExistsSubQuery(currentDb, sqlSelect, x.isNot());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -669,7 +695,43 @@ public class MySQLItemVisitor extends MySqlASTVisitorAdapter {
|
||||
@Override
|
||||
public void endVisit(SQLSelectStatement node) {
|
||||
SQLSelectQuery sqlSelect = node.getSelect().getQuery();
|
||||
item = new ItemSinglerowSubselect(currentDb, sqlSelect);
|
||||
item = new ItemScalarSubQuery(currentDb, sqlSelect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void handleAnySubQuery(SQLBinaryOpExpr parent, SQLSelectQuery sqlSelect, boolean isAll) {
|
||||
SQLBinaryOperator operator = parent.getOperator();
|
||||
switch (operator) {
|
||||
case Equality:
|
||||
if (isAll) {
|
||||
item = new ItemAllAnySubQuery(currentDb, operator, sqlSelect, true);
|
||||
} else {
|
||||
Item left = getItem(parent.getLeft());
|
||||
item = new ItemInSubQuery(currentDb, left, sqlSelect, false);
|
||||
}
|
||||
break;
|
||||
case NotEqual:
|
||||
case LessThanOrGreater:
|
||||
if (isAll) {
|
||||
Item left = getItem(parent.getLeft());
|
||||
item = new ItemInSubQuery(currentDb, left, sqlSelect, true);
|
||||
} else {
|
||||
item = new ItemAllAnySubQuery(currentDb, operator, sqlSelect, false);
|
||||
}
|
||||
break;
|
||||
case LessThan:
|
||||
case LessThanOrEqual:
|
||||
case GreaterThan:
|
||||
case GreaterThanOrEqual:
|
||||
item = new ItemAllAnySubQuery(currentDb, operator, sqlSelect, isAll);
|
||||
break;
|
||||
default:
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "",
|
||||
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near all");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private CastType getCastType(SQLDataTypeImpl dataTypeImpl) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.actiontech.dble.plan.common.item.Item;
|
||||
import com.actiontech.dble.plan.common.item.ItemField;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.cmpfunc.ItemFuncEqual;
|
||||
import com.actiontech.dble.plan.common.item.function.operator.logic.ItemCondAnd;
|
||||
import com.actiontech.dble.plan.common.item.subquery.ItemScalarSubQuery;
|
||||
import com.actiontech.dble.plan.node.*;
|
||||
import com.actiontech.dble.plan.util.FilterUtils;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
@@ -21,7 +22,6 @@ import com.alibaba.druid.sql.ast.*;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
@@ -139,7 +139,7 @@ public class MySQLPlanNodeVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLExprTableSource tableSource) {
|
||||
PlanNode table = null;
|
||||
PlanNode table;
|
||||
SQLExpr expr = tableSource.getExpr();
|
||||
if (expr instanceof SQLPropertyExpr) {
|
||||
SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
|
||||
@@ -248,19 +248,13 @@ public class MySQLPlanNodeVisitor {
|
||||
this.tableNode.setSubQuery(true);
|
||||
if (subQueryTables.getAlias() != null) {
|
||||
tableNode.alias(subQueryTables.getAlias());
|
||||
if (tableNode.getSubAlias() == null) {
|
||||
if (tableNode.getSubAlias() == null && tableNode.type() == PlanNode.PlanNodeType.TABLE && !tableNode.isSubQuery()) {
|
||||
tableNode.setSubAlias(tableNode.getAlias());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLSelect node) {
|
||||
MySQLPlanNodeVisitor mtv = new MySQLPlanNodeVisitor(this.currentDb, this.charsetIndex);
|
||||
mtv.visit(node);
|
||||
this.tableNode = mtv.getTableNode();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void visit(SQLTableSource tables) {
|
||||
if (tables instanceof SQLExprTableSource) {
|
||||
@@ -290,12 +284,14 @@ public class MySQLPlanNodeVisitor {
|
||||
List<Item> selectItems = new ArrayList<>();
|
||||
for (SQLSelectItem item : items) {
|
||||
SQLExpr expr = item.getExpr();
|
||||
if (expr instanceof SQLQueryExpr)
|
||||
throw new RuntimeException("query statement as column is not supported!");
|
||||
MySQLItemVisitor ev = new MySQLItemVisitor(currentDb, this.charsetIndex);
|
||||
expr.accept(ev);
|
||||
Item selItem = ev.getItem();
|
||||
|
||||
if (selItem instanceof ItemScalarSubQuery) {
|
||||
((ItemScalarSubQuery) selItem).setField(true);
|
||||
tableNode.getSubQueries().add((ItemScalarSubQuery) selItem);
|
||||
tableNode.setSubQuery(true);
|
||||
}
|
||||
selItem.setAlias(item.getAlias());
|
||||
selectItems.add(selItem);
|
||||
}
|
||||
@@ -306,9 +302,12 @@ public class MySQLPlanNodeVisitor {
|
||||
MySQLItemVisitor mev = new MySQLItemVisitor(this.currentDb, this.charsetIndex);
|
||||
whereExpr.accept(mev);
|
||||
if (this.tableNode != null) {
|
||||
Item whereFiler = mev.getItem();
|
||||
tableNode.query(whereFiler);
|
||||
// this.tableNode.setWhereFilter(tableNode.getWhereFilter());
|
||||
Item whereFilter = mev.getItem();
|
||||
tableNode.query(whereFilter);
|
||||
if (whereFilter.isWithSubQuery()) {
|
||||
tableNode.setSubQuery(true);
|
||||
tableNode.setCorrelatedSubQuery(whereFilter.isCorrelatedSubQuery());
|
||||
}
|
||||
} else {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "", "from expression is null,check the sql!");
|
||||
}
|
||||
@@ -359,9 +358,9 @@ public class MySQLPlanNodeVisitor {
|
||||
|
||||
private void handleLimit(SQLLimit limit) {
|
||||
long from = 0;
|
||||
SQLExpr offest = limit.getOffset();
|
||||
if (offest != null) {
|
||||
SQLIntegerExpr offsetExpr = (SQLIntegerExpr) offest;
|
||||
SQLExpr offset = limit.getOffset();
|
||||
if (offset != null) {
|
||||
SQLIntegerExpr offsetExpr = (SQLIntegerExpr) offset;
|
||||
from = offsetExpr.getNumber().longValue();
|
||||
}
|
||||
SQLExpr rowCount = limit.getRowCount();
|
||||
|
||||
@@ -81,28 +81,28 @@ public class ServerSchemaStatVisitor extends MySqlSchemaStatVisitor {
|
||||
@Override
|
||||
public boolean visit(SQLExistsExpr x) {
|
||||
super.visit(x);
|
||||
notSupportMsg = "Subqueries with EXISTS or NOT EXISTS is not supported";
|
||||
hasSubQuery = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLAllExpr x) {
|
||||
super.visit(x);
|
||||
notSupportMsg = "Subqueries with All is not supported";
|
||||
hasSubQuery = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSomeExpr x) {
|
||||
super.visit(x);
|
||||
notSupportMsg = "Subqueries with Some is not supported";
|
||||
hasSubQuery = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLAnyExpr x) {
|
||||
super.visit(x);
|
||||
notSupportMsg = "Subqueries with Any is not supported";
|
||||
hasSubQuery = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package com.actiontech.dble.route.parser.druid.impl;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.cache.LayerCachePool;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.route.RouteResultset;
|
||||
@@ -83,7 +83,7 @@ public class DefaultDruidParser implements DruidParser {
|
||||
for (Map.Entry<String, String> entry : originTableAliasMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
if (key != null) {
|
||||
key = key.toLowerCase();
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public class DefaultDruidParser implements DruidParser {
|
||||
if (checkConditionValues(values)) {
|
||||
String columnName = StringUtil.removeBackQuote(condition.getColumn().getName().toUpperCase());
|
||||
String tableName = StringUtil.removeBackQuote(condition.getColumn().getTable());
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
tableName = tableName.toLowerCase();
|
||||
}
|
||||
if (tableAliasMap != null && tableAliasMap.get(tableName) == null) {
|
||||
|
||||
@@ -152,7 +152,7 @@ public class DruidInsertParser extends DefaultDruidParser {
|
||||
// try to route by ER parent partion key
|
||||
RouteResultset theRrs = ReplaceInsertUtil.routeByERParentKey(rrs, tc, realVal);
|
||||
if (theRrs != null) {
|
||||
rrs.setFinishedRoute(true);
|
||||
theRrs.setFinishedRoute(true);
|
||||
return theRrs;
|
||||
}
|
||||
// route by sql query root parent's datanode
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package com.actiontech.dble.route.parser.druid.impl;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
import com.actiontech.dble.config.model.TableConfig;
|
||||
import com.actiontech.dble.route.RouteResultset;
|
||||
@@ -58,7 +58,7 @@ public class DruidLockTableParser extends DefaultDruidParser {
|
||||
}
|
||||
MySqlLockTableStatement lockTableStat = (MySqlLockTableStatement) stmt;
|
||||
String table = lockTableStat.getTableSource().toString();
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
table = table.toLowerCase();
|
||||
}
|
||||
TableConfig tableConfig = schema.getTables().get(table);
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.actiontech.dble.server.util.SchemaUtil.SchemaInfo;
|
||||
import com.actiontech.dble.sqlengine.mpp.ColumnRoutePair;
|
||||
import com.actiontech.dble.sqlengine.mpp.HavingCols;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.*;
|
||||
import com.alibaba.druid.sql.ast.expr.*;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
@@ -66,9 +65,17 @@ public class DruidSelectParser extends DefaultDruidParser {
|
||||
if (mysqlSelectQuery.getInto() != null) {
|
||||
throw new SQLNonTransientException("select ... into is not supported!");
|
||||
}
|
||||
checkSelectList(mysqlSelectQuery);
|
||||
SQLTableSource mysqlFrom = mysqlSelectQuery.getFrom();
|
||||
if (mysqlFrom == null) {
|
||||
List<SQLSelectItem> selectList = mysqlSelectQuery.getSelectList();
|
||||
for (SQLSelectItem item : selectList) {
|
||||
SQLExpr itemExpr = item.getExpr();
|
||||
if (itemExpr instanceof SQLQueryExpr) {
|
||||
rrs.setSqlStatement(selectStmt);
|
||||
rrs.setNeedOptimizer(true);
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
RouterUtil.routeNoNameTableToSingleNode(rrs, schema);
|
||||
return schema;
|
||||
}
|
||||
@@ -138,14 +145,6 @@ public class DruidSelectParser extends DefaultDruidParser {
|
||||
return schema;
|
||||
}
|
||||
|
||||
private void checkSelectList(MySqlSelectQueryBlock mysqlSelectQuery) throws SQLNonTransientException {
|
||||
for (SQLSelectItem item : mysqlSelectQuery.getSelectList()) {
|
||||
if (item.getExpr() instanceof SQLQueryExpr) {
|
||||
throw new SQLNonTransientException("query statement as column is not supported!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchSysTable(RouteResultset rrs, ServerConnection sc, SchemaInfo schemaInfo) {
|
||||
// support PhpAdmin
|
||||
//TODO:refactor INFORMATION_SCHEMA,MYSQL
|
||||
@@ -192,7 +191,10 @@ public class DruidSelectParser extends DefaultDruidParser {
|
||||
List<SQLSelectItem> selectList = mysqlSelectQuery.getSelectList();
|
||||
for (SQLSelectItem item : selectList) {
|
||||
SQLExpr itemExpr = item.getExpr();
|
||||
if (itemExpr instanceof SQLAggregateExpr) {
|
||||
if (itemExpr instanceof SQLQueryExpr) {
|
||||
rrs.setNeedOptimizer(true);
|
||||
return;
|
||||
} else if (itemExpr instanceof SQLAggregateExpr) {
|
||||
/*
|
||||
* MAX,MIN; SUM,COUNT without distinct is not need optimize, but
|
||||
* there is bugs in default Aggregate IN FACT ,ONLY:
|
||||
@@ -477,10 +479,9 @@ public class DruidSelectParser extends DefaultDruidParser {
|
||||
if (isNeedAddLimit) {
|
||||
SQLLimit limit = new SQLLimit();
|
||||
limit.setRowCount(new SQLIntegerExpr(limitSize));
|
||||
String strLimit = SQLUtils.toMySqlString(limit);
|
||||
mysqlSelectQuery.setLimit(limit);
|
||||
rrs.setLimitSize(limitSize);
|
||||
String sql = rrs.getStatement() + " " + strLimit;
|
||||
String sql = getSql(rrs, stmt, isNeedAddLimit, schema.getName());
|
||||
rrs.changeNodeSqlAfterAddLimit(sql, 0, limitSize);
|
||||
|
||||
}
|
||||
@@ -512,10 +513,9 @@ public class DruidSelectParser extends DefaultDruidParser {
|
||||
|
||||
}
|
||||
}
|
||||
String strLimit = SQLUtils.toMySqlString(changedLimit);
|
||||
|
||||
mysqlSelectQuery.setLimit(changedLimit);
|
||||
int iLimit = rrs.getStatement().toLowerCase().lastIndexOf("limit");
|
||||
String sql = rrs.getStatement().substring(0, iLimit) + strLimit;
|
||||
String sql = getSql(rrs, stmt, isNeedAddLimit, schema.getName());
|
||||
rrs.changeNodeSqlAfterAddLimit(sql, 0, limitStart + limitSize);
|
||||
} else {
|
||||
rrs.changeNodeSqlAfterAddLimit(rrs.getStatement(), rrs.getLimitStart(), rrs.getLimitSize());
|
||||
@@ -577,6 +577,15 @@ public class DruidSelectParser extends DefaultDruidParser {
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
protected String getSql(RouteResultset rrs, SQLStatement stmt, boolean isNeedAddLimit, String schema) {
|
||||
if ((isNeedChangeLimit(rrs) || isNeedAddLimit)) {
|
||||
return RouterUtil.removeSchema(stmt.toString(), schema);
|
||||
}
|
||||
return rrs.getStatement();
|
||||
}
|
||||
|
||||
|
||||
private boolean isNeedChangeLimit(RouteResultset rrs) {
|
||||
if (rrs.getNodes() == null) {
|
||||
return false;
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.actiontech.dble.server.ServerConnection;
|
||||
import com.actiontech.dble.server.parser.ServerParse;
|
||||
import com.actiontech.dble.server.util.SchemaUtil;
|
||||
import com.actiontech.dble.server.util.SchemaUtil.SchemaInfo;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.sqlengine.mpp.ColumnRoutePair;
|
||||
import com.actiontech.dble.sqlengine.mpp.LoadData;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
@@ -36,6 +37,8 @@ import java.sql.SQLException;
|
||||
import java.sql.SQLNonTransientException;
|
||||
import java.util.*;
|
||||
|
||||
import static com.actiontech.dble.plan.optimizer.JoinStrategyProcessor.NEED_REPLACE;
|
||||
|
||||
/**
|
||||
* ServerRouterUtil
|
||||
*
|
||||
@@ -48,7 +51,7 @@ public final class RouterUtil {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RouterUtil.class);
|
||||
|
||||
public static String removeSchema(String stmt, String schema) {
|
||||
return removeSchema(stmt, schema, DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames());
|
||||
return removeSchema(stmt, schema, SystemVariables.getSysVars().isLowerCaseTableNames());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,11 +146,15 @@ public final class RouterUtil {
|
||||
SortedSet<RouteResultsetNode> nodeSet = new TreeSet<>();
|
||||
for (RouteCalculateUnit unit : druidParser.getCtx().getRouteCalculateUnits()) {
|
||||
RouteResultset rrsTmp = RouterUtil.tryRouteForTables(schema, druidParser.getCtx(), unit, rrs, isSelect(statement), cachePool);
|
||||
if (rrsTmp != null) {
|
||||
if (rrsTmp != null && rrsTmp.getNodes() != null) {
|
||||
Collections.addAll(nodeSet, rrsTmp.getNodes());
|
||||
if (rrsTmp.isGlobalTable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSet.size()];
|
||||
int i = 0;
|
||||
for (RouteResultsetNode aNodeSet : nodeSet) {
|
||||
@@ -289,7 +296,7 @@ public final class RouterUtil {
|
||||
|
||||
|
||||
public static String lowerCaseTable(String tableName) {
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
return tableName.toLowerCase();
|
||||
}
|
||||
return tableName;
|
||||
@@ -575,7 +582,7 @@ public final class RouterUtil {
|
||||
//router for shard-ing tables
|
||||
for (Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry : tablesAndConditions.entrySet()) {
|
||||
String tableName = entry.getKey();
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
tableName = tableName.toLowerCase();
|
||||
}
|
||||
if (tableName.startsWith(schema.getName() + ".")) {
|
||||
@@ -634,9 +641,12 @@ public final class RouterUtil {
|
||||
for (ColumnRoutePair pair : partitionValue) {
|
||||
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
|
||||
if (pair.colValue != null) {
|
||||
if (NEED_REPLACE.equals(pair.colValue)) {
|
||||
return;
|
||||
}
|
||||
Integer nodeIndex = algorithm.calculate(pair.colValue);
|
||||
if (nodeIndex == null) {
|
||||
String msg = "can't find any valid datanode :" + tableConfig.getName() +
|
||||
String msg = "can't find any valid data node :" + tableConfig.getName() +
|
||||
" -> " + tableConfig.getPartitionColumn() + " -> " + pair.colValue;
|
||||
LOGGER.warn(msg);
|
||||
throw new SQLNonTransientException(msg);
|
||||
|
||||
@@ -220,6 +220,12 @@ public class NonBlockingSession implements Session {
|
||||
LOGGER.warn(String.valueOf(source) + " execute plan is : " + node, e);
|
||||
this.terminate();
|
||||
source.writeErrMessage(ErrorCode.ER_NO_VALID_CONNECTION, "no valid connection");
|
||||
} catch (MySQLOutPutException e) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(String.valueOf(source) + " execute plan is : " + node, e);
|
||||
}
|
||||
this.terminate();
|
||||
source.writeErrMessage(e.getSqlState(), e.getMessage(), e.getErrorCode());
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(String.valueOf(source) + " execute plan is : " + node, e);
|
||||
this.terminate();
|
||||
@@ -232,6 +238,9 @@ public class NonBlockingSession implements Session {
|
||||
MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(this.getSource().getSchema(), this.getSource().getCharset().getResultsIndex());
|
||||
visitor.visit(ast);
|
||||
PlanNode node = visitor.getTableNode();
|
||||
if (node.isCorrelatedSubQuery()) {
|
||||
throw new MySQLOutPutException(ErrorCode.ER_UNKNOWN_ERROR, "", "Correlated Subqueries is not supported ");
|
||||
}
|
||||
node.setSql(rrs.getStatement());
|
||||
node.setUpFields();
|
||||
checkTablesPrivilege(node, ast);
|
||||
@@ -253,8 +262,13 @@ public class NonBlockingSession implements Session {
|
||||
}
|
||||
|
||||
public void onQueryError(byte[] message) {
|
||||
if (outputHandler != null)
|
||||
if (outputHandler != null) {
|
||||
outputHandler.backendConnError(message);
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
source.close(new String(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CommitNodesHandler createCommitNodesHandler() {
|
||||
|
||||
@@ -1,202 +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;
|
||||
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class SystemVariables {
|
||||
private SystemVariables() {
|
||||
}
|
||||
|
||||
private static Map<String, String> sessionVariables = new HashMap<>();
|
||||
|
||||
static {
|
||||
//some may not useful for middle-ware
|
||||
sessionVariables.put("audit_log_current_session", "0");
|
||||
sessionVariables.put("audit_log_filter_id", "0");
|
||||
sessionVariables.put("auto_increment_increment", "1");
|
||||
sessionVariables.put("auto_increment_offset", "1");
|
||||
sessionVariables.put("autocommit", "1");
|
||||
sessionVariables.put("big_tables", "0");
|
||||
sessionVariables.put("binlog_direct_non_transactional_updates", "0");
|
||||
sessionVariables.put("binlog_error_action", "IGNORE_ERROR");
|
||||
sessionVariables.put("binlog_format", "ROW");
|
||||
sessionVariables.put("binlog_row_image", "FULL");
|
||||
sessionVariables.put("binlog_rows_query_log_events", "0");
|
||||
sessionVariables.put("binlogging_impossible_mode", "IGNORE_ERROR");
|
||||
sessionVariables.put("block_encryption_mode", "aes-128-ecb");
|
||||
sessionVariables.put("bulk_insert_buffer_size", "8388608");
|
||||
sessionVariables.put("character_set_client", "utf8");
|
||||
sessionVariables.put("character_set_connection", "utf8");
|
||||
sessionVariables.put("character_set_database", "utf8");
|
||||
sessionVariables.put("character_set_filesystem", "binary");
|
||||
sessionVariables.put("character_set_results", "utf8");
|
||||
sessionVariables.put("character_set_server", "utf8");
|
||||
sessionVariables.put("collation_connection", "utf8_general_ci");
|
||||
sessionVariables.put("collation_database", "utf8_general_ci");
|
||||
sessionVariables.put("collation_server", "utf8_general_ci");
|
||||
sessionVariables.put("completion_type", "NO_CHAIN");
|
||||
sessionVariables.put("debug", "d:t:i:o,/tmp/mysqld.trace");
|
||||
sessionVariables.put("debug_sync", "0");
|
||||
sessionVariables.put("default_storage_engine", "InnoDB");
|
||||
sessionVariables.put("default_tmp_storage_engine", "InnoDB");
|
||||
sessionVariables.put("default_week_format", "0");
|
||||
sessionVariables.put("disconnect_on_expired_password", "1");
|
||||
sessionVariables.put("div_precision_increment", "4");
|
||||
sessionVariables.put("end_markers_in_json", "0");
|
||||
sessionVariables.put("eq_range_index_dive_limit", "10");
|
||||
sessionVariables.put("error_count", "0");
|
||||
sessionVariables.put("explicit_defaults_for_timestamp", "0");
|
||||
sessionVariables.put("external_user", "NULL");
|
||||
sessionVariables.put("foreign_key_checks", "1");
|
||||
sessionVariables.put("group_concat_max_len", "1024");
|
||||
sessionVariables.put("gtid_next", "AUTOMATIC");
|
||||
sessionVariables.put("gtid_owned", "NULL");
|
||||
sessionVariables.put("identity", "0");
|
||||
sessionVariables.put("innodb_create_intrinsic", "0");
|
||||
sessionVariables.put("innodb_ft_user_stopword_table", "NULL");
|
||||
sessionVariables.put("innodb_lock_wait_timeout", "50");
|
||||
sessionVariables.put("innodb_optimize_point_storage", "0");
|
||||
sessionVariables.put("innodb_strict_mode", "0");
|
||||
sessionVariables.put("innodb_support_xa", "1");
|
||||
sessionVariables.put("innodb_table_locks", "1");
|
||||
sessionVariables.put("innodb_tmpdir", "NULL");
|
||||
sessionVariables.put("insert_id", "0");
|
||||
sessionVariables.put("interactive_timeout", "28800");
|
||||
sessionVariables.put("join_buffer_size", "262144");
|
||||
sessionVariables.put("keep_files_on_create", "0");
|
||||
sessionVariables.put("last_insert_id", "0");
|
||||
sessionVariables.put("lc_messages", "en_US");
|
||||
sessionVariables.put("lc_time_names", "en_US");
|
||||
sessionVariables.put("lock_wait_timeout", "31536000");
|
||||
sessionVariables.put("long_query_time", "10");
|
||||
sessionVariables.put("low_priority_updates", "0");
|
||||
sessionVariables.put("max_allowed_packet", "4194304");
|
||||
sessionVariables.put("max_delayed_threads", "20");
|
||||
sessionVariables.put("max_error_count", "64");
|
||||
sessionVariables.put("max_execution_time", "0");
|
||||
sessionVariables.put("max_heap_table_size", "16777216");
|
||||
sessionVariables.put("max_insert_delayed_threads", "20");
|
||||
sessionVariables.put("max_join_size", String.valueOf(Long.MAX_VALUE));
|
||||
sessionVariables.put("max_length_for_sort_data", "1024");
|
||||
sessionVariables.put("max_seeks_for_key", String.valueOf(Long.MAX_VALUE));
|
||||
sessionVariables.put("max_sort_length", "1024");
|
||||
sessionVariables.put("max_sp_recursion_depth", "0");
|
||||
sessionVariables.put("max_statement_time", "0");
|
||||
//max_tmp_tables This variable is unused. It is deprecated and is removed in MySQL 8.0
|
||||
sessionVariables.put("max_user_connections", "0");
|
||||
sessionVariables.put("min_examined_row_limit", "0");
|
||||
//multi_range_count This variable has no effect. It is deprecated and is removed in MySQL 8.0.
|
||||
sessionVariables.put("myisam_repair_threads", "1");
|
||||
sessionVariables.put("myisam_sort_buffer_size", "8388608");
|
||||
sessionVariables.put("myisam_stats_method", "nulls_unequal");
|
||||
sessionVariables.put("ndb-allow-copying-alter-table", "0");
|
||||
sessionVariables.put("ndb_autoincrement_prefetch_sz", "32");
|
||||
sessionVariables.put("ndb-blob-read-batch-bytes", "65536");
|
||||
sessionVariables.put("ndb-blob-write-batch-bytes", "65536");
|
||||
sessionVariables.put("ndb_deferred_constraints", "0");
|
||||
sessionVariables.put("ndb_force_send", "1");
|
||||
sessionVariables.put("ndb_fully_replicated", "0");
|
||||
sessionVariables.put("ndb_index_stat_enable", "1");
|
||||
sessionVariables.put("ndb_index_stat_option", "NULL");
|
||||
sessionVariables.put("ndb_join_pushdown", "1");
|
||||
sessionVariables.put("ndb_log_bin", "1");
|
||||
sessionVariables.put("ndb_log_bin", "0");
|
||||
sessionVariables.put("ndb_table_no_logging", "0");
|
||||
sessionVariables.put("ndb_table_temporary", "0");
|
||||
sessionVariables.put("ndb_use_copying_alter_table", "0");
|
||||
sessionVariables.put("ndb_use_exact_count", "0");
|
||||
sessionVariables.put("ndb_use_transactions", "1");
|
||||
sessionVariables.put("ndbinfo_max_bytes", "0");
|
||||
sessionVariables.put("ndbinfo_max_rows", "10");
|
||||
sessionVariables.put("ndbinfo_show_hidden", "0");
|
||||
sessionVariables.put("ndbinfo_table_prefix", "ndb$");
|
||||
sessionVariables.put("net_buffer_length", "16384");
|
||||
sessionVariables.put("net_read_timeout", "30");
|
||||
sessionVariables.put("net_retry_count", "10");
|
||||
sessionVariables.put("net_write_timeout", "60");
|
||||
sessionVariables.put("new", "0");
|
||||
sessionVariables.put("old_alter_table", "0");
|
||||
sessionVariables.put("old_passwords", "0");
|
||||
sessionVariables.put("optimizer_prune_level", "1");
|
||||
sessionVariables.put("optimizer_search_depth", "62");
|
||||
sessionVariables.put("optimizer_switch", "index_merge=on,index_merge_union=on," +
|
||||
"index_merge_sort_union=on,index_merge_intersection=on," +
|
||||
"engine_condition_pushdown=on,index_condition_pushdown=on," +
|
||||
"mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off," +
|
||||
"materialization=on,semijoin=on,loosescan=on,firstmatch=on," +
|
||||
"subquery_materialization_cost_based=on,use_index_extensions=on");
|
||||
sessionVariables.put("optimizer_trace", "enabled=off,one_line=off");
|
||||
sessionVariables.put("optimizer_trace_features", "greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on");
|
||||
sessionVariables.put("optimizer_trace_limit", "1");
|
||||
sessionVariables.put("optimizer_trace_max_mem_size", "16384");
|
||||
sessionVariables.put("optimizer_trace_offset", "-1");
|
||||
sessionVariables.put("parser_max_mem_size", String.valueOf(Long.MAX_VALUE));
|
||||
sessionVariables.put("preload_buffer_size", "32768");
|
||||
sessionVariables.put("profiling", "0");
|
||||
sessionVariables.put("profiling_history_size", "15");
|
||||
sessionVariables.put("proxy_user", "NULL");
|
||||
sessionVariables.put("pseudo_slave_mode", "0");
|
||||
sessionVariables.put("pseudo_thread_id", "11");
|
||||
sessionVariables.put("query_alloc_block_size", "8192");
|
||||
sessionVariables.put("query_cache_type", "0");
|
||||
sessionVariables.put("query_cache_wlock_invalidate", "0");
|
||||
sessionVariables.put("query_prealloc_size", "8192");
|
||||
sessionVariables.put("rand_seed1", "0");
|
||||
sessionVariables.put("rand_seed2", "0");
|
||||
sessionVariables.put("range_alloc_block_size", "4096");
|
||||
sessionVariables.put("range_optimizer_max_mem_size", "8388608");
|
||||
sessionVariables.put("rbr_exec_mode", "AUTOMATIC");
|
||||
sessionVariables.put("read_buffer_size", "131072");
|
||||
sessionVariables.put("read_rnd_buffer_size", "262144");
|
||||
sessionVariables.put("session_track_gtids", "0");
|
||||
sessionVariables.put("session_track_schema", "1");
|
||||
sessionVariables.put("session_track_state_change", "0");
|
||||
sessionVariables.put("session_track_system_variables", "time_zone, autocommit, character_set_client, character_set_results, character_set_connection");
|
||||
sessionVariables.put("show_old_temporals", "0");
|
||||
sessionVariables.put("sort_buffer_size", "262144");
|
||||
sessionVariables.put("sql_auto_is_null", "0");
|
||||
sessionVariables.put("sql_big_selects", "1");
|
||||
sessionVariables.put("sql_buffer_result", "0");
|
||||
sessionVariables.put("sql_log_bin", "1");
|
||||
sessionVariables.put("sql_log_off", "0");
|
||||
sessionVariables.put("sql_mode", "IGNORE_SPACE");
|
||||
sessionVariables.put("sql_notes", "1");
|
||||
sessionVariables.put("sql_quote_show_create", "1");
|
||||
sessionVariables.put("sql_safe_updates", "0");
|
||||
sessionVariables.put("sql_select_limit", String.valueOf(Long.MAX_VALUE));
|
||||
sessionVariables.put("sql_warnings", "0");
|
||||
sessionVariables.put("storage_engine", "InnoDB");
|
||||
sessionVariables.put("thread_pool_high_priority_connection", "0");
|
||||
sessionVariables.put("thread_pool_prio_kickup_timer", "1000");
|
||||
sessionVariables.put("time_zone", "SYSTEM");
|
||||
sessionVariables.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
||||
sessionVariables.put("tmp_table_size", "16777216");
|
||||
sessionVariables.put("transaction_alloc_block_size", "8192");
|
||||
sessionVariables.put("transaction_allow_batching", "0");
|
||||
sessionVariables.put("transaction_prealloc_size", "4096");
|
||||
sessionVariables.put("transaction_write_set_extraction", "0");
|
||||
sessionVariables.put("tx_isolation", "REPEATABLE-READ"); //transaction-isolation
|
||||
sessionVariables.put("tx_read_only", "0"); // OFF|0|false //transaction-read-only
|
||||
sessionVariables.put("unique_checks", "1"); // ON|1|TRUE
|
||||
sessionVariables.put("updatable_views_with_limit", "1"); // ON|1|TRUE
|
||||
sessionVariables.put("version_tokens_session", "NULL");
|
||||
sessionVariables.put("version_tokens_session_number", "0");
|
||||
sessionVariables.put("wait_timeout", "28800");
|
||||
sessionVariables.put("warning_count", "0");
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static String getDefaultValue(String variable) {
|
||||
if (StringUtil.isEmpty(variable))
|
||||
return null;
|
||||
return sessionVariables.get(variable.toLowerCase());
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package com.actiontech.dble.server.handler;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.backend.mysql.PacketUtil;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.builder.BaseHandlerBuilder;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.builder.HandlerBuilder;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.*;
|
||||
@@ -14,6 +15,9 @@ import com.actiontech.dble.backend.mysql.nio.handler.query.impl.groupby.DirectGr
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.groupby.OrderedGroupByHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.join.JoinHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.join.NotInHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.AllAnySubQueryHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.InSubQueryHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.impl.subquery.SingleRowSubQueryHandler;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.config.Fields;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
@@ -114,30 +118,76 @@ public final class ExplainHandler {
|
||||
}
|
||||
|
||||
private static List<String[]> getComplexQueryResult(RouteResultset rrs, ServerConnection c) {
|
||||
List<String[]> result = new ArrayList<>();
|
||||
DMLResponseHandler endHandler = buildNode(rrs, c);
|
||||
Map<DMLResponseHandler, RefHandlerInfo> handlerMap = new HashMap<>();
|
||||
Map<String, RefHandlerInfo> refMap = new HashMap<>();
|
||||
int mergeCnt = 0;
|
||||
List<BaseHandlerBuilder> builderList = getBaseHandlerBuilders(rrs, c);
|
||||
Map<String, Integer> nameMap = new HashMap<>();
|
||||
List<String[]> result = new ArrayList<>();
|
||||
|
||||
Map<BaseHandlerBuilder, String> builderNameMap = new HashMap<>();
|
||||
for (int i = builderList.size() - 1; i >= 0; i--) {
|
||||
BaseHandlerBuilder tmpBuilder = builderList.get(i);
|
||||
Set<String> subQueries = new LinkedHashSet<>();
|
||||
for (BaseHandlerBuilder childBuilder : tmpBuilder.getSubQueryBuilderList()) {
|
||||
subQueries.add(builderNameMap.get(childBuilder));
|
||||
}
|
||||
String subQueryRootName = buildResultByEndHandler(subQueries, result, tmpBuilder.getEndHandler(), nameMap);
|
||||
builderNameMap.put(tmpBuilder, subQueryRootName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<BaseHandlerBuilder> getBaseHandlerBuilders(RouteResultset rrs, ServerConnection c) {
|
||||
BaseHandlerBuilder builder = buildNodes(rrs, c);
|
||||
Queue<BaseHandlerBuilder> queue = new LinkedList<>();
|
||||
queue.add(builder);
|
||||
List<BaseHandlerBuilder> builderList = new ArrayList<>();
|
||||
while (queue.size() > 0) {
|
||||
BaseHandlerBuilder rootBuilder = queue.poll();
|
||||
builderList.add(rootBuilder);
|
||||
if (rootBuilder.getSubQueryBuilderList().size() > 0) {
|
||||
queue.addAll(rootBuilder.getSubQueryBuilderList());
|
||||
}
|
||||
}
|
||||
return builderList;
|
||||
}
|
||||
|
||||
private static String buildResultByEndHandler(Set<String> subQueries, List<String[]> result, DMLResponseHandler endHandler, Map<String, Integer> nameMap) {
|
||||
Map<String, RefHandlerInfo> refMap = new HashMap<>();
|
||||
String rootName = buildHandlerTree(endHandler, refMap, new HashMap<DMLResponseHandler, RefHandlerInfo>(), nameMap, subQueries);
|
||||
List<RefHandlerInfo> resultList = new ArrayList<>(refMap.size());
|
||||
getDFSHandlers(refMap, rootName, resultList);
|
||||
for (int i = resultList.size() - 1; i >= 0; i--) {
|
||||
RefHandlerInfo handlerInfo = resultList.get(i);
|
||||
result.add(new String[]{handlerInfo.name, handlerInfo.type, handlerInfo.getRefOrSQL()});
|
||||
}
|
||||
return rootName;
|
||||
}
|
||||
|
||||
private static String buildHandlerTree(DMLResponseHandler endHandler, Map<String, RefHandlerInfo> refMap, Map<DMLResponseHandler, RefHandlerInfo> handlerMap, Map<String, Integer> nameMap, Set<String> dependencies) {
|
||||
String rootName = null;
|
||||
for (DMLResponseHandler startHandler : endHandler.getMerges()) {
|
||||
MultiNodeMergeHandler mergeHandler = (MultiNodeMergeHandler) startHandler;
|
||||
List<BaseSelectHandler> mergeList = new ArrayList<>();
|
||||
mergeList.addAll(((MultiNodeMergeHandler) startHandler).getExeHandlers());
|
||||
mergeCnt++;
|
||||
String mergeNode = "merge." + mergeCnt;
|
||||
String mergeNode = genHandlerName("MERGE", nameMap);
|
||||
RefHandlerInfo refInfo = new RefHandlerInfo(mergeNode, "MERGE");
|
||||
handlerMap.put(mergeHandler, refInfo);
|
||||
refMap.put(mergeNode, refInfo);
|
||||
for (BaseSelectHandler exeHandler : mergeList) {
|
||||
RouteResultsetNode rrss = exeHandler.getRrss();
|
||||
String dateNode = rrss.getName() + "." + rrss.getMultiplexNum();
|
||||
result.add(new String[]{dateNode, "BASE SQL", rrss.getStatement()});
|
||||
refInfo.addChild(dateNode);
|
||||
String type = "BASE SQL";
|
||||
if (dependencies != null && dependencies.size() > 0) {
|
||||
type += "(May No Need)";
|
||||
}
|
||||
RefHandlerInfo baseSQLInfo = new RefHandlerInfo(dateNode, type, rrss.getStatement());
|
||||
refMap.put(dateNode, baseSQLInfo);
|
||||
if (dependencies != null && dependencies.size() > 0) {
|
||||
baseSQLInfo.addAllStepChildren(dependencies);
|
||||
}
|
||||
}
|
||||
String mergeRootName = dfsHandler(mergeHandler, handlerMap, refMap, nameMap);
|
||||
if (mergeCnt == 1) {
|
||||
String mergeRootName = getAllNodesFromLeaf(mergeHandler, refMap, handlerMap, nameMap);
|
||||
if (rootName == null) {
|
||||
if (mergeRootName == null) {
|
||||
rootName = mergeNode;
|
||||
} else {
|
||||
@@ -145,10 +195,11 @@ public final class ExplainHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
nameMap.clear();
|
||||
handlerMap.clear();
|
||||
return rootName;
|
||||
}
|
||||
|
||||
private static void getDFSHandlers(Map<String, RefHandlerInfo> refMap, String rootName, List<RefHandlerInfo> resultList) {
|
||||
Stack<RefHandlerInfo> stackSearch = new Stack<>();
|
||||
List<RefHandlerInfo> resultList = new ArrayList<>(refMap.size());
|
||||
stackSearch.push(refMap.get(rootName));
|
||||
while (stackSearch.size() > 0) {
|
||||
RefHandlerInfo root = stackSearch.pop();
|
||||
@@ -161,14 +212,9 @@ public final class ExplainHandler {
|
||||
}
|
||||
}
|
||||
refMap.clear();
|
||||
for (int i = resultList.size() - 1; i >= 0; i--) {
|
||||
RefHandlerInfo handlerInfo = resultList.get(i);
|
||||
result.add(new String[]{handlerInfo.name, handlerInfo.type, handlerInfo.getChildrenNames()});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String dfsHandler(DMLResponseHandler handler, Map<DMLResponseHandler, RefHandlerInfo> handlerMap, Map<String, RefHandlerInfo> refMap, Map<String, Integer> nameMap) {
|
||||
private static String getAllNodesFromLeaf(DMLResponseHandler handler, Map<String, RefHandlerInfo> refMap, Map<DMLResponseHandler, RefHandlerInfo> handlerMap, Map<String, Integer> nameMap) {
|
||||
DMLResponseHandler nextHandler = skipSendMake(handler.getNextHandler());
|
||||
String rootName = null;
|
||||
while (nextHandler != null) {
|
||||
@@ -185,6 +231,12 @@ public final class ExplainHandler {
|
||||
} else {
|
||||
handlerMap.get(nextHandler).addChild(childName);
|
||||
}
|
||||
if (handler instanceof TempTableHandler) {
|
||||
TempTableHandler tmp = (TempTableHandler) handler;
|
||||
DMLResponseHandler endHandler = tmp.getCreatedHandler();
|
||||
endHandler.setNextHandler(nextHandler);
|
||||
buildHandlerTree(endHandler, refMap, handlerMap, nameMap, Collections.singleton(childName + "'s RESULTS"));
|
||||
}
|
||||
handler = nextHandler;
|
||||
nextHandler = skipSendMake(nextHandler.getNextHandler());
|
||||
}
|
||||
@@ -236,11 +288,17 @@ public final class ExplainHandler {
|
||||
return "DIRECT_GROUP";
|
||||
} else if (handler instanceof TempTableHandler) {
|
||||
return "NEST_LOOP";
|
||||
} else if (handler instanceof InSubQueryHandler) {
|
||||
return "IN_SUB_QUERY";
|
||||
} else if (handler instanceof AllAnySubQueryHandler) {
|
||||
return "ALL_ANY_SUB_QUERY";
|
||||
} else if (handler instanceof SingleRowSubQueryHandler) {
|
||||
return "SCALAR_SUB_QUERY";
|
||||
}
|
||||
return "OTHER";
|
||||
}
|
||||
|
||||
private static DMLResponseHandler buildNode(RouteResultset rrs, ServerConnection c) {
|
||||
private static BaseHandlerBuilder buildNodes(RouteResultset rrs, ServerConnection c) {
|
||||
SQLSelectStatement ast = (SQLSelectStatement) rrs.getSqlStatement();
|
||||
MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor(c.getSchema(), c.getCharset().getResultsIndex());
|
||||
visitor.visit(ast);
|
||||
@@ -249,7 +307,7 @@ public final class ExplainHandler {
|
||||
node.setUpFields();
|
||||
node = MyOptimizer.optimize(node);
|
||||
HandlerBuilder builder = new HandlerBuilder(node, c.getSession2());
|
||||
return builder.buildNode(c.getSession2(), node);
|
||||
return builder.getBuilder(c.getSession2(), node, true);
|
||||
}
|
||||
|
||||
private static RowDataPacket getRow(RouteResultsetNode node, String charset) {
|
||||
@@ -318,22 +376,39 @@ public final class ExplainHandler {
|
||||
private static class RefHandlerInfo {
|
||||
private String name;
|
||||
private String type;
|
||||
private Set<String> children = new TreeSet<>();
|
||||
private String baseSQL;
|
||||
private Set<String> children = new LinkedHashSet<>();
|
||||
private Set<String> stepChildren = new LinkedHashSet<>();
|
||||
|
||||
RefHandlerInfo(String name, String type, String baseSQL) {
|
||||
this(name, type);
|
||||
this.baseSQL = baseSQL;
|
||||
}
|
||||
RefHandlerInfo(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
String getChildrenNames() {
|
||||
String getRefOrSQL() {
|
||||
StringBuilder names = new StringBuilder("");
|
||||
int i = 0;
|
||||
for (String child : children) {
|
||||
if (i > 0) {
|
||||
names.append(", ");
|
||||
for (String child : stepChildren) {
|
||||
if (names.length() > 0) {
|
||||
names.append("; ");
|
||||
}
|
||||
names.append(child);
|
||||
i++;
|
||||
}
|
||||
for (String child : children) {
|
||||
if (names.length() > 0) {
|
||||
names.append("; ");
|
||||
}
|
||||
names.append(child);
|
||||
}
|
||||
|
||||
if (baseSQL != null) {
|
||||
if (names.length() > 0) {
|
||||
names.append("; ");
|
||||
}
|
||||
names.append(baseSQL);
|
||||
}
|
||||
return names.toString();
|
||||
}
|
||||
@@ -342,6 +417,9 @@ public final class ExplainHandler {
|
||||
return children;
|
||||
}
|
||||
|
||||
void addAllStepChildren(Set<String> dependencies) {
|
||||
this.stepChildren.addAll(dependencies);
|
||||
}
|
||||
void addChild(String child) {
|
||||
this.children.add(child);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.server.handler;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.cache.LayerCachePool;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
@@ -20,7 +21,6 @@ import com.actiontech.dble.route.parser.druid.DruidShardingParseInfo;
|
||||
import com.actiontech.dble.route.parser.druid.RouteCalculateUnit;
|
||||
import com.actiontech.dble.route.util.RouterUtil;
|
||||
import com.actiontech.dble.server.ServerConnection;
|
||||
import com.actiontech.dble.server.SystemVariables;
|
||||
import com.actiontech.dble.server.parser.ServerParse;
|
||||
import com.actiontech.dble.sqlengine.mpp.LoadData;
|
||||
import com.actiontech.dble.util.ObjectUtil;
|
||||
@@ -116,7 +116,7 @@ public final class ServerLoadDataInfileHandler implements LoadDataInfileHandler
|
||||
SQLTextLiteralExpr escapedExpr = (SQLTextLiteralExpr) statement.getColumnsEscaped();
|
||||
String escaped = escapedExpr == null ? "\\" : escapedExpr.getText();
|
||||
loadData.setEscape(escaped);
|
||||
String charset = statement.getCharset() != null ? statement.getCharset() : SystemVariables.getDefaultValue("character_set_filesystem");
|
||||
String charset = statement.getCharset() != null ? statement.getCharset() : SystemVariables.getSysVars().getDefaultValue("character_set_filesystem");
|
||||
loadData.setCharset(charset);
|
||||
loadData.setFileName(fileName);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ public final class ServerLoadDataInfileHandler implements LoadDataInfileHandler
|
||||
schema = DbleServer.getInstance().getConfig().getSchemas().get(serverConnection.getSchema());
|
||||
tableId2DataNodeCache = (LayerCachePool) DbleServer.getInstance().getCacheService().getCachePool("TableID2DataNodeCache");
|
||||
tableName = statement.getTableName().getSimpleName();
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
tableName = tableName.toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ 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.SystemVariables;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.sqlengine.OneRawSQLQueryResultHandler;
|
||||
import com.actiontech.dble.sqlengine.SetTestJob;
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
@@ -231,7 +231,10 @@ public final class SetHandler {
|
||||
if (!handleTxIsolationInMultiStmt(c, contextTask, valueExpr)) return false;
|
||||
break;
|
||||
case SYSTEM_VARIABLES:
|
||||
if (SystemVariables.getDefaultValue(key) == null) {
|
||||
if (key.startsWith("@@")) {
|
||||
key = key.substring(2);
|
||||
}
|
||||
if (SystemVariables.getSysVars().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))));
|
||||
@@ -361,7 +364,10 @@ public final class SetHandler {
|
||||
case TX_ISOLATION:
|
||||
return handleTxIsolation(c, valueExpr);
|
||||
case SYSTEM_VARIABLES:
|
||||
if (SystemVariables.getDefaultValue(key) == null) {
|
||||
if (key.startsWith("@@")) {
|
||||
key = key.substring(2);
|
||||
}
|
||||
if (SystemVariables.getSysVars().getDefaultValue(key) == null) {
|
||||
c.writeErrMessage(ErrorCode.ERR_NOT_SUPPORTED, "system variable " + key + " is not supported");
|
||||
return false;
|
||||
}
|
||||
@@ -575,7 +581,7 @@ public final class SetHandler {
|
||||
|
||||
private static boolean checkValue(SQLExpr valueExpr) {
|
||||
return (valueExpr instanceof SQLCharExpr) || (valueExpr instanceof SQLIdentifierExpr) ||
|
||||
(valueExpr instanceof SQLIntegerExpr);
|
||||
(valueExpr instanceof SQLIntegerExpr) || (valueExpr instanceof SQLNumberExpr) || (valueExpr instanceof SQLBooleanExpr);
|
||||
}
|
||||
|
||||
private static KeyType parseKeyType(String key, boolean origin, KeyType defaultVariables) {
|
||||
@@ -623,6 +629,9 @@ public final class SetHandler {
|
||||
return null;
|
||||
}
|
||||
return (iValue == 1);
|
||||
} else if (valueExpr instanceof SQLBooleanExpr) {
|
||||
SQLBooleanExpr value = (SQLBooleanExpr) valueExpr;
|
||||
return value.getValue();
|
||||
}
|
||||
String strValue = parseStringValue(valueExpr);
|
||||
switch (strValue) {
|
||||
@@ -646,6 +655,12 @@ public final class SetHandler {
|
||||
} else if (valueExpr instanceof SQLIntegerExpr) {
|
||||
SQLIntegerExpr value = (SQLIntegerExpr) valueExpr;
|
||||
strValue = value.getNumber().toString();
|
||||
} else if (valueExpr instanceof SQLNumberExpr) {
|
||||
SQLNumberExpr value = (SQLNumberExpr) valueExpr;
|
||||
strValue = value.getNumber().toString();
|
||||
} else if (valueExpr instanceof SQLBooleanExpr) {
|
||||
SQLBooleanExpr value = (SQLBooleanExpr) valueExpr;
|
||||
strValue = String.valueOf(value.getValue());
|
||||
}
|
||||
return strValue;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package com.actiontech.dble.server.handler;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.net.handler.FrontendPrivileges;
|
||||
import com.actiontech.dble.net.mysql.OkPacket;
|
||||
@@ -34,7 +34,7 @@ public final class UseHandler {
|
||||
if (schema.charAt(0) == '\'' && schema.charAt(length - 1) == '\'') {
|
||||
schema = schema.substring(1, length - 1);
|
||||
}
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
schema = schema.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package com.actiontech.dble.server.response;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.route.factory.RouteStrategyFactory;
|
||||
import com.actiontech.dble.server.ServerConnection;
|
||||
@@ -48,7 +48,7 @@ public final class ShowColumns {
|
||||
showColumnsStatement.setDatabase(null);
|
||||
sql = showColumnsStatement.toString();
|
||||
}
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
schema = StringUtil.removeBackQuote(schema).toLowerCase();
|
||||
table = table.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package com.actiontech.dble.server.response;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.route.factory.RouteStrategyFactory;
|
||||
import com.actiontech.dble.server.ServerConnection;
|
||||
@@ -83,7 +83,7 @@ public final class ShowIndex {
|
||||
sql.append(" ");
|
||||
sql.append(strWhere);
|
||||
}
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
schema = StringUtil.removeBackQuote(schema).toLowerCase();
|
||||
table = table.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.server.response;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.mysql.PacketUtil;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.ShowTablesHandler;
|
||||
import com.actiontech.dble.backend.mysql.nio.handler.query.DMLResponseHandler;
|
||||
@@ -54,7 +55,7 @@ public final class ShowTables {
|
||||
return;
|
||||
}
|
||||
String showSchema = info.getSchema();
|
||||
if (showSchema != null && DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (showSchema != null && SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
showSchema = showSchema.toLowerCase();
|
||||
}
|
||||
String cSchema = showSchema == null ? c.getSchema() : showSchema;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.server.util;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDBNode;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDBPool;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDatasource;
|
||||
@@ -88,7 +89,7 @@ public final class GlobalTableUtil {
|
||||
for (TableConfig table : entry.getValue().getTables().values()) {
|
||||
if (table.isGlobalTable()) {
|
||||
String tableName = table.getName();
|
||||
if (config.getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
tableName = tableName.toLowerCase();
|
||||
}
|
||||
globalTableMap.put(entry.getKey() + "." + tableName, table);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package com.actiontech.dble.server.util;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.server.variables.SystemVariables;
|
||||
import com.actiontech.dble.config.ErrorCode;
|
||||
import com.actiontech.dble.config.ServerPrivileges;
|
||||
import com.actiontech.dble.config.model.SchemaConfig;
|
||||
@@ -69,7 +70,7 @@ public final class SchemaUtil {
|
||||
String msg = "No database selected";
|
||||
throw new SQLException(msg, "3D000", ErrorCode.ER_NO_DB_ERROR);
|
||||
}
|
||||
if (DbleServer.getInstance().getConfig().getSystem().isLowerCaseTableNames()) {
|
||||
if (SystemVariables.getSysVars().isLowerCaseTableNames()) {
|
||||
schemaInfo.table = schemaInfo.table.toLowerCase();
|
||||
schemaInfo.schema = schemaInfo.schema.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
package com.actiontech.dble.server.variables;
|
||||
|
||||
import com.actiontech.dble.sqlengine.SQLQueryResult;
|
||||
import com.actiontech.dble.sqlengine.SQLQueryResultListener;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MysqlVarsListener implements SQLQueryResultListener<SQLQueryResult<Map<String, String>>> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MysqlVarsListener.class);
|
||||
private final VarsExtractorHandler handler;
|
||||
|
||||
public MysqlVarsListener(VarsExtractorHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(SQLQueryResult<Map<String, String>> result) {
|
||||
if (!result.isSuccess()) {
|
||||
//not thread safe
|
||||
LOGGER.warn("Can't get variables from DataNode: " + result.getDataNode() + "!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* the logic is twist */
|
||||
if (!handler.isExtracting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String> kvs = result.getResult();
|
||||
handler.handleVars(kvs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -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.variables;
|
||||
|
||||
import com.actiontech.dble.config.ServerConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SysVarsExtractor {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SysVarsExtractor.class);
|
||||
|
||||
private final ServerConfig config;
|
||||
|
||||
public SysVarsExtractor(ServerConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public void extract() {
|
||||
VarsExtractorHandler handler = new VarsExtractorHandler();
|
||||
handler.execute();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
package com.actiontech.dble.server.variables;
|
||||
|
||||
public interface SystemGlobalVariable {
|
||||
void setVariable(String value, SystemVariables sys) throws RuntimeException;
|
||||
String getVariable();
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
package com.actiontech.dble.server.variables;
|
||||
|
||||
import com.actiontech.dble.util.StringUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class SystemVariables {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SystemVariables.class);
|
||||
|
||||
private Map<String, SystemGlobalVariable> globalVariables;
|
||||
private Map<String, String> sessionVariables;
|
||||
|
||||
private boolean isInited;
|
||||
private static final SystemVariables INSTANCE = new SystemVariables();
|
||||
|
||||
public static SystemVariables getSysVars() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private SystemVariables() {
|
||||
isInited = false;
|
||||
globalVariables = new HashMap<>();
|
||||
pickGlobalVariables();
|
||||
sessionVariables = new HashMap<>();
|
||||
pickSessionVariables();
|
||||
}
|
||||
|
||||
public boolean isInited() {
|
||||
return isInited;
|
||||
}
|
||||
|
||||
public void setInited() {
|
||||
if (isInited) {
|
||||
LOGGER.error("System variables have been inited!");
|
||||
}
|
||||
isInited = true;
|
||||
}
|
||||
|
||||
private void pickGlobalVariables() {
|
||||
globalVariables.put("lower_case_table_names", new SystemGlobalVariable() {
|
||||
String value = "0";
|
||||
|
||||
public void setVariable(String value, SystemVariables sys) throws RuntimeException {
|
||||
if (sys.isInited()) {
|
||||
throw new RuntimeException("lower_case_table_names is global static variable, don't been change at run time");
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getVariable() {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isLowerCaseTableNames() {
|
||||
Integer value = Integer.valueOf(globalVariables.get("lower_case_table_names").getVariable());
|
||||
return value != 0 ? true : false;
|
||||
}
|
||||
|
||||
private void pickSessionVariables() {
|
||||
//some may not useful for middle-ware
|
||||
sessionVariables.put("audit_log_current_session", null);
|
||||
sessionVariables.put("audit_log_filter_id", null);
|
||||
sessionVariables.put("auto_increment_increment", null);
|
||||
sessionVariables.put("auto_increment_offset", null);
|
||||
sessionVariables.put("autocommit", null);
|
||||
sessionVariables.put("big_tables", null);
|
||||
sessionVariables.put("binlog_direct_non_transactional_updates", null);
|
||||
sessionVariables.put("binlog_error_action", null);
|
||||
sessionVariables.put("binlog_format", null);
|
||||
sessionVariables.put("binlog_row_image", null);
|
||||
sessionVariables.put("binlog_rows_query_log_events", null);
|
||||
sessionVariables.put("binlogging_impossible_mode", null);
|
||||
sessionVariables.put("block_encryption_mode", null);
|
||||
sessionVariables.put("bulk_insert_buffer_size", null);
|
||||
sessionVariables.put("character_set_client", null);
|
||||
sessionVariables.put("character_set_connection", null);
|
||||
sessionVariables.put("character_set_database", null);
|
||||
sessionVariables.put("character_set_filesystem", null);
|
||||
sessionVariables.put("character_set_results", null);
|
||||
sessionVariables.put("character_set_server", null);
|
||||
sessionVariables.put("collation_connection", null);
|
||||
sessionVariables.put("collation_database", null);
|
||||
sessionVariables.put("collation_server", null);
|
||||
sessionVariables.put("completion_type", null);
|
||||
sessionVariables.put("debug", null);
|
||||
sessionVariables.put("debug_sync", null);
|
||||
sessionVariables.put("default_storage_engine", null);
|
||||
sessionVariables.put("default_tmp_storage_engine", null);
|
||||
sessionVariables.put("default_week_format", null);
|
||||
sessionVariables.put("disconnect_on_expired_password", null);
|
||||
sessionVariables.put("div_precision_increment", null);
|
||||
sessionVariables.put("end_markers_in_json", null);
|
||||
sessionVariables.put("eq_range_index_dive_limit", null);
|
||||
sessionVariables.put("error_count", null);
|
||||
sessionVariables.put("explicit_defaults_for_timestamp", null);
|
||||
sessionVariables.put("external_user", null);
|
||||
sessionVariables.put("foreign_key_checks", null);
|
||||
sessionVariables.put("group_concat_max_len", null);
|
||||
sessionVariables.put("gtid_next", null);
|
||||
sessionVariables.put("gtid_owned", null);
|
||||
sessionVariables.put("identity", null);
|
||||
sessionVariables.put("innodb_create_intrinsic", null);
|
||||
sessionVariables.put("innodb_ft_user_stopword_table", null);
|
||||
sessionVariables.put("innodb_lock_wait_timeout", null);
|
||||
sessionVariables.put("innodb_optimize_point_storage", null);
|
||||
sessionVariables.put("innodb_strict_mode", null);
|
||||
sessionVariables.put("innodb_support_xa", null);
|
||||
sessionVariables.put("innodb_table_locks", null);
|
||||
sessionVariables.put("innodb_tmpdir", null);
|
||||
sessionVariables.put("insert_id", null);
|
||||
sessionVariables.put("interactive_timeout", null);
|
||||
sessionVariables.put("join_buffer_size", null);
|
||||
sessionVariables.put("keep_files_on_create", null);
|
||||
sessionVariables.put("last_insert_id", null);
|
||||
sessionVariables.put("lc_messages", null);
|
||||
sessionVariables.put("lc_time_names", null);
|
||||
sessionVariables.put("lock_wait_timeout", null);
|
||||
sessionVariables.put("long_query_time", null);
|
||||
sessionVariables.put("low_priority_updates", null);
|
||||
sessionVariables.put("max_allowed_packet", null);
|
||||
sessionVariables.put("max_delayed_threads", null);
|
||||
sessionVariables.put("max_error_count", null);
|
||||
sessionVariables.put("max_execution_time", null);
|
||||
sessionVariables.put("max_heap_table_size", null);
|
||||
sessionVariables.put("max_insert_delayed_threads", null);
|
||||
sessionVariables.put("max_join_size", null);
|
||||
sessionVariables.put("max_length_for_sort_data", null);
|
||||
sessionVariables.put("max_seeks_for_key", null);
|
||||
sessionVariables.put("max_sort_length", null);
|
||||
sessionVariables.put("max_sp_recursion_depth", null);
|
||||
sessionVariables.put("max_statement_time", null);
|
||||
//max_tmp_tables This variable is unused. It is deprecated and is removed in MySQL 8.0
|
||||
sessionVariables.put("max_user_connections", null);
|
||||
sessionVariables.put("min_examined_row_limit", null);
|
||||
//multi_range_count This variable has no effect. It is deprecated and is removed in MySQL 8.0.
|
||||
sessionVariables.put("myisam_repair_threads", null);
|
||||
sessionVariables.put("myisam_sort_buffer_size", null);
|
||||
sessionVariables.put("myisam_stats_method", null);
|
||||
sessionVariables.put("ndb-allow-copying-alter-table", null);
|
||||
sessionVariables.put("ndb_autoincrement_prefetch_sz", null);
|
||||
sessionVariables.put("ndb-blob-read-batch-bytes", null);
|
||||
sessionVariables.put("ndb-blob-write-batch-bytes", null);
|
||||
sessionVariables.put("ndb_deferred_constraints", null);
|
||||
sessionVariables.put("ndb_force_send", null);
|
||||
sessionVariables.put("ndb_fully_replicated", null);
|
||||
sessionVariables.put("ndb_index_stat_enable", null);
|
||||
sessionVariables.put("ndb_index_stat_option", null);
|
||||
sessionVariables.put("ndb_join_pushdown", null);
|
||||
sessionVariables.put("ndb_log_bin", null);
|
||||
sessionVariables.put("ndb_log_bin", null);
|
||||
sessionVariables.put("ndb_table_no_logging", null);
|
||||
sessionVariables.put("ndb_table_temporary", null);
|
||||
sessionVariables.put("ndb_use_copying_alter_table", null);
|
||||
sessionVariables.put("ndb_use_exact_count", null);
|
||||
sessionVariables.put("ndb_use_transactions", null);
|
||||
sessionVariables.put("ndbinfo_max_bytes", null);
|
||||
sessionVariables.put("ndbinfo_max_rows", null);
|
||||
sessionVariables.put("ndbinfo_show_hidden", null);
|
||||
sessionVariables.put("ndbinfo_table_prefix", null);
|
||||
sessionVariables.put("net_buffer_length", null);
|
||||
sessionVariables.put("net_read_timeout", null);
|
||||
sessionVariables.put("net_retry_count", null);
|
||||
sessionVariables.put("net_write_timeout", null);
|
||||
sessionVariables.put("new", null);
|
||||
sessionVariables.put("old_alter_table", null);
|
||||
sessionVariables.put("old_passwords", null);
|
||||
sessionVariables.put("optimizer_prune_level", null);
|
||||
sessionVariables.put("optimizer_search_depth", null);
|
||||
sessionVariables.put("optimizer_switch", null);
|
||||
sessionVariables.put("optimizer_trace", null);
|
||||
sessionVariables.put("optimizer_trace_features", null);
|
||||
sessionVariables.put("optimizer_trace_limit", null);
|
||||
sessionVariables.put("optimizer_trace_max_mem_size", null);
|
||||
sessionVariables.put("optimizer_trace_offset", null);
|
||||
sessionVariables.put("parser_max_mem_size", null);
|
||||
sessionVariables.put("preload_buffer_size", null);
|
||||
sessionVariables.put("profiling", null);
|
||||
sessionVariables.put("profiling_history_size", null);
|
||||
sessionVariables.put("proxy_user", null);
|
||||
sessionVariables.put("pseudo_slave_mode", null);
|
||||
sessionVariables.put("pseudo_thread_id", null);
|
||||
sessionVariables.put("query_alloc_block_size", null);
|
||||
sessionVariables.put("query_cache_type", null);
|
||||
sessionVariables.put("query_cache_wlock_invalidate", null);
|
||||
sessionVariables.put("query_prealloc_size", null);
|
||||
sessionVariables.put("rand_seed1", null);
|
||||
sessionVariables.put("rand_seed2", null);
|
||||
sessionVariables.put("range_alloc_block_size", null);
|
||||
sessionVariables.put("range_optimizer_max_mem_size", null);
|
||||
sessionVariables.put("rbr_exec_mode", null);
|
||||
sessionVariables.put("read_buffer_size", null);
|
||||
sessionVariables.put("read_rnd_buffer_size", null);
|
||||
sessionVariables.put("session_track_gtids", null);
|
||||
sessionVariables.put("session_track_schema", null);
|
||||
sessionVariables.put("session_track_state_change", null);
|
||||
sessionVariables.put("session_track_system_variables", null);
|
||||
sessionVariables.put("show_old_temporals", null);
|
||||
sessionVariables.put("sort_buffer_size", null);
|
||||
sessionVariables.put("sql_auto_is_null", null);
|
||||
sessionVariables.put("sql_big_selects", null);
|
||||
sessionVariables.put("sql_buffer_result", null);
|
||||
sessionVariables.put("sql_log_bin", null);
|
||||
sessionVariables.put("sql_log_off", null);
|
||||
sessionVariables.put("sql_mode", null);
|
||||
sessionVariables.put("sql_notes", null);
|
||||
sessionVariables.put("sql_quote_show_create", null);
|
||||
sessionVariables.put("sql_safe_updates", null);
|
||||
sessionVariables.put("sql_select_limit", null);
|
||||
sessionVariables.put("sql_warnings", null);
|
||||
sessionVariables.put("storage_engine", null);
|
||||
sessionVariables.put("thread_pool_high_priority_connection", null);
|
||||
sessionVariables.put("thread_pool_prio_kickup_timer", null);
|
||||
sessionVariables.put("time_zone", null);
|
||||
sessionVariables.put("timestamp", null);
|
||||
sessionVariables.put("tmp_table_size", null);
|
||||
sessionVariables.put("transaction_alloc_block_size", null);
|
||||
sessionVariables.put("transaction_allow_batching", null);
|
||||
sessionVariables.put("transaction_prealloc_size", null);
|
||||
sessionVariables.put("transaction_write_set_extraction", null);
|
||||
sessionVariables.put("tx_isolation", null); //transaction-isolation
|
||||
sessionVariables.put("tx_read_only", null); // OFF|0|false //transaction-read-only
|
||||
sessionVariables.put("unique_checks", null); // ON|1|TRUE
|
||||
sessionVariables.put("updatable_views_with_limit", null); // ON|1|TRUE
|
||||
sessionVariables.put("version_tokens_session", null);
|
||||
sessionVariables.put("version_tokens_session_number", null);
|
||||
sessionVariables.put("wait_timeout", null);
|
||||
sessionVariables.put("warning_count", null);
|
||||
}
|
||||
|
||||
public void setDefaultValue(String variable, String value) {
|
||||
if (StringUtil.isEmpty(variable))
|
||||
return;
|
||||
|
||||
String key = variable.toLowerCase();
|
||||
if (sessionVariables.containsKey(key)) {
|
||||
sessionVariables.replace(key, value);
|
||||
} else {
|
||||
SystemGlobalVariable gv = globalVariables.get(key);
|
||||
if (gv != null) {
|
||||
gv.setVariable(value, this);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public String getGlobalVarValue(String variable) {
|
||||
SystemGlobalVariable gv = globalVariables.get(variable.toLowerCase());
|
||||
if (gv != null) {
|
||||
return gv.getVariable();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDefaultValue(String variable) {
|
||||
if (StringUtil.isEmpty(variable))
|
||||
return null;
|
||||
|
||||
return sessionVariables.get(variable.toLowerCase());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2017 ActionTech.
|
||||
* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
|
||||
*/
|
||||
|
||||
package com.actiontech.dble.server.variables;
|
||||
|
||||
import com.actiontech.dble.DbleServer;
|
||||
import com.actiontech.dble.backend.datasource.PhysicalDBNode;
|
||||
import com.actiontech.dble.sqlengine.OneRawSQLQueryResultHandler;
|
||||
import com.actiontech.dble.sqlengine.SQLJob;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VarsExtractorHandler {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(VarsExtractorHandler.class);
|
||||
private static final String[] MYSQL_SHOW_VARIABLES_COLS = new String[]{
|
||||
"Variable_name",
|
||||
"Value"};
|
||||
private static final String MYSQL_SHOW_VARIABLES = "show variables";
|
||||
private AtomicBoolean extracting;
|
||||
private Lock lock;
|
||||
private Condition done;
|
||||
|
||||
public VarsExtractorHandler() {
|
||||
this.extracting = new AtomicBoolean(false);
|
||||
this.lock = new ReentrantLock();
|
||||
this.done = lock.newCondition();
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
Map<String, PhysicalDBNode> dataNodes = DbleServer.getInstance().getConfig().getDataNodes();
|
||||
for (Map.Entry<String, PhysicalDBNode> entry : dataNodes.entrySet()) {
|
||||
if (extracting.get()) {
|
||||
break;
|
||||
}
|
||||
|
||||
OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler(MYSQL_SHOW_VARIABLES_COLS, new MysqlVarsListener(this));
|
||||
PhysicalDBNode dn = entry.getValue();
|
||||
SQLJob sqlJob = new SQLJob(MYSQL_SHOW_VARIABLES, dn.getDatabase(), resultHandler, dn.getDbPool().getSource());
|
||||
sqlJob.run();
|
||||
}
|
||||
|
||||
waitDone();
|
||||
}
|
||||
|
||||
public void handleVars(Map<String, String> vars) {
|
||||
for (Map.Entry<String, String> entry : vars.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
SystemVariables.getSysVars().setDefaultValue(key, value);
|
||||
}
|
||||
SystemVariables.getSysVars().setInited();
|
||||
signalDone();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public boolean isExtracting() {
|
||||
return extracting.compareAndSet(false, true);
|
||||
}
|
||||
|
||||
private void signalDone() {
|
||||
lock.lock();
|
||||
try {
|
||||
done.signal();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitDone() {
|
||||
lock.lock();
|
||||
try {
|
||||
while (!extracting.get()) {
|
||||
done.await();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.warn("wait variables grapping done " + e);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,13 @@
|
||||
</rule>
|
||||
</tableRule>
|
||||
|
||||
<tableRule name="sharding-by-hash3">
|
||||
<rule>
|
||||
<columns>id</columns>
|
||||
<algorithm>hashLong3</algorithm>
|
||||
</rule>
|
||||
</tableRule>
|
||||
|
||||
<tableRule name="sharding-by-mod">
|
||||
<rule>
|
||||
<columns>id</columns>
|
||||
@@ -82,7 +89,7 @@
|
||||
</function>
|
||||
|
||||
<!-- Hash partition,when partitionLength=1, it is a mod partition-->
|
||||
<!--MAX(sum(count*length[i]) must not more then 1024-->
|
||||
<!--MAX(sum(count*length[i]) must not more then 2880-->
|
||||
<function name="hashLong" class="Hash">
|
||||
<property name="partitionCount">8</property>
|
||||
<property name="partitionLength">128</property>
|
||||
@@ -91,7 +98,7 @@
|
||||
</function>
|
||||
|
||||
<!-- Hash partition,when partitionLength=1, it is a mod partition-->
|
||||
<!--MAX(sum(count*length[i]) must not more then 1024-->
|
||||
<!--MAX(sum(count*length[i]) must not more then 2880-->
|
||||
<function name="hashLong2" class="Hash">
|
||||
<property name="partitionCount">2</property>
|
||||
<property name="partitionLength">512</property>
|
||||
@@ -99,6 +106,15 @@
|
||||
<property name="partitionLength">4,5</property>-->
|
||||
</function>
|
||||
|
||||
<!-- Hash partition,when partitionLength=1, it is a mod partition-->
|
||||
<!--MAX(sum(count*length[i]) must not more then 2880-->
|
||||
<function name="hashLong3" class="Hash">
|
||||
<property name="partitionCount">2,1</property>
|
||||
<property name="partitionLength">256,512</property>
|
||||
<!-- <property name="partitionCount">2,3</property>
|
||||
<property name="partitionLength">4,5</property>-->
|
||||
</function>
|
||||
|
||||
<!-- eg: mod 4 -->
|
||||
<function name="hashmod" class="Hash">
|
||||
<property name="partitionCount">4</property>
|
||||
@@ -117,8 +133,8 @@
|
||||
<!-- 4 case:
|
||||
1.set sEndDate and defaultNode: input <sBeginDate ,router to defaultNode; input>sEndDate ,mod the period
|
||||
2.set sEndDate, but no defaultNode:input <sBeginDate report error; input>sEndDate ,mod the period
|
||||
3.set defaultNode without sEndDate: input <sBeginDate router to defaultNode;input>sEndDate + (node size)*sPartionDay-1 will report error(expected is defaultNode,but can't control now)
|
||||
4.sEndDate and defaultNode are all not set: input <sBeginDate report error;input>sEndDate + (node size)*sPartionDay-1 will report error
|
||||
3.set defaultNode without sEndDate: input <sBeginDate router to defaultNode;input>sBeginDate + (node size)*sPartionDay-1 will report error(expected is defaultNode,but can't control now)
|
||||
4.sEndDate and defaultNode are all not set: input <sBeginDate report error;input>sBeginDate + (node size)*sPartionDay-1 will report error
|
||||
-->
|
||||
<function name="partbydate"
|
||||
class="Date">
|
||||
|
||||
@@ -14,8 +14,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public class Testparser {
|
||||
public static void main(String args[]) {
|
||||
|
||||
@@ -24,95 +22,95 @@ public class Testparser {
|
||||
// obj.test("CREATE TABLE `xx`.`char_columns_test` (`id` int(11) NOT NULL,`c_char` char(255) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
|
||||
// obj.test("drop table char_columns_test;");
|
||||
// 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);
|
||||
// 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 @@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;";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET max_connections = 1000;";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET @x = 1;";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET @x = 1, SESSION sql_mode = '';";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET GLOBAL sort_buffer_size = 1000000, SESSION sort_buffer_size = 1000000;";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET GLOBAL max_connections = 1000, sort_buffer_size = 1000000;";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET xa =0 ;";
|
||||
obj.test(strSetSql);
|
||||
strSetSql = "SET xa = off ;";
|
||||
obj.test(strSetSql);
|
||||
// strSetSql = "SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET TRANSACTION ISOLATION LEVEL READ COMMITTED ;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET TRANSACTION READ WRITE;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET TRANSACTION read only;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET @total_tax = (SELECT SUM(tax) FROM taxable_transactions);";
|
||||
// obj.test(strSetSql);
|
||||
//
|
||||
// strSetSql = "SET @@session.sql_mode = 'TRADITIONAL';";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET @@global.sql_mode = 'TRADITIONAL';";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET @@sql_mode = 'TRADITIONAL';";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET GLOBAL sql_log_bin = ON;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET max_connections = 1000;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET @x = 1;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET @x = 1, SESSION sql_mode = '';";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET GLOBAL sort_buffer_size = 1000000, SESSION sort_buffer_size = 1000000;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET GLOBAL max_connections = 1000, sort_buffer_size = 1000000;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET xa =0 ;";
|
||||
// obj.test(strSetSql);
|
||||
// strSetSql = "SET xa = off ;";
|
||||
// obj.test(strSetSql);
|
||||
//String strShowSql = "";
|
||||
//strShowSql = "show create table a;";
|
||||
//obj.test(strShowSql);
|
||||
@@ -231,10 +229,18 @@ public class Testparser {
|
||||
+ " from char_columns where id =1 and name = 'x';";
|
||||
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id > SOME(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id > ANY(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id > ALL(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select * from constant_one where id <> ALL(select name from constant_two);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "SELECT BINARY 'a' = 'A';";
|
||||
// obj.test(selectSQl);
|
||||
selectSQl = "SELECT b'1000001';";
|
||||
obj.test(selectSQl);
|
||||
// selectSQl = "SELECT b'1000001';";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "SELECT GET_FORMAT(DATE);";
|
||||
// obj.test(selectSQl);
|
||||
// selectSQl = "select CURRENT_DATE;";//not support
|
||||
@@ -356,6 +362,8 @@ public class Testparser {
|
||||
// //not support
|
||||
// selectSQl = "select sql_big_result distinct pad from sbtest1;";
|
||||
// obj.test(selectSQl);
|
||||
String insertSQl = "insert into test_shard values(1,1,'a\\%string','test001');";
|
||||
obj.test(insertSQl);
|
||||
|
||||
}
|
||||
|
||||
@@ -603,6 +611,19 @@ public class Testparser {
|
||||
System.out.println("---------------------------");
|
||||
}
|
||||
}
|
||||
if (selectQueryBlock.getWhere() != null) {
|
||||
if(selectQueryBlock.getWhere() instanceof SQLBinaryOpExpr){
|
||||
SQLBinaryOpExpr where = (SQLBinaryOpExpr)(selectQueryBlock.getWhere());
|
||||
System.out.println("where right:");
|
||||
System.out.println("class :" + where.getRight().getClass());
|
||||
System.out.println("---------------------------");
|
||||
}
|
||||
else{
|
||||
System.out.println("where:");
|
||||
System.out.println("class :" + selectQueryBlock.getWhere().getClass());
|
||||
System.out.println("---------------------------");
|
||||
}
|
||||
}
|
||||
} else if (sqlSelectQuery instanceof MySqlUnionQuery) {
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<!-- 用户访问定义,用户名、密码、schema等信息。 -->
|
||||
<user name="test">
|
||||
<property name="password">test</property>
|
||||
<property name="schemas">dbtest,mysqldb,cndb,testdb,dubbo,dubbo2,config,none_node_test,solo1,ignoreSchemaTest
|
||||
<property name="schemas">dbtest,mysqldb,cndb,TESTDB,dubbo,dubbo2,config,none_node_test,solo1,ignoreSchemaTest
|
||||
</property>
|
||||
<property name="benchmark">11111</property>
|
||||
<!-- benchmark 基准, 当前端的整体connection数达到基准值是, 对来自该账户的请求开始拒绝连接,0或不设表示不限制 -->
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BuildTime 2017-10-24 10:24:07
|
||||
BuildTime 2017-10-17 08:14:49
|
||||
MavenVersion 2.17.09.0-dev
|
||||
GitUrl https://github.com/actiontech/dble
|
||||
WebSite http://dble.cloud/
|
||||
|
||||
Reference in New Issue
Block a user