Skip to content

Commit

Permalink
fixes #2303: composite and filtered query logics (#2319)
Browse files Browse the repository at this point in the history
* Updated to not drop filtered query logics allowing appropriate failure and success scenarios
* Updated query plan to show filtered and failed queries
  • Loading branch information
ivakegg authored and hgklohr committed Apr 23, 2024
1 parent e696248 commit 12f2a94
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import datawave.webservice.query.logic.BaseQueryLogic;
import datawave.webservice.query.logic.QueryLogic;
import datawave.webservice.query.logic.QueryLogicTransformer;
import datawave.webservice.query.logic.filtered.FilteredQueryLogic;
import datawave.webservice.query.result.event.EventBase;
import datawave.webservice.result.BaseResponse;

Expand Down Expand Up @@ -265,6 +266,13 @@ public GenericQueryConfiguration initialize(AccumuloClient client, Query setting
String logicName = next.getKey();
QueryLogic<?> logic = next.getValue();
GenericQueryConfiguration config = null;

// start the next query logic plan expression
if (logicQueryStringBuilder.length() > 0) {
logicQueryStringBuilder.append(" || ");
}
logicQueryStringBuilder.append("( ( logic = '").append(logicName).append("' )").append(" && ");

try {
// duplicate the settings for this query
Query settingsCopy = settings.duplicate(settings.getQueryName() + " -> " + logicName);
Expand All @@ -273,29 +281,37 @@ public GenericQueryConfiguration initialize(AccumuloClient client, Query setting
runtimeQueryAuthorizations = updateRuntimeAuthorizationsAndQueryAuths(logic, settingsCopy);

config = logic.initialize(client, settingsCopy, runtimeQueryAuthorizations);
if (logicQueryStringBuilder.length() > 0) {
logicQueryStringBuilder.append(" || ");
}
logicQueryStringBuilder.append("( ( logic = '").append(logicName).append("' )");
logicQueryStringBuilder.append(" && ").append(config.getQueryString()).append(" )");
QueryLogicHolder holder = new QueryLogicHolder(logicName, logic);
holder.setConfig(config);
holder.setSettings(settingsCopy);
holder.setMaxResults(logic.getMaxResults());
logicState.put(logicName, holder);

// if doing sequential execution, then stop since we have one initialized
if (isShortCircuitExecution()) {
break;

// only add this query logic to the initialized logic states if it was not simply filtered out
if (logic instanceof FilteredQueryLogic && ((FilteredQueryLogic) logic).isFiltered()) {
log.info("Dropping " + logic.getLogicName() + " as it was filtered out");
logicQueryStringBuilder.append("( filtered = true )");
} else {
logicQueryStringBuilder.append(config.getQueryString());

QueryLogicHolder holder = new QueryLogicHolder(logicName, logic);
holder.setConfig(config);
holder.setSettings(settingsCopy);
holder.setMaxResults(logic.getMaxResults());
logicState.put(logicName, holder);

// if doing sequential execution, then stop since we have one initialized
if (isShortCircuitExecution()) {
break;
}
}

} catch (Exception e) {
exceptions.put(logicName, e);
log.error("Failed to initialize " + logic.getClass().getName(), e);
logicQueryStringBuilder.append("( failure = '").append(e.getMessage()).append("' )");
failedQueryLogics.put(logicName, logic);
} finally {
queryLogics.remove(next.getKey());
}

// close out the query plan expression
logicQueryStringBuilder.append(" )");
}

// if something failed initialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public boolean isFiltered() {
log.debug("Passing through filter " + filter + " for query " + super.getLogicName());
}
}
return filtered;
return filtered || (getDelegate() instanceof FilteredQueryLogic && ((FilteredQueryLogic) getDelegate()).isFiltered());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import datawave.webservice.query.logic.EasyRoleManager;
import datawave.webservice.query.logic.QueryLogic;
import datawave.webservice.query.logic.QueryLogicTransformer;
import datawave.webservice.query.logic.filtered.FilteredQueryLogic;
import datawave.webservice.query.result.EdgeQueryResponseBase;
import datawave.webservice.query.result.edge.EdgeBase;
import datawave.webservice.result.BaseQueryResponse;
Expand Down Expand Up @@ -454,6 +455,21 @@ public Set<String> getExampleQueries() {

}

public static class TestFilteredQueryLogic extends FilteredQueryLogic {
private boolean filtered;

public TestFilteredQueryLogic(boolean filtered) {
QueryLogic delegate = new TestQueryLogic();
setDelegate(delegate);
this.filtered = filtered;
}

@Override
public boolean isFiltered() {
return filtered;
}
}

@Before
public void setup() {
System.setProperty(DnUtils.NPE_OU_PROPERTY, "iamnotaperson");
Expand Down Expand Up @@ -597,6 +613,61 @@ public GenericQueryConfiguration initialize(AccumuloClient connection, Query set
Assert.assertEquals(1, c.getInitializedLogics().size());
}

@Test
public void testInitializeOKWithFilter() throws Exception {

Map<String,QueryLogic<?>> logics = new HashMap<>();
logics.put("TestQueryLogic", new TestQueryLogic());
logics.put("TestQueryLogic2", new TestFilteredQueryLogic(true));

QueryImpl settings = new QueryImpl();
settings.setPagesize(100);
settings.setQueryAuthorizations(auths.toString());
settings.setQuery("FOO == 'BAR'");
settings.setParameters(new HashSet<>());
settings.setId(UUID.randomUUID());

CompositeQueryLogic c = new CompositeQueryLogic();
c.setQueryLogics(logics);

c.setPrincipal(principal);
c.initialize(null, settings, Collections.singleton(auths));

Assert.assertEquals(1, c.getInitializedLogics().size());
// ensure the filtered query logic is actually dropped
Assert.assertEquals(0, c.getUninitializedLogics().size());
}

@Test(expected = CompositeLogicException.class)
public void testInitializeNotOKWithFilter() throws Exception {

Map<String,QueryLogic<?>> logics = new HashMap<>();
logics.put("TestQueryLogic", new TestQueryLogic() {
@Override
public GenericQueryConfiguration initialize(AccumuloClient connection, Query settings, Set<Authorizations> runtimeQueryAuthorizations)
throws Exception {
throw new Exception("initialize failed");
}
});
logics.put("TestQueryLogic2", new TestFilteredQueryLogic(true));

QueryImpl settings = new QueryImpl();
settings.setPagesize(100);
settings.setQueryAuthorizations(auths.toString());
settings.setQuery("FOO == 'BAR'");
settings.setParameters(new HashSet<>());
settings.setId(UUID.randomUUID());

CompositeQueryLogic c = new CompositeQueryLogic();
c.setQueryLogics(logics);

// testing that we fail despite allMustInitialize to false because the filtered logic does not count
c.setAllMustInitialize(false);

c.setPrincipal(principal);
c.initialize(null, settings, Collections.singleton(auths));
}

@Test(expected = CompositeLogicException.class)
public void testInitializeNotOKWithFailure() throws Exception {

Expand Down

0 comments on commit 12f2a94

Please sign in to comment.