mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
update to implicity add a queryJoin, if a filter field calls out a table name that matches a join in the instance
This commit is contained in:
@ -225,7 +225,7 @@ public class GenerateReportAction
|
|||||||
JoinsContext joinsContext = null;
|
JoinsContext joinsContext = null;
|
||||||
if(StringUtils.hasContent(dataSource.getSourceTable()))
|
if(StringUtils.hasContent(dataSource.getSourceTable()))
|
||||||
{
|
{
|
||||||
joinsContext = new JoinsContext(exportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins());
|
joinsContext = new JoinsContext(exportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), dataSource.getQueryFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<QFieldMetaData> fields = new ArrayList<>();
|
List<QFieldMetaData> fields = new ArrayList<>();
|
||||||
@ -308,7 +308,7 @@ public class GenerateReportAction
|
|||||||
queryInput.setQueryJoins(dataSource.getQueryJoins());
|
queryInput.setQueryJoins(dataSource.getQueryJoins());
|
||||||
|
|
||||||
queryInput.setShouldTranslatePossibleValues(true);
|
queryInput.setShouldTranslatePossibleValues(true);
|
||||||
queryInput.setFieldsToTranslatePossibleValues(setupFieldsToTranslatePossibleValues(reportInput, dataSource, new JoinsContext(reportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins())));
|
queryInput.setFieldsToTranslatePossibleValues(setupFieldsToTranslatePossibleValues(reportInput, dataSource, new JoinsContext(reportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), queryInput.getFilter())));
|
||||||
|
|
||||||
if(dataSource.getQueryInputCustomizer() != null)
|
if(dataSource.getQueryInputCustomizer() != null)
|
||||||
{
|
{
|
||||||
|
@ -23,8 +23,12 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.query;
|
|||||||
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
@ -55,7 +59,7 @@ public class JoinsContext
|
|||||||
** Constructor
|
** Constructor
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public JoinsContext(QInstance instance, String tableName, List<QueryJoin> queryJoins) throws QException
|
public JoinsContext(QInstance instance, String tableName, List<QueryJoin> queryJoins, QQueryFilter filter) throws QException
|
||||||
{
|
{
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.mainTableName = tableName;
|
this.mainTableName = tableName;
|
||||||
@ -63,13 +67,7 @@ public class JoinsContext
|
|||||||
|
|
||||||
for(QueryJoin queryJoin : this.queryJoins)
|
for(QueryJoin queryJoin : this.queryJoins)
|
||||||
{
|
{
|
||||||
QTableMetaData joinTable = instance.getTable(queryJoin.getJoinTable());
|
processQueryJoin(queryJoin);
|
||||||
String tableNameOrAlias = queryJoin.getJoinTableOrItsAlias();
|
|
||||||
if(aliasToTableNameMap.containsKey(tableNameOrAlias))
|
|
||||||
{
|
|
||||||
throw (new QException("Duplicate table name or alias: " + tableNameOrAlias));
|
|
||||||
}
|
|
||||||
aliasToTableNameMap.put(tableNameOrAlias, joinTable.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
@ -92,11 +90,16 @@ public class JoinsContext
|
|||||||
{
|
{
|
||||||
join = join.flip();
|
join = join.flip();
|
||||||
}
|
}
|
||||||
this.queryJoins.add(new QueryJoin().withJoinMetaData(join).withType(QueryJoin.Type.INNER)); // todo aliases? probably.
|
|
||||||
|
QueryJoin queryJoin = new QueryJoin().withJoinMetaData(join).withType(QueryJoin.Type.INNER);
|
||||||
|
this.queryJoins.add(queryJoin); // todo something else with aliases? probably.
|
||||||
|
processQueryJoin(queryJoin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensureFilterIsRepresented(filter);
|
||||||
|
|
||||||
/* todo!!
|
/* todo!!
|
||||||
for(QueryJoin queryJoin : queryJoins)
|
for(QueryJoin queryJoin : queryJoins)
|
||||||
{
|
{
|
||||||
@ -111,6 +114,22 @@ public class JoinsContext
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void processQueryJoin(QueryJoin queryJoin) throws QException
|
||||||
|
{
|
||||||
|
QTableMetaData joinTable = QContext.getQInstance().getTable(queryJoin.getJoinTable());
|
||||||
|
String tableNameOrAlias = queryJoin.getJoinTableOrItsAlias();
|
||||||
|
if(aliasToTableNameMap.containsKey(tableNameOrAlias))
|
||||||
|
{
|
||||||
|
throw (new QException("Duplicate table name or alias: " + tableNameOrAlias));
|
||||||
|
}
|
||||||
|
aliasToTableNameMap.put(tableNameOrAlias, joinTable.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for queryJoins
|
** Getter for queryJoins
|
||||||
**
|
**
|
||||||
@ -202,6 +221,82 @@ public class JoinsContext
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void ensureFilterIsRepresented(QQueryFilter filter) throws QException
|
||||||
|
{
|
||||||
|
Set<String> filterTables = new HashSet<>();
|
||||||
|
populateFilterTablesSet(filter, filterTables);
|
||||||
|
|
||||||
|
for(String filterTable : filterTables)
|
||||||
|
{
|
||||||
|
if(!aliasToTableNameMap.containsKey(filterTable) && !Objects.equals(mainTableName, filterTable))
|
||||||
|
{
|
||||||
|
for(QJoinMetaData join : CollectionUtils.nonNullMap(QContext.getQInstance().getJoins()).values())
|
||||||
|
{
|
||||||
|
QueryJoin queryJoin = null;
|
||||||
|
if(join.getLeftTable().equals(mainTableName) && join.getRightTable().equals(filterTable))
|
||||||
|
{
|
||||||
|
queryJoin = new QueryJoin().withJoinMetaData(join).withType(QueryJoin.Type.INNER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
join = join.flip();
|
||||||
|
if(join.getLeftTable().equals(mainTableName) && join.getRightTable().equals(filterTable))
|
||||||
|
{
|
||||||
|
queryJoin = new QueryJoin().withJoinMetaData(join).withType(QueryJoin.Type.INNER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(queryJoin != null)
|
||||||
|
{
|
||||||
|
this.queryJoins.add(queryJoin); // todo something else with aliases? probably.
|
||||||
|
processQueryJoin(queryJoin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void populateFilterTablesSet(QQueryFilter filter, Set<String> filterTables)
|
||||||
|
{
|
||||||
|
if(filter != null)
|
||||||
|
{
|
||||||
|
for(QFilterCriteria criteria : CollectionUtils.nonNullList(filter.getCriteria()))
|
||||||
|
{
|
||||||
|
getTableNameFromFieldNameAndAddToSet(criteria.getFieldName(), filterTables);
|
||||||
|
getTableNameFromFieldNameAndAddToSet(criteria.getOtherFieldName(), filterTables);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(QQueryFilter subFilter : CollectionUtils.nonNullList(filter.getSubFilters()))
|
||||||
|
{
|
||||||
|
populateFilterTablesSet(subFilter, filterTables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void getTableNameFromFieldNameAndAddToSet(String fieldName, Set<String> filterTables)
|
||||||
|
{
|
||||||
|
if(fieldName != null && fieldName.contains("."))
|
||||||
|
{
|
||||||
|
String tableName = fieldName.replaceFirst("\\..*", "");
|
||||||
|
filterTables.add(tableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -64,7 +64,7 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
|||||||
{
|
{
|
||||||
QTableMetaData table = aggregateInput.getTable();
|
QTableMetaData table = aggregateInput.getTable();
|
||||||
|
|
||||||
JoinsContext joinsContext = new JoinsContext(aggregateInput.getInstance(), table.getName(), aggregateInput.getQueryJoins());
|
JoinsContext joinsContext = new JoinsContext(aggregateInput.getInstance(), table.getName(), aggregateInput.getQueryJoins(), aggregateInput.getFilter());
|
||||||
String fromClause = makeFromClause(aggregateInput.getInstance(), table.getName(), joinsContext);
|
String fromClause = makeFromClause(aggregateInput.getInstance(), table.getName(), joinsContext);
|
||||||
List<String> selectClauses = buildSelectClauses(aggregateInput, joinsContext);
|
List<String> selectClauses = buildSelectClauses(aggregateInput, joinsContext);
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public class RDBMSCountAction extends AbstractRDBMSAction implements CountInterf
|
|||||||
{
|
{
|
||||||
QTableMetaData table = countInput.getTable();
|
QTableMetaData table = countInput.getTable();
|
||||||
|
|
||||||
JoinsContext joinsContext = new JoinsContext(countInput.getInstance(), countInput.getTableName(), countInput.getQueryJoins());
|
JoinsContext joinsContext = new JoinsContext(countInput.getInstance(), countInput.getTableName(), countInput.getQueryJoins(), countInput.getFilter());
|
||||||
|
|
||||||
String sql = "SELECT count(*) as record_count FROM "
|
String sql = "SELECT count(*) as record_count FROM "
|
||||||
+ makeFromClause(countInput.getInstance(), table.getName(), joinsContext);
|
+ makeFromClause(countInput.getInstance(), table.getName(), joinsContext);
|
||||||
|
@ -260,7 +260,7 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte
|
|||||||
QTableMetaData table = deleteInput.getTable();
|
QTableMetaData table = deleteInput.getTable();
|
||||||
|
|
||||||
String tableName = getTableName(table);
|
String tableName = getTableName(table);
|
||||||
JoinsContext joinsContext = new JoinsContext(deleteInput.getInstance(), table.getName(), Collections.emptyList());
|
JoinsContext joinsContext = new JoinsContext(deleteInput.getInstance(), table.getName(), Collections.emptyList(), deleteInput.getQueryFilter());
|
||||||
String whereClause = makeWhereClause(deleteInput.getInstance(), deleteInput.getSession(), table, joinsContext, filter, params);
|
String whereClause = makeWhereClause(deleteInput.getInstance(), deleteInput.getSession(), table, joinsContext, filter, params);
|
||||||
|
|
||||||
// todo sql customization - can edit sql and/or param list?
|
// todo sql customization - can edit sql and/or param list?
|
||||||
|
@ -70,7 +70,7 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
|
|||||||
|
|
||||||
StringBuilder sql = new StringBuilder("SELECT ").append(makeSelectClause(queryInput));
|
StringBuilder sql = new StringBuilder("SELECT ").append(makeSelectClause(queryInput));
|
||||||
|
|
||||||
JoinsContext joinsContext = new JoinsContext(queryInput.getInstance(), tableName, queryInput.getQueryJoins());
|
JoinsContext joinsContext = new JoinsContext(queryInput.getInstance(), tableName, queryInput.getQueryJoins(), queryInput.getFilter());
|
||||||
sql.append(" FROM ").append(makeFromClause(queryInput.getInstance(), tableName, joinsContext));
|
sql.append(" FROM ").append(makeFromClause(queryInput.getInstance(), tableName, joinsContext));
|
||||||
|
|
||||||
QQueryFilter filter = queryInput.getFilter();
|
QQueryFilter filter = queryInput.getFilter();
|
||||||
|
@ -639,6 +639,21 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testFilterFromJoinTableImplicitly() throws QException
|
||||||
|
{
|
||||||
|
QueryInput queryInput = initQueryRequest();
|
||||||
|
queryInput.setFilter(new QQueryFilter(new QFilterCriteria("personalIdCard.idNumber", QCriteriaOperator.EQUALS, "19800531")));
|
||||||
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
|
assertEquals(1, queryOutput.getRecords().size(), "Query should find 1 rows");
|
||||||
|
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -999,7 +1014,6 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
|||||||
@Test
|
@Test
|
||||||
void testRecordSecurityPrimaryKeyFieldNoFilters() throws QException
|
void testRecordSecurityPrimaryKeyFieldNoFilters() throws QException
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(TestUtils.TABLE_NAME_STORE);
|
queryInput.setTableName(TestUtils.TABLE_NAME_STORE);
|
||||||
|
|
||||||
@ -1044,7 +1058,6 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
|||||||
@Test
|
@Test
|
||||||
void testRecordSecurityForeignKeyFieldNoFilters() throws QException
|
void testRecordSecurityForeignKeyFieldNoFilters() throws QException
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||||
|
|
||||||
@ -1087,7 +1100,6 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
|||||||
@Test
|
@Test
|
||||||
void testRecordSecurityWithFilters() throws QException
|
void testRecordSecurityWithFilters() throws QException
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||||
|
|
||||||
@ -1124,7 +1136,6 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
|||||||
@Test
|
@Test
|
||||||
void testRecordSecurityWithOrQueries() throws QException
|
void testRecordSecurityWithOrQueries() throws QException
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||||
|
|
||||||
@ -1156,7 +1167,6 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
|||||||
@Test
|
@Test
|
||||||
void testRecordSecurityWithSubFilters() throws QException
|
void testRecordSecurityWithSubFilters() throws QException
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
QueryInput queryInput = new QueryInput();
|
QueryInput queryInput = new QueryInput();
|
||||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user