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;
}
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;
}
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;
}
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);
}
}
Aggregations