Adding booleanOperator and subFilters to QQueryFilter

This commit is contained in:
2022-10-10 08:40:51 -05:00
parent 28060e95e3
commit 262038bc87
8 changed files with 453 additions and 154 deletions

View File

@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.query;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
/*******************************************************************************
@ -36,6 +37,20 @@ public class QQueryFilter implements Serializable, Cloneable
private List<QFilterCriteria> criteria = new ArrayList<>();
private List<QFilterOrderBy> orderBys = new ArrayList<>();
private BooleanOperator booleanOperator = BooleanOperator.AND;
private List<QQueryFilter> subFilters = new ArrayList<>();
/*******************************************************************************
**
*******************************************************************************/
public enum BooleanOperator
{
AND,
OR
}
/*******************************************************************************
@ -66,6 +81,15 @@ public class QQueryFilter implements Serializable, Cloneable
}
}
if(subFilters != null)
{
clone.subFilters = new ArrayList<>();
for(QQueryFilter subFilter : subFilters)
{
clone.subFilters.add(subFilter.clone());
}
}
return clone;
}
catch(CloneNotSupportedException e)
@ -76,6 +100,32 @@ public class QQueryFilter implements Serializable, Cloneable
/*******************************************************************************
**
*******************************************************************************/
public boolean hasAnyCriteria()
{
if(CollectionUtils.nullSafeHasContents(criteria))
{
return (true);
}
if(CollectionUtils.nullSafeHasContents(subFilters))
{
for(QQueryFilter subFilter : subFilters)
{
if(subFilter.hasAnyCriteria())
{
return (true);
}
}
}
return (false);
}
/*******************************************************************************
** Getter for criteria
**
@ -168,4 +218,72 @@ public class QQueryFilter implements Serializable, Cloneable
return (this);
}
/*******************************************************************************
** Getter for booleanOperator
**
*******************************************************************************/
public BooleanOperator getBooleanOperator()
{
return booleanOperator;
}
/*******************************************************************************
** Setter for booleanOperator
**
*******************************************************************************/
public void setBooleanOperator(BooleanOperator booleanOperator)
{
this.booleanOperator = booleanOperator;
}
/*******************************************************************************
** Fluent setter for booleanOperator
**
*******************************************************************************/
public QQueryFilter withBooleanOperator(BooleanOperator booleanOperator)
{
this.booleanOperator = booleanOperator;
return (this);
}
/*******************************************************************************
** Getter for subFilters
**
*******************************************************************************/
public List<QQueryFilter> getSubFilters()
{
return subFilters;
}
/*******************************************************************************
** Setter for subFilters
**
*******************************************************************************/
public void setSubFilters(List<QQueryFilter> subFilters)
{
this.subFilters = subFilters;
}
/*******************************************************************************
** Fluent setter for subFilters
**
*******************************************************************************/
public QQueryFilter withSubFilters(List<QQueryFilter> subFilters)
{
this.subFilters = subFilters;
return (this);
}
}

View File

