55
66package org .opensearch .sql .ppl .antlr ;
77
8- import static org .junit .Assert .assertEquals ;
9- import static org .junit .Assert .assertNotEquals ;
10- import static org .junit .Assert .assertNotNull ;
11- import static org .junit .Assert .assertThrows ;
12- import static org .junit .Assert .assertTrue ;
8+ import static org .junit .Assert .*;
139
1410import java .util .List ;
1511import org .antlr .v4 .runtime .CommonTokenStream ;
@@ -140,22 +136,22 @@ public void testDynamicSourceClauseParseTreeStructure() {
140136 searchFrom .fromClause ().dynamicSourceClause ();
141137
142138 // Verify source references size and text
143- assertEquals (
144- "Should have 2 source references" ,
145- 2 ,
146- dynamicSource .sourceReferences ().sourceReference ().size ());
139+ assertEquals ("Should have 2 source references" , 2 , dynamicSource .sourceReference ().size ());
147140 assertEquals (
148141 "Source references text should match" ,
149- "myindex,logs " ,
150- dynamicSource .sourceReferences ( ).getText ());
142+ "myindex" ,
143+ dynamicSource .sourceReference ( 0 ).getText ());
151144
152- // Verify filter args size and text
153145 assertEquals (
154- "Should have 2 filter args" , 2 , dynamicSource .sourceFilterArgs ().sourceFilterArg ().size ());
146+ "Source references text should match" , "logs" , dynamicSource .sourceReference (1 ).getText ());
147+ // Verify filter args size and text
148+ assertEquals ("Should have 2 filter args" , 2 , dynamicSource .sourceFilterArg ().size ());
155149 assertEquals (
156150 "Filter args text should match" ,
157- "fieldIndex=\" test\" ,count=100" ,
158- dynamicSource .sourceFilterArgs ().getText ());
151+ "fieldIndex=\" test\" " ,
152+ dynamicSource .sourceFilterArg (0 ).getText ());
153+ assertEquals (
154+ "Filter args text should match" , "count=100" , dynamicSource .sourceFilterArg (1 ).getText ());
159155 }
160156
161157 @ Test
@@ -173,22 +169,21 @@ public void testDynamicSourceWithComplexFilters() {
173169 searchFrom .fromClause ().dynamicSourceClause ();
174170
175171 // Verify source references
172+ assertEquals ("Should have 2 source references" , 2 , dynamicSource .sourceReference ().size ());
176173 assertEquals (
177- "Should have 2 source references" ,
178- 2 ,
179- dynamicSource .sourceReferences ().sourceReference ().size ());
174+ "First source reference text" , "vpc.flow_logs" , dynamicSource .sourceReference (0 ).getText ());
180175 assertEquals (
181- "Source references text" ,
182- "vpc.flow_logs,api.gateway" ,
183- dynamicSource .sourceReferences ().getText ());
176+ "Second source reference text" , "api.gateway" , dynamicSource .sourceReference (1 ).getText ());
184177
185178 // Verify filter args
179+ assertEquals ("Should have 3 filter args" , 3 , dynamicSource .sourceFilterArg ().size ());
186180 assertEquals (
187- "Should have 3 filter args" , 3 , dynamicSource .sourceFilterArgs ().sourceFilterArg ().size ());
181+ "First filter arg text" ,
182+ "region=\" us-east-1\" " ,
183+ dynamicSource .sourceFilterArg (0 ).getText ());
188184 assertEquals (
189- "Filter args text" ,
190- "region=\" us-east-1\" ,env=\" prod\" ,count=5" ,
191- dynamicSource .sourceFilterArgs ().getText ());
185+ "Second filter arg text" , "env=\" prod\" " , dynamicSource .sourceFilterArg (1 ).getText ());
186+ assertEquals ("Third filter arg text" , "count=5" , dynamicSource .sourceFilterArg (2 ).getText ());
192187 }
193188
194189 @ Test
@@ -204,24 +199,61 @@ public void testDynamicSourceWithSingleSource() {
204199 OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
205200 searchFrom .fromClause ().dynamicSourceClause ();
206201
202+ assertEquals ("Should have 1 source reference" , 1 , dynamicSource .sourceReference ().size ());
203+ assertEquals ("Source reference text" , "ds:myindex" , dynamicSource .sourceReference (0 ).getText ());
204+
205+ assertEquals ("Should have 1 filter arg" , 1 , dynamicSource .sourceFilterArg ().size ());
207206 assertEquals (
208- "Should have 1 source reference" ,
209- 1 ,
210- dynamicSource .sourceReferences ().sourceReference ().size ());
211- assertEquals ("Source reference text" , "ds:myindex" , dynamicSource .sourceReferences ().getText ());
207+ "Filter arg text" , "fieldIndex=\" test\" " , dynamicSource .sourceFilterArg (0 ).getText ());
208+ }
209+
210+ @ Test
211+ public void testDynamicSourceWithoutSource () {
212+ String query = "source=[fieldIndex=\" httpStatus\" , region=\" us-west-2\" ]" ;
213+ OpenSearchPPLLexer lexer = new OpenSearchPPLLexer (new CaseInsensitiveCharStream (query ));
214+ OpenSearchPPLParser parser = new OpenSearchPPLParser (new CommonTokenStream (lexer ));
212215
216+ OpenSearchPPLParser .RootContext root = parser .root ();
217+ OpenSearchPPLParser .SearchFromContext searchFrom =
218+ (OpenSearchPPLParser .SearchFromContext )
219+ root .pplStatement ().queryStatement ().pplCommands ().searchCommand ();
220+ OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
221+ searchFrom .fromClause ().dynamicSourceClause ();
222+ assertEquals ("Should have no source references" , 0 , dynamicSource .sourceReference ().size ());
223+ assertEquals ("Should have 2 filter arg" , 2 , dynamicSource .sourceFilterArg ().size ());
213224 assertEquals (
214- "Should have 1 filter arg" , 1 , dynamicSource .sourceFilterArgs ().sourceFilterArg ().size ());
225+ "First filter arg text" ,
226+ "fieldIndex=\" httpStatus\" " ,
227+ dynamicSource .sourceFilterArg (0 ).getText ());
215228 assertEquals (
216- "Filter arg text" , "fieldIndex=\" test\" " , dynamicSource .sourceFilterArgs ().getText ());
229+ "Second filter arg text" ,
230+ "region=\" us-west-2\" " ,
231+ dynamicSource .sourceFilterArg (1 ).getText ());
217232 }
218233
219234 @ Test
220- public void testDynamicSourceRequiresAtLeastOneSource () {
221- // The grammar requires at least one source reference before optional filter args
222- // This test documents that behavior
223- exceptionRule .expect (RuntimeException .class );
224- new PPLSyntaxParser ().parse ("source=[fieldIndex=\" httpStatus\" , region=\" us-west-2\" ]" );
235+ public void testDynamicSourceWithAllSources () {
236+ String query = "source=[`*`, fieldIndex=\" httpStatus\" , region=\" us-west-2\" ]" ;
237+ OpenSearchPPLLexer lexer = new OpenSearchPPLLexer (new CaseInsensitiveCharStream (query ));
238+ OpenSearchPPLParser parser = new OpenSearchPPLParser (new CommonTokenStream (lexer ));
239+
240+ OpenSearchPPLParser .RootContext root = parser .root ();
241+ OpenSearchPPLParser .SearchFromContext searchFrom =
242+ (OpenSearchPPLParser .SearchFromContext )
243+ root .pplStatement ().queryStatement ().pplCommands ().searchCommand ();
244+ OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
245+ searchFrom .fromClause ().dynamicSourceClause ();
246+ assertEquals ("Should have 1 source reference" , 1 , dynamicSource .sourceReference ().size ());
247+ assertEquals ("Source reference text" , "`*`" , dynamicSource .sourceReference (0 ).getText ());
248+ assertEquals ("Should have 2 filter arg" , 2 , dynamicSource .sourceFilterArg ().size ());
249+ assertEquals (
250+ "First filter arg text" ,
251+ "fieldIndex=\" httpStatus\" " ,
252+ dynamicSource .sourceFilterArg (0 ).getText ());
253+ assertEquals (
254+ "Second filter arg text" ,
255+ "region=\" us-west-2\" " ,
256+ dynamicSource .sourceFilterArg (1 ).getText ());
225257 }
226258
227259 @ Test
@@ -237,18 +269,16 @@ public void testDynamicSourceWithDottedNames() {
237269 OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
238270 searchFrom .fromClause ().dynamicSourceClause ();
239271
272+ assertEquals ("Should have 2 source references" , 2 , dynamicSource .sourceReference ().size ());
240273 assertEquals (
241- "Should have 2 source references" ,
242- 2 ,
243- dynamicSource .sourceReferences ().sourceReference ().size ());
274+ "First source reference text" , "vpc.flow_logs" , dynamicSource .sourceReference (0 ).getText ());
244275 assertEquals (
245- "Source references text" ,
246- "vpc.flow_logs, api.gateway.logs" ,
247- dynamicSource .sourceReferences ( ).getText ());
276+ "Second source reference text" ,
277+ "api.gateway.logs" ,
278+ dynamicSource .sourceReference ( 1 ).getText ());
248279
249- assertEquals (
250- "Should have 1 filter arg" , 1 , dynamicSource .sourceFilterArgs ().sourceFilterArg ().size ());
251- assertEquals ("Filter arg text" , "env=\" prod\" " , dynamicSource .sourceFilterArgs ().getText ());
280+ assertEquals ("Should have 1 filter arg" , 1 , dynamicSource .sourceFilterArg ().size ());
281+ assertEquals ("Filter arg text" , "env=\" prod\" " , dynamicSource .sourceFilterArg (0 ).getText ());
252282 }
253283
254284 @ Test
@@ -264,15 +294,11 @@ public void testDynamicSourceWithSimpleFilter() {
264294 OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
265295 searchFrom .fromClause ().dynamicSourceClause ();
266296
267- assertEquals (
268- "Should have 1 source reference" ,
269- 1 ,
270- dynamicSource .sourceReferences ().sourceReference ().size ());
271- assertEquals ("Source reference text" , "logs" , dynamicSource .sourceReferences ().getText ());
297+ assertEquals ("Should have 1 source reference" , 1 , dynamicSource .sourceReference ().size ());
298+ assertEquals ("Source reference text" , "logs" , dynamicSource .sourceReference (0 ).getText ());
272299
273- assertEquals (
274- "Should have 1 filter arg" , 1 , dynamicSource .sourceFilterArgs ().sourceFilterArg ().size ());
275- assertEquals ("Filter arg text" , "count=100" , dynamicSource .sourceFilterArgs ().getText ());
300+ assertEquals ("Should have 1 filter arg" , 1 , dynamicSource .sourceFilterArg ().size ());
301+ assertEquals ("Filter arg text" , "count=100" , dynamicSource .sourceFilterArg (0 ).getText ());
276302 }
277303
278304 @ Test
@@ -293,12 +319,12 @@ public void testDynamicSourceWithInClause() {
293319 searchFrom .fromClause ().dynamicSourceClause ();
294320
295321 assertNotNull ("Dynamic source should exist" , dynamicSource );
296- assertNotNull ("Filter args should exist" , dynamicSource . sourceFilterArgs () );
322+ assertNotNull ("Filter args should exist" , dynamicSource );
297323
298324 // The IN clause should be parsed as a sourceFilterArg
299325 assertTrue (
300326 "Should have at least one filter arg with IN clause" ,
301- dynamicSource .sourceFilterArgs (). sourceFilterArg ().size () >= 1 );
327+ dynamicSource .sourceFilterArg ().size () >= 1 );
302328 }
303329
304330 @ Test
@@ -717,6 +743,124 @@ public void testBlockCommentShouldPass() {
717743 """ ));
718744 }
719745
746+ @ Test
747+ public void testDynamicSourceWithIntermixedSourcesAndFilters () {
748+ // Test intermixed sources and filters in various orders
749+ String query = "source=[myindex, region=\" us-east-1\" , logs, count=100, api.gateway]" ;
750+ OpenSearchPPLLexer lexer = new OpenSearchPPLLexer (new CaseInsensitiveCharStream (query ));
751+ OpenSearchPPLParser parser = new OpenSearchPPLParser (new CommonTokenStream (lexer ));
752+
753+ OpenSearchPPLParser .RootContext root = parser .root ();
754+ OpenSearchPPLParser .SearchFromContext searchFrom =
755+ (OpenSearchPPLParser .SearchFromContext )
756+ root .pplStatement ().queryStatement ().pplCommands ().searchCommand ();
757+ OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
758+ searchFrom .fromClause ().dynamicSourceClause ();
759+
760+ // Verify we have 3 source references
761+ assertEquals ("Should have 3 source references" , 3 , dynamicSource .sourceReference ().size ());
762+ assertEquals ("First source reference" , "myindex" , dynamicSource .sourceReference (0 ).getText ());
763+ assertEquals ("Second source reference" , "logs" , dynamicSource .sourceReference (1 ).getText ());
764+ assertEquals (
765+ "Third source reference" , "api.gateway" , dynamicSource .sourceReference (2 ).getText ());
766+
767+ // Verify we have 2 filter args
768+ assertEquals ("Should have 2 filter args" , 2 , dynamicSource .sourceFilterArg ().size ());
769+ assertEquals (
770+ "First filter arg" , "region=\" us-east-1\" " , dynamicSource .sourceFilterArg (0 ).getText ());
771+ assertEquals ("Second filter arg" , "count=100" , dynamicSource .sourceFilterArg (1 ).getText ());
772+ }
773+
774+ @ Test
775+ public void testDynamicSourceStartingWithFilter () {
776+ // Test starting with a filter argument instead of source reference
777+ String query = "source=[region=\" us-west-1\" , myindex, env=\" prod\" , logs]" ;
778+ OpenSearchPPLLexer lexer = new OpenSearchPPLLexer (new CaseInsensitiveCharStream (query ));
779+ OpenSearchPPLParser parser = new OpenSearchPPLParser (new CommonTokenStream (lexer ));
780+
781+ OpenSearchPPLParser .RootContext root = parser .root ();
782+ OpenSearchPPLParser .SearchFromContext searchFrom =
783+ (OpenSearchPPLParser .SearchFromContext )
784+ root .pplStatement ().queryStatement ().pplCommands ().searchCommand ();
785+ OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
786+ searchFrom .fromClause ().dynamicSourceClause ();
787+
788+ // Verify source references
789+ assertEquals ("Should have 2 source references" , 2 , dynamicSource .sourceReference ().size ());
790+ assertEquals ("First source reference" , "myindex" , dynamicSource .sourceReference (0 ).getText ());
791+ assertEquals ("Second source reference" , "logs" , dynamicSource .sourceReference (1 ).getText ());
792+
793+ // Verify filter args
794+ assertEquals ("Should have 2 filter args" , 2 , dynamicSource .sourceFilterArg ().size ());
795+ assertEquals (
796+ "First filter arg" , "region=\" us-west-1\" " , dynamicSource .sourceFilterArg (0 ).getText ());
797+ assertEquals ("Second filter arg" , "env=\" prod\" " , dynamicSource .sourceFilterArg (1 ).getText ());
798+ }
799+
800+ @ Test
801+ public void testDynamicSourceAlternatingPattern () {
802+ // Test alternating pattern of sources and filters
803+ String query =
804+ "source=[ds:index1, type=\" logs\" , ds:index2, count=50, ds:index3, region=\" us-east-1\" ]" ;
805+ OpenSearchPPLLexer lexer = new OpenSearchPPLLexer (new CaseInsensitiveCharStream (query ));
806+ OpenSearchPPLParser parser = new OpenSearchPPLParser (new CommonTokenStream (lexer ));
807+
808+ OpenSearchPPLParser .RootContext root = parser .root ();
809+ OpenSearchPPLParser .SearchFromContext searchFrom =
810+ (OpenSearchPPLParser .SearchFromContext )
811+ root .pplStatement ().queryStatement ().pplCommands ().searchCommand ();
812+ OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
813+ searchFrom .fromClause ().dynamicSourceClause ();
814+
815+ // Verify source references
816+ assertEquals ("Should have 3 source references" , 3 , dynamicSource .sourceReference ().size ());
817+ assertEquals ("First source reference" , "ds:index1" , dynamicSource .sourceReference (0 ).getText ());
818+ assertEquals (
819+ "Second source reference" , "ds:index2" , dynamicSource .sourceReference (1 ).getText ());
820+ assertEquals ("Third source reference" , "ds:index3" , dynamicSource .sourceReference (2 ).getText ());
821+
822+ // Verify filter args
823+ assertEquals ("Should have 3 filter args" , 3 , dynamicSource .sourceFilterArg ().size ());
824+ assertEquals ("First filter arg" , "type=\" logs\" " , dynamicSource .sourceFilterArg (0 ).getText ());
825+ assertEquals ("Second filter arg" , "count=50" , dynamicSource .sourceFilterArg (1 ).getText ());
826+ assertEquals (
827+ "Third filter arg" , "region=\" us-east-1\" " , dynamicSource .sourceFilterArg (2 ).getText ());
828+ }
829+
830+ @ Test
831+ public void testDynamicSourceWithComplexIntermixedIN () {
832+ // Test intermixed with IN clause filter
833+ String query =
834+ "source=[logs, fieldIndex IN (\" status\" , \" error\" ), api.gateway, region=\" us-east-1\" ]" ;
835+ OpenSearchPPLLexer lexer = new OpenSearchPPLLexer (new CaseInsensitiveCharStream (query ));
836+ OpenSearchPPLParser parser = new OpenSearchPPLParser (new CommonTokenStream (lexer ));
837+
838+ OpenSearchPPLParser .RootContext root = parser .root ();
839+ assertNotNull ("Query should parse successfully" , root );
840+
841+ OpenSearchPPLParser .SearchFromContext searchFrom =
842+ (OpenSearchPPLParser .SearchFromContext )
843+ root .pplStatement ().queryStatement ().pplCommands ().searchCommand ();
844+ OpenSearchPPLParser .DynamicSourceClauseContext dynamicSource =
845+ searchFrom .fromClause ().dynamicSourceClause ();
846+
847+ assertNotNull ("Dynamic source should exist" , dynamicSource );
848+
849+ // Verify source references
850+ assertEquals ("Should have 2 source references" , 2 , dynamicSource .sourceReference ().size ());
851+ assertEquals ("First source reference" , "logs" , dynamicSource .sourceReference (0 ).getText ());
852+ assertEquals (
853+ "Second source reference" , "api.gateway" , dynamicSource .sourceReference (1 ).getText ());
854+
855+ // Verify filter args - should have IN clause and region filter
856+ assertEquals ("Should have 2 filter args" , 2 , dynamicSource .sourceFilterArg ().size ());
857+ assertTrue (
858+ "First filter should contain IN clause" ,
859+ dynamicSource .sourceFilterArg (0 ).getText ().contains ("IN" ));
860+ assertEquals (
861+ "Second filter arg" , "region=\" us-east-1\" " , dynamicSource .sourceFilterArg (1 ).getText ());
862+ }
863+
720864 @ Test
721865 public void testWhereCommand () {
722866 assertNotEquals (null , new PPLSyntaxParser ().parse ("SOURCE=test | WHERE x" ));
0 commit comments