1use crate::sync::Arc;
2use std::fmt;
3use std::fmt::{Debug, Display};
4use strum::IntoEnumIterator;
5use turso_ext::{
6 ContextDestructor, FinalizeFunction, InitAggFunction, ScalarFunction, StepFunction,
7 ValueDestructor,
8};
9
10use crate::LimboError;
11
12pub type ContextCollationFunction = unsafe extern "C" fn(
13 context: usize,
14 left_ptr: *const u8,
15 left_len: usize,
16 right_ptr: *const u8,
17 right_len: usize,
18) -> i32;
19
20pub trait Deterministic: std::fmt::Display {
21 fn is_deterministic(&self) -> bool;
22}
23
24pub struct ExternalFunc {
25 pub name: String,
26 pub func: ExtFunc,
27}
28
29pub struct ExternalCollation {
30 pub name: String,
31 pub context: usize,
32 pub callback: ContextCollationFunction,
33 pub context_destructor: Option<ContextDestructor>,
34}
35
36impl ExternalCollation {
37 pub fn new(
38 name: String,
39 context: usize,
40 callback: ContextCollationFunction,
41 context_destructor: Option<ContextDestructor>,
42 ) -> Self {
43 Self {
44 name,
45 context,
46 callback,
47 context_destructor,
48 }
49 }
50}
51
52impl Drop for ExternalCollation {
53 fn drop(&mut self) {
54 if let Some(destructor) = self.context_destructor {
55 unsafe { destructor(self.context) };
56 }
57 }
58}
59
60impl Debug for ExternalCollation {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f.debug_struct("ExternalCollation")
63 .field("name", &self.name)
64 .finish()
65 }
66}
67
68impl Deterministic for ExternalFunc {
69 fn is_deterministic(&self) -> bool {
70 match self.func {
71 ExtFunc::Scalar { deterministic, .. } => deterministic,
72 _ => false,
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
78pub enum ExtFunc {
79 Scalar {
80 context: usize,
81 argc: i32,
82 deterministic: bool,
83 callback: ScalarFunction,
84 context_destructor: Option<ContextDestructor>,
85 value_destructor: Option<ValueDestructor>,
86 },
87 Aggregate {
88 context: usize,
89 argc: i32,
90 init: InitAggFunction,
91 step: StepFunction,
92 finalize: FinalizeFunction,
93 context_destructor: Option<ContextDestructor>,
94 aggregate_destructor: Option<ContextDestructor>,
95 value_destructor: Option<ValueDestructor>,
96 },
97}
98
99impl ExtFunc {
100 pub fn agg_args(&self) -> Result<i32, ()> {
101 if let ExtFunc::Aggregate { argc, .. } = self {
102 return Ok(*argc);
103 }
104 Err(())
105 }
106
107 pub fn matches_arg_count(&self, arg_count: usize) -> bool {
108 match self {
109 Self::Scalar { argc, .. } => *argc < 0 || *argc as usize == arg_count,
110 Self::Aggregate { argc, .. } => *argc < 0 || *argc as usize == arg_count,
111 }
112 }
113
114 pub fn is_aggregate(&self) -> bool {
115 matches!(self, Self::Aggregate { .. })
116 }
117
118 pub fn with_aggregate_arg_count(&self, arg_count: usize) -> Self {
119 match self {
120 Self::Aggregate {
121 context,
122 init,
123 step,
124 finalize,
125 aggregate_destructor,
126 value_destructor,
127 ..
128 } => Self::Aggregate {
129 context: *context,
130 argc: arg_count as i32,
131 init: *init,
132 step: *step,
133 finalize: *finalize,
134 context_destructor: None,
135 aggregate_destructor: *aggregate_destructor,
136 value_destructor: *value_destructor,
137 },
138 _ => self.clone(),
139 }
140 }
141}
142
143impl ExternalFunc {
144 pub fn new_scalar(
145 name: String,
146 argc: i32,
147 deterministic: bool,
148 context: usize,
149 callback: ScalarFunction,
150 context_destructor: Option<ContextDestructor>,
151 value_destructor: Option<ValueDestructor>,
152 ) -> Self {
153 Self {
154 name,
155 func: ExtFunc::Scalar {
156 context,
157 argc,
158 deterministic,
159 callback,
160 context_destructor,
161 value_destructor,
162 },
163 }
164 }
165
166 pub fn new_aggregate(
167 name: String,
168 argc: i32,
169 context: usize,
170 func: (InitAggFunction, StepFunction, FinalizeFunction),
171 context_destructor: Option<ContextDestructor>,
172 aggregate_destructor: Option<ContextDestructor>,
173 value_destructor: Option<ValueDestructor>,
174 ) -> Self {
175 Self {
176 name,
177 func: ExtFunc::Aggregate {
178 context,
179 argc,
180 init: func.0,
181 step: func.1,
182 finalize: func.2,
183 context_destructor,
184 aggregate_destructor,
185 value_destructor,
186 },
187 }
188 }
189}
190
191impl Drop for ExternalFunc {
192 fn drop(&mut self) {
193 match self.func {
194 ExtFunc::Scalar {
195 context,
196 context_destructor: Some(context_destructor),
197 ..
198 }
199 | ExtFunc::Aggregate {
200 context,
201 context_destructor: Some(context_destructor),
202 ..
203 } => unsafe { context_destructor(context) },
204 _ => {}
205 }
206 }
207}
208
209impl Debug for ExternalFunc {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 write!(f, "{}", self.name)
212 }
213}
214
215impl Display for ExternalFunc {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(f, "{}", self.name)
218 }
219}
220
221#[cfg(clt_turso_feature = "json")]
222#[derive(Debug, Clone, PartialEq, strum::EnumIter)]
223pub enum JsonFunc {
224 Json,
225 Jsonb,
226 JsonArray,
227 JsonbArray,
228 JsonArrayLength,
229 JsonArrowExtract,
230 JsonArrowShiftExtract,
231 JsonExtract,
232 JsonbExtract,
233 JsonObject,
234 JsonbObject,
235 JsonType,
236 JsonErrorPosition,
237 JsonValid,
238 JsonPatch,
239 JsonbPatch,
240 JsonRemove,
241 JsonbRemove,
242 JsonReplace,
243 JsonbReplace,
244 JsonInsert,
245 JsonbInsert,
246 JsonPretty,
247 JsonSet,
248 JsonbSet,
249 JsonQuote,
250}
251
252#[cfg(clt_turso_feature = "json")]
253impl Deterministic for JsonFunc {
254 fn is_deterministic(&self) -> bool {
255 true
256 }
257}
258
259#[cfg(clt_turso_feature = "json")]
260impl Display for JsonFunc {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 write!(
263 f,
264 "{}",
265 match self {
266 Self::Json => "json",
267 Self::Jsonb => "jsonb",
268 Self::JsonArray => "json_array",
269 Self::JsonbArray => "jsonb_array",
270 Self::JsonExtract => "json_extract",
271 Self::JsonbExtract => "jsonb_extract",
272 Self::JsonArrayLength => "json_array_length",
273 Self::JsonArrowExtract => "->",
274 Self::JsonArrowShiftExtract => "->>",
275 Self::JsonObject => "json_object",
276 Self::JsonbObject => "jsonb_object",
277 Self::JsonType => "json_type",
278 Self::JsonErrorPosition => "json_error_position",
279 Self::JsonValid => "json_valid",
280 Self::JsonPatch => "json_patch",
281 Self::JsonbPatch => "jsonb_patch",
282 Self::JsonRemove => "json_remove",
283 Self::JsonbRemove => "jsonb_remove",
284 Self::JsonReplace => "json_replace",
285 Self::JsonbReplace => "jsonb_replace",
286 Self::JsonInsert => "json_insert",
287 Self::JsonbInsert => "jsonb_insert",
288 Self::JsonPretty => "json_pretty",
289 Self::JsonSet => "json_set",
290 Self::JsonbSet => "jsonb_set",
291 Self::JsonQuote => "json_quote",
292 }
293 )
294 }
295}
296
297#[cfg(clt_turso_feature = "json")]
298impl JsonFunc {
299 pub fn is_internal(&self) -> bool {
301 matches!(self, Self::JsonArrowExtract | Self::JsonArrowShiftExtract)
302 }
303
304 pub fn arities(&self) -> &'static [i32] {
305 match self {
306 Self::Json
307 | Self::Jsonb
308 | Self::JsonQuote
309 | Self::JsonErrorPosition
310 | Self::JsonValid => &[1],
311 Self::JsonPatch | Self::JsonbPatch => &[2],
312 Self::JsonArrayLength | Self::JsonType => &[1, 2],
313 Self::JsonArrowExtract | Self::JsonArrowShiftExtract => &[2],
315 _ => &[-1],
317 }
318 }
319}
320
321#[derive(Debug, Clone, strum::EnumIter)]
322pub enum VectorFunc {
323 Vector,
324 Vector32,
325 Vector32Sparse,
326 Vector64,
327 Vector8,
328 Vector1Bit,
329 VectorExtract,
330 VectorDistanceCos,
331 VectorDistanceL2,
332 VectorDistanceJaccard,
333 VectorDistanceDot,
334 VectorConcat,
335 VectorSlice,
336}
337
338impl Deterministic for VectorFunc {
339 fn is_deterministic(&self) -> bool {
340 true
341 }
342}
343
344impl Display for VectorFunc {
345 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346 let str = match self {
347 Self::Vector => "vector",
348 Self::Vector32 => "vector32",
349 Self::Vector32Sparse => "vector32_sparse",
350 Self::Vector64 => "vector64",
351 Self::Vector8 => "vector8",
352 Self::Vector1Bit => "vector1bit",
353 Self::VectorExtract => "vector_extract",
354 Self::VectorDistanceCos => "vector_distance_cos",
355 Self::VectorDistanceL2 => "vector_distance_l2",
356 Self::VectorDistanceJaccard => "vector_distance_jaccard",
357 Self::VectorDistanceDot => "vector_distance_dot",
358 Self::VectorConcat => "vector_concat",
359 Self::VectorSlice => "vector_slice",
360 };
361 write!(f, "{str}")
362 }
363}
364
365impl VectorFunc {
366 pub fn arities(&self) -> &'static [i32] {
367 match self {
368 Self::Vector
369 | Self::Vector32
370 | Self::Vector32Sparse
371 | Self::Vector64
372 | Self::Vector8
373 | Self::Vector1Bit
374 | Self::VectorExtract => &[1],
375 Self::VectorDistanceCos
376 | Self::VectorDistanceL2
377 | Self::VectorDistanceJaccard
378 | Self::VectorDistanceDot => &[2],
379 Self::VectorSlice => &[3],
380 Self::VectorConcat => &[-1],
381 }
382 }
383}
384
385#[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
387#[derive(Debug, Clone, PartialEq, strum::EnumIter)]
388pub enum FtsFunc {
389 Score,
392 Match,
395 Highlight,
398}
399
400#[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
401impl FtsFunc {
402 pub fn is_deterministic(&self) -> bool {
403 true
404 }
405
406 pub fn arities(&self) -> &'static [i32] {
407 match self {
408 Self::Highlight => &[4],
409 Self::Score | Self::Match => &[-1],
411 }
412 }
413}
414
415#[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
416impl Display for FtsFunc {
417 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418 let str = match self {
419 Self::Score => "fts_score",
420 Self::Match => "fts_match",
421 Self::Highlight => "fts_highlight",
422 };
423 write!(f, "{str}")
424 }
425}
426
427#[derive(Debug, Clone, strum::EnumIter)]
428pub enum AggFunc {
429 Avg,
430 Count,
431 Count0,
432 GroupConcat,
433 Max,
434 Min,
435 StringAgg,
436 Sum,
437 Total,
438 #[cfg(clt_turso_feature = "json")]
439 JsonbGroupArray,
440 #[cfg(clt_turso_feature = "json")]
441 JsonGroupArray,
442 #[cfg(clt_turso_feature = "json")]
443 JsonbGroupObject,
444 #[cfg(clt_turso_feature = "json")]
445 JsonGroupObject,
446 ArrayAgg,
447 #[strum(disabled)]
450 Mode,
451 #[strum(disabled)]
454 PercentileCont,
455 #[strum(disabled)]
458 PercentileDisc,
459 #[strum(disabled)]
460 External(Arc<ExtFunc>),
461}
462
463#[derive(Debug, Clone, strum::EnumIter)]
464pub enum WindowFunc {
465 RowNumber,
466 Rank,
467 DenseRank,
468 PercentRank,
469 CumeDist,
470 Ntile,
471 Lag,
472 Lead,
473 FirstValue,
474 LastValue,
475 NthValue,
476 #[strum(disabled)]
477 External(Arc<ExtFunc>),
478}
479
480impl WindowFunc {
481 pub fn as_str(&self) -> &'static str {
484 match self {
485 Self::RowNumber => "row_number",
486 Self::Rank => "rank",
487 Self::DenseRank => "dense_rank",
488 Self::PercentRank => "percent_rank",
489 Self::CumeDist => "cume_dist",
490 Self::Ntile => "ntile",
491 Self::Lag => "lag",
492 Self::Lead => "lead",
493 Self::FirstValue => "first_value",
494 Self::LastValue => "last_value",
495 Self::NthValue => "nth_value",
496 Self::External(_) => unreachable!(
497 "WindowFunc::External is not constructible: ExtFunc has no Window variant"
498 ),
499 }
500 }
501
502 pub fn arities(&self) -> &'static [i32] {
503 match self {
504 Self::RowNumber | Self::Rank | Self::DenseRank | Self::PercentRank | Self::CumeDist => {
505 &[0]
506 }
507 Self::Ntile | Self::FirstValue | Self::LastValue => &[1],
508 Self::NthValue => &[2],
509 Self::Lag | Self::Lead => &[1, 2, 3],
510 Self::External(_) => unreachable!(
511 "WindowFunc::External is not constructible: ExtFunc has no Window variant"
512 ),
513 }
514 }
515
516 pub fn is_implemented(&self) -> bool {
521 matches!(self, Self::RowNumber)
522 }
523}
524
525impl PartialEq for WindowFunc {
526 fn eq(&self, other: &Self) -> bool {
527 match (self, other) {
528 (Self::RowNumber, Self::RowNumber)
529 | (Self::Rank, Self::Rank)
530 | (Self::DenseRank, Self::DenseRank)
531 | (Self::PercentRank, Self::PercentRank)
532 | (Self::CumeDist, Self::CumeDist)
533 | (Self::Ntile, Self::Ntile)
534 | (Self::Lag, Self::Lag)
535 | (Self::Lead, Self::Lead)
536 | (Self::FirstValue, Self::FirstValue)
537 | (Self::LastValue, Self::LastValue)
538 | (Self::NthValue, Self::NthValue) => true,
539 (Self::External(a), Self::External(b)) => Arc::ptr_eq(a, b),
540 _ => false,
541 }
542 }
543}
544
545impl Eq for WindowFunc {}
546
547impl Deterministic for WindowFunc {
548 fn is_deterministic(&self) -> bool {
549 match self {
550 Self::RowNumber
551 | Self::Rank
552 | Self::DenseRank
553 | Self::PercentRank
554 | Self::CumeDist
555 | Self::Ntile
556 | Self::Lag
557 | Self::Lead
558 | Self::FirstValue
559 | Self::LastValue
560 | Self::NthValue => true,
561 Self::External(_) => unreachable!(
562 "WindowFunc::External is not constructible: ExtFunc has no Window variant"
563 ),
564 }
565 }
566}
567
568impl std::fmt::Display for WindowFunc {
569 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
570 f.write_str(self.as_str())
571 }
572}
573
574#[derive(Debug, Clone)]
579pub enum AccumulatorFunc {
580 Agg(AggFunc),
581 Window(WindowFunc),
582}
583
584impl AccumulatorFunc {
585 pub fn expect_agg(&self) -> &AggFunc {
591 match self {
592 Self::Agg(f) => f,
593 Self::Window(f) => {
594 unreachable!("window function {f} reached an aggregate-only dispatch path")
595 }
596 }
597 }
598
599 pub fn as_str(&self) -> &'static str {
600 match self {
601 Self::Agg(f) => f.as_str(),
602 Self::Window(f) => f.as_str(),
603 }
604 }
605}
606
607impl PartialEq for AggFunc {
608 fn eq(&self, other: &Self) -> bool {
609 match (self, other) {
610 (Self::Avg, Self::Avg)
611 | (Self::Count, Self::Count)
612 | (Self::GroupConcat, Self::GroupConcat)
613 | (Self::Max, Self::Max)
614 | (Self::Min, Self::Min)
615 | (Self::StringAgg, Self::StringAgg)
616 | (Self::Sum, Self::Sum)
617 | (Self::Total, Self::Total)
618 | (Self::ArrayAgg, Self::ArrayAgg)
619 | (Self::Mode, Self::Mode)
620 | (Self::PercentileCont, Self::PercentileCont)
621 | (Self::PercentileDisc, Self::PercentileDisc) => true,
622 (Self::External(a), Self::External(b)) => Arc::ptr_eq(a, b),
623 _ => false,
624 }
625 }
626}
627
628impl Deterministic for AggFunc {
629 fn is_deterministic(&self) -> bool {
630 false }
632}
633impl std::fmt::Display for AggFunc {
634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635 write!(f, "{}", self.as_str())
636 }
637}
638
639impl AggFunc {
640 pub fn num_args(&self) -> usize {
641 match self {
642 Self::Avg => 1,
643 Self::Count0 => 0,
644 Self::Count => 1,
645 Self::GroupConcat => 1,
646 Self::Max => 1,
647 Self::Min => 1,
648 Self::StringAgg => 2,
649 Self::Sum => 1,
650 Self::Total => 1,
651 Self::ArrayAgg => 1,
652 Self::Mode => 1,
655 Self::PercentileCont | Self::PercentileDisc => 2,
656 #[cfg(clt_turso_feature = "json")]
657 Self::JsonGroupArray | Self::JsonbGroupArray => 1,
658 #[cfg(clt_turso_feature = "json")]
659 Self::JsonGroupObject | Self::JsonbGroupObject => 2,
660 Self::External(func) => func
661 .agg_args()
662 .map(|argc| argc.max(0) as usize)
663 .unwrap_or(0),
664 }
665 }
666
667 pub fn arities(&self) -> &'static [i32] {
670 match self {
671 Self::Avg => &[1],
672 Self::Count0 => &[0],
673 Self::Count => &[1],
674 Self::GroupConcat => &[1, 2],
675 Self::Max => &[1],
676 Self::Min => &[1],
677 Self::StringAgg => &[2],
678 Self::Sum => &[1],
679 Self::Total => &[1],
680 Self::ArrayAgg => &[1],
681 Self::Mode => &[1],
682 Self::PercentileCont | Self::PercentileDisc => &[2],
683 #[cfg(clt_turso_feature = "json")]
684 Self::JsonGroupArray | Self::JsonbGroupArray => &[1],
685 #[cfg(clt_turso_feature = "json")]
686 Self::JsonGroupObject | Self::JsonbGroupObject => &[2],
687 Self::External(_) => &[-1],
688 }
689 }
690
691 pub fn as_str(&self) -> &'static str {
692 match self {
693 Self::Avg => "avg",
694 Self::Count0 => "count",
695 Self::Count => "count",
696 Self::GroupConcat => "group_concat",
697 Self::Max => "max",
698 Self::Min => "min",
699 Self::StringAgg => "string_agg",
700 Self::Sum => "sum",
701 Self::Total => "total",
702 Self::ArrayAgg => "array_agg",
703 Self::Mode => "mode",
704 Self::PercentileCont => "percentile_cont",
705 Self::PercentileDisc => "percentile_disc",
706 #[cfg(clt_turso_feature = "json")]
707 Self::JsonbGroupArray => "jsonb_group_array",
708 #[cfg(clt_turso_feature = "json")]
709 Self::JsonGroupArray => "json_group_array",
710 #[cfg(clt_turso_feature = "json")]
711 Self::JsonbGroupObject => "jsonb_group_object",
712 #[cfg(clt_turso_feature = "json")]
713 Self::JsonGroupObject => "json_group_object",
714 Self::External(_) => "extension function",
715 }
716 }
717}
718
719#[derive(Debug, Clone, PartialEq, strum::EnumIter)]
720pub enum ScalarFunc {
721 Cast,
722 Changes,
723 Char,
724 Coalesce,
725 Concat,
726 ConcatWs,
727 Glob,
728 IfNull,
729 Iif,
730 Instr,
731 Like,
732 Abs,
733 Upper,
734 Lower,
735 Random,
736 RandomBlob,
737 Trim,
738 LTrim,
739 RTrim,
740 Round,
741 Length,
742 OctetLength,
743 Min,
744 Max,
745 Nullif,
746 Sign,
747 Substr,
748 Substring,
749 Soundex,
750 Date,
751 Time,
752 TotalChanges,
753 DateTime,
754 Typeof,
755 Unicode,
756 Unistr,
757 UnistrQuote,
758 Quote,
759 SqliteVersion,
760 TursoVersion,
761 SqliteSourceId,
762 UnixEpoch,
763 JulianDay,
764 Hex,
765 Unhex,
766 ZeroBlob,
767 LastInsertRowid,
768 Replace,
769 #[cfg(clt_turso_feature = "fs")]
770 #[cfg(not(target_family = "wasm"))]
771 LoadExtension,
772 StrfTime,
773 Printf,
774 Likely,
775 TimeDiff,
776 Likelihood,
777 TableColumnsJsonArray,
778 BinRecordJsonObject,
779 Attach,
780 Detach,
781 Unlikely,
782 StatInit,
783 StatPush,
784 StatGet,
785 ConnTxnId,
786 IsAutocommit,
787 SequenceWatermark,
788 TestUintEncode,
790 TestUintDecode,
791 TestUintAdd,
792 TestUintSub,
793 TestUintMul,
794 TestUintDiv,
795 TestUintLt,
796 TestUintEq,
797 #[cfg(clt_turso_feature = "test_helper")]
801 TestNondetCounter,
802 StringReverse,
803 Gcd,
805 Lcm,
806 Repeat,
807 Lpad,
808 Rpad,
809 BooleanToInt,
811 IntToBoolean,
812 ValidateIpAddr,
813 NumericEncode,
815 NumericDecode,
816 NumericAdd,
817 NumericSub,
818 NumericMul,
819 NumericDiv,
820 NumericLt,
821 NumericEq,
822 Array,
824 ArrayElement,
825 ArraySetElement,
826 ArrayLength,
828 ArrayAppend,
829 ArrayPrepend,
830 ArrayCat,
831 ArrayRemove,
832 ArrayContains,
833 ArrayPosition,
834 ArraySlice,
835 StringToArray,
836 ArrayToString,
837 ArrayOverlap,
838 ArrayContainsAll,
839 StructPack,
841 StructExtractFunc,
842 UnionValueFunc,
843 UnionTagFunc,
844 UnionExtractFunc,
845 NextVal,
847 CurrVal,
848 SetVal,
849}
850
851impl Deterministic for ScalarFunc {
852 fn is_deterministic(&self) -> bool {
853 match self {
854 ScalarFunc::Cast => true,
855 ScalarFunc::Changes => false, ScalarFunc::Char => true,
857 ScalarFunc::Coalesce => true,
858 ScalarFunc::Concat => true,
859 ScalarFunc::ConcatWs => true,
860 ScalarFunc::Glob => true,
861 ScalarFunc::IfNull => true,
862 ScalarFunc::Iif => true,
863 ScalarFunc::Instr => true,
864 ScalarFunc::Like => true,
865 ScalarFunc::Abs => true,
866 ScalarFunc::Upper => true,
867 ScalarFunc::Lower => true,
868 ScalarFunc::Random => false, ScalarFunc::RandomBlob => false, ScalarFunc::Trim => true,
871 ScalarFunc::LTrim => true,
872 ScalarFunc::RTrim => true,
873 ScalarFunc::Round => true,
874 ScalarFunc::Length => true,
875 ScalarFunc::OctetLength => true,
876 ScalarFunc::Min => true,
877 ScalarFunc::Max => true,
878 ScalarFunc::Nullif => true,
879 ScalarFunc::Sign => true,
880 ScalarFunc::Substr => true,
881 ScalarFunc::Substring => true,
882 ScalarFunc::Soundex => true,
883 ScalarFunc::Date => false,
884 ScalarFunc::Time => false,
885 ScalarFunc::TotalChanges => false,
886 ScalarFunc::DateTime => false,
887 ScalarFunc::Typeof => true,
888 ScalarFunc::Unicode => true,
889 ScalarFunc::Unistr => true,
890 ScalarFunc::UnistrQuote => true,
891 ScalarFunc::Quote => true,
892 ScalarFunc::SqliteVersion => false,
893 ScalarFunc::TursoVersion => false,
894 ScalarFunc::SqliteSourceId => false,
895 ScalarFunc::UnixEpoch => false,
896 ScalarFunc::JulianDay => false,
897 ScalarFunc::Hex => true,
898 ScalarFunc::Unhex => true,
899 ScalarFunc::ZeroBlob => true,
900 ScalarFunc::LastInsertRowid => false,
901 ScalarFunc::Replace => true,
902 #[cfg(clt_turso_feature = "fs")]
903 #[cfg(not(target_family = "wasm"))]
904 ScalarFunc::LoadExtension => false,
905 ScalarFunc::StrfTime => false,
906 ScalarFunc::Printf => true,
907 ScalarFunc::Likely => true,
908 ScalarFunc::TimeDiff => false,
909 ScalarFunc::Likelihood => true,
910 ScalarFunc::TableColumnsJsonArray => true, ScalarFunc::BinRecordJsonObject => true,
912 ScalarFunc::Attach => false, ScalarFunc::Detach => false, ScalarFunc::Unlikely => true,
915 ScalarFunc::StatInit => false, ScalarFunc::StatPush => false, ScalarFunc::StatGet => false, ScalarFunc::ConnTxnId => false, ScalarFunc::IsAutocommit => false, ScalarFunc::SequenceWatermark => false, ScalarFunc::TestUintEncode
922 | ScalarFunc::TestUintDecode
923 | ScalarFunc::TestUintAdd
924 | ScalarFunc::TestUintSub
925 | ScalarFunc::TestUintMul
926 | ScalarFunc::TestUintDiv
927 | ScalarFunc::TestUintLt
928 | ScalarFunc::TestUintEq
929 | ScalarFunc::StringReverse => true,
930 ScalarFunc::Gcd
931 | ScalarFunc::Lcm
932 | ScalarFunc::Repeat
933 | ScalarFunc::Lpad
934 | ScalarFunc::Rpad => true,
935 #[cfg(clt_turso_feature = "test_helper")]
936 ScalarFunc::TestNondetCounter => false,
937 ScalarFunc::BooleanToInt
938 | ScalarFunc::IntToBoolean
939 | ScalarFunc::ValidateIpAddr
940 | ScalarFunc::NumericEncode
941 | ScalarFunc::NumericDecode
942 | ScalarFunc::NumericAdd
943 | ScalarFunc::NumericSub
944 | ScalarFunc::NumericMul
945 | ScalarFunc::NumericDiv
946 | ScalarFunc::NumericLt
947 | ScalarFunc::NumericEq => true,
948 ScalarFunc::Array
949 | ScalarFunc::ArrayElement
950 | ScalarFunc::ArraySetElement
951 | ScalarFunc::ArrayLength
952 | ScalarFunc::ArrayAppend
953 | ScalarFunc::ArrayPrepend
954 | ScalarFunc::ArrayCat
955 | ScalarFunc::ArrayRemove
956 | ScalarFunc::ArrayContains
957 | ScalarFunc::ArrayPosition
958 | ScalarFunc::ArraySlice
959 | ScalarFunc::StringToArray
960 | ScalarFunc::ArrayToString
961 | ScalarFunc::ArrayOverlap
962 | ScalarFunc::ArrayContainsAll => true,
963 ScalarFunc::StructPack
964 | ScalarFunc::StructExtractFunc
965 | ScalarFunc::UnionValueFunc
966 | ScalarFunc::UnionTagFunc
967 | ScalarFunc::UnionExtractFunc => true,
968 ScalarFunc::NextVal | ScalarFunc::CurrVal | ScalarFunc::SetVal => false,
969 }
970 }
971}
972
973impl ScalarFunc {
974 pub fn returns_array_blob(&self) -> bool {
982 matches!(
983 self,
984 Self::Array
985 | Self::ArraySetElement
986 | Self::ArrayAppend
987 | Self::ArrayPrepend
988 | Self::ArrayCat
989 | Self::ArrayRemove
990 | Self::ArraySlice
991 | Self::StringToArray
992 )
993 }
994}
995
996impl Display for ScalarFunc {
997 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
998 let str = match self {
999 Self::Cast => "cast",
1000 Self::Changes => "changes",
1001 Self::Char => "char",
1002 Self::Coalesce => "coalesce",
1003 Self::Concat => "concat",
1004 Self::ConcatWs => "concat_ws",
1005 Self::Glob => "glob",
1006 Self::IfNull => "ifnull",
1007 Self::Iif => "iif",
1008 Self::Instr => "instr",
1009 Self::Like => "like",
1010 Self::Abs => "abs",
1011 Self::Upper => "upper",
1012 Self::Lower => "lower",
1013 Self::Random => "random",
1014 Self::RandomBlob => "randomblob",
1015 Self::Trim => "trim",
1016 Self::LTrim => "ltrim",
1017 Self::RTrim => "rtrim",
1018 Self::Round => "round",
1019 Self::Length => "length",
1020 Self::OctetLength => "octet_length",
1021 Self::Min => "min",
1022 Self::Max => "max",
1023 Self::Nullif => "nullif",
1024 Self::Sign => "sign",
1025 Self::Substr => "substr",
1026 Self::Substring => "substring",
1027 Self::Soundex => "soundex",
1028 Self::Date => "date",
1029 Self::Time => "time",
1030 Self::TotalChanges => "total_changes",
1031 Self::Typeof => "typeof",
1032 Self::Unicode => "unicode",
1033 Self::Unistr => "unistr",
1034 Self::UnistrQuote => "unistr_quote",
1035 Self::Quote => "quote",
1036 Self::SqliteVersion => "sqlite_version",
1037 Self::TursoVersion => "turso_version",
1038 Self::SqliteSourceId => "sqlite_source_id",
1039 Self::JulianDay => "julianday",
1040 Self::UnixEpoch => "unixepoch",
1041 Self::Hex => "hex",
1042 Self::Unhex => "unhex",
1043 Self::ZeroBlob => "zeroblob",
1044 Self::LastInsertRowid => "last_insert_rowid",
1045 Self::Replace => "replace",
1046 Self::DateTime => "datetime",
1047 #[cfg(clt_turso_feature = "fs")]
1048 #[cfg(not(target_family = "wasm"))]
1049 Self::LoadExtension => "load_extension",
1050 Self::StrfTime => "strftime",
1051 Self::Printf => "printf",
1052 Self::Likely => "likely",
1053 Self::TimeDiff => "timediff",
1054 Self::Likelihood => "likelihood",
1055 Self::TableColumnsJsonArray => "table_columns_json_array",
1056 Self::BinRecordJsonObject => "bin_record_json_object",
1057 Self::Attach => "attach",
1058 Self::Detach => "detach",
1059 Self::Unlikely => "unlikely",
1060 Self::StatInit => "stat_init",
1061 Self::StatPush => "stat_push",
1062 Self::StatGet => "stat_get",
1063 Self::ConnTxnId => "conn_txn_id",
1064 Self::IsAutocommit => "is_autocommit",
1065 Self::SequenceWatermark => "sequence_watermark_experimental",
1066 Self::TestUintEncode => "test_uint_encode",
1067 Self::TestUintDecode => "test_uint_decode",
1068 Self::TestUintAdd => "test_uint_add",
1069 Self::TestUintSub => "test_uint_sub",
1070 Self::TestUintMul => "test_uint_mul",
1071 Self::TestUintDiv => "test_uint_div",
1072 Self::TestUintLt => "test_uint_lt",
1073 Self::TestUintEq => "test_uint_eq",
1074 #[cfg(clt_turso_feature = "test_helper")]
1075 Self::TestNondetCounter => "test_nondet_counter",
1076 Self::StringReverse => "string_reverse",
1077 Self::Gcd => "gcd",
1078 Self::Lcm => "lcm",
1079 Self::Repeat => "repeat",
1080 Self::Lpad => "lpad",
1081 Self::Rpad => "rpad",
1082 Self::BooleanToInt => "boolean_to_int",
1083 Self::IntToBoolean => "int_to_boolean",
1084 Self::ValidateIpAddr => "validate_ipaddr",
1085 Self::NumericEncode => "numeric_encode",
1086 Self::NumericDecode => "numeric_decode",
1087 Self::NumericAdd => "numeric_add",
1088 Self::NumericSub => "numeric_sub",
1089 Self::NumericMul => "numeric_mul",
1090 Self::NumericDiv => "numeric_div",
1091 Self::NumericLt => "numeric_lt",
1092 Self::NumericEq => "numeric_eq",
1093 Self::Array => "array",
1094 Self::ArrayElement => "array_element",
1095 Self::ArraySetElement => "array_set_element",
1096 Self::ArrayLength => "array_length",
1097 Self::ArrayAppend => "array_append",
1098 Self::ArrayPrepend => "array_prepend",
1099 Self::ArrayCat => "array_cat",
1100 Self::ArrayRemove => "array_remove",
1101 Self::ArrayContains => "array_contains",
1102 Self::ArrayPosition => "array_position",
1103 Self::ArraySlice => "array_slice",
1104 Self::StringToArray => "string_to_array",
1105 Self::ArrayToString => "array_to_string",
1106 Self::ArrayOverlap => "array_overlap",
1107 Self::ArrayContainsAll => "array_contains_all",
1108 Self::StructPack => "struct_pack",
1109 Self::StructExtractFunc => "struct_extract",
1110 Self::UnionValueFunc => "union_value",
1111 Self::UnionTagFunc => "union_tag",
1112 Self::UnionExtractFunc => "union_extract",
1113 Self::NextVal => "nextval",
1114 Self::CurrVal => "currval",
1115 Self::SetVal => "setval",
1116 };
1117 write!(f, "{str}")
1118 }
1119}
1120
1121impl ScalarFunc {
1122 pub fn is_internal(&self) -> bool {
1124 matches!(
1125 self,
1126 Self::Cast
1127 | Self::Array
1128 | Self::ArrayElement
1129 | Self::ArraySetElement
1130 | Self::StatInit
1131 | Self::StatPush
1132 | Self::StatGet
1133 | Self::Attach
1134 | Self::Detach
1135 | Self::TableColumnsJsonArray
1136 | Self::BinRecordJsonObject
1137 | Self::ConnTxnId
1138 | Self::IsAutocommit
1139 )
1140 }
1141
1142 pub fn arities(&self) -> &'static [i32] {
1146 match self {
1147 Self::Changes
1149 | Self::LastInsertRowid
1150 | Self::Random
1151 | Self::SqliteVersion
1152 | Self::TursoVersion
1153 | Self::SqliteSourceId
1154 | Self::TotalChanges => &[0],
1155 #[cfg(clt_turso_feature = "test_helper")]
1156 Self::TestNondetCounter => &[0],
1157 Self::Abs
1159 | Self::Hex
1160 | Self::Length
1161 | Self::Lower
1162 | Self::OctetLength
1163 | Self::Quote
1164 | Self::UnistrQuote
1165 | Self::RandomBlob
1166 | Self::Sign
1167 | Self::Soundex
1168 | Self::Typeof
1169 | Self::Unicode
1170 | Self::Unistr
1171 | Self::Upper
1172 | Self::ZeroBlob
1173 | Self::Likely
1174 | Self::Unlikely
1175 | Self::SequenceWatermark => &[1],
1176 Self::Glob
1178 | Self::Instr
1179 | Self::Nullif
1180 | Self::IfNull
1181 | Self::Likelihood
1182 | Self::TimeDiff => &[2],
1183 Self::Iif | Self::Replace => &[3],
1185 Self::Like => &[2, 3],
1187 Self::Trim | Self::LTrim | Self::RTrim | Self::Round | Self::Unhex => &[1, 2],
1188 Self::Substr | Self::Substring => &[2, 3],
1189 Self::Char
1191 | Self::Coalesce
1192 | Self::Concat
1193 | Self::ConcatWs
1194 | Self::Date
1195 | Self::Time
1196 | Self::DateTime
1197 | Self::UnixEpoch
1198 | Self::JulianDay
1199 | Self::StrfTime
1200 | Self::Printf => &[-1],
1201 #[cfg(clt_turso_feature = "fs")]
1202 #[cfg(not(target_family = "wasm"))]
1203 Self::LoadExtension => &[-1],
1204 Self::Cast
1206 | Self::StatInit
1207 | Self::StatPush
1208 | Self::StatGet
1209 | Self::Attach
1210 | Self::Detach
1211 | Self::TableColumnsJsonArray
1212 | Self::BinRecordJsonObject
1213 | Self::ConnTxnId
1214 | Self::IsAutocommit => &[0],
1215 Self::Max | Self::Min => &[-1],
1217 Self::Gcd | Self::Lcm | Self::Repeat => &[2],
1219 Self::Lpad | Self::Rpad => &[2, 3],
1220 Self::TestUintEncode | Self::TestUintDecode | Self::StringReverse => &[1],
1222 Self::TestUintAdd
1223 | Self::TestUintSub
1224 | Self::TestUintMul
1225 | Self::TestUintDiv
1226 | Self::TestUintLt
1227 | Self::TestUintEq => &[2],
1228 Self::BooleanToInt
1230 | Self::IntToBoolean
1231 | Self::ValidateIpAddr
1232 | Self::NumericDecode => &[1],
1233 Self::NumericAdd
1234 | Self::NumericSub
1235 | Self::NumericMul
1236 | Self::NumericDiv
1237 | Self::NumericLt
1238 | Self::NumericEq => &[2],
1239 Self::NumericEncode => &[3],
1240 Self::Array => &[-1], Self::ArrayElement => &[2],
1243 Self::ArraySetElement => &[3],
1244 Self::ArrayLength => &[1, 2],
1246 Self::ArrayAppend
1247 | Self::ArrayPrepend
1248 | Self::ArrayCat
1249 | Self::ArrayRemove
1250 | Self::ArrayContains
1251 | Self::ArrayPosition
1252 | Self::ArrayOverlap
1253 | Self::ArrayContainsAll => &[2],
1254 Self::ArraySlice => &[3],
1255 Self::StringToArray => &[2, 3],
1256 Self::ArrayToString => &[2, 3],
1257 Self::StructPack => &[-1],
1262 Self::StructExtractFunc => &[2], Self::UnionValueFunc => &[2], Self::UnionTagFunc => &[1], Self::UnionExtractFunc => &[2], Self::NextVal | Self::CurrVal => &[1],
1268 Self::SetVal => &[2, 3],
1269 }
1270 }
1271
1272 pub fn can_mask_nulls(&self) -> bool {
1277 matches!(self, Self::Coalesce | Self::IfNull)
1278 }
1279}
1280
1281#[derive(Debug, Clone, PartialEq, strum::EnumIter)]
1282pub enum MathFunc {
1283 Acos,
1284 Acosh,
1285 Asin,
1286 Asinh,
1287 Atan,
1288 Atan2,
1289 Atanh,
1290 Ceil,
1291 Ceiling,
1292 Cos,
1293 Cosh,
1294 Degrees,
1295 Exp,
1296 Floor,
1297 Ln,
1298 Log,
1299 Log10,
1300 Log2,
1301 Mod,
1302 Pi,
1303 Pow,
1304 Power,
1305 Radians,
1306 Sin,
1307 Sinh,
1308 Sqrt,
1309 Tan,
1310 Tanh,
1311 Trunc,
1312}
1313
1314pub enum MathFuncArity {
1315 Nullary,
1316 Unary,
1317 Binary,
1318 UnaryOrBinary,
1319}
1320
1321impl Deterministic for MathFunc {
1322 fn is_deterministic(&self) -> bool {
1323 true
1324 }
1325}
1326
1327impl MathFunc {
1328 pub fn arity(&self) -> MathFuncArity {
1329 match self {
1330 Self::Pi => MathFuncArity::Nullary,
1331 Self::Acos
1332 | Self::Acosh
1333 | Self::Asin
1334 | Self::Asinh
1335 | Self::Atan
1336 | Self::Atanh
1337 | Self::Ceil
1338 | Self::Ceiling
1339 | Self::Cos
1340 | Self::Cosh
1341 | Self::Degrees
1342 | Self::Exp
1343 | Self::Floor
1344 | Self::Ln
1345 | Self::Log10
1346 | Self::Log2
1347 | Self::Radians
1348 | Self::Sin
1349 | Self::Sinh
1350 | Self::Sqrt
1351 | Self::Tan
1352 | Self::Tanh
1353 | Self::Trunc => MathFuncArity::Unary,
1354
1355 Self::Atan2 | Self::Mod | Self::Pow | Self::Power => MathFuncArity::Binary,
1356
1357 Self::Log => MathFuncArity::UnaryOrBinary,
1358 }
1359 }
1360
1361 pub fn arities(&self) -> &'static [i32] {
1362 match self.arity() {
1363 MathFuncArity::Nullary => &[0],
1364 MathFuncArity::Unary => &[1],
1365 MathFuncArity::Binary => &[2],
1366 MathFuncArity::UnaryOrBinary => &[1, 2],
1367 }
1368 }
1369}
1370
1371impl Display for MathFunc {
1372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373 let str = match self {
1374 Self::Acos => "acos",
1375 Self::Acosh => "acosh",
1376 Self::Asin => "asin",
1377 Self::Asinh => "asinh",
1378 Self::Atan => "atan",
1379 Self::Atan2 => "atan2",
1380 Self::Atanh => "atanh",
1381 Self::Ceil => "ceil",
1382 Self::Ceiling => "ceiling",
1383 Self::Cos => "cos",
1384 Self::Cosh => "cosh",
1385 Self::Degrees => "degrees",
1386 Self::Exp => "exp",
1387 Self::Floor => "floor",
1388 Self::Ln => "ln",
1389 Self::Log => "log",
1390 Self::Log10 => "log10",
1391 Self::Log2 => "log2",
1392 Self::Mod => "mod",
1393 Self::Pi => "pi",
1394 Self::Pow => "pow",
1395 Self::Power => "power",
1396 Self::Radians => "radians",
1397 Self::Sin => "sin",
1398 Self::Sinh => "sinh",
1399 Self::Sqrt => "sqrt",
1400 Self::Tan => "tan",
1401 Self::Tanh => "tanh",
1402 Self::Trunc => "trunc",
1403 };
1404 write!(f, "{str}")
1405 }
1406}
1407
1408#[derive(Debug, Clone)]
1409pub enum AlterTableFunc {
1410 RenameTable,
1411 AlterColumn,
1412 RenameColumn,
1413}
1414
1415impl Display for AlterTableFunc {
1416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1417 match self {
1418 AlterTableFunc::RenameTable => write!(f, "limbo_rename_table"),
1419 AlterTableFunc::RenameColumn => write!(f, "limbo_rename_column"),
1420 AlterTableFunc::AlterColumn => write!(f, "limbo_alter_column"),
1421 }
1422 }
1423}
1424
1425#[derive(Debug, Clone)]
1426pub enum Func {
1427 Agg(AggFunc),
1428 Window(WindowFunc),
1429 Scalar(ScalarFunc),
1430 Math(MathFunc),
1431 Vector(VectorFunc),
1432 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1433 Fts(FtsFunc),
1434 #[cfg(clt_turso_feature = "json")]
1435 Json(JsonFunc),
1436 AlterTable(AlterTableFunc),
1437 External(Arc<ExternalFunc>),
1438}
1439
1440impl Display for Func {
1441 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1442 match self {
1443 Self::Agg(agg_func) => write!(f, "{}", agg_func.as_str()),
1444 Self::Window(window_func) => write!(f, "{window_func}"),
1445 Self::Scalar(scalar_func) => write!(f, "{scalar_func}"),
1446 Self::Math(math_func) => write!(f, "{math_func}"),
1447 Self::Vector(vector_func) => write!(f, "{vector_func}"),
1448 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1449 Self::Fts(fts_func) => write!(f, "{fts_func}"),
1450 #[cfg(clt_turso_feature = "json")]
1451 Self::Json(json_func) => write!(f, "{json_func}"),
1452 Self::External(generic_func) => write!(f, "{generic_func}"),
1453 Self::AlterTable(alter_func) => write!(f, "{alter_func}"),
1454 }
1455 }
1456}
1457
1458#[derive(Debug, Clone)]
1459pub struct FuncCtx {
1460 pub func: Func,
1461 pub arg_count: usize,
1462}
1463
1464impl Deterministic for Func {
1465 fn is_deterministic(&self) -> bool {
1466 match self {
1467 Self::Agg(agg_func) => agg_func.is_deterministic(),
1468 Self::Window(window_func) => window_func.is_deterministic(),
1469 Self::Scalar(scalar_func) => scalar_func.is_deterministic(),
1470 Self::Math(math_func) => math_func.is_deterministic(),
1471 Self::Vector(vector_func) => vector_func.is_deterministic(),
1472 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1473 Self::Fts(fts_func) => fts_func.is_deterministic(),
1474 #[cfg(clt_turso_feature = "json")]
1475 Self::Json(json_func) => json_func.is_deterministic(),
1476 Self::External(external_func) => external_func.is_deterministic(),
1477 Self::AlterTable(_) => true,
1478 }
1479 }
1480}
1481
1482impl Func {
1483 pub fn supports_star_syntax(&self) -> bool {
1484 if self.needs_star_expansion() {
1486 return true;
1487 }
1488 match self {
1489 Self::Scalar(scalar_func) => {
1490 let basic = matches!(
1491 scalar_func,
1492 ScalarFunc::Changes
1493 | ScalarFunc::Random
1494 | ScalarFunc::TotalChanges
1495 | ScalarFunc::SqliteVersion
1496 | ScalarFunc::TursoVersion
1497 | ScalarFunc::SqliteSourceId
1498 | ScalarFunc::LastInsertRowid
1499 );
1500 #[cfg(clt_turso_feature = "test_helper")]
1501 let basic = basic || matches!(scalar_func, ScalarFunc::TestNondetCounter);
1502 basic
1503 }
1504 Self::Math(math_func) => {
1505 matches!(math_func.arity(), MathFuncArity::Nullary)
1506 }
1507 Self::Agg(_) => false,
1509 Self::Window(_) => false,
1510 _ => false,
1511 }
1512 }
1513
1514 pub fn can_mask_nulls(&self) -> bool {
1518 match self {
1519 Self::Scalar(scalar_func) => scalar_func.can_mask_nulls(),
1520 _ => false,
1521 }
1522 }
1523
1524 #[cfg(clt_turso_feature = "json")]
1529 pub fn needs_star_expansion(&self) -> bool {
1530 matches!(
1531 self,
1532 Self::Json(JsonFunc::JsonObject) | Self::Json(JsonFunc::JsonbObject)
1533 )
1534 }
1535
1536 #[cfg(not(clt_turso_feature = "json"))]
1537 pub fn needs_star_expansion(&self) -> bool {
1538 false
1539 }
1540 pub fn resolve_function(name: &str, arg_count: usize) -> Result<Option<Self>, LimboError> {
1541 let normalized_name = crate::util::normalize_ident(name);
1542 match normalized_name.as_str() {
1543 "avg" => {
1544 if arg_count != 1 {
1545 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1546 }
1547 Ok(Some(Self::Agg(AggFunc::Avg)))
1548 }
1549 "count" => {
1550 if arg_count == 0 {
1552 Ok(Some(Self::Agg(AggFunc::Count0))) } else if arg_count == 1 {
1554 Ok(Some(Self::Agg(AggFunc::Count))) } else {
1556 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1557 }
1558 }
1559 "group_concat" => {
1560 if arg_count != 1 && arg_count != 2 {
1561 println!("{arg_count}");
1562 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1563 }
1564 Ok(Some(Self::Agg(AggFunc::GroupConcat)))
1565 }
1566 "max" if arg_count > 1 => Ok(Some(Self::Scalar(ScalarFunc::Max))),
1567 "max" => {
1568 if arg_count < 1 {
1569 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1570 }
1571 Ok(Some(Self::Agg(AggFunc::Max)))
1572 }
1573 "min" if arg_count > 1 => Ok(Some(Self::Scalar(ScalarFunc::Min))),
1574 "min" => {
1575 if arg_count < 1 {
1576 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1577 }
1578 Ok(Some(Self::Agg(AggFunc::Min)))
1579 }
1580 "nullif" if arg_count == 2 => Ok(Some(Self::Scalar(ScalarFunc::Nullif))),
1581 "string_agg" => {
1582 if arg_count != 2 {
1583 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1584 }
1585 Ok(Some(Self::Agg(AggFunc::StringAgg)))
1586 }
1587 "sum" => {
1588 if arg_count != 1 {
1589 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1590 }
1591 Ok(Some(Self::Agg(AggFunc::Sum)))
1592 }
1593 "total" => {
1594 if arg_count != 1 {
1595 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1596 }
1597 Ok(Some(Self::Agg(AggFunc::Total)))
1598 }
1599 "row_number" => {
1600 if arg_count != 0 {
1601 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1602 }
1603 Ok(Some(Self::Window(WindowFunc::RowNumber)))
1604 }
1605 "timediff" => {
1606 if arg_count != 2 {
1607 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1608 }
1609 Ok(Some(Self::Scalar(ScalarFunc::TimeDiff)))
1610 }
1611 "array_agg" => Ok(Some(Self::Agg(AggFunc::ArrayAgg))),
1612 #[cfg(clt_turso_feature = "json")]
1613 "jsonb_group_array" => Ok(Some(Self::Agg(AggFunc::JsonbGroupArray))),
1614 #[cfg(clt_turso_feature = "json")]
1615 "json_group_array" => Ok(Some(Self::Agg(AggFunc::JsonGroupArray))),
1616 #[cfg(clt_turso_feature = "json")]
1617 "jsonb_group_object" => Ok(Some(Self::Agg(AggFunc::JsonbGroupObject))),
1618 #[cfg(clt_turso_feature = "json")]
1619 "json_group_object" => Ok(Some(Self::Agg(AggFunc::JsonGroupObject))),
1620 "char" | "chr" => Ok(Some(Self::Scalar(ScalarFunc::Char))),
1621 "coalesce" => Ok(Some(Self::Scalar(ScalarFunc::Coalesce))),
1622 "concat" => {
1623 if arg_count == 0 {
1624 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1625 }
1626 Ok(Some(Self::Scalar(ScalarFunc::Concat)))
1627 }
1628 "concat_ws" => {
1629 if arg_count < 2 {
1630 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1631 }
1632 Ok(Some(Self::Scalar(ScalarFunc::ConcatWs)))
1633 }
1634 "changes" => Ok(Some(Self::Scalar(ScalarFunc::Changes))),
1635 "total_changes" => Ok(Some(Self::Scalar(ScalarFunc::TotalChanges))),
1636 "glob" => Ok(Some(Self::Scalar(ScalarFunc::Glob))),
1637 "ifnull" => Ok(Some(Self::Scalar(ScalarFunc::IfNull))),
1638 "if" | "iif" => Ok(Some(Self::Scalar(ScalarFunc::Iif))),
1639 "instr" | "strpos" => Ok(Some(Self::Scalar(ScalarFunc::Instr))),
1640 "like" => Ok(Some(Self::Scalar(ScalarFunc::Like))),
1641 "abs" => Ok(Some(Self::Scalar(ScalarFunc::Abs))),
1642 "upper" => Ok(Some(Self::Scalar(ScalarFunc::Upper))),
1643 "lower" => Ok(Some(Self::Scalar(ScalarFunc::Lower))),
1644 "random" => Ok(Some(Self::Scalar(ScalarFunc::Random))),
1645 "randomblob" => Ok(Some(Self::Scalar(ScalarFunc::RandomBlob))),
1646 "trim" | "btrim" => Ok(Some(Self::Scalar(ScalarFunc::Trim))),
1647 "ltrim" => Ok(Some(Self::Scalar(ScalarFunc::LTrim))),
1648 "rtrim" => Ok(Some(Self::Scalar(ScalarFunc::RTrim))),
1649 "round" => Ok(Some(Self::Scalar(ScalarFunc::Round))),
1650 "length" | "char_length" | "character_length" => {
1651 Ok(Some(Self::Scalar(ScalarFunc::Length)))
1652 }
1653 "octet_length" => Ok(Some(Self::Scalar(ScalarFunc::OctetLength))),
1654 "sign" => Ok(Some(Self::Scalar(ScalarFunc::Sign))),
1655 "substr" => {
1656 if arg_count != 2 && arg_count != 3 {
1657 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1658 }
1659 Ok(Some(Self::Scalar(ScalarFunc::Substr)))
1660 }
1661 "substring" => {
1662 if arg_count != 2 && arg_count != 3 {
1663 crate::bail_parse_error!("wrong number of arguments to function {}()", name)
1664 }
1665 Ok(Some(Self::Scalar(ScalarFunc::Substring)))
1666 }
1667 "date" => Ok(Some(Self::Scalar(ScalarFunc::Date))),
1668 "time" => Ok(Some(Self::Scalar(ScalarFunc::Time))),
1669 "datetime" => Ok(Some(Self::Scalar(ScalarFunc::DateTime))),
1670 "typeof" => Ok(Some(Self::Scalar(ScalarFunc::Typeof))),
1671 "last_insert_rowid" => Ok(Some(Self::Scalar(ScalarFunc::LastInsertRowid))),
1672 "unicode" => Ok(Some(Self::Scalar(ScalarFunc::Unicode))),
1673 "unistr" => Ok(Some(Self::Scalar(ScalarFunc::Unistr))),
1674 "unistr_quote" => Ok(Some(Self::Scalar(ScalarFunc::UnistrQuote))),
1675 "quote" => Ok(Some(Self::Scalar(ScalarFunc::Quote))),
1676 "sqlite_version" => Ok(Some(Self::Scalar(ScalarFunc::SqliteVersion))),
1677 "turso_version" => Ok(Some(Self::Scalar(ScalarFunc::TursoVersion))),
1678 "sqlite_source_id" => Ok(Some(Self::Scalar(ScalarFunc::SqliteSourceId))),
1679 "replace" => Ok(Some(Self::Scalar(ScalarFunc::Replace))),
1680 "likely" => Ok(Some(Self::Scalar(ScalarFunc::Likely))),
1681 "likelihood" => Ok(Some(Self::Scalar(ScalarFunc::Likelihood))),
1682 "unlikely" => Ok(Some(Self::Scalar(ScalarFunc::Unlikely))),
1683 #[cfg(clt_turso_feature = "json")]
1684 "json" => Ok(Some(Self::Json(JsonFunc::Json))),
1685 #[cfg(clt_turso_feature = "json")]
1686 "jsonb" => Ok(Some(Self::Json(JsonFunc::Jsonb))),
1687 #[cfg(clt_turso_feature = "json")]
1688 "json_array_length" => Ok(Some(Self::Json(JsonFunc::JsonArrayLength))),
1689 #[cfg(clt_turso_feature = "json")]
1690 "json_array" => Ok(Some(Self::Json(JsonFunc::JsonArray))),
1691 #[cfg(clt_turso_feature = "json")]
1692 "jsonb_array" => Ok(Some(Self::Json(JsonFunc::JsonbArray))),
1693 #[cfg(clt_turso_feature = "json")]
1694 "json_extract" => Ok(Some(Func::Json(JsonFunc::JsonExtract))),
1695 #[cfg(clt_turso_feature = "json")]
1696 "jsonb_extract" => Ok(Some(Func::Json(JsonFunc::JsonbExtract))),
1697 #[cfg(clt_turso_feature = "json")]
1698 "json_object" => Ok(Some(Func::Json(JsonFunc::JsonObject))),
1699 #[cfg(clt_turso_feature = "json")]
1700 "jsonb_object" => Ok(Some(Func::Json(JsonFunc::JsonbObject))),
1701 #[cfg(clt_turso_feature = "json")]
1702 "json_type" => Ok(Some(Func::Json(JsonFunc::JsonType))),
1703 #[cfg(clt_turso_feature = "json")]
1704 "json_error_position" => Ok(Some(Self::Json(JsonFunc::JsonErrorPosition))),
1705 #[cfg(clt_turso_feature = "json")]
1706 "json_valid" => Ok(Some(Self::Json(JsonFunc::JsonValid))),
1707 #[cfg(clt_turso_feature = "json")]
1708 "json_patch" => Ok(Some(Self::Json(JsonFunc::JsonPatch))),
1709 #[cfg(clt_turso_feature = "json")]
1710 "jsonb_patch" => Ok(Some(Self::Json(JsonFunc::JsonbPatch))),
1711 #[cfg(clt_turso_feature = "json")]
1712 "json_remove" => Ok(Some(Self::Json(JsonFunc::JsonRemove))),
1713 #[cfg(clt_turso_feature = "json")]
1714 "jsonb_remove" => Ok(Some(Self::Json(JsonFunc::JsonbRemove))),
1715 #[cfg(clt_turso_feature = "json")]
1716 "json_replace" => Ok(Some(Self::Json(JsonFunc::JsonReplace))),
1717 #[cfg(clt_turso_feature = "json")]
1718 "json_insert" => Ok(Some(Self::Json(JsonFunc::JsonInsert))),
1719 #[cfg(clt_turso_feature = "json")]
1720 "jsonb_insert" => Ok(Some(Self::Json(JsonFunc::JsonbInsert))),
1721 #[cfg(clt_turso_feature = "json")]
1722 "jsonb_replace" => Ok(Some(Self::Json(JsonFunc::JsonbReplace))),
1723 #[cfg(clt_turso_feature = "json")]
1724 "json_pretty" => Ok(Some(Self::Json(JsonFunc::JsonPretty))),
1725 #[cfg(clt_turso_feature = "json")]
1726 "json_set" => Ok(Some(Self::Json(JsonFunc::JsonSet))),
1727 #[cfg(clt_turso_feature = "json")]
1728 "jsonb_set" => Ok(Some(Self::Json(JsonFunc::JsonbSet))),
1729 #[cfg(clt_turso_feature = "json")]
1730 "json_quote" => Ok(Some(Self::Json(JsonFunc::JsonQuote))),
1731 "unixepoch" => Ok(Some(Self::Scalar(ScalarFunc::UnixEpoch))),
1732 "julianday" => Ok(Some(Self::Scalar(ScalarFunc::JulianDay))),
1733 "hex" => Ok(Some(Self::Scalar(ScalarFunc::Hex))),
1734 "unhex" => Ok(Some(Self::Scalar(ScalarFunc::Unhex))),
1735 "zeroblob" => Ok(Some(Self::Scalar(ScalarFunc::ZeroBlob))),
1736 "soundex" => Ok(Some(Self::Scalar(ScalarFunc::Soundex))),
1737 "table_columns_json_array" => Ok(Some(Self::Scalar(ScalarFunc::TableColumnsJsonArray))),
1738 "bin_record_json_object" => Ok(Some(Self::Scalar(ScalarFunc::BinRecordJsonObject))),
1739 "conn_txn_id" => Ok(Some(Self::Scalar(ScalarFunc::ConnTxnId))),
1740 "is_autocommit" => Ok(Some(Self::Scalar(ScalarFunc::IsAutocommit))),
1741 "sequence_watermark_experimental" => {
1742 Ok(Some(Self::Scalar(ScalarFunc::SequenceWatermark)))
1743 }
1744 "acos" => Ok(Some(Self::Math(MathFunc::Acos))),
1745 "acosh" => Ok(Some(Self::Math(MathFunc::Acosh))),
1746 "asin" => Ok(Some(Self::Math(MathFunc::Asin))),
1747 "asinh" => Ok(Some(Self::Math(MathFunc::Asinh))),
1748 "atan" => Ok(Some(Self::Math(MathFunc::Atan))),
1749 "atan2" => Ok(Some(Self::Math(MathFunc::Atan2))),
1750 "atanh" => Ok(Some(Self::Math(MathFunc::Atanh))),
1751 "ceil" => Ok(Some(Self::Math(MathFunc::Ceil))),
1752 "ceiling" => Ok(Some(Self::Math(MathFunc::Ceiling))),
1753 "cos" => Ok(Some(Self::Math(MathFunc::Cos))),
1754 "cosh" => Ok(Some(Self::Math(MathFunc::Cosh))),
1755 "degrees" => Ok(Some(Self::Math(MathFunc::Degrees))),
1756 "exp" => Ok(Some(Self::Math(MathFunc::Exp))),
1757 "floor" => Ok(Some(Self::Math(MathFunc::Floor))),
1758 "ln" => Ok(Some(Self::Math(MathFunc::Ln))),
1759 "log" => Ok(Some(Self::Math(MathFunc::Log))),
1760 "log10" => Ok(Some(Self::Math(MathFunc::Log10))),
1761 "log2" => Ok(Some(Self::Math(MathFunc::Log2))),
1762 "mod" => Ok(Some(Self::Math(MathFunc::Mod))),
1763 "pi" => Ok(Some(Self::Math(MathFunc::Pi))),
1764 "pow" => Ok(Some(Self::Math(MathFunc::Pow))),
1765 "power" => Ok(Some(Self::Math(MathFunc::Power))),
1766 "radians" => Ok(Some(Self::Math(MathFunc::Radians))),
1767 "sin" => Ok(Some(Self::Math(MathFunc::Sin))),
1768 "sinh" => Ok(Some(Self::Math(MathFunc::Sinh))),
1769 "sqrt" => Ok(Some(Self::Math(MathFunc::Sqrt))),
1770 "tan" => Ok(Some(Self::Math(MathFunc::Tan))),
1771 "tanh" => Ok(Some(Self::Math(MathFunc::Tanh))),
1772 "trunc" => Ok(Some(Self::Math(MathFunc::Trunc))),
1773 #[cfg(clt_turso_feature = "fs")]
1774 #[cfg(not(target_family = "wasm"))]
1775 "load_extension" => Ok(Some(Self::Scalar(ScalarFunc::LoadExtension))),
1776 "strftime" => Ok(Some(Self::Scalar(ScalarFunc::StrfTime))),
1777 "printf" | "format" => Ok(Some(Self::Scalar(ScalarFunc::Printf))),
1778 "vector" => Ok(Some(Self::Vector(VectorFunc::Vector))),
1779 "vector32" => Ok(Some(Self::Vector(VectorFunc::Vector32))),
1780 "vector32_sparse" => Ok(Some(Self::Vector(VectorFunc::Vector32Sparse))),
1781 "vector64" => Ok(Some(Self::Vector(VectorFunc::Vector64))),
1782 "vector8" => Ok(Some(Self::Vector(VectorFunc::Vector8))),
1783 "vector1bit" => Ok(Some(Self::Vector(VectorFunc::Vector1Bit))),
1784 "vector_extract" => Ok(Some(Self::Vector(VectorFunc::VectorExtract))),
1785 "vector_distance_cos" => Ok(Some(Self::Vector(VectorFunc::VectorDistanceCos))),
1786 "vector_distance_l2" => Ok(Some(Self::Vector(VectorFunc::VectorDistanceL2))),
1787 "vector_distance_jaccard" => Ok(Some(Self::Vector(VectorFunc::VectorDistanceJaccard))),
1788 "vector_distance_dot" => Ok(Some(Self::Vector(VectorFunc::VectorDistanceDot))),
1789 "vector_concat" => Ok(Some(Self::Vector(VectorFunc::VectorConcat))),
1790 "vector_slice" => Ok(Some(Self::Vector(VectorFunc::VectorSlice))),
1791 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1793 "fts_score" => Ok(Some(Self::Fts(FtsFunc::Score))),
1794 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1795 "fts_match" => Ok(Some(Self::Fts(FtsFunc::Match))),
1796 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1797 "fts_highlight" => Ok(Some(Self::Fts(FtsFunc::Highlight))),
1798 "test_uint_encode" => Ok(Some(Self::Scalar(ScalarFunc::TestUintEncode))),
1800 "test_uint_decode" => Ok(Some(Self::Scalar(ScalarFunc::TestUintDecode))),
1801 "test_uint_add" => Ok(Some(Self::Scalar(ScalarFunc::TestUintAdd))),
1802 "test_uint_sub" => Ok(Some(Self::Scalar(ScalarFunc::TestUintSub))),
1803 "test_uint_mul" => Ok(Some(Self::Scalar(ScalarFunc::TestUintMul))),
1804 "test_uint_div" => Ok(Some(Self::Scalar(ScalarFunc::TestUintDiv))),
1805 "test_uint_lt" => Ok(Some(Self::Scalar(ScalarFunc::TestUintLt))),
1806 "test_uint_eq" => Ok(Some(Self::Scalar(ScalarFunc::TestUintEq))),
1807 #[cfg(clt_turso_feature = "test_helper")]
1808 "test_nondet_counter" => Ok(Some(Self::Scalar(ScalarFunc::TestNondetCounter))),
1809 "string_reverse" | "reverse" => Ok(Some(Self::Scalar(ScalarFunc::StringReverse))),
1810 "gcd" => Ok(Some(Self::Scalar(ScalarFunc::Gcd))),
1811 "lcm" => Ok(Some(Self::Scalar(ScalarFunc::Lcm))),
1812 "repeat" => Ok(Some(Self::Scalar(ScalarFunc::Repeat))),
1813 "lpad" => Ok(Some(Self::Scalar(ScalarFunc::Lpad))),
1814 "rpad" => Ok(Some(Self::Scalar(ScalarFunc::Rpad))),
1815 "boolean_to_int" => Ok(Some(Self::Scalar(ScalarFunc::BooleanToInt))),
1817 "int_to_boolean" => Ok(Some(Self::Scalar(ScalarFunc::IntToBoolean))),
1818 "validate_ipaddr" => Ok(Some(Self::Scalar(ScalarFunc::ValidateIpAddr))),
1819 "numeric_encode" => Ok(Some(Self::Scalar(ScalarFunc::NumericEncode))),
1820 "numeric_decode" => Ok(Some(Self::Scalar(ScalarFunc::NumericDecode))),
1821 "numeric_add" => Ok(Some(Self::Scalar(ScalarFunc::NumericAdd))),
1822 "numeric_sub" => Ok(Some(Self::Scalar(ScalarFunc::NumericSub))),
1823 "numeric_mul" => Ok(Some(Self::Scalar(ScalarFunc::NumericMul))),
1824 "numeric_div" => Ok(Some(Self::Scalar(ScalarFunc::NumericDiv))),
1825 "numeric_lt" => Ok(Some(Self::Scalar(ScalarFunc::NumericLt))),
1826 "numeric_eq" => Ok(Some(Self::Scalar(ScalarFunc::NumericEq))),
1827 "array" => Ok(Some(Self::Scalar(ScalarFunc::Array))),
1829 "array_element" => Ok(Some(Self::Scalar(ScalarFunc::ArrayElement))),
1830 "array_set_element" => Ok(Some(Self::Scalar(ScalarFunc::ArraySetElement))),
1831 "array_length" | "array_upper" => Ok(Some(Self::Scalar(ScalarFunc::ArrayLength))),
1833 "array_append" => Ok(Some(Self::Scalar(ScalarFunc::ArrayAppend))),
1834 "array_prepend" => Ok(Some(Self::Scalar(ScalarFunc::ArrayPrepend))),
1835 "array_cat" => Ok(Some(Self::Scalar(ScalarFunc::ArrayCat))),
1836 "array_remove" => Ok(Some(Self::Scalar(ScalarFunc::ArrayRemove))),
1837 "array_contains" => Ok(Some(Self::Scalar(ScalarFunc::ArrayContains))),
1838 "array_position" => Ok(Some(Self::Scalar(ScalarFunc::ArrayPosition))),
1839 "array_slice" => Ok(Some(Self::Scalar(ScalarFunc::ArraySlice))),
1840 "string_to_array" => Ok(Some(Self::Scalar(ScalarFunc::StringToArray))),
1841 "array_to_string" => Ok(Some(Self::Scalar(ScalarFunc::ArrayToString))),
1842 "array_overlap" | "array_overlaps" => Ok(Some(Self::Scalar(ScalarFunc::ArrayOverlap))),
1843 "array_contains_all" => Ok(Some(Self::Scalar(ScalarFunc::ArrayContainsAll))),
1844 "struct_pack" => Ok(Some(Self::Scalar(ScalarFunc::StructPack))),
1846 "struct_extract" => Ok(Some(Self::Scalar(ScalarFunc::StructExtractFunc))),
1847 "union_value" => Ok(Some(Self::Scalar(ScalarFunc::UnionValueFunc))),
1848 "union_tag" => Ok(Some(Self::Scalar(ScalarFunc::UnionTagFunc))),
1849 "union_extract" => Ok(Some(Self::Scalar(ScalarFunc::UnionExtractFunc))),
1850 "nextval" => Ok(Some(Self::Scalar(ScalarFunc::NextVal))),
1852 "currval" => Ok(Some(Self::Scalar(ScalarFunc::CurrVal))),
1853 "setval" => Ok(Some(Self::Scalar(ScalarFunc::SetVal))),
1854 _ => Ok(None),
1855 }
1856 }
1857
1858 pub fn builtin_function_list() -> Vec<FunctionListEntry> {
1862 let mut funcs = Vec::new();
1863
1864 let mut push = |name: String, func_type: &'static str, arities: &[i32], det: bool| {
1866 for &narg in arities {
1867 funcs.push(FunctionListEntry {
1868 name: name.clone(),
1869 func_type,
1870 narg,
1871 deterministic: det,
1872 });
1873 }
1874 };
1875
1876 for f in ScalarFunc::iter() {
1878 if f.is_internal() {
1879 continue;
1880 }
1881 push(f.to_string(), "s", f.arities(), f.is_deterministic());
1882 }
1883
1884 for f in AggFunc::iter() {
1888 push(f.to_string(), "w", f.arities(), f.is_deterministic());
1889 }
1890
1891 for f in WindowFunc::iter() {
1893 if !f.is_implemented() {
1894 continue;
1895 }
1896 push(f.to_string(), "w", f.arities(), f.is_deterministic());
1897 }
1898
1899 for f in MathFunc::iter() {
1901 push(f.to_string(), "s", f.arities(), f.is_deterministic());
1902 }
1903
1904 for f in VectorFunc::iter() {
1906 push(f.to_string(), "s", f.arities(), f.is_deterministic());
1907 }
1908
1909 #[cfg(clt_turso_feature = "json")]
1911 for f in JsonFunc::iter() {
1912 if f.is_internal() {
1913 continue;
1914 }
1915 push(f.to_string(), "s", f.arities(), f.is_deterministic());
1916 }
1917
1918 #[cfg(all(clt_turso_feature = "fts", not(target_family = "wasm")))]
1920 for f in FtsFunc::iter() {
1921 push(f.to_string(), "s", f.arities(), f.is_deterministic());
1922 }
1923
1924 funcs.push(FunctionListEntry {
1928 name: "format".into(),
1929 func_type: "s",
1930 narg: -1,
1931 deterministic: true,
1932 });
1933 funcs.push(FunctionListEntry {
1934 name: "if".into(),
1935 func_type: "s",
1936 narg: 3,
1937 deterministic: true,
1938 });
1939
1940 funcs
1941 }
1942}
1943
1944pub struct FunctionListEntry {
1945 pub name: String,
1946 pub func_type: &'static str, pub narg: i32, pub deterministic: bool,
1949}