@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
@ -141,126 +142,121 @@ public class MemoryRecordStore
/*******************************************************************************
**
*******************************************************************************/
@SuppressWarnings("checkstyle:indentation")
private boolean doesRecordMatch(QQueryFilter filter, QRecord qRecord)
{
boolean recordMatches = true;
if(filter != null && filter.getCriteria() != null)
if(filter == null || !filter.hasAnyCriteria())
{
for(QFilterCriteria criterion : filter.getCriteria())
{
String fieldName = criterion.getFieldName();
Serializable value = qRecord.getValue(fieldName);
return (true);
}
switch(criterion.getOperator())
/////////////////////////////////////////////////////////////////////////////////////
// for an AND query, default to a TRUE answer, and we'll &= each criteria's value. //
// for an OR query, default to FALSE, and |= each criteria's value. //
/////////////////////////////////////////////////////////////////////////////////////
AtomicBoolean recordMatches = new AtomicBoolean(filter.getBooleanOperator().equals(QQueryFilter.BooleanOperator.AND) ? true : false);
///////////////////////////////////////
// if there are criteria, apply them //
///////////////////////////////////////
for(QFilterCriteria criterion : CollectionUtils.nonNullList(filter.getCriteria()))
{
String fieldName = criterion.getFieldName();
Serializable value = qRecord.getValue(fieldName);
boolean criterionMatches = switch(criterion.getOperator())
{
case EQUALS:
{
recordMatches = testEquals(criterion, value);
break;
}
case NOT_EQUALS:
{
recordMatches = !testEquals(criterion, value);
break;
}
case IN:
{
recordMatches = testIn(criterion, value);
break;
}
case NOT_IN:
{
recordMatches = !testIn(criterion, value);
break;
}
case IS_BLANK:
{
recordMatches = testBlank(criterion, value);
break;
}
case IS_NOT_BLANK:
{
recordMatches = !testBlank(criterion, value);
break;
}
case CONTAINS:
{
recordMatches = testContains(criterion, fieldName, value);
break;
}
case NOT_CONTAINS:
{
recordMatches = !testContains(criterion, fieldName, value);
break;
}
case STARTS_WITH:
{
recordMatches = testStartsWith(criterion, fieldName, value);
break;
}
case NOT_STARTS_WITH:
{
recordMatches = !testStartsWith(criterion, fieldName, value);
break;
}
case ENDS_WITH:
{
recordMatches = testEndsWith(criterion, fieldName, value);
break;
}
case NOT_ENDS_WITH:
{
recordMatches = !testEndsWith(criterion, fieldName, value);
break;
}
case GREATER_THAN:
{
recordMatches = testGreaterThan(criterion, value);
break;
}
case GREATER_THAN_OR_EQUALS:
{
recordMatches = testGreaterThan(criterion, value) || testEquals(criterion, value);
break;
}
case LESS_THAN:
{
recordMatches = !testGreaterThan(criterion, value) && !testEquals(criterion, value);
break;
}
case LESS_THAN_OR_EQUALS:
{
recordMatches = !testGreaterThan(criterion, value);
break;
}
case BETWEEN:
case EQUALS -> testEquals(criterion, value);
case NOT_EQUALS -> !testEquals(criterion, value);
case IN -> testIn(criterion, value);
case NOT_IN -> !testIn(criterion, value);
case IS_BLANK -> testBlank(criterion, value);
case IS_NOT_BLANK -> !testBlank(criterion, value);
case CONTAINS -> testContains(criterion, fieldName, value);
case NOT_CONTAINS -> !testContains(criterion, fieldName, value);
case STARTS_WITH -> testStartsWith(criterion, fieldName, value);
case NOT_STARTS_WITH -> !testStartsWith(criterion, fieldName, value);
case ENDS_WITH -> testEndsWith(criterion, fieldName, value);
case NOT_ENDS_WITH -> !testEndsWith(criterion, fieldName, value);
case GREATER_THAN -> testGreaterThan(criterion, value);
case GREATER_THAN_OR_EQUALS -> testGreaterThan(criterion, value) || testEquals(criterion, value);
case LESS_THAN -> !testGreaterThan(criterion, value) && !testEquals(criterion, value);
case LESS_THAN_OR_EQUALS -> !testGreaterThan(criterion, value);
case BETWEEN ->
{
QFilterCriteria criteria0 = new QFilterCriteria().withValues(criterion.getValues());
QFilterCriteria criteria1 = new QFilterCriteria().withValues(new ArrayList<>(criterion.getValues()));
criteria1.getValues().remove(0);
recordMatches = (testGreaterThan(criteria0, value) || testEquals(criteria0, value)) && (!testGreaterThan(criteria1, value) || testEquals(criteria1, value));
break;
yield (testGreaterThan(criteria0, value) || testEquals(criteria0, value)) && (!testGreaterThan(criteria1, value) || testEquals(criteria1, value));
}
case NOT_BETWEEN:
case NOT_BETWEEN ->
{
QFilterCriteria criteria0 = new QFilterCriteria().withValues(criterion.getValues());
QFilterCriteria criteria1 = new QFilterCriteria().withValues(criterion.getValues());
criteria1.getValues().remove(0);
recordMatches = !(testGreaterThan(criteria0, value) || testEquals(criteria0, value)) && (!testGreaterThan(criteria1, value) || testEquals(criteria1, value));
break;
yield !(testGreaterThan(criteria0, value) || testEquals(criteria0, value)) && (!testGreaterThan(criteria1, value) || testEquals(criteria1, value));
}
default:
{
throw new NotImplementedException("Operator [" + criterion.getOperator() + "] is not yet implemented in the Memory backend.");
}
}
if(!recordMatches)
{
break;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// add this new value to the existing recordMatches value - and if we can short circuit the remaining checks, do so. //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Boolean shortCircuitValue = applyBooleanOperator(recordMatches, criterionMatches, filter.getBooleanOperator());
if(shortCircuitValue != null)
{
return (shortCircuitValue);
}
}
return recordMatches;
////////////////////////////////////////
// apply sub-filters if there are any //
////////////////////////////////////////
for(QQueryFilter subFilter : CollectionUtils.nonNullList(filter.getSubFilters()))
{
boolean subFilterMatches = doesRecordMatch(subFilter, qRecord);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// add this new value to the existing recordMatches value - and if we can short circuit the remaining checks, do so. //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Boolean shortCircuitValue = applyBooleanOperator(recordMatches, subFilterMatches, filter.getBooleanOperator());
if(shortCircuitValue != null)
{
return (shortCircuitValue);
}
}
return (recordMatches.getPlain());
}
/*******************************************************************************
** Based on an incoming boolean value (accumulator), a new value, and a boolean
** operator, update the accumulator, and if we can then short-circuit remaining
** operations, return a true or false. Returning null means to keep going.
*******************************************************************************/
private Boolean applyBooleanOperator(AtomicBoolean accumulator, boolean newValue, QQueryFilter.BooleanOperator booleanOperator)
{
boolean accumulatorValue = accumulator.getPlain();
if(booleanOperator.equals(QQueryFilter.BooleanOperator.AND))
{
accumulatorValue &= newValue;
if(!accumulatorValue)
{
return (false);
}
}
else
{
accumulatorValue |= newValue;
if(accumulatorValue)
{
return (true);
}
}
accumulator.set(accumulatorValue);
return (null);
}

View File

@ -55,6 +55,7 @@ import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -211,48 +212,49 @@ class MemoryBackendModuleTest
insertInput.setTableName(table.getName());
insertInput.setRecords(List.of(
new QRecord().withValue("id", 1).withValue("name", "Square").withValue("date", LocalDate.of(1980, Month.MAY, 31)),
new QRecord().withValue("id", 2).withValue("name", "Triangle").withValue("date", LocalDate.of(1999, Month.DECEMBER, 31))
new QRecord().withValue("id", 2).withValue("name", "Triangle").withValue("date", LocalDate.of(1999, Month.DECEMBER, 31)),
new QRecord().withValue("id", 3).withValue("name", "Circle").withValue("date", LocalDate.of(2022, Month.OCTOBER, 10))
));
new InsertAction().execute(insertInput);
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.IN, List.of(1, 2))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.IN, List.of(2, 3))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.IN, List.of(3, 4))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.NOT_IN, List.of(3, 4))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.NOT_IN, List.of(4, 5))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.NOT_IN, List.of(2, 3))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square"))).size());
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square"))).get(0).getValue("name"));
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("notAFieldSoNull", QCriteriaOperator.EQUALS, List.of("Square"))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_EQUALS, List.of("notFound"))).size());
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_EQUALS, List.of("Triangle"))).get(0).getValue("name"));
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_EQUALS, List.of("notFound"))).size());
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_EQUALS, List.of("Triangle", "Circle"))).get(0).getValue("name"));
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of("ria"))).size());
assertEquals("Triangle", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of("ria"))).get(0).getValue("name"));
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_CONTAINS, List.of("notFound"))).size());
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_CONTAINS, List.of("ria"))).get(0).getValue("name"));
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_CONTAINS, List.of("notFound"))).size());
assertEquals("Square", queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.NOT_CONTAINS, List.of("le"))).get(0).getValue("name"));
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.CONTAINS, List.of("ria"))));
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of(1))));
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.CONTAINS, List.of())));
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(2))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(1))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(0))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(2035, Month.JANUARY, 1)))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(3))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(1))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN, List.of(0))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1980, Month.MAY, 31)))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(3))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(2))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(1))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(0))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(2035, Month.JANUARY, 1)))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(LocalDate.of(1980, Month.MAY, 31)))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(4))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(3))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(2))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.GREATER_THAN_OR_EQUALS, List.of(1))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN, List.of(LocalDate.of(2022, Month.SEPTEMBER, 1)))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
@ -265,7 +267,7 @@ class MemoryBackendModuleTest
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(1990, Month.JANUARY, 1)))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(1980, Month.MAY, 31)))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("date", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(LocalDate.of(1970, Month.JANUARY, 1)))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(3))).size());
assertEquals(3, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(3))).size());
assertEquals(2, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(2))).size());
assertEquals(1, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(1))).size());
assertEquals(0, queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of(0))).size());
@ -275,16 +277,88 @@ class MemoryBackendModuleTest
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN, List.of())));
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("id", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of())));
assertThrows(QException.class, () -> queryShapes(qInstance, table, session, new QFilterCriteria("name", QCriteriaOperator.LESS_THAN_OR_EQUALS, List.of("Bob"))));
{
////////////////////////////
// test a simple OR query //
////////////////////////////
QQueryFilter filter = new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.OR)
.withCriteria(new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square")))
.withCriteria(new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Triangle")));
assertEquals(2, queryShapes(qInstance, table, session, filter).size());
assertThat(queryShapes(qInstance, table, session, filter)).anyMatch(r -> r.getValueString("name").equals("Square"));
assertThat(queryShapes(qInstance, table, session, filter)).anyMatch(r -> r.getValueString("name").equals("Triangle"));
}
///////////////////////////////////////////////////
// null or empty query - should find all records //
///////////////////////////////////////////////////
assertEquals(3, queryShapes(qInstance, table, session, (QQueryFilter) null).size());
assertEquals(3, queryShapes(qInstance, table, session, new QQueryFilter()).size());
{
/////////////////////////////////
// test a complex nested query //
/////////////////////////////////
QQueryFilter filter = new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.OR)
.withSubFilters(List.of(
new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.AND)
.withCriteria(new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square")))
.withCriteria(new QFilterCriteria("id", QCriteriaOperator.EQUALS, List.of(1))),
new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.AND)
.withCriteria(new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Circle")))
.withCriteria(new QFilterCriteria("id", QCriteriaOperator.EQUALS, List.of(3)))
));
assertEquals(2, queryShapes(qInstance, table, session, filter).size());
assertThat(queryShapes(qInstance, table, session, filter)).anyMatch(r -> r.getValueString("name").equals("Square") && r.getValueInteger("id").equals(1));
assertThat(queryShapes(qInstance, table, session, filter)).anyMatch(r -> r.getValueString("name").equals("Circle") && r.getValueInteger("id").equals(3));
}
{
/////////////////////////////////
// test a complex nested query //
/////////////////////////////////
QQueryFilter filter = new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.AND)
.withSubFilters(List.of(
new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.OR)
.withCriteria(new QFilterCriteria("id", QCriteriaOperator.EQUALS, List.of(1)))
.withCriteria(new QFilterCriteria("id", QCriteriaOperator.EQUALS, List.of(3))),
new QQueryFilter()
.withBooleanOperator(QQueryFilter.BooleanOperator.OR)
.withCriteria(new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Square")))
.withCriteria(new QFilterCriteria("name", QCriteriaOperator.EQUALS, List.of("Circle")))
));
assertEquals(2, queryShapes(qInstance, table, session, filter).size());
assertThat(queryShapes(qInstance, table, session, filter)).anyMatch(r -> r.getValueString("name").equals("Square") && r.getValueInteger("id").equals(1));
assertThat(queryShapes(qInstance, table, session, filter)).anyMatch(r -> r.getValueString("name").equals("Circle") && r.getValueInteger("id").equals(3));
}
}
/*******************************************************************************
**
*******************************************************************************/
private List<QRecord> queryShapes(QInstance qInstance, QTableMetaData table, QSession session, QFilterCriteria criteria) throws QException
{
return queryShapes(qInstance, table, session, new QQueryFilter().withCriteria(criteria));
}
private List<QRecord> queryShapes(QInstance qInstance, QTableMetaData table, QSession session, QQueryFilter filter) throws QException
{
QueryInput queryInput = new QueryInput(qInstance);
queryInput.setSession(session);
queryInput.setTableName(table.getName());
queryInput.setFilter(new QQueryFilter().withCriteria(criteria));
queryInput.setFilter(filter);
QueryOutput queryOutput = new QueryAction().execute(queryInput);
return queryOutput.getRecords();
}