1use akar_common::types::Value;
9use akar_common::vector::DataChunk;
10use hashbrown::HashMap;
11use std::sync::Arc;
12
13#[derive(Clone)]
17#[allow(clippy::type_complexity)]
18pub enum ScalarFunction {
19 Arithmetic {
20 op: ArithmeticOp,
21 },
22 Comparison {
23 op: ComparisonOp,
24 },
25 String {
26 op: StringOp,
27 },
28 Cast {
29 target_type: CastTarget,
30 },
31 Date {
32 op: DateOp,
33 },
34 List {
35 op: ListOp,
36 },
37 Map {
38 op: MapOp,
39 },
40 Struct {
41 op: StructOp,
42 },
43 Boolean {
44 op: BooleanOp,
45 },
46 Utility {
47 op: UtilityOp,
48 },
49 Schema {
50 op: SchemaOp,
51 },
52 Array {
53 op: ArrayOp,
54 },
55 Path {
57 op: PathOp,
58 },
59 Uuid,
61 CustomScalar {
64 name: String,
65 execute: Arc<dyn Fn(&[Value]) -> Result<Value, String> + Send + Sync>,
66 },
67 SequenceOp {
70 is_nextval: bool,
71 },
72 Hash {
74 op: HashOp,
75 },
76 Interval {
78 op: IntervalOp,
79 },
80 Blob {
82 op: BlobOp,
83 },
84 Union {
86 op: UnionOp,
87 },
88}
89
90impl std::fmt::Debug for ScalarFunction {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 match self {
93 Self::Arithmetic { op } => f.debug_struct("Arithmetic").field("op", op).finish(),
94 Self::Comparison { op } => f.debug_struct("Comparison").field("op", op).finish(),
95 Self::String { op } => f.debug_struct("String").field("op", op).finish(),
96 Self::Cast { target_type } => f.debug_struct("Cast").field("target_type", target_type).finish(),
97 Self::Date { op } => f.debug_struct("Date").field("op", op).finish(),
98 Self::List { op } => f.debug_struct("List").field("op", op).finish(),
99 Self::Map { op } => f.debug_struct("Map").field("op", op).finish(),
100 Self::Struct { op } => f.debug_struct("Struct").field("op", op).finish(),
101 Self::Boolean { op } => f.debug_struct("Boolean").field("op", op).finish(),
102 Self::Utility { op } => f.debug_struct("Utility").field("op", op).finish(),
103 Self::Schema { op } => f.debug_struct("Schema").field("op", op).finish(),
104 Self::Array { op } => f.debug_struct("Array").field("op", op).finish(),
105 Self::Path { op } => f.debug_struct("Path").field("op", op).finish(),
106 Self::Uuid => f.debug_struct("Uuid").finish(),
107 Self::CustomScalar { name, .. } => f.debug_struct("CustomScalar").field("name", name).finish(),
108 Self::SequenceOp { is_nextval } => f.debug_struct("SequenceOp").field("is_nextval", is_nextval).finish(),
109 Self::Hash { op } => f.debug_struct("Hash").field("op", op).finish(),
110 Self::Interval { op } => f.debug_struct("Interval").field("op", op).finish(),
111 Self::Blob { op } => f.debug_struct("Blob").field("op", op).finish(),
112 Self::Union { op } => f.debug_struct("Union").field("op", op).finish(),
113 }
114 }
115}
116
117#[derive(Debug, Clone, Copy)]
118pub enum ArithmeticOp {
119 Add,
120 Sub,
121 Mul,
122 Div,
123 Mod,
124 Abs,
125 Ceil,
126 Floor,
127 Round,
128 Negate,
129 Power,
130 Sqrt,
131 Log,
132 Exp,
133 Sin,
134 Cos,
135 Tan,
136 Asin,
137 Acos,
138 Atan,
139 Atan2,
140 Sinh,
141 Cosh,
142 Tanh,
143 Degrees,
144 Radians,
145 Sign,
146 Pi,
147 Rand,
148 Cbrt,
150 Cot,
151 Log2,
152 Even,
153 Gcd,
154 Lcm,
155 Factorial,
157 Gamma,
158 Lgamma,
159 SetSeed,
161 BitwiseAnd,
163 BitwiseOr,
164 BitwiseXor,
165 BitShiftLeft,
166 BitShiftRight,
167}
168
169#[derive(Debug, Clone, Copy)]
170pub enum ComparisonOp {
171 Eq,
172 NotEq,
173 Lt,
174 Lte,
175 Gt,
176 Gte,
177 IsNull,
178 IsNotNull,
179}
180
181#[derive(Debug, Clone, Copy)]
182pub enum StringOp {
183 Concat,
184 Contains,
185 StartsWith,
186 EndsWith,
187 ToUpper,
188 ToLower,
189 Trim,
190 LTrim,
191 RTrim,
192 Length,
193 Reverse,
194 Repeat,
195 Replace,
196 Substring,
197 RegexMatches,
198 RegexReplace,
199 Split,
200 Head,
201 Tail,
202 Left,
203 Right,
204 Lpad,
205 Rpad,
206 InitCap,
208 Soundex,
209 ConcatWs,
210 SplitPart,
211 ArrayExtract,
212 RegexpFullMatch,
214 RegexpExtract,
215 RegexpExtractAll,
216 RegexpSplitToArray,
217 Levenshtein,
219 Like,
221}
222
223#[derive(Debug, Clone, Copy)]
224pub enum CastTarget {
225 String,
226 Int64,
227 Int32,
228 Double,
229 Float,
230 Bool,
231 Date,
232 Timestamp,
233 Interval,
234}
235
236#[derive(Debug, Clone, Copy)]
237pub enum DateOp {
238 DatePart,
239 DateTrunc,
240 DateDiff,
241 DateAdd,
242 CurrentDate,
243 CurrentTimestamp,
244 Year,
245 Month,
246 Day,
247 Hour,
248 Minute,
249 Second,
250 DayName,
251 MonthName,
252 LastDay,
253 MakeDate,
254 Century,
256 EpochMs,
257 ToTimestamp,
258 ToEpochMs,
259}
260
261#[derive(Debug, Clone, Copy)]
262pub enum ListOp {
263 Creation,
264 Extract,
265 Concat,
266 Len,
267 Sort,
268 Reverse,
269 Contains,
270 Append,
271 Prepend,
272 Slice,
273 Range,
275 Distinct,
276 Unique,
277 Sum,
278 Product,
279 AnyValue,
280 ToString,
281 Position,
282 HasAll,
283 ReverseSort,
284 Any,
286 All,
287 None,
288 Single,
289 Count,
290 Min,
291 Max,
292 HasAny,
293 Transform,
295 Filter,
296 Reduce,
297}
298
299#[derive(Debug, Clone, Copy)]
300pub enum MapOp {
301 Creation,
302 Extract,
303 MapFromEntries,
304 Keys,
305 Values,
306 Contains,
307}
308
309#[derive(Debug, Clone, Copy)]
310pub enum StructOp {
311 Creation,
312 Extract,
313}
314
315#[derive(Debug, Clone, Copy)]
316pub enum BooleanOp {
317 And,
318 Or,
319 Xor,
320 Not,
321}
322
323#[derive(Debug, Clone, Copy)]
325pub enum UtilityOp {
326 Coalesce,
327 IfNull,
328 TypeOf,
329 NullIf,
330 Size,
331 Error,
332 PgIsReady,
333 Greatest,
335 Least,
337 ConstantOrNull,
340}
341
342#[derive(Debug, Clone, Copy)]
351pub enum SchemaOp {
352 Offset,
353 Id,
354 StartNode,
355 EndNode,
356 Label,
357 Cost,
359 RowId,
361}
362
363#[derive(Debug, Clone, Copy)]
370pub enum PathOp {
371 Nodes,
372 Rels,
373 Length,
374 Properties,
376 IsTrail,
378 IsAcyclic,
380}
381
382#[derive(Debug, Clone, Copy)]
391pub enum ArrayOp {
392 CosineSimilarity,
393 Distance,
394 InnerProduct,
395 DotProduct,
396 CrossProduct,
397 SquaredDistance,
398 Intersect,
399}
400
401#[derive(Debug, Clone, Copy)]
407pub enum HashOp {
408 Md5,
409 Sha256,
410 Hash,
411}
412
413#[derive(Debug, Clone, Copy)]
425pub enum IntervalOp {
426 ToYears,
427 ToMonths,
428 ToDays,
429 ToHours,
430 ToMinutes,
431 ToSeconds,
432 ToMilliseconds,
433 ToMicroseconds,
434}
435
436#[derive(Debug, Clone, Copy)]
442pub enum BlobOp {
443 Encode,
444 Decode,
445 OctetLength,
446 ToBase64,
447 FromBase64,
448 BlobFromBytes,
449}
450
451#[derive(Debug, Clone, Copy)]
458pub enum UnionOp {
459 UnionValue,
460 UnionTag,
461 UnionExtract,
462}
463
464#[derive(Debug, Clone)]
468pub enum AggregateFunction {
469 Count,
470 Sum,
471 Avg,
472 Min,
473 Max,
474 Collect,
475 CountStar,
476 StdDev,
477 Variance,
478 StringAgg {
480 delimiter: String,
481 },
482 PercentileDisc {
484 percentile: f64,
485 },
486 PercentileCont {
488 percentile: f64,
489 },
490 CountIf,
492}
493
494#[derive(Clone)]
498pub enum TableFunction {
499 ScanCsv {
500 path: String,
501 },
502 ScanParquet {
503 path: String,
504 },
505 ScanJson {
506 path: String,
507 },
508 ListTables,
509 ShowColumns {
510 table_name: String,
511 },
512 CurrentSetting {
513 key: String,
514 },
515 Custom {
518 name: String,
519 },
520 #[allow(clippy::type_complexity)]
523 CustomTable {
524 name: String,
525 execute: Arc<dyn Fn(&[Value], &mut DataChunk) -> Result<(), String> + Send + Sync>,
526 },
527 #[allow(clippy::type_complexity)]
532 CustomTableWithGraph {
533 name: String,
534 execute: Arc<
535 dyn Fn(&[Value], Option<&dyn crate::graph::GraphDataSource>, &mut DataChunk) -> Result<(), String>
536 + Send
537 + Sync,
538 >,
539 },
540}
541
542impl std::fmt::Debug for TableFunction {
543 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
544 match self {
545 Self::ScanCsv { path } => f.debug_struct("ScanCsv").field("path", path).finish(),
546 Self::ScanParquet { path } => f.debug_struct("ScanParquet").field("path", path).finish(),
547 Self::ScanJson { path } => f.debug_struct("ScanJson").field("path", path).finish(),
548 Self::ListTables => write!(f, "ListTables"),
549 Self::ShowColumns { table_name } => f.debug_struct("ShowColumns").field("table_name", table_name).finish(),
550 Self::CurrentSetting { key } => f.debug_struct("CurrentSetting").field("key", key).finish(),
551 Self::Custom { name } => f.debug_struct("Custom").field("name", name).finish(),
552 Self::CustomTable { name, .. } => f.debug_struct("CustomTable").field("name", name).finish(),
553 Self::CustomTableWithGraph { name, .. } => {
554 f.debug_struct("CustomTableWithGraph").field("name", name).finish()
555 }
556 }
557 }
558}
559
560#[derive(Debug, Clone)]
562pub enum ResolvedFunction {
563 Scalar(ScalarFunction),
564 Aggregate(AggregateFunction),
565 Table(TableFunction),
566}
567
568#[derive(Default)]
572pub struct FunctionRegistry {
573 scalar_functions: HashMap<String, ScalarFunction>,
574 aggregate_functions: HashMap<String, AggregateFunction>,
575 table_functions: HashMap<String, TableFunction>,
576}
577
578impl FunctionRegistry {
579 pub fn new() -> Self {
580 let mut reg = Self::default();
581 reg.register_builtins();
582 reg
583 }
584
585 fn register_builtins(&mut self) {
586 self.register_scalar("+", ScalarFunction::Arithmetic { op: ArithmeticOp::Add });
588 self.register_scalar("-", ScalarFunction::Arithmetic { op: ArithmeticOp::Sub });
589 self.register_scalar("*", ScalarFunction::Arithmetic { op: ArithmeticOp::Mul });
590 self.register_scalar("/", ScalarFunction::Arithmetic { op: ArithmeticOp::Div });
591 self.register_scalar("%", ScalarFunction::Arithmetic { op: ArithmeticOp::Mod });
592 self.register_scalar("abs", ScalarFunction::Arithmetic { op: ArithmeticOp::Abs });
593 self.register_scalar("ceil", ScalarFunction::Arithmetic { op: ArithmeticOp::Ceil });
594 self.register_scalar("ceiling", ScalarFunction::Arithmetic { op: ArithmeticOp::Ceil });
596 self.register_scalar(
597 "floor",
598 ScalarFunction::Arithmetic {
599 op: ArithmeticOp::Floor,
600 },
601 );
602 self.register_scalar(
603 "round",
604 ScalarFunction::Arithmetic {
605 op: ArithmeticOp::Round,
606 },
607 );
608 self.register_scalar(
609 "^",
610 ScalarFunction::Arithmetic {
611 op: ArithmeticOp::Power,
612 },
613 );
614 self.register_scalar("sqrt", ScalarFunction::Arithmetic { op: ArithmeticOp::Sqrt });
615 self.register_scalar(
617 "pow",
618 ScalarFunction::Arithmetic {
619 op: ArithmeticOp::Power,
620 },
621 );
622 self.register_scalar("log10", ScalarFunction::Arithmetic { op: ArithmeticOp::Log });
623 self.register_scalar("cbrt", ScalarFunction::Arithmetic { op: ArithmeticOp::Cbrt });
625 self.register_scalar("cot", ScalarFunction::Arithmetic { op: ArithmeticOp::Cot });
626 self.register_scalar("log", ScalarFunction::Arithmetic { op: ArithmeticOp::Log });
627 self.register_scalar("ln", ScalarFunction::Arithmetic { op: ArithmeticOp::Log });
628 self.register_scalar("log2", ScalarFunction::Arithmetic { op: ArithmeticOp::Log2 });
629 self.register_scalar("even", ScalarFunction::Arithmetic { op: ArithmeticOp::Even });
630 self.register_scalar(
631 "factorial",
632 ScalarFunction::Arithmetic {
633 op: ArithmeticOp::Factorial,
634 },
635 );
636 self.register_scalar(
637 "gamma",
638 ScalarFunction::Arithmetic {
639 op: ArithmeticOp::Gamma,
640 },
641 );
642 self.register_scalar(
643 "lgamma",
644 ScalarFunction::Arithmetic {
645 op: ArithmeticOp::Lgamma,
646 },
647 );
648 self.register_scalar(
649 "set_seed",
650 ScalarFunction::Arithmetic {
651 op: ArithmeticOp::SetSeed,
652 },
653 );
654 self.register_scalar("exp", ScalarFunction::Arithmetic { op: ArithmeticOp::Exp });
655 self.register_scalar("sin", ScalarFunction::Arithmetic { op: ArithmeticOp::Sin });
656 self.register_scalar("cos", ScalarFunction::Arithmetic { op: ArithmeticOp::Cos });
657 self.register_scalar("tan", ScalarFunction::Arithmetic { op: ArithmeticOp::Tan });
658 self.register_scalar("asin", ScalarFunction::Arithmetic { op: ArithmeticOp::Asin });
659 self.register_scalar("acos", ScalarFunction::Arithmetic { op: ArithmeticOp::Acos });
660 self.register_scalar("atan", ScalarFunction::Arithmetic { op: ArithmeticOp::Atan });
661 self.register_scalar(
662 "atan2",
663 ScalarFunction::Arithmetic {
664 op: ArithmeticOp::Atan2,
665 },
666 );
667 self.register_scalar(
668 "degrees",
669 ScalarFunction::Arithmetic {
670 op: ArithmeticOp::Degrees,
671 },
672 );
673 self.register_scalar(
674 "radians",
675 ScalarFunction::Arithmetic {
676 op: ArithmeticOp::Radians,
677 },
678 );
679 self.register_scalar("sign", ScalarFunction::Arithmetic { op: ArithmeticOp::Sign });
680 self.register_scalar("pi", ScalarFunction::Arithmetic { op: ArithmeticOp::Pi });
681 self.register_scalar("rand", ScalarFunction::Arithmetic { op: ArithmeticOp::Rand });
682
683 self.register_scalar("sinh", ScalarFunction::Arithmetic { op: ArithmeticOp::Sinh });
684 self.register_scalar("cosh", ScalarFunction::Arithmetic { op: ArithmeticOp::Cosh });
685 self.register_scalar("tanh", ScalarFunction::Arithmetic { op: ArithmeticOp::Tanh });
686 self.register_scalar("gcd", ScalarFunction::Arithmetic { op: ArithmeticOp::Gcd });
687 self.register_scalar("lcm", ScalarFunction::Arithmetic { op: ArithmeticOp::Lcm });
688
689 self.register_scalar(
691 "bitwise_and",
692 ScalarFunction::Arithmetic {
693 op: ArithmeticOp::BitwiseAnd,
694 },
695 );
696 self.register_scalar(
697 "&",
698 ScalarFunction::Arithmetic {
699 op: ArithmeticOp::BitwiseAnd,
700 },
701 );
702 self.register_scalar(
703 "bitwise_or",
704 ScalarFunction::Arithmetic {
705 op: ArithmeticOp::BitwiseOr,
706 },
707 );
708 self.register_scalar(
709 "|",
710 ScalarFunction::Arithmetic {
711 op: ArithmeticOp::BitwiseOr,
712 },
713 );
714 self.register_scalar(
715 "bitwise_xor",
716 ScalarFunction::Arithmetic {
717 op: ArithmeticOp::BitwiseXor,
718 },
719 );
720 self.register_scalar(
721 "#",
722 ScalarFunction::Arithmetic {
723 op: ArithmeticOp::BitwiseXor,
724 },
725 );
726 self.register_scalar(
727 "bit_shift_left",
728 ScalarFunction::Arithmetic {
729 op: ArithmeticOp::BitShiftLeft,
730 },
731 );
732 self.register_scalar(
733 "<<",
734 ScalarFunction::Arithmetic {
735 op: ArithmeticOp::BitShiftLeft,
736 },
737 );
738 self.register_scalar(
739 "bit_shift_right",
740 ScalarFunction::Arithmetic {
741 op: ArithmeticOp::BitShiftRight,
742 },
743 );
744 self.register_scalar(
745 ">>",
746 ScalarFunction::Arithmetic {
747 op: ArithmeticOp::BitShiftRight,
748 },
749 );
750
751 self.register_scalar("=", ScalarFunction::Comparison { op: ComparisonOp::Eq });
753 self.register_scalar(
754 "<>",
755 ScalarFunction::Comparison {
756 op: ComparisonOp::NotEq,
757 },
758 );
759 self.register_scalar("<", ScalarFunction::Comparison { op: ComparisonOp::Lt });
760 self.register_scalar("<=", ScalarFunction::Comparison { op: ComparisonOp::Lte });
761 self.register_scalar(">", ScalarFunction::Comparison { op: ComparisonOp::Gt });
762 self.register_scalar(">=", ScalarFunction::Comparison { op: ComparisonOp::Gte });
763 self.register_scalar(
764 "IS NULL",
765 ScalarFunction::Comparison {
766 op: ComparisonOp::IsNull,
767 },
768 );
769 self.register_scalar(
770 "IS NOT NULL",
771 ScalarFunction::Comparison {
772 op: ComparisonOp::IsNotNull,
773 },
774 );
775
776 self.register_scalar("concat", ScalarFunction::String { op: StringOp::Concat });
778 self.register_scalar("contains", ScalarFunction::String { op: StringOp::Contains });
779 self.register_scalar(
780 "starts_with",
781 ScalarFunction::String {
782 op: StringOp::StartsWith,
783 },
784 );
785 self.register_scalar("ends_with", ScalarFunction::String { op: StringOp::EndsWith });
786 self.register_scalar(
788 "prefix",
789 ScalarFunction::String {
790 op: StringOp::StartsWith,
791 },
792 );
793 self.register_scalar("suffix", ScalarFunction::String { op: StringOp::EndsWith });
794 self.register_scalar("like", ScalarFunction::String { op: StringOp::Like });
795 self.register_scalar("to_upper", ScalarFunction::String { op: StringOp::ToUpper });
796 self.register_scalar("to_lower", ScalarFunction::String { op: StringOp::ToLower });
797 self.register_scalar("upper", ScalarFunction::String { op: StringOp::ToUpper });
799 self.register_scalar("lower", ScalarFunction::String { op: StringOp::ToLower });
800 self.register_scalar("ucase", ScalarFunction::String { op: StringOp::ToUpper });
801 self.register_scalar("lcase", ScalarFunction::String { op: StringOp::ToLower });
802 self.register_scalar("trim", ScalarFunction::String { op: StringOp::Trim });
803 self.register_scalar("ltrim", ScalarFunction::String { op: StringOp::LTrim });
804 self.register_scalar("rtrim", ScalarFunction::String { op: StringOp::RTrim });
805 self.register_scalar("length", ScalarFunction::String { op: StringOp::Length });
806 self.register_scalar("reverse", ScalarFunction::String { op: StringOp::Reverse });
807 self.register_scalar("repeat", ScalarFunction::String { op: StringOp::Repeat });
808 self.register_scalar("replace", ScalarFunction::String { op: StringOp::Replace });
809 self.register_scalar(
810 "substring",
811 ScalarFunction::String {
812 op: StringOp::Substring,
813 },
814 );
815 self.register_scalar(
816 "regex_matches",
817 ScalarFunction::String {
818 op: StringOp::RegexMatches,
819 },
820 );
821 self.register_scalar(
822 "regex_replace",
823 ScalarFunction::String {
824 op: StringOp::RegexReplace,
825 },
826 );
827 self.register_scalar("split", ScalarFunction::String { op: StringOp::Split });
828 self.register_scalar("head", ScalarFunction::String { op: StringOp::Head });
829 self.register_scalar("tail", ScalarFunction::String { op: StringOp::Tail });
830 self.register_scalar("left", ScalarFunction::String { op: StringOp::Left });
831 self.register_scalar("right", ScalarFunction::String { op: StringOp::Right });
832 self.register_scalar("lpad", ScalarFunction::String { op: StringOp::Lpad });
833 self.register_scalar("rpad", ScalarFunction::String { op: StringOp::Rpad });
834
835 self.register_scalar("initcap", ScalarFunction::String { op: StringOp::InitCap });
837 self.register_scalar("concat_ws", ScalarFunction::String { op: StringOp::ConcatWs });
838 self.register_scalar(
839 "split_part",
840 ScalarFunction::String {
841 op: StringOp::SplitPart,
842 },
843 );
844 self.register_scalar(
845 "array_extract",
846 ScalarFunction::String {
847 op: StringOp::ArrayExtract,
848 },
849 );
850
851 self.register_scalar(
853 "regexp_full_match",
854 ScalarFunction::String {
855 op: StringOp::RegexpFullMatch,
856 },
857 );
858 self.register_scalar(
859 "regexp_extract",
860 ScalarFunction::String {
861 op: StringOp::RegexpExtract,
862 },
863 );
864 self.register_scalar(
865 "regexp_extract_all",
866 ScalarFunction::String {
867 op: StringOp::RegexpExtractAll,
868 },
869 );
870 self.register_scalar(
871 "regexp_split_to_array",
872 ScalarFunction::String {
873 op: StringOp::RegexpSplitToArray,
874 },
875 );
876 self.register_scalar(
877 "levenshtein",
878 ScalarFunction::String {
879 op: StringOp::Levenshtein,
880 },
881 );
882 self.register_scalar("soundex", ScalarFunction::String { op: StringOp::Soundex });
883
884 self.register_scalar("md5", ScalarFunction::Hash { op: HashOp::Md5 });
886 self.register_scalar("sha256", ScalarFunction::Hash { op: HashOp::Sha256 });
887 self.register_scalar("hash", ScalarFunction::Hash { op: HashOp::Hash });
888
889 self.register_scalar(
891 "to_years",
892 ScalarFunction::Interval {
893 op: IntervalOp::ToYears,
894 },
895 );
896 self.register_scalar(
897 "to_months",
898 ScalarFunction::Interval {
899 op: IntervalOp::ToMonths,
900 },
901 );
902 self.register_scalar("to_days", ScalarFunction::Interval { op: IntervalOp::ToDays });
903 self.register_scalar(
904 "to_hours",
905 ScalarFunction::Interval {
906 op: IntervalOp::ToHours,
907 },
908 );
909 self.register_scalar(
910 "to_minutes",
911 ScalarFunction::Interval {
912 op: IntervalOp::ToMinutes,
913 },
914 );
915 self.register_scalar(
916 "to_seconds",
917 ScalarFunction::Interval {
918 op: IntervalOp::ToSeconds,
919 },
920 );
921 self.register_scalar(
922 "to_milliseconds",
923 ScalarFunction::Interval {
924 op: IntervalOp::ToMilliseconds,
925 },
926 );
927 self.register_scalar(
928 "to_microseconds",
929 ScalarFunction::Interval {
930 op: IntervalOp::ToMicroseconds,
931 },
932 );
933
934 self.register_scalar("date_part", ScalarFunction::Date { op: DateOp::DatePart });
936 self.register_scalar("date_trunc", ScalarFunction::Date { op: DateOp::DateTrunc });
937 self.register_scalar("date_diff", ScalarFunction::Date { op: DateOp::DateDiff });
938 self.register_scalar("date_add", ScalarFunction::Date { op: DateOp::DateAdd });
939 self.register_scalar(
940 "current_date",
941 ScalarFunction::Date {
942 op: DateOp::CurrentDate,
943 },
944 );
945 self.register_scalar(
946 "current_timestamp",
947 ScalarFunction::Date {
948 op: DateOp::CurrentTimestamp,
949 },
950 );
951 self.register_scalar("year", ScalarFunction::Date { op: DateOp::Year });
952 self.register_scalar("month", ScalarFunction::Date { op: DateOp::Month });
953
954 self.register_scalar("nextval", ScalarFunction::SequenceOp { is_nextval: true });
956 self.register_scalar("currval", ScalarFunction::SequenceOp { is_nextval: false });
957 self.register_scalar("day", ScalarFunction::Date { op: DateOp::Day });
958 self.register_scalar("hour", ScalarFunction::Date { op: DateOp::Hour });
959 self.register_scalar("minute", ScalarFunction::Date { op: DateOp::Minute });
960 self.register_scalar("second", ScalarFunction::Date { op: DateOp::Second });
961 self.register_scalar("dayname", ScalarFunction::Date { op: DateOp::DayName });
962 self.register_scalar("monthname", ScalarFunction::Date { op: DateOp::MonthName });
963 self.register_scalar("last_day", ScalarFunction::Date { op: DateOp::LastDay });
964 self.register_scalar("make_date", ScalarFunction::Date { op: DateOp::MakeDate });
965 self.register_scalar("century", ScalarFunction::Date { op: DateOp::Century });
966 self.register_scalar("epoch_ms", ScalarFunction::Date { op: DateOp::EpochMs });
967 self.register_scalar(
968 "to_timestamp",
969 ScalarFunction::Date {
970 op: DateOp::ToTimestamp,
971 },
972 );
973 self.register_scalar("to_epoch_ms", ScalarFunction::Date { op: DateOp::ToEpochMs });
974
975 self.register_scalar(
977 "CAST",
978 ScalarFunction::Cast {
979 target_type: CastTarget::String,
980 },
981 );
982 self.register_scalar(
983 "cast_string",
984 ScalarFunction::Cast {
985 target_type: CastTarget::String,
986 },
987 );
988 self.register_scalar(
989 "cast_int64",
990 ScalarFunction::Cast {
991 target_type: CastTarget::Int64,
992 },
993 );
994 self.register_scalar(
995 "cast_double",
996 ScalarFunction::Cast {
997 target_type: CastTarget::Double,
998 },
999 );
1000 self.register_scalar(
1001 "cast_bool",
1002 ScalarFunction::Cast {
1003 target_type: CastTarget::Bool,
1004 },
1005 );
1006 self.register_scalar(
1008 "date",
1009 ScalarFunction::Cast {
1010 target_type: CastTarget::Date,
1011 },
1012 );
1013 self.register_scalar(
1014 "timestamp",
1015 ScalarFunction::Cast {
1016 target_type: CastTarget::Timestamp,
1017 },
1018 );
1019 self.register_scalar(
1020 "float",
1021 ScalarFunction::Cast {
1022 target_type: CastTarget::Double,
1023 },
1024 );
1025 self.register_scalar(
1026 "double",
1027 ScalarFunction::Cast {
1028 target_type: CastTarget::Double,
1029 },
1030 );
1031 self.register_scalar(
1032 "int64",
1033 ScalarFunction::Cast {
1034 target_type: CastTarget::Int64,
1035 },
1036 );
1037 self.register_scalar(
1038 "int",
1039 ScalarFunction::Cast {
1040 target_type: CastTarget::Int64,
1041 },
1042 );
1043 self.register_scalar(
1044 "bool",
1045 ScalarFunction::Cast {
1046 target_type: CastTarget::Bool,
1047 },
1048 );
1049 self.register_scalar(
1050 "boolean",
1051 ScalarFunction::Cast {
1052 target_type: CastTarget::Bool,
1053 },
1054 );
1055 self.register_scalar(
1056 "string",
1057 ScalarFunction::Cast {
1058 target_type: CastTarget::String,
1059 },
1060 );
1061 self.register_scalar(
1062 "blob",
1063 ScalarFunction::Cast {
1064 target_type: CastTarget::String,
1065 },
1066 );
1067
1068 self.register_scalar("encode", ScalarFunction::Blob { op: BlobOp::Encode });
1070 self.register_scalar("decode", ScalarFunction::Blob { op: BlobOp::Decode });
1071 self.register_scalar(
1072 "octet_length",
1073 ScalarFunction::Blob {
1074 op: BlobOp::OctetLength,
1075 },
1076 );
1077
1078 self.register_scalar("list_creation", ScalarFunction::List { op: ListOp::Creation });
1080 self.register_scalar("list_extract", ScalarFunction::List { op: ListOp::Extract });
1081 self.register_scalar("list_concat", ScalarFunction::List { op: ListOp::Concat });
1082 self.register_scalar("list_cat", ScalarFunction::List { op: ListOp::Concat });
1083 self.register_scalar("list_len", ScalarFunction::List { op: ListOp::Len });
1084 self.register_scalar("list_sort", ScalarFunction::List { op: ListOp::Sort });
1085 self.register_scalar("list_reverse", ScalarFunction::List { op: ListOp::Reverse });
1086 self.register_scalar("list_contains", ScalarFunction::List { op: ListOp::Contains });
1087 self.register_scalar("list_append", ScalarFunction::List { op: ListOp::Append });
1088 self.register_scalar("list_prepend", ScalarFunction::List { op: ListOp::Prepend });
1089 self.register_scalar("list_slice", ScalarFunction::List { op: ListOp::Slice });
1090
1091 self.register_scalar("range", ScalarFunction::List { op: ListOp::Range });
1093 self.register_scalar("list_distinct", ScalarFunction::List { op: ListOp::Distinct });
1094 self.register_scalar("list_unique", ScalarFunction::List { op: ListOp::Unique });
1095 self.register_scalar("list_sum", ScalarFunction::List { op: ListOp::Sum });
1096 self.register_scalar("list_product", ScalarFunction::List { op: ListOp::Product });
1097 self.register_scalar("list_any_value", ScalarFunction::List { op: ListOp::AnyValue });
1098 self.register_scalar("list_to_string", ScalarFunction::List { op: ListOp::ToString });
1099 self.register_scalar("list_position", ScalarFunction::List { op: ListOp::Position });
1100 self.register_scalar("list_indexof", ScalarFunction::List { op: ListOp::Position });
1101 self.register_scalar("list_has_all", ScalarFunction::List { op: ListOp::HasAll });
1102 self.register_scalar("list_has_any", ScalarFunction::List { op: ListOp::HasAny });
1103 self.register_scalar("list_count", ScalarFunction::List { op: ListOp::Count });
1104 self.register_scalar("list_min", ScalarFunction::List { op: ListOp::Min });
1105 self.register_scalar("list_max", ScalarFunction::List { op: ListOp::Max });
1106 self.register_scalar(
1107 "list_reverse_sort",
1108 ScalarFunction::List {
1109 op: ListOp::ReverseSort,
1110 },
1111 );
1112
1113 self.register_scalar("list_transform", ScalarFunction::List { op: ListOp::Transform });
1115 self.register_scalar("list_filter", ScalarFunction::List { op: ListOp::Filter });
1116 self.register_scalar("list_reduce", ScalarFunction::List { op: ListOp::Reduce });
1117
1118 self.register_scalar("any", ScalarFunction::List { op: ListOp::Any });
1120 self.register_scalar("all", ScalarFunction::List { op: ListOp::All });
1121 self.register_scalar("none", ScalarFunction::List { op: ListOp::None });
1122 self.register_scalar("single", ScalarFunction::List { op: ListOp::Single });
1123
1124 self.register_scalar("map_creation", ScalarFunction::Map { op: MapOp::Creation });
1126 self.register_scalar("map_extract", ScalarFunction::Map { op: MapOp::Extract });
1127 self.register_scalar("element_at", ScalarFunction::Map { op: MapOp::Extract });
1128 self.register_scalar("map_keys", ScalarFunction::Map { op: MapOp::Keys });
1129 self.register_scalar("map_values", ScalarFunction::Map { op: MapOp::Values });
1130
1131 self.register_scalar("struct_creation", ScalarFunction::Struct { op: StructOp::Creation });
1133 self.register_scalar("struct_extract", ScalarFunction::Struct { op: StructOp::Extract });
1134
1135 self.register_scalar(
1137 "union_value",
1138 ScalarFunction::Union {
1139 op: UnionOp::UnionValue,
1140 },
1141 );
1142 self.register_scalar(
1143 "union_extract",
1144 ScalarFunction::Union {
1145 op: UnionOp::UnionExtract,
1146 },
1147 );
1148 self.register_scalar("union_tag", ScalarFunction::Union { op: UnionOp::UnionTag });
1149
1150 self.register_scalar("AND", ScalarFunction::Boolean { op: BooleanOp::And });
1152 self.register_scalar("OR", ScalarFunction::Boolean { op: BooleanOp::Or });
1153 self.register_scalar("XOR", ScalarFunction::Boolean { op: BooleanOp::Xor });
1154 self.register_scalar("NOT", ScalarFunction::Boolean { op: BooleanOp::Not });
1155
1156 self.register_scalar(
1158 "coalesce",
1159 ScalarFunction::Utility {
1160 op: UtilityOp::Coalesce,
1161 },
1162 );
1163 self.register_scalar("ifnull", ScalarFunction::Utility { op: UtilityOp::IfNull });
1164 self.register_scalar("nullif", ScalarFunction::Utility { op: UtilityOp::NullIf });
1165 self.register_scalar("size", ScalarFunction::Utility { op: UtilityOp::Size });
1166 self.register_scalar("cardinality", ScalarFunction::Utility { op: UtilityOp::Size });
1167 self.register_scalar("typeof", ScalarFunction::Utility { op: UtilityOp::TypeOf });
1168 self.register_scalar("error", ScalarFunction::Utility { op: UtilityOp::Error });
1169 self.register_scalar(
1170 "pg_isready",
1171 ScalarFunction::Utility {
1172 op: UtilityOp::PgIsReady,
1173 },
1174 );
1175
1176 self.register_scalar(
1178 "greatest",
1179 ScalarFunction::Utility {
1180 op: UtilityOp::Greatest,
1181 },
1182 );
1183 self.register_scalar("least", ScalarFunction::Utility { op: UtilityOp::Least });
1184 self.register_scalar(
1185 "constant_or_null",
1186 ScalarFunction::Utility {
1187 op: UtilityOp::ConstantOrNull,
1188 },
1189 );
1190
1191 self.register_scalar("OFFSET", ScalarFunction::Schema { op: SchemaOp::Offset });
1193 self.register_scalar("ID", ScalarFunction::Schema { op: SchemaOp::Id });
1194 self.register_scalar(
1195 "START_NODE",
1196 ScalarFunction::Schema {
1197 op: SchemaOp::StartNode,
1198 },
1199 );
1200 self.register_scalar("END_NODE", ScalarFunction::Schema { op: SchemaOp::EndNode });
1201 self.register_scalar("LABEL", ScalarFunction::Schema { op: SchemaOp::Label });
1202 self.register_scalar("COST", ScalarFunction::Schema { op: SchemaOp::Cost });
1203 self.register_scalar("ROWID", ScalarFunction::Schema { op: SchemaOp::RowId });
1204
1205 self.register_scalar(
1207 "array_cosine_similarity",
1208 ScalarFunction::Array {
1209 op: ArrayOp::CosineSimilarity,
1210 },
1211 );
1212 self.register_scalar("array_distance", ScalarFunction::Array { op: ArrayOp::Distance });
1213 self.register_scalar(
1214 "array_inner_product",
1215 ScalarFunction::Array {
1216 op: ArrayOp::InnerProduct,
1217 },
1218 );
1219 self.register_scalar(
1220 "array_dot_product",
1221 ScalarFunction::Array {
1222 op: ArrayOp::DotProduct,
1223 },
1224 );
1225 self.register_scalar(
1226 "array_cross_product",
1227 ScalarFunction::Array {
1228 op: ArrayOp::CrossProduct,
1229 },
1230 );
1231 self.register_scalar(
1232 "array_squared_distance",
1233 ScalarFunction::Array {
1234 op: ArrayOp::SquaredDistance,
1235 },
1236 );
1237 self.register_scalar("array_intersect", ScalarFunction::Array { op: ArrayOp::Intersect });
1238
1239 self.register_scalar("nodes", ScalarFunction::Path { op: PathOp::Nodes });
1241 self.register_scalar("rels", ScalarFunction::Path { op: PathOp::Rels });
1242 self.register_scalar("relationships", ScalarFunction::Path { op: PathOp::Rels });
1243 self.register_scalar("properties", ScalarFunction::Path { op: PathOp::Properties });
1244 self.register_scalar("is_trail", ScalarFunction::Path { op: PathOp::IsTrail });
1245 self.register_scalar("is_acyclic", ScalarFunction::Path { op: PathOp::IsAcyclic });
1246
1247 self.register_scalar("gen_random_uuid", ScalarFunction::Uuid);
1249
1250 self.register_scalar(
1252 "map_from_entries",
1253 ScalarFunction::Map {
1254 op: MapOp::MapFromEntries,
1255 },
1256 );
1257
1258 self.register_scalar(
1260 "blob_from_bytes",
1261 ScalarFunction::Blob {
1262 op: BlobOp::BlobFromBytes,
1263 },
1264 );
1265 self.register_scalar("to_base64", ScalarFunction::Blob { op: BlobOp::ToBase64 });
1266 self.register_scalar("from_base64", ScalarFunction::Blob { op: BlobOp::FromBase64 });
1267
1268 self.register_scalar("array_concat", ScalarFunction::List { op: ListOp::Concat });
1270 self.register_scalar("array_cat", ScalarFunction::List { op: ListOp::Concat });
1271 self.register_scalar("array_append", ScalarFunction::List { op: ListOp::Append });
1272 self.register_scalar("array_push_back", ScalarFunction::List { op: ListOp::Append });
1273 self.register_scalar("array_prepend", ScalarFunction::List { op: ListOp::Prepend });
1274 self.register_scalar("array_push_front", ScalarFunction::List { op: ListOp::Prepend });
1275 self.register_scalar("array_contains", ScalarFunction::List { op: ListOp::Contains });
1276 self.register_scalar("array_has", ScalarFunction::List { op: ListOp::Contains });
1277 self.register_scalar("array_slice", ScalarFunction::List { op: ListOp::Slice });
1278 self.register_scalar("array_value", ScalarFunction::List { op: ListOp::Creation });
1279
1280 self.register_aggregate("COUNT", AggregateFunction::Count);
1282 self.register_aggregate("COUNT(*)", AggregateFunction::CountStar);
1283 self.register_aggregate("COUNT_IF", AggregateFunction::CountIf);
1284 self.register_aggregate("SUM", AggregateFunction::Sum);
1285 self.register_aggregate("AVG", AggregateFunction::Avg);
1286 self.register_aggregate("MIN", AggregateFunction::Min);
1287 self.register_aggregate("MAX", AggregateFunction::Max);
1288 self.register_aggregate("COLLECT", AggregateFunction::Collect);
1289 self.register_aggregate("STDDEV", AggregateFunction::StdDev);
1290 self.register_aggregate("VARIANCE", AggregateFunction::Variance);
1291 self.register_aggregate(
1292 "STRING_AGG",
1293 AggregateFunction::StringAgg {
1294 delimiter: ",".to_string(),
1295 },
1296 );
1297 self.register_aggregate(
1298 "GROUP_CONCAT",
1299 AggregateFunction::StringAgg {
1300 delimiter: ",".to_string(),
1301 },
1302 );
1303 self.register_aggregate("PERCENTILE_DISC", AggregateFunction::PercentileDisc { percentile: 0.5 });
1304 self.register_aggregate("PERCENTILE_CONT", AggregateFunction::PercentileCont { percentile: 0.5 });
1305
1306 self.register_table("list_tables", TableFunction::ListTables);
1308 }
1309
1310 pub fn register_scalar(&mut self, name: &str, func: ScalarFunction) {
1313 self.scalar_functions.insert(name.to_lowercase(), func);
1314 }
1315
1316 pub fn register_aggregate(&mut self, name: &str, func: AggregateFunction) {
1317 self.aggregate_functions.insert(name.to_lowercase(), func);
1318 }
1319
1320 pub fn register_table(&mut self, name: &str, func: TableFunction) {
1321 self.table_functions.insert(name.to_lowercase(), func);
1322 }
1323
1324 pub fn resolve(&self, name: &str) -> Option<ResolvedFunction> {
1327 let lower = name.to_lowercase();
1328 if let Some(f) = self.scalar_functions.get(&lower) {
1329 return Some(ResolvedFunction::Scalar(f.clone()));
1330 }
1331 if let Some(f) = self.aggregate_functions.get(&lower) {
1332 return Some(ResolvedFunction::Aggregate(f.clone()));
1333 }
1334 if let Some(f) = self.table_functions.get(&lower) {
1335 return Some(ResolvedFunction::Table(f.clone()));
1336 }
1337 None
1338 }
1339
1340 pub fn get_scalar(&self, name: &str) -> Option<&ScalarFunction> {
1341 self.scalar_functions.get(&name.to_lowercase())
1342 }
1343
1344 pub fn get_aggregate(&self, name: &str) -> Option<&AggregateFunction> {
1345 self.aggregate_functions.get(&name.to_lowercase())
1346 }
1347
1348 pub fn get_table(&self, name: &str) -> Option<&TableFunction> {
1349 self.table_functions.get(&name.to_lowercase())
1350 }
1351
1352 pub fn list_all(&self) -> Vec<(String, String)> {
1355 let mut result = Vec::new();
1356 for name in self.scalar_functions.keys() {
1357 result.push((name.clone(), "SCALAR".to_string()));
1358 }
1359 for name in self.aggregate_functions.keys() {
1360 result.push((name.clone(), "AGGREGATE".to_string()));
1361 }
1362 for name in self.table_functions.keys() {
1363 result.push((name.clone(), "TABLE".to_string()));
1364 }
1365 result.sort_by(|a, b| a.0.cmp(&b.0));
1366 result
1367 }
1368
1369 pub fn contains(&self, name: &str) -> bool {
1370 let lower = name.to_lowercase();
1371 self.scalar_functions.contains_key(&lower)
1372 || self.aggregate_functions.contains_key(&lower)
1373 || self.table_functions.contains_key(&lower)
1374 }
1375
1376 pub fn scalar_count(&self) -> usize {
1378 self.scalar_functions.len()
1379 }
1380
1381 pub fn aggregate_count(&self) -> usize {
1383 self.aggregate_functions.len()
1384 }
1385
1386 pub fn table_count(&self) -> usize {
1388 self.table_functions.len()
1389 }
1390
1391 pub fn total_count(&self) -> usize {
1393 self.scalar_count() + self.aggregate_count() + self.table_count()
1394 }
1395
1396 pub fn execute_table_function(
1407 &self,
1408 name: &str,
1409 args: &[Value],
1410 graph: Option<&dyn crate::graph::GraphDataSource>,
1411 ) -> Result<Vec<Vec<Value>>, String> {
1412 use akar_common::vector::DataChunk;
1413
1414 let func = self
1415 .get_table(name)
1416 .ok_or_else(|| format!("Table function '{}' not found", name))?;
1417
1418 match func {
1419 TableFunction::ListTables => Err("ListTables requires catalog access — handled at connection level".into()),
1420 TableFunction::ShowColumns { .. } => {
1421 Err("ShowColumns requires catalog access — handled at connection level".into())
1422 }
1423 TableFunction::Custom { name: custom_name } => Err(format!(
1424 "Table function '{}' requires an extension or external context to be loaded. \
1425 Use LOAD EXTENSION or CALL with the appropriate handler.",
1426 custom_name
1427 )),
1428 TableFunction::CustomTable { name: _, execute } => {
1429 let mut chunk = DataChunk {
1430 fields: Vec::new(),
1431 field_types: Vec::new(),
1432 size: 0,
1433 field_names: vec![],
1434 sel_vector: None,
1435 };
1436 execute(args, &mut chunk).map(|_| {
1437 let mut rows = Vec::new();
1438 for row in 0..chunk.size {
1439 let mut row_vals = Vec::new();
1440 for field_idx in 0..chunk.fields.len() {
1441 row_vals.push(chunk.get_value(field_idx, row).unwrap_or(Value::Null));
1442 }
1443 rows.push(row_vals);
1444 }
1445 rows
1446 })
1447 }
1448 TableFunction::CustomTableWithGraph { name: _, execute } => {
1449 let mut chunk = DataChunk {
1450 fields: Vec::new(),
1451 field_types: Vec::new(),
1452 size: 0,
1453 field_names: vec![],
1454 sel_vector: None,
1455 };
1456 execute(args, graph, &mut chunk).map(|_| {
1457 let mut rows = Vec::new();
1458 for row in 0..chunk.size {
1459 let mut row_vals = Vec::new();
1460 for field_idx in 0..chunk.fields.len() {
1461 row_vals.push(chunk.get_value(field_idx, row).unwrap_or(Value::Null));
1462 }
1463 rows.push(row_vals);
1464 }
1465 rows
1466 })
1467 }
1468 TableFunction::ScanCsv { .. }
1469 | TableFunction::ScanParquet { .. }
1470 | TableFunction::ScanJson { .. }
1471 | TableFunction::CurrentSetting { .. } => Err(format!(
1472 "Table function '{}' cannot be executed via CALL — it requires file path or catalog context. \
1473 Use COPY FROM 'file' FORMAT CSV/PARQUET/JSON or CALL current_setting('key') via the connection layer.",
1474 name
1475 )),
1476 }
1477 }
1478}