Skip to main content

nodedb_sql/visitor/plan_visitor/
dispatch.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Exhaustive [`SqlPlan`] → [`PlanVisitor`] dispatcher; missing arms fail to compile.
3use super::trait_def::PlanVisitor;
4use crate::types::SqlPlan;
5
6pub fn dispatch<V: PlanVisitor>(visitor: &mut V, plan: &SqlPlan) -> Result<V::Output, V::Error> {
7    match plan {
8        SqlPlan::ConstantResult { columns, values } => visitor.constant_result(columns, values),
9        SqlPlan::Scan {
10            collection,
11            alias,
12            engine,
13            filters,
14            projection,
15            sort_keys,
16            limit,
17            offset,
18            distinct,
19            window_functions,
20            temporal,
21        } => visitor.scan(
22            collection,
23            alias.as_deref(),
24            *engine,
25            filters,
26            projection,
27            sort_keys,
28            *limit,
29            *offset,
30            *distinct,
31            window_functions,
32            temporal,
33        ),
34        SqlPlan::PointGet {
35            collection,
36            alias,
37            engine,
38            key_column,
39            key_value,
40        } => visitor.point_get(collection, alias.as_deref(), *engine, key_column, key_value),
41        SqlPlan::DocumentIndexLookup {
42            collection,
43            alias,
44            engine,
45            field,
46            value,
47            filters,
48            projection,
49            sort_keys,
50            limit,
51            offset,
52            distinct,
53            window_functions,
54            case_insensitive,
55            temporal,
56        } => visitor.document_index_lookup(
57            collection,
58            alias.as_deref(),
59            *engine,
60            field,
61            value,
62            filters,
63            projection,
64            sort_keys,
65            *limit,
66            *offset,
67            *distinct,
68            window_functions,
69            *case_insensitive,
70            temporal,
71        ),
72        SqlPlan::RangeScan {
73            collection,
74            field,
75            lower,
76            upper,
77            limit,
78        } => visitor.range_scan(collection, field, lower.as_ref(), upper.as_ref(), *limit),
79        SqlPlan::Insert {
80            collection,
81            engine,
82            rows,
83            column_defaults,
84            if_absent,
85            column_schema,
86        } => visitor.insert(
87            collection,
88            *engine,
89            rows,
90            column_defaults,
91            *if_absent,
92            column_schema,
93        ),
94        SqlPlan::KvInsert {
95            collection,
96            entries,
97            ttl_secs,
98            intent,
99            on_conflict_updates,
100        } => visitor.kv_insert(collection, entries, *ttl_secs, *intent, on_conflict_updates),
101        SqlPlan::Upsert {
102            collection,
103            engine,
104            rows,
105            column_defaults,
106            on_conflict_updates,
107            column_schema,
108        } => visitor.upsert(
109            collection,
110            *engine,
111            rows,
112            column_defaults,
113            on_conflict_updates,
114            column_schema,
115        ),
116        SqlPlan::InsertSelect {
117            target,
118            source,
119            limit,
120        } => visitor.insert_select(target, source, *limit),
121        SqlPlan::Update {
122            collection,
123            engine,
124            assignments,
125            filters,
126            target_keys,
127            returning,
128        } => visitor.update(
129            collection,
130            *engine,
131            assignments,
132            filters,
133            target_keys,
134            *returning,
135        ),
136        SqlPlan::UpdateFrom {
137            collection,
138            engine,
139            source,
140            target_join_col,
141            source_join_col,
142            assignments,
143            target_filters,
144            returning,
145        } => visitor.update_from(
146            collection,
147            *engine,
148            source,
149            target_join_col,
150            source_join_col,
151            assignments,
152            target_filters,
153            *returning,
154        ),
155        SqlPlan::Delete {
156            collection,
157            engine,
158            filters,
159            target_keys,
160        } => visitor.delete(collection, *engine, filters, target_keys),
161        SqlPlan::Truncate {
162            collection,
163            restart_identity,
164        } => visitor.truncate(collection, *restart_identity),
165        SqlPlan::Join {
166            left,
167            right,
168            on,
169            join_type,
170            condition,
171            limit,
172            projection,
173            filters,
174        } => visitor.join(
175            left,
176            right,
177            on,
178            *join_type,
179            condition.as_ref(),
180            *limit,
181            projection,
182            filters,
183        ),
184        SqlPlan::Aggregate {
185            input,
186            group_by,
187            aggregates,
188            having,
189            limit,
190            grouping_sets,
191            sort_keys,
192        } => visitor.aggregate(
193            input,
194            group_by,
195            aggregates,
196            having,
197            *limit,
198            grouping_sets.as_deref(),
199            sort_keys,
200        ),
201        SqlPlan::TimeseriesScan {
202            collection,
203            time_range,
204            bucket_interval_ms,
205            group_by,
206            aggregates,
207            filters,
208            projection,
209            gap_fill,
210            limit,
211            tiered,
212            temporal,
213        } => visitor.timeseries_scan(
214            collection,
215            *time_range,
216            *bucket_interval_ms,
217            group_by,
218            aggregates,
219            filters,
220            projection,
221            gap_fill,
222            *limit,
223            *tiered,
224            temporal,
225        ),
226        SqlPlan::TimeseriesIngest { collection, rows } => {
227            visitor.timeseries_ingest(collection, rows)
228        }
229        SqlPlan::VectorSearch {
230            collection,
231            field,
232            query_vector,
233            top_k,
234            ef_search,
235            metric,
236            filters,
237            array_prefilter,
238            ann_options,
239            skip_payload_fetch,
240            payload_filters,
241        } => visitor.vector_search(
242            collection,
243            field,
244            query_vector,
245            *top_k,
246            *ef_search,
247            *metric,
248            filters,
249            array_prefilter.as_ref(),
250            ann_options,
251            *skip_payload_fetch,
252            payload_filters,
253        ),
254        SqlPlan::MultiVectorSearch {
255            collection,
256            query_vector,
257            top_k,
258            ef_search,
259        } => visitor.multi_vector_search(collection, query_vector, *top_k, *ef_search),
260        SqlPlan::TextSearch {
261            collection,
262            query,
263            top_k,
264            filters,
265            score_alias,
266        } => visitor.text_search(collection, query, *top_k, filters, score_alias.as_deref()),
267        SqlPlan::HybridSearch {
268            collection,
269            query_vector,
270            query_text,
271            top_k,
272            ef_search,
273            vector_weight,
274            fuzzy,
275            score_alias,
276        } => visitor.hybrid_search(
277            collection,
278            query_vector,
279            query_text,
280            *top_k,
281            *ef_search,
282            *vector_weight,
283            *fuzzy,
284            score_alias.as_deref(),
285        ),
286        SqlPlan::HybridSearchTriple {
287            collection,
288            query_vector,
289            query_text,
290            graph_seed_id,
291            graph_depth,
292            graph_edge_label,
293            top_k,
294            ef_search,
295            fuzzy,
296            rrf_k,
297            score_alias,
298        } => visitor.hybrid_search_triple(
299            collection,
300            query_vector,
301            query_text,
302            graph_seed_id,
303            *graph_depth,
304            graph_edge_label.as_deref(),
305            *top_k,
306            *ef_search,
307            *fuzzy,
308            *rrf_k,
309            score_alias.as_deref(),
310        ),
311        SqlPlan::SpatialScan {
312            collection,
313            field,
314            predicate,
315            query_geometry,
316            distance_meters,
317            attribute_filters,
318            limit,
319            projection,
320        } => visitor.spatial_scan(
321            collection,
322            field,
323            predicate,
324            query_geometry,
325            *distance_meters,
326            attribute_filters,
327            *limit,
328            projection,
329        ),
330        SqlPlan::Union { inputs, distinct } => visitor.union(inputs, *distinct),
331        SqlPlan::Intersect { left, right, all } => visitor.intersect(left, right, *all),
332        SqlPlan::Except { left, right, all } => visitor.except(left, right, *all),
333        SqlPlan::RecursiveScan {
334            collection,
335            base_filters,
336            recursive_filters,
337            join_link,
338            max_iterations,
339            distinct,
340            limit,
341        } => visitor.recursive_scan(
342            collection,
343            base_filters,
344            recursive_filters,
345            join_link.as_ref(),
346            *max_iterations,
347            *distinct,
348            *limit,
349        ),
350        SqlPlan::RecursiveValue {
351            cte_name,
352            columns,
353            init_exprs,
354            step_exprs,
355            condition,
356            max_depth,
357            distinct,
358        } => visitor.recursive_value(
359            cte_name,
360            columns,
361            init_exprs,
362            step_exprs,
363            condition.as_deref(),
364            *max_depth,
365            *distinct,
366        ),
367        SqlPlan::Cte { definitions, outer } => visitor.cte(definitions, outer),
368        SqlPlan::CreateArray {
369            name,
370            dims,
371            attrs,
372            tile_extents,
373            cell_order,
374            tile_order,
375            prefix_bits,
376            audit_retain_ms,
377            minimum_audit_retain_ms,
378        } => visitor.create_array(
379            name,
380            dims,
381            attrs,
382            tile_extents,
383            *cell_order,
384            *tile_order,
385            *prefix_bits,
386            *audit_retain_ms,
387            *minimum_audit_retain_ms,
388        ),
389        SqlPlan::DropArray { name, if_exists } => visitor.drop_array(name, *if_exists),
390        SqlPlan::AlterArray {
391            name,
392            audit_retain_ms,
393            minimum_audit_retain_ms,
394        } => visitor.alter_array(name, *audit_retain_ms, *minimum_audit_retain_ms),
395        SqlPlan::InsertArray { name, rows } => visitor.insert_array(name, rows),
396        SqlPlan::DeleteArray { name, coords } => visitor.delete_array(name, coords),
397        SqlPlan::ArraySlice {
398            name,
399            slice,
400            attr_projection,
401            limit,
402            temporal,
403        } => visitor.array_slice(name, slice, attr_projection, *limit, temporal),
404        SqlPlan::ArrayProject {
405            name,
406            attr_projection,
407        } => visitor.array_project(name, attr_projection),
408        SqlPlan::ArrayAgg {
409            name,
410            attr,
411            reducer,
412            group_by_dim,
413            temporal,
414        } => visitor.array_agg(name, attr, reducer, group_by_dim.as_deref(), temporal),
415        SqlPlan::ArrayElementwise {
416            left,
417            right,
418            op,
419            attr,
420        } => visitor.array_elementwise(left, right, *op, attr),
421        SqlPlan::ArrayFlush { name } => visitor.array_flush(name),
422        SqlPlan::ArrayCompact { name } => visitor.array_compact(name),
423        SqlPlan::Merge {
424            target,
425            engine,
426            source,
427            target_join_col,
428            source_join_col,
429            source_alias,
430            clauses,
431            returning,
432        } => visitor.merge(
433            target,
434            *engine,
435            source,
436            target_join_col,
437            source_join_col,
438            source_alias,
439            clauses,
440            *returning,
441        ),
442        SqlPlan::LateralTopK {
443            outer,
444            outer_alias,
445            inner_collection,
446            inner_filters,
447            inner_order_by,
448            inner_limit,
449            correlation_keys,
450            lateral_alias,
451            projection,
452            left_join,
453        } => visitor.lateral_top_k(
454            outer,
455            outer_alias.as_deref(),
456            inner_collection,
457            inner_filters,
458            inner_order_by,
459            *inner_limit,
460            correlation_keys,
461            lateral_alias,
462            projection,
463            *left_join,
464        ),
465        SqlPlan::LateralLoop {
466            outer,
467            outer_alias,
468            inner,
469            correlation_predicates,
470            lateral_alias,
471            projection,
472            outer_row_cap,
473            left_join,
474        } => visitor.lateral_loop(
475            outer,
476            outer_alias.as_deref(),
477            inner,
478            correlation_predicates,
479            lateral_alias,
480            projection,
481            *outer_row_cap,
482            *left_join,
483        ),
484        SqlPlan::VectorPrimaryInsert {
485            collection,
486            field,
487            quantization,
488            storage_dtype,
489            payload_indexes,
490            rows,
491        } => visitor.vector_primary_insert(
492            collection,
493            field,
494            quantization,
495            storage_dtype,
496            payload_indexes,
497            rows,
498        ),
499        SqlPlan::CreateIndex {
500            index_name,
501            collection,
502            field,
503            unique,
504            if_not_exists,
505            case_insensitive,
506        } => visitor.create_index(
507            index_name.as_deref(),
508            collection,
509            field,
510            *unique,
511            *if_not_exists,
512            *case_insensitive,
513        ),
514        SqlPlan::DropIndex {
515            index_name,
516            collection,
517            if_exists,
518        } => visitor.drop_index(index_name, collection.as_deref(), *if_exists),
519    }
520}