Support searching for a localdate or instant.

This commit is contained in:
2023-10-16 12:17:17 -05:00
parent d28426562a
commit e633ea8ed1
2 changed files with 110 additions and 21 deletions

View File

@ -23,6 +23,8 @@ package com.kingsrook.qqq.backend.core.actions.values;
import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -208,37 +210,50 @@ public class SearchPossibleValueSourceAction
}
else
{
if(StringUtils.hasContent(input.getSearchTerm()))
String searchTerm = input.getSearchTerm();
if(StringUtils.hasContent(searchTerm))
{
for(String valueField : possibleValueSource.getSearchFields())
{
QFieldMetaData field = table.getField(valueField);
if(field.getType().equals(QFieldType.STRING))
try
{
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.STARTS_WITH, List.of(input.getSearchTerm())));
}
else if(field.getType().equals(QFieldType.DATE) || field.getType().equals(QFieldType.DATE_TIME))
{
LOG.debug("Not querying PVS [" + possibleValueSource.getName() + "] on date field [" + field.getName() + "]");
// todo - what? queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.STARTS_WITH, List.of(input.getSearchTerm())));
}
else
{
try
QFieldMetaData field = table.getField(valueField);
if(field.getType().equals(QFieldType.STRING))
{
Integer valueAsInteger = ValueUtils.getValueAsInteger(input.getSearchTerm());
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.STARTS_WITH, List.of(searchTerm)));
}
else if(field.getType().equals(QFieldType.DATE))
{
LocalDate searchDate = ValueUtils.getValueAsLocalDate(searchTerm);
if(searchDate != null)
{
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.EQUALS, searchDate));
}
}
else if(field.getType().equals(QFieldType.DATE_TIME))
{
Instant searchDate = ValueUtils.getValueAsInstant(searchTerm);
if(searchDate != null)
{
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.EQUALS, searchDate));
}
}
else
{
Integer valueAsInteger = ValueUtils.getValueAsInteger(searchTerm);
if(valueAsInteger != null)
{
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.EQUALS, List.of(valueAsInteger)));
}
}
catch(Exception e)
{
////////////////////////////////////////////////////////
// write a FALSE criteria if the value isn't a number //
////////////////////////////////////////////////////////
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.IN, List.of()));
}
}
catch(Exception e)
{
//////////////////////////////////////////////////////////////////////////////////////////
// write a FALSE criteria upon exceptions (e.g., type conversion fails) //
// Why are we doing this? so a single-field query finds nothing instead of everything. //
//////////////////////////////////////////////////////////////////////////////////////////
queryFilter.addCriteria(new QFilterCriteria(valueField, QCriteriaOperator.IN, List.of()));
}
}
}

View File

@ -23,12 +23,18 @@ package com.kingsrook.qqq.backend.core.actions.values;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.Month;
import java.util.List;
import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryRecordStore;
import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.AfterEach;
@ -224,6 +230,74 @@ class SearchPossibleValueSourceActionTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testSearchPvsAction_tableByIdOnlyNonNumeric() throws QException
{
QContext.getQInstance().getPossibleValueSource(TestUtils.TABLE_NAME_SHAPE)
.withSearchFields(List.of("id"));
/////////////////////////////////////////////////////////////////////////////////////////////
// a non-integer input should find nothing //
// the catch { (IN, empty) } code makes this happen - without that, all records are found. //
// (furthermore, i think that's only exposed if there's only 1 search field, maybe) //
/////////////////////////////////////////////////////////////////////////////////////////////
SearchPossibleValueSourceOutput output = getSearchPossibleValueSourceOutput("A", TestUtils.TABLE_NAME_SHAPE);
assertEquals(0, output.getResults().size());
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testSearchPvsAction_tableByLocalDate() throws QException
{
MemoryRecordStore.getInstance().reset();
////////////////////////////////////////////
// make a PVS for the person-memory table //
////////////////////////////////////////////
QContext.getQInstance().addPossibleValueSource(QPossibleValueSource.newForTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
.withSearchFields(List.of("id", "firstName", "birthDate"))
);
List<QRecord> shapeRecords = List.of(
new QRecord().withValue("id", 1).withValue("firstName", "Homer").withValue("birthDate", LocalDate.of(1960, Month.JANUARY, 1)),
new QRecord().withValue("id", 2).withValue("firstName", "Marge").withValue("birthDate", LocalDate.of(1961, Month.FEBRUARY, 2)),
new QRecord().withValue("id", 3).withValue("firstName", "Bart").withValue("birthDate", LocalDate.of(1980, Month.MARCH, 3)));
InsertInput insertInput = new InsertInput();
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
insertInput.setRecords(shapeRecords);
new InsertAction().execute(insertInput);
/////////////////////////////////////
// a parseable date yields a match //
/////////////////////////////////////
SearchPossibleValueSourceOutput output = getSearchPossibleValueSourceOutput("1960-01-01", TestUtils.TABLE_NAME_PERSON_MEMORY);
assertEquals(1, output.getResults().size());
assertThat(output.getResults()).anyMatch(pv -> pv.getId().equals(1));
///////////////////////////////////////////////////////////////////////
// alternative date format also works (thanks to ValueUtils parsing) //
///////////////////////////////////////////////////////////////////////
output = getSearchPossibleValueSourceOutput("1/1/1960", TestUtils.TABLE_NAME_PERSON_MEMORY);
assertEquals(1, output.getResults().size());
assertThat(output.getResults()).anyMatch(pv -> pv.getId().equals(1));
///////////////////////////////////
// incomplete date finds nothing //
///////////////////////////////////
output = getSearchPossibleValueSourceOutput("1960-01", TestUtils.TABLE_NAME_PERSON_MEMORY);
assertEquals(0, output.getResults().size());
}
/*******************************************************************************
**
*******************************************************************************/