Skip to content

Commit 10b7165

Browse files
authored
Merge pull request #15 from SOFTNETWORK-APP/feature/dateTimeFunctions
add support for date time functions : * Date DATE_ADD(date, INTERVAL) DATE_SUB(date, INTERVAL) PARSE_DATE(string, format) FORMAT_DATE(date, format) DATE_TRUNC(date, unit) * DateTime DATETIME_ADD(datetime, INTERVAL) DATETIME_SUB(datetime, INTERVAL) PARSE_DATETIME(string, format) FORMAT_DATETIME(datetime, format) * Diff DATE_DIFF(end, start, unit) * System (default values) CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP NOW * Transformation + / - INTERVAL YEAR MONTH DAY HOUR MINUTE SECOND
2 parents afda884 + 9d60fcf commit 10b7165

File tree

25 files changed

+2663
-262
lines changed

25 files changed

+2663
-262
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ThisBuild / organization := "app.softnetwork"
1919

2020
name := "softclient4es"
2121

22-
ThisBuild / version := "0.4.0"
22+
ThisBuild / version := "0.5.0"
2323

2424
ThisBuild / scalaVersion := scala213
2525

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

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import app.softnetwork.elastic.sql.{
77
BucketSelectorScript,
88
Count,
99
ElasticBoolQuery,
10+
Field,
1011
Max,
1112
Min,
1213
SQLBucket,
1314
SQLCriteria,
14-
SQLField,
15+
SQLFunctionUtils,
1516
SortOrder,
1617
Sum
1718
}
@@ -57,7 +58,7 @@ case class ElasticAggregation(
5758

5859
object ElasticAggregation {
5960
def apply(
60-
sqlAgg: SQLField,
61+
sqlAgg: Field,
6162
having: Option[SQLCriteria],
6263
bucketsDirection: Map[String, SortOrder]
6364
): ElasticAggregation = {
@@ -88,6 +89,23 @@ object ElasticAggregation {
8889

8990
var aggPath = Seq[String]()
9091

92+
val (aggFuncs, transformFuncs) = SQLFunctionUtils.aggregateAndTransformFunctions(identifier)
93+
94+
require(aggFuncs.size == 1, s"Multiple aggregate functions not supported: $aggFuncs")
95+
96+
def aggWithFieldOrScript(
97+
buildField: (String, String) => Aggregation,
98+
buildScript: (String, Script) => Aggregation
99+
): Aggregation = {
100+
if (transformFuncs.nonEmpty) {
101+
val scriptSrc = identifier.painless
102+
val script = Script(scriptSrc).lang("painless")
103+
buildScript(aggName, script)
104+
} else {
105+
buildField(aggName, sourceField)
106+
}
107+
}
108+
91109
val _agg =
92110
aggType match {
93111
case Count =>
@@ -96,10 +114,10 @@ object ElasticAggregation {
96114
else {
97115
valueCountAgg(aggName, sourceField)
98116
}
99-
case Min => minAgg(aggName, sourceField)
100-
case Max => maxAgg(aggName, sourceField)
101-
case Avg => avgAgg(aggName, sourceField)
102-
case Sum => sumAgg(aggName, sourceField)
117+
case Min => aggWithFieldOrScript(minAgg, (name, s) => minAgg(name, sourceField).script(s))
118+
case Max => aggWithFieldOrScript(maxAgg, (name, s) => maxAgg(name, sourceField).script(s))
119+
case Avg => aggWithFieldOrScript(avgAgg, (name, s) => avgAgg(name, sourceField).script(s))
120+
case Sum => aggWithFieldOrScript(sumAgg, (name, s) => sumAgg(name, sourceField).script(s))
103121
}
104122

105123
val filteredAggName = "filtered_agg"

es6/sql-bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticQuery.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import app.softnetwork.elastic.sql.{
99
ElasticNested,
1010
ElasticParent,
1111
SQLBetween,
12+
SQLComparisonDateMath,
1213
SQLExpression,
1314
SQLIn,
1415
SQLIsNotNull,
1516
SQLIsNull
1617
}
17-
import com.sksamuel.elastic4s.ElasticApi.{bool, _}
18+
import com.sksamuel.elastic4s.ElasticApi._
1819
import com.sksamuel.elastic4s.searches.queries.Query
1920

2021
case class ElasticQuery(filter: ElasticFilter) {
@@ -69,6 +70,7 @@ case class ElasticQuery(filter: ElasticFilter) {
6970
case between: SQLBetween[Double] => between
7071
case geoDistance: ElasticGeoDistance => geoDistance
7172
case matchExpression: ElasticMatch => matchExpression
73+
case dateMath: SQLComparisonDateMath => dateMath
7274
case other =>
7375
throw new IllegalArgumentException(s"Unsupported filter type: ${other.getClass.getName}")
7476
}

es6/sql-bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticSearchRequest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package app.softnetwork.elastic.sql.bridge
22

3-
import app.softnetwork.elastic.sql.{SQLBucket, SQLCriteria, SQLExcept, SQLField}
3+
import app.softnetwork.elastic.sql.{Field, SQLBucket, SQLCriteria, SQLExcept}
44
import com.sksamuel.elastic4s.searches.SearchRequest
55
import com.sksamuel.elastic4s.http.search.SearchBodyBuilderFn
66

77
case class ElasticSearchRequest(
8-
fields: Seq[SQLField],
8+
fields: Seq[Field],
99
except: Option[SQLExcept],
1010
sources: Seq[String],
1111
criteria: Option[SQLCriteria],

es6/sql-bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/package.scala

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.sksamuel.elastic4s.ElasticApi
44
import com.sksamuel.elastic4s.ElasticApi._
55
import com.sksamuel.elastic4s.http.ElasticDsl.BuildableTermsNoOp
66
import com.sksamuel.elastic4s.http.search.SearchBodyBuilderFn
7+
import com.sksamuel.elastic4s.script.Script
78
import com.sksamuel.elastic4s.searches.aggs.Aggregation
89
import com.sksamuel.elastic4s.searches.queries.Query
910
import com.sksamuel.elastic4s.searches.{MultiSearchRequest, SearchRequest}
@@ -95,6 +96,17 @@ package object bridge {
9596
}
9697
}
9798

99+
_search = scriptFields match {
100+
case Nil => _search
101+
case _ =>
102+
_search scriptfields scriptFields.map { field =>
103+
scriptField(
104+
field.scriptName,
105+
Script(script = field.painless).lang("painless").scriptType("source")
106+
)
107+
}
108+
}
109+
98110
_search = orderBy match {
99111
case Some(o) if aggregates.isEmpty && buckets.isEmpty =>
100112
_search sortBy o.sorts.map(sort =>
@@ -134,7 +146,7 @@ package object bridge {
134146
value match {
135147
case n: SQLNumeric[_] if !aggregation =>
136148
operator match {
137-
case _: Ge.type =>
149+
case Ge =>
138150
maybeNot match {
139151
case Some(_) =>
140152
applyNumericOp(n)(
@@ -147,7 +159,7 @@ package object bridge {
147159
d => rangeQuery(identifier.name) gte d
148160
)
149161
}
150-
case _: Gt.type =>
162+
case Gt =>
151163
maybeNot match {
152164
case Some(_) =>
153165
applyNumericOp(n)(
@@ -160,7 +172,7 @@ package object bridge {
160172
d => rangeQuery(identifier.name) gt d
161173
)
162174
}
163-
case _: Le.type =>
175+
case Le =>
164176
maybeNot match {
165177
case Some(_) =>
166178
applyNumericOp(n)(
@@ -173,7 +185,7 @@ package object bridge {
173185
d => rangeQuery(identifier.name) lte d
174186
)
175187
}
176-
case _: Lt.type =>
188+
case Lt =>
177189
maybeNot match {
178190
case Some(_) =>
179191
applyNumericOp(n)(
@@ -186,7 +198,7 @@ package object bridge {
186198
d => rangeQuery(identifier.name) lt d
187199
)
188200
}
189-
case _: Eq.type =>
201+
case Eq =>
190202
maybeNot match {
191203
case Some(_) =>
192204
applyNumericOp(n)(
@@ -199,7 +211,7 @@ package object bridge {
199211
d => termQuery(identifier.name, d)
200212
)
201213
}
202-
case _: Ne.type =>
214+
case Ne | Diff =>
203215
maybeNot match {
204216
case Some(_) =>
205217
applyNumericOp(n)(
@@ -216,49 +228,49 @@ package object bridge {
216228
}
217229
case l: SQLLiteral if !aggregation =>
218230
operator match {
219-
case _: Like.type =>
231+
case Like =>
220232
maybeNot match {
221233
case Some(_) =>
222234
not(regexQuery(identifier.name, toRegex(l.value)))
223235
case _ =>
224236
regexQuery(identifier.name, toRegex(l.value))
225237
}
226-
case _: Ge.type =>
238+
case Ge =>
227239
maybeNot match {
228240
case Some(_) =>
229241
rangeQuery(identifier.name) lt l.value
230242
case _ =>
231243
rangeQuery(identifier.name) gte l.value
232244
}
233-
case _: Gt.type =>
245+
case Gt =>
234246
maybeNot match {
235247
case Some(_) =>
236248
rangeQuery(identifier.name) lte l.value
237249
case _ =>
238250
rangeQuery(identifier.name) gt l.value
239251
}
240-
case _: Le.type =>
252+
case Le =>
241253
maybeNot match {
242254
case Some(_) =>
243255
rangeQuery(identifier.name) gt l.value
244256
case _ =>
245257
rangeQuery(identifier.name) lte l.value
246258
}
247-
case _: Lt.type =>
259+
case Lt =>
248260
maybeNot match {
249261
case Some(_) =>
250262
rangeQuery(identifier.name) gte l.value
251263
case _ =>
252264
rangeQuery(identifier.name) lt l.value
253265
}
254-
case _: Eq.type =>
266+
case Eq =>
255267
maybeNot match {
256268
case Some(_) =>
257269
not(termQuery(identifier.name, l.value))
258270
case _ =>
259271
termQuery(identifier.name, l.value)
260272
}
261-
case _: Ne.type =>
273+
case Ne | Diff =>
262274
maybeNot match {
263275
case Some(_) =>
264276
termQuery(identifier.name, l.value)
@@ -269,14 +281,14 @@ package object bridge {
269281
}
270282
case b: SQLBoolean if !aggregation =>
271283
operator match {
272-
case _: Eq.type =>
284+
case Eq =>
273285
maybeNot match {
274286
case Some(_) =>
275287
not(termQuery(identifier.name, b.value))
276288
case _ =>
277289
termQuery(identifier.name, b.value)
278290
}
279-
case _: Ne.type =>
291+
case Ne | Diff =>
280292
maybeNot match {
281293
case Some(_) =>
282294
termQuery(identifier.name, b.value)
@@ -289,6 +301,26 @@ package object bridge {
289301
}
290302
}
291303

304+
implicit def dateMathToQuery(dateMath: SQLComparisonDateMath): Query = {
305+
import dateMath._
306+
if (aggregation)
307+
return matchAllQuery()
308+
dateTimeFunction match {
309+
case _: CurrentTimeFunction =>
310+
scriptQuery(Script(script = script).lang("painless").scriptType("source"))
311+
case _ =>
312+
val op = if (maybeNot.isDefined) operator.not else operator
313+
op match {
314+
case Gt => rangeQuery(identifier.name) gt script
315+
case Ge => rangeQuery(identifier.name) gte script
316+
case Lt => rangeQuery(identifier.name) lt script
317+
case Le => rangeQuery(identifier.name) lte script
318+
case Eq => rangeQuery(identifier.name) gte script lte script
319+
case Ne | Diff => not(rangeQuery(identifier.name) gte script lte script)
320+
}
321+
}
322+
}
323+
292324
implicit def isNullToQuery(
293325
isNull: SQLIsNull
294326
): Query = {

0 commit comments

Comments
 (0)