/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.linkedin.pinot.pql.parsers.pql2.ast; import com.linkedin.pinot.common.request.FilterOperator; import com.linkedin.pinot.common.request.FilterQuery; import com.linkedin.pinot.common.utils.request.FilterQueryTree; import java.util.ArrayList; import java.util.List; /** * AST node for a list of predicates joined by boolean operators. */ public class PredicateListAstNode extends PredicateAstNode { @Override public FilterQueryTree buildFilterQueryTree() { List<FilterQueryTree> orPredicates = null; List<FilterQueryTree> andPredicates = null; int childrenCount = getChildren().size(); if (childrenCount == 1) { return ((PredicateAstNode)getChildren().get(0)).buildFilterQueryTree(); } for (int i = 0; i < childrenCount; i += 2) { PredicateAstNode predicate = (PredicateAstNode) getChildren().get(i); BooleanOperatorAstNode nextOperator = null; if (i + 1 < childrenCount) { nextOperator = (BooleanOperatorAstNode) getChildren().get(i + 1); } // 3 cases for the next operator: // - No next operator: Add the predicate to the AND predicates or to the parent OR predicate // - AND: Add the predicate to the AND predicates, creating it if necessary // - OR: // 1. Add the predicate to the AND predicates if it exists, then add it to the parent OR predicate // 2. If there is no current AND predicate list, add the predicate directly // 3. Clear the current AND predicates list // Is it the last predicate? if (nextOperator == null) { if (andPredicates != null) { andPredicates.add(predicate.buildFilterQueryTree()); if (orPredicates != null) { orPredicates.add(buildPredicate(andPredicates, FilterOperator.AND)); } } else { // Previous predicate was OR, therefore add the predicate directly orPredicates.add(predicate.buildFilterQueryTree()); } } else if (nextOperator == BooleanOperatorAstNode.AND) { if (andPredicates == null) { andPredicates = new ArrayList<>(); } andPredicates.add(predicate.buildFilterQueryTree()); } else { if (orPredicates == null) { orPredicates = new ArrayList<>(); } if (andPredicates != null) { andPredicates.add(predicate.buildFilterQueryTree()); orPredicates.add(buildPredicate(andPredicates, FilterOperator.AND)); andPredicates = null; } else { orPredicates.add(predicate.buildFilterQueryTree()); } } } if (orPredicates != null) { return buildPredicate(orPredicates, FilterOperator.OR); } else { return buildPredicate(andPredicates, FilterOperator.AND); } } private FilterQueryTree buildPredicate(List<FilterQueryTree> children, FilterOperator operator) { return new FilterQueryTree(null, null, operator, children); } }