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 pub fn if_not_exists(&mut self) -> &mut Self {
296 self.if_not_exists.replace(true);
297 self
298 }
299
300 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 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 pub fn if_not_exists(&mut self) -> &mut Self {
488 self.if_not_exists.replace(true);
489 self
490 }
491
492 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 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}