use of org.apache.calcite.sql.SqlCall 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.SqlCall in project calcite by apache.
the class SqlToRelConverter method convertValuesImpl.
/**
* Converts a values clause (as in "INSERT INTO T(x,y) VALUES (1,2)") into a
* relational expression.
*
* @param bb Blackboard
* @param values Call to SQL VALUES operator
* @param targetRowType Target row type
*/
private void convertValuesImpl(Blackboard bb, SqlCall values, RelDataType targetRowType) {
// Attempt direct conversion to LogicalValues; if that fails, deal with
// fancy stuff like sub-queries below.
RelNode valuesRel = convertRowValues(bb, values, values.getOperandList(), true, targetRowType);
if (valuesRel != null) {
bb.setRoot(valuesRel, true);
return;
}
final List<RelNode> unionRels = new ArrayList<>();
for (SqlNode rowConstructor1 : values.getOperandList()) {
SqlCall rowConstructor = (SqlCall) rowConstructor1;
Blackboard tmpBb = createBlackboard(bb.scope, null, false);
replaceSubQueries(tmpBb, rowConstructor, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
final List<Pair<RexNode, String>> exps = new ArrayList<>();
for (Ord<SqlNode> operand : Ord.zip(rowConstructor.getOperandList())) {
exps.add(Pair.of(tmpBb.convertExpression(operand.e), validator.deriveAlias(operand.e, operand.i)));
}
RelNode in = (null == tmpBb.root) ? LogicalValues.createOneRow(cluster) : tmpBb.root;
unionRels.add(relBuilder.push(in).project(Pair.left(exps), Pair.right(exps)).build());
}
if (unionRels.size() == 0) {
throw new AssertionError("empty values clause");
} else if (unionRels.size() == 1) {
bb.setRoot(unionRels.get(0), true);
} else {
bb.setRoot(LogicalUnion.create(unionRels, true), true);
}
// REVIEW jvs 22-Jan-2004: should I add
// mapScopeToLux.put(validator.getScope(values),bb.root);
// ?
}
use of org.apache.calcite.sql.SqlCall in project calcite by apache.
the class StandardConvertletTable method convertOverlapsOperand.
private Pair<RexNode, RexNode> convertOverlapsOperand(SqlRexContext cx, SqlParserPos pos, SqlNode operand) {
final SqlNode a0;
final SqlNode a1;
switch(operand.getKind()) {
case ROW:
a0 = ((SqlCall) operand).operand(0);
final SqlNode a10 = ((SqlCall) operand).operand(1);
final RelDataType t1 = cx.getValidator().getValidatedNodeType(a10);
if (SqlTypeUtil.isInterval(t1)) {
// make t1 = t0 + t1 when t1 is an interval.
a1 = plus(pos, a0, a10);
} else {
a1 = a10;
}
break;
default:
a0 = operand;
a1 = operand;
}
final RexNode r0 = cx.convertExpression(a0);
final RexNode r1 = cx.convertExpression(a1);
return Pair.of(r0, r1);
}
use of org.apache.calcite.sql.SqlCall 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);
}
}
use of org.apache.calcite.sql.SqlCall in project calcite by apache.
the class SqlValidatorImpl method validateNoAggs.
/**
* Throws an error if there is an aggregate or windowed aggregate in the
* given clause.
*
* @param aggFinder Finder for the particular kind(s) of aggregate function
* @param node Parse tree
* @param clause Name of clause: "WHERE", "GROUP BY", "ON"
*/
private void validateNoAggs(AggFinder aggFinder, SqlNode node, String clause) {
final SqlCall agg = aggFinder.findAgg(node);
if (agg == null) {
return;
}
final SqlOperator op = agg.getOperator();
if (op == SqlStdOperatorTable.OVER) {
throw newValidationError(agg, RESOURCE.windowedAggregateIllegalInClause(clause));
} else if (op.isGroup() || op.isGroupAuxiliary()) {
throw newValidationError(agg, RESOURCE.groupFunctionMustAppearInGroupByClause(op.getName()));
} else {
throw newValidationError(agg, RESOURCE.aggregateIllegalInClause(clause));
}
}
Aggregations