Search in sources :

Example 1 with QueryContext

use of datawave.query.tables.edge.contexts.QueryContext in project datawave by NationalSecurityAgency.

the class EdgeTableRangeBuildingVisitor method computeVisitaionContext.

/**
 * This method creates a new VisitationContext object to be returned and loads the final list of queryContexts which are then used to build the ranges and
 * normalized query One of the main purposes of this method is to create the normalized query that is used to filter column families from ranges. This is a
 * problem when there are multiple query contexts because the whitelist will exclude certain column family values, which will affect what gets returned by
 * the query. This is addressed by the columnFamilyAreDifferent boolean which is passed down to populateQuery()
 */
private VisitationContext computeVisitaionContext(List<QueryContext> queryContexts) {
    // if both edge types and edge relationships are complete (not regex) for each query context then we can use the
    // batch scanners built in fetch column method to do the filtering for us so we can drop the edge types, and relations
    // from the normalized query that goes to the edge filter iterator.
    boolean includColumnFamilyTerms = false;
    boolean columnFamilyAreDifferent = false;
    // If the sink field appears in a query contexts, 'otherContext' list then it will have to be included in the normalized
    // query string sent to the edge filter iterator
    boolean includeSink = false;
    boolean includeSource = false;
    for (QueryContext queryContext : queryContexts) {
        if (queryContext.hasCompleteColumnFamily() == false) {
            includColumnFamilyTerms = true;
            break;
        }
    }
    if (queryContexts.size() > 1) {
        int i;
        QueryContext.ColumnContext firstColumn = (queryContexts.get(0).getColumnContext());
        for (i = 1; i < queryContexts.size(); i++) {
            QueryContext.ColumnContext currentContext = queryContexts.get(i).getColumnContext();
            if ((firstColumn != null && currentContext == null) || (firstColumn == null && currentContext != null)) {
                columnFamilyAreDifferent = true;
                break;
            }
            if (firstColumn != null) {
                if (!(firstColumn.equals(queryContexts.get(i).getColumnContext()))) {
                    columnFamilyAreDifferent = true;
                    break;
                }
            }
        }
    }
    VisitationContext vContext = new VisitationContext(includeStats);
    vContext.setHasAllCompleteColumnFamilies(!includColumnFamilyTerms);
    for (QueryContext qContext : queryContexts) {
        includeSink = vContext.updateQueryRanges(qContext);
        includeSink = includeSink || sawEquivalenceRegexSink || columnFamilyAreDifferent;
        // If there is only one query context you don't need to include the source, you do if there are multiple QCs
        if (queryContexts.size() > 1) {
            // If there are multiple query contexts, that means that there are multiple sources. If there are multiple
            // sources, then they need to be included with sinks.
            includeSource = includeSink || sawEquivalenceRegexSource || columnFamilyAreDifferent;
        } else if (queryContexts.size() == 1) {
            // If there is only one source, you don't need to include it with the sink. It is implied.
            includeSource = sawEquivalenceRegexSource || columnFamilyAreDifferent;
        }
        // boolean for source and sink inclusion for normalized query
        // boolean to include column family terms to the normalized query
        // boolean to create white list for column family terms
        vContext.updateQueryStrings(qContext, includeSource, includeSink, includColumnFamilyTerms, !columnFamilyAreDifferent);
        if (!includColumnFamilyTerms) {
            vContext.buildColumnFamilyList(qContext, includeStats);
        }
    }
    vContext.setTermCount(termCount);
    return vContext;
}
Also used : QueryContext(datawave.query.tables.edge.contexts.QueryContext) VisitationContext(datawave.query.tables.edge.contexts.VisitationContext)

Example 2 with QueryContext

use of datawave.query.tables.edge.contexts.QueryContext in project datawave by NationalSecurityAgency.

the class EdgeTableRangeBuildingVisitor method visit.

