Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge query results on refined query when sub-results contains different headers #40

Open
wants to merge 3 commits into
base: development
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.geppetto.core.datasources.GeppettoDataSourceException;
import org.geppetto.core.model.GeppettoModelAccess;
Expand Down Expand Up @@ -120,16 +121,14 @@ public QueryResults getResults() throws GeppettoDataSourceException
boolean first = true;
for(QueryResults result : results.keySet())
{
if(finalResults.getHeader().isEmpty())
{
finalResults.getHeader().addAll(result.getHeader());
// If no ID present in one of the results, return '0 results'
if(!result.getHeader().contains(ID)){
finalResults = DatasourcesFactory.eINSTANCE.createQueryResults();
return finalResults;
}
else
{
if(!finalResults.getHeader().equals(result.getHeader()))
{
throw new GeppettoDataSourceException("Multiple queries were executed but they returned incompatible headers");
}
// If it's the first result, add the headers to 'finalResults' before continuing
if(first){
finalResults.getHeader().addAll(result.getHeader());
}
BooleanOperator o = results.get(result);
switch(o)
Expand All @@ -153,12 +152,23 @@ public QueryResults getResults() throws GeppettoDataSourceException
{
toRemove.add(id);
}
// Merge results, only for second result and beyond, and if ID in new results matches
// one in the first result.
else if(ids.get(result).contains(id) && !first){
mergeResult(result, id);
}
}
for(String id : toRemove)
{
finalResults.getResults().remove(finalIds.indexOf(id));
finalIds.remove(id);
}

// Add headers for new result to 'finalResults' list, this is done after merging results
// to avoid having a mismatch of values and headers prior to the merge.
if(!first){
finalResults.getHeader().addAll(result.getHeader());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really calling a unit test! We have this in pygeppetto: https://github.com/openworm/pygeppetto/blob/5932729e4098cd6e0f766b9fd43ff6b33fce56a2/tests/test_datasource_service.py#L33. Should test also the case with different headers from here VirtualFlyBrain/geppetto-vfb#464

}
break;
case OR:
for(String id : ids.get(result))
Expand Down Expand Up @@ -213,6 +223,40 @@ private void cache(String key, QueryResults results, List<String> ids)
cachedIds.get(key).addAll(ids);

}

/**
* This function takes new QueryResults (the 'result' parameter ) and merges it with an existing QueryResult in the
* 'finalResults' list. The match happens using the 'id' parameter, if no match is present nothing is done.
*
* @param result - The new result to be merged into 'finalResults'.
* @param id - The id of the existing QueryResult found in 'finalResults' list that matches the ID of the new QueryResult
*/
private void mergeResult(QueryResults result, String id){
// Extract index from 'result' list
int resultIndex = ids.get(result).indexOf(id);
// Extract the ID column value from the new QueryResult that matched the 'id' of the existing result
String resultID =
((SerializableQueryResult) result.getResults().get(resultIndex)).getValues().get(result.getHeader().indexOf(ID));
// Extract the existing matching QueryResult in 'finalResults', this belongs to previous QueryResult(s) already added
SerializableQueryResult existingResult =
(SerializableQueryResult) finalResults.getResults().get(finalIds.indexOf(resultID));
// Extract column headers in new QueryResult
EList<String> newResultHeaders = result.getHeader();
// Extract column headers from existing QueryResult already added to 'finalResults' list
EList<String> finalResultsHeaders = finalResults.getHeader();
// Extract column values for new QueryResult
EList<String> resultValues = ((SerializableQueryResult) result.getResults().get(resultIndex)).getValues();
// Loop through headers of new QueryResult, if a header is not present in 'finalResults', add its value
// to the matching existing QueryResult in the final list.
for(String header : newResultHeaders){
int indexFinalHeaders = finalResultsHeaders.indexOf(header);
int newResultIndexHeader = newResultHeaders.indexOf(header);
// If a header is not present in 'finalResults' list, we add the new column value to the existing QueryResult.
if(indexFinalHeaders==-1){
existingResult.getValues().add(resultValues.get(newResultIndexHeader));
}
}
}

/**
* @param query
Expand Down