use of org.apache.calcite.sql.SqlSelect in project flink by apache.
the class SqlValidatorImpl method validateSelectList.
protected RelDataType validateSelectList(final SqlNodeList selectItems, SqlSelect select, RelDataType targetRowType) {
// First pass, ensure that aliases are unique. "*" and "TABLE.*" items
// are ignored.
// Validate SELECT list. Expand terms of the form "*" or "TABLE.*".
final SqlValidatorScope selectScope = getSelectScope(select);
final List<SqlNode> expandedSelectItems = new ArrayList<>();
final Set<String> aliases = new HashSet<>();
final List<Map.Entry<String, RelDataType>> fieldList = new ArrayList<>();
for (SqlNode selectItem : selectItems) {
if (selectItem instanceof SqlSelect) {
handleScalarSubQuery(select, (SqlSelect) selectItem, expandedSelectItems, aliases, fieldList);
} else {
// Use the field list size to record the field index
// because the select item may be a STAR(*), which could have been expanded.
final int fieldIdx = fieldList.size();
final RelDataType fieldType = targetRowType.isStruct() && targetRowType.getFieldCount() > fieldIdx ? targetRowType.getFieldList().get(fieldIdx).getType() : unknownType;
expandSelectItem(selectItem, select, fieldType, expandedSelectItems, aliases, fieldList, false);
}
}
// Create the new select list with expanded items. Pass through
// the original parser position so that any overall failures can
// still reference the original input text.
SqlNodeList newSelectList = new SqlNodeList(expandedSelectItems, selectItems.getParserPosition());
if (config.identifierExpansion()) {
select.setSelectList(newSelectList);
}
getRawSelectScope(select).setExpandedSelectList(expandedSelectItems);
// TODO: when SELECT appears as a value sub-query, should be using
// something other than unknownType for targetRowType
inferUnknownTypes(targetRowType, selectScope, newSelectList);
for (SqlNode selectItem : expandedSelectItems) {
validateNoAggs(groupFinder, selectItem, "SELECT");
validateExpr(selectItem, selectScope);
}
return typeFactory.createStructType(fieldList);
}
use of org.apache.calcite.sql.SqlSelect in project flink by apache.
the class SqlValidatorImpl method registerQuery.
/**
* Registers a query in a parent scope.
*
* @param parentScope Parent scope which this scope turns to in order to resolve objects
* @param usingScope Scope whose child list this scope should add itself to
* @param node Query node
* @param alias Name of this query within its parent. Must be specified if usingScope != null
* @param checkUpdate if true, validate that the update feature is supported if validating the
* update statement
*/
private void registerQuery(SqlValidatorScope parentScope, SqlValidatorScope usingScope, SqlNode node, SqlNode enclosingNode, String alias, boolean forceNullable, boolean checkUpdate) {
Objects.requireNonNull(node);
Objects.requireNonNull(enclosingNode);
Preconditions.checkArgument(usingScope == null || alias != null);
SqlCall call;
List<SqlNode> operands;
switch(node.getKind()) {
case SELECT:
final SqlSelect select = (SqlSelect) node;
final SelectNamespace selectNs = createSelectNamespace(select, enclosingNode);
registerNamespace(usingScope, alias, selectNs, forceNullable);
final SqlValidatorScope windowParentScope = (usingScope != null) ? usingScope : parentScope;
SelectScope selectScope = new SelectScope(parentScope, windowParentScope, select);
scopes.put(select, selectScope);
// Start by registering the WHERE clause
clauseScopes.put(IdPair.of(select, Clause.WHERE), selectScope);
registerOperandSubQueries(selectScope, select, SqlSelect.WHERE_OPERAND);
// Register FROM with the inherited scope 'parentScope', not
// 'selectScope', otherwise tables in the FROM clause would be
// able to see each other.
final SqlNode from = select.getFrom();
if (from != null) {
final SqlNode newFrom = registerFrom(parentScope, selectScope, true, from, from, null, null, false, false);
if (newFrom != from) {
select.setFrom(newFrom);
}
}
// If this is an aggregating query, the SELECT list and HAVING
// clause use a different scope, where you can only reference
// columns which are in the GROUP BY clause.
SqlValidatorScope aggScope = selectScope;
if (isAggregate(select)) {
aggScope = new AggregatingSelectScope(selectScope, select, false);
clauseScopes.put(IdPair.of(select, Clause.SELECT), aggScope);
} else {
clauseScopes.put(IdPair.of(select, Clause.SELECT), selectScope);
}
if (select.getGroup() != null) {
GroupByScope groupByScope = new GroupByScope(selectScope, select.getGroup(), select);
clauseScopes.put(IdPair.of(select, Clause.GROUP_BY), groupByScope);
registerSubQueries(groupByScope, select.getGroup());
}
registerOperandSubQueries(aggScope, select, SqlSelect.HAVING_OPERAND);
registerSubQueries(aggScope, select.getSelectList());
final SqlNodeList orderList = select.getOrderList();
if (orderList != null) {
// available to the ORDER BY clause.
if (select.isDistinct()) {
aggScope = new AggregatingSelectScope(selectScope, select, true);
}
OrderByScope orderScope = new OrderByScope(aggScope, orderList, select);
clauseScopes.put(IdPair.of(select, Clause.ORDER), orderScope);
registerSubQueries(orderScope, orderList);
if (!isAggregate(select)) {
// Since this is not an aggregating query,
// there cannot be any aggregates in the ORDER BY clause.
SqlNode agg = aggFinder.findAgg(orderList);
if (agg != null) {
throw newValidationError(agg, RESOURCE.aggregateIllegalInOrderBy());
}
}
}
break;
case INTERSECT:
validateFeature(RESOURCE.sQLFeature_F302(), node.getParserPosition());
registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
break;
case EXCEPT:
validateFeature(RESOURCE.sQLFeature_E071_03(), node.getParserPosition());
registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
break;
case UNION:
registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
break;
case WITH:
registerWith(parentScope, usingScope, (SqlWith) node, enclosingNode, alias, forceNullable, checkUpdate);
break;
case VALUES:
call = (SqlCall) node;
scopes.put(call, parentScope);
final TableConstructorNamespace tableConstructorNamespace = new TableConstructorNamespace(this, call, parentScope, enclosingNode);
registerNamespace(usingScope, alias, tableConstructorNamespace, forceNullable);
operands = call.getOperandList();
for (int i = 0; i < operands.size(); ++i) {
assert operands.get(i).getKind() == SqlKind.ROW;
// FIXME jvs 9-Feb-2005: Correlation should
// be illegal in these sub-queries. Same goes for
// any non-lateral SELECT in the FROM list.
registerOperandSubQueries(parentScope, call, i);
}
break;
case INSERT:
SqlInsert insertCall = (SqlInsert) node;
InsertNamespace insertNs = new InsertNamespace(this, insertCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, insertNs, forceNullable);
registerQuery(parentScope, usingScope, insertCall.getSource(), enclosingNode, null, false);
break;
case DELETE:
SqlDelete deleteCall = (SqlDelete) node;
DeleteNamespace deleteNs = new DeleteNamespace(this, deleteCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, deleteNs, forceNullable);
registerQuery(parentScope, usingScope, deleteCall.getSourceSelect(), enclosingNode, null, false);
break;
case UPDATE:
if (checkUpdate) {
validateFeature(RESOURCE.sQLFeature_E101_03(), node.getParserPosition());
}
SqlUpdate updateCall = (SqlUpdate) node;
UpdateNamespace updateNs = new UpdateNamespace(this, updateCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, updateNs, forceNullable);
registerQuery(parentScope, usingScope, updateCall.getSourceSelect(), enclosingNode, null, false);
break;
case MERGE:
validateFeature(RESOURCE.sQLFeature_F312(), node.getParserPosition());
SqlMerge mergeCall = (SqlMerge) node;
MergeNamespace mergeNs = new MergeNamespace(this, mergeCall, enclosingNode, parentScope);
registerNamespace(usingScope, null, mergeNs, forceNullable);
registerQuery(parentScope, usingScope, mergeCall.getSourceSelect(), enclosingNode, null, false);
// validation check
if (mergeCall.getUpdateCall() != null) {
registerQuery(clauseScopes.get(IdPair.of(mergeCall.getSourceSelect(), Clause.WHERE)), null, mergeCall.getUpdateCall(), enclosingNode, null, false, false);
}
if (mergeCall.getInsertCall() != null) {
registerQuery(parentScope, null, mergeCall.getInsertCall(), enclosingNode, null, false);
}
break;
case UNNEST:
call = (SqlCall) node;
final UnnestNamespace unnestNs = new UnnestNamespace(this, call, parentScope, enclosingNode);
registerNamespace(usingScope, alias, unnestNs, forceNullable);
registerOperandSubQueries(parentScope, call, 0);
scopes.put(node, parentScope);
break;
case OTHER_FUNCTION:
call = (SqlCall) node;
ProcedureNamespace procNs = new ProcedureNamespace(this, parentScope, call, enclosingNode);
registerNamespace(usingScope, alias, procNs, forceNullable);
registerSubQueries(parentScope, call);
break;
case MULTISET_QUERY_CONSTRUCTOR:
case MULTISET_VALUE_CONSTRUCTOR:
validateFeature(RESOURCE.sQLFeature_S271(), node.getParserPosition());
call = (SqlCall) node;
CollectScope cs = new CollectScope(parentScope, usingScope, call);
final CollectNamespace tableConstructorNs = new CollectNamespace(call, cs, enclosingNode);
final String alias2 = deriveAlias(node, nextGeneratedId++);
registerNamespace(usingScope, alias2, tableConstructorNs, forceNullable);
operands = call.getOperandList();
for (int i = 0; i < operands.size(); i++) {
registerOperandSubQueries(parentScope, call, i);
}
break;
default:
throw Util.unexpected(node.getKind());
}
}
use of org.apache.calcite.sql.SqlSelect in project flink by apache.
the class SqlValidatorImpl method declareCursor.
// implement SqlValidator
public void declareCursor(SqlSelect select, SqlValidatorScope parentScope) {
cursorSet.add(select);
// add the cursor to a map that maps the cursor to its select based on
// the position of the cursor relative to other cursors in that call
FunctionParamInfo funcParamInfo = functionCallStack.peek();
Map<Integer, SqlSelect> cursorMap = funcParamInfo.cursorPosToSelectMap;
int numCursors = cursorMap.size();
cursorMap.put(numCursors, select);
// create a namespace associated with the result of the select
// that is the argument to the cursor constructor; register it
// with a scope corresponding to the cursor
SelectScope cursorScope = new SelectScope(parentScope, null, select);
clauseScopes.put(IdPair.of(select, Clause.CURSOR), cursorScope);
final SelectNamespace selectNs = createSelectNamespace(select, select);
String alias = deriveAlias(select, nextGeneratedId++);
registerNamespace(cursorScope, alias, selectNs, false);
}
use of org.apache.calcite.sql.SqlSelect in project flink by apache.
the class SqlValidatorImpl method rewriteUpdateToMerge.
private SqlNode rewriteUpdateToMerge(SqlUpdate updateCall, SqlNode selfJoinSrcExpr) {
// Make sure target has an alias.
if (updateCall.getAlias() == null) {
updateCall.setAlias(new SqlIdentifier(UPDATE_TGT_ALIAS, SqlParserPos.ZERO));
}
SqlNode selfJoinTgtExpr = getSelfJoinExprForUpdate(updateCall.getTargetTable(), updateCall.getAlias().getSimple());
assert selfJoinTgtExpr != null;
// Create join condition between source and target exprs,
// creating a conjunction with the user-level WHERE
// clause if one was supplied
SqlNode condition = updateCall.getCondition();
SqlNode selfJoinCond = SqlStdOperatorTable.EQUALS.createCall(SqlParserPos.ZERO, selfJoinSrcExpr, selfJoinTgtExpr);
if (condition == null) {
condition = selfJoinCond;
} else {
condition = SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, selfJoinCond, condition);
}
SqlNode target = updateCall.getTargetTable().clone(SqlParserPos.ZERO);
// For the source, we need to anonymize the fields, so
// that for a statement like UPDATE T SET I = I + 1,
// there's no ambiguity for the "I" in "I + 1";
// this is OK because the source and target have
// identical values due to the self-join.
// Note that we anonymize the source rather than the
// target because downstream, the optimizer rules
// don't want to see any projection on top of the target.
IdentifierNamespace ns = new IdentifierNamespace(this, target, null, null);
RelDataType rowType = ns.getRowType();
SqlNode source = updateCall.getTargetTable().clone(SqlParserPos.ZERO);
final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
int i = 1;
for (RelDataTypeField field : rowType.getFieldList()) {
SqlIdentifier col = new SqlIdentifier(field.getName(), SqlParserPos.ZERO);
selectList.add(SqlValidatorUtil.addAlias(col, UPDATE_ANON_PREFIX + i));
++i;
}
source = new SqlSelect(SqlParserPos.ZERO, null, selectList, source, null, null, null, null, null, null, null, null);
source = SqlValidatorUtil.addAlias(source, UPDATE_SRC_ALIAS);
SqlMerge mergeCall = new SqlMerge(updateCall.getParserPosition(), target, condition, source, updateCall, null, null, updateCall.getAlias());
rewriteMerge(mergeCall);
return mergeCall;
}
use of org.apache.calcite.sql.SqlSelect in project calcite by apache.
the class MysqlSqlDialect method rewriteSingleValueExpr.
@Override
public SqlNode rewriteSingleValueExpr(SqlNode aggCall) {
final SqlNode operand = ((SqlBasicCall) aggCall).operand(0);
final SqlLiteral nullLiteral = SqlLiteral.createNull(SqlParserPos.ZERO);
final SqlNode unionOperand = new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY, SqlNodeList.of(nullLiteral), null, null, null, null, SqlNodeList.EMPTY, null, null, null);
// For MySQL, generate
// CASE COUNT(*)
// WHEN 0 THEN NULL
// WHEN 1 THEN <result>
// ELSE (SELECT NULL UNION ALL SELECT NULL)
// END
final SqlNode caseExpr = new SqlCase(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT.createCall(SqlParserPos.ZERO, operand), SqlNodeList.of(SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO), SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO)), SqlNodeList.of(nullLiteral, operand), SqlStdOperatorTable.SCALAR_QUERY.createCall(SqlParserPos.ZERO, SqlStdOperatorTable.UNION_ALL.createCall(SqlParserPos.ZERO, unionOperand, unionOperand)));
LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr);
return caseExpr;
}
Aggregations