/**
 * Or node should have exactly two children This or node's only function is to combine the lists returned by its children.
 *
 * The Children can return lists of type IdentityContext or QueryContext both children must return the same type of lists else its an improper query ex:
 * Both children return lists of IdentityContexts where the identity is source Both children return lists of QueryContexts
 *
 * There is one exception where a QueryContext list and a IdentityContext list could be returned by the children in which case the returned IdentityContext
 * list is immediately packaged into a new QueryContext and is then combined with the returned other QueryContext list Happens with a query like this:
 * {@code (SOURCE == 'source1' && SINK == 'sink') || (SOURCE == 'source2')}
 *
 * Or node will return either a list of IdentityContexts or QueryContexts
 */
@Override
public Object visit(ASTOrNode node, Object data) {
    if (termCount > maxTerms) {
        log.error("Query has too many terms");
        throw new IllegalArgumentException("Too many search terms " + termCount);
    }
    // run the visitor against all of the children
    List<List<? extends EdgeContext>> childContexts = new ArrayList<>(node.jjtGetNumChildren());
    for (JexlNode child : children(node)) {
        childContexts.add((List<? extends EdgeContext>) child.jjtAccept(this, null));
    }
    if (childContexts.isEmpty()) {
        log.error("Unable to get edge context from OR node");
        throw new IllegalArgumentException("Unable to get edge context from OR node");
    }
    List<? extends EdgeContext> mergedContext = childContexts.remove(childContexts.size() - 1);
    // now merge the child contexts
    while (!childContexts.isEmpty()) {
        List<? extends EdgeContext> childContext = childContexts.remove(childContexts.size() - 1);
        if ((childContext.get(0) instanceof IdentityContext) && (mergedContext.get(0) instanceof IdentityContext)) {
            // Combine two lists of Identity contexts
            IdentityContext iContext1 = (IdentityContext) childContext.get(0);
            IdentityContext iContext2 = (IdentityContext) mergedContext.get(0);
            checkNotExclusion(iContext1, "Can't OR exclusion expressions");
            checkNotExclusion(iContext2, "Can't OR exclusion expressions");
            if (iContext1.getIdentity().equals(iContext2.getIdentity())) {
                ((List<IdentityContext>) childContext).addAll((List<IdentityContext>) mergedContext);
                mergedContext = childContext;
            } else {
                log.error("Query attempted to or like terms: " + iContext1.getIdentity() + " and " + iContext1.getIdentity());
                throw new IllegalArgumentException("Can't OR unlike terms: " + iContext1.getIdentity() + " and " + iContext2.getIdentity());
            }
        } else if ((childContext.get(0) instanceof QueryContext) && (mergedContext.get(0) instanceof QueryContext)) {
            List<QueryContext> context1 = (List<QueryContext>) childContext;
            List<QueryContext> context2 = (List<QueryContext>) mergedContext;
            if (context1.size() == 1 && context1.get(0).hasSourceList() == false) {
                runCombine(context2, context1);
                mergedContext = context2;
            } else if (context2.size() == 1 && context2.get(0).hasSourceList() == false) {
                runCombine(context1, context2);
                mergedContext = context1;
            } else {
                context1.addAll(context2);
                mergedContext = context1;
            }
        } else if ((childContext.get(0) instanceof IdentityContext) && (mergedContext.get(0) instanceof QueryContext)) {
            checkNotExclusion((IdentityContext) childContext.get(0), "Can't OR exclusion expressions");
            QueryContext queryContext = new QueryContext();
            queryContext.packageIdentities((List<IdentityContext>) childContext, false);
            if (isSourceList((List<IdentityContext>) childContext)) {
                ((List<QueryContext>) mergedContext).add(queryContext);
            } else {
                List<QueryContext> otherContexts = new ArrayList<>();
                otherContexts.add(queryContext);
                runCombine((List<QueryContext>) mergedContext, otherContexts);
            }
        } else if ((childContext.get(0) instanceof QueryContext) && (mergedContext.get(0) instanceof IdentityContext)) {
            checkNotExclusion((IdentityContext) mergedContext.get(0), "Can't OR exclusion expressions");
            QueryContext queryContext = new QueryContext();
            queryContext.packageIdentities((List<IdentityContext>) mergedContext, false);
            if (isSourceList((List<IdentityContext>) mergedContext)) {
                ((List<QueryContext>) childContext).add(queryContext);
            } else {
                List<QueryContext> otherContexts = new ArrayList<>();
                otherContexts.add(queryContext);
                runCombine((List<QueryContext>) childContext, otherContexts);
            }
            mergedContext = childContext;
        } else {
            log.error("OR node had unexpected return type");
            throw new IllegalArgumentException("Error: problem with query syntax");
        }
    }
    return mergedContext;
}
Also used : EdgeContext(datawave.query.tables.edge.contexts.EdgeContext) ArrayList(java.util.ArrayList) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ArrayList(java.util.ArrayList) List(java.util.List) IdentityContext(datawave.query.tables.edge.contexts.IdentityContext) QueryContext(datawave.query.tables.edge.contexts.QueryContext)

