@@ -137,6 +137,88 @@ mod tests {
137137 assert_eq ! ( vector. values[ 0 ] . value, 18.0 ) ;
138138 }
139139
140+ #[ test]
141+ fn sql_executes_wider_sliding_dual_population_query ( ) {
142+ use crate :: data_model:: {
143+ AggregationConfig , AggregationType , CleanupPolicy , KeyByLabelValues , PrecomputedOutput ,
144+ } ;
145+ use crate :: engines:: query_result:: QueryResult ;
146+ use crate :: precompute_operators:: { CountMinSketchAccumulator , SetAggregatorAccumulator } ;
147+ use crate :: stores:: simple_map_store:: SimpleMapStore ;
148+
149+ let sql_query = "SELECT COUNT(value) FROM events WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY host" ;
150+ let ( _, mut sql_config, mut streaming_config) = TestConfigBuilder :: new ( "events" )
151+ . with_grouping_labels ( vec ! [ "host" ] )
152+ . add_temporal_query (
153+ "count_over_time(events[10s])" ,
154+ sql_query,
155+ 1 ,
156+ 5_000 ,
157+ WindowType :: Sliding ,
158+ )
159+ . build_both ( ) ;
160+
161+ let value_config = streaming_config
162+ . get_aggregation_config ( 1 )
163+ . expect ( "value config" )
164+ . clone ( ) ;
165+ let mut value_config = AggregationConfig {
166+ aggregation_type : AggregationType :: CountMinSketch ,
167+ ..value_config
168+ } ;
169+ value_config. slide_interval_ms = 1_000 ;
170+ let mut key_config = value_config. clone ( ) ;
171+ key_config. aggregation_id = 2 ;
172+ key_config. aggregation_type = AggregationType :: SetAggregator ;
173+ streaming_config = Arc :: new ( crate :: data_model:: StreamingConfig {
174+ aggregation_configs : HashMap :: from ( [ ( 1 , value_config) , ( 2 , key_config) ] ) ,
175+ } ) ;
176+ sql_config. query_configs [ 1 ] = sql_config. query_configs [ 1 ]
177+ . clone ( )
178+ . add_aggregation ( crate :: data_model:: AggregationReference :: new ( 2 , None ) ) ;
179+
180+ let store = Arc :: new ( SimpleMapStore :: new (
181+ streaming_config. clone ( ) ,
182+ CleanupPolicy :: NoCleanup ,
183+ ) ) ;
184+ for ( start, end, count) in [ ( 0 , 5_000 , 2.0 ) , ( 5_000 , 10_000 , 3.0 ) ] {
185+ let mut value = CountMinSketchAccumulator :: new ( 4 , 64 ) ;
186+ value. inner . update ( "host-a" , count) ;
187+ let mut keys = SetAggregatorAccumulator :: new ( ) ;
188+ keys. add_key ( KeyByLabelValues {
189+ labels : vec ! [ "host-a" . to_string( ) ] ,
190+ } ) ;
191+ store
192+ . insert_precomputed_output (
193+ PrecomputedOutput :: new ( start, end, None , 1 ) ,
194+ Box :: new ( value) ,
195+ )
196+ . unwrap ( ) ;
197+ store
198+ . insert_precomputed_output (
199+ PrecomputedOutput :: new ( start, end, None , 2 ) ,
200+ Box :: new ( keys) ,
201+ )
202+ . unwrap ( ) ;
203+ }
204+
205+ let engine = SimpleEngine :: new (
206+ store,
207+ sql_config,
208+ streaming_config,
209+ 1_000 ,
210+ QueryLanguage :: sql,
211+ ) ;
212+ let ( _, result) = engine
213+ . handle_query_sql ( sql_query. to_string ( ) , 10.0 )
214+ . expect ( "SQL dual-population query should execute" ) ;
215+ let QueryResult :: Vector ( vector) = result else {
216+ panic ! ( "expected an instant SQL vector" ) ;
217+ } ;
218+ assert_eq ! ( vector. values. len( ) , 1 ) ;
219+ assert_eq ! ( vector. values[ 0 ] . value, 5.0 ) ;
220+ }
221+
140222 #[ test]
141223 fn test_temporal_sum_equivalence ( ) {
142224 let scrape_interval_ms = 1000 ;
0 commit comments