@Override
public void onRelationFormula(State2 relation) { }
};
State2 r1 = TableReferenceTranslation.of(tableReference.get(0), storesForJoin, translates, schema).interpret();
State2 r2 = TableReferenceTranslation.of(tableReference.get(1), storesForJoin, translates, schema).interpret();
if (natural != null) {
throw new RuntimeException("NATURAL JOIN is not supported"); // TODO
}
if (joinSpecification == null) {
// TODO
throw new RuntimeException("JOIN specification missing");
}
boolean isInnerJoin = joinType == null || joinType.INNER() != null;
ColumnNamesImpl named = new ColumnNamesImpl();
named.addAll(r1.named().inner());
named.addAll(r2.named().inner());
if (! isInnerJoin) {
r1.overwriteExpand();
r2.overwriteExpand();
}
Proposition p = visitJoinSpecification(joinSpecification, columnNamesLookupForJoin2(r1, r2));
// TODO move the check inside {@link Proposition} instead of matching like this
boolean pIsEq;
String pcode = p.code(columnIndexesForJoin2(r1, r2));
Matcher eqMatcher = EQ_PATTERN.matcher(pcode);
pIsEq = eqMatcher.matches();
if (pIsEq) {
// TODO refactor
int index1 = Integer.parseInt(eqMatcher.group(1));
int index2 = Integer.parseInt(eqMatcher.group(2));
if (index1 > index2) {
int tmp = index1;
index1 = index2;
index2 = tmp;
}
boolean bothColumnsFromSameOperand = (index1 > r1.relation().columns().size() || index2 <= r1.relation().columns().size());
if (bothColumnsFromSameOperand) {
pIsEq = false;
} else if (isInnerJoin) {
index2 = index2 - r1.relation().columns().size();
SimpleColumn replacedColumn = r2.relation().columns().get(index2 - 1);
SimpleColumn replacedBy = r1.relation().columns().get(index1 - 1);
for (ColumnNamesImpl cibn : relationsFound.values()) {
// TODO improve time complexity
cibn.replace(replacedColumn, replacedBy);
}
named.replace(replacedColumn, replacedBy);
}
}
if (checkContainsSubquery(p)) {
throw new RuntimeException("not implemented (EXISTS in JOIN condition)");
}
Relation rel;
if (! isInnerJoin) {
if (joinType.UNION() != null) {
throw new RuntimeException("UNION JOIN is not supported");// TODO
} else {
checkNotNull(joinType.outerJoinType());
if (joinType.outerJoinType().LEFT() != null) {
rel = r1.relation().leftOuterJoin(r2.relation(), pcode, pIsEq);
} else if (joinType.outerJoinType().RIGHT() != null) {
rel = r1.relation().rightOuterJoin(r2.relation(), pcode, pIsEq);
} else {
checkNotNull(joinType.outerJoinType().FULL());
rel = r1.relation().fullOuterJoin(r2.relation(), pcode, pIsEq);
}
}
} else {
rel = r1.relation().join(r2.relation(), pcode, pIsEq);
}
return makeState2(rel, rel.columns(), named);
}