From 13b7e01cbd4396e8e4cbb6357baec4514ad2eb6c Mon Sep 17 00:00:00 2001 From: taepper Date: Wed, 5 Jul 2023 18:12:03 +0200 Subject: [PATCH] feat: add limit orderBy and offset to all query actions --- .../test/invalidQueries/OffsetNegative.json | 30 + .../test/queries/DetailsOrderBy.json | 588 +++++++++++++++++ .../test/queries/DetailsOrderByLimit.json | 51 ++ .../GroupByLineageOrderByCountLimit.json | 7 +- .../test/queries/LimitLargerThanTable.json | 589 ++++++++++++++++++ endToEndTests/test/queries/Offset0.json | 589 ++++++++++++++++++ endToEndTests/test/queries/OffsetFull.json | 15 + .../test/queries/OffsetLargerThanTable.json | 27 + .../test/queries/OffsetLimitOverlap.json | 126 ++++ endToEndTests/test/queries/OrderByAge.json | 7 +- endToEndTests/test/queries/OrderByFloat.json | 2 +- .../test/queries/OrderByFloatDesc.json | 7 +- .../test/queries/OrderByFloatFiltered.json | 2 +- include/silo/config/database_config.h | 2 +- include/silo/query_engine/actions/action.h | 20 + .../silo/query_engine/actions/aggregated.h | 8 +- src/silo/config/database_config.cpp | 4 +- src/silo/query_engine/actions/action.cpp | 92 +++ src/silo/query_engine/actions/aggregated.cpp | 112 +--- src/silo/query_engine/actions/details.cpp | 29 +- 20 files changed, 2191 insertions(+), 116 deletions(-) create mode 100644 endToEndTests/test/invalidQueries/OffsetNegative.json create mode 100644 endToEndTests/test/queries/DetailsOrderBy.json create mode 100644 endToEndTests/test/queries/DetailsOrderByLimit.json create mode 100644 endToEndTests/test/queries/LimitLargerThanTable.json create mode 100644 endToEndTests/test/queries/Offset0.json create mode 100644 endToEndTests/test/queries/OffsetFull.json create mode 100644 endToEndTests/test/queries/OffsetLargerThanTable.json create mode 100644 endToEndTests/test/queries/OffsetLimitOverlap.json diff --git a/endToEndTests/test/invalidQueries/OffsetNegative.json b/endToEndTests/test/invalidQueries/OffsetNegative.json new file mode 100644 index 000000000..924072aae --- /dev/null +++ b/endToEndTests/test/invalidQueries/OffsetNegative.json @@ -0,0 +1,30 @@ +{ + "testCaseName": "Details action with order by field EPI_ISL", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "offset": -1231 + }, + "filterExpression": { + "type": "And", + "children": [ + { + "type": "StringEquals", + "column": "country", + "value": "Switzerland" + }, + { + "type": "PangoLineage", + "column": "pango_lineage", + "value": "B.1.1.7", + "includeSublineages": true + } + ] + } + }, + "expectedError": { + "error": "Bad request", + "message": "If the action contains an offset, it must be a non-negative number" + } +} diff --git a/endToEndTests/test/queries/DetailsOrderBy.json b/endToEndTests/test/queries/DetailsOrderBy.json new file mode 100644 index 000000000..ebcfca3a2 --- /dev/null +++ b/endToEndTests/test/queries/DetailsOrderBy.json @@ -0,0 +1,588 @@ +{ + "testCaseName": "Details action with order by field EPI_ISL", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"] + }, + "filterExpression": { + "type": "And", + "children": [ + { + "type": "StringEquals", + "column": "country", + "value": "Switzerland" + }, + { + "type": "PangoLineage", + "column": "pango_lineage", + "value": "B.1.1.7", + "includeSublineages": true + } + ] + } + }, + "expectedQueryResult": [ + { + "age": 57, + "country": "Switzerland", + "date": "2021-02-10", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1080536", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-08-04" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-02-14", + "division": "Graubünden", + "gisaid_epi_isl": "EPI_ISL_1119315", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-03-18" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2020-12-29", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1129663", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-07" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-02-23", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1195052", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-07-04" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-01-26", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1273458", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-05-18" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-03-08", + "division": "Jura", + "gisaid_epi_isl": "EPI_ISL_1360935", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-01-03" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-06", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_1361468", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-01-20" + }, + { + "age": 55, + "country": "Switzerland", + "date": null, + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1407962", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-01-16" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-03", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_1408062", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2020-11-24" + }, + { + "age": 4, + "country": "Switzerland", + "date": "2021-03-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1408408", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": null + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-03-21", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_1597890", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": null, + "unsorted_date": "2021-01-25" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-03-19", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1597932", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-02-10" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-05", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1747752", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-03-21" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-03-09", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1747885", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-03-03" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-03-03", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1748215", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2020-12-15" + }, + { + "age": null, + "country": "Switzerland", + "date": "2021-03-02", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1748243", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2020-11-24" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-03-25", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_1748395", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-04-27" + }, + { + "age": 4, + "country": "Switzerland", + "date": "2021-04-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1749892", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2020-12-24" + }, + { + "age": 5, + "country": "Switzerland", + "date": "2021-04-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1749899", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2020-03-08" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-04-15", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1749960", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-02-03" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-04-12", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_1760534", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-04-23" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-04-23", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_1840634", + "pango_lineage": "B.1.1.7.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-10" + }, + { + "age": 6, + "country": "Switzerland", + "date": "2021-04-25", + "division": "Aargau", + "gisaid_epi_isl": "EPI_ISL_2016901", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-01-29" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-04-23", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_2017036", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-03-09" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-04-28", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2019235", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-01-22" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-04-27", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2019350", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2020-12-21" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-12", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2180023", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2020-08-17" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-09", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2180995", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-05-25" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-05", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2181005", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2020-10-08" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213804", + "pango_lineage": "B.1.1.7.7", + "qc_value": null, + "region": "Europe", + "unsorted_date": "2021-04-12" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-05-13", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213934", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-04-23" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213984", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-09" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-10", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2214128", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2020-11-13" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-10", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2270139", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-08" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-05-11", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_2307766", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-05-08" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_2307888", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-23" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-07", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_2308054", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2020-12-09" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-23", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2360326", + "pango_lineage": "B.1.1.7.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-03-10" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-05-18", + "division": "Aargau", + "gisaid_epi_isl": "EPI_ISL_2374969", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-06-05" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-16", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_2375097", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2020-10-22" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_2375165", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2020-10-28" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-05-14", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_2375247", + "pango_lineage": "B.1.1.7", + "qc_value": null, + "region": "Europe", + "unsorted_date": "2021-05-11" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-05-10", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2375490", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-06-10" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-11", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2379651", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-06-01" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-05-24", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_2405276", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-04-28" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-25", + "division": "Obwalden", + "gisaid_epi_isl": "EPI_ISL_2408472", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-03-02" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-06-05", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2544226", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-05-12" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-06-03", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_2544332", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-05-13" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-06-01", + "division": "Schwyz", + "gisaid_epi_isl": "EPI_ISL_2544452", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-24" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-06-10", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_2574088", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-05" + }, + { + "age": null, + "country": "Switzerland", + "date": "2021-07-05", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_3016465", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-01-16" + } + ] +} diff --git a/endToEndTests/test/queries/DetailsOrderByLimit.json b/endToEndTests/test/queries/DetailsOrderByLimit.json new file mode 100644 index 000000000..a45fb6d02 --- /dev/null +++ b/endToEndTests/test/queries/DetailsOrderByLimit.json @@ -0,0 +1,51 @@ +{ + "testCaseName": "Details action with order by, limit and offset", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "offset": 9, + "limit": 2 + }, + "filterExpression": { + "type": "And", + "children": [ + { + "type": "StringEquals", + "column": "country", + "value": "Switzerland" + }, + { + "type": "PangoLineage", + "column": "pango_lineage", + "value": "B.1.1.7", + "includeSublineages": true + } + ] + } + }, + "expectedQueryResult": [ + { + "age": 4, + "country": "Switzerland", + "date": "2021-03-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1408408", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": null + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-03-21", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_1597890", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": null, + "unsorted_date": "2021-01-25" + } + ] +} diff --git a/endToEndTests/test/queries/GroupByLineageOrderByCountLimit.json b/endToEndTests/test/queries/GroupByLineageOrderByCountLimit.json index 5cc0aa6e8..60338524f 100644 --- a/endToEndTests/test/queries/GroupByLineageOrderByCountLimit.json +++ b/endToEndTests/test/queries/GroupByLineageOrderByCountLimit.json @@ -4,7 +4,12 @@ "action": { "type": "Aggregated", "groupByFields": ["pango_lineage"], - "orderByFields": ["count desc"], + "orderByFields": [ + { + "field": "count", + "ascending": false + } + ], "limit": 4 }, "filterExpression": { diff --git a/endToEndTests/test/queries/LimitLargerThanTable.json b/endToEndTests/test/queries/LimitLargerThanTable.json new file mode 100644 index 000000000..d13f69d50 --- /dev/null +++ b/endToEndTests/test/queries/LimitLargerThanTable.json @@ -0,0 +1,589 @@ +{ + "testCaseName": "Limit larger than table", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "limit": 1231241 + }, + "filterExpression": { + "type": "And", + "children": [ + { + "type": "StringEquals", + "column": "country", + "value": "Switzerland" + }, + { + "type": "PangoLineage", + "column": "pango_lineage", + "value": "B.1.1.7", + "includeSublineages": true + } + ] + } + }, + "expectedQueryResult": [ + { + "age": 57, + "country": "Switzerland", + "date": "2021-02-10", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1080536", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-08-04" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-02-14", + "division": "Graubünden", + "gisaid_epi_isl": "EPI_ISL_1119315", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-03-18" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2020-12-29", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1129663", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-07" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-02-23", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1195052", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-07-04" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-01-26", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1273458", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-05-18" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-03-08", + "division": "Jura", + "gisaid_epi_isl": "EPI_ISL_1360935", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-01-03" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-06", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_1361468", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-01-20" + }, + { + "age": 55, + "country": "Switzerland", + "date": null, + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1407962", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-01-16" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-03", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_1408062", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2020-11-24" + }, + { + "age": 4, + "country": "Switzerland", + "date": "2021-03-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1408408", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": null + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-03-21", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_1597890", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": null, + "unsorted_date": "2021-01-25" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-03-19", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1597932", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-02-10" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-05", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1747752", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-03-21" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-03-09", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1747885", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-03-03" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-03-03", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1748215", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2020-12-15" + }, + { + "age": null, + "country": "Switzerland", + "date": "2021-03-02", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1748243", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2020-11-24" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-03-25", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_1748395", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-04-27" + }, + { + "age": 4, + "country": "Switzerland", + "date": "2021-04-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1749892", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2020-12-24" + }, + { + "age": 5, + "country": "Switzerland", + "date": "2021-04-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1749899", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2020-03-08" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-04-15", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1749960", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-02-03" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-04-12", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_1760534", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-04-23" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-04-23", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_1840634", + "pango_lineage": "B.1.1.7.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-10" + }, + { + "age": 6, + "country": "Switzerland", + "date": "2021-04-25", + "division": "Aargau", + "gisaid_epi_isl": "EPI_ISL_2016901", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-01-29" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-04-23", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_2017036", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-03-09" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-04-28", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2019235", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-01-22" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-04-27", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2019350", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2020-12-21" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-12", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2180023", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2020-08-17" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-09", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2180995", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-05-25" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-05", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2181005", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2020-10-08" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213804", + "pango_lineage": "B.1.1.7.7", + "qc_value": null, + "region": "Europe", + "unsorted_date": "2021-04-12" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-05-13", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213934", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-04-23" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213984", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-09" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-10", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2214128", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2020-11-13" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-10", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2270139", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-08" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-05-11", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_2307766", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-05-08" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_2307888", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-23" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-07", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_2308054", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2020-12-09" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-23", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2360326", + "pango_lineage": "B.1.1.7.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-03-10" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-05-18", + "division": "Aargau", + "gisaid_epi_isl": "EPI_ISL_2374969", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-06-05" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-16", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_2375097", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2020-10-22" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_2375165", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2020-10-28" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-05-14", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_2375247", + "pango_lineage": "B.1.1.7", + "qc_value": null, + "region": "Europe", + "unsorted_date": "2021-05-11" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-05-10", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2375490", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-06-10" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-11", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2379651", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-06-01" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-05-24", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_2405276", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-04-28" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-25", + "division": "Obwalden", + "gisaid_epi_isl": "EPI_ISL_2408472", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-03-02" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-06-05", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2544226", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-05-12" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-06-03", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_2544332", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-05-13" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-06-01", + "division": "Schwyz", + "gisaid_epi_isl": "EPI_ISL_2544452", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-24" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-06-10", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_2574088", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-05" + }, + { + "age": null, + "country": "Switzerland", + "date": "2021-07-05", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_3016465", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-01-16" + } + ] +} diff --git a/endToEndTests/test/queries/Offset0.json b/endToEndTests/test/queries/Offset0.json new file mode 100644 index 000000000..d76118579 --- /dev/null +++ b/endToEndTests/test/queries/Offset0.json @@ -0,0 +1,589 @@ +{ + "testCaseName": "Offset by 0", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "offset": 0 + }, + "filterExpression": { + "type": "And", + "children": [ + { + "type": "StringEquals", + "column": "country", + "value": "Switzerland" + }, + { + "type": "PangoLineage", + "column": "pango_lineage", + "value": "B.1.1.7", + "includeSublineages": true + } + ] + } + }, + "expectedQueryResult": [ + { + "age": 57, + "country": "Switzerland", + "date": "2021-02-10", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1080536", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-08-04" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-02-14", + "division": "Graubünden", + "gisaid_epi_isl": "EPI_ISL_1119315", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-03-18" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2020-12-29", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1129663", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-07" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-02-23", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1195052", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-07-04" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-01-26", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1273458", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-05-18" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-03-08", + "division": "Jura", + "gisaid_epi_isl": "EPI_ISL_1360935", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-01-03" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-06", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_1361468", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-01-20" + }, + { + "age": 55, + "country": "Switzerland", + "date": null, + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1407962", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-01-16" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-03", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_1408062", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2020-11-24" + }, + { + "age": 4, + "country": "Switzerland", + "date": "2021-03-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1408408", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": null + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-03-21", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_1597890", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": null, + "unsorted_date": "2021-01-25" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-03-19", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1597932", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-02-10" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-05", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1747752", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-03-21" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-03-09", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1747885", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-03-03" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-03-03", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1748215", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2020-12-15" + }, + { + "age": null, + "country": "Switzerland", + "date": "2021-03-02", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_1748243", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2020-11-24" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-03-25", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_1748395", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-04-27" + }, + { + "age": 4, + "country": "Switzerland", + "date": "2021-04-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1749892", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2020-12-24" + }, + { + "age": 5, + "country": "Switzerland", + "date": "2021-04-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_1749899", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2020-03-08" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-04-15", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_1749960", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-02-03" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-04-12", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_1760534", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-04-23" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-04-23", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_1840634", + "pango_lineage": "B.1.1.7.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-10" + }, + { + "age": 6, + "country": "Switzerland", + "date": "2021-04-25", + "division": "Aargau", + "gisaid_epi_isl": "EPI_ISL_2016901", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-01-29" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-04-23", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_2017036", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-03-09" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-04-28", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2019235", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-01-22" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-04-27", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2019350", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2020-12-21" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-12", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2180023", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2020-08-17" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-09", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2180995", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-05-25" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-05", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2181005", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2020-10-08" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213804", + "pango_lineage": "B.1.1.7.7", + "qc_value": null, + "region": "Europe", + "unsorted_date": "2021-04-12" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-05-13", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213934", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2021-04-23" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2213984", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-09" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-10", + "division": "Geneva", + "gisaid_epi_isl": "EPI_ISL_2214128", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2020-11-13" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-03-10", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_2270139", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-08" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-05-11", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_2307766", + "pango_lineage": "B.1.1.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-05-08" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-05-08", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_2307888", + "pango_lineage": "B.1.1.7", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-23" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-07", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_2308054", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2020-12-09" + }, + { + "age": 57, + "country": "Switzerland", + "date": "2021-05-23", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2360326", + "pango_lineage": "B.1.1.7.7", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-03-10" + }, + { + "age": 54, + "country": "Switzerland", + "date": "2021-05-18", + "division": "Aargau", + "gisaid_epi_isl": "EPI_ISL_2374969", + "pango_lineage": "B.1.1.7", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-06-05" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-16", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_2375097", + "pango_lineage": "B.1.1.7", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2020-10-22" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-18", + "division": "Basel-Land", + "gisaid_epi_isl": "EPI_ISL_2375165", + "pango_lineage": "B.1.1.7", + "qc_value": 0.93, + "region": "Europe", + "unsorted_date": "2020-10-28" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-05-14", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_2375247", + "pango_lineage": "B.1.1.7", + "qc_value": null, + "region": "Europe", + "unsorted_date": "2021-05-11" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2021-05-10", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2375490", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-06-10" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2021-05-11", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_2379651", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-06-01" + }, + { + "age": 52, + "country": "Switzerland", + "date": "2021-05-24", + "division": "Vaud", + "gisaid_epi_isl": "EPI_ISL_2405276", + "pango_lineage": "B.1.1.7", + "qc_value": 0.94, + "region": "Europe", + "unsorted_date": "2021-04-28" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-05-25", + "division": "Obwalden", + "gisaid_epi_isl": "EPI_ISL_2408472", + "pango_lineage": "B.1.1.7", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2021-03-02" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2021-06-05", + "division": "Ticino", + "gisaid_epi_isl": "EPI_ISL_2544226", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-05-12" + }, + { + "age": 51, + "country": "Switzerland", + "date": "2021-06-03", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_2544332", + "pango_lineage": "B.1.1.7", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-05-13" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2021-06-01", + "division": "Schwyz", + "gisaid_epi_isl": "EPI_ISL_2544452", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-24" + }, + { + "age": 55, + "country": "Switzerland", + "date": "2021-06-10", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_2574088", + "pango_lineage": "B.1.1.7", + "qc_value": 0.91, + "region": "Europe", + "unsorted_date": "2021-05-05" + }, + { + "age": null, + "country": "Switzerland", + "date": "2021-07-05", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_3016465", + "pango_lineage": "B.1.1.7", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-01-16" + } + ] +} diff --git a/endToEndTests/test/queries/OffsetFull.json b/endToEndTests/test/queries/OffsetFull.json new file mode 100644 index 000000000..9a53756f9 --- /dev/null +++ b/endToEndTests/test/queries/OffsetFull.json @@ -0,0 +1,15 @@ +{ + "testCaseName": "Offset by exactly table size", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "offset": 100, + "limit": 90 + }, + "filterExpression": { + "type": "True" + } + }, + "expectedQueryResult": [] +} diff --git a/endToEndTests/test/queries/OffsetLargerThanTable.json b/endToEndTests/test/queries/OffsetLargerThanTable.json new file mode 100644 index 000000000..f4214f9e0 --- /dev/null +++ b/endToEndTests/test/queries/OffsetLargerThanTable.json @@ -0,0 +1,27 @@ +{ + "testCaseName": "Offset is larger than the table", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "offset": 1231241 + }, + "filterExpression": { + "type": "And", + "children": [ + { + "type": "StringEquals", + "column": "country", + "value": "Switzerland" + }, + { + "type": "PangoLineage", + "column": "pango_lineage", + "value": "B.1.1.7", + "includeSublineages": true + } + ] + } + }, + "expectedQueryResult": [] +} diff --git a/endToEndTests/test/queries/OffsetLimitOverlap.json b/endToEndTests/test/queries/OffsetLimitOverlap.json new file mode 100644 index 000000000..a4cef6984 --- /dev/null +++ b/endToEndTests/test/queries/OffsetLimitOverlap.json @@ -0,0 +1,126 @@ +{ + "testCaseName": "Offset overlaps with results to show", + "query": { + "action": { + "type": "Details", + "orderByFields": ["gisaid_epi_isl"], + "offset": 90, + "limit": 90 + }, + "filterExpression": { + "type": "True" + } + }, + "expectedQueryResult": [ + { + "age": 53, + "country": "Switzerland", + "date": "2020-11-24", + "division": "Zürich", + "gisaid_epi_isl": "EPI_ISL_721941", + "pango_lineage": "B.1.1.70", + "qc_value": 0.9, + "region": "Europe", + "unsorted_date": "2021-03-15" + }, + { + "age": 53, + "country": "Switzerland", + "date": "2020-12-14", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_737604", + "pango_lineage": "B.1.1", + "qc_value": 0.92, + "region": "Europe", + "unsorted_date": "2021-05-14" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2020-12-13", + "division": "Bern", + "gisaid_epi_isl": "EPI_ISL_737715", + "pango_lineage": "B.1.177", + "qc_value": 0.89, + "region": "Europe", + "unsorted_date": "2021-05-16" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2020-12-09", + "division": "Valais", + "gisaid_epi_isl": "EPI_ISL_737860", + "pango_lineage": "B.1.160", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-04-28" + }, + { + "age": 56, + "country": "Switzerland", + "date": "2020-12-24", + "division": "Sankt Gallen", + "gisaid_epi_isl": "EPI_ISL_768148", + "pango_lineage": "B.1.160", + "qc_value": 0.98, + "region": "Europe", + "unsorted_date": "2020-03-16" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2020-10-08", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_830864", + "pango_lineage": "B.1.177", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-03-03" + }, + { + "age": 59, + "country": "Switzerland", + "date": "2021-01-12", + "division": "Solothurn", + "gisaid_epi_isl": "EPI_ISL_899725", + "pango_lineage": "B.1.177", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-07-14" + }, + { + "age": 58, + "country": "Switzerland", + "date": "2020-12-25", + "division": "Schwyz", + "gisaid_epi_isl": "EPI_ISL_899762", + "pango_lineage": "B.1.177", + "qc_value": 0.97, + "region": "Europe", + "unsorted_date": "2021-07-19" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2020-10-22", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_931031", + "pango_lineage": "B.1.177", + "qc_value": 0.95, + "region": "Europe", + "unsorted_date": "2021-05-10" + }, + { + "age": 50, + "country": "Switzerland", + "date": "2020-10-28", + "division": "Basel-Stadt", + "gisaid_epi_isl": "EPI_ISL_931279", + "pango_lineage": "B.1.1", + "qc_value": 0.96, + "region": "Europe", + "unsorted_date": "2021-05-11" + } + ] +} diff --git a/endToEndTests/test/queries/OrderByAge.json b/endToEndTests/test/queries/OrderByAge.json index c47c691cf..f59c1f940 100644 --- a/endToEndTests/test/queries/OrderByAge.json +++ b/endToEndTests/test/queries/OrderByAge.json @@ -4,7 +4,12 @@ "action": { "type": "Aggregated", "groupByFields": ["age"], - "orderByFields": ["age asc"] + "orderByFields": [ + { + "field": "age", + "ascending": true + } + ] }, "filterExpression": { "type": "True" diff --git a/endToEndTests/test/queries/OrderByFloat.json b/endToEndTests/test/queries/OrderByFloat.json index a2d5eccf3..ae558c168 100644 --- a/endToEndTests/test/queries/OrderByFloat.json +++ b/endToEndTests/test/queries/OrderByFloat.json @@ -4,7 +4,7 @@ "action": { "type": "Aggregated", "groupByFields": ["qc_value"], - "orderByFields": ["qc_value asc"] + "orderByFields": ["qc_value"] }, "filterExpression": { "type": "True" diff --git a/endToEndTests/test/queries/OrderByFloatDesc.json b/endToEndTests/test/queries/OrderByFloatDesc.json index 7f96ff16e..20b42aab6 100644 --- a/endToEndTests/test/queries/OrderByFloatDesc.json +++ b/endToEndTests/test/queries/OrderByFloatDesc.json @@ -4,7 +4,12 @@ "action": { "type": "Aggregated", "groupByFields": ["qc_value"], - "orderByFields": ["qc_value desc"] + "orderByFields": [ + { + "field": "qc_value", + "ascending": false + } + ] }, "filterExpression": { "type": "True" diff --git a/endToEndTests/test/queries/OrderByFloatFiltered.json b/endToEndTests/test/queries/OrderByFloatFiltered.json index b9d69f17c..26d355e40 100644 --- a/endToEndTests/test/queries/OrderByFloatFiltered.json +++ b/endToEndTests/test/queries/OrderByFloatFiltered.json @@ -4,7 +4,7 @@ "action": { "type": "Aggregated", "groupByFields": ["qc_value"], - "orderByFields": ["qc_value asc"] + "orderByFields": ["qc_value"] }, "filterExpression": { "from": 0.1, diff --git a/include/silo/config/database_config.h b/include/silo/config/database_config.h index 648390fe4..821974f0a 100644 --- a/include/silo/config/database_config.h +++ b/include/silo/config/database_config.h @@ -32,7 +32,7 @@ struct DatabaseConfig { std::string default_nucleotide_sequence; DatabaseSchema schema; - [[nodiscard]] DatabaseMetadata getMetadata(const std::string& name) const; + [[nodiscard]] std::optional getMetadata(const std::string& name) const; }; } // namespace silo::config diff --git a/include/silo/query_engine/actions/action.h b/include/silo/query_engine/actions/action.h index 674042e61..459f9c9ca 100644 --- a/include/silo/query_engine/actions/action.h +++ b/include/silo/query_engine/actions/action.h @@ -2,6 +2,7 @@ #define SILO_ACTION_H #include +#include #include @@ -19,6 +20,17 @@ struct DatabasePartition; namespace silo::query_engine::actions { class Action { + public: + struct OrderByField { + std::string name; + bool ascending; + }; + + protected: + std::vector order_by_fields; + std::optional limit; + std::optional offset; + public: Action(); virtual ~Action() = default; @@ -27,6 +39,14 @@ class Action { const Database& database, std::vector bitmap_filter ) const = 0; + + void applyOrderByAndLimit(QueryResult& result) const; + + void setOrdering( + const std::vector& order_by_fields, + std::optional limit, + std::optional offset + ); }; // NOLINTNEXTLINE(readability-identifier-naming) diff --git a/include/silo/query_engine/actions/aggregated.h b/include/silo/query_engine/actions/aggregated.h index e1830242d..5059ef2cd 100644 --- a/include/silo/query_engine/actions/aggregated.h +++ b/include/silo/query_engine/actions/aggregated.h @@ -10,15 +10,9 @@ namespace silo::query_engine::actions { class Aggregated : public Action { private: std::vector group_by_fields; - std::vector order_by_fields; - std::optional limit; public: - Aggregated( - std::vector group_by_fields, - std::vector order_by_fields, - std::optional limit - ); + Aggregated(std::vector group_by_fields); [[nodiscard]] QueryResult execute( const Database& database, diff --git a/src/silo/config/database_config.cpp b/src/silo/config/database_config.cpp index 011ded49b..8e26b675b 100644 --- a/src/silo/config/database_config.cpp +++ b/src/silo/config/database_config.cpp @@ -52,14 +52,14 @@ ColumnType DatabaseMetadata::getColumnType() const { throw std::runtime_error("Did not find metadata with name: " + std::string(name)); } -DatabaseMetadata DatabaseConfig::getMetadata(const std::string& name) const { +std::optional DatabaseConfig::getMetadata(const std::string& name) const { auto element = std::find_if( std::begin(schema.metadata), std::end(schema.metadata), [&name](const auto& metadata) { return metadata.name == name; } ); if (element == std::end(schema.metadata)) { - throw std::runtime_error("Unknown metadata type: " + std::string(name)); + return std::nullopt; } return *element; } diff --git a/src/silo/query_engine/actions/action.cpp b/src/silo/query_engine/actions/action.cpp index f43b137f2..348665c64 100644 --- a/src/silo/query_engine/actions/action.cpp +++ b/src/silo/query_engine/actions/action.cpp @@ -9,11 +9,86 @@ #include "silo/query_engine/actions/fasta_aligned.h" #include "silo/query_engine/actions/nuc_mutations.h" #include "silo/query_engine/query_parse_exception.h" +#include "silo/query_engine/query_result.h" namespace silo::query_engine::actions { Action::Action() = default; +std::string stringToLowerCase(std::string str) { + std::transform(str.begin(), str.end(), str.begin(), [](unsigned char character) { + return std::tolower(character); + }); + return str; +} + +void Action::applyOrderByAndLimit(QueryResult& result) const { + auto& result_vector = result.query_result; + auto cmp = [&](const QueryResultEntry& entry1, const QueryResultEntry& entry2) { + for (const OrderByField& field : order_by_fields) { + if (entry1.fields.at(field.name) == entry2.fields.at(field.name)) { + continue; + } + return entry1.fields.at(field.name) < entry2.fields.at(field.name) ? field.ascending + : !field.ascending; + } + return false; + }; + int64_t end_of_sort = static_cast(std::min( + static_cast(limit.value_or(result_vector.size()) + offset.value_or(0UL)), + result_vector.size() + )); + if (end_of_sort < result_vector.size()) { + std::partial_sort( + result_vector.begin(), result_vector.begin() + end_of_sort, result_vector.end(), cmp + ); + } else { + std::sort(result_vector.begin(), result_vector.end(), cmp); + } + + if (offset.value_or(0) > 0) { + if (offset.value() >= result_vector.size()) { + result_vector = {}; + return; + } + auto begin = result_vector.begin() + offset.value(); + auto end = result_vector.end(); + if (end_of_sort < result_vector.size()) { + end = result_vector.begin() + (end_of_sort); + } + std::copy(begin, end, result_vector.begin()); + end_of_sort -= offset.value(); + } + if (end_of_sort < result_vector.size()) { + result_vector.resize(end_of_sort); + } +} + +void Action::setOrdering( + const std::vector& order_by_fields_, + std::optional limit_, + std::optional offset_ +) { + order_by_fields = order_by_fields_; + limit = limit_; + offset = offset_; +} + +void from_json(const nlohmann::json& json, Action::OrderByField& field) { + if (json.is_string()) { + field = {json.get(), true}; + return; + } + CHECK_SILO_QUERY( + json.is_object() && json.contains("field") && json.contains("ascending") && + json["field"].is_string() && json["ascending"].is_boolean(), + "The orderByField '" + json.dump() + + "' must be either a string or an object containing the fields 'field':string and " + "'ascending':boolean" + ) + field = {json["field"].get(), json["ascending"].get()}; +} + void from_json(const nlohmann::json& json, std::unique_ptr& action) { CHECK_SILO_QUERY(json.contains("type"), "The field 'type' is required in any action") CHECK_SILO_QUERY( @@ -36,6 +111,23 @@ void from_json(const nlohmann::json& json, std::unique_ptr& action) { } else { throw QueryParseException(expression_type + " is not a valid action"); } + + auto order_by_fields = json.contains("orderByFields") + ? json["orderByFields"].get>() + : std::vector(); + CHECK_SILO_QUERY( + !json.contains("limit") || json["limit"].is_number_unsigned(), + "If the action contains a limit, it must be a non-negative number" + ) + CHECK_SILO_QUERY( + !json.contains("offset") || json["offset"].is_number_unsigned(), + "If the action contains an offset, it must be a non-negative number" + ) + auto limit = json.contains("limit") ? std::optional(json["limit"].get()) + : std::nullopt; + auto offset = json.contains("offset") ? std::optional(json["offset"].get()) + : std::nullopt; + action->setOrdering(order_by_fields, limit, offset); } } // namespace silo::query_engine::actions diff --git a/src/silo/query_engine/actions/aggregated.cpp b/src/silo/query_engine/actions/aggregated.cpp index 7030f1d59..b570351e2 100644 --- a/src/silo/query_engine/actions/aggregated.cpp +++ b/src/silo/query_engine/actions/aggregated.cpp @@ -162,60 +162,6 @@ struct std::hash { namespace silo::query_engine::actions { -struct OrderByField { - std::string name; - bool ascending; -}; - -std::string stringToLowerCase(std::string str) { - std::transform(str.begin(), str.end(), str.begin(), [](unsigned char character) { - return std::tolower(character); - }); - return str; -} - -OrderByField parseOrderByField(const std::string& order_by_field) { - bool ascending = true; - - std::string accessed_column = order_by_field; - - auto space_position = order_by_field.find(' '); - if (space_position != order_by_field.size()) { - accessed_column = order_by_field.substr(0, space_position); - const std::string additional_instruction = - stringToLowerCase(order_by_field.substr(space_position + 1)); - if (additional_instruction == "asc" || additional_instruction == "ascending") { - ascending = true; - } else if (additional_instruction == "desc" || additional_instruction == "descending") { - ascending = false; - } - } - - return OrderByField{accessed_column, ascending}; -} - -void applyOrderByAndLimit( - std::vector& result, - const std::vector& order_by_fields, - std::optional limit -) { - auto cmp = [&order_by_fields](const QueryResultEntry& entry1, const QueryResultEntry& entry2) { - for (const OrderByField& field : order_by_fields) { - if (entry1.fields.at(field.name) == entry2.fields.at(field.name)) { - continue; - } - return entry1.fields.at(field.name) < entry2.fields.at(field.name) ? field.ascending - : !field.ascending; - } - return false; - }; - if (limit.has_value() && limit.value() < result.size()) { - std::partial_sort(result.begin(), result.begin() + limit.value(), result.end(), cmp); - result.resize(limit.value()); - } else { - std::sort(result.begin(), result.end(), cmp); - } -} const std::string COUNT_FIELD = "count"; std::vector generateResult(std::unordered_map& tuple_counts) { @@ -239,14 +185,8 @@ QueryResult aggregateWithoutGrouping(const std::vector& bitmap_f return QueryResult{std::vector{{tuple_fields}}}; } -Aggregated::Aggregated( - std::vector group_by_fields, - std::vector order_by_fields, - std::optional limit -) - : group_by_fields(std::move(group_by_fields)), - order_by_fields(std::move(order_by_fields)), - limit(limit) {} +Aggregated::Aggregated(std::vector group_by_fields) + : group_by_fields(std::move(group_by_fields)) {} QueryResult Aggregated::execute( const Database& database, @@ -255,31 +195,20 @@ QueryResult Aggregated::execute( if (group_by_fields.empty()) { return aggregateWithoutGrouping(bitmap_filters); } - if (group_by_fields.size() == 1) { - const std::string group_by_field = group_by_fields[0]; - const auto& metadata = database.database_config.getMetadata(group_by_field); - if (metadata.name == database.database_config.schema.primary_key) { - throw QueryParseException("Cannot group by primary key field: '" + group_by_field + "'"); - } - // TODO(#133) optimize when equal to partition_by field - // TODO(#133) optimize single field groupby - } + // TODO(#133) optimize when equal to partition_by field + // TODO(#133) optimize single field groupby + /*if (group_by_fields.size() == 1) { + }*/ std::vector group_by_metadata; for (const std::string& group_by_field : group_by_fields) { const auto& metadata = database.database_config.getMetadata(group_by_field); - group_by_metadata.push_back(metadata); + CHECK_SILO_QUERY( + metadata.has_value(), "Metadata field '" + group_by_field + "' to group by not found" + ) + group_by_metadata.push_back(*metadata); } - std::vector order_by_definition; - bool randomize_order = false; - for (const std::string& order_by_field : order_by_fields) { - if (order_by_field == "random()") { - randomize_order = true; - break; - } - order_by_definition.push_back(parseOrderByField(order_by_field)); - } - for (const OrderByField& field : order_by_definition) { + for (const Action::OrderByField& field : order_by_fields) { if (field.name != COUNT_FIELD && !std::any_of(group_by_metadata.begin(), group_by_metadata.end(), [&field](const config::DatabaseMetadata& group_by_field) { return group_by_field.name == field.name; })) { @@ -316,26 +245,15 @@ QueryResult Aggregated::execute( final_map[key] += value; } } - std::vector result = generateResult(final_map); - if (randomize_order) { - const uint32_t time_based_seed = std::chrono::system_clock::now().time_since_epoch().count(); - std::default_random_engine rng(time_based_seed); - std::shuffle(result.begin(), result.end(), rng); - } - if (!order_by_definition.empty()) { - applyOrderByAndLimit(result, order_by_definition, limit); - } - return {result}; + QueryResult result = {generateResult(final_map)}; + applyOrderByAndLimit(result); + return result; } void from_json(const nlohmann::json& json, std::unique_ptr& action) { const std::vector group_by_fields = json.value("groupByFields", std::vector()); - const std::vector order_by_fields = - json.value("orderByFields", std::vector()); - const std::optional limit = - json.contains("limit") ? std::optional(json["limit"]) : std::nullopt; - action = std::make_unique(group_by_fields, order_by_fields, limit); + action = std::make_unique(group_by_fields); } } // namespace silo::query_engine::actions diff --git a/src/silo/query_engine/actions/details.cpp b/src/silo/query_engine/actions/details.cpp index 9d5dd6a85..4232330d8 100644 --- a/src/silo/query_engine/actions/details.cpp +++ b/src/silo/query_engine/actions/details.cpp @@ -7,6 +7,7 @@ #include "silo/config/database_config.h" #include "silo/database.h" #include "silo/query_engine/operator_result.h" +#include "silo/query_engine/query_parse_exception.h" #include "silo/query_engine/query_result.h" #include "silo/storage/database_partition.h" @@ -24,18 +25,37 @@ std::vector parseFields( std::vector field_metadata; for (const std::string& field : fields) { const auto& metadata = database.database_config.getMetadata(field); - field_metadata.push_back(metadata); + CHECK_SILO_QUERY(metadata.has_value(), "Metadata field " + field + " not found.") + field_metadata.push_back(metadata.value()); } return field_metadata; } +void validateOrderByFields( + const std::vector& order_by_fields, + const std::vector& field_metadata +) { + for (const Action::OrderByField& field : order_by_fields) { + CHECK_SILO_QUERY( + std::any_of( + field_metadata.begin(), + field_metadata.end(), + [&](const config::DatabaseMetadata& metadata) { return metadata.name == field.name; } + ), + "OrderByField " + field.name + " is not contained in the result of this operation." + ) + } +} + QueryResult Details::execute( const silo::Database& database, std::vector bitmap_filter ) const { const std::vector field_metadata = parseFields(database, fields); - std::vector results; + validateOrderByFields(order_by_fields, field_metadata); + + QueryResult results; for (size_t partition_id = 0; partition_id < database.partitions.size(); partition_id++) { const auto& bitmap = bitmap_filter[partition_id]; const auto& columns = database.partitions[partition_id].columns; @@ -93,10 +113,11 @@ QueryResult Details::execute( throw std::runtime_error("Unchecked column type of column " + metadata.name); } } - results.push_back(QueryResultEntry{row_fields}); + results.query_result.push_back(QueryResultEntry{row_fields}); } } - return {results}; + applyOrderByAndLimit(results); + return results; } // NOLINTNEXTLINE(readability-identifier-naming)