use of org.apache.calcite.sql.SqlFunction in project calcite by apache.
the class SqlFloorFunction method unparseDatetimeFunction.
/**
* Most dialects that natively support datetime floor will use this.
* In those cases the call will look like TRUNC(datetime, 'year').
*
* @param writer SqlWriter
* @param call SqlCall
* @param funName Name of the sql function to call
* @param datetimeFirst Specify the order of the datetime & timeUnit
* arguments
*/
public static void unparseDatetimeFunction(SqlWriter writer, SqlCall call, String funName, Boolean datetimeFirst) {
SqlFunction func = new SqlFunction(funName, SqlKind.OTHER_FUNCTION, ReturnTypes.ARG0_NULLABLE_VARYING, null, null, SqlFunctionCategory.STRING);
SqlCall call1;
if (datetimeFirst) {
call1 = call;
} else {
// switch order of operands
SqlNode op1 = call.operand(0);
SqlNode op2 = call.operand(1);
call1 = call.getOperator().createCall(call.getParserPosition(), op2, op1);
}
SqlUtil.unparseFunctionSyntax(func, writer, call1, false);
}
use of org.apache.calcite.sql.SqlFunction in project calcite by apache.
the class RelOptRulesTest method testMonotonicityUDF.
/**
* Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-3151">[CALCITE-3151]
* RexCall's Monotonicity is not considered in determining a Calc's
* collation</a>.
*/
@Test
void testMonotonicityUDF() {
final SqlFunction monotonicityFun = new SqlFunction("MONOFUN", SqlKind.OTHER_FUNCTION, ReturnTypes.BIGINT, null, OperandTypes.NILADIC, SqlFunctionCategory.USER_DEFINED_FUNCTION) {
@Override
public boolean isDeterministic() {
return false;
}
@Override
public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
return SqlMonotonicity.INCREASING;
}
};
// Build a tree equivalent to the SQL
// SELECT sal, MONOFUN() AS n FROM emp
final RelBuilder builder = RelBuilder.create(RelBuilderTest.config().build());
final RelNode root = builder.scan("EMP").project(builder.field("SAL"), builder.alias(builder.call(monotonicityFun), "M")).build();
HepProgram preProgram = new HepProgramBuilder().build();
HepPlanner prePlanner = new HepPlanner(preProgram);
prePlanner.setRoot(root);
final RelNode relBefore = prePlanner.findBestExp();
final RelCollation collationBefore = relBefore.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE);
HepProgram hepProgram = new HepProgramBuilder().addRuleInstance(CoreRules.PROJECT_TO_CALC).build();
HepPlanner hepPlanner = new HepPlanner(hepProgram);
hepPlanner.setRoot(root);
final RelNode relAfter = hepPlanner.findBestExp();
final RelCollation collationAfter = relAfter.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE);
assertEquals(collationBefore, collationAfter);
}
use of org.apache.calcite.sql.SqlFunction in project calcite by apache.
the class RelJson method toJson.
private Object toJson(RexNode node) {
final Map<String, @Nullable Object> map;
switch(node.getKind()) {
case FIELD_ACCESS:
map = jsonBuilder().map();
final RexFieldAccess fieldAccess = (RexFieldAccess) node;
map.put("field", fieldAccess.getField().getName());
map.put("expr", toJson(fieldAccess.getReferenceExpr()));
return map;
case LITERAL:
final RexLiteral literal = (RexLiteral) node;
final Object value = literal.getValue3();
map = jsonBuilder().map();
map.put("literal", RelEnumTypes.fromEnum(value));
map.put("type", toJson(node.getType()));
return map;
case INPUT_REF:
map = jsonBuilder().map();
map.put("input", ((RexSlot) node).getIndex());
map.put("name", ((RexSlot) node).getName());
return map;
case LOCAL_REF:
map = jsonBuilder().map();
map.put("input", ((RexSlot) node).getIndex());
map.put("name", ((RexSlot) node).getName());
map.put("type", toJson(node.getType()));
return map;
case CORREL_VARIABLE:
map = jsonBuilder().map();
map.put("correl", ((RexCorrelVariable) node).getName());
map.put("type", toJson(node.getType()));
return map;
default:
if (node instanceof RexCall) {
final RexCall call = (RexCall) node;
map = jsonBuilder().map();
map.put("op", toJson(call.getOperator()));
final List<@Nullable Object> list = jsonBuilder().list();
for (RexNode operand : call.getOperands()) {
list.add(toJson(operand));
}
map.put("operands", list);
switch(node.getKind()) {
case CAST:
map.put("type", toJson(node.getType()));
break;
default:
break;
}
if (call.getOperator() instanceof SqlFunction) {
if (((SqlFunction) call.getOperator()).getFunctionType().isUserDefined()) {
SqlOperator op = call.getOperator();
map.put("class", op.getClass().getName());
map.put("type", toJson(node.getType()));
map.put("deterministic", op.isDeterministic());
map.put("dynamic", op.isDynamicFunction());
}
}
if (call instanceof RexOver) {
RexOver over = (RexOver) call;
map.put("distinct", over.isDistinct());
map.put("type", toJson(node.getType()));
map.put("window", toJson(over.getWindow()));
}
return map;
}
throw new UnsupportedOperationException("unknown rex " + node);
}
}
use of org.apache.calcite.sql.SqlFunction in project calcite by apache.
the class AggVisitor method visit.
@Override
public Void visit(SqlCall call) {
final SqlOperator operator = call.getOperator();
// If nested aggregates disallowed or found an aggregate at invalid level
if (operator.isAggregator() && !(operator instanceof SqlAbstractGroupFunction) && !operator.requiresOver()) {
if (delegate != null) {
return operator.acceptCall(delegate, call);
}
if (aggregate) {
return found(call);
}
}
if (group && operator.isGroup()) {
return found(call);
}
// User-defined function may not be resolved yet.
if (operator instanceof SqlFunction) {
final SqlFunction sqlFunction = (SqlFunction) operator;
if (sqlFunction.getFunctionType().isUserDefinedNotSpecificFunction()) {
final List<SqlOperator> list = new ArrayList<>();
final SqlIdentifier identifier = sqlFunction.getSqlIdentifier();
if (identifier != null) {
opTab.lookupOperatorOverloads(identifier, sqlFunction.getFunctionType(), SqlSyntax.FUNCTION, list, nameMatcher);
for (SqlOperator operator2 : list) {
if (operator2.isAggregator() && !operator2.requiresOver()) {
// level
if (aggregate) {
found(call);
}
}
}
}
}
}
if (call.isA(SqlKind.QUERY)) {
// don't traverse into queries
return null;
}
if (call.getKind() == SqlKind.WITHIN_GROUP) {
if (aggregate) {
return found(call);
}
}
if (call.getKind() == SqlKind.OVER) {
if (over) {
return found(call);
} else {
// an aggregate function over a window is not an aggregate!
return null;
}
}
return super.visit(call);
}
use of org.apache.calcite.sql.SqlFunction in project calcite by apache.
the class ReflectiveSqlOperatorTable method lookupOperatorOverloads.
// implement SqlOperatorTable
@Override
public void lookupOperatorOverloads(SqlIdentifier opName, @Nullable SqlFunctionCategory category, SqlSyntax syntax, List<SqlOperator> operatorList, SqlNameMatcher nameMatcher) {
// NOTE jvs 3-Mar-2005: ignore category until someone cares
String simpleName;
if (opName.names.size() > 1) {
if (opName.names.get(opName.names.size() - 2).equals(IS_NAME)) {
// per SQL99 Part 2 Section 10.4 Syntax Rule 7.b.ii.1
simpleName = Util.last(opName.names);
} else {
return;
}
} else {
simpleName = opName.getSimple();
}
final Collection<SqlOperator> list = lookUpOperators(simpleName, syntax, nameMatcher);
if (list.isEmpty()) {
return;
}
for (SqlOperator op : list) {
if (op.getSyntax() == syntax) {
operatorList.add(op);
} else if (syntax == SqlSyntax.FUNCTION && op instanceof SqlFunction) {
// this special case is needed for operators like CAST,
// which are treated as functions but have special syntax
operatorList.add(op);
}
}
// Shouldn't it be covered by search above?
switch(syntax) {
case BINARY:
case PREFIX:
case POSTFIX:
for (SqlOperator extra : lookUpOperators(simpleName, syntax, nameMatcher)) {
// REVIEW: should only search operators added during this method?
if (extra != null && !operatorList.contains(extra)) {
operatorList.add(extra);
}
}
break;
default:
break;
}
}
Aggregations