scylladb_parse/statements/
function.rs

1use super::*;
2
3pub type FunctionName = KeyspaceQualifiedName;
4
5#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
6pub struct FunctionDeclaration {
7    #[builder(setter(into))]
8    pub name: FunctionName,
9    #[builder(setter(into))]
10    pub args: Vec<ArgumentDeclaration>,
11}
12
13impl FunctionDeclaration {
14    pub fn new<N: Into<FunctionName>, T: Into<ArgumentDeclaration>>(name: N, args: Vec<T>) -> Self {
15        Self {
16            name: name.into(),
17            args: args.into_iter().map(T::into).collect(),
18        }
19    }
20}
21
22impl Parse for FunctionDeclaration {
23    type Output = Self;
24    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
25        let name = s.parse()?;
26        let args = s.parse_from::<Parens<List<ArgumentDeclaration, Comma>>>()?;
27        Ok(Self { name, args })
28    }
29}
30
31impl Display for FunctionDeclaration {
32    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
33        write!(
34            f,
35            "{} ({})",
36            self.name,
37            self.args.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", ")
38        )
39    }
40}
41
42#[derive(ParseFromStr, Clone, Debug, ToTokens, PartialEq, Eq)]
43pub struct FunctionReference {
44    pub name: FunctionName,
45    pub args: Option<Vec<CqlType>>,
46}
47
48impl FunctionReference {
49    pub fn args<T: Into<CqlType>>(self, args: Vec<T>) -> Self {
50        Self {
51            name: self.name,
52            args: Some(args.into_iter().map(T::into).collect()),
53        }
54    }
55}
56
57impl Parse for FunctionReference {
58    type Output = Self;
59    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
60        let name = s.parse()?;
61        let args = s.parse_from::<Option<Parens<List<CqlType, Comma>>>>()?;
62        Ok(Self { name, args })
63    }
64}
65
66impl Display for FunctionReference {
67    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68        write!(
69            f,
70            "{}{}",
71            self.name,
72            if let Some(a) = self.args.as_ref() {
73                format!("({})", a.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", "))
74            } else {
75                String::new()
76            }
77        )
78    }
79}
80
81impl From<FunctionName> for FunctionReference {
82    fn from(name: FunctionName) -> Self {
83        Self { name, args: None }
84    }
85}
86
87impl From<String> for FunctionReference {
88    fn from(name: String) -> Self {
89        Self {
90            name: name.into(),
91            args: None,
92        }
93    }
94}
95
96impl From<&str> for FunctionReference {
97    fn from(name: &str) -> Self {
98        Self {
99            name: name.into(),
100            args: None,
101        }
102    }
103}
104
105#[derive(ParseFromStr, Clone, Debug, ToTokens, PartialEq, Eq)]
106pub struct FunctionSignature {
107    pub name: FunctionName,
108    pub args: Vec<CqlType>,
109}
110
111impl FunctionSignature {
112    pub fn new<F: Into<FunctionName>, T: Into<CqlType>>(name: F, args: Vec<T>) -> Self {
113        Self {
114            name: name.into(),
115            args: args.into_iter().map(T::into).collect(),
116        }
117    }
118}
119
120impl Parse for FunctionSignature {
121    type Output = Self;
122    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
123        Ok(Self {
124            name: s.parse()?,
125            args: s.parse_from::<Parens<List<CqlType, Comma>>>()?,
126        })
127    }
128}
129
130impl Display for FunctionSignature {
131    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
132        write!(
133            f,
134            "{}({})",
135            self.name,
136            self.args.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", ")
137        )
138    }
139}
140
141#[derive(ParseFromStr, Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd, ToTokens)]
142pub struct FunctionCall {
143    pub name: FunctionName,
144    pub args: Vec<Term>,
145}
146
147impl FunctionCall {
148    pub fn new<F: Into<FunctionName>, T: Into<Term>>(name: F, args: Vec<T>) -> Self {
149        Self {
150            name: name.into(),
151            args: args.into_iter().map(|a| a.into()).collect(),
152        }
153    }
154}
155
156impl Parse for FunctionCall {
157    type Output = Self;
158    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
159        let (name, args) = s.parse_from::<(FunctionName, Parens<List<Term, Comma>>)>()?;
160        Ok(Self { name, args })
161    }
162}
163
164impl Display for FunctionCall {
165    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
166        write!(
167            f,
168            "{}({})",
169            self.name,
170            self.args.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(", ")
171        )
172    }
173}
174
175#[derive(ParseFromStr, Clone, Debug, TryInto, From, ToTokens, PartialEq, Eq)]
176#[parse_via(TaggedUserDefinedFunctionStatement)]
177pub enum UserDefinedFunctionStatement {
178    Create(CreateFunctionStatement),
179    Drop(DropFunctionStatement),
180    CreateAggregate(CreateAggregateFunctionStatement),
181    DropAggregate(DropAggregateFunctionStatement),
182}
183
184impl TryFrom<TaggedUserDefinedFunctionStatement> for UserDefinedFunctionStatement {
185    type Error = anyhow::Error;
186    fn try_from(t: TaggedUserDefinedFunctionStatement) -> anyhow::Result<Self> {
187        Ok(match t {
188            TaggedUserDefinedFunctionStatement::Create(s) => Self::Create(s.try_into()?),
189            TaggedUserDefinedFunctionStatement::Drop(s) => Self::Drop(s.try_into()?),
190            TaggedUserDefinedFunctionStatement::CreateAggregate(s) => Self::CreateAggregate(s.try_into()?),
191            TaggedUserDefinedFunctionStatement::DropAggregate(s) => Self::DropAggregate(s.try_into()?),
192        })
193    }
194}
195
196#[derive(ParseFromStr, Clone, Debug, TryInto, From, ToTokens, PartialEq, Eq)]
197#[tokenize_as(UserDefinedFunctionStatement)]
198pub enum TaggedUserDefinedFunctionStatement {
199    Create(TaggedCreateFunctionStatement),
200    Drop(TaggedDropFunctionStatement),
201    CreateAggregate(TaggedCreateAggregateFunctionStatement),
202    DropAggregate(TaggedDropAggregateFunctionStatement),
203}
204
205impl Parse for TaggedUserDefinedFunctionStatement {
206    type Output = Self;
207    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
208        let mut lookahead = s.clone();
209        let keyword1 = lookahead.parse::<ReservedKeyword>()?;
210        Ok(match keyword1 {
211            ReservedKeyword::CREATE | ReservedKeyword::DROP => {
212                let keyword2 = lookahead.parse_from::<Alpha>()?;
213                match (keyword1, keyword2.to_uppercase().as_str()) {
214                    (ReservedKeyword::CREATE, "OR") => {
215                        if lookahead.check::<(REPLACE, FUNCTION)>() {
216                            Self::Create(s.parse()?)
217                        } else if lookahead.check::<(REPLACE, AGGREGATE)>() {
218                            Self::CreateAggregate(s.parse()?)
219                        } else {
220                            anyhow::bail!("Unexpected token following OR: {}", keyword2);
221                        }
222                    }
223                    (ReservedKeyword::CREATE, "FUNCTION") => Self::Create(s.parse()?),
224                    (ReservedKeyword::CREATE, "AGGREGATE") => Self::CreateAggregate(s.parse()?),
225                    (ReservedKeyword::DROP, "FUNCTION") => Self::Drop(s.parse()?),
226                    (ReservedKeyword::DROP, "AGGREGATE") => Self::DropAggregate(s.parse()?),
227                    _ => anyhow::bail!("Unexpected token following {}: {}", keyword1, keyword2),
228                }
229            }
230            _ => anyhow::bail!("Expected a user defined function statement, found {}", s.info()),
231        })
232    }
233}
234
235impl Display for UserDefinedFunctionStatement {
236    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
237        match self {
238            Self::Create(stmt) => stmt.fmt(f),
239            Self::Drop(stmt) => stmt.fmt(f),
240            Self::CreateAggregate(stmt) => stmt.fmt(f),
241            Self::DropAggregate(stmt) => stmt.fmt(f),
242        }
243    }
244}
245
246#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
247#[parse_via(TaggedCreateFunctionStatement)]
248pub struct CreateFunctionStatement {
249    #[builder(setter(name = "set_or_replace"), default)]
250    pub or_replace: bool,
251    #[builder(setter(name = "set_if_not_exists"), default)]
252    pub if_not_exists: bool,
253    pub func: FunctionDeclaration,
254    pub on_null_input: OnNullInput,
255    #[builder(setter(into))]
256    pub return_type: CqlType,
257    #[builder(setter(into))]
258    pub language: Name,
259    #[builder(setter(into))]
260    pub body: LitStr,
261}
262
263impl TryFrom<TaggedCreateFunctionStatement> for CreateFunctionStatement {
264    type Error = anyhow::Error;
265    fn try_from(value: TaggedCreateFunctionStatement) -> Result<Self, Self::Error> {
266        Ok(Self {
267            or_replace: value.or_replace,
268            if_not_exists: value.if_not_exists,
269            func: value.func.into_value()?,
270            on_null_input: value.on_null_input.into_value()?,
271            return_type: value.return_type.into_value()?,
272            language: value.language.into_value()?,
273            body: value.body.into_value()?,
274        })
275    }
276}
277
278#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
279#[tokenize_as(CreateFunctionStatement)]
280pub struct TaggedCreateFunctionStatement {
281    #[builder(setter(name = "set_or_replace"), default)]
282    pub or_replace: bool,
283    #[builder(setter(name = "set_if_not_exists"), default)]
284    pub if_not_exists: bool,
285    pub func: Tag<FunctionDeclaration>,
286    pub on_null_input: Tag<OnNullInput>,
287    pub return_type: Tag<CqlType>,
288    pub language: Tag<Name>,
289    pub body: Tag<LitStr>,
290}
291
292impl CreateFunctionStatementBuilder {
293    /// Set IF NOT EXISTS on the statement.
294    /// To undo this, use `set_if_not_exists(false)`.
295    pub fn if_not_exists(&mut self) -> &mut Self {
296        self.if_not_exists.replace(true);
297        self
298    }
299
300    /// Set OR REPLACE on the statement.
301    /// To undo this, use `set_or_replace(false)`.
302    pub fn or_replace(&mut self) -> &mut Self {
303        self.or_replace.replace(true);
304        self
305    }
306}
307
308impl Parse for TaggedCreateFunctionStatement {
309    type Output = Self;
310    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
311        s.parse::<CREATE>()?;
312        let mut res = TaggedCreateFunctionStatementBuilder::default();
313        res.set_or_replace(s.parse::<Option<(OR, REPLACE)>>()?.is_some());
314        s.parse::<FUNCTION>()?;
315        res.set_if_not_exists(s.parse::<Option<(IF, NOT, EXISTS)>>()?.is_some())
316            .func(s.parse()?)
317            .on_null_input(s.parse()?)
318            .return_type(s.parse::<(RETURNS, _)>()?.1)
319            .language(s.parse::<(LANGUAGE, _)>()?.1);
320        res.body(s.parse::<(AS, _)>()?.1);
321        s.parse::<Option<Semicolon>>()?;
322        Ok(res
323            .build()
324            .map_err(|e| anyhow::anyhow!("Invalid CREATE FUNCTION statement: {}", e))?)
325    }
326}
327
328impl Display for CreateFunctionStatement {
329    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
330        write!(
331            f,
332            "CREATE{} FUNCTION{} {} {} RETURNS {} LANGUAGE {} AS {}",
333            if self.or_replace { " OR REPLACE" } else { "" },
334            if self.if_not_exists { " IF NOT EXISTS" } else { "" },
335            self.func,
336            self.on_null_input,
337            self.return_type,
338            self.language,
339            self.body
340        )
341    }
342}
343
344#[derive(ParseFromStr, Clone, Debug, ToTokens, PartialEq, Eq)]
345pub enum OnNullInput {
346    Called,
347    ReturnsNull,
348}
349
350impl Parse for OnNullInput {
351    type Output = Self;
352    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
353        Ok(if s.parse::<(CALLED, ON, NULL, INPUT)>().is_ok() {
354            Self::Called
355        } else if s.parse::<(RETURNS, NULL, ON, NULL, INPUT)>().is_ok() {
356            Self::ReturnsNull
357        } else {
358            anyhow::bail!("Expected ON NULL INPUT declaration, found {}", s.info())
359        })
360    }
361}
362
363impl Display for OnNullInput {
364    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
365        match self {
366            Self::Called => write!(f, "CALLED ON NULL INPUT"),
367            Self::ReturnsNull => write!(f, "RETURNS NULL ON NULL INPUT"),
368        }
369    }
370}
371
372pub type ArgumentDeclaration = FieldDefinition;
373
374#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
375#[parse_via(TaggedDropFunctionStatement)]
376pub struct DropFunctionStatement {
377    #[builder(setter(name = "set_if_exists"), default)]
378    pub if_exists: bool,
379    #[builder(setter(into))]
380    pub func: FunctionReference,
381}
382
383impl TryFrom<TaggedDropFunctionStatement> for DropFunctionStatement {
384    type Error = anyhow::Error;
385    fn try_from(value: TaggedDropFunctionStatement) -> Result<Self, Self::Error> {
386        Ok(Self {
387            if_exists: value.if_exists,
388            func: value.func.into_value()?,
389        })
390    }
391}
392
393#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
394#[tokenize_as(DropFunctionStatement)]
395pub struct TaggedDropFunctionStatement {
396    #[builder(setter(name = "set_if_exists"), default)]
397    pub if_exists: bool,
398    pub func: Tag<FunctionReference>,
399}
400
401impl DropFunctionStatementBuilder {
402    /// Set IF EXISTS on the statement.
403    /// To undo this, use `set_if_exists(false)`.
404    pub fn if_exists(&mut self) -> &mut Self {
405        self.if_exists.replace(true);
406        self
407    }
408}
409
410impl Parse for TaggedDropFunctionStatement {
411    type Output = Self;
412    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
413        s.parse::<(DROP, FUNCTION)>()?;
414        let mut res = TaggedDropFunctionStatementBuilder::default();
415        res.set_if_exists(s.parse::<Option<(IF, EXISTS)>>()?.is_some())
416            .func(s.parse()?);
417        s.parse::<Option<Semicolon>>()?;
418        Ok(res
419            .build()
420            .map_err(|e| anyhow::anyhow!("Invalid DROP FUNCTION statement: {}", e))?)
421    }
422}
423
424impl Display for DropFunctionStatement {
425    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
426        write!(
427            f,
428            "DROP FUNCTION{} {}",
429            if self.if_exists { " IF EXISTS" } else { "" },
430            self.func
431        )
432    }
433}
434#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
435#[builder(setter(strip_option))]
436#[parse_via(TaggedCreateAggregateFunctionStatement)]
437pub struct CreateAggregateFunctionStatement {
438    #[builder(setter(name = "set_or_replace"), default)]
439    pub or_replace: bool,
440    #[builder(setter(name = "set_if_not_exists"), default)]
441    pub if_not_exists: bool,
442    pub func: FunctionSignature,
443    pub state_modifying_fn: FunctionName,
444    #[builder(setter(into))]
445    pub state_value_type: CqlType,
446    #[builder(default)]
447    pub final_fn: Option<FunctionName>,
448    #[builder(setter(into), default)]
449    pub init_condition: Option<Term>,
450}
451
452impl TryFrom<TaggedCreateAggregateFunctionStatement> for CreateAggregateFunctionStatement {
453    type Error = anyhow::Error;
454    fn try_from(value: TaggedCreateAggregateFunctionStatement) -> Result<Self, Self::Error> {
455        Ok(Self {
456            or_replace: value.or_replace,
457            if_not_exists: value.if_not_exists,
458            func: value.func.into_value()?,
459            state_modifying_fn: value.state_modifying_fn.into_value()?,
460            state_value_type: value.state_value_type.into_value()?,
461            final_fn: value.final_fn.map(|v| v.into_value()).transpose()?,
462            init_condition: value.init_condition.map(|v| v.into_value()).transpose()?,
463        })
464    }
465}
466
467#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
468#[builder(setter(strip_option))]
469#[tokenize_as(CreateAggregateFunctionStatement)]
470pub struct TaggedCreateAggregateFunctionStatement {
471    #[builder(setter(name = "set_or_replace"), default)]
472    pub or_replace: bool,
473    #[builder(setter(name = "set_if_not_exists"), default)]
474    pub if_not_exists: bool,
475    pub func: Tag<FunctionSignature>,
476    pub state_modifying_fn: Tag<FunctionName>,
477    pub state_value_type: Tag<CqlType>,
478    #[builder(default)]
479    pub final_fn: Option<Tag<FunctionName>>,
480    #[builder(default)]
481    pub init_condition: Option<Tag<Term>>,
482}
483
484impl CreateAggregateFunctionStatementBuilder {
485    /// Set IF NOT EXISTS on the statement.
486    /// To undo this, use `set_if_not_exists(false)`.
487    pub fn if_not_exists(&mut self) -> &mut Self {
488        self.if_not_exists.replace(true);
489        self
490    }
491
492    /// Set OR REPLACE on the statement.
493    /// To undo this, use `set_or_replace(false)`.
494    pub fn or_replace(&mut self) -> &mut Self {
495        self.or_replace.replace(true);
496        self
497    }
498}
499
500impl Parse for TaggedCreateAggregateFunctionStatement {
501    type Output = Self;
502    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
503        s.parse::<CREATE>()?;
504        let mut res = TaggedCreateAggregateFunctionStatementBuilder::default();
505        res.set_or_replace(s.parse::<Option<(OR, REPLACE)>>()?.is_some());
506        s.parse::<AGGREGATE>()?;
507        res.set_if_not_exists(s.parse::<Option<(IF, NOT, EXISTS)>>()?.is_some())
508            .func(s.parse()?)
509            .state_modifying_fn(s.parse::<(SFUNC, _)>()?.1)
510            .state_value_type(s.parse::<(STYPE, _)>()?.1);
511        loop {
512            if s.remaining() == 0 || s.parse::<Option<Semicolon>>()?.is_some() {
513                break;
514            }
515            if let Some(f) = s.parse_from::<If<FINALFUNC, Tag<FunctionName>>>()? {
516                if res.final_fn.is_some() {
517                    anyhow::bail!("Duplicate FINALFUNC declaration");
518                }
519                res.final_fn(f);
520            } else if let Some(i) = s.parse_from::<If<INITCOND, Tag<Term>>>()? {
521                if res.init_condition.is_some() {
522                    anyhow::bail!("Duplicate INITCOND declaration");
523                }
524                res.init_condition(i);
525            } else {
526                return Ok(res.build().map_err(|_| {
527                    anyhow::anyhow!("Invalid tokens in CREATE AGGREGATE FUNCTION statement: {}", s.info())
528                })?);
529            }
530        }
531        s.parse::<Option<Semicolon>>()?;
532        Ok(res
533            .build()
534            .map_err(|e| anyhow::anyhow!("Invalid CREATE AGGREGATE FUNCTION statement: {}", e))?)
535    }
536}
537
538impl Display for CreateAggregateFunctionStatement {
539    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
540        write!(
541            f,
542            "CREATE{} AGGREGATE{} {} SFUNC {} STYPE {}",
543            if self.or_replace { " OR REPLACE" } else { "" },
544            if self.if_not_exists { " IF NOT EXISTS" } else { "" },
545            self.func,
546            self.state_modifying_fn,
547            self.state_value_type
548        )?;
549        if let Some(n) = &self.final_fn {
550            write!(f, " FINALFUNC {}", n)?;
551        }
552        if let Some(i) = &self.init_condition {
553            write!(f, " INITCOND {}", i)?;
554        }
555        Ok(())
556    }
557}
558
559#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
560#[parse_via(TaggedDropAggregateFunctionStatement)]
561pub struct DropAggregateFunctionStatement {
562    #[builder(setter(name = "set_if_exists"), default)]
563    pub if_exists: bool,
564    #[builder(setter(into))]
565    pub func: FunctionReference,
566}
567
568impl TryFrom<TaggedDropAggregateFunctionStatement> for DropAggregateFunctionStatement {
569    type Error = anyhow::Error;
570    fn try_from(value: TaggedDropAggregateFunctionStatement) -> Result<Self, Self::Error> {
571        Ok(Self {
572            if_exists: value.if_exists,
573            func: value.func.into_value()?,
574        })
575    }
576}
577
578#[derive(ParseFromStr, Builder, Clone, Debug, ToTokens, PartialEq, Eq)]
579#[tokenize_as(DropAggregateFunctionStatement)]
580pub struct TaggedDropAggregateFunctionStatement {
581    #[builder(setter(name = "set_if_exists"), default)]
582    pub if_exists: bool,
583    pub func: Tag<FunctionReference>,
584}
585
586impl DropAggregateFunctionStatementBuilder {
587    /// Set IF EXISTS on the statement.
588    /// To undo this, use `set_if_exists(false)`.
589    pub fn if_exists(&mut self) -> &mut Self {
590        self.if_exists.replace(true);
591        self
592    }
593}
594
595impl Parse for TaggedDropAggregateFunctionStatement {
596    type Output = Self;
597    fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self::Output> {
598        s.parse::<(DROP, AGGREGATE)>()?;
599        let mut res = TaggedDropAggregateFunctionStatementBuilder::default();
600        res.set_if_exists(s.parse::<Option<(IF, EXISTS)>>()?.is_some())
601            .func(s.parse()?);
602        s.parse::<Option<Semicolon>>()?;
603        Ok(res
604            .build()
605            .map_err(|e| anyhow::anyhow!("Invalid DROP AGGREGATE statement: {}", e))?)
606    }
607}
608
609impl Display for DropAggregateFunctionStatement {
610    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
611        write!(
612            f,
613            "DROP AGGREGATE{} {}",
614            if self.if_exists { " IF EXISTS" } else { "" },
615            self.func
616        )
617    }
618}
619
620#[cfg(test)]
621mod test {
622    use super::*;
623    use crate::{
624        ArithmeticOp,
625        CollectionType,
626        Constant,
627        KeyspaceQualifyExt,
628        NativeType,
629    };
630
631    #[test]
632    fn test_parse_create_function() {
633        let mut builder = CreateFunctionStatementBuilder::default();
634        builder.on_null_input(OnNullInput::Called);
635        assert!(builder.build().is_err());
636        builder.func(FunctionDeclaration::new(
637            "test".dot("func"),
638            vec![("a", NativeType::Int), ("b whitespace", NativeType::Float)],
639        ));
640        assert!(builder.build().is_err());
641        builder.return_type(NativeType::Int);
642        assert!(builder.build().is_err());
643        builder.language("java");
644        assert!(builder.build().is_err());
645        builder.body("java.lang.Math.add(a, b)");
646        let statement = builder.build().unwrap().to_string();
647        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
648        builder.or_replace();
649        let statement = builder.build().unwrap().to_string();
650        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
651        builder.if_not_exists();
652        let statement = builder.build().unwrap().to_string();
653        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
654    }
655
656    #[test]
657    fn test_parse_drop_function() {
658        let mut builder = DropFunctionStatementBuilder::default();
659        builder.func("test".dot("func"));
660        let statement = builder.build().unwrap().to_string();
661        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
662        builder.func(FunctionReference::from("test".dot("func")).args::<CqlType>(vec![
663            NativeType::Int.into(),
664            CollectionType::list(NativeType::Float).into(),
665            "my_keyspace".dot("my_func").into(),
666        ]));
667        builder.if_exists();
668        let statement = builder.build().unwrap().to_string();
669        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
670    }
671
672    #[test]
673    fn test_parse_create_aggregate_function() {
674        let mut builder = CreateAggregateFunctionStatementBuilder::default();
675        builder.func(FunctionSignature::new(
676            "test".dot("func"),
677            vec![NativeType::Int, NativeType::Float],
678        ));
679        assert!(builder.build().is_err());
680        builder.state_modifying_fn("test".dot("func_state_modifying_fn"));
681        assert!(builder.build().is_err());
682        builder.state_value_type(NativeType::Int);
683        let statement = builder.build().unwrap().to_string();
684        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
685        builder.init_condition(0_i32);
686        let statement = builder.build().unwrap().to_string();
687        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
688        builder.if_not_exists();
689        let statement = builder.build().unwrap().to_string();
690        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
691        builder.or_replace();
692        let statement = builder.build().unwrap().to_string();
693        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
694        builder.state_value_type(CollectionType::list(NativeType::Uuid));
695        let statement = builder.build().unwrap().to_string();
696        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
697        builder.final_fn("test".dot("final_fn"));
698        let statement = builder.build().unwrap().to_string();
699        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
700        builder.init_condition(Term::negative(Constant::string("test")));
701        let statement = builder.build().unwrap().to_string();
702        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
703        builder.init_condition(Term::arithmetic_op(
704            10_f32,
705            ArithmeticOp::Mul,
706            Constant::float("2.06E3").unwrap(),
707        ));
708        let statement = builder.build().unwrap().to_string();
709        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
710        builder.init_condition(Term::type_hint(NativeType::Bigint, "test"));
711        let statement = builder.build().unwrap().to_string();
712        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
713        builder.init_condition(Term::bind_marker("marker whitespace"));
714        let statement = builder.build().unwrap().to_string();
715        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
716    }
717
718    #[test]
719    fn test_parse_drop_aggregate_function() {
720        let mut builder = DropAggregateFunctionStatementBuilder::default();
721        builder.func("func");
722        let statement = builder.build().unwrap().to_string();
723        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
724        builder.if_exists();
725        let statement = builder.build().unwrap().to_string();
726        assert_eq!(builder.build().unwrap(), statement.parse().unwrap());
727    }
728}