Search in sources :

Example 1 with ExceededValueThresholdMarkerJexlNode

use of datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode in project datawave by NationalSecurityAgency.

the class IteratorBuildingVisitor method visit.

@Override
public Object visit(ASTAndNode and, Object data) {
    QueryPropertyMarker.Instance instance = QueryPropertyMarker.findInstance(and);
    if (instance.isType(ExceededOrThresholdMarkerJexlNode.class)) {
        JexlNode source = instance.getSource();
        // Ivarator to get the job done
        if (source instanceof ASTAndNode) {
            try {
                ivarateList(and, source, data);
            } catch (IOException ioe) {
                throw new DatawaveFatalQueryException(ioe);
            }
        } else {
            QueryException qe = new QueryException(DatawaveErrorCode.UNEXPECTED_SOURCE_NODE, MessageFormat.format("{0}", "Limited ExceededOrThresholdMarkerJexlNode"));
            throw new DatawaveFatalQueryException(qe);
        }
    } else if (data instanceof IndexRangeIteratorBuilder) {
        // index checking has already been done, otherwise we would not have
        // an "ExceededValueThresholdMarker"
        // hence the "IndexAgnostic" method can be used here
        LiteralRange range = JexlASTHelper.findRange().recursively().getRange(and);
        if (range == null) {
            QueryException qe = new QueryException(DatawaveErrorCode.MULTIPLE_RANGES_IN_EXPRESSION);
            throw new DatawaveFatalQueryException(qe);
        }
        ((IndexRangeIteratorBuilder) data).setRange(range);
    } else if (instance.isType(ExceededValueThresholdMarkerJexlNode.class)) {
        // if the parent is our ExceededValueThreshold marker, then use an
        // Ivarator to get the job done unless we don't have to
        JexlNode source = instance.getSource();
        String identifier = null;
        LiteralRange<?> range = null;
        boolean negatedLocal = false;
        if (source instanceof ASTAndNode) {
            range = buildLiteralRange(source, null);
            identifier = range.getFieldName();
        } else {
            if (source instanceof ASTNRNode || source instanceof ASTNotNode)
                negatedLocal = true;
            range = buildLiteralRange(source);
            identifier = JexlASTHelper.getIdentifier(source);
        }
        boolean negatedOverall = negatedLocal;
        if (data instanceof AbstractIteratorBuilder) {
            AbstractIteratorBuilder oib = (AbstractIteratorBuilder) data;
            if (oib.isInANot()) {
                negatedOverall = !negatedOverall;
            }
        }
        // or the field is index only but not in the term frequencies, then we must ivarate
        if (!limitLookup || !allowTermFrequencyLookup || (indexOnlyFields.contains(identifier) && !termFrequencyFields.contains(identifier))) {
            if (source instanceof ASTAndNode) {
                try {
                    List<ASTFunctionNode> functionNodes = JexlASTHelper.getFunctionNodes(source).stream().filter(node -> JexlFunctionArgumentDescriptorFactory.F.getArgumentDescriptor(node).allowIvaratorFiltering()).collect(Collectors.toList());
                    if (functionNodes.isEmpty()) {
                        ivarateRange(and, source, data);
                    } else {
                        ivarateFilter(and, source, data, functionNodes);
                    }
                } catch (IOException ioe) {
                    throw new DatawaveFatalQueryException("Unable to ivarate", ioe);
                }
            } else if (source instanceof ASTERNode || source instanceof ASTNRNode) {
                try {
                    ivarateRegex(and, source, data);
                } catch (IOException ioe) {
                    throw new DatawaveFatalQueryException("Unable to ivarate", ioe);
                }
            } else {
                QueryException qe = new QueryException(DatawaveErrorCode.UNEXPECTED_SOURCE_NODE, MessageFormat.format("{0}", "ExceededValueThresholdMarkerJexlNode"));
                throw new DatawaveFatalQueryException(qe);
            }
        } else {
            NestedIterator<Key> nested = null;
            if (termFrequencyFields.contains(identifier)) {
                nested = buildExceededFromTermFrequency(identifier, and, source, range, data);
            } else {
                /**
                 * This is okay since 1) We are doc specific 2) We are not index only or tf 3) Therefore, we must evaluate against the document for this
                 * expression 4) Return a stubbed range in case we have a disjunction that breaks the current doc.
                 */
                if (!limitOverride && !negatedOverall)
                    nested = createExceededCheck(identifier, range, and);
            }
            if (null != nested && null != data && data instanceof AbstractIteratorBuilder) {
                AbstractIteratorBuilder iterators = (AbstractIteratorBuilder) data;
                if (negatedLocal) {
                    iterators.addExclude(nested);
                } else {
                    iterators.addInclude(nested);
                }
            } else {
                if (isQueryFullySatisfied == true) {
                    log.warn("Determined that isQueryFullySatisfied should be false, but it was not preset to false in the SatisfactionVisitor");
                }
                return nested;
            }
        }
    } else if (null != data && data instanceof AndIteratorBuilder) {
        and.childrenAccept(this, data);
    } else {
        // Create an AndIterator and recursively add the children
        AbstractIteratorBuilder andItr = new AndIteratorBuilder();
        andItr.negateAsNeeded(data);
        and.childrenAccept(this, andItr);
        // If there is no parent
        if (data == null) {
            // Make this AndIterator the root node
            if (!andItr.includes().isEmpty()) {
                root = andItr.build();
            }
        } else {
            // Otherwise, add this AndIterator to its parent
            AbstractIteratorBuilder parent = (AbstractIteratorBuilder) data;
            if (!andItr.includes().isEmpty()) {
                parent.addInclude(andItr.build());
            }
        }
        if (log.isTraceEnabled()) {
            log.trace("ASTAndNode visit: pretty formatting of:\nparent.includes:" + formatIncludesOrExcludes(andItr.includes()) + "\nparent.excludes:" + formatIncludesOrExcludes(andItr.excludes()));
        }
    }
    return null;
}
Also used : Arrays(java.util.Arrays) Text(org.apache.hadoop.io.Text) ASTSizeMethod(org.apache.commons.jexl2.parser.ASTSizeMethod) AbstractIteratorBuilder(datawave.query.iterator.builder.AbstractIteratorBuilder) JavaRegexParseException(datawave.query.parser.JavaRegexAnalyzer.JavaRegexParseException) IvaratorCacheDir(datawave.query.iterator.ivarator.IvaratorCacheDir) ASTNRNode(org.apache.commons.jexl2.parser.ASTNRNode) Map(java.util.Map) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) AttributeFactory(datawave.query.attributes.AttributeFactory) JexlFunctionArgumentDescriptorFactory(datawave.query.jexl.functions.JexlFunctionArgumentDescriptorFactory) ExceededOrThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededOrThresholdMarkerJexlNode) DatawaveFatalQueryException(datawave.query.exceptions.DatawaveFatalQueryException) ASTJexlScript(org.apache.commons.jexl2.parser.ASTJexlScript) TimeFilter(datawave.query.predicate.TimeFilter) Set(java.util.Set) IndexRangeIteratorBuilder(datawave.query.iterator.builder.IndexRangeIteratorBuilder) ASTNENode(org.apache.commons.jexl2.parser.ASTNENode) DefaultArithmetic(datawave.query.jexl.DefaultArithmetic) ASTOrNode(org.apache.commons.jexl2.parser.ASTOrNode) Predicate(com.google.common.base.Predicate) AndIteratorBuilder(datawave.query.iterator.builder.AndIteratorBuilder) JexlContext(org.apache.commons.jexl2.JexlContext) DatawaveFieldIndexListIteratorJexl(datawave.core.iterators.DatawaveFieldIndexListIteratorJexl) TermFrequencyAggregator(datawave.query.jexl.functions.TermFrequencyAggregator) FileSortedSet(datawave.query.util.sortedset.FileSortedSet) IteratorBuilder(datawave.query.iterator.builder.IteratorBuilder) ASTEQNode(org.apache.commons.jexl2.parser.ASTEQNode) NestedIterator(datawave.query.iterator.NestedIterator) JexlASTHelper(datawave.query.jexl.JexlASTHelper) IndexIteratorBuilder(datawave.query.iterator.builder.IndexIteratorBuilder) JexlArithmetic(org.apache.commons.jexl2.JexlArithmetic) ASTMethodNode(org.apache.commons.jexl2.parser.ASTMethodNode) IteratorToSortedKeyValueIterator(datawave.query.util.IteratorToSortedKeyValueIterator) JexlNode(org.apache.commons.jexl2.parser.JexlNode) SortedKeyValueIterator(org.apache.accumulo.core.iterators.SortedKeyValueIterator) TreeSet(java.util.TreeSet) SourceFactory(datawave.query.iterator.SourceFactory) ArrayList(java.util.ArrayList) NodeOperand(datawave.query.jexl.LiteralRange.NodeOperand) Lists(com.google.common.collect.Lists) LiteralRange(datawave.query.jexl.LiteralRange) Key(org.apache.accumulo.core.data.Key) IndexFilterIteratorBuilder(datawave.query.iterator.builder.IndexFilterIteratorBuilder) OrIteratorBuilder(datawave.query.iterator.builder.OrIteratorBuilder) Predicates(com.google.common.base.Predicates) EventFieldIterator(datawave.query.iterator.EventFieldIterator) IndexRegexIteratorBuilder(datawave.query.iterator.builder.IndexRegexIteratorBuilder) FileSystemCache(datawave.core.iterators.filesystem.FileSystemCache) FieldIndexAggregator(datawave.query.jexl.functions.FieldIndexAggregator) QueryPropertyMarker(datawave.query.jexl.nodes.QueryPropertyMarker) TermFrequencyIndexBuilder(datawave.query.iterator.builder.TermFrequencyIndexBuilder) IOException(java.io.IOException) IndexListIteratorBuilder(datawave.query.iterator.builder.IndexListIteratorBuilder) DatawaveErrorCode(datawave.webservice.query.exception.DatawaveErrorCode) QueryLock(datawave.core.iterators.querylock.QueryLock) OrIterator(datawave.query.iterator.logic.OrIterator) NegationBuilder(datawave.query.iterator.builder.NegationBuilder) Range(org.apache.accumulo.core.data.Range) JavaRegexAnalyzer(datawave.query.parser.JavaRegexAnalyzer) Filter(datawave.query.predicate.Filter) QueryException(datawave.webservice.query.exception.QueryException) ASTEvaluationOnly(org.apache.commons.jexl2.parser.ASTEvaluationOnly) FST(org.apache.lucene.util.fst.FST) PartialKey(org.apache.accumulo.core.data.PartialKey) QuerySpanCollector(datawave.query.iterator.profile.QuerySpanCollector) IvaratorBuilder(datawave.query.iterator.builder.IvaratorBuilder) ASTIdentifier(org.apache.commons.jexl2.parser.ASTIdentifier) IteratorEnvironment(org.apache.accumulo.core.iterators.IteratorEnvironment) Script(org.apache.commons.jexl2.Script) SortedSet(java.util.SortedSet) DatawaveJexlEngine(datawave.query.jexl.DatawaveJexlEngine) URISyntaxException(java.net.URISyntaxException) SourceManager(datawave.query.iterator.SourceManager) Logger(org.apache.log4j.Logger) ValueTuple(datawave.query.attributes.ValueTuple) EventDataQueryFilter(datawave.query.predicate.EventDataQueryFilter) ASTNotNode(org.apache.commons.jexl2.parser.ASTNotNode) ASTStringLiteral(org.apache.commons.jexl2.parser.ASTStringLiteral) Path(org.apache.hadoop.fs.Path) Value(org.apache.accumulo.core.data.Value) URI(java.net.URI) UniversalSet(datawave.util.UniversalSet) TypeMetadata(datawave.query.util.TypeMetadata) ASTDelayedPredicate(org.apache.commons.jexl2.parser.ASTDelayedPredicate) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) List(java.util.List) IdentifierOpLiteral(datawave.query.jexl.JexlASTHelper.IdentifierOpLiteral) Entry(java.util.Map.Entry) IvaratorCacheDirConfig(datawave.query.iterator.ivarator.IvaratorCacheDirConfig) EventDataQueryExpressionFilter(datawave.query.predicate.EventDataQueryExpressionFilter) JexlNodes.children(org.apache.commons.jexl2.parser.JexlNodes.children) GenericObjectPool(org.apache.commons.pool.impl.GenericObjectPool) ASTReferenceExpression(org.apache.commons.jexl2.parser.ASTReferenceExpression) ASTNumberLiteral(org.apache.commons.jexl2.parser.ASTNumberLiteral) NoOpType(datawave.data.type.NoOpType) IdentityAggregator(datawave.query.jexl.functions.IdentityAggregator) MessageFormat(java.text.MessageFormat) HashSet(java.util.HashSet) ASTERNode(org.apache.commons.jexl2.parser.ASTERNode) DatawaveJexlContext(datawave.query.jexl.DatawaveJexlContext) ASTAndNode(org.apache.commons.jexl2.parser.ASTAndNode) NoSuchElementException(java.util.NoSuchElementException) ParserTreeConstants(org.apache.commons.jexl2.parser.ParserTreeConstants) MalformedURLException(java.net.MalformedURLException) Maps(com.google.common.collect.Maps) Constants(datawave.query.Constants) ArithmeticJexlEngines(datawave.query.jexl.ArithmeticJexlEngines) ASTFunctionNode(org.apache.commons.jexl2.parser.ASTFunctionNode) CompositeMetadata(datawave.query.composite.CompositeMetadata) EventFieldAggregator(datawave.query.jexl.functions.EventFieldAggregator) Collections(java.util.Collections) ChainableEventDataQueryFilter(datawave.query.predicate.ChainableEventDataQueryFilter) ASTReference(org.apache.commons.jexl2.parser.ASTReference) ASTNotNode(org.apache.commons.jexl2.parser.ASTNotNode) ASTERNode(org.apache.commons.jexl2.parser.ASTERNode) ASTNRNode(org.apache.commons.jexl2.parser.ASTNRNode) QueryPropertyMarker(datawave.query.jexl.nodes.QueryPropertyMarker) IOException(java.io.IOException) AndIteratorBuilder(datawave.query.iterator.builder.AndIteratorBuilder) DatawaveFatalQueryException(datawave.query.exceptions.DatawaveFatalQueryException) QueryException(datawave.webservice.query.exception.QueryException) ASTFunctionNode(org.apache.commons.jexl2.parser.ASTFunctionNode) AbstractIteratorBuilder(datawave.query.iterator.builder.AbstractIteratorBuilder) DatawaveFatalQueryException(datawave.query.exceptions.DatawaveFatalQueryException) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) ExceededOrThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededOrThresholdMarkerJexlNode) JexlNode(org.apache.commons.jexl2.parser.JexlNode) IndexRangeIteratorBuilder(datawave.query.iterator.builder.IndexRangeIteratorBuilder) LiteralRange(datawave.query.jexl.LiteralRange) Key(org.apache.accumulo.core.data.Key) PartialKey(org.apache.accumulo.core.data.PartialKey) ASTAndNode(org.apache.commons.jexl2.parser.ASTAndNode)

