in exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/UnsupportedOperatorsVisitor.java [95:359]
public SqlNode visit(SqlCall sqlCall) {
// Inspect the window functions
if (sqlCall instanceof SqlSelect) {
SqlSelect sqlSelect = (SqlSelect) sqlCall;
checkGrouping((sqlSelect));
checkRollupCubeGrpSets(sqlSelect);
for (SqlNode nodeInSelectList : sqlSelect.getSelectList()) {
// If the window function is used with an alias,
// enter the first operand of AS operator
if (nodeInSelectList.getKind() == SqlKind.AS
&& (((SqlCall) nodeInSelectList).getOperandList().get(0).getKind() == SqlKind.OVER)) {
nodeInSelectList = ((SqlCall) nodeInSelectList).getOperandList().get(0);
}
if (nodeInSelectList.getKind() == SqlKind.OVER) {
// Throw exceptions if window functions are disabled
if (!context.getOptions().getOption(ExecConstants.ENABLE_WINDOW_FUNCTIONS).bool_val) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Window functions are disabled\n" +
"See Apache Drill JIRA: DRILL-2559");
throw new UnsupportedOperationException();
}
// DRILL-3182, DRILL-3195
SqlCall over = (SqlCall) nodeInSelectList;
if (over.getOperandList().get(0) instanceof SqlCall) {
SqlCall function = (SqlCall) over.getOperandList().get(0);
// DRILL-3182
// Window function with DISTINCT qualifier is temporarily disabled
if (function.getFunctionQuantifier() != null
&& function.getFunctionQuantifier().getValue() == SqlSelectKeyword.DISTINCT) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"DISTINCT for window aggregate functions is not currently supported\n" +
"See Apache Drill JIRA: DRILL-3182");
throw new UnsupportedOperationException();
}
// DRILL-3596: we only allow (<column-name>) or (<column-name>, 1)
final String functionName = function.getOperator().getName().toUpperCase();
if ("LEAD".equals(functionName) || "LAG".equals(functionName)) {
boolean supported = true;
if (function.operandCount() > 2) {
// we don't support more than 2 arguments
supported = false;
} else if (function.operandCount() == 2) {
SqlNode operand = function.operand(1);
if (operand instanceof SqlNumericLiteral) {
SqlNumericLiteral offsetLiteral = (SqlNumericLiteral) operand;
try {
if (offsetLiteral.intValue(true) != 1) {
// we don't support offset != 1
supported = false;
}
} catch (AssertionError e) {
// we only support offset as an integer
supported = false;
}
} else {
// we only support offset as a numeric literal
supported = false;
}
}
if (!supported) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Function " + functionName + " only supports (<value expression>) or (<value expression>, 1)\n" +
"See Apache DRILL JIRA: DRILL-3596");
throw new UnsupportedOperationException();
}
}
}
}
}
}
// DRILL-3188
// Disable frame which is other than the default
// (i.e., BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
if (sqlCall instanceof SqlWindow) {
SqlWindow window = (SqlWindow) sqlCall;
SqlNode lowerBound = window.getLowerBound();
SqlNode upperBound = window.getUpperBound();
// If no frame is specified
// it is a default frame
boolean isSupported = (lowerBound == null && upperBound == null);
// When OVER clause contain an ORDER BY clause the following frames are supported:
// RANGE UNBOUNDED PRECEDING
// RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
// RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
if (window.getOrderList().size() != 0
&& !window.isRows()
&& SqlWindow.isUnboundedPreceding(lowerBound)
&& (upperBound == null || SqlWindow.isCurrentRow(upperBound) || SqlWindow.isUnboundedFollowing(upperBound))) {
isSupported = true;
}
// ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
// is supported with and without the ORDER BY clause
if (window.isRows()
&& SqlWindow.isUnboundedPreceding(lowerBound)
&& (upperBound == null || SqlWindow.isCurrentRow(upperBound))) {
isSupported = true;
}
// RANGE BETWEEN CURRENT ROW AND CURRENT ROW
// is supported with and without an ORDER BY clause
if (!window.isRows() &&
SqlWindow.isCurrentRow(lowerBound) &&
SqlWindow.isCurrentRow(upperBound)) {
isSupported = true;
}
// When OVER clause doesn't contain an ORDER BY clause, the following are equivalent to the default frame:
// RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
// ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
if (window.getOrderList().size() == 0
&& SqlWindow.isUnboundedPreceding(lowerBound)
&& SqlWindow.isUnboundedFollowing(upperBound)) {
isSupported = true;
}
if (!isSupported) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"This type of window frame is currently not supported \n" +
"See Apache Drill JIRA: DRILL-3188");
throw new UnsupportedOperationException();
}
// DRILL-3189: Disable DISALLOW PARTIAL
if (!window.isAllowPartial()) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Disallowing partial windows is currently not supported \n" +
"See Apache Drill JIRA: DRILL-3189");
throw new UnsupportedOperationException();
}
}
// Disable unsupported JOINs
if (sqlCall.getKind() == SqlKind.JOIN) {
SqlJoin join = (SqlJoin) sqlCall;
// Block Natural Join
if (join.isNatural()) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.RELATIONAL,
"NATURAL JOIN is not supported\n" +
"See Apache Drill JIRA: DRILL-1986");
throw new UnsupportedOperationException();
}
}
//Disable UNNEST if the configuration disable it
if (sqlCall.getKind() == SqlKind.UNNEST) {
if (!context.getPlannerSettings().isUnnestLateralEnabled()) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.RELATIONAL,
"Unnest is not enabled per configuration");
throw new UnsupportedOperationException();
}
}
// Disable Function
for (String strOperator : disabledOperators) {
if (sqlCall.getOperator().isName(strOperator, true)) { // true is passed to preserve previous behavior
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
sqlCall.getOperator().getName() + " is not supported\n" +
"See Apache Drill JIRA: DRILL-2115");
throw new UnsupportedOperationException();
}
}
// Disable complex functions incorrect placement
if (sqlCall instanceof SqlSelect) {
SqlSelect sqlSelect = (SqlSelect) sqlCall;
for (SqlNode nodeInSelectList : sqlSelect.getSelectList()) {
if (checkDirExplorers(nodeInSelectList)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Directory explorers " + dirExplorers + " functions are not supported in Select List\n" +
"See Apache Drill JIRA: DRILL-3944");
throw new UnsupportedOperationException();
}
}
if (sqlSelect.hasWhere()) {
if (checkDirExplorers(sqlSelect.getWhere()) && !context.getPlannerSettings().isConstantFoldingEnabled()) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Directory explorers " + dirExplorers + " functions can not be used " +
"when " + PlannerSettings.CONSTANT_FOLDING.getOptionName() + " option is set to false\n" +
"See Apache Drill JIRA: DRILL-3944");
throw new UnsupportedOperationException();
}
}
if (sqlSelect.hasOrderBy()) {
for (SqlNode sqlNode : sqlSelect.getOrderList()) {
if (containsFlatten(sqlNode)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Flatten function is not supported in Order By\n" +
"See Apache Drill JIRA: DRILL-2181");
throw new UnsupportedOperationException();
} else if (checkDirExplorers(sqlNode)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Directory explorers " + dirExplorers + " functions are not supported in Order By\n" +
"See Apache Drill JIRA: DRILL-3944");
throw new UnsupportedOperationException();
}
}
}
if (sqlSelect.getGroup() != null) {
for (SqlNode sqlNode : sqlSelect.getGroup()) {
if (containsFlatten(sqlNode)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Flatten function is not supported in Group By\n" +
"See Apache Drill JIRA: DRILL-2181");
throw new UnsupportedOperationException();
} else if (checkDirExplorers(sqlNode)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Directory explorers " + dirExplorers + " functions are not supported in Group By\n" +
"See Apache Drill JIRA: DRILL-3944");
throw new UnsupportedOperationException();
}
}
}
if (sqlSelect.isDistinct()) {
for (SqlNode column : sqlSelect.getSelectList()) {
if (column.getKind() == SqlKind.AS) {
if (containsFlatten(((SqlCall) column).getOperandList().get(0))) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Flatten function is not supported in Distinct\n" +
"See Apache Drill JIRA: DRILL-2181");
throw new UnsupportedOperationException();
}
} else {
if (containsFlatten(column)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Flatten function is not supported in Distinct\n" +
"See Apache Drill JIRA: DRILL-2181");
throw new UnsupportedOperationException();
}
}
}
}
}
if (DrillCalciteWrapperUtility.extractSqlOperatorFromWrapper(sqlCall.getOperator()) instanceof SqlCountAggFunction) {
for (SqlNode sqlNode : sqlCall.getOperandList()) {
if (containsFlatten(sqlNode)) {
unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
"Flatten function in aggregate functions is not supported\n" +
"See Apache Drill JIRA: DRILL-2181");
throw new UnsupportedOperationException();
}
}
}
return sqlCall.getOperator().acceptCall(this, sqlCall);
}