use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class ItemField method fixFields.
@Override
public Item fixFields(NameResolutionContext context) {
if (this.isWild())
return this;
String tmpFieldTable = null;
String tmpFieldName = getItemName();
PlanNode planNode = context.getPlanNode();
if (context.getPlanNode().type() == PlanNodeType.MERGE) {
return getMergeNodeColumn(tmpFieldTable, tmpFieldName, planNode);
}
Item column = null;
if (context.isFindInSelect()) {
// try to find in selectlist
if (StringUtils.isEmpty(getTableName())) {
for (NamedField namedField : planNode.getOuterFields().keySet()) {
if (StringUtils.equalsIgnoreCase(tmpFieldName, namedField.getName())) {
if (column == null) {
column = planNode.getOuterFields().get(namedField);
} else
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "42S22", "duplicate column:" + this);
}
}
} else {
tmpFieldTable = getTableName();
column = planNode.getOuterFields().get(new NamedField(tmpFieldTable, tmpFieldName, null));
}
}
if (column != null && context.isSelectFirst()) {
return column;
}
// find from inner fields
Item columnFromMeta = null;
if (StringUtils.isEmpty(getTableName())) {
for (NamedField namedField : planNode.getInnerFields().keySet()) {
if (StringUtils.equalsIgnoreCase(tmpFieldName, namedField.getName())) {
if (columnFromMeta == null) {
tmpFieldTable = namedField.getTable();
NamedField coutField = planNode.getInnerFields().get(new NamedField(tmpFieldTable, tmpFieldName, null));
this.tableName = namedField.getTable();
getReferTables().clear();
this.getReferTables().add(coutField.planNode);
columnFromMeta = this;
} else {
if (planNode.type() == PlanNodeType.JOIN) {
JoinNode jn = (JoinNode) planNode;
if (jn.getUsingFields() != null && jn.getUsingFields().contains(columnFromMeta.getItemName().toLowerCase())) {
continue;
}
}
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "42S22", "duplicate column:" + this);
}
}
}
} else {
tmpFieldTable = getTableName();
NamedField tmpField = new NamedField(tmpFieldTable, tmpFieldName, null);
if (planNode.getInnerFields().containsKey(tmpField)) {
NamedField coutField = planNode.getInnerFields().get(tmpField);
getReferTables().clear();
getReferTables().add(coutField.planNode);
this.tableName = tmpField.getTable();
columnFromMeta = this;
}
}
if (columnFromMeta != null) {
return columnFromMeta;
} else if (column == null)
throw new MySQLOutPutException(ErrorCode.ER_OPTIMIZER, "42S22", "column " + this + " not found");
else {
return column;
}
}
use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class ConfigTest method testERjoin.
private boolean testERjoin(ERTable er0, ERTable er1) {
Class<ERJoinChooser> classERJoin = ERJoinChooser.class;
try {
Constructor<ERJoinChooser> construtor = classERJoin.getConstructor(new Class[] { JoinNode.class, Map.class });
Object instance = construtor.newInstance(new Object[] { new JoinNode(), this.erRealtions });
Method isERRelstionMethod = classERJoin.getDeclaredMethod("isErRelation", new Class[] { ERTable.class, ERTable.class });
isERRelstionMethod.setAccessible(true);
Object result = isERRelstionMethod.invoke(instance, new Object[] { er0, er1 });
return (Boolean) result;
} catch (Exception e) {
System.out.println(e);
return false;
}
}
use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class FilterPusher method getJoinNode.
private static PlanNode getJoinNode(PlanNode qtn, List<Item> dnfNodeToPush) {
JoinNode jn = (JoinNode) qtn;
List<Item> dnfNodetoPushToLeft = new LinkedList<>();
List<Item> dnfNodetoPushToRight = new LinkedList<>();
List<Item> leftCopyedPushFilters = new LinkedList<>();
List<Item> rightCopyedPushFilters = new LinkedList<>();
List<Item> dnfNodeToCurrent = new LinkedList<>();
PlanUtil.findJoinKeysAndRemoveIt(dnfNodeToPush, jn);
for (Item filter : dnfNodeToPush) {
// ex. 1 = -1
if (filter.getReferTables().size() == 0) {
dnfNodetoPushToLeft.add(filter);
dnfNodetoPushToRight.add(filter);
continue;
}
if (PlanUtil.canPush(filter, jn.getLeftNode(), jn)) {
dnfNodetoPushToLeft.add(filter);
} else if (PlanUtil.canPush(filter, jn.getRightNode(), jn)) {
dnfNodetoPushToRight.add(filter);
} else {
dnfNodeToCurrent.add(filter);
}
}
if (jn.isInnerJoin() || jn.isLeftOuterJoin() || jn.isRightOuterJoin()) {
// push the left expr to join filter's right condition
rightCopyedPushFilters.addAll(copyFilterToJoinOnColumns(dnfNodetoPushToLeft, jn.getLeftKeys(), jn.getRightKeys()));
// push the right expr to join filter's left condition
leftCopyedPushFilters.addAll(copyFilterToJoinOnColumns(dnfNodetoPushToRight, jn.getRightKeys(), jn.getLeftKeys()));
}
// if it can not push down, merge to current where
Item node = FilterUtils.and(dnfNodeToCurrent);
if (node != null) {
qtn.query(FilterUtils.and(qtn.getWhereFilter(), node));
}
if (jn.isInnerJoin() || jn.isLeftOuterJoin() || jn.isRightOuterJoin()) {
if (jn.isLeftOuterJoin()) {
// left join, push down the right join ,but still contains right joins condition
jn.query(FilterUtils.and(qtn.getWhereFilter(), FilterUtils.and(dnfNodetoPushToRight)));
}
if (jn.isRightOuterJoin()) {
// right join, push down the left join ,but still contains left joins condition
jn.query(FilterUtils.and(qtn.getWhereFilter(), FilterUtils.and(dnfNodetoPushToLeft)));
}
// merge
dnfNodetoPushToRight.addAll(rightCopyedPushFilters);
dnfNodetoPushToLeft.addAll(leftCopyedPushFilters);
refreshPdFilters(jn, dnfNodetoPushToLeft);
refreshPdFilters(jn, dnfNodetoPushToRight);
jn.setLeftNode(pushFilter(jn.getLeftNode(), dnfNodetoPushToLeft));
jn.setRightNode(pushFilter(((JoinNode) qtn).getRightNode(), dnfNodetoPushToRight));
} else {
if (!dnfNodeToPush.isEmpty()) {
jn.query(FilterUtils.and(qtn.getWhereFilter(), FilterUtils.and(dnfNodeToPush)));
}
}
return jn;
}
use of com.actiontech.dble.plan.node.JoinNode in project dble by actiontech.
the class FilterPusher method pushJoinOnFilter.
/**
* inner join's other join on would add to where when FilterPre and push down,
* when Left join, eg" select * from t1 left join t2 on t1.id=t2.id and t1.id = 10 and
* t2.name = 'aaa' push down t2.id=10 and t2.name='aaa'
*/
private static PlanNode pushJoinOnFilter(PlanNode qtn) {
if (PlanUtil.isGlobalOrER(qtn))
return qtn;
if (qtn.type().equals(PlanNodeType.JOIN)) {
JoinNode jn = (JoinNode) qtn;
Item otherJoinOn = jn.getOtherJoinOnFilter();
if (jn.isLeftOuterJoin() && otherJoinOn != null) {
List<Item> pushToRightNode = new ArrayList<>();
List<Item> splitedFilters = FilterUtils.splitFilter(otherJoinOn);
for (Item filter : splitedFilters) {
if (filter.getReferTables().isEmpty())
pushToRightNode.add(filter);
else if (PlanUtil.canPush(filter, jn.getRightNode(), jn))
pushToRightNode.add(filter);
else if (PlanUtil.canPush(filter, jn.getLeftNode(), jn)) {
Item copyedFilter = copyFilterToJoinOnColumns(filter, jn.getRightKeys(), jn.getLeftKeys());
if (copyedFilter != null)
pushToRightNode.add(copyedFilter);
} else
continue;
}
if (!pushToRightNode.isEmpty()) {
splitedFilters.removeAll(pushToRightNode);
Item newOtherJoinOn = FilterUtils.and(splitedFilters);
jn.setOtherJoinOnFilter(newOtherJoinOn);
refreshPdFilters(jn, pushToRightNode);
List<Item> subHavingList = new ArrayList<>();
List<Item> subWhereList = new ArrayList<>();
for (Item filter : pushToRightNode) {
if (filter.isWithSumFunc()) {
subHavingList.add(filter);
} else {
subWhereList.add(filter);
}
}
Item subHaving = FilterUtils.and(subHavingList);
Item subWhere = FilterUtils.and(subWhereList);
jn.getRightNode().having(FilterUtils.and(jn.getRightNode().getHavingFilter(), subHaving));
jn.getRightNode().setWhereFilter(FilterUtils.and(jn.getRightNode().getWhereFilter(), subWhere));
}
}
}
for (PlanNode child : qtn.getChildren()) pushJoinOnFilter(child);
return qtn;
}
use of com.actiontech.dble.plan.node.JoinNode 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;
}
Aggregations