use of com.actiontech.dble.plan.common.item.subquery.ItemSubQuery in project dble by actiontech.
the class BaseHandlerBuilder method handleBlockingSubQuery.
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.info("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));
}
}
use of com.actiontech.dble.plan.common.item.subquery.ItemSubQuery in project dble by actiontech.
the class GlobalTableProcessor method initGlobalStatus.
/**
* @param tn
* @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 || 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 er join as an un global table
tn.setUnGlobalTableCount(1);
Set<String> newSet = new HashSet<>();
newSet.addAll(tn.getReferedTableNodes().get(0).getNoshardNode());
tn.setNoshardNode(newSet);
} else {
int unGlobalCount = calcUnGlobalCount(tn);
tn.setUnGlobalTableCount(unGlobalCount);
if (tn.getNoshardNode() != null && tn.getNoshardNode().size() == 0) {
tn.setNoshardNode(null);
}
if (!status) {
tn.setNoshardNode(null);
return false;
}
if (unGlobalCount == 1 && tn instanceof JoinNode) {
// joinNode
JoinNode jn = (JoinNode) tn;
if (jn.isNotIn()) {
tn.setNoshardNode(null);
status = false;
} else if (jn.isInnerJoin()) {
if (!isGlobalTableBigEnough(jn)) {
tn.setNoshardNode(null);
status = false;
}
} else {
// left join
PlanNode left = jn.getLeftNode();
if (left.getUnGlobalTableCount() == 0) {
// left node is global,left join will not push down
tn.setNoshardNode(null);
status = false;
} else if (left.type() == PlanNode.PlanNodeType.TABLE || !PlanUtil.isERNode(left)) {
if (!isGlobalTableBigEnough(jn)) {
tn.setNoshardNode(null);
status = false;
}
} else {
// left node is not single table or er table
tn.setNoshardNode(null);
status = false;
}
}
} else if (unGlobalCount != 0) {
tn.setNoshardNode(null);
status = false;
}
}
return status;
}
use of com.actiontech.dble.plan.common.item.subquery.ItemSubQuery in project dble by actiontech.
the class SelectedProcessor method pushSelected.
/**
* pushSelected
* if parent's selected refered isA.id,A.name,B.id,B.name,
* node of A only need push A.id,A.nam
*
* @param qtn
* @param toPushColumns
* @return
*/
private static PlanNode pushSelected(PlanNode qtn, Collection<Item> toPushColumns) {
boolean isPushDownNode = false;
if (PlanUtil.isGlobalOrER(qtn)) {
// TODO:buildColumnRefers for every child
List<Item> selList = qtn.getColumnsSelected();
for (Item pdSel : toPushColumns) {
if (!selList.contains(pdSel)) {
selList.add(pdSel);
}
}
isPushDownNode = true;
qtn.setUpRefers(isPushDownNode);
return qtn;
}
isPushDownNode = (qtn.type() == PlanNode.PlanNodeType.TABLE || qtn.type() == PlanNode.PlanNodeType.NONAME);
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()) {
List<Item> selList = qtn.getColumnsSelected();
for (Item pdSel : toPushColumns) {
if (!selList.contains(pdSel)) {
selList.add(pdSel);
}
}
qtn.setUpRefers(isPushDownNode);
} else {
List<Item> selList = qtn.getColumnsSelected();
selList.clear();
boolean existSum = false;
for (Item toPush : toPushColumns) {
selList.add(toPush);
existSum |= toPush.type().equals(Item.ItemType.SUM_FUNC_ITEM);
}
// if only push id,it will miss sum(id)
if (!existSum && qtn.getSumFuncs().size() > 0) {
selList.add(qtn.getSumFuncs().iterator().next());
}
qtn.setUpRefers(isPushDownNode);
}
PlanNode.PlanNodeType i = qtn.type();
if (i == PlanNode.PlanNodeType.NONAME) {
return qtn;
} else if (i == PlanNode.PlanNodeType.TABLE) {
return qtn;
} else {
for (PlanNode child : qtn.getChildren()) {
List<Item> referList = qtn.getColumnsReferedByChild(child);
if (referList.isEmpty()) {
referList.add(new ItemInt(1));
}
Collection<Item> pdRefers = getPushDownSel(qtn, child, referList);
pushSelected(child, pdRefers);
}
return qtn;
}
}
}
use of com.actiontech.dble.plan.common.item.subquery.ItemSubQuery in project dble by actiontech.
the class GlobalTableProcessor method calcUnGlobalCount.
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) {
resetNoShardNode(tn, tnChild);
unGlobalCount += tnChild.getUnGlobalTableCount();
}
}
return unGlobalCount;
}
use of com.actiontech.dble.plan.common.item.subquery.ItemSubQuery in project dble by actiontech.
the class MyOptimizer method updateReferedTableNodes.
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;
}
Aggregations