@Override public ColumnPlanNode visitFunctionCall(FunctionCallNode callNode) { if(!(callNode.getFunction() instanceof ColumnFunction)) { throw new UnsupportedOperationException("TODO: " + callNode.getFunction().getId()); } List<ColumnPlanNode> arguments = new ArrayList<>(); for (FormulaNode formulaNode : callNode.getArguments()) { arguments.add(formulaNode.accept(this)); } return new VectorOp((ColumnFunction) callNode.getFunction(), arguments); }
public static FunctionCallNode equals(FormulaNode x, FormulaNode y) { return new FunctionCallNode(EqualFunction.INSTANCE, x, y); }
private static SimpleCondition parseCondition(FormulaNode node) { if(node instanceof GroupNode) { return parseCondition(((GroupNode) node).getExpr()); } else if(node instanceof FunctionCallNode) { FunctionCallNode callNode = ((FunctionCallNode) node); if(callNode.getFunction() == NotFunction.INSTANCE) { return parseCondition(callNode.getArgument(0)).negate(); } else if(callNode.getArguments().size() == 2) { return parseBinary(((FunctionCallNode) node)); } else { throw new UnsupportedOperationException("function: " + ((FunctionCallNode) node).getFunction()); } } else if(node instanceof CompoundExpr) { return parseEnumCondition((CompoundExpr) node); } else { throw new UnsupportedOperationException("cannot handle expression: " + node); } }
private static boolean isBinaryOperation(FormulaNode node, FormulaFunction operator) { if(node instanceof FunctionCallNode) { FunctionCallNode callNode = (FunctionCallNode) node; return callNode.getArgumentCount() == 2 && callNode.getFunction() == operator; } return false; }
private static SimpleConditionList contains(Criteria criteria, FunctionCallNode call, SimpleOperator operator) { ResourceId field = parseFieldId(call.getArgument(0)); List<SimpleCondition> conditions = new ArrayList<>(); for (int i = 1; i < call.getArguments().size(); i++) { conditions.add(new SimpleCondition(field, operator, parseEnum(call.getArgument(i)))); } return new SimpleConditionList(criteria, conditions); }
private static SimpleCondition parseBinary(FunctionCallNode call) { ResourceId fieldId = parseFieldId(call.getArgument(0)); SimpleOperator op = parseOp(call.getFunction()); FieldValue fieldValue = parseFieldValue(call.getArgument(1)); return new SimpleCondition(fieldId, op, fieldValue); }
private static boolean filterContainsPartner(String filter, ResourceId partnerFormId, ResourceId partnerId) { FormulaNode filterFormula = FormulaParser.parse(filter); SymbolNode expectedPartnerForm = new SymbolNode(partnerFormId); ConstantNode expectedPartnerRecord = new ConstantNode(partnerId.asString()); if (!(filterFormula instanceof FunctionCallNode)) { return false; } if (!(((FunctionCallNode) filterFormula).getFunction() instanceof EqualFunction)) { return false; } if (((FunctionCallNode) filterFormula).getArgumentCount() != 2) { return false; } FunctionCallNode equalFunctionCall = (FunctionCallNode) filterFormula; if (!(equalFunctionCall.getArgument(0 ) instanceof SymbolNode)) { return false; } if (!(equalFunctionCall.getArgument(1) instanceof ConstantNode)) { return false; } SymbolNode partnerFormNode = (SymbolNode) equalFunctionCall.getArgument(0); ConstantNode partnerFieldNode = (ConstantNode) equalFunctionCall.getArgument(1); if (!partnerFormNode.equals(expectedPartnerForm)) { return false; } if (!partnerFieldNode.equals(expectedPartnerRecord)) { return false; } return true; }
@Test public void binaryInfix() { assertThat( new FunctionCallNode(PlusFunction.INSTANCE, new SymbolNode("X"), new SymbolNode("Y")).asExpression(), equalTo("X + Y")); }
private void gatherPlaceholderExprs(FormulaNode node, List<SymbolNode> placeholderExprList) { if (node instanceof SymbolNode) { placeholderExprList.add((SymbolNode) node); } else if (node instanceof FunctionCallNode) { FunctionCallNode functionCallNode = (FunctionCallNode) node; List<FormulaNode> arguments = functionCallNode.getArguments(); for (FormulaNode arg : arguments) { gatherPlaceholderExprs(arg, placeholderExprList); } } }
private String parseNumericComparison(FunctionCallNode callNode) { if(callNode.getFunction() == LessFunction.INSTANCE) { return "lt"; } else if(callNode.getFunction() == GreaterFunction.INSTANCE) { return "gt"; } else if(callNode.getFunction() == EqualFunction.INSTANCE) { return "eq"; } return null; }
private boolean parseComparison(FormulaNode node, Multimap<Integer, FilterConfig> result) { if(!(node instanceof FunctionCallNode)) { return false; } // Check that this is a binary FunctionCallNode callNode = (FunctionCallNode) node; if(callNode.getArgumentCount() != 2) { return false; } // Does this comparison involve one of our fields? Integer columnIndex = findColumnIndex(callNode.getArgument(0)); if(columnIndex == null) { return false; } // Is it compared with a constant value? FieldValue value = parseLiteral(callNode.getArgument(1)); if(value == null) { return false; } FilterConfig config; if(value instanceof Quantity) { config = numericFilter(callNode, (Quantity) value); } else if(value instanceof LocalDate) { config = dateFilter(callNode, (LocalDate) value); } else { return false; } result.put(columnIndex, config); return true; }
@Test public void symbolSourceRefs() { FunctionCallNode call = (FunctionCallNode) FormulaParser.parse("[A] + [B]"); assertThat(call.getSourceRange(), equalTo(new SourceRange(new SourcePos(0, 0), new SourcePos(0, 9)))); assertThat(call.getArgument(1).getSourceRange(), equalTo(new SourceRange(new SourcePos(0, 6), new SourcePos(0, 9)))); }
private static void findBinaryTree(FormulaNode node, List<FormulaNode> list, FormulaFunction operator) { // Unwrap group expressions ((A)) node = simplify(node); if(isBinaryOperation(node, operator)) { // If this expression is in the form A && B, then descend // recursively FunctionCallNode callNode = (FunctionCallNode) node; findBinaryTree(callNode.getArgument(0), list, operator); findBinaryTree(callNode.getArgument(1), list, operator); } else { // If not a conjunction, then add this node to the list list.add(node); } }
private static void parse(List<SimpleCondition> conditions, Set<Criteria> criteria, FormulaNode node) { if(node instanceof GroupNode) { parse(conditions, criteria, ((GroupNode) node).getExpr()); return; } if(node instanceof FunctionCallNode) { FunctionCallNode call = (FunctionCallNode) node; if (call.getFunction() == AndFunction.INSTANCE) { criteria.add(Criteria.ALL_TRUE); parse(conditions, criteria, call.getArgument(0)); parse(conditions, criteria, call.getArgument(1)); return; } else if (call.getFunction() == OrFunction.INSTANCE) { criteria.add(Criteria.ANY_TRUE); parse(conditions, criteria, call.getArgument(0)); parse(conditions, criteria, call.getArgument(1)); return; } } conditions.add(parseCondition(node)); }
if(isNumberCall.getFunction() != IsNumberFunction.INSTANCE) { return false; FormulaNode isNumberArgument = Formulas.simplify(isNumberCall.getArgument(0)); if(!(isNumberArgument instanceof FunctionCallNode)) { return false; if(searchCall.getFunction() != SearchFunction.INSTANCE) { return false; if(searchCall.getArgumentCount() != 2) { return false; FieldValue substring = parseLiteral(searchCall.getArgument(0)); if(!(substring instanceof HasStringValue)) { return false; FormulaNode columnExpr = searchCall.getArgument(1); Integer columnIndex = columnMap.get(columnExpr); if(columnIndex == -1) {
@Test public void normalCall() { assertThat( new FunctionCallNode(MaxFunction.INSTANCE, new SymbolNode("X"), new SymbolNode("Y")).asExpression(), equalTo("max(X, Y)")); }
private Slot<ColumnView> createNullaryFunctionCall(final FunctionCallNode call) { assert call.getArguments().isEmpty(); final Slot<Integer> rowCount = batch.addRowCount(filterLevel, rootFormClass); return new Slot<ColumnView>() { @Override public ColumnView get() { return ((ColumnFunction) call.getFunction()).columnApply(rowCount.get(), Collections.<ColumnView>emptyList()); } }; }
private String parseDateComparison(FunctionCallNode callNode) { if(callNode.getFunction() == LessFunction.INSTANCE) { return "before"; } else if(callNode.getFunction() == GreaterFunction.INSTANCE) { return "after"; } else if(callNode.getFunction() == EqualFunction.INSTANCE) { return "on"; } return null; }
private FunctionCallSlot createFunctionCall(final FunctionCallNode call) { resolver.enterFunction(call.getFunction()); try { final List<Slot<ColumnView>> argumentSlots = Lists.newArrayList(); for (FormulaNode argument : call.getArguments()) { argumentSlots.add(argument.accept(this)); } return new FunctionCallSlot((ColumnFunction)call.getFunction(), argumentSlots); } finally { resolver.exitFunction(call.getFunction()); } }
@Override public Slot<ColumnView> visitFunctionCall(final FunctionCallNode call) { if(call.getFunction() instanceof ColumnFunction) { if(call.getArguments().isEmpty()) { return createNullaryFunctionCall(call); } else { return createFunctionCall(call); } } else if(call.getFunction() instanceof BoundingBoxFunction) { FormulaNode geometry = call.getArgument(0); Collection<NodeMatch> nodes; if(geometry instanceof SymbolNode) { nodes = resolver.resolveSymbol(((SymbolNode) geometry)); } else if(geometry instanceof CompoundExpr) { nodes = resolver.resolveCompoundExpr((CompoundExpr) geometry); } else { throw new QuerySyntaxException("Function " + call.getFunction().getId() + " can only be applied" + " to an argument of type GeoArea."); } return addColumn(nodes.stream().map(n -> n.withComponent(call.getFunction().getId())).collect(Collectors.toList())); } else { throw new UnsupportedOperationException("TODO: " + call.getFunction().getId()); } }