Example 2 with ExceededValueThresholdMarkerJexlNode

use of datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode in project datawave by NationalSecurityAgency.

the class ExecutableExpansionVisitorTest method testExceededThresholdExpansionExternal.

@Test
public void testExceededThresholdExpansionExternal() throws Exception {
    ASTJexlScript queryTree = JexlASTHelper.parseJexlQuery("UUID == 'capone' && (filter:includeRegex(QUOTE,'.*kind.*') || QUOTE == 'kind' || BIRTH_DATE == '123')");
    // update the generated queryTree to have an ExceededThreshold marker
    JexlNode child = new ExceededValueThresholdMarkerJexlNode(queryTree.jjtGetChild(0).jjtGetChild(0));
    // unlink the old node
    queryTree.jjtGetChild(0).jjtGetChild(0).jjtSetParent(null);
    // overwrite the old UUID==capone with the ExceededThreshold marker
    queryTree.jjtGetChild(0).jjtAddChild(child, 0);
    ShardQueryConfiguration config = EasyMock.createMock(ShardQueryConfiguration.class);
    MetadataHelper helper = EasyMock.createMock(MetadataHelper.class);
    HashSet<String> indexedFields = new HashSet<>();
    indexedFields.add("UUID");
    indexedFields.add("QUOTE");
    EasyMock.expect(config.getIndexedFields()).andReturn(indexedFields).anyTimes();
    EasyMock.replay(config, helper);
    ASTJexlScript newTree = ExecutableExpansionVisitor.expand(queryTree, config, helper);
    EasyMock.verify(config, helper);
    // included ExceededValueThresholdMarker before
    Assert.assertTrue(JexlStringBuildingVisitor.buildQuery(queryTree), JexlStringBuildingVisitor.buildQuery(queryTree).equals("((_Value_ = true) && (UUID == 'capone')) && (filter:includeRegex(QUOTE, '.*kind.*') || QUOTE == 'kind' || BIRTH_DATE == '123')"));
    // not executable
    Assert.assertFalse(ExecutableDeterminationVisitor.isExecutable(queryTree, config, helper));
    // what came out is executable
    Assert.assertTrue(ExecutableDeterminationVisitor.isExecutable(newTree, config, helper));
    // it looks like what we'd expect
    String expected = "(QUOTE == 'kind' && ((_Value_ = true) && (UUID == 'capone'))) || " + "((filter:includeRegex(QUOTE, '.*kind.*') || BIRTH_DATE == '123') && ((_Value_ = true) && (UUID == 'capone')))";
    Assert.assertEquals(expected, JexlStringBuildingVisitor.buildQueryWithoutParse(newTree));
}
Also used : MetadataHelper(datawave.query.util.MetadataHelper) ASTJexlScript(org.apache.commons.jexl2.parser.ASTJexlScript) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) ExceededOrThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededOrThresholdMarkerJexlNode) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) ShardQueryConfiguration(datawave.query.config.ShardQueryConfiguration) HashSet(java.util.HashSet) CompositeFunctionsTest(datawave.query.CompositeFunctionsTest) Test(org.junit.Test)

