Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/src/main/codegen/templates/Parser.jj
Original file line number Diff line number Diff line change
Expand Up @@ -1928,13 +1928,13 @@ void ColumnType(List<SqlNode> list) :
SqlNode TableFunctionCall(SqlParserPos pos) :
{
SqlNode call;
SqlFunctionCategory funcType = SqlFunctionCategory.USER_DEFINED_FUNCTION;
SqlFunctionCategory funcType = SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION;
}
{
[
<SPECIFIC>
{
funcType = SqlFunctionCategory.USER_DEFINED_SPECIFIC_FUNCTION;
funcType = SqlFunctionCategory.USER_DEFINED_TABLE_SPECIFIC_FUNCTION;
}
]
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
import java.util.Map;
import java.util.NavigableSet;

import javax.annotation.Nullable;

/**
* Implementation of {@link org.apache.calcite.prepare.Prepare.CatalogReader}
* and also {@link org.apache.calcite.sql.SqlOperatorTable} based on tables and
Expand Down Expand Up @@ -226,13 +228,30 @@ public RelDataType createTypeFromProjection(final RelDataType type,
}

public void lookupOperatorOverloads(final SqlIdentifier opName,
SqlFunctionCategory category,
final SqlFunctionCategory category,
SqlSyntax syntax,
List<SqlOperator> operatorList) {
if (syntax != SqlSyntax.FUNCTION) {
return;
}
final Collection<Function> functions = getFunctionsFrom(opName.names);
final Collection<Function> functionsOld = getFunctionsFrom(opName.names);

final Collection<Function> functions = Collections2.filter(functionsOld,
new Predicate<Function>() {
@Override public boolean apply(@Nullable Function function) {
if (function instanceof TableMacro || function instanceof TableFunction) {
if (category == null || !category.isTableFunction()) {
return false;
}
} else {
if (category != null && category.isTableFunction()) {
return false;
}
}
return true;
}
}
);
if (functions.isEmpty()) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,7 @@ private Object toJson(RexNode node) {
map.put("type", toJson(node.getType()));
}
if (call.getOperator() instanceof SqlFunction) {
switch (((SqlFunction) call.getOperator()).getFunctionType()) {
case USER_DEFINED_CONSTRUCTOR:
case USER_DEFINED_FUNCTION:
case USER_DEFINED_PROCEDURE:
case USER_DEFINED_SPECIFIC_FUNCTION:
if (((SqlFunction) call.getOperator()).getFunctionType().isUserDefined()) {
map.put("class", call.getOperator().getClass().getName());
}
}
Expand Down
73 changes: 62 additions & 11 deletions core/src/main/java/org/apache/calcite/sql/SqlFunctionCategory.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,76 @@

import org.apache.calcite.util.Util;

import static org.apache.calcite.sql.SqlFunctionCategoryProperty.FUNCTION;
import static org.apache.calcite.sql.SqlFunctionCategoryProperty.SPECIFIC;
import static org.apache.calcite.sql.SqlFunctionCategoryProperty.TABLE_FUNCTION;
import static org.apache.calcite.sql.SqlFunctionCategoryProperty.USER_DEFINED;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
* Enumeration of the categories of
* SQL-invoked routines.
*/
public enum SqlFunctionCategory {
STRING("STRING", "String function"),
NUMERIC("NUMERIC", "Numeric function"),
TIMEDATE("TIMEDATE", "Time and date function"),
SYSTEM("SYSTEM", "System function"),
USER_DEFINED_FUNCTION("UDF", "User-defined function"),
USER_DEFINED_PROCEDURE("UDP", "User-defined procedure"),
USER_DEFINED_CONSTRUCTOR("UDC", "User-defined constructor"),
USER_DEFINED_SPECIFIC_FUNCTION("UDF_SPECIFIC",
"User-defined function with SPECIFIC name");

SqlFunctionCategory(String abbrev, String description) {
STRING("STRING", "String function", FUNCTION),
NUMERIC("NUMERIC", "Numeric function", FUNCTION),
TIMEDATE("TIMEDATE", "Time and date function", FUNCTION),
SYSTEM("SYSTEM", "System function", FUNCTION),
USER_DEFINED_FUNCTION("UDF", "User-defined function", USER_DEFINED, FUNCTION),
USER_DEFINED_PROCEDURE("UDP", "User-defined procedure", USER_DEFINED),
USER_DEFINED_CONSTRUCTOR("UDC", "User-defined constructor", USER_DEFINED),
USER_DEFINED_SPECIFIC_FUNCTION(
"UDF_SPECIFIC", "User-defined function with SPECIFIC name", USER_DEFINED, SPECIFIC, FUNCTION),
USER_DEFINED_TABLE_FUNCTION(
"TABLE_UDF", "User-defined table function", USER_DEFINED, TABLE_FUNCTION),
USER_DEFINED_TABLE_SPECIFIC_FUNCTION("TABLE_UDF_SPECIFIC",
"User-defined table function with SPECIFIC name", USER_DEFINED, TABLE_FUNCTION, SPECIFIC);

private final boolean userDefined;
private final boolean tableFunction;
private final boolean specific;
private final boolean function;

SqlFunctionCategory(String abbrev, String description, SqlFunctionCategoryProperty... types) {
Util.discard(abbrev);
Util.discard(description);
Set<SqlFunctionCategoryProperty> typeSet = new HashSet<>(Arrays.asList(types));
this.userDefined = typeSet.contains(USER_DEFINED);
this.tableFunction = typeSet.contains(TABLE_FUNCTION);
this.specific = typeSet.contains(SPECIFIC);
this.function = typeSet.contains(FUNCTION);
}

public boolean isUserDefined() {
return userDefined;
}

public boolean isTableFunction() {
return tableFunction;
}

public boolean isFunction() {
return function;
}

public boolean isSpecific() {
return specific;
}

public boolean isUserDefinedNotSpecificFunction() {
return userDefined && (function || tableFunction) && !specific;
}

}

/**
* Properties of a SqlFunctionCategory
*/
enum SqlFunctionCategoryProperty {
USER_DEFINED, TABLE_FUNCTION, SPECIFIC, FUNCTION;
}

// End SqlFunctionCategory.java
3 changes: 1 addition & 2 deletions core/src/main/java/org/apache/calcite/sql/SqlUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,7 @@ public static void unparseFunctionSyntax(
if (operator instanceof SqlFunction) {
SqlFunction function = (SqlFunction) operator;

switch (function.getFunctionType()) {
case USER_DEFINED_SPECIFIC_FUNCTION:
if (function.getFunctionType().isSpecific()) {
writer.keyword("SPECIFIC");
}
SqlIdentifier id = function.getSqlIdentifier();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ protected SqlCall createCall(
/// name when regenerating SQL).
if (funName.isSimple()) {
final List<SqlOperator> list = Lists.newArrayList();
opTab.lookupOperatorOverloads(funName, null, SqlSyntax.FUNCTION, list);
opTab.lookupOperatorOverloads(funName, funcType, SqlSyntax.FUNCTION, list);
if (list.size() == 1) {
fun = list.get(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ public void lookupOperatorOverloads(SqlIdentifier opName,
} else {
functionCategory = SqlFunctionCategory.SYSTEM;
}
if (category != functionCategory
&& category != SqlFunctionCategory.USER_DEFINED_FUNCTION) {
if (category != functionCategory && !category.isUserDefinedNotSpecificFunction()) {
continue;
}
operatorList.add(operator);
Expand Down
30 changes: 16 additions & 14 deletions core/src/main/java/org/apache/calcite/sql/validate/AggFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@

import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlFunction;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlOperatorTable;
import org.apache.calcite.sql.SqlSyntax;
import org.apache.calcite.sql.util.SqlBasicVisitor;
import org.apache.calcite.util.Util;

import com.google.common.collect.Lists;

import java.util.List;

import static org.apache.calcite.sql.SqlKind.QUERY;
import static org.apache.calcite.sql.SqlSyntax.FUNCTION;

/**
* Visitor which looks for an aggregate function inside a tree of
* {@link SqlNode} objects.
Expand Down Expand Up @@ -110,22 +111,23 @@ public Void visit(SqlCall call) {
}
}
// User-defined function may not be resolved yet.
if (operator instanceof SqlFunction
&& ((SqlFunction) operator).getFunctionType()
== SqlFunctionCategory.USER_DEFINED_FUNCTION) {
final List<SqlOperator> list = Lists.newArrayList();
opTab.lookupOperatorOverloads(((SqlFunction) operator).getSqlIdentifier(),
SqlFunctionCategory.USER_DEFINED_FUNCTION, SqlSyntax.FUNCTION, list);
for (SqlOperator sqlOperator : list) {
if (sqlOperator.isAggregator()) {
// If nested aggregates disallowed or found aggregate at invalid level
if (aggregate) {
throw new Util.FoundOne(call);
if (operator instanceof SqlFunction) {
SqlFunction sqlFunction = (SqlFunction) operator;
if (sqlFunction.getFunctionType().isUserDefinedNotSpecificFunction()) {
final List<SqlOperator> list = Lists.newArrayList();
opTab.lookupOperatorOverloads(sqlFunction.getSqlIdentifier(),
sqlFunction.getFunctionType(), FUNCTION, list);
for (SqlOperator sqlOperator : list) {
if (sqlOperator.isAggregator()) {
// If nested aggregates disallowed or found aggregate at invalid level
if (aggregate) {
throw new Util.FoundOne(call);
}
}
}
}
}
if (call.isA(SqlKind.QUERY)) {
if (call.isA(QUERY)) {
// don't traverse into queries
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,25 @@ public SqlUserDefinedFunction(SqlIdentifier opName,
SqlOperandTypeChecker operandTypeChecker,
List<RelDataType> paramTypes,
Function function) {
this(opName,
returnTypeInference,
operandTypeInference,
operandTypeChecker,
paramTypes,
function,
SqlFunctionCategory.USER_DEFINED_FUNCTION);
}

protected SqlUserDefinedFunction(SqlIdentifier opName,
SqlReturnTypeInference returnTypeInference,
SqlOperandTypeInference operandTypeInference,
SqlOperandTypeChecker operandTypeChecker,
List<RelDataType> paramTypes,
Function function,
SqlFunctionCategory category) {
super(Util.last(opName.names), opName, SqlKind.OTHER_FUNCTION,
returnTypeInference, operandTypeInference, operandTypeChecker,
paramTypes, SqlFunctionCategory.USER_DEFINED_FUNCTION);
paramTypes, category);
this.function = function;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.schema.TableFunction;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.type.SqlOperandTypeChecker;
Expand All @@ -42,7 +43,7 @@ public SqlUserDefinedTableFunction(SqlIdentifier opName,
List<RelDataType> paramTypes,
TableFunction function) {
super(opName, returnTypeInference, operandTypeInference, operandTypeChecker,
paramTypes, function);
paramTypes, function, SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public SqlUserDefinedTableMacro(SqlIdentifier opName,
super(Util.last(opName.names), opName, SqlKind.OTHER_FUNCTION,
returnTypeInference, operandTypeInference, operandTypeChecker,
Preconditions.checkNotNull(paramTypes),
SqlFunctionCategory.USER_DEFINED_FUNCTION);
SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION);
this.tableMacro = tableMacro;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -720,13 +720,12 @@ public void visit(RelNode p, int ordinal, RelNode parent) {
// for leaves, it's usually safe to assume that
// no transformation is required
rewriteGeneric(p);
} else {
throw Util.newInternal(
"no '" + visitMethodName + "' method found for class "
+ p.getClass().getName());
}
}
if (!found) {
throw Util.newInternal(
"no '" + visitMethodName + "' method found for class "
+ p.getClass().getName());
}
}
}

Expand Down
Loading