@@ -23,29 +23,22 @@ import org.elasticsearch.action.{ActionResponse, CompositeIndicesRequest}
2323import org .joor .Reflect .*
2424import tech .beshu .ror .accesscontrol .domain .FieldLevelSecurity
2525import tech .beshu .ror .accesscontrol .domain .FieldLevelSecurity .FieldsRestrictions
26+ import tech .beshu .ror .es .EsVersion
2627import tech .beshu .ror .es .handler .response .FieldsFiltering
2728import tech .beshu .ror .es .handler .response .FieldsFiltering .NonMetadataDocumentFields
28- import tech .beshu .ror .es .utils .*
29+ import tech .beshu .ror .es .utils .EsqlRequestHelper . *
2930import tech .beshu .ror .syntax .*
3031import tech .beshu .ror .utils .ReflecUtils
3132import tech .beshu .ror .utils .ScalaOps .*
3233
3334import java .lang .reflect .Modifier
34- import java .util .List as JList
35+ import java .time .ZoneOffset
36+ import java .util .{Locale , List as JList }
3537import java .util .regex .Pattern
3638import scala .jdk .CollectionConverters .*
3739import scala .util .{Failure , Success , Try }
3840
39- object EsqlRequestHelper {
40-
41- final case class IndexTable (tableStringInQuery : String , indices : NonEmptyList [String ])
42-
43- sealed trait ModificationError
44- object ModificationError {
45- final case class UnexpectedException (ex : Throwable ) extends ModificationError
46-
47- implicit val show : Show [ModificationError ] = Show .show(_.toString)
48- }
41+ class EsqlRequestHelper (esVersion : EsVersion ) {
4942
5043 def modifyIndicesOf (request : CompositeIndicesRequest ,
5144 requestTables : NonEmptyList [IndexTable ],
@@ -61,37 +54,21 @@ object EsqlRequestHelper {
6154 .toEither.left.map(ModificationError .UnexpectedException .apply)
6255 }
6356
64- sealed trait EsqlRequestClassification
65- object EsqlRequestClassification {
66- final case class IndicesRelated (tables : NonEmptyList [IndexTable ]) extends EsqlRequestClassification {
67- lazy val indices : Set [String ] = tables.toCovariantSet.flatMap(_.indices.toIterable)
68- }
69- case object NonIndicesRelated extends EsqlRequestClassification
70- }
71-
72- sealed trait ClassificationError
73- object ClassificationError {
74- final case class UnexpectedException (ex : Throwable ) extends ClassificationError
75- case object ParsingException extends ClassificationError
76- }
77-
78- import EsqlRequestClassification ._
57+ import EsqlRequestClassification .*
7958
8059 def classifyEsqlRequest (request : CompositeIndicesRequest ): Either [ClassificationError , EsqlRequestClassification ] = {
81- val result = Try {
82- val query = getQuery(request)
83- val params = ReflecUtils .invokeMethodCached(request, request.getClass, " params" )
84-
85- implicit val classLoader : ClassLoader = request.getClass.getClassLoader
86- Try (new EsqlParser ().createStatement(query, params)) match {
87- case Success (statement : IndicesRelatedStatement ) => Right (IndicesRelated (statement.indices))
88- case Success (command : OtherCommand ) => Right (NonIndicesRelated )
89- case Failure (_) => Left (ClassificationError .ParsingException : ClassificationError )
90- }
60+ createStatement(request) match {
61+ case Right (statement : IndicesRelatedStatement ) => Right (IndicesRelated (statement.indices))
62+ case Right (command : OtherCommand ) => Right (NonIndicesRelated )
63+ case Left (error) => Left (error)
9164 }
92- result match {
93- case Success (value) => value
94- case Failure (exception) => Left (ClassificationError .UnexpectedException (exception))
65+ }
66+
67+ private def createStatement (request : CompositeIndicesRequest ): Either [ClassificationError , Statement ] = {
68+ implicit val classLoader : ClassLoader = request.getClass.getClassLoader
69+ Try (new EsqlParser (esVersion)) match {
70+ case Success (parser) => parser.createStatementBasedOn(request)
71+ case Failure (ex) => Left (ClassificationError .UnexpectedException (ex))
9572 }
9673 }
9774
@@ -106,6 +83,30 @@ object EsqlRequestHelper {
10683 request
10784 }
10885
86+ private def getParams (request : CompositeIndicesRequest ): AnyRef = {
87+ ReflecUtils .invokeMethodCached(request, request.getClass, " params" )
88+ }
89+
90+ private def createConfiguration (request : CompositeIndicesRequest ): AnyRef = {
91+ val classLoader = request.getClass.getClassLoader
92+ onClass(classLoader.loadClass(" org.elasticsearch.xpack.esql.session.Configuration" ))
93+ .create(
94+ ZoneOffset .UTC ,
95+ Option (on(request).call(" locale" ).get[Locale ]).getOrElse(Locale .US ),
96+ null , // at the moment it's not used anywhere, so it's null here - probably to be fixed in the future
97+ " ROR" , // at the moment it's not used anywhere, so it's placeholder here - probably to be fixed in the future
98+ on(request).call(" pragmas" ).get[AnyRef ],
99+ Int .MaxValue ,
100+ Int .MaxValue ,
101+ getQuery(request),
102+ on(request).call(" profile" ).get[AnyRef ],
103+ on(request).call(" tables" ).get[AnyRef ],
104+ System .nanoTime(),
105+ Option (on(request).call(" allowPartialResults" ).get[Any ]).getOrElse(true )
106+ )
107+ .get[AnyRef ]()
108+ }
109+
109110 private def newQueryFrom (oldQuery : String , requestTables : NonEmptyList [IndexTable ], finalIndices : Set [String ]) = {
110111 requestTables.toList.foldLeft(oldQuery) {
111112 case (currentQuery, table) =>
@@ -123,18 +124,43 @@ object EsqlRequestHelper {
123124 currentQuery.replaceAll(Pattern .quote(originTable), finalIndices.mkString(" ," ))
124125 }
125126
126- private final class EsqlParser (implicit classLoader : ClassLoader ) {
127+ private final class EsqlParser (esVersion : EsVersion )
128+ (implicit classLoader : ClassLoader ) {
127129
128130 private val underlyingObject =
129131 onClass(classLoader.loadClass(" org.elasticsearch.xpack.esql.parser.EsqlParser" ))
130132 .create().get[Any ]()
131133
132- def createStatement (query : String , params : AnyRef ): Statement = {
133- val statement = on(underlyingObject).call(" createStatement" , query, params).get[Any ]
134- NonEmptyList .fromList(indicesFrom(statement)) match {
135- case Some (indices) => new IndicesRelatedStatement (statement, indices)
136- case None => OtherCommand (statement)
134+ def createStatementBasedOn (request : CompositeIndicesRequest ): Either [ClassificationError , Statement ] = {
135+ val statement = esVersion match {
136+ case v if v >= EsVersion (8 , 19 , 0 ) => createStatementForEsEqualOrAbove8190(request)
137+ case v => createStatementForEsBelow8190(request)
137138 }
139+ statement.map { s =>
140+ NonEmptyList .fromList(indicesFrom(s)) match {
141+ case Some (indices) => new IndicesRelatedStatement (statement, indices)
142+ case None => OtherCommand (statement)
143+ }
144+ }
145+ }
146+
147+ private def createStatementForEsBelow8190 (request : CompositeIndicesRequest ) = {
148+ for {
149+ query <- Try (getQuery(request)).toEither.left.map(ClassificationError .UnexpectedException .apply)
150+ params <- Try (getParams(request)).toEither.left.map(ClassificationError .UnexpectedException .apply)
151+ statement <- Try (on(underlyingObject).call(" createStatement" , query, params).get[Any ])
152+ .toEither.left.map(_ => ClassificationError .ParsingException )
153+ } yield statement
154+ }
155+
156+ private def createStatementForEsEqualOrAbove8190 (request : CompositeIndicesRequest ) = {
157+ for {
158+ query <- Try (getQuery(request)).toEither.left.map(ClassificationError .UnexpectedException .apply)
159+ params <- Try (getParams(request)).toEither.left.map(ClassificationError .UnexpectedException .apply)
160+ configuration <- Try (createConfiguration(request)).toEither.left.map(ClassificationError .UnexpectedException .apply)
161+ statement <- Try (on(underlyingObject).call(" createStatement" , query, params, configuration).get[Any ])
162+ .toEither.left.map(_ => ClassificationError .ParsingException )
163+ } yield statement
138164 }
139165
140166 private def indicesFrom (statement : Any ) = {
@@ -273,3 +299,29 @@ object EsqlRequestHelper {
273299 }
274300 }
275301}
302+ object EsqlRequestHelper {
303+
304+ final case class IndexTable (tableStringInQuery : String , indices : NonEmptyList [String ])
305+
306+ sealed trait ModificationError
307+ object ModificationError {
308+ final case class UnexpectedException (ex : Throwable ) extends ModificationError
309+
310+ implicit val show : Show [ModificationError ] = Show .show(_.toString)
311+ }
312+
313+ sealed trait EsqlRequestClassification
314+ object EsqlRequestClassification {
315+ final case class IndicesRelated (tables : NonEmptyList [IndexTable ]) extends EsqlRequestClassification {
316+ lazy val indices : Set [String ] = tables.toCovariantSet.flatMap(_.indices.toIterable)
317+ }
318+ case object NonIndicesRelated extends EsqlRequestClassification
319+ }
320+
321+ sealed trait ClassificationError
322+ object ClassificationError {
323+ final case class UnexpectedException (ex : Throwable ) extends ClassificationError
324+ case object ParsingException extends ClassificationError
325+ }
326+
327+ }
0 commit comments