Example 3 with ExceededValueThresholdMarkerJexlNode

use of datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode in project datawave by NationalSecurityAgency.

the class ExecutableExpansionVisitorTest method testExceededThresholdExpansionInternal.

@Test
public void testExceededThresholdExpansionInternal() throws Exception {
    ASTJexlScript queryTree = JexlASTHelper.parseJexlQuery("UUID == 'capone' && (filter:includeRegex(QUOTE,'.*kind.*') || QUOTE == 'kind' || BIRTH_DATE == '123')");
    // update the generated queryTree to have an ExceededThreshold marker for BIRTH_DATE
    JexlNode child = new ExceededValueThresholdMarkerJexlNode(queryTree.jjtGetChild(0).jjtGetChild(1).jjtGetChild(0).jjtGetChild(0).jjtGetChild(1));
    // unlink the old node
    queryTree.jjtGetChild(0).jjtGetChild(1).jjtGetChild(0).jjtGetChild(0).jjtGetChild(1).jjtSetParent(null);
    // overwrite the old BIRTH_DATE==123 with the ExceededThreshold marker
    queryTree.jjtGetChild(0).jjtGetChild(1).jjtGetChild(0).jjtGetChild(0).jjtAddChild(child, 1);
    ShardQueryConfiguration config = EasyMock.createMock(ShardQueryConfiguration.class);
    MetadataHelper helper = EasyMock.createMock(MetadataHelper.class);
    HashSet<String> indexedFields = new HashSet<>();
    indexedFields.add("UUID");
    indexedFields.add("QUOTE");
    EasyMock.expect(config.getIndexedFields()).andReturn(indexedFields).anyTimes();
    EasyMock.replay(config, helper);
    ASTJexlScript newTree = ExecutableExpansionVisitor.expand(queryTree, config, helper);
    EasyMock.verify(config, helper);
    // included ExceededValueThresholdMarker before
    Assert.assertTrue(JexlStringBuildingVisitor.buildQuery(queryTree), JexlStringBuildingVisitor.buildQuery(queryTree).equals("UUID == 'capone' && (filter:includeRegex(QUOTE, '.*kind.*') || QUOTE == 'kind' || " + "((_Value_ = true) && (BIRTH_DATE == '123')))"));
    // not executable
    Assert.assertFalse(ExecutableDeterminationVisitor.isExecutable(queryTree, config, helper));
    // what came out is executable
    Assert.assertTrue(ExecutableDeterminationVisitor.isExecutable(newTree, config, helper));
    // it looks like what we'd expect
    String expected = "(QUOTE == 'kind' && UUID == 'capone') || " + "(((_Value_ = true) && (BIRTH_DATE == '123')) && UUID == 'capone') || " + "(filter:includeRegex(QUOTE, '.*kind.*') && UUID == 'capone')";
    Assert.assertEquals(expected, JexlStringBuildingVisitor.buildQueryWithoutParse(newTree));
}
Also used : MetadataHelper(datawave.query.util.MetadataHelper) ASTJexlScript(org.apache.commons.jexl2.parser.ASTJexlScript) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) ExceededOrThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededOrThresholdMarkerJexlNode) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) ShardQueryConfiguration(datawave.query.config.ShardQueryConfiguration) HashSet(java.util.HashSet) CompositeFunctionsTest(datawave.query.CompositeFunctionsTest) Test(org.junit.Test)

