diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/DateAggregationContext.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/DateAggregationContext.java index ff5c7ec452..b3e98cd578 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/DateAggregationContext.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/DateAggregationContext.java @@ -22,7 +22,7 @@ class DateAggregationContext implements Context { Field primaryColumn; List carryThroughSelects; - DateAggregationTables dateAggregationTables; + DateAggregationTables dateAggregationTables; DateAggregationDates dateAggregationDates; @Builder.Default Map> intervalMergeSteps = new HashMap<>(); diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/IntersectAggregationAction.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/IntersectAggregationAction.java index f4f582c526..bd15287d4e 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/IntersectAggregationAction.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/IntersectAggregationAction.java @@ -46,7 +46,7 @@ public ColumnDateRange getOverlapValidityDate(DateAggregationDates dateAggregati @Override public List getIntermediateTableSelects(DateAggregationDates dateAggregationDates, List carryThroughSelects) { - List nulledRangeStartAndEnd = + List> nulledRangeStartAndEnd = Stream.of( DSL.inline(null, Date.class).as(DateAggregationCte.RANGE_START), DSL.inline(null, Date.class).as(DateAggregationCte.RANGE_END) diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/RowNumberCte.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/RowNumberCte.java index 6d2b5d9c41..b3387fdae6 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/RowNumberCte.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/RowNumberCte.java @@ -35,7 +35,7 @@ protected QueryStep.QueryStepBuilder convertStep(DateAggregationContext context) .as(ROW_NUMBER_FIELD_NAME); ArrayList selects = new ArrayList<>(context.getCarryThroughSelects()); - selects.add(new FieldWrapper(rowNumber)); + selects.add(new FieldWrapper<>(rowNumber)); Selects rowNumberSelects = Selects.builder() .primaryColumn(primaryColumn) diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/SqlAggregationAction.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/SqlAggregationAction.java index b83ecb55b8..f0d7300960 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/SqlAggregationAction.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/aggregation/SqlAggregationAction.java @@ -14,7 +14,7 @@ */ interface SqlAggregationAction { - DateAggregationTables tableNames(NameGenerator nameGenerator); + DateAggregationTables tableNames(NameGenerator nameGenerator); List dateAggregationCtes(); diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationFilterCte.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationFilterCte.java index f0b3ca5277..2e2fededac 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationFilterCte.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationFilterCte.java @@ -1,12 +1,10 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept; import java.util.List; -import java.util.stream.Collectors; import com.bakdata.conquery.sql.conversion.model.QueryStep; import com.bakdata.conquery.sql.conversion.model.Selects; import com.bakdata.conquery.sql.conversion.model.filter.FilterCondition; -import com.bakdata.conquery.sql.conversion.model.select.ExistsSqlSelect; import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; import org.jooq.Condition; @@ -34,11 +32,10 @@ public QueryStep.QueryStepBuilder convertStep(ConceptCteContext conceptCteContex private List getForAggregationFilterSelects(ConceptCteContext conceptCteContext) { return conceptCteContext.getSelects().stream() - .flatMap(sqlSelects -> sqlSelects.getForFinalStep().stream()) - // TODO: EXISTS edge case is only in a concepts final select statement and has no predecessor selects - .filter(conquerySelect -> !(conquerySelect instanceof ExistsSqlSelect)) + .flatMap(sqlSelects -> sqlSelects.getFinalSelects().stream()) + .filter(sqlSelect -> !sqlSelect.isUniversal()) .distinct() - .collect(Collectors.toList()); + .toList(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationSelectCte.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationSelectCte.java index afe40b8368..9a07cecf03 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationSelectCte.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/AggregationSelectCte.java @@ -1,7 +1,6 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept; import java.util.List; -import java.util.stream.Collectors; import com.bakdata.conquery.sql.conversion.model.QueryStep; import com.bakdata.conquery.sql.conversion.model.Selects; @@ -13,9 +12,9 @@ class AggregationSelectCte extends ConceptCte { public QueryStep.QueryStepBuilder convertStep(ConceptCteContext conceptCteContext) { List requiredInAggregationFilterStep = conceptCteContext.allConceptSelects() - .flatMap(sqlSelects -> sqlSelects.getForAggregationSelectStep().stream()) + .flatMap(sqlSelects -> sqlSelects.getAggregationSelects().stream()) .distinct() - .collect(Collectors.toList()); + .toList(); Selects aggregationSelectSelects = Selects.builder() .primaryColumn(conceptCteContext.getPrimaryColumn()) diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/CQConceptConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/CQConceptConverter.java index c25594e1c3..8f39f96fb9 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/CQConceptConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/CQConceptConverter.java @@ -19,7 +19,7 @@ import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; import com.bakdata.conquery.sql.conversion.model.QueryStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; import com.bakdata.conquery.sql.conversion.model.filter.ConditionUtil; import com.bakdata.conquery.sql.conversion.model.filter.FilterType; import com.bakdata.conquery.sql.conversion.model.filter.Filters; @@ -91,10 +91,10 @@ private ConceptCteContext createConceptCteContext(CQConcept node, ConversionCont ConceptTables conceptTables = new ConceptTables(conceptLabel, requiredSteps, tableName, context.getNameGenerator()); // convert filters - Stream conceptFilters = table.getFilters().stream() - .map(filterValue -> this.filterValueConversions.convert(filterValue, context, conceptTables)); - Stream dateRestrictionFilter = getDateRestriction(context, validityDateSelect).stream(); - List allFilters = Stream.concat(conceptFilters, dateRestrictionFilter).toList(); + Stream conceptFilters = table.getFilters().stream() + .map(filterValue -> this.filterValueConversions.convert(filterValue, context, conceptTables)); + Stream dateRestrictionFilter = getDateRestriction(context, validityDateSelect).stream(); + List allFilters = Stream.concat(conceptFilters, dateRestrictionFilter).toList(); // convert selects SelectContext selectContext = new SelectContext(context, node, conceptLabel, validityDateSelect, conceptTables); @@ -146,7 +146,7 @@ private Optional convertValidityDate( return Optional.of(validityDate); } - private Optional getDateRestriction(ConversionContext context, Optional validityDate) { + private Optional getDateRestriction(ConversionContext context, Optional validityDate) { if (!dateRestrictionApplicable(context.dateRestrictionActive(), validityDate)) { return Optional.empty(); @@ -162,8 +162,8 @@ private Optional getDateRestriction(ConversionContext context, Op Condition dateRestrictionCondition = this.functionProvider.dateRestriction(dateRestriction, validityDate.get()); - return Optional.of(new ConceptFilter( - SqlSelects.builder().forPreprocessingStep(dateRestrictionSelects).build(), + return Optional.of(new SqlFilters( + SqlSelects.builder().preprocessingSelects(dateRestrictionSelects).build(), Filters.builder().event(List.of(ConditionUtil.wrap(dateRestrictionCondition, FilterType.EVENT))).build() )); } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/ConceptCteContext.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/ConceptCteContext.java index 451438292e..6ad120e9ca 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/ConceptCteContext.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/ConceptCteContext.java @@ -11,7 +11,7 @@ import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; import com.bakdata.conquery.sql.conversion.model.NameGenerator; import com.bakdata.conquery.sql.conversion.model.QueryStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; import lombok.Builder; import lombok.Value; @@ -28,7 +28,7 @@ class ConceptCteContext implements Context { Optional validityDate; boolean isExcludedFromDateAggregation; List selects; - List filters; + List filters; ConceptTables conceptTables; @With QueryStep previous; @@ -38,7 +38,7 @@ class ConceptCteContext implements Context { */ public Stream allConceptSelects() { return Stream.concat( - getFilters().stream().map(ConceptFilter::getSelects), + getFilters().stream().map(SqlFilters::getSelects), getSelects().stream() ); } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/EventFilterCte.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/EventFilterCte.java index 6bd0e5f3c8..cd1846c031 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/EventFilterCte.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/EventFilterCte.java @@ -1,7 +1,9 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept; import java.util.List; +import java.util.Optional; +import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; import com.bakdata.conquery.sql.conversion.model.QueryStep; import com.bakdata.conquery.sql.conversion.model.Selects; import com.bakdata.conquery.sql.conversion.model.filter.FilterCondition; @@ -12,34 +14,39 @@ class EventFilterCte extends ConceptCte { @Override public QueryStep.QueryStepBuilder convertStep(ConceptCteContext conceptCteContext) { - - String predecessorTableName = conceptCteContext.getConceptTables().getPredecessor(cteStep()); - Selects eventFilterSelects = Selects.builder() - .primaryColumn(conceptCteContext.getPrimaryColumn()) - .validityDate(conceptCteContext.getValidityDate()) - .sqlSelects(getForAggregationSelectStep(conceptCteContext)) - .build() - .qualify(predecessorTableName); - + Selects eventFilterSelects = getEventFilterSelects(conceptCteContext); List eventFilterConditions = conceptCteContext.getFilters().stream() .flatMap(conceptFilter -> conceptFilter.getFilters().getEvent().stream()) .map(FilterCondition::filterCondition) .toList(); - return QueryStep.builder() .selects(eventFilterSelects) .conditions(eventFilterConditions); } - private static List getForAggregationSelectStep(ConceptCteContext conceptCteContext) { - return conceptCteContext.allConceptSelects() - .flatMap(sqlSelects -> sqlSelects.getForAggregationSelectStep().stream()) - .toList(); - } - @Override public ConceptCteStep cteStep() { return ConceptCteStep.EVENT_FILTER; } + private Selects getEventFilterSelects(ConceptCteContext conceptCteContext) { + String predecessorTableName = conceptCteContext.getConceptTables().getPredecessor(cteStep()); + + Optional validityDate = conceptCteContext.getValidityDate(); + if (validityDate.isPresent()) { + validityDate = Optional.of(validityDate.get().qualify(predecessorTableName)); + } + + List sqlSelects = conceptCteContext.allConceptSelects() + .flatMap(selects -> selects.getAggregationSelects().stream()) + .map(sqlSelect -> sqlSelect.createColumnReference(predecessorTableName)) + .toList(); + + return Selects.builder() + .primaryColumn(conceptCteContext.getPrimaryColumn()) + .validityDate(validityDate) + .sqlSelects(sqlSelects) + .build(); + } + } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/FinalConceptCte.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/FinalConceptCte.java index c672621a3a..098dc1897a 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/FinalConceptCte.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/FinalConceptCte.java @@ -21,7 +21,7 @@ class FinalConceptCte extends ConceptCte { protected QueryStep.QueryStepBuilder convertStep(ConceptCteContext conceptCteContext) { List forFinalStep = conceptCteContext.getSelects().stream() - .flatMap(sqlSelects -> sqlSelects.getForFinalStep().stream()) + .flatMap(sqlSelects -> sqlSelects.getFinalSelects().stream()) .distinct() .toList(); diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/PreprocessingCte.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/PreprocessingCte.java index 9332a5e62a..f0c80cc73a 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/PreprocessingCte.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/PreprocessingCte.java @@ -11,7 +11,7 @@ class PreprocessingCte extends ConceptCte { public QueryStep.QueryStepBuilder convertStep(ConceptCteContext conceptCteContext) { List forPreprocessing = conceptCteContext.allConceptSelects() - .flatMap(sqlSelects -> sqlSelects.getForPreprocessingStep().stream()) + .flatMap(sqlSelects -> sqlSelects.getPreprocessingSelects().stream()) .distinct() .toList(); diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/BigMultiSelectFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/BigMultiSelectFilterConverter.java index c51d0f8ee3..5ad7dc6b58 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/BigMultiSelectFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/BigMultiSelectFilterConverter.java @@ -4,12 +4,12 @@ import com.bakdata.conquery.models.datasets.concepts.filters.specific.BigMultiSelectFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; public class BigMultiSelectFilterConverter implements FilterConverter { @Override - public ConceptFilter convert(BigMultiSelectFilter bigMultiSelectFilter, FilterContext context) { + public SqlFilters convert(BigMultiSelectFilter bigMultiSelectFilter, FilterContext context) { return SelectFilterUtil.convert(bigMultiSelectFilter, context, context.getValue()); } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/CountFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/CountFilterConverter.java index facae2fb80..0fe49a39eb 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/CountFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/CountFilterConverter.java @@ -1,50 +1,18 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.filter; -import java.util.List; import java.util.Set; import com.bakdata.conquery.models.common.Range; import com.bakdata.conquery.models.datasets.concepts.filters.specific.CountFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; -import com.bakdata.conquery.sql.conversion.model.filter.CountCondition; -import com.bakdata.conquery.sql.conversion.model.filter.Filters; -import com.bakdata.conquery.sql.conversion.model.select.CountSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import org.jooq.Field; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; +import com.bakdata.conquery.sql.conversion.model.select.CountSqlAggregator; public class CountFilterConverter implements FilterConverter { @Override - public ConceptFilter convert(CountFilter countFilter, FilterContext context) { - - SqlSelect rootSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - countFilter.getColumn().getName(), - Object.class - ); - - Field qualifiedRootSelect = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - CountSqlSelect countSqlSelect = new CountSqlSelect( - qualifiedRootSelect, - context.getNameGenerator().selectName(countFilter), - CountSqlSelect.CountType.fromBoolean(countFilter.isDistinct()) - ); - - Field qualifiedCountGroupBy = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_FILTER, countSqlSelect.aliased()); - CountCondition countFilterCondition = new CountCondition(qualifiedCountGroupBy, context.getValue()); - - return new ConceptFilter( - SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(countSqlSelect)) - .build(), - Filters.builder() - .group(List.of(countFilterCondition)) - .build() - ); + public SqlFilters convert(CountFilter countFilter, FilterContext context) { + return CountSqlAggregator.create(countFilter, context).getSqlFilters(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/DateDistanceFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/DateDistanceFilterConverter.java index f97aa0c8a9..3fe3bc19ae 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/DateDistanceFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/DateDistanceFilterConverter.java @@ -1,17 +1,12 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.filter; -import java.util.List; import java.util.Set; import com.bakdata.conquery.models.common.Range; import com.bakdata.conquery.models.datasets.concepts.filters.specific.DateDistanceFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; -import com.bakdata.conquery.sql.conversion.model.filter.DateDistanceCondition; -import com.bakdata.conquery.sql.conversion.model.filter.FilterCondition; -import com.bakdata.conquery.sql.conversion.model.filter.Filters; -import com.bakdata.conquery.sql.conversion.model.select.DateDistanceSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; +import com.bakdata.conquery.sql.conversion.model.select.DateDistanceSqlAggregator; import com.bakdata.conquery.sql.conversion.supplier.DateNowSupplier; public class DateDistanceFilterConverter implements FilterConverter { @@ -23,31 +18,8 @@ public DateDistanceFilterConverter(DateNowSupplier dateNowSupplier) { } @Override - public ConceptFilter convert(DateDistanceFilter dateDistanceFilter, FilterContext context) { - - DateDistanceSqlSelect dateDistanceSqlSelect = new DateDistanceSqlSelect( - dateNowSupplier, - dateDistanceFilter.getTimeUnit(), - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - dateDistanceFilter.getColumn(), - dateDistanceFilter.getName(), - context.getParentContext().getDateRestrictionRange(), - context.getParentContext().getSqlDialect().getFunctionProvider() - ); - - FilterCondition dateDistanceCondition = new DateDistanceCondition( - context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.EVENT_FILTER, dateDistanceSqlSelect.aliased()), - context.getValue() - ); - - return new ConceptFilter( - SqlSelects.builder() - .forPreprocessingStep(List.of(dateDistanceSqlSelect)) - .build(), - Filters.builder() - .event(List.of(dateDistanceCondition)) - .build() - ); + public SqlFilters convert(DateDistanceFilter dateDistanceFilter, FilterContext context) { + return DateDistanceSqlAggregator.create(dateDistanceFilter, context, dateNowSupplier).getSqlFilters(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConversions.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConversions.java index 9ab2bbe9e0..fb44920356 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConversions.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConversions.java @@ -4,9 +4,9 @@ import com.bakdata.conquery.models.datasets.concepts.filters.Filter; import com.bakdata.conquery.sql.conversion.Conversions; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; -public class FilterConversions extends Conversions, ConceptFilter, FilterContext> { +public class FilterConversions extends Conversions, SqlFilters, FilterContext> { public FilterConversions(List> converters) { super(converters); diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConverter.java index da66ce9035..3aa2359797 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterConverter.java @@ -2,8 +2,8 @@ import com.bakdata.conquery.models.datasets.concepts.filters.Filter; import com.bakdata.conquery.sql.conversion.Converter; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; -public interface FilterConverter> extends Converter> { +public interface FilterConverter> extends Converter> { } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterValueConversions.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterValueConversions.java index 253cb072ef..0d996f72b4 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterValueConversions.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/FilterValueConversions.java @@ -6,7 +6,7 @@ import com.bakdata.conquery.sql.conversion.cqelement.ConversionContext; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; import com.bakdata.conquery.sql.conversion.model.SqlTables; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; public class FilterValueConversions { private final FilterConversions filterConversions; @@ -15,10 +15,10 @@ public FilterValueConversions(FilterConversions filterConversions) { this.filterConversions = filterConversions; } - public ConceptFilter convert(FilterValue filterValue, ConversionContext context, SqlTables conceptTables) { - ConceptFilter convert = this.filterConversions.convert(filterValue.getFilter(), new FilterContext<>(filterValue.getValue(), context, conceptTables)); + public SqlFilters convert(FilterValue filterValue, ConversionContext context, SqlTables conceptTables) { + SqlFilters convert = this.filterConversions.convert(filterValue.getFilter(), new FilterContext<>(filterValue.getValue(), context, conceptTables)); if (context.isNegation()) { - return new ConceptFilter(convert.getSelects(), convert.getFilters().negated()); + return new SqlFilters(convert.getSelects(), convert.getFilters().negated()); } return convert; } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/MultiSelectFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/MultiSelectFilterConverter.java index 7cca2ba098..597e2119e9 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/MultiSelectFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/MultiSelectFilterConverter.java @@ -4,12 +4,12 @@ import com.bakdata.conquery.models.datasets.concepts.filters.specific.MultiSelectFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; public class MultiSelectFilterConverter implements FilterConverter { @Override - public ConceptFilter convert(MultiSelectFilter multiSelectFilter, FilterContext context) { + public SqlFilters convert(MultiSelectFilter multiSelectFilter, FilterContext context) { return SelectFilterUtil.convert(multiSelectFilter, context, context.getValue()); } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/NumberFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/NumberFilterConverter.java index 4514b341a4..8541d8d728 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/NumberFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/NumberFilterConverter.java @@ -9,7 +9,7 @@ import com.bakdata.conquery.models.datasets.concepts.filters.specific.NumberFilter; import com.bakdata.conquery.models.events.MajorTypeId; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; import com.bakdata.conquery.sql.conversion.model.filter.Filters; import com.bakdata.conquery.sql.conversion.model.filter.NumberCondition; import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; @@ -21,7 +21,7 @@ public class NumberFilterConverter implements FilterConverter CLASS = NumberFilter.class; @Override - public ConceptFilter convert(NumberFilter> numberFilter, FilterContext> context) { + public SqlFilters convert(NumberFilter> numberFilter, FilterContext> context) { Class numberClass = NumberMapUtil.NUMBER_MAP.get(numberFilter.getColumn().getType()); @@ -36,9 +36,9 @@ public ConceptFilter convert(NumberFilter> numberFil IRange filterValue = prepareFilterValue(numberFilter, context); NumberCondition condition = new NumberCondition(eventFilterCtePredecessor, filterValue); - return new ConceptFilter( + return new SqlFilters( SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) + .preprocessingSelects(List.of(rootSelect)) .build(), Filters.builder() .event(List.of(condition)) diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SelectFilterUtil.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SelectFilterUtil.java index f3bc6421ce..be9cf10bb7 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SelectFilterUtil.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SelectFilterUtil.java @@ -4,19 +4,18 @@ import com.bakdata.conquery.models.datasets.concepts.filters.specific.SelectFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; import com.bakdata.conquery.sql.conversion.model.filter.FilterCondition; import com.bakdata.conquery.sql.conversion.model.filter.Filters; import com.bakdata.conquery.sql.conversion.model.filter.MultiSelectCondition; import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; class SelectFilterUtil { - public static ConceptFilter convert(SelectFilter selectFilter, FilterContext context, String[] values) { + public static SqlFilters convert(SelectFilter selectFilter, FilterContext context, String[] values) { - SqlSelect rootSelect = new ExtractingSqlSelect<>( + ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>( context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), selectFilter.getColumn().getName(), String.class @@ -28,9 +27,9 @@ public static ConceptFilter convert(SelectFilter selectFilter, FilterCont context.getParentContext().getSqlDialect().getFunctionProvider() ); - return new ConceptFilter( + return new SqlFilters( SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) + .preprocessingSelect(rootSelect) .build(), Filters.builder() .event(List.of(condition)) diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SingleSelectFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SingleSelectFilterConverter.java index 451aa33944..76978aa831 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SingleSelectFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SingleSelectFilterConverter.java @@ -4,12 +4,12 @@ import com.bakdata.conquery.models.datasets.concepts.filters.specific.SingleSelectFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; public class SingleSelectFilterConverter implements FilterConverter { @Override - public ConceptFilter convert(SingleSelectFilter singleSelect, FilterContext context) { + public SqlFilters convert(SingleSelectFilter singleSelect, FilterContext context) { return SelectFilterUtil.convert(singleSelect, context, new String[]{context.getValue()}); } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SumFilterConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SumFilterConverter.java index ad542f5e02..8ae4c1aa32 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SumFilterConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/filter/SumFilterConverter.java @@ -1,52 +1,20 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.filter; -import java.util.List; import java.util.Set; import com.bakdata.conquery.models.common.IRange; import com.bakdata.conquery.models.datasets.concepts.filters.specific.SumFilter; import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.filter.ConceptFilter; -import com.bakdata.conquery.sql.conversion.model.filter.Filters; -import com.bakdata.conquery.sql.conversion.model.filter.SumCondition; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import com.bakdata.conquery.sql.conversion.model.select.SumSqlSelect; -import org.jooq.Field; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; +import com.bakdata.conquery.sql.conversion.model.select.SumSqlAggregator; public class SumFilterConverter implements FilterConverter, SumFilter>> { private static final Class CLASS = SumFilter.class; @Override - public ConceptFilter convert(SumFilter> sumFilter, FilterContext> context) { - - // TODO(tm): convert getSubtractColumn and getDistinctByColumn - Class numberClass = NumberMapUtil.NUMBER_MAP.get(sumFilter.getColumn().getType()); - ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - sumFilter.getColumn().getName(), - numberClass - ); - - Field qualifiedRootSelect = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - String alias = context.getNameGenerator().selectName(sumFilter); - SumSqlSelect sumSqlSelect = new SumSqlSelect(qualifiedRootSelect, alias); - - Field - qualifiedSumGroupBy = - context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_FILTER, sumSqlSelect.aliased()); - SumCondition sumFilterCondition = new SumCondition(qualifiedSumGroupBy, context.getValue()); - - return new ConceptFilter( - SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(sumSqlSelect)) - .build(), - Filters.builder() - .group(List.of(sumFilterCondition)) - .build() - ); + public SqlFilters convert(SumFilter> sumFilter, FilterContext> context) { + return SumSqlAggregator.create(sumFilter, context).getSqlFilters(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/CountSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/CountSelectConverter.java index 4e47f11bfb..6f09319040 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/CountSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/CountSelectConverter.java @@ -1,42 +1,14 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.connector.specific.CountSelect; -import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.select.CountSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; +import com.bakdata.conquery.sql.conversion.model.select.CountSqlAggregator; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import org.jooq.Field; public class CountSelectConverter implements SelectConverter { @Override public SqlSelects convert(CountSelect countSelect, SelectContext context) { - - SqlSelect rootSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - countSelect.getColumn().getName(), - Object.class - ); - - Field qualifiedRootSelect = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - String alias = context.getNameGenerator().selectName(countSelect); - CountSqlSelect.CountType countType = CountSqlSelect.CountType.fromBoolean(countSelect.isDistinct()); - CountSqlSelect countSqlSelect = new CountSqlSelect(qualifiedRootSelect, alias, countType); - - ExtractingSqlSelect finalSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.FINAL), - countSqlSelect.aliased().getName(), - Integer.class - ); - - return SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(countSqlSelect)) - .forFinalStep(List.of(finalSelect)) - .build(); + return CountSqlAggregator.create(countSelect, context).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/DateDistanceSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/DateDistanceSelectConverter.java index af32fdcd88..1cde1ba1bd 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/DateDistanceSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/DateDistanceSelectConverter.java @@ -1,17 +1,9 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.connector.specific.DateDistanceSelect; -import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.NameGenerator; -import com.bakdata.conquery.sql.conversion.model.select.DateDistanceSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.MinSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; +import com.bakdata.conquery.sql.conversion.model.select.DateDistanceSqlAggregator; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; import com.bakdata.conquery.sql.conversion.supplier.DateNowSupplier; -import org.jooq.Field; public class DateDistanceSelectConverter implements SelectConverter { @@ -23,33 +15,7 @@ public DateDistanceSelectConverter(DateNowSupplier dateNowSupplier) { @Override public SqlSelects convert(DateDistanceSelect dateDistanceSelect, SelectContext context) { - - NameGenerator nameGenerator = context.getNameGenerator(); - - SqlSelect rootSelect = new DateDistanceSqlSelect( - dateNowSupplier, - dateDistanceSelect.getTimeUnit(), - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - dateDistanceSelect.getColumn(), - nameGenerator.selectName(dateDistanceSelect), - context.getParentContext().getDateRestrictionRange(), - context.getParentContext().getSqlDialect().getFunctionProvider() - ); - - Field qualifiedDateDistance = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - MinSqlSelect minDateDistance = new MinSqlSelect(qualifiedDateDistance, nameGenerator.selectName(dateDistanceSelect)); - - ExtractingSqlSelect firstValueReference = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.FINAL), - minDateDistance.aliased().getName(), - Object.class - ); - - return SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(minDateDistance)) - .forFinalStep(List.of(firstValueReference)) - .build(); + return DateDistanceSqlAggregator.create(dateDistanceSelect, context, dateNowSupplier).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/ExistsSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/ExistsSelectConverter.java index 016f774061..e3f6d036e6 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/ExistsSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/ExistsSelectConverter.java @@ -1,19 +1,14 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.concept.specific.ExistsSelect; -import com.bakdata.conquery.sql.conversion.model.select.ExistsSqlSelect; +import com.bakdata.conquery.sql.conversion.model.select.ExistsSqlAggregator; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; public class ExistsSelectConverter implements SelectConverter { @Override public SqlSelects convert(ExistsSelect existsSelect, SelectContext context) { - String existsSelectAlias = context.getNameGenerator().selectName(existsSelect); - return SqlSelects.builder() - .forFinalStep(List.of(new ExistsSqlSelect(existsSelectAlias))) - .build(); + return ExistsSqlAggregator.create(existsSelect, context).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/FirstValueSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/FirstValueSelectConverter.java index bb97ad4a9f..6756e973e7 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/FirstValueSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/FirstValueSelectConverter.java @@ -1,53 +1,14 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.Collections; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.connector.FirstValueSelect; -import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.FirstValueSqlSelect; +import com.bakdata.conquery.sql.conversion.model.select.FirstValueSqlAggregator; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import org.jooq.Field; public class FirstValueSelectConverter implements SelectConverter { @Override public SqlSelects convert(FirstValueSelect firstSelect, SelectContext context) { - - ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - firstSelect.getColumn().getName(), - Object.class - ); - - List> validityDateFields = context.getValidityDate() - .map(validityDate -> validityDate.qualify(context.getConceptTables() - .getPredecessor(ConceptCteStep.AGGREGATION_SELECT))) - .map(ColumnDateRange::toFields) - .orElse(Collections.emptyList()); - - FirstValueSqlSelect firstValueSqlSelect = - FirstValueSqlSelect.builder() - .firstColumn(context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased())) - .alias(context.getNameGenerator().selectName(firstSelect)) - .orderByColumns(validityDateFields) - .functionProvider(context.getParentContext().getSqlDialect().getFunctionProvider()) - .build(); - - - ExtractingSqlSelect finalSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.FINAL), - firstValueSqlSelect.aliased().getName(), - Object.class - ); - - return SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(firstValueSqlSelect)) - .forFinalStep(List.of(finalSelect)) - .build(); + return FirstValueSqlAggregator.create(firstSelect, context).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/LastValueSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/LastValueSelectConverter.java index 4a6df1fdd2..c11428bf29 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/LastValueSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/LastValueSelectConverter.java @@ -1,52 +1,14 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.Collections; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.connector.LastValueSelect; -import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.LastValueSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; +import com.bakdata.conquery.sql.conversion.model.select.LastValueSqlAggregator; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import org.jooq.Field; public class LastValueSelectConverter implements SelectConverter { @Override public SqlSelects convert(LastValueSelect lastSelect, SelectContext context) { - - String rootTableName = context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING); - String columName = lastSelect.getColumn().getName(); - SqlSelect rootSelect = new ExtractingSqlSelect<>(rootTableName, columName, Object.class); - - List> validityDateFields = context.getValidityDate() - .map(validityDate -> validityDate.qualify(context.getConceptTables() - .getPredecessor(ConceptCteStep.AGGREGATION_SELECT))) - .map(ColumnDateRange::toFields) - .orElse(Collections.emptyList()); - - Field qualifiedRootSelect = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - String alias = lastSelect.getName(); - SqlSelect lastValueSqlSelect = LastValueSqlSelect.builder() - .lastColumn(qualifiedRootSelect) - .alias(alias) - .orderByColumns(validityDateFields) - .functionProvider(context.getParentContext().getSqlDialect().getFunctionProvider()) - .build(); - - ExtractingSqlSelect finalSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.FINAL), - lastValueSqlSelect.aliased().getName(), - Object.class - ); - - return SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(lastValueSqlSelect)) - .forFinalStep(List.of(finalSelect)) - .build(); + return LastValueSqlAggregator.create(lastSelect, context).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/RandomValueSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/RandomValueSelectConverter.java index df13ebb47b..7638a52b1d 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/RandomValueSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/RandomValueSelectConverter.java @@ -1,43 +1,14 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.connector.RandomValueSelect; -import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.RandomValueSqlSelect; -import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; +import com.bakdata.conquery.sql.conversion.model.select.RandomValueSqlAggregator; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import org.jooq.Field; public class RandomValueSelectConverter implements SelectConverter { @Override public SqlSelects convert(RandomValueSelect randomSelect, SelectContext context) { - - String rootTableName = context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING); - String columnName = randomSelect.getColumn().getName(); - SqlSelect rootSelect = new ExtractingSqlSelect<>(rootTableName, columnName, Object.class); - - Field qualifiedRootSelect = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - String alias = randomSelect.getName(); - SqlSelect randomValueSqlSelect = RandomValueSqlSelect.builder() - .randomColumn(qualifiedRootSelect) - .alias(alias) - .functionProvider(context.getParentContext().getSqlDialect().getFunctionProvider()) - .build(); - - ExtractingSqlSelect finalSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.FINAL), - randomValueSqlSelect.aliased().getName(), - Object.class - ); - - return SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(randomValueSqlSelect)) - .forFinalStep(List.of(finalSelect)) - .build(); + return RandomValueSqlAggregator.create(randomSelect, context).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/SumSelectConverter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/SumSelectConverter.java index 310b083850..48a52b40ed 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/SumSelectConverter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/concept/select/SumSelectConverter.java @@ -1,42 +1,14 @@ package com.bakdata.conquery.sql.conversion.cqelement.concept.select; -import java.util.List; - import com.bakdata.conquery.models.datasets.concepts.select.connector.specific.SumSelect; -import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; -import com.bakdata.conquery.sql.conversion.cqelement.concept.filter.NumberMapUtil; -import com.bakdata.conquery.sql.conversion.model.select.ExtractingSqlSelect; import com.bakdata.conquery.sql.conversion.model.select.SqlSelects; -import com.bakdata.conquery.sql.conversion.model.select.SumSqlSelect; -import org.jooq.Field; +import com.bakdata.conquery.sql.conversion.model.select.SumSqlAggregator; public class SumSelectConverter implements SelectConverter { @Override public SqlSelects convert(SumSelect sumSelect, SelectContext context) { - - Class numberClass = NumberMapUtil.NUMBER_MAP.get(sumSelect.getColumn().getType()); - - ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.PREPROCESSING), - sumSelect.getColumn().getName(), - numberClass - ); - - Field qualifiedRootSelect = context.getConceptTables().qualifyOnPredecessor(ConceptCteStep.AGGREGATION_SELECT, rootSelect.aliased()); - SumSqlSelect sumGroupBy = new SumSqlSelect(qualifiedRootSelect, context.getNameGenerator().selectName(sumSelect)); - - ExtractingSqlSelect finalSelect = new ExtractingSqlSelect<>( - context.getConceptTables().getPredecessor(ConceptCteStep.FINAL), - sumGroupBy.aliased().getName(), - numberClass - ); - - return SqlSelects.builder() - .forPreprocessingStep(List.of(rootSelect)) - .forAggregationSelectStep(List.of(sumGroupBy)) - .forFinalStep(List.of(finalSelect)) - .build(); + return SumSqlAggregator.create(sumSelect, context).getSqlSelects(); } @Override diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/intervalpacking/AnsiSqlIntervalPacker.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/intervalpacking/AnsiSqlIntervalPacker.java index 09d9c12912..72074f0a94 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/intervalpacking/AnsiSqlIntervalPacker.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/cqelement/intervalpacking/AnsiSqlIntervalPacker.java @@ -41,8 +41,8 @@ private QueryStep createPreviousEndStep(IntervalPackingContext context) { .andPreceding(1)) .as(IntervalPacker.PREVIOUS_END_FIELD_NAME); - ArrayList qualifiedSelects = new ArrayList<>(QualifyingUtil.qualify(context.getCarryThroughSelects(), sourceTableName)); - qualifiedSelects.add(new FieldWrapper(previousEnd)); + List qualifiedSelects = new ArrayList<>(QualifyingUtil.qualify(context.getCarryThroughSelects(), sourceTableName)); + qualifiedSelects.add(new FieldWrapper<>(previousEnd)); Selects previousEndSelects = Selects.builder() .primaryColumn(primaryColumn) @@ -75,8 +75,8 @@ private QueryStep createRangeIndexStep(QueryStep previousEndStep, IntervalPackin .rowsUnboundedPreceding()) .as(IntervalPacker.RANGE_INDEX_FIELD_NAME); - ArrayList qualifiedSelects = new ArrayList<>(QualifyingUtil.qualify(context.getCarryThroughSelects(), previousEndCteName)); - qualifiedSelects.add(new FieldWrapper(rangeIndex)); + List qualifiedSelects = new ArrayList<>(QualifyingUtil.qualify(context.getCarryThroughSelects(), previousEndCteName)); + qualifiedSelects.add(new FieldWrapper<>(rangeIndex)); Selects rangeIndexSelects = Selects.builder() .primaryColumn(primaryColumn) diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/dialect/SqlFunctionProvider.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/dialect/SqlFunctionProvider.java index a373b2bd83..2ac69b9891 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/dialect/SqlFunctionProvider.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/dialect/SqlFunctionProvider.java @@ -115,10 +115,10 @@ default Field replace(Field target, String old, String _new) { return DSL.function("replace", String.class, target, DSL.val(old), DSL.val(_new)); } - default Field prefixStringAggregation(Field field, String prefix) { + default Field prefixStringAggregation(Field field, String prefix) { Field likePattern = DSL.inline(prefix + "%"); String sqlTemplate = "'[' || STRING_AGG(CASE WHEN {0} LIKE {1} THEN {0} ELSE NULL END, ', ') || ']'"; - return DSL.field(DSL.sql(sqlTemplate, field, likePattern)); + return DSL.field(DSL.sql(sqlTemplate, field, likePattern), String.class); } } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/QualifyingUtil.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/QualifyingUtil.java index 9fe5d5f6c5..bf7f4dbb7e 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/QualifyingUtil.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/QualifyingUtil.java @@ -15,7 +15,7 @@ public static Field qualify(Field field, String qualifier) { public static List qualify(List sqlSelects, String qualifier) { return sqlSelects.stream() - .map(sqlSelect -> sqlSelect.createReference(qualifier)) + .map(sqlSelect -> sqlSelect.createAliasedReference(qualifier)) .collect(Collectors.toList()); } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/Selects.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/Selects.java index 5eae4ab54f..982ed51568 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/Selects.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/Selects.java @@ -1,6 +1,5 @@ package com.bakdata.conquery.sql.conversion.model; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Function; @@ -9,6 +8,7 @@ import com.bakdata.conquery.sql.conversion.model.select.SqlSelect; import lombok.Builder; +import lombok.Singular; import lombok.Value; import org.jooq.Field; import org.jooq.impl.DSL; @@ -20,8 +20,8 @@ public class Selects { Field primaryColumn; @Builder.Default Optional validityDate = Optional.empty(); - @Builder.Default - List sqlSelects = Collections.emptyList(); + @Singular + List sqlSelects; public Selects withValidityDate(ColumnDateRange validityDate) { return this.toBuilder() @@ -38,13 +38,13 @@ public Selects blockValidityDate() { public Selects qualify(String qualifier) { Field qualifiedPrimaryColumn = DSL.field(DSL.name(qualifier, this.primaryColumn.getName())); List sqlSelects = this.sqlSelects.stream() - .map(sqlSelect -> sqlSelect.createReference(qualifier)) + .map(sqlSelect -> sqlSelect.createAliasedReference(qualifier)) .distinct() .collect(Collectors.toList()); - SelectsBuilder builder = this.toBuilder() - .primaryColumn(qualifiedPrimaryColumn) - .sqlSelects(sqlSelects); + SelectsBuilder builder = Selects.builder() + .primaryColumn(qualifiedPrimaryColumn) + .sqlSelects(sqlSelects); if (this.validityDate.isPresent()) { builder = builder.validityDate(this.validityDate.map(_validityDate -> _validityDate.qualify(qualifier))); diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/filter/ConceptFilter.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/filter/SqlFilters.java similarity index 87% rename from backend/src/main/java/com/bakdata/conquery/sql/conversion/model/filter/ConceptFilter.java rename to backend/src/main/java/com/bakdata/conquery/sql/conversion/model/filter/SqlFilters.java index 2929b4ea37..b2d6059aea 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/filter/ConceptFilter.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/filter/SqlFilters.java @@ -4,7 +4,7 @@ import lombok.Value; @Value -public class ConceptFilter { +public class SqlFilters { SqlSelects selects; Filters filters; } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/CountSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/CountSqlAggregator.java new file mode 100644 index 0000000000..827a795242 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/CountSqlAggregator.java @@ -0,0 +1,100 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import java.util.List; + +import com.bakdata.conquery.models.common.IRange; +import com.bakdata.conquery.models.common.Range; +import com.bakdata.conquery.models.datasets.Column; +import com.bakdata.conquery.models.datasets.concepts.filters.specific.CountFilter; +import com.bakdata.conquery.models.datasets.concepts.select.connector.specific.CountSelect; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; +import com.bakdata.conquery.sql.conversion.cqelement.concept.filter.FilterContext; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.model.SqlTables; +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; +import com.bakdata.conquery.sql.conversion.model.filter.CountCondition; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import lombok.Value; +import org.jooq.Field; +import org.jooq.impl.DSL; + + +@Value +public class CountSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private CountSqlAggregator( + Column countColumn, + CountType countType, + String alias, + SqlTables conceptTables, + IRange filterValue + ) { + ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>( + conceptTables.getPredecessor(ConceptCteStep.PREPROCESSING), + countColumn.getName(), + Object.class + ); + + Field qualifiedRootSelect = rootSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT)).select(); + Field countField = countType == CountType.DISTINCT + ? DSL.countDistinct(qualifiedRootSelect) + : DSL.count(qualifiedRootSelect); + FieldWrapper countGroupBy = new FieldWrapper<>(countField.as(alias), countColumn.getName()); + + SqlSelects.SqlSelectsBuilder builder = SqlSelects.builder() + .preprocessingSelect(rootSelect) + .aggregationSelect(countGroupBy); + + if (filterValue == null) { + ExtractingSqlSelect finalSelect = countGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.FINAL)); + this.sqlSelects = builder.finalSelect(finalSelect).build(); + this.filters = null; + } + else { + this.sqlSelects = builder.build(); + Field qualifiedCountSelect = countGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_FILTER)).select(); + CountCondition countCondition = new CountCondition(qualifiedCountSelect, filterValue); + this.filters = Filters.builder() + .group(List.of(countCondition)) + .build(); + } + } + + public static CountSqlAggregator create(CountSelect countSelect, SelectContext selectContext) { + return new CountSqlAggregator( + countSelect.getColumn(), + CountType.fromBoolean(countSelect.isDistinct()), + selectContext.getNameGenerator().selectName(countSelect), + selectContext.getConceptTables(), + null + ); + } + + public static CountSqlAggregator create(CountFilter countFilter, FilterContext filterContext) { + return new CountSqlAggregator( + countFilter.getColumn(), + CountType.fromBoolean(countFilter.isDistinct()), + filterContext.getNameGenerator().selectName(countFilter), + filterContext.getConceptTables(), + filterContext.getValue() + ); + } + + @Override + public SqlFilters getSqlFilters() { + return new SqlFilters(this.sqlSelects, this.filters); + } + + public enum CountType { + DEFAULT, + DISTINCT; + + public static CountType fromBoolean(boolean value) { + return value ? DISTINCT : DEFAULT; + } + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/CountSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/CountSqlSelect.java deleted file mode 100644 index 4ba615b502..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/CountSqlSelect.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import java.math.BigDecimal; - -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@RequiredArgsConstructor -@EqualsAndHashCode -public class CountSqlSelect implements SqlSelect { - - private final Field columnToCount; - private final String alias; - private final CountType countType; - - @Override - public Field select() { - Field countField = countType == CountType.DISTINCT ? DSL.countDistinct(columnToCount) : DSL.count(columnToCount); - return countField.as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias, BigDecimal.class); - } - - @Override - public String columnName() { - return columnToCount.getName(); - } - - public enum CountType { - DEFAULT, - DISTINCT; - - public static CountType fromBoolean(boolean value) { - return value ? DISTINCT : DEFAULT; - } - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/DateDistanceSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/DateDistanceSqlAggregator.java new file mode 100644 index 0000000000..715ef2b16e --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/DateDistanceSqlAggregator.java @@ -0,0 +1,128 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import java.sql.Date; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Objects; + +import com.bakdata.conquery.models.common.Range; +import com.bakdata.conquery.models.common.daterange.CDateRange; +import com.bakdata.conquery.models.datasets.Column; +import com.bakdata.conquery.models.datasets.concepts.filters.specific.DateDistanceFilter; +import com.bakdata.conquery.models.datasets.concepts.select.connector.specific.DateDistanceSelect; +import com.bakdata.conquery.models.events.MajorTypeId; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; +import com.bakdata.conquery.sql.conversion.cqelement.concept.filter.FilterContext; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; +import com.bakdata.conquery.sql.conversion.model.SqlTables; +import com.bakdata.conquery.sql.conversion.model.filter.DateDistanceCondition; +import com.bakdata.conquery.sql.conversion.model.filter.FilterCondition; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import com.bakdata.conquery.sql.conversion.supplier.DateNowSupplier; +import lombok.Value; +import org.jooq.Field; +import org.jooq.Name; +import org.jooq.impl.DSL; + +@Value +public class DateDistanceSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private DateDistanceSqlAggregator( + Column column, + String alias, + CDateRange dateRestriction, + ChronoUnit timeUnit, + SqlTables conceptTables, + DateNowSupplier dateNowSupplier, + Range.LongRange filterValue, + SqlFunctionProvider functionProvider + ) { + Date endDate = getEndDate(dateRestriction, dateNowSupplier); + if (column.getType() != MajorTypeId.DATE) { + throw new UnsupportedOperationException("Can't calculate date distance to column of type " + column.getType()); + } + Name dateColumnName = DSL.name(conceptTables.getRootTable(), column.getName()); + FieldWrapper dateDistanceSelect = new FieldWrapper<>(functionProvider.dateDistance(timeUnit, dateColumnName, endDate).as(alias)); + + SqlSelects.SqlSelectsBuilder builder = SqlSelects.builder().preprocessingSelect(dateDistanceSelect); + + if (filterValue == null) { + + Field qualifiedDateDistance = dateDistanceSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT)) + .select(); + FieldWrapper minDateDistance = new FieldWrapper<>(DSL.min(qualifiedDateDistance).as(alias)); + + ExtractingSqlSelect finalSelect = minDateDistance.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.FINAL)); + + this.sqlSelects = builder.aggregationSelect(minDateDistance) + .finalSelect(finalSelect) + .build(); + this.filters = null; + } + else { + this.sqlSelects = builder.build(); + Field + qualifiedDateDistanceSelect = + dateDistanceSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.EVENT_FILTER)).select(); + FilterCondition dateDistanceCondition = new DateDistanceCondition(qualifiedDateDistanceSelect, filterValue); + this.filters = Filters.builder() + .event(List.of(dateDistanceCondition)) + .build(); + } + } + + public static DateDistanceSqlAggregator create( + DateDistanceSelect dateDistanceSelect, + SelectContext selectContext, + DateNowSupplier dateNowSupplier + ) { + return new DateDistanceSqlAggregator( + dateDistanceSelect.getColumn(), + selectContext.getNameGenerator().selectName(dateDistanceSelect), + selectContext.getParentContext().getDateRestrictionRange(), + dateDistanceSelect.getTimeUnit(), + selectContext.getConceptTables(), + dateNowSupplier, + null, + selectContext.getParentContext().getSqlDialect().getFunctionProvider() + ); + } + + public static DateDistanceSqlAggregator create( + DateDistanceFilter dateDistanceFilter, + FilterContext filterContext, + DateNowSupplier dateNowSupplier + ) { + return new DateDistanceSqlAggregator( + dateDistanceFilter.getColumn(), + filterContext.getNameGenerator().selectName(dateDistanceFilter), + filterContext.getParentContext().getDateRestrictionRange(), + dateDistanceFilter.getTimeUnit(), + filterContext.getConceptTables(), + dateNowSupplier, + filterContext.getValue(), + filterContext.getParentContext().getSqlDialect().getFunctionProvider() + ); + } + + private Date getEndDate(CDateRange dateRange, DateNowSupplier dateNowSupplier) { + LocalDate endDate; + // if a date restriction is set, the max of the date restriction equals the end date of the date distance + // but there is also the possibility that the user set's an empty daterange which will be non-null but with null values + if (Objects.nonNull(dateRange) && dateRange.getMax() != null) { + endDate = dateRange.getMax(); + } + else { + // otherwise the current date is the upper bound + endDate = dateNowSupplier.getLocalDateNow(); + } + return Date.valueOf(endDate); + } + + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/DateDistanceSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/DateDistanceSqlSelect.java deleted file mode 100644 index a7c8401790..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/DateDistanceSqlSelect.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import java.sql.Date; -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; -import java.util.Objects; - -import com.bakdata.conquery.models.common.daterange.CDateRange; -import com.bakdata.conquery.models.datasets.Column; -import com.bakdata.conquery.models.events.MajorTypeId; -import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; -import com.bakdata.conquery.sql.conversion.supplier.DateNowSupplier; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.Name; -import org.jooq.impl.DSL; - -@RequiredArgsConstructor -@EqualsAndHashCode -public class DateDistanceSqlSelect implements SqlSelect { - - private final DateNowSupplier dateNowSupplier; - private final ChronoUnit timeUnit; - private final String sourceTable; - private final Column column; - private final String alias; - private final CDateRange dateRestriction; - @EqualsAndHashCode.Exclude - private final SqlFunctionProvider functionProvider; - - @Override - public Field select() { - Date endDate = getEndDate(dateRestriction); - - if (column.getType() != MajorTypeId.DATE) { - throw new UnsupportedOperationException("Can't calculate date distance to column of type " + column.getType()); - } - - Name dateColumnName = DSL.name(sourceTable, column.getName()); - return functionProvider.dateDistance(timeUnit, dateColumnName, endDate) - .as(alias); - } - - private Date getEndDate(CDateRange dateRange) { - LocalDate endDate; - // if a date restriction is set, the max of the date restriction equals the end date of the date distance - // but there is also the possibility that the user set's an empty daterange which will be non-null but with null values - if (Objects.nonNull(dateRange) && dateRange.getMax() != null) { - endDate = dateRange.getMax(); - } - else { - // otherwise the current date is the upper bound - endDate = dateNowSupplier.getLocalDateNow(); - } - return Date.valueOf(endDate); - } - - @Override - public Field aliased() { - return DSL.field(alias, Integer.class); - } - - @Override - public String columnName() { - return column.getName(); - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExistsSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExistsSqlAggregator.java new file mode 100644 index 0000000000..df98b793d9 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExistsSqlAggregator.java @@ -0,0 +1,28 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import com.bakdata.conquery.models.datasets.concepts.select.concept.specific.ExistsSelect; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import lombok.Value; +import org.jooq.impl.DSL; + +@Value +public class ExistsSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private ExistsSqlAggregator(String alias) { + FieldWrapper existsSelect = new UniversalSqlSelect<>(DSL.field("1", Integer.class).as(alias)); + this.sqlSelects = SqlSelects.builder() + .finalSelect(existsSelect) + .build(); + this.filters = Filters.builder().build(); + } + + public static ExistsSqlAggregator create(ExistsSelect existsSelect, SelectContext selectContext) { + String alias = selectContext.getNameGenerator().selectName(existsSelect); + return new ExistsSqlAggregator(alias); + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExistsSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExistsSqlSelect.java deleted file mode 100644 index 775b569676..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExistsSqlSelect.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import lombok.EqualsAndHashCode; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@EqualsAndHashCode -public class ExistsSqlSelect implements SqlSelect { - - private static final String EXISTS_SUFFIX = "_exists"; - - private final String alias; - - public ExistsSqlSelect(String alias) { - this.alias = alias + EXISTS_SUFFIX; - } - - @Override - public Field select() { - return DSL.field("1", Integer.class) - .as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias, Integer.class); - } - - @Override - public String columnName() { - return alias; - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExtractingSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExtractingSqlSelect.java index ec6656f629..04496ca30a 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExtractingSqlSelect.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/ExtractingSqlSelect.java @@ -10,24 +10,24 @@ *

* This can be used if another select requires a column in a later step. * - * @param type of column + * @param type of column */ @Value @EqualsAndHashCode -public class ExtractingSqlSelect implements SqlSelect { +public class ExtractingSqlSelect implements SqlSelect { String table; String column; @EqualsAndHashCode.Exclude - Class columnClass; + Class columnClass; @Override - public Field select() { + public Field select() { return DSL.field(DSL.name(table, column), columnClass); } @Override - public Field aliased() { + public Field aliased() { return DSL.field(DSL.name(column), columnClass); } @@ -36,4 +36,14 @@ public String columnName() { return column; } + @Override + public ExtractingSqlSelect createAliasedReference(String qualifier) { + Field aliased = aliased(); + return new ExtractingSqlSelect<>( + qualifier, + aliased.getName(), + aliased.getType() + ); + } + } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FieldWrapper.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FieldWrapper.java index 9e53fffd27..39b93fc923 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FieldWrapper.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FieldWrapper.java @@ -1,29 +1,63 @@ package com.bakdata.conquery.sql.conversion.model.select; import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; import org.jooq.Field; import org.jooq.impl.DSL; -@RequiredArgsConstructor @EqualsAndHashCode -public class FieldWrapper implements SqlSelect { +public class FieldWrapper implements SqlSelect { - private final Field field; + private final Field field; + private final String columnName; + + /** + * Wrapper for a {@link Field}. + *

+ * {@link FieldWrapper#columnName()} will return the given column name of the given field. + * + * @param field The field to wrap, e.g. {@code DSL.sum(DSL.field(DSL.name("foo", "bar"))).as("foo_bar")}; + * @param columnName The "root" column name of the wrapped field, e.g. "bar" + */ + public FieldWrapper(Field field, String columnName) { + this.field = field; + this.columnName = columnName; + } + + /** + * Wrapper for a {@link Field}. + *

+ * {@link FieldWrapper#columnName()} will return the alias of the given field. + * + * @param field @param field The field to wrap, e.g. {@code DSL.field(DSL.name("fizz", "buzz"))).as("fizz_buzz")}; + */ + public FieldWrapper(Field field) { + this.field = field; + this.columnName = field.getName(); + } @Override - public Field select() { + public Field select() { return field; } @Override - public Field aliased() { - return DSL.field(DSL.name(field.getName())); + public Field aliased() { + return DSL.field(DSL.name(field.getName()), field.getType()); } @Override public String columnName() { - return field.getName(); + return this.columnName; + } + + @Override + public ExtractingSqlSelect createAliasedReference(String qualifier) { + Field aliased = aliased(); + return new ExtractingSqlSelect<>( + qualifier, + aliased.getName(), + aliased.getType() + ); } } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FirstValueSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FirstValueSqlAggregator.java new file mode 100644 index 0000000000..9d6f2a51db --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FirstValueSqlAggregator.java @@ -0,0 +1,63 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import com.bakdata.conquery.models.datasets.Column; +import com.bakdata.conquery.models.datasets.concepts.select.connector.FirstValueSelect; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; +import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; +import com.bakdata.conquery.sql.conversion.model.SqlTables; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import lombok.Value; +import org.jooq.Field; + +@Value +public class FirstValueSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private FirstValueSqlAggregator( + Column column, + String alias, + Optional validityDate, + SqlTables conceptTables, + SqlFunctionProvider functionProvider + ) { + String rootTableName = conceptTables.getPredecessor(ConceptCteStep.PREPROCESSING); + String columnName = column.getName(); + ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>(rootTableName, columnName, Object.class); + + List> validityDateFields = + validityDate.map(_validityDate -> _validityDate.qualify(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT))) + .map(ColumnDateRange::toFields) + .orElse(Collections.emptyList()); + Field qualifiedRootSelect = rootSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT)).select(); + FieldWrapper firstGroupBy = new FieldWrapper<>(functionProvider.first(qualifiedRootSelect, validityDateFields).as(alias), columnName); + + ExtractingSqlSelect finalSelect = firstGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.FINAL)); + + this.sqlSelects = SqlSelects.builder() + .preprocessingSelect(rootSelect) + .aggregationSelect(firstGroupBy) + .finalSelect(finalSelect) + .build(); + + this.filters = Filters.builder().build(); + } + + public static FirstValueSqlAggregator create(FirstValueSelect firstValueSelect, SelectContext selectContext) { + return new FirstValueSqlAggregator( + firstValueSelect.getColumn(), + selectContext.getNameGenerator().selectName(firstValueSelect), + selectContext.getValidityDate(), + selectContext.getConceptTables(), + selectContext.getParentContext().getSqlDialect().getFunctionProvider() + ); + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FirstValueSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FirstValueSqlSelect.java deleted file mode 100644 index e61f983fd9..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/FirstValueSqlSelect.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import java.util.List; - -import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Value; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@Value -@Builder -@EqualsAndHashCode -public class FirstValueSqlSelect implements SqlSelect { - - Field firstColumn; - String alias; - List> orderByColumns; - @EqualsAndHashCode.Exclude - SqlFunctionProvider functionProvider; - - @Override - public Field select() { - return functionProvider.first(firstColumn, orderByColumns) - .as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias); - } - - @Override - public String columnName() { - return firstColumn.getName(); - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/LastValueSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/LastValueSqlAggregator.java new file mode 100644 index 0000000000..22f11a0f29 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/LastValueSqlAggregator.java @@ -0,0 +1,63 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import com.bakdata.conquery.models.datasets.Column; +import com.bakdata.conquery.models.datasets.concepts.select.connector.LastValueSelect; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; +import com.bakdata.conquery.sql.conversion.model.ColumnDateRange; +import com.bakdata.conquery.sql.conversion.model.SqlTables; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import lombok.Value; +import org.jooq.Field; + +@Value +public class LastValueSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private LastValueSqlAggregator( + Column column, + String alias, + Optional validityDate, + SqlTables conceptTables, + SqlFunctionProvider functionProvider + ) { + String rootTableName = conceptTables.getPredecessor(ConceptCteStep.PREPROCESSING); + String columnName = column.getName(); + ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>(rootTableName, columnName, Object.class); + + List> validityDateFields = + validityDate.map(_validityDate -> _validityDate.qualify(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT))) + .map(ColumnDateRange::toFields) + .orElse(Collections.emptyList()); + Field qualifiedRootSelect = rootSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT)).select(); + FieldWrapper lastGroupBy = new FieldWrapper<>(functionProvider.last(qualifiedRootSelect, validityDateFields).as(alias), columnName); + + ExtractingSqlSelect finalSelect = lastGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.FINAL)); + + this.sqlSelects = SqlSelects.builder() + .preprocessingSelect(rootSelect) + .aggregationSelect(lastGroupBy) + .finalSelect(finalSelect) + .build(); + + this.filters = Filters.builder().build(); + } + + public static LastValueSqlAggregator create(LastValueSelect lastValueSelect, SelectContext selectContext) { + return new LastValueSqlAggregator( + lastValueSelect.getColumn(), + selectContext.getNameGenerator().selectName(lastValueSelect), + selectContext.getValidityDate(), + selectContext.getConceptTables(), + selectContext.getParentContext().getSqlDialect().getFunctionProvider() + ); + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/LastValueSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/LastValueSqlSelect.java deleted file mode 100644 index b64486077b..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/LastValueSqlSelect.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import java.util.List; - -import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Value; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@Value -@Builder -@EqualsAndHashCode -public class LastValueSqlSelect implements SqlSelect { - - Field lastColumn; - String alias; - List> orderByColumns; - @EqualsAndHashCode.Exclude - SqlFunctionProvider functionProvider; - - @Override - public Field select() { - return functionProvider.last(lastColumn, orderByColumns) - .as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias); - } - - @Override - public String columnName() { - return lastColumn.getName(); - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/MinSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/MinSqlSelect.java deleted file mode 100644 index f85f4301a8..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/MinSqlSelect.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import java.math.BigDecimal; - -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@RequiredArgsConstructor -@EqualsAndHashCode -public class MinSqlSelect implements SqlSelect { - - private final Field minColumn; - private final String alias; - - @Override - public Field select() { - return DSL.min(minColumn) - .as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias, BigDecimal.class); - } - - @Override - public String columnName() { - return minColumn.getName(); - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/RandomValueSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/RandomValueSqlAggregator.java new file mode 100644 index 0000000000..d47b1bff1c --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/RandomValueSqlAggregator.java @@ -0,0 +1,52 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import com.bakdata.conquery.models.datasets.Column; +import com.bakdata.conquery.models.datasets.concepts.select.connector.RandomValueSelect; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; +import com.bakdata.conquery.sql.conversion.model.SqlTables; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import lombok.Value; +import org.jooq.Field; + +@Value +public class RandomValueSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private RandomValueSqlAggregator( + Column column, + String alias, + SqlTables conceptTables, + SqlFunctionProvider functionProvider + ) { + String rootTableName = conceptTables.getPredecessor(ConceptCteStep.PREPROCESSING); + String columnName = column.getName(); + ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>(rootTableName, columnName, Object.class); + + Field qualifiedRootSelect = rootSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT)).select(); + FieldWrapper randomGroupBy = new FieldWrapper<>(functionProvider.random(qualifiedRootSelect).as(alias), columnName); + + ExtractingSqlSelect finalSelect = randomGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.FINAL)); + + this.sqlSelects = SqlSelects.builder() + .preprocessingSelect(rootSelect) + .aggregationSelect(randomGroupBy) + .finalSelect(finalSelect) + .build(); + + this.filters = Filters.builder().build(); + } + + public static RandomValueSqlAggregator create(RandomValueSelect randomValueSelect, SelectContext selectContext) { + return new RandomValueSqlAggregator( + randomValueSelect.getColumn(), + selectContext.getNameGenerator().selectName(randomValueSelect), + selectContext.getConceptTables(), + selectContext.getParentContext().getSqlDialect().getFunctionProvider() + ); + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/RandomValueSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/RandomValueSqlSelect.java deleted file mode 100644 index 9575504965..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/RandomValueSqlSelect.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import com.bakdata.conquery.sql.conversion.dialect.SqlFunctionProvider; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Value; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@Value -@Builder -@EqualsAndHashCode -public class RandomValueSqlSelect implements SqlSelect { - - Field randomColumn; - String alias; - @EqualsAndHashCode.Exclude - SqlFunctionProvider functionProvider; - - @Override - public Field select() { - return functionProvider.random(randomColumn).as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias); - } - - @Override - public String columnName() { - return randomColumn.getName(); - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlAggregator.java new file mode 100644 index 0000000000..93dbf08f17 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlAggregator.java @@ -0,0 +1,16 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import com.bakdata.conquery.sql.conversion.model.filter.SqlFilters; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; + +public interface SqlAggregator { + + SqlSelects getSqlSelects(); + + Filters getFilters(); + + default SqlFilters getSqlFilters() { + return new SqlFilters(getSqlSelects(), getFilters()); + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelect.java index 527814de1b..898803e45d 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelect.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelect.java @@ -1,6 +1,7 @@ package com.bakdata.conquery.sql.conversion.model.select; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; import org.jooq.Field; public interface SqlSelect { @@ -24,14 +25,25 @@ public interface SqlSelect { String columnName(); /** - * @return A reference to this {@link SqlSelect} qualified on the given qualifier. + * @return Creates a reference to the alias of this SqlSelect qualified onto the given qualifier. */ - default ExtractingSqlSelect createReference(String qualifier) { + ExtractingSqlSelect createAliasedReference(String qualifier); + /** + * @return Creates a reference to the column of this SqlSelect qualified onto the given qualifier. + */ + default ExtractingSqlSelect createColumnReference(String qualifier) { return new ExtractingSqlSelect<>( qualifier, columnName(), - aliased().getType() + Object.class ); } + /** + * @return Determines if this is only part of the {@link ConceptCteStep#FINAL} CTE and has no predeceasing selects. + */ + default boolean isUniversal() { + return false; + } + } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelects.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelects.java index 2b7c199297..be42762148 100644 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelects.java +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SqlSelects.java @@ -1,20 +1,20 @@ package com.bakdata.conquery.sql.conversion.model.select; -import java.util.Collections; import java.util.List; import lombok.Builder; +import lombok.Singular; import lombok.Value; -@Builder @Value +@Builder public class SqlSelects { - @Builder.Default - List forPreprocessingStep = Collections.emptyList(); + @Singular + List preprocessingSelects; // Empty if only used in event filter - @Builder.Default - List forAggregationSelectStep = Collections.emptyList(); + @Singular + List aggregationSelects; // Empty if only used in aggregation select - @Builder.Default - List forFinalStep = Collections.emptyList(); + @Singular + List finalSelects; } diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SumSqlAggregator.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SumSqlAggregator.java new file mode 100644 index 0000000000..5462bf73cb --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SumSqlAggregator.java @@ -0,0 +1,76 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import java.math.BigDecimal; +import java.util.List; + +import com.bakdata.conquery.models.common.IRange; +import com.bakdata.conquery.models.datasets.Column; +import com.bakdata.conquery.models.datasets.concepts.filters.specific.SumFilter; +import com.bakdata.conquery.models.datasets.concepts.select.connector.specific.SumSelect; +import com.bakdata.conquery.sql.conversion.cqelement.concept.ConceptCteStep; +import com.bakdata.conquery.sql.conversion.cqelement.concept.filter.FilterContext; +import com.bakdata.conquery.sql.conversion.cqelement.concept.filter.NumberMapUtil; +import com.bakdata.conquery.sql.conversion.cqelement.concept.select.SelectContext; +import com.bakdata.conquery.sql.conversion.model.SqlTables; +import com.bakdata.conquery.sql.conversion.model.filter.Filters; +import com.bakdata.conquery.sql.conversion.model.filter.SumCondition; +import lombok.Value; +import org.jooq.Field; +import org.jooq.impl.DSL; + +@Value +public class SumSqlAggregator implements SqlAggregator { + + SqlSelects sqlSelects; + Filters filters; + + private SumSqlAggregator( + Column sumColumn, + String alias, + SqlTables conceptTables, + IRange filterValue + ) { + Class numberClass = NumberMapUtil.NUMBER_MAP.get(sumColumn.getType()); + ExtractingSqlSelect rootSelect = new ExtractingSqlSelect<>( + conceptTables.getPredecessor(ConceptCteStep.PREPROCESSING), + sumColumn.getName(), + numberClass + ); + + Field + qualifiedRootSelect = + rootSelect.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_SELECT)).select(); + FieldWrapper sumGroupBy = new FieldWrapper<>(DSL.sum(qualifiedRootSelect).as(alias), sumColumn.getName()); + + SqlSelects.SqlSelectsBuilder builder = SqlSelects.builder() + .preprocessingSelect(rootSelect) + .aggregationSelect(sumGroupBy); + + if (filterValue == null) { + ExtractingSqlSelect finalSelect = sumGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.FINAL)); + this.sqlSelects = builder.finalSelect(finalSelect).build(); + this.filters = null; + } + else { + this.sqlSelects = builder.build(); + Field qualifiedSumGroupBy = sumGroupBy.createAliasedReference(conceptTables.getPredecessor(ConceptCteStep.AGGREGATION_FILTER)).select(); + SumCondition sumCondition = new SumCondition(qualifiedSumGroupBy, filterValue); + this.filters = Filters.builder() + .group(List.of(sumCondition)) + .build(); + } + } + + public static SumSqlAggregator create(SumSelect sumSelect, SelectContext selectContext) { + Column sumColumn = sumSelect.getColumn(); + String alias = selectContext.getNameGenerator().selectName(sumSelect); + return new SumSqlAggregator(sumColumn, alias, selectContext.getConceptTables(), null); + } + + public static SumSqlAggregator create(SumFilter> sumFilter, FilterContext> filterContext) { + Column sumColumn = sumFilter.getColumn(); + String alias = filterContext.getNameGenerator().selectName(sumFilter); + return new SumSqlAggregator(sumColumn, alias, filterContext.getConceptTables(), filterContext.getValue()); + } + +} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SumSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SumSqlSelect.java deleted file mode 100644 index 6247bd0653..0000000000 --- a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/SumSqlSelect.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.bakdata.conquery.sql.conversion.model.select; - -import java.math.BigDecimal; - -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@RequiredArgsConstructor -@EqualsAndHashCode -public class SumSqlSelect implements SqlSelect { - - private final Field columnToSum; - private final String alias; - - @Override - public Field select() { - return DSL.sum(columnToSum) - .as(alias); - } - - @Override - public Field aliased() { - return DSL.field(alias, BigDecimal.class); - } - - @Override - public String columnName() { - return columnToSum.getName(); - } - -} diff --git a/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/UniversalSqlSelect.java b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/UniversalSqlSelect.java new file mode 100644 index 0000000000..cc3a531de5 --- /dev/null +++ b/backend/src/main/java/com/bakdata/conquery/sql/conversion/model/select/UniversalSqlSelect.java @@ -0,0 +1,15 @@ +package com.bakdata.conquery.sql.conversion.model.select; + +import org.jooq.Field; + +public class UniversalSqlSelect extends FieldWrapper { + + public UniversalSqlSelect(Field field) { + super(field); + } + + @Override + public boolean isUniversal() { + return true; + } +}