use of com.bakdata.conquery.models.common.CDateSet in project conquery by bakdata.
the class CQConcept method createQueryPlan.
@Override
public QPNode createQueryPlan(QueryPlanContext context, ConceptQueryPlan plan) {
final List<Aggregator<?>> conceptAggregators = createAggregators(plan, selects);
List<QPNode> tableNodes = new ArrayList<>();
for (CQTable table : tables) {
List<FilterNode<?>> filters = table.getFilters().stream().map(FilterValue::createNode).collect(Collectors.toList());
// add filter to children
List<Aggregator<?>> aggregators = new ArrayList<>();
aggregators.addAll(conceptAggregators);
final List<Aggregator<?>> connectorAggregators = createAggregators(plan, table.getSelects());
// Exists aggregators hold a reference to their parent FiltersNode so they need to be treated separately.
// They also don't need aggregation as they simply imitate their reference.
List<ExistsAggregator> existsAggregators = connectorAggregators.stream().filter(ExistsAggregator.class::isInstance).map(ExistsAggregator.class::cast).collect(Collectors.toList());
aggregators.addAll(connectorAggregators);
aggregators.removeIf(ExistsAggregator.class::isInstance);
List<Aggregator<CDateSet>> eventDateUnionAggregators = aggregateEventDates ? List.of(new EventDateUnionAggregator(Set.of(table.getConnector().getTable()))) : Collections.emptyList();
aggregators.addAll(eventDateUnionAggregators);
final QPNode filtersNode = getConcept().createConceptQuery(context, filters, aggregators, eventDateUnionAggregators);
// Link up the ExistsAggregators to the node
existsAggregators.forEach(agg -> agg.setReference(filtersNode));
// Select if matching secondaryId available
final boolean hasSelectedSecondaryId = Arrays.stream(table.getConnector().getTable().getColumns()).map(Column::getSecondaryId).filter(Objects::nonNull).anyMatch(o -> Objects.equals(context.getSelectedSecondaryId(), o));
final Column validityDateColumn = selectValidityDateColumn(table);
final ConceptNode node = new ConceptNode(// TODO Don't set validity node, when no validity column exists. See workaround for this and remove it: https://github.com/bakdata/conquery/pull/1362
new ValidityDateNode(validityDateColumn, filtersNode), elements, table, // if the node is excluded, don't pass it into the Node.
!excludeFromSecondaryId && hasSelectedSecondaryId ? context.getSelectedSecondaryId() : null);
tableNodes.add(node);
}
// We always merge on concept level
final QPNode outNode = OrNode.of(tableNodes, aggregateEventDates ? DateAggregationAction.MERGE : DateAggregationAction.BLOCK);
// Link concept-level Exists-select to outer node.
conceptAggregators.stream().filter(aggregator -> aggregator instanceof ExistsAggregator).forEach(aggregator -> ((ExistsAggregator) aggregator).setReference(outNode));
return outNode;
}
use of com.bakdata.conquery.models.common.CDateSet in project conquery by bakdata.
the class FormQueryPlan method execute.
@Override
public Optional<MultilineEntityResult> execute(QueryExecutionContext ctx, Entity entity) {
if (!isOfInterest(entity)) {
// If the entity is not covered by the query generate a basic result line with constants but without features
return Optional.of(createResultForNotContained(entity, null));
}
List<Object[]> resultValues = new ArrayList<>(dateContexts.size());
for (DateContext dateContext : dateContexts) {
CDateSet dateRestriction = CDateSet.create(ctx.getDateRestriction());
dateRestriction.retainAll(dateContext.getDateRange());
// Reference the dates per sub-query, don't accumulate dates of all sub-queries
QueryExecutionContext innerContext = QueryUtils.determineDateAggregatorForContext(ctx, features::getValidityDateAggregator).withDateRestriction(dateRestriction);
features.init(ctx, entity);
Optional<SinglelineEntityResult> subResult = features.execute(innerContext, entity);
if (subResult.isEmpty()) {
resultValues.addAll(createResultForNotContained(entity, dateContext).listResultLines());
continue;
}
resultValues.addAll(ResultModifier.modify(subResult.get(), ResultModifier.existAggValuesSetterFor(features.getAggregators(), OptionalInt.of(0)).unaryAndThen(v -> addConstants(v, dateContext))).listResultLines());
}
return Optional.of(new MultilineEntityResult(entity.getId(), resultValues));
}
use of com.bakdata.conquery.models.common.CDateSet in project conquery by bakdata.
the class CDateSetDeserializer method deserialize.
@Override
public CDateSet deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
if (p.currentToken() == JsonToken.START_ARRAY) {
int[][] ints = p.readValueAs(int[][].class);
CDateSet set = CDateSet.create();
for (int i = 0; i < ints.length; i++) {
set.add(CDateRange.of(ints[i][0], ints[i][1]));
}
return set;
}
if (p.currentToken() == JsonToken.VALUE_STRING) {
return formats.parseToCDateSet(p.readValueAs(String.class));
}
return (CDateSet) ctxt.handleUnexpectedToken(CDateSet.class, p.currentToken(), p, "can't deserialize CDateSet");
}
use of com.bakdata.conquery.models.common.CDateSet in project conquery by bakdata.
the class CQExternal method readDates.
/**
* For each row try and collect all dates.
*
* @return Row -> Dates
*/
private static CDateSet[] readDates(String[][] values, List<String> format, DateReader dateReader, FrontendConfig.UploadConfig queryUpload) {
final CDateSet[] out = new CDateSet[values.length];
List<DateFormat> dateFormats = format.stream().map(queryUpload::resolveDateFormat).collect(Collectors.toList());
// If no format provided, put empty dates into output.
if (dateFormats.stream().allMatch(Objects::isNull)) {
// Initialize empty
for (int row = 0; row < values.length; row++) {
out[row] = CDateSet.create();
}
return out;
}
for (int row = 1; row < values.length; row++) {
try {
final CDateSet dates = CDateSet.create();
// Collect all specified dates into a single set.
for (int col = 0; col < dateFormats.size(); col++) {
final DateFormat dateFormat = dateFormats.get(col);
if (dateFormat == null) {
continue;
}
dateFormat.readDates(values[row][col], dateReader, dates);
}
if (dates.isEmpty()) {
continue;
}
if (out[row] == null) {
out[row] = CDateSet.create();
}
out[row].addAll(dates);
} catch (Exception e) {
log.warn("Failed to parse Date from {}", row, e);
}
}
return out;
}
use of com.bakdata.conquery.models.common.CDateSet in project conquery by bakdata.
the class EntityDateQueryPlan method execute.
@Override
public Optional<MultilineEntityResult> execute(QueryExecutionContext ctx, Entity entity) {
// Don't set the query date aggregator here because the subqueries should set their aggregator independently
// Execute the prerequisite query
Optional<EntityResult> preResult = query.execute(ctx, entity);
if (preResult.isEmpty()) {
return Optional.empty();
}
Optional<DateAggregator> validityDateAggregator = query.getValidityDateAggregator();
if (validityDateAggregator.isEmpty()) {
return Optional.empty();
}
final CDateSet aggregationResult = validityDateAggregator.get().createAggregationResult();
aggregationResult.retainAll(dateRestriction);
// Generate DateContexts in the provided resolutions
List<DateContext> contexts = new ArrayList<>();
for (CDateRange range : aggregationResult.asRanges()) {
contexts.addAll(DateContext.generateAbsoluteContexts(range, resolutionsAndAlignments));
}
FormQueryPlan resolutionQuery = new FormQueryPlan(contexts, features);
return resolutionQuery.execute(ctx, entity);
}
Aggregations