Example 3 with QueryContext

use of datawave.query.tables.edge.contexts.QueryContext in project datawave by NationalSecurityAgency.

the class EdgeTableRangeBuildingVisitor method visit.

/*
     * And node should have exactly two children This node's only function is to pack lists of IdentityContexts into a QueryContext
     * 
     * Returns a QueryContext
     */
@Override
public Object visit(ASTAndNode node, Object data) {
    if (termCount > maxTerms) {
        log.error("Query has too many terms");
        throw new IllegalArgumentException("Too many search terms " + termCount);
    }
    // run the visitor against all of the children
    List<List<? extends EdgeContext>> childContexts = new ArrayList<>(node.jjtGetNumChildren());
    for (JexlNode child : children(node)) {
        childContexts.add((List<? extends EdgeContext>) child.jjtAccept(this, null));
    }
    if (childContexts.isEmpty()) {
        log.error("Unable to get edge context from AND node");
        throw new IllegalArgumentException("Unable to get edge context from AND node");
    }
    List<? extends EdgeContext> mergedContext = childContexts.remove(childContexts.size() - 1);
    // now merge the child contexts
    while (!childContexts.isEmpty()) {
        List<? extends EdgeContext> childContext = childContexts.remove(childContexts.size() - 1);
        if ((childContext.get(0) instanceof IdentityContext) && (mergedContext.get(0) instanceof IdentityContext)) {
            QueryContext qContext = new QueryContext();
            qContext.packageIdentities((List<IdentityContext>) childContext);
            qContext.packageIdentities((List<IdentityContext>) mergedContext);
            ArrayList<QueryContext> aList = new ArrayList<>();
            aList.add(qContext);
            mergedContext = aList;
        } else if ((childContext.get(0) instanceof IdentityContext) && (mergedContext.get(0) instanceof QueryContext)) {
            for (QueryContext qContext : (List<QueryContext>) mergedContext) {
                qContext.packageIdentities((List<IdentityContext>) childContext);
            }
        } else if ((childContext.get(0) instanceof QueryContext) && (mergedContext.get(0) instanceof IdentityContext)) {
            for (QueryContext qContext : (List<QueryContext>) childContext) {
                qContext.packageIdentities((List<IdentityContext>) mergedContext);
            }
            mergedContext = childContext;
        /*
                 * On rare occasion a group of Query contexts without a source can get grouped together, this happens with queries like: SOURCE == 's1' &&
                 * ((TYPE == 't1' && RELATIONSHIP == 'r1') || (TYPE == 't2' && RELATIONSHIP == 'r2'))
                 * 
                 * This probably was not supposed to be allowed, you should only be ANDing groups of sources with groups of other identifiers rather here it is
                 * ANDing source(s) with groups of expressions. Honestly it would be safer to split that type of query up into two separate ones but limited
                 * support has been included. However it can be dangerous if the user tries to use SINK in one of the grouped expressions so that is not
                 * allowed.
                 */
        } else if ((childContext.get(0) instanceof QueryContext) && (mergedContext.get(0) instanceof QueryContext)) {
            // Assumes that if the first query context does not have a row context then they all don't
            if (((List<QueryContext>) childContext).get(0).getRowContext() != null) {
                // The size of the list for contexts1 is usually going to be 1
                for (QueryContext qContext : ((List<QueryContext>) childContext)) {
                    // Combine the query contexts if anything fails blame the user
                    if (!(qContext.combineQueryContexts(((List<QueryContext>) mergedContext), false))) {
                        log.error("And node had unexpected return type");
                        throw new IllegalArgumentException("Error: problem with query syntax");
                    }
                }
                mergedContext = childContext;
            } else if (((List<QueryContext>) mergedContext).get(0).getRowContext() != null) {
                for (QueryContext qContext : ((List<QueryContext>) mergedContext)) {
                    if (!(qContext.combineQueryContexts(((List<QueryContext>) childContext), false))) {
                        log.error("And node had unexpected return type");
                        throw new IllegalArgumentException("Error: problem with query syntax");
                    }
                }
            } else {
                log.error("Problem parsing query");
                throw new IllegalArgumentException("Error: problem with query syntax");
            }
        } else {
            log.error("And node had unexpected return type");
            throw new IllegalArgumentException("Error: problem with query syntax");
        }
    }
    return mergedContext;
}
Also used : EdgeContext(datawave.query.tables.edge.contexts.EdgeContext) ArrayList(java.util.ArrayList) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ArrayList(java.util.ArrayList) List(java.util.List) IdentityContext(datawave.query.tables.edge.contexts.IdentityContext) QueryContext(datawave.query.tables.edge.contexts.QueryContext)