Example 4 with ExceededValueThresholdMarkerJexlNode

use of datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode in project datawave by NationalSecurityAgency.

the class JexlNodeFactory method createNodeTreeFromFieldsToValues.

/**
 * Expand a node given a mapping of fields to values. If the list is empty, then the original regex should be used.
 *
 * @param containerType
 *            should we create OR nodes or AND nodes
 * @param node
 * @param fieldsToValues
 *            A mapping of fields to values. If the values for a field is empty, then the original regex should be used.
 * @param expandFields
 *            Expand fields if true
 * @param expandValues
 *            Expand values if true
 * @param keepOriginalNode
 *            Keep the original node along with any expansions
 * @return A new sub query
 */
public static JexlNode createNodeTreeFromFieldsToValues(ContainerType containerType, JexlNode node, JexlNode orgNode, IndexLookupMap fieldsToValues, boolean expandFields, boolean expandValues, boolean keepOriginalNode) {
    // do nothing if not expanding fields or values
    if (!expandFields && !expandValues) {
        return orgNode;
    }
    // no expansions needed if the fieldname threshold is exceeded
    if (fieldsToValues.isKeyThresholdExceeded()) {
        return new ExceededTermThresholdMarkerJexlNode(orgNode);
    }
    // collapse the value sets if not expanding fields
    if (!expandFields) {
        ValueSet allValues = new ValueSet(-1);
        for (ValueSet values : fieldsToValues.values()) {
            allValues.addAll(values);
        }
        fieldsToValues.clear();
        for (String identifier : JexlASTHelper.getIdentifierNames(orgNode)) {
            fieldsToValues.put(identifier, allValues);
        }
    }
    Set<String> fields = fieldsToValues.keySet();
    JexlNode parentNode = (containerType.equals(ContainerType.OR_NODE) ? new ASTOrNode(ParserTreeConstants.JJTORNODE) : new ASTAndNode(ParserTreeConstants.JJTANDNODE));
    int parentNodeChildCount = 0;
    if (keepOriginalNode) {
        JexlNodes.ensureCapacity(parentNode, fields.size() + 1);
        JexlNode child = RebuildingVisitor.copy(orgNode);
        parentNode.jjtAddChild(child, parentNodeChildCount);
        child.jjtSetParent(parentNode);
        parentNodeChildCount++;
        // remove this entry from the fieldsToValues to avoid duplication
        for (String identifier : JexlASTHelper.getIdentifierNames(orgNode)) {
            for (Object value : JexlASTHelper.getLiteralValues(orgNode)) {
                fieldsToValues.remove(identifier, value);
            }
        }
    } else {
        JexlNodes.ensureCapacity(parentNode, fields.size());
    }
    for (String field : fields) {
        ValueSet valuesForField = fieldsToValues.get(field);
        // if not expanding values, then reuse the original node with simply a new field name (anyfield only)
        if (!expandValues) {
            JexlNode child = RebuildingVisitor.copy(orgNode);
            for (ASTIdentifier identifier : JexlASTHelper.getIdentifiers(child)) {
                if (identifier.image.equals(Constants.ANY_FIELD)) {
                    identifier.image = field;
                }
            }
            parentNode.jjtAddChild(child, parentNodeChildCount);
            child.jjtSetParent(parentNode);
            parentNodeChildCount++;
        } else // node with a new fieldname, wrapped with a marker node
        if (valuesForField.isThresholdExceeded()) {
            // create a set of nodes wrapping each pattern
            List<String> patterns = new ArrayList<>(fieldsToValues.getPatterns() == null ? new ArrayList<>() : fieldsToValues.getPatterns());
            if (patterns.isEmpty()) {
                JexlNode child = new ExceededValueThresholdMarkerJexlNode(buildUntypedNode(orgNode, field));
                parentNode.jjtAddChild(child, parentNodeChildCount);
                child.jjtSetParent(parentNode);
                parentNodeChildCount++;
            } else if (patterns.size() == 1) {
                JexlNode child = new ExceededValueThresholdMarkerJexlNode(buildUntypedNode(orgNode, field, patterns.get(0)));
                parentNode.jjtAddChild(child, parentNodeChildCount);
                child.jjtSetParent(parentNode);
                parentNodeChildCount++;
            } else {
                int childNodeChildCount = 0;
                JexlNode childNode = (containerType.equals(ContainerType.OR_NODE) ? new ASTOrNode(ParserTreeConstants.JJTORNODE) : new ASTAndNode(ParserTreeConstants.JJTANDNODE));
                JexlNodes.ensureCapacity(childNode, patterns.size());
                for (String pattern : patterns) {
                    JexlNode child = new ExceededValueThresholdMarkerJexlNode(buildUntypedNode(orgNode, field, pattern));
                    childNode.jjtAddChild(child, childNodeChildCount);
                    child.jjtSetParent(childNode);
                    childNodeChildCount++;
                }
                if (0 < childNodeChildCount) {
                    JexlNode wrappedChildNode = wrap(childNode);
                    childNode.jjtSetParent(wrappedChildNode);
                    parentNode.jjtAddChild(wrappedChildNode, parentNodeChildCount);
                    childNode.jjtSetParent(childNode);
                    parentNodeChildCount++;
                }
            }
        } else // Don't create an OR if we have only one value, directly attach it
        if (1 == valuesForField.size()) {
            JexlNode child = buildUntypedNode(node, field, valuesForField.iterator().next());
            parentNode.jjtAddChild(child, parentNodeChildCount);
            child.jjtSetParent(parentNode);
            parentNodeChildCount++;
        } else {
            int childNodeChildCount = 0;
            JexlNode childNode = (containerType.equals(ContainerType.OR_NODE) ? new ASTOrNode(ParserTreeConstants.JJTORNODE) : new ASTAndNode(ParserTreeConstants.JJTANDNODE));
            JexlNodes.ensureCapacity(childNode, valuesForField.size());
            for (String value : valuesForField) {
                JexlNode child = buildUntypedNode(node, field, value);
                childNode.jjtAddChild(child, childNodeChildCount);
                child.jjtSetParent(childNode);
                childNodeChildCount++;
            }
            if (0 < childNodeChildCount) {
                JexlNode wrappedChildNode = wrap(childNode);
                childNode.jjtSetParent(wrappedChildNode);
                parentNode.jjtAddChild(wrappedChildNode, parentNodeChildCount);
                childNode.jjtSetParent(childNode);
                parentNodeChildCount++;
            }
        }
    }
    switch(parentNodeChildCount) {
        case 0:
            // in this case we had no matches for the range, so this expression gets replaced with a FALSE node.
            return new ASTFalseNode(ParserTreeConstants.JJTFALSENODE);
        case 1:
            JexlNode child = parentNode.jjtGetChild(0);
            JexlNodes.promote(parentNode, child);
            return child;
        default:
            JexlNode wrappedParentNode = wrap(parentNode);
            parentNode.jjtSetParent(wrappedParentNode);
            return wrappedParentNode;
    }
}
Also used : ASTOrNode(org.apache.commons.jexl2.parser.ASTOrNode) ASTIdentifier(org.apache.commons.jexl2.parser.ASTIdentifier) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) ASTFalseNode(org.apache.commons.jexl2.parser.ASTFalseNode) ExceededTermThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededTermThresholdMarkerJexlNode) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ExceededTermThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededTermThresholdMarkerJexlNode) List(java.util.List) ArrayList(java.util.ArrayList) ValueSet(datawave.query.jexl.lookups.ValueSet) ASTAndNode(org.apache.commons.jexl2.parser.ASTAndNode)

