use of com.bakdata.conquery.models.datasets.Column in project conquery by bakdata.
the class CBlock method calculateEntityDateIndices.
/**
* For every included entity, calculate min and max and store them as statistics in the CBlock.
*
* @implNote This is an unrolled implementation of {@link CDateRange#spanClosed(CDateRange)}.
*/
private static CDateRange[] calculateEntityDateIndices(Bucket bucket, int bucketSize) {
CDateRange[] spans = new CDateRange[bucketSize];
Arrays.fill(spans, CDateRange.all());
// First initialize to an illegal state that's easy on our comparisons
Table table = bucket.getTable();
for (Column column : table.getColumns()) {
if (!column.getType().isDateCompatible()) {
continue;
}
for (int entity : bucket.getEntities()) {
final int index = bucket.getEntityIndex(entity);
final int end = bucket.getEntityEnd(entity);
// We unroll spanClosed for the whole bucket/entity, this avoids costly
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int event = bucket.getEntityStart(entity); event < end; event++) {
if (!bucket.has(event, column)) {
continue;
}
CDateRange range = bucket.getAsDateRange(event, column);
if (range.hasLowerBound()) {
final int minValue = range.getMinValue();
max = Math.max(max, minValue);
min = Math.min(min, minValue);
}
if (range.hasUpperBound()) {
final int maxValue = range.getMaxValue();
max = Math.max(max, maxValue);
min = Math.min(min, maxValue);
}
}
spans[index] = createClosed(max, min, spans[index]);
}
}
return spans;
}
use of com.bakdata.conquery.models.datasets.Column in project conquery by bakdata.
the class RequiredColumn method toColumn.
public Column toColumn(Table table, CentralRegistry storage) {
Column col = new Column();
col.setName(name);
col.setType(type);
col.setSharedDictionary(sharedDictionary);
col.setTable(table);
if (!Strings.isNullOrEmpty(secondaryId)) {
final SecondaryIdDescription description = storage.resolve(new SecondaryIdDescriptionId(table.getDataset().getId(), secondaryId));
col.setSecondaryId(description);
}
return col;
}
use of com.bakdata.conquery.models.datasets.Column in project conquery by bakdata.
the class TableExportQueryPlan method execute.
@Override
public Optional<MultilineEntityResult> execute(QueryExecutionContext ctx, Entity entity) {
Optional<? extends EntityResult> result = subPlan.execute(ctx, entity);
if (result.isEmpty() || tables.isEmpty()) {
return Optional.empty();
}
List<Object[]> results = new ArrayList<>();
final int totalColumns = positions.values().stream().mapToInt(i -> i).max().getAsInt() + 1;
for (TableExportDescription exportDescription : tables) {
for (Bucket bucket : ctx.getEntityBucketsForTable(entity, exportDescription.getTable())) {
int entityId = entity.getId();
if (!bucket.containsEntity(entityId)) {
continue;
}
int start = bucket.getEntityStart(entityId);
int end = bucket.getEntityEnd(entityId);
for (int event = start; event < end; event++) {
// Export Full-table if it has no validity date.
if (exportDescription.getValidityDateColumn() != null && !bucket.eventIsContainedIn(event, exportDescription.getValidityDateColumn(), CDateSet.create(dateRange))) {
continue;
}
Object[] entry = new Object[totalColumns];
for (Column column : exportDescription.getTable().getColumns()) {
if (!bucket.has(event, column)) {
continue;
}
if (column.equals(exportDescription.getValidityDateColumn())) {
entry[0] = List.of(bucket.getAsDateRange(event, column));
} else {
entry[positions.get(column)] = bucket.createScriptValue(event, column);
}
}
results.add(entry);
}
}
}
return Optional.of(new MultilineEntityResult(entity.getId(), results));
}
use of com.bakdata.conquery.models.datasets.Column in project conquery by bakdata.
the class TableExportQuery method resolve.
@Override
public void resolve(QueryResolveContext context) {
query.resolve(context);
// First is dates
AtomicInteger currentPosition = new AtomicInteger(1);
positions = new HashMap<>();
Map<SecondaryIdDescription, Integer> secondaryIdPositions = new HashMap<>();
// SecondaryIds are pulled to the front and grouped over all tables
tables.stream().map(cqUnfilteredTable -> cqUnfilteredTable.getTable().getTable().getColumns()).flatMap(Arrays::stream).map(Column::getSecondaryId).filter(Objects::nonNull).distinct().sorted(Comparator.comparing(SecondaryIdDescription::getLabel)).forEach(secondaryId -> secondaryIdPositions.put(secondaryId, currentPosition.getAndIncrement()));
for (CQUnfilteredTable table : tables) {
Connector connector = table.getTable();
final Column validityDateColumn = findValidityDateColumn(connector, table.getDateColumn());
if (validityDateColumn != null) {
positions.putIfAbsent(validityDateColumn, 0);
}
// Set column positions, set SecondaryId positions to precomputed ones.
for (Column column : connector.getTable().getColumns()) {
positions.computeIfAbsent(column, col -> col.getSecondaryId() != null ? secondaryIdPositions.get(col.getSecondaryId()) : currentPosition.getAndIncrement());
}
}
resultInfos = createResultInfos(currentPosition.get(), secondaryIdPositions, positions);
}
use of com.bakdata.conquery.models.datasets.Column 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;
}
Aggregations