Example 4 with QueryContext

use of datawave.query.tables.edge.contexts.QueryContext in project datawave by NationalSecurityAgency.

the class EdgeTableRangeBuildingVisitor method visit.

/*
     * This is treated as the root node of the tree it can only have one child
     * 
     * The job of this node is to take the results of its child and create the visitation context to be returned
     */
public Object visit(ASTJexlScript node, Object data) {
    int numChildren = node.jjtGetNumChildren();
    if (numChildren != 1) {
        log.error("JexlScript node had an unexpected number of children: " + numChildren);
        BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.NODE_PROCESSING_ERROR);
        throw new RuntimeException(qe);
    }
    @SuppressWarnings("unchecked") List<? extends EdgeContext> context = (List<? extends EdgeContext>) node.jjtGetChild(0).jjtAccept(this, null);
    if (context.get(0) instanceof IdentityContext) {
        // this can only happen if there is no AND node in the query
        // Build singleton list of QueryContexts then create VisitationContext
        QueryContext qContext = new QueryContext();
        qContext.packageIdentities((List<IdentityContext>) context);
        return computeVisitaionContext(Collections.singletonList(qContext));
    } else if (context.get(0) instanceof QueryContext) {
        return computeVisitaionContext((List<QueryContext>) context);
    // return context;
    } else {
        log.error("JexlScript node recieved unexpected return type: " + context);
        BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.NODE_PROCESSING_ERROR);
        throw new RuntimeException(qe);
    }
}
Also used : EdgeContext(datawave.query.tables.edge.contexts.EdgeContext) BadRequestQueryException(datawave.webservice.query.exception.BadRequestQueryException) ArrayList(java.util.ArrayList) List(java.util.List) IdentityContext(datawave.query.tables.edge.contexts.IdentityContext) QueryContext(datawave.query.tables.edge.contexts.QueryContext)

Aggregations

QueryContext (datawave.query.tables.edge.contexts.QueryContext)4 EdgeContext (datawave.query.tables.edge.contexts.EdgeContext)3 IdentityContext (datawave.query.tables.edge.contexts.IdentityContext)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 JexlNode (org.apache.commons.jexl2.parser.JexlNode)2 VisitationContext (datawave.query.tables.edge.contexts.VisitationContext)1 BadRequestQueryException (datawave.webservice.query.exception.BadRequestQueryException)1