Aggregations

ExceededValueThresholdMarkerJexlNode (datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode)4 JexlNode (org.apache.commons.jexl2.parser.JexlNode)4 ExceededOrThresholdMarkerJexlNode (datawave.query.jexl.nodes.ExceededOrThresholdMarkerJexlNode)3 HashSet (java.util.HashSet)3 ASTJexlScript (org.apache.commons.jexl2.parser.ASTJexlScript)3 CompositeFunctionsTest (datawave.query.CompositeFunctionsTest)2 ShardQueryConfiguration (datawave.query.config.ShardQueryConfiguration)2 MetadataHelper (datawave.query.util.MetadataHelper)2 Test (org.junit.Test)2 Predicate (com.google.common.base.Predicate)1 Predicates (com.google.common.base.Predicates)1 Lists (com.google.common.collect.Lists)1 Maps (com.google.common.collect.Maps)1 Sets (com.google.common.collect.Sets)1 DatawaveFieldIndexListIteratorJexl (datawave.core.iterators.DatawaveFieldIndexListIteratorJexl)1 FileSystemCache (datawave.core.iterators.filesystem.FileSystemCache)1 QueryLock (datawave.core.iterators.querylock.QueryLock)1 NoOpType (datawave.data.type.NoOpType)1 Constants (datawave.query.Constants)1 AttributeFactory (datawave.query.attributes.AttributeFactory)1