use of org.apache.calcite.sql.JoinType in project calcite by apache.
the class SqlToRelConverter method convertFrom.
/**
* Converts a FROM clause into a relational expression.
*
* @param bb Scope within which to resolve identifiers
* @param from FROM clause of a query. Examples include:
*
* <ul>
* <li>a single table ("SALES.EMP"),
* <li>an aliased table ("EMP AS E"),
* <li>a list of tables ("EMP, DEPT"),
* <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
* DEPT.DEPTNO"),
* <li>a VALUES clause ("VALUES ('Fred', 20)"),
* <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
* <li>or any combination of the above.
* </ul>
*/
protected void convertFrom(Blackboard bb, SqlNode from) {
if (from == null) {
bb.setRoot(LogicalValues.createOneRow(cluster), false);
return;
}
final SqlCall call;
final SqlNode[] operands;
switch(from.getKind()) {
case MATCH_RECOGNIZE:
convertMatchRecognize(bb, (SqlCall) from);
return;
case AS:
call = (SqlCall) from;
convertFrom(bb, call.operand(0));
if (call.operandCount() > 2 && bb.root instanceof Values) {
final List<String> fieldNames = new ArrayList<>();
for (SqlNode node : Util.skip(call.getOperandList(), 2)) {
fieldNames.add(((SqlIdentifier) node).getSimple());
}
bb.setRoot(relBuilder.push(bb.root).rename(fieldNames).build(), true);
}
return;
case WITH_ITEM:
convertFrom(bb, ((SqlWithItem) from).query);
return;
case WITH:
convertFrom(bb, ((SqlWith) from).body);
return;
case TABLESAMPLE:
operands = ((SqlBasicCall) from).getOperands();
SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]);
if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) {
String sampleName = ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec).getName();
datasetStack.push(sampleName);
convertFrom(bb, operands[0]);
datasetStack.pop();
} else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) {
SqlSampleSpec.SqlTableSampleSpec tableSampleSpec = (SqlSampleSpec.SqlTableSampleSpec) sampleSpec;
convertFrom(bb, operands[0]);
RelOptSamplingParameters params = new RelOptSamplingParameters(tableSampleSpec.isBernoulli(), tableSampleSpec.getSamplePercentage(), tableSampleSpec.isRepeatable(), tableSampleSpec.getRepeatableSeed());
bb.setRoot(new Sample(cluster, bb.root, params), false);
} else {
throw new AssertionError("unknown TABLESAMPLE type: " + sampleSpec);
}
return;
case IDENTIFIER:
convertIdentifier(bb, (SqlIdentifier) from, null);
return;
case EXTEND:
call = (SqlCall) from;
SqlIdentifier id = (SqlIdentifier) call.getOperandList().get(0);
SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1);
convertIdentifier(bb, id, extendedColumns);
return;
case JOIN:
final SqlJoin join = (SqlJoin) from;
final SqlValidatorScope scope = validator.getJoinScope(from);
final Blackboard fromBlackboard = createBlackboard(scope, null, false);
SqlNode left = join.getLeft();
SqlNode right = join.getRight();
final boolean isNatural = join.isNatural();
final JoinType joinType = join.getJoinType();
final SqlValidatorScope leftScope = Util.first(validator.getJoinScope(left), ((DelegatingScope) bb.scope).getParent());
final Blackboard leftBlackboard = createBlackboard(leftScope, null, false);
final SqlValidatorScope rightScope = Util.first(validator.getJoinScope(right), ((DelegatingScope) bb.scope).getParent());
final Blackboard rightBlackboard = createBlackboard(rightScope, null, false);
convertFrom(leftBlackboard, left);
RelNode leftRel = leftBlackboard.root;
convertFrom(rightBlackboard, right);
RelNode rightRel = rightBlackboard.root;
JoinRelType convertedJoinType = convertJoinType(joinType);
RexNode conditionExp;
final SqlValidatorNamespace leftNamespace = validator.getNamespace(left);
final SqlValidatorNamespace rightNamespace = validator.getNamespace(right);
if (isNatural) {
final RelDataType leftRowType = leftNamespace.getRowType();
final RelDataType rightRowType = rightNamespace.getRowType();
final List<String> columnList = SqlValidatorUtil.deriveNaturalJoinColumnList(leftRowType, rightRowType);
conditionExp = convertUsing(leftNamespace, rightNamespace, columnList);
} else {
conditionExp = convertJoinCondition(fromBlackboard, leftNamespace, rightNamespace, join.getCondition(), join.getConditionType(), leftRel, rightRel);
}
final RelNode joinRel = createJoin(fromBlackboard, leftRel, rightRel, conditionExp, convertedJoinType);
bb.setRoot(joinRel, false);
return;
case SELECT:
case INTERSECT:
case EXCEPT:
case UNION:
final RelNode rel = convertQueryRecursive(from, false, null).project();
bb.setRoot(rel, true);
return;
case VALUES:
convertValuesImpl(bb, (SqlCall) from, null);
return;
case UNNEST:
call = (SqlCall) from;
final List<SqlNode> nodes = call.getOperandList();
final SqlUnnestOperator operator = (SqlUnnestOperator) call.getOperator();
for (SqlNode node : nodes) {
replaceSubQueries(bb, node, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
}
final List<RexNode> exprs = new ArrayList<>();
final List<String> fieldNames = new ArrayList<>();
for (Ord<SqlNode> node : Ord.zip(nodes)) {
exprs.add(bb.convertExpression(node.e));
fieldNames.add(validator.deriveAlias(node.e, node.i));
}
RelNode child = (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster);
relBuilder.push(child).projectNamed(exprs, fieldNames, false);
Uncollect uncollect = new Uncollect(cluster, cluster.traitSetOf(Convention.NONE), relBuilder.build(), operator.withOrdinality);
bb.setRoot(uncollect, true);
return;
case COLLECTION_TABLE:
call = (SqlCall) from;
// Dig out real call; TABLE() wrapper is just syntactic.
assert call.getOperandList().size() == 1;
final SqlCall call2 = call.operand(0);
convertCollectionTable(bb, call2);
return;
default:
throw new AssertionError("not a join operator " + from);
}
}
use of org.apache.calcite.sql.JoinType in project calcite by apache.
the class SqlValidatorImpl method rewriteMerge.
private void rewriteMerge(SqlMerge call) {
SqlNodeList selectList;
SqlUpdate updateStmt = call.getUpdateCall();
if (updateStmt != null) {
// if we have an update statement, just clone the select list
// from the update statement's source since it's the same as
// what we want for the select list of the merge source -- '*'
// followed by the update set expressions
selectList = SqlNode.clone(updateStmt.getSourceSelect().getSelectList());
} else {
// otherwise, just use select *
selectList = new SqlNodeList(SqlParserPos.ZERO);
selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
}
SqlNode targetTable = call.getTargetTable();
if (call.getAlias() != null) {
targetTable = SqlValidatorUtil.addAlias(targetTable, call.getAlias().getSimple());
}
// Provided there is an insert substatement, the source select for
// the merge is a left outer join between the source in the USING
// clause and the target table; otherwise, the join is just an
// inner join. Need to clone the source table reference in order
// for validation to work
SqlNode sourceTableRef = call.getSourceTableRef();
SqlInsert insertCall = call.getInsertCall();
JoinType joinType = (insertCall == null) ? JoinType.INNER : JoinType.LEFT;
final SqlNode leftJoinTerm = SqlNode.clone(sourceTableRef);
SqlNode outerJoin = new SqlJoin(SqlParserPos.ZERO, leftJoinTerm, SqlLiteral.createBoolean(false, SqlParserPos.ZERO), joinType.symbol(SqlParserPos.ZERO), targetTable, JoinConditionType.ON.symbol(SqlParserPos.ZERO), call.getCondition());
SqlSelect select = new SqlSelect(SqlParserPos.ZERO, null, selectList, outerJoin, null, null, null, null, null, null, null);
call.setSourceSelect(select);
// that via the from clause on the select
if (insertCall != null) {
SqlCall valuesCall = (SqlCall) insertCall.getSource();
SqlCall rowCall = valuesCall.operand(0);
selectList = new SqlNodeList(rowCall.getOperandList(), SqlParserPos.ZERO);
final SqlNode insertSource = SqlNode.clone(sourceTableRef);
select = new SqlSelect(SqlParserPos.ZERO, null, selectList, insertSource, null, null, null, null, null, null, null);
insertCall.setSource(select);
}
}
Aggregations