Skip to content

Commit 5b27725

Browse files
committed
to fix window function parsing + mapping within bucket scripts
1 parent 2b85c83 commit 5b27725

File tree

10 files changed

+118
-110
lines changed

10 files changed

+118
-110
lines changed

bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticAggregation.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -659,17 +659,17 @@ object ElasticAggregation {
659659
val currentBucketPath =
660660
bucketScriptAggregation.identifier.nestedElement.map(_.nestedPath).getOrElse("")
661661
// Extract ALL metrics paths
662-
val allMetricsPaths = bucketScriptAggregation.params.keys
662+
val allMetricsPaths = bucketScriptAggregation.params
663663
val result =
664-
allMetricsPaths.flatMap { metricName =>
665-
allAggregations.find(agg => agg.aggName == metricName || agg.field == metricName) match {
664+
allMetricsPaths.flatMap { metric =>
665+
allAggregations.find(agg => agg.aggName == metric._2 || agg.field == metric._2) match {
666666
case Some(sqlAgg) =>
667667
val metricBucketPath = sqlAgg.nestedElement
668668
.map(_.nestedPath)
669669
.getOrElse("")
670670
if (metricBucketPath == currentBucketPath) {
671671
// Metric of the same level
672-
Some(metricName -> metricName)
672+
Some(metric._1 -> metric._2)
673673
} else if (isDirectChild(metricBucketPath, currentBucketPath)) {
674674
// Metric of a direct child
675675
// CHECK if it is a "global" metric (cardinality, etc.) or a bucket metric (avg, sum, etc.)
@@ -683,7 +683,7 @@ object ElasticAggregation {
683683
// println(
684684
// s"[DEBUG extractMetricsPath] Direct child (global metric): $metricName -> $childNestedName>$metricName"
685685
// )
686-
Some(metricName -> s"$childNestedName>$metricName")
686+
Some(metric._1 -> s"$childNestedName>${metric._2}")
687687
} else {
688688
// Bucket metric: cannot be referenced from the parent
689689
// println(

bridge/src/test/scala/app/softnetwork/elastic/sql/SQLQuerySpec.scala

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,47 +1182,47 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
11821182
println(query)
11831183
query shouldBe
11841184
"""{
1185-
| "query": {
1186-
| "bool": {
1187-
| "filter": [
1188-
| {
1189-
| "exists": {
1190-
| "field": "identifier2"
1191-
| }
1192-
| }
1193-
| ]
1194-
| }
1195-
| },
1196-
| "size": 0,
1197-
| "_source": false,
1198-
| "aggs": {
1199-
| "identifier": {
1200-
| "terms": {
1201-
| "field": "identifier",
1202-
| "min_doc_count": 1,
1203-
| "order": {
1204-
| "ct": "desc"
1205-
| }
1206-
| },
1207-
| "aggs": {
1208-
| "lastSeen": {
1209-
| "max": {
1210-
| "field": "createdAt",
1211-
| "script": {
1212-
| "lang": "painless",
1213-
| "source": "def param1 = (doc['createdAt'].size() == 0 ? null : doc['createdAt'].value); (param1 == null) ? null : LocalDate.parse(param1, DateTimeFormatter.ofPattern(\"yyyy-MM-dd\"))"
1214-
| }
1215-
| }
1216-
| },
1217-
| "ct": {
1218-
| "value_count": {
1219-
| "field": "identifier2"
1220-
| }
1221-
| }
1222-
| }
1223-
| }
1224-
| }
1225-
|}""".stripMargin
1185+
| "query": {
1186+
| "bool": {
1187+
| "filter": [
1188+
| {
1189+
| "exists": {
1190+
| "field": "identifier2"
1191+
| }
1192+
| }
1193+
| ]
1194+
| }
1195+
| },
1196+
| "size": 0,
1197+
| "_source": false,
1198+
| "aggs": {
1199+
| "identifier": {
1200+
| "terms": {
1201+
| "field": "identifier",
1202+
| "min_doc_count": 1,
1203+
| "order": {
1204+
| "ct": "desc"
1205+
| }
1206+
| },
1207+
| "aggs": {
1208+
| "ct": {
1209+
| "value_count": {
1210+
| "field": "identifier2"
1211+
| }
1212+
| },
1213+
| "lastSeen": {
1214+
| "max": {
1215+
| "field": "createdAt",
1216+
| "script": {
1217+
| "lang": "painless",
1218+
| "source": "def param1 = (doc['createdAt'].size() == 0 ? null : doc['createdAt'].value); (param1 == null) ? null : LocalDate.parse(param1, DateTimeFormatter.ofPattern(\"yyyy-MM-dd\"))"
1219+
| }
1220+
| }
1221+
| }
1222+
| }
1223+
| }
1224+
| }
1225+
|}""".stripMargin
12261226
.replaceAll("\\s", "")
12271227
.replaceAll("defp", "def p")
12281228
.replaceAll("defe", "def e")
@@ -1350,47 +1350,47 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
13501350
println(query)
13511351
query shouldBe
13521352
"""{
1353-
| "query": {
1354-
| "bool": {
1355-
| "filter": [
1356-
| {
1357-
| "exists": {
1358-
| "field": "identifier2"
1359-
| }
1360-
| }
1361-
| ]
1362-
| }
1363-
| },
1364-
| "size": 0,
1365-
| "_source": false,
1366-
| "aggs": {
1367-
| "identifier": {
1368-
| "terms": {
1369-
| "field": "identifier",
1370-
| "min_doc_count": 1,
1371-
| "order": {
1372-
| "ct": "desc"
1373-
| }
1374-
| },
1375-
| "aggs": {
1376-
| "lastSeen": {
1377-
| "max": {
1378-
| "field": "createdAt",
1379-
| "script": {
1380-
| "lang": "painless",
1381-
| "source": "def param1 = (doc['createdAt'].size() == 0 ? null : doc['createdAt'].value); (param1 == null) ? null : ZonedDateTime.parse(param1, DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS XXX\")).truncatedTo(ChronoUnit.MINUTES).get(ChronoField.YEAR)"
1382-
| }
1383-
| }
1384-
| },
1385-
| "ct": {
1386-
| "value_count": {
1387-
| "field": "identifier2"
1388-
| }
1389-
| }
1390-
| }
1391-
| }
1392-
| }
1393-
|}""".stripMargin
1353+
| "query": {
1354+
| "bool": {
1355+
| "filter": [
1356+
| {
1357+
| "exists": {
1358+
| "field": "identifier2"
1359+
| }
1360+
| }
1361+
| ]
1362+
| }
1363+
| },
1364+
| "size": 0,
1365+
| "_source": false,
1366+
| "aggs": {
1367+
| "identifier": {
1368+
| "terms": {
1369+
| "field": "identifier",
1370+
| "min_doc_count": 1,
1371+
| "order": {
1372+
| "ct": "desc"
1373+
| }
1374+
| },
1375+
| "aggs": {
1376+
| "ct": {
1377+
| "value_count": {
1378+
| "field": "identifier2"
1379+
| }
1380+
| },
1381+
| "lastSeen": {
1382+
| "max": {
1383+
| "field": "createdAt",
1384+
| "script": {
1385+
| "lang": "painless",
1386+
| "source": "def param1 = (doc['createdAt'].size() == 0 ? null : doc['createdAt'].value); (param1 == null) ? null : ZonedDateTime.parse(param1, DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS XXX\")).truncatedTo(ChronoUnit.MINUTES).get(ChronoField.YEAR)"
1387+
| }
1388+
| }
1389+
| }
1390+
| }
1391+
| }
1392+
| }
1393+
|}""".stripMargin
13941394
.replaceAll("\\s", "")
13951395
.replaceAll("defp", "def p")
13961396
.replaceAll("defe", "def e")

es6/bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticAggregation.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -659,17 +659,17 @@ object ElasticAggregation {
659659
val currentBucketPath =
660660
bucketScriptAggregation.identifier.nestedElement.map(_.nestedPath).getOrElse("")
661661
// Extract ALL metrics paths
662-
val allMetricsPaths = bucketScriptAggregation.params.keys
662+
val allMetricsPaths = bucketScriptAggregation.params
663663
val result =
664-
allMetricsPaths.flatMap { metricName =>
665-
allAggregations.find(agg => agg.aggName == metricName || agg.field == metricName) match {
664+
allMetricsPaths.flatMap { metric =>
665+
allAggregations.find(agg => agg.aggName == metric._2 || agg.field == metric._2) match {
666666
case Some(sqlAgg) =>
667667
val metricBucketPath = sqlAgg.nestedElement
668668
.map(_.nestedPath)
669669
.getOrElse("")
670670
if (metricBucketPath == currentBucketPath) {
671671
// Metric of the same level
672-
Some(metricName -> metricName)
672+
Some(metric._1 -> metric._2)
673673
} else if (isDirectChild(metricBucketPath, currentBucketPath)) {
674674
// Metric of a direct child
675675
// CHECK if it is a "global" metric (cardinality, etc.) or a bucket metric (avg, sum, etc.)
@@ -683,7 +683,7 @@ object ElasticAggregation {
683683
// println(
684684
// s"[DEBUG extractMetricsPath] Direct child (global metric): $metricName -> $childNestedName>$metricName"
685685
// )
686-
Some(metricName -> s"$childNestedName>$metricName")
686+
Some(metric._1 -> s"$childNestedName>${metric._2}")
687687
} else {
688688
// Bucket metric: cannot be referenced from the parent
689689
// println(

es6/bridge/src/test/scala/app/softnetwork/elastic/sql/SQLQuerySpec.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,11 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
12051205
| }
12061206
| },
12071207
| "aggs": {
1208+
| "ct": {
1209+
| "value_count": {
1210+
| "field": "identifier2"
1211+
| }
1212+
| },
12081213
| "lastSeen": {
12091214
| "max": {
12101215
| "field": "createdAt",
@@ -1213,11 +1218,6 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
12131218
| "source": "def param1 = (doc['createdAt'].size() == 0 ? null : doc['createdAt'].value); (param1 == null) ? null : LocalDate.parse(param1, DateTimeFormatter.ofPattern(\"yyyy-MM-dd\"))"
12141219
| }
12151220
| }
1216-
| },
1217-
| "ct": {
1218-
| "value_count": {
1219-
| "field": "identifier2"
1220-
| }
12211221
| }
12221222
| }
12231223
| }
@@ -1373,6 +1373,11 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
13731373
| }
13741374
| },
13751375
| "aggs": {
1376+
| "ct": {
1377+
| "value_count": {
1378+
| "field": "identifier2"
1379+
| }
1380+
| },
13761381
| "lastSeen": {
13771382
| "max": {
13781383
| "field": "createdAt",
@@ -1381,11 +1386,6 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
13811386
| "source": "def param1 = (doc['createdAt'].size() == 0 ? null : doc['createdAt'].value); (param1 == null) ? null : ZonedDateTime.parse(param1, DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS XXX\")).truncatedTo(ChronoUnit.MINUTES).get(ChronoField.YEAR)"
13821387
| }
13831388
| }
1384-
| },
1385-
| "ct": {
1386-
| "value_count": {
1387-
| "field": "identifier2"
1388-
| }
13891389
| }
13901390
| }
13911391
| }

sql/src/main/scala/app/softnetwork/elastic/sql/parser/GroupByParser.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ trait GroupByParser {
2525
def bucketWithFunction: PackratParser[Identifier] =
2626
identifierWithArithmeticExpression |
2727
identifierWithTransformation |
28+
identifierWithWindowFunction |
2829
identifierWithAggregation |
2930
identifierWithIntervalFunction |
3031
identifierWithFunction |

sql/src/main/scala/app/softnetwork/elastic/sql/parser/OrderByParser.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ trait OrderByParser {
3333
def fieldWithFunction: PackratParser[Identifier] =
3434
identifierWithArithmeticExpression |
3535
identifierWithTransformation |
36+
identifierWithWindowFunction |
3637
identifierWithAggregation |
3738
identifierWithIntervalFunction |
3839
identifierWithFunction |

sql/src/main/scala/app/softnetwork/elastic/sql/parser/Parser.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,12 @@ trait Parser
238238
"length",
239239
"lower",
240240
"upper",
241-
"trim"
241+
"trim",
242+
"first",
243+
"last",
244+
"array_agg",
245+
"first_value",
246+
"last_value"
242247
// "ltrim",
243248
// "rtrim",
244249
// "replace",

sql/src/main/scala/app/softnetwork/elastic/sql/parser/SelectParser.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ trait SelectParser {
2222
self: Parser with WhereParser =>
2323

2424
def field: PackratParser[Field] =
25-
(identifierWithWindowFunction |
26-
identifierWithArithmeticExpression |
25+
(identifierWithArithmeticExpression |
2726
identifierWithTransformation |
27+
identifierWithWindowFunction |
2828
identifierWithAggregation |
2929
identifierWithIntervalFunction |
3030
identifierWithFunction |

sql/src/main/scala/app/softnetwork/elastic/sql/parser/WhereParser.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ trait WhereParser {
9595
private def any_identifier: PackratParser[Identifier] =
9696
identifierWithArithmeticExpression |
9797
identifierWithTransformation |
98+
identifierWithWindowFunction |
9899
identifierWithAggregation |
99100
identifierWithIntervalFunction |
100101
identifierWithFunction |

sql/src/main/scala/app/softnetwork/elastic/sql/parser/function/aggregate/package.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,27 +96,27 @@ package object aggregate {
9696
}
9797

9898
def count_agg: PackratParser[WindowFunction] =
99-
count ~ window_function() ^^ { case _ ~ top =>
99+
count ~ window_function(aggWithFunction) ^^ { case _ ~ top =>
100100
CountAgg(top._1, top._2)
101101
}
102102

103103
def min_agg: PackratParser[WindowFunction] =
104-
min ~ window_function() ^^ { case _ ~ top =>
104+
min ~ window_function(aggWithFunction) ^^ { case _ ~ top =>
105105
MinAgg(top._1, top._2)
106106
}
107107

108108
def max_agg: PackratParser[WindowFunction] =
109-
max ~ window_function() ^^ { case _ ~ top =>
109+
max ~ window_function(aggWithFunction) ^^ { case _ ~ top =>
110110
MaxAgg(top._1, top._2)
111111
}
112112

113113
def avg_agg: PackratParser[WindowFunction] =
114-
avg ~ window_function() ^^ { case _ ~ top =>
114+
avg ~ window_function(aggWithFunction) ^^ { case _ ~ top =>
115115
AvgAgg(top._1, top._2)
116116
}
117117

118118
def sum_agg: PackratParser[WindowFunction] =
119-
sum ~ window_function() ^^ { case _ ~ top =>
119+
sum ~ window_function(aggWithFunction) ^^ { case _ ~ top =>
120120
SumAgg(top._1, top._2)
121121
}
122122

0 commit comments

Comments
 (0)