@@ -35,6 +35,142 @@ public void testTimechartByDynamicField() throws IOException {
3535
3636 JSONObject result = executeQuery (query );
3737
38+ assertExplainYaml (
39+ query ,
40+ "calcite:\n "
41+ + " logical: |\n "
42+ + " LogicalSystemLimit(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC], fetch=[200],"
43+ + " type=[QUERY_SIZE_LIMIT])\n "
44+ + " LogicalSort(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC])\n "
45+ + " LogicalAggregate(group=[{0, 1}], count=[SUM($2)])\n "
46+ + " LogicalUnion(all=[false])\n "
47+ + " LogicalAggregate(group=[{0, 1}], actual_count=[SUM($2)])\n "
48+ + " LogicalProject(@timestamp=[CAST($0):TIMESTAMP(0) NOT NULL],"
49+ + " event=[CASE(IS NOT NULL($3), $1, CASE(IS NULL($1), null:NULL, 'OTHER'))],"
50+ + " count=[$2])\n "
51+ + " LogicalJoin(condition=[IS NOT DISTINCT FROM($1, $3)],"
52+ + " joinType=[left])\n "
53+ + " LogicalProject(@timestamp=[$1], event=[$0], $f2_0=[$2])\n "
54+ + " LogicalAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
55+ + " LogicalProject(event=[SAFE_CAST(ITEM($8, 'event'))],"
56+ + " $f2=[SPAN(SAFE_CAST(ITEM($8, '@timestamp')), 1, 'd')])\n "
57+ + " CalciteLogicalIndexScan(table=[[OpenSearch,"
58+ + " test_dynamic_fields]])\n "
59+ + " LogicalSort(sort0=[$1], dir0=[DESC], fetch=[10])\n "
60+ + " LogicalAggregate(group=[{1}], grand_total=[SUM($2)])\n "
61+ + " LogicalFilter(condition=[IS NOT NULL($1)])\n "
62+ + " LogicalProject(@timestamp=[$1], event=[$0], $f2_0=[$2])\n "
63+ + " LogicalAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
64+ + " LogicalProject(event=[SAFE_CAST(ITEM($8, 'event'))],"
65+ + " $f2=[SPAN(SAFE_CAST(ITEM($8, '@timestamp')), 1, 'd')])\n "
66+ + " CalciteLogicalIndexScan(table=[[OpenSearch,"
67+ + " test_dynamic_fields]])\n "
68+ + " LogicalProject(@timestamp=[CAST($0):TIMESTAMP(0) NOT NULL], event=[$1],"
69+ + " count=[0])\n "
70+ + " LogicalJoin(condition=[true], joinType=[inner])\n "
71+ + " LogicalAggregate(group=[{0}])\n "
72+ + " LogicalProject(@timestamp=[$1])\n "
73+ + " LogicalAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
74+ + " LogicalProject(event=[SAFE_CAST(ITEM($8, 'event'))],"
75+ + " $f2=[SPAN(SAFE_CAST(ITEM($8, '@timestamp')), 1, 'd')])\n "
76+ + " CalciteLogicalIndexScan(table=[[OpenSearch,"
77+ + " test_dynamic_fields]])\n "
78+ + " LogicalAggregate(group=[{0}])\n "
79+ + " LogicalProject($f0=[CASE(IS NOT NULL($3), $1, CASE(IS NULL($1),"
80+ + " null:NULL, 'OTHER'))])\n "
81+ + " LogicalJoin(condition=[IS NOT DISTINCT FROM($1, $3)],"
82+ + " joinType=[left])\n "
83+ + " LogicalProject(@timestamp=[$1], event=[$0], $f2_0=[$2])\n "
84+ + " LogicalAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
85+ + " LogicalProject(event=[SAFE_CAST(ITEM($8, 'event'))],"
86+ + " $f2=[SPAN(SAFE_CAST(ITEM($8, '@timestamp')), 1, 'd')])\n "
87+ + " CalciteLogicalIndexScan(table=[[OpenSearch,"
88+ + " test_dynamic_fields]])\n "
89+ + " LogicalSort(sort0=[$1], dir0=[DESC], fetch=[10])\n "
90+ + " LogicalAggregate(group=[{1}], grand_total=[SUM($2)])\n "
91+ + " LogicalFilter(condition=[IS NOT NULL($1)])\n "
92+ + " LogicalProject(@timestamp=[$1], event=[$0],"
93+ + " $f2_0=[$2])\n "
94+ + " LogicalAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
95+ + " LogicalProject(event=[SAFE_CAST(ITEM($8, 'event'))],"
96+ + " $f2=[SPAN(SAFE_CAST(ITEM($8, '@timestamp')), 1, 'd')])\n "
97+ + " CalciteLogicalIndexScan(table=[[OpenSearch,"
98+ + " test_dynamic_fields]])\n "
99+ + " physical: |\n "
100+ + " EnumerableLimit(fetch=[200])\n "
101+ + " EnumerableSort(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC])\n "
102+ + " EnumerableAggregate(group=[{0, 1}], count=[$SUM0($2)])\n "
103+ + " EnumerableUnion(all=[false])\n "
104+ + " EnumerableAggregate(group=[{0, 1}], actual_count=[$SUM0($2)])\n "
105+ + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[CAST($t0):TIMESTAMP(0)"
106+ + " NOT NULL], expr#6=[IS NOT NULL($t3)], expr#7=[IS NULL($t1)], expr#8=[null:NULL],"
107+ + " expr#9=['OTHER'], expr#10=[CASE($t7, $t8, $t9)], expr#11=[CASE($t6, $t1, $t10)],"
108+ + " @timestamp=[$t5], event=[$t11], count=[$t2])\n "
109+ + " EnumerableMergeJoin(condition=[=($1, $3)], joinType=[left])\n "
110+ + " EnumerableSort(sort0=[$1], dir0=[ASC])\n "
111+ + " EnumerableCalc(expr#0..2=[{inputs}], @timestamp=[$t1],"
112+ + " event=[$t0], $f2_0=[$t2])\n "
113+ + " EnumerableAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
114+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['event'],"
115+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], expr#12=['@timestamp'],"
116+ + " expr#13=[ITEM($t8, $t12)], expr#14=[SAFE_CAST($t13)], expr#15=[1], expr#16=['d'],"
117+ + " expr#17=[SPAN($t14, $t15, $t16)], event=[$t11], $f2=[$t17])\n "
118+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
119+ + " test_dynamic_fields]])\n "
120+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n "
121+ + " EnumerableLimit(fetch=[10])\n "
122+ + " EnumerableSort(sort0=[$1], dir0=[DESC])\n "
123+ + " EnumerableAggregate(group=[{0}], grand_total=[$SUM0($2)])\n "
124+ + " EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT"
125+ + " NULL($t0)], proj#0..2=[{exprs}], $condition=[$t3])\n "
126+ + " EnumerableAggregate(group=[{0, 1}], agg#0=[COUNT()])\n "
127+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['event'],"
128+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], expr#12=['@timestamp'],"
129+ + " expr#13=[ITEM($t8, $t12)], expr#14=[SAFE_CAST($t13)], expr#15=[1], expr#16=['d'],"
130+ + " expr#17=[SPAN($t14, $t15, $t16)], event=[$t11], $f2=[$t17])\n "
131+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
132+ + " test_dynamic_fields]])\n "
133+ + " EnumerableCalc(expr#0..1=[{inputs}], expr#2=[CAST($t0):TIMESTAMP(0) NOT"
134+ + " NULL], expr#3=[0], @timestamp=[$t2], event=[$t1], count=[$t3])\n "
135+ + " EnumerableNestedLoopJoin(condition=[true], joinType=[inner])\n "
136+ + " EnumerableAggregate(group=[{1}])\n "
137+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['event'],"
138+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], expr#12=['@timestamp'],"
139+ + " expr#13=[ITEM($t8, $t12)], expr#14=[SAFE_CAST($t13)], expr#15=[1], expr#16=['d'],"
140+ + " expr#17=[SPAN($t14, $t15, $t16)], event=[$t11], $f2=[$t17])\n "
141+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
142+ + " test_dynamic_fields]])\n "
143+ + " EnumerableAggregate(group=[{0}])\n "
144+ + " EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT NULL($t1)],"
145+ + " expr#4=[IS NULL($t0)], expr#5=[null:NULL], expr#6=['OTHER'], expr#7=[CASE($t4, $t5,"
146+ + " $t6)], expr#8=[CASE($t3, $t0, $t7)], $f0=[$t8])\n "
147+ + " EnumerableMergeJoin(condition=[=($0, $1)], joinType=[left])\n "
148+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n "
149+ + " EnumerableCalc(expr#0..1=[{inputs}], event=[$t0])\n "
150+ + " EnumerableAggregate(group=[{0, 1}])\n "
151+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['event'],"
152+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], expr#12=['@timestamp'],"
153+ + " expr#13=[ITEM($t8, $t12)], expr#14=[SAFE_CAST($t13)], expr#15=[1], expr#16=['d'],"
154+ + " expr#17=[SPAN($t14, $t15, $t16)], event=[$t11], $f2=[$t17])\n "
155+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
156+ + " test_dynamic_fields]])\n "
157+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n "
158+ + " EnumerableLimit(fetch=[10])\n "
159+ + " EnumerableSort(sort0=[$1], dir0=[DESC])\n "
160+ + " EnumerableAggregate(group=[{0}],"
161+ + " grand_total=[$SUM0($2)])\n "
162+ + " EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT"
163+ + " NULL($t0)], proj#0..2=[{exprs}], $condition=[$t3])\n "
164+ + " EnumerableAggregate(group=[{0, 1}],"
165+ + " agg#0=[COUNT()])\n "
166+ + " EnumerableCalc(expr#0..8=[{inputs}],"
167+ + " expr#9=['event'], expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)],"
168+ + " expr#12=['@timestamp'], expr#13=[ITEM($t8, $t12)], expr#14=[SAFE_CAST($t13)],"
169+ + " expr#15=[1], expr#16=['d'], expr#17=[SPAN($t14, $t15, $t16)], event=[$t11],"
170+ + " $f2=[$t17])\n "
171+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
172+ + " test_dynamic_fields]])\n " );
173+
38174 verifySchema (
39175 result ,
40176 schema ("@timestamp" , "timestamp" ),
@@ -53,18 +189,70 @@ public void testTimechartWithDynamicField() throws IOException {
53189
54190 JSONObject result = executeQuery (query );
55191
192+ assertExplainYaml (
193+ query ,
194+ "calcite:\n "
195+ + " logical: |\n "
196+ + " LogicalSystemLimit(sort0=[$0], dir0=[ASC], fetch=[200],"
197+ + " type=[QUERY_SIZE_LIMIT])\n "
198+ + " LogicalSort(sort0=[$0], dir0=[ASC])\n "
199+ + " LogicalProject(@timestamp=[$0], avg(latency)=[$1])\n "
200+ + " LogicalAggregate(group=[{0}], avg(latency)=[AVG($1)])\n "
201+ + " LogicalProject(timestamp=[SPAN(SAFE_CAST(ITEM($8, '@timestamp')), 1,"
202+ + " 'd')], $f3=[SAFE_CAST(ITEM($8, 'latency'))])\n "
203+ + " CalciteLogicalIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n "
204+ + " physical: |\n "
205+ + " EnumerableCalc(expr#0..2=[{inputs}], expr#3=[0], expr#4=[=($t2, $t3)],"
206+ + " expr#5=[null:BIGINT], expr#6=[CASE($t4, $t5, $t1)], expr#7=[CAST($t6):DOUBLE],"
207+ + " expr#8=[/($t7, $t2)], timestamp=[$t0], avg(latency)=[$t8])\n "
208+ + " EnumerableLimit(fetch=[200])\n "
209+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n "
210+ + " EnumerableAggregate(group=[{0}], agg#0=[$SUM0($1)], agg#1=[COUNT($1)])\n "
211+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['@timestamp'],"
212+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], expr#12=[1], expr#13=['d'],"
213+ + " expr#14=[SPAN($t11, $t12, $t13)], expr#15=['latency'], expr#16=[ITEM($t8, $t15)],"
214+ + " expr#17=[SAFE_CAST($t16)], timestamp=[$t14], $f3=[$t17])\n "
215+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
216+ + " test_dynamic_fields]])\n " );
217+
56218 verifySchema (result , schema ("@timestamp" , "string" ), schema ("avg(latency)" , "double" ));
57219 verifyDataRows (result , rows ("2025-10-25 00:00:00" , 62 ));
58220 }
59221
60222 @ Test
61- public void testTrendlineWithDynamicFieldWithCast () throws IOException {
223+ public void testTrendlineWithDynamicField () throws IOException {
62224 String query =
63225 source (
64226 TEST_INDEX_DYNAMIC ,
65227 "trendline sma(2, latency) as latency_trend| fields id, latency, latency_trend" );
66228 JSONObject result = executeQuery (query );
67229
230+ assertExplainYaml (
231+ query ,
232+ "calcite:\n "
233+ + " logical: |\n "
234+ + " LogicalSystemLimit(fetch=[200], type=[QUERY_SIZE_LIMIT])\n "
235+ + " LogicalProject(id=[$1], latency=[$9], latency_trend=[CASE(>(COUNT() OVER (ROWS"
236+ + " 1 PRECEDING), 1), /(SUM(SAFE_CAST($9)) OVER (ROWS 1 PRECEDING), CAST(COUNT($9) OVER"
237+ + " (ROWS 1 PRECEDING)):DOUBLE NOT NULL), null:NULL)])\n "
238+ + " LogicalFilter(condition=[IS NOT NULL($9)])\n "
239+ + " LogicalProject(name=[$0], id=[$1], _id=[$2], _index=[$3], _score=[$4],"
240+ + " _maxscore=[$5], _sort=[$6], _routing=[$7], _MAP=[$8], latency=[ITEM($8,"
241+ + " 'latency')])\n "
242+ + " CalciteLogicalIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n "
243+ + " physical: |\n "
244+ + " EnumerableCalc(expr#0..5=[{inputs}], expr#6=[1], expr#7=[>($t3, $t6)],"
245+ + " expr#8=[CAST($t5):DOUBLE NOT NULL], expr#9=[/($t4, $t8)], expr#10=[null:NULL],"
246+ + " expr#11=[CASE($t7, $t9, $t10)], proj#0..1=[{exprs}], latency_trend=[$t11])\n "
247+ + " EnumerableLimit(fetch=[200])\n "
248+ + " EnumerableWindow(window#0=[window(rows between $3 PRECEDING and CURRENT ROW"
249+ + " aggs [COUNT(), $SUM0($2), COUNT($1)])])\n "
250+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['latency'],"
251+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], expr#12=[IS NOT NULL($t10)],"
252+ + " id=[$t1], latency=[$t10], $2=[$t11], $condition=[$t12])\n "
253+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
254+ + " test_dynamic_fields]])\n " );
255+
68256 verifySchema (
69257 result ,
70258 schema ("id" , "bigint" ),
@@ -88,6 +276,40 @@ public void testTrendlineSortByDynamicField() throws IOException {
88276 + "| fields id, latency, latency_trend" );
89277 JSONObject result = executeQuery (query );
90278
279+ assertExplainYaml (
280+ query ,
281+ "calcite:\n "
282+ + " logical: |\n "
283+ + " LogicalSystemLimit(fetch=[200], type=[QUERY_SIZE_LIMIT])\n "
284+ + " LogicalProject(id=[$1], latency=[$10], latency_trend=[CASE(>(COUNT() OVER"
285+ + " (ROWS 1 PRECEDING), 1), /(SUM(SAFE_CAST($10)) OVER (ROWS 1 PRECEDING),"
286+ + " CAST(COUNT($10) OVER (ROWS 1 PRECEDING)):DOUBLE NOT NULL), null:NULL)])\n "
287+ + " LogicalFilter(condition=[IS NOT NULL($10)])\n "
288+ + " LogicalProject(name=[$0], id=[$1], _id=[$2], _index=[$3], _score=[$4],"
289+ + " _maxscore=[$5], _sort=[$6], _routing=[$7], _MAP=[$8], event=[$9], latency=[ITEM($8,"
290+ + " 'latency')])\n "
291+ + " LogicalSort(sort0=[$9], dir0=[ASC])\n "
292+ + " LogicalProject(name=[$0], id=[$1], _id=[$2], _index=[$3], _score=[$4],"
293+ + " _maxscore=[$5], _sort=[$6], _routing=[$7], _MAP=[$8], event=[SAFE_CAST(ITEM($8,"
294+ + " 'event'))])\n "
295+ + " CalciteLogicalIndexScan(table=[[OpenSearch, test_dynamic_fields]])\n "
296+ + " physical: |\n "
297+ + " EnumerableCalc(expr#0..5=[{inputs}], expr#6=[1], expr#7=[>($t3, $t6)],"
298+ + " expr#8=[CAST($t5):DOUBLE NOT NULL], expr#9=[/($t4, $t8)], expr#10=[null:NULL],"
299+ + " expr#11=[CASE($t7, $t9, $t10)], proj#0..1=[{exprs}], latency_trend=[$t11])\n "
300+ + " EnumerableLimit(fetch=[200])\n "
301+ + " EnumerableWindow(window#0=[window(rows between $3 PRECEDING and CURRENT ROW"
302+ + " aggs [COUNT(), $SUM0($2), COUNT($1)])])\n "
303+ + " EnumerableCalc(expr#0..2=[{inputs}], expr#3=['latency'], expr#4=[ITEM($t1,"
304+ + " $t3)], expr#5=[SAFE_CAST($t4)], expr#6=[IS NOT NULL($t4)], id=[$t0], latency=[$t4],"
305+ + " $2=[$t5], $condition=[$t6])\n "
306+ + " EnumerableSort(sort0=[$2], dir0=[ASC])\n "
307+ + " EnumerableCalc(expr#0..8=[{inputs}], expr#9=['event'],"
308+ + " expr#10=[ITEM($t8, $t9)], expr#11=[SAFE_CAST($t10)], id=[$t1], _MAP=[$t8],"
309+ + " event=[$t11])\n "
310+ + " CalciteEnumerableIndexScan(table=[[OpenSearch,"
311+ + " test_dynamic_fields]])\n " );
312+
91313 verifySchema (
92314 result ,
93315 schema ("id" , "bigint" ),
0 commit comments