Skip to content

Commit 9906da0

Browse files
committed
update painless for case when
1 parent fba02c9 commit 9906da0

File tree

6 files changed

+45
-36
lines changed

6 files changed

+45
-36
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
19031903
| "c": {
19041904
| "script": {
19051905
| "lang": "painless",
1906-
| "source": "{ if (def left = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); left == null ? false : left > ZonedDateTime.now(ZoneId.of('Z')).minus(7, ChronoUnit.DAYS)) return left; if (def left = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); left != null) return left; def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
1906+
| "source": "{ if (def left = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); left == null ? false : left > ZonedDateTime.now(ZoneId.of('Z')).minus(7, ChronoUnit.DAYS)) return left; if (def left = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); left != null) return left.plus(2, ChronoUnit.DAYS); def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
19071907
| }
19081908
| }
19091909
| },
@@ -1953,7 +1953,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
19531953
| "c": {
19541954
| "script": {
19551955
| "lang": "painless",
1956-
| "source": "{ def expr = ZonedDateTime.now(ZoneId.of('Z')).minus(7, ChronoUnit.DAYS); def val0 = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); if (expr == val0) return val0; def val1 = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); if (expr == val1) return val1; def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
1956+
| "source": "{ def expr = ZonedDateTime.now(ZoneId.of('Z')).toLocalDate().minus(7, ChronoUnit.DAYS); def e0 = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); def val0 = e0 != null ? ((e0).atStartOfDay(ZoneId.of('Z')).minus(3, ChronoUnit.DAYS)).atStartOfDay(ZoneId.of('Z')) : null; if (expr == val0) return e0; def val1 = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); if (expr == val1) return val1.plus(2, ChronoUnit.DAYS); def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
19571957
| }
19581958
| }
19591959
| },
@@ -1988,6 +1988,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
19881988
.replaceAll("if \\(\\s*def", "if (def")
19891989
.replaceAll("ChronoUnit", " ChronoUnit")
19901990
.replaceAll("=ZonedDateTime", " = ZonedDateTime")
1991+
.replaceAll("=e", " = e")
19911992
}
19921993

19931994
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,7 +1892,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
18921892
| "c": {
18931893
| "script": {
18941894
| "lang": "painless",
1895-
| "source": "{ if (def left = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); left == null ? false : left > ZonedDateTime.now(ZoneId.of('Z')).minus(7, ChronoUnit.DAYS)) return left; if (def left = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); left != null) return left; def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
1895+
| "source": "{ if (def left = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); left == null ? false : left > ZonedDateTime.now(ZoneId.of('Z')).minus(7, ChronoUnit.DAYS)) return left; if (def left = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); left != null) return left.plus(2, ChronoUnit.DAYS); def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
18961896
| }
18971897
| }
18981898
| },
@@ -1942,7 +1942,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
19421942
| "c": {
19431943
| "script": {
19441944
| "lang": "painless",
1945-
| "source": "{ def expr = ZonedDateTime.now(ZoneId.of('Z')).minus(7, ChronoUnit.DAYS); def val0 = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); if (expr == val0) return val0; def val1 = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); if (expr == val1) return val1; def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
1945+
| "source": "{ def expr = ZonedDateTime.now(ZoneId.of('Z')).toLocalDate().minus(7, ChronoUnit.DAYS); def e0 = (!doc.containsKey('lastUpdated') || doc['lastUpdated'].empty ? null : doc['lastUpdated'].value); def val0 = e0 != null ? ((e0).atStartOfDay(ZoneId.of('Z')).minus(3, ChronoUnit.DAYS)).atStartOfDay(ZoneId.of('Z')) : null; if (expr == val0) return e0; def val1 = (!doc.containsKey('lastSeen') || doc['lastSeen'].empty ? null : doc['lastSeen'].value); if (expr == val1) return val1.plus(2, ChronoUnit.DAYS); def dval = (!doc.containsKey('createdAt') || doc['createdAt'].empty ? null : doc['createdAt'].value); return dval; }"
19461946
| }
19471947
| }
19481948
| },
@@ -1977,6 +1977,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
19771977
.replaceAll("if \\(\\s*def", "if (def")
19781978
.replaceAll("ChronoUnit", " ChronoUnit")
19791979
.replaceAll("=ZonedDateTime", " = ZonedDateTime")
1980+
.replaceAll("=e", " = e")
19801981
}
19811982

19821983
}

sql/src/main/scala/app/softnetwork/elastic/sql/SQLFunction.scala

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -710,42 +710,42 @@ case class SQLCaseWhen(
710710
case _ => ""
711711
}
712712
val cases = conditions.zipWithIndex
713-
.map { case ((cond, res), zindex) =>
713+
.map { case ((cond, res), idx) =>
714+
val name =
715+
cond match {
716+
case e: Expression =>
717+
e.identifier.name
718+
case i: Identifier =>
719+
i.name
720+
case _ => ""
721+
}
714722
expression match {
715723
case Some(expr) =>
716724
val c = SQLTypeUtils.coerce(cond, expr.out)
717725
if (cond.sql == res.sql) {
718-
s"def val$zindex = $c; if (expr == val$zindex) return val$zindex;"
726+
s"def val$idx = $c; if (expr == val$idx) return val$idx;"
719727
} else {
720-
val _res = {
721-
res match {
722-
case i: Identifier =>
723-
val name = i.name
724-
cond match {
725-
case e: Expression if e.identifier.name == name =>
726-
e.identifier.nullable = false
727-
e
728-
case i: Identifier if i.name == name =>
729-
i.nullable = false
730-
i
731-
case _ => res
732-
}
733-
case _ => res
734-
}
728+
res match {
729+
case i: Identifier if i.name == name && cond.isInstanceOf[Identifier] =>
730+
i.nullable = false
731+
if (cond.asInstanceOf[Identifier].functions.isEmpty)
732+
s"def val$idx = $c; if (expr == val$idx) return ${SQLTypeUtils.coerce(i.toPainless(s"val$idx"), i.out, out, nullable = false)};"
733+
else {
734+
cond.asInstanceOf[Identifier].nullable = false
735+
s"def e$idx = ${i.checkNotNull}; def val$idx = e$idx != null ? ${SQLTypeUtils.coerce(cond.asInstanceOf[Identifier].toPainless(s"e$idx"), cond.out, out, nullable = false)} : null; if (expr == val$idx) return ${SQLTypeUtils
736+
.coerce(i.toPainless(s"e$idx"), i.out, out, nullable = false)};"
737+
}
738+
case _ =>
739+
s"if (expr == $c) return ${SQLTypeUtils.coerce(res, out)};"
735740
}
736-
val r = SQLTypeUtils.coerce(_res, out)
737-
s"if (expr == $c) return $r;"
738741
}
739742
case None =>
740743
val c = SQLTypeUtils.coerce(cond, SQLTypes.Boolean)
741744
val r =
742-
cond match {
743-
case e: Expression =>
744-
val name = e.identifier.name
745-
res match {
746-
case i: Identifier if i.name == name => "left"
747-
case _ => SQLTypeUtils.coerce(res, out)
748-
}
745+
res match {
746+
case i: Identifier if i.name == name && cond.isInstanceOf[Expression] =>
747+
i.nullable = false
748+
SQLTypeUtils.coerce(i.toPainless("left"), i.out, out, nullable = false)
749749
case _ => SQLTypeUtils.coerce(res, out)
750750
}
751751
s"if ($c) return $r;"

sql/src/main/scala/app/softnetwork/elastic/sql/SQLParser.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,9 +483,11 @@ trait SQLParser extends RegexParsers with PackratParsers { _: SQLWhereParser =>
483483
string_type | datetime_type | timestamp_type | date_type | time_type | boolean_type | long_type | double_type | int_type
484484

485485
private[this] def castFunctionWithIdentifier: PackratParser[SQLIdentifier] =
486-
"(?i)cast".r ~ start ~ (identifierWithTransformation | identifierWithSystemFunction | identifierWithArithmeticFunction | identifierWithFunction | date_diff_identifier | identifier) ~ Alias.regex.? ~ sql_type ~ end ^^ {
487-
case _ ~ _ ~ i ~ as ~ t ~ _ =>
488-
i.copy(functions = SQLCast(i, targetType = t, as = as.isDefined) +: i.functions)
486+
"(?i)cast".r ~ start ~ (identifierWithTransformation | identifierWithSystemFunction | identifierWithArithmeticFunction | identifierWithFunction | date_diff_identifier | identifier) ~ Alias.regex.? ~ sql_type ~ end ~ arithmeticFunction.? ^^ {
487+
case _ ~ _ ~ i ~ as ~ t ~ _ ~ a =>
488+
i.copy(functions =
489+
(SQLCast(i, targetType = t, as = as.isDefined) +: i.functions) ++ a.toList
490+
)
489491
}
490492

491493
private[this] def dateFunctionWithIdentifier: PackratParser[SQLIdentifier] =

sql/src/main/scala/app/softnetwork/elastic/sql/package.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,14 @@ package object sql {
363363
expr
364364
}
365365

366+
def checkNotNull: String =
367+
if (name.isEmpty) ""
368+
else
369+
s"(!doc.containsKey('$name') || doc['$name'].empty ? $nullValue : doc['$name'].value)"
370+
366371
override def painless: String = toPainless(
367372
if (nullable)
368-
s"(!doc.containsKey('$name') || doc['$name'].empty ? $nullValue : doc['$name'].value)"
373+
checkNotNull
369374
else
370375
paramName
371376
)

sql/src/test/scala/app/softnetwork/elastic/sql/SQLParserSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ object Queries {
144144
val cast: String =
145145
"select cast(coalesce(nullif(createdAt, parse_date('2025-09-11', 'yyyy-MM-dd')), current_date - interval 2 hour) bigint) as c, identifier from Table"
146146
val caseWhen: String =
147-
"select case when lastUpdated > now - interval 7 day then lastUpdated when isnotnull(lastSeen) then lastSeen else createdAt end as c, identifier from Table"
147+
"select case when lastUpdated > now - interval 7 day then lastUpdated when isnotnull(lastSeen) then lastSeen + interval 2 day else createdAt end as c, identifier from Table"
148148
val caseWhenExpr: String =
149-
"select case now - interval 7 day when lastUpdated then lastUpdated when lastSeen then lastSeen else createdAt end as c, identifier from Table"
149+
"select case current_date - interval 7 day when cast(lastUpdated as date) - interval 3 day then lastUpdated when lastSeen then lastSeen + interval 2 day else createdAt end as c, identifier from Table"
150150
}
151151

152152
/** Created by smanciot on 15/02/17.

0 commit comments

Comments
 (0)