1use {
2 super::{
3 select_body::{
4 Order,
5 SelectBody,
6 SelectJunction,
7 },
8 utils::SqliteQueryCtx,
9 },
10 crate::{
11 sqlite::{
12 query::select_body::build_select_junction,
13 schema::field::Field,
14 types::{
15 to_rust_types,
16 SimpleSimpleType,
17 SimpleType,
18 Type,
19 },
20 QueryResCount,
21 },
22 utils::{
23 sanitize_ident,
24 Errs,
25 Tokens,
26 },
27 },
28 quote::{
29 format_ident,
30 quote,
31 ToTokens,
32 },
33 samevariant::samevariant,
34 std::{
35 collections::HashMap,
36 fmt::Display,
37 rc::Rc,
38 },
39 syn::Path,
40};
41#[cfg(feature = "chrono")]
42use {
43 chrono::{
44 DateTime,
45 FixedOffset,
46 Utc,
47 },
48};
49#[cfg(feature = "jiff")]
50use {
51 jiff::{
52 Timestamp,
53 },
54};
55
56#[derive(Clone)]
59pub struct ComputeType(Rc<dyn Fn(&mut SqliteQueryCtx, &rpds::Vector<String>, Vec<ExprType>) -> Option<Type>>);
60
61impl ComputeType {
62 pub fn new(
63 f: impl Fn(&mut SqliteQueryCtx, &rpds::Vector<String>, Vec<ExprType>) -> Option<Type> + 'static,
64 ) -> ComputeType {
65 return ComputeType(Rc::new(f));
66 }
67}
68
69impl std::fmt::Debug for ComputeType {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 return f.write_str("ComputeType");
72 }
73}
74
75#[derive(Clone, Debug)]
76pub enum Expr {
77 LitArray(Vec<Expr>),
78 LitNull(SimpleType),
81 LitBool(bool),
82 LitI32(i32),
83 LitI64(i64),
84 LitU32(u32),
85 LitF32(f32),
86 LitF64(f64),
87 LitString(String),
88 LitBytes(Vec<u8>),
89 #[cfg(feature = "chrono")]
90 LitUtcTimeSChrono(DateTime<Utc>),
91 #[cfg(feature = "chrono")]
92 LitUtcTimeMsChrono(DateTime<Utc>),
93 #[cfg(feature = "chrono")]
94 LitFixedOffsetTimeMsChrono(DateTime<FixedOffset>),
95 #[cfg(feature = "jiff")]
96 LitUtcTimeSJiff(Timestamp),
97 #[cfg(feature = "jiff")]
98 LitUtcTimeMsJiff(Timestamp),
99 Param {
102 name: String,
103 type_: Type,
104 },
105 Binding(Binding),
110 BinOp {
111 left: Box<Expr>,
112 op: BinOp,
113 right: Box<Expr>,
114 },
115 BinOpChain {
118 op: BinOp,
119 exprs: Vec<Expr>,
120 },
121 PrefixOp {
122 op: PrefixOp,
123 right: Box<Expr>,
124 },
125 Call {
129 func: String,
130 args: Vec<Expr>,
131 compute_type: ComputeType,
133 },
134 Window {
137 expr: Box<Expr>,
138 partition_by: Vec<Expr>,
139 order_by: Vec<(Expr, Order)>,
140 },
141 Select {
143 body: Box<SelectBody>,
144 body_junctions: Vec<SelectJunction>,
145 },
146 Exists {
147 not: bool,
148 body: Box<SelectBody>,
149 body_junctions: Vec<SelectJunction>,
150 },
151 Cast(Box<Expr>, Type),
155}
156
157impl Expr {
158 pub fn field(f: &Field) -> Expr {
159 return Expr::Binding(Binding::field(f));
160 }
161}
162
163#[derive(Clone, Hash, PartialEq, Eq, Debug)]
164pub struct Binding {
165 pub table_id: String,
166 pub id: String,
167}
168
169impl Binding {
170 pub fn local(name: impl AsRef<str>) -> Self {
173 Binding {
174 table_id: "".into(),
175 id: name.as_ref().to_string(),
176 }
177 }
178
179 pub(crate) fn empty() -> Self {
180 Binding {
181 table_id: "".into(),
182 id: "".into(),
183 }
184 }
185
186 pub fn field(f: &Field) -> Self {
188 Binding {
189 table_id: f.table.id.clone(),
190 id: f.id.clone(),
191 }
192 }
193
194 pub fn with_alias(&self, s: &str) -> Binding {
196 Binding {
197 table_id: s.into(),
198 id: self.id.clone(),
199 }
200 }
201}
202
203impl Display for Binding {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 Display::fmt(&format!("{}.{}", self.table_id, self.id), f)
206 }
207}
208
209pub struct ExprType(pub Vec<(Binding, Type)>);
210
211impl ExprType {
212 pub fn assert_scalar(&self, errs: &mut Errs, path: &rpds::Vector<String>) -> Option<(Binding, Type)> {
213 if self.0.len() != 1 {
214 errs.err(path, format!("Select outputs must be scalars, but got result with {} fields", self.0.len()));
215 return None;
216 }
217 Some(self.0[0].clone())
218 }
219}
220
221pub fn check_general_same_type(ctx: &mut SqliteQueryCtx, path: &rpds::Vector<String>, left: &Type, right: &Type) {
222 if left.opt != right.opt {
223 ctx.errs.err(path, format!("Operator arms have differing optionality"));
224 }
225 if left.array != right.array {
226 ctx.errs.err(path, format!("Operator arms are either not both arrays or not both scalars"));
227 }
228
229 #[derive(Debug)]
230 #[samevariant(GeneralTypePairs)]
231 enum GeneralType {
232 Bool,
233 Numeric,
234 Blob,
235 }
236
237 fn general_type(t: &Type) -> GeneralType {
238 match t.type_.type_ {
239 SimpleSimpleType::U32 => GeneralType::Numeric,
240 SimpleSimpleType::I32 => GeneralType::Numeric,
241 SimpleSimpleType::I64 => GeneralType::Numeric,
242 SimpleSimpleType::F32 => GeneralType::Numeric,
243 SimpleSimpleType::F64 => GeneralType::Numeric,
244 SimpleSimpleType::Bool => GeneralType::Bool,
245 SimpleSimpleType::String => GeneralType::Blob,
246 SimpleSimpleType::Bytes => GeneralType::Blob,
247 #[cfg(feature = "chrono")]
248 SimpleSimpleType::UtcTimeSChrono => GeneralType::Numeric,
249 #[cfg(feature = "chrono")]
250 SimpleSimpleType::UtcTimeMsChrono => GeneralType::Blob,
251 #[cfg(feature = "chrono")]
252 SimpleSimpleType::FixedOffsetTimeMsChrono => GeneralType::Blob,
253 #[cfg(feature = "jiff")]
254 SimpleSimpleType::UtcTimeSJiff => GeneralType::Numeric,
255 #[cfg(feature = "jiff")]
256 SimpleSimpleType::UtcTimeMsJiff => GeneralType::Blob,
257 }
258 }
259
260 match GeneralTypePairs::pairs(&general_type(left), &general_type(right)) {
261 GeneralTypePairs::Nonmatching(left, right) => {
262 ctx.errs.err(path, format!("Operator arms have incompatible types: {:?} and {:?}", left, right));
263 },
264 _ => { },
265 }
266}
267
268pub(crate) fn check_general_same(
269 ctx: &mut SqliteQueryCtx,
270 path: &rpds::Vector<String>,
271 left: &ExprType,
272 right: &ExprType,
273) {
274 if left.0.len() != right.0.len() {
275 ctx
276 .errs
277 .err(
278 path,
279 format!(
280 "Operator arms record type lengths don't match: left has {} fields and right has {}",
281 left.0.len(),
282 right.0.len()
283 ),
284 );
285 } else if left.0.len() == 1 && right.0.len() == 1 {
286 check_general_same_type(ctx, path, &left.0[0].1, &left.0[0].1);
287 } else {
288 for (i, (left, right)) in left.0.iter().zip(right.0.iter()).enumerate() {
289 check_general_same_type(ctx, &path.push_back(format!("Record pair {}", i)), &left.1, &right.1);
290 }
291 }
292}
293
294pub(crate) fn check_same(
295 errs: &mut Errs,
296 path: &rpds::Vector<String>,
297 left: &ExprType,
298 right: &ExprType,
299) -> Option<Type> {
300 let left = match left.assert_scalar(errs, &path.push_back("Left".into())) {
301 Some(t) => t,
302 None => {
303 return None;
304 },
305 };
306 let right = match right.assert_scalar(errs, &path.push_back("Right".into())) {
307 Some(t) => t,
308 None => {
309 return None;
310 },
311 };
312 if left.1.opt != right.1.opt {
313 errs.err(
314 path,
315 format!(
316 "Expected same types, but left nullability is {} but right nullability is {}",
317 left.1.opt,
318 right.1.opt
319 ),
320 );
321 }
322 if left.1.type_.custom != right.1.type_.custom {
323 errs.err(
324 path,
325 format!(
326 "Expected same types, but left rust type is {:?} while right rust type is {:?}",
327 left.1.type_.custom,
328 right.1.type_.custom
329 ),
330 );
331 }
332 if left.1.type_.type_ != right.1.type_.type_ {
333 errs.err(
334 path,
335 format!(
336 "Expected same types, but left base type is {:?} while right base type is {:?}",
337 left.1.type_.type_,
338 right.1.type_.type_
339 ),
340 );
341 }
342 Some(left.1.clone())
343}
344
345pub(crate) fn check_bool(ctx: &mut SqliteQueryCtx, path: &rpds::Vector<String>, a: &ExprType) {
346 let t = match a.assert_scalar(&mut ctx.errs, path) {
347 Some(t) => t,
348 None => {
349 return;
350 },
351 };
352 if t.1.opt {
353 ctx.errs.err(path, format!("Expected bool type but is nullable: got {:?}", t));
354 }
355 if !matches!(t.1.type_.type_, SimpleSimpleType::Bool) {
356 ctx.errs.err(path, format!("Expected bool but type is non-bool: got {:?}", t.1.type_.type_));
357 }
358}
359
360#[cfg(feature = "chrono")]
361pub(crate) fn check_utc_if_time(ctx: &mut SqliteQueryCtx, path: &rpds::Vector<String>, t: &ExprType) {
362 for (i, el) in t.0.iter().enumerate() {
363 if matches!(el.1.type_.type_, SimpleSimpleType::FixedOffsetTimeMsChrono) {
364 ctx.errs.err(
365 &if t.0.len() == 1 {
366 path.clone()
367 } else {
368 path.push_back(format!("Record pair {}", i))
369 },
370 format!(
371 "Datetimes with non-utc offsets may not be used in normal binary operators - use the `Tz` operators instead"
372 ),
373 );
374 }
375 }
376}
377
378pub(crate) fn check_assignable(errs: &mut Errs, path: &rpds::Vector<String>, a: &Type, b: &ExprType) {
379 check_same(errs, path, &ExprType(vec![(Binding::empty(), a.clone())]), b);
380}
381
382impl Expr {
383 pub(crate) fn build(
384 &self,
385 ctx: &mut SqliteQueryCtx,
386 path: &rpds::Vector<String>,
387 scope: &HashMap<Binding, Type>,
388 ) -> (ExprType, Tokens) {
389 macro_rules! empty_type{
390 ($o: expr, $t: expr) => {
391 (ExprType(vec![(Binding::empty(), Type {
392 type_: SimpleType {
393 type_: $t,
394 custom: None,
395 },
396 opt: false,
397 array: false,
398 })]), $o)
399 };
400 }
401
402 fn do_bin_op(
403 ctx: &mut SqliteQueryCtx,
404 path: &rpds::Vector<String>,
405 scope: &HashMap<Binding, Type>,
406 op: &BinOp,
407 exprs: &Vec<Expr>,
408 ) -> (ExprType, Tokens) {
409 let operand_lower_limit;
410 match op {
411 BinOp::Plus | BinOp::Minus | BinOp::Multiply | BinOp::Divide | BinOp::And | BinOp::Or => {
412 operand_lower_limit = 1;
413 },
414 BinOp::Equals |
415 BinOp::NotEquals |
416 BinOp::Is |
417 BinOp::IsNot |
418 BinOp::TzEquals |
419 BinOp::TzNotEquals |
420 BinOp::TzIs |
421 BinOp::TzIsNot |
422 BinOp::LessThan |
423 BinOp::LessThanEqualTo |
424 BinOp::GreaterThan |
425 BinOp::GreaterThanEqualTo |
426 BinOp::Like |
427 BinOp::In |
428 BinOp::NotIn => {
429 operand_lower_limit = 2;
430 },
431 };
432 if exprs.len() < operand_lower_limit {
433 ctx
434 .errs
435 .err(
436 path,
437 format!(
438 "{:?} must have at least {} operand(s), but got {}",
439 op,
440 operand_lower_limit,
441 exprs.len()
442 ),
443 );
444 }
445 let mut res = vec![];
446 for (i, e) in exprs.iter().enumerate() {
447 res.push(e.build(ctx, &path.push_back(format!("Operand {}", i)), scope));
448 }
449 let t = match op {
450 BinOp::Plus | BinOp::Minus | BinOp::Multiply | BinOp::Divide => {
451 let base = res.get(0).unwrap();
452 let t =
453 match check_same(
454 &mut ctx.errs,
455 &path.push_back(format!("Operands 0, 1")),
456 &base.0,
457 &res.get(0).unwrap().0,
458 ) {
459 Some(t) => t,
460 None => {
461 return (ExprType(vec![]), Tokens::new());
462 },
463 };
464 for (i, res) in res.iter().enumerate().skip(2) {
465 match check_same(
466 &mut ctx.errs,
467 &path.push_back(format!("Operands 0, {}", i)),
468 &base.0,
469 &res.0,
470 ) {
471 Some(_) => { },
472 None => {
473 return (ExprType(vec![]), Tokens::new());
474 },
475 };
476 }
477 t
478 },
479 BinOp::And | BinOp::Or => {
480 for (i, res) in res.iter().enumerate() {
481 check_bool(ctx, &path.push_back(format!("Operand {}", i)), &res.0);
482 }
483 Type {
484 type_: SimpleType {
485 type_: SimpleSimpleType::Bool,
486 custom: None,
487 },
488 array: false,
489 opt: false,
490 }
491 },
492 BinOp::Equals |
493 BinOp::NotEquals |
494 BinOp::Is |
495 BinOp::IsNot |
496 BinOp::TzEquals |
497 BinOp::TzNotEquals |
498 BinOp::TzIs |
499 BinOp::TzIsNot |
500 BinOp::LessThan |
501 BinOp::LessThanEqualTo |
502 BinOp::GreaterThan |
503 BinOp::GreaterThanEqualTo |
504 BinOp::Like => {
505 #[cfg(feature = "chrono")]
506 if match op {
507 BinOp::TzEquals | BinOp::TzNotEquals | BinOp::TzIs | BinOp::TzIsNot => false,
508 _ => true,
509 } {
510 for (i, el) in res.iter().enumerate() {
511 check_utc_if_time(ctx, &path.push_back(format!("Operand {}", i)), &el.0);
512 }
513 }
514 let base = res.get(0).unwrap();
515 check_general_same(
516 ctx,
517 &path.push_back(format!("Operands 0, 1")),
518 &base.0,
519 &res.get(1).unwrap().0,
520 );
521 for (i, res) in res.iter().enumerate().skip(2) {
522 check_general_same(ctx, &path.push_back(format!("Operands 0, {}", i)), &base.0, &res.0);
523 }
524 Type {
525 type_: SimpleType {
526 type_: SimpleSimpleType::Bool,
527 custom: None,
528 },
529 opt: false,
530 array: false,
531 }
532 },
533 BinOp::In | BinOp::NotIn => {
534 #[cfg(feature = "chrono")]
535 if match op {
536 BinOp::TzEquals | BinOp::TzNotEquals | BinOp::TzIs | BinOp::TzIsNot => false,
537 _ => true,
538 } {
539 for (i, el) in res.iter().enumerate() {
540 check_utc_if_time(ctx, &path.push_back(format!("Operand {}", i)), &el.0);
541 }
542 }
543 let base = res.get(0).unwrap();
544 check_general_same(
545 ctx,
546 &path.push_back(format!("Operands 0, 1")),
547 &base.0,
548 &res.get(1).unwrap().0,
549 );
550 for (i, res) in res.iter().enumerate().skip(2) {
551 check_general_same(ctx, &path.push_back(format!("Operands 0, {}", i)), &base.0, &res.0);
552 }
553 Type {
554 type_: SimpleType {
555 type_: SimpleSimpleType::Bool,
556 custom: None,
557 },
558 opt: false,
559 array: false,
560 }
561 },
562 };
563 let token = match op {
564 BinOp::Plus => "+",
565 BinOp::Minus => "-",
566 BinOp::Multiply => "*",
567 BinOp::Divide => "/",
568 BinOp::And => "and",
569 BinOp::Or => "or",
570 BinOp::Equals => "=",
571 BinOp::NotEquals => "!=",
572 BinOp::Is => "is",
573 BinOp::IsNot => "is not",
574 BinOp::TzEquals => "=",
575 BinOp::TzNotEquals => "!=",
576 BinOp::TzIs => "is",
577 BinOp::TzIsNot => "is not",
578 BinOp::LessThan => "<",
579 BinOp::LessThanEqualTo => "<=",
580 BinOp::GreaterThan => ">",
581 BinOp::GreaterThanEqualTo => ">=",
582 BinOp::Like => "like",
583 BinOp::In => "in",
584 BinOp::NotIn => "not in",
585 };
586 let mut out = Tokens::new();
587 out.s("(");
588 for (i, res) in res.iter().enumerate() {
589 if i > 0 {
590 out.s(token);
591 }
592 out.s(&res.1.to_string());
593 }
594 out.s(")");
595 (ExprType(vec![(Binding::empty(), t)]), out)
596 }
597
598 match self {
599 Expr::LitArray(t) => {
600 let mut out = Tokens::new();
601 let mut child_types = vec![];
602 out.s("(");
603 for (i, child) in t.iter().enumerate() {
604 if i > 0 {
605 out.s(", ");
606 }
607 let (child_type, child_tokens) = child.build(ctx, path, scope);
608 out.s(&child_tokens.to_string());
609 child_types.extend(child_type.0);
610 }
611 out.s(")");
612 return (ExprType(child_types), out);
613 },
614 Expr::LitNull(t) => {
615 let mut out = Tokens::new();
616 out.s("null");
617 return (ExprType(vec![(Binding::empty(), Type {
618 type_: t.clone(),
619 opt: true,
620 array: false,
621 })]), out);
622 },
623 Expr::LitBool(x) => {
624 let mut out = Tokens::new();
625 out.s(if *x {
626 "true"
627 } else {
628 "false"
629 });
630 return empty_type!(out, SimpleSimpleType::Bool);
631 },
632 Expr::LitI32(x) => {
633 let mut out = Tokens::new();
634 out.s(&x.to_string());
635 return empty_type!(out, SimpleSimpleType::I32);
636 },
637 Expr::LitI64(x) => {
638 let mut out = Tokens::new();
639 out.s(&x.to_string());
640 return empty_type!(out, SimpleSimpleType::I64);
641 },
642 Expr::LitU32(x) => {
643 let mut out = Tokens::new();
644 out.s(&x.to_string());
645 return empty_type!(out, SimpleSimpleType::U32);
646 },
647 Expr::LitF32(x) => {
648 let mut out = Tokens::new();
649 out.s(&x.to_string());
650 return empty_type!(out, SimpleSimpleType::F32);
651 },
652 Expr::LitF64(x) => {
653 let mut out = Tokens::new();
654 out.s(&x.to_string());
655 return empty_type!(out, SimpleSimpleType::F64);
656 },
657 Expr::LitString(x) => {
658 let mut out = Tokens::new();
659 out.s(&format!("'{}'", x.replace("'", "''")));
660 return empty_type!(out, SimpleSimpleType::String);
661 },
662 Expr::LitBytes(x) => {
663 let mut out = Tokens::new();
664 let h = hex::encode(&x);
665 out.s(&format!("x'{}'", h));
666 return empty_type!(out, SimpleSimpleType::Bytes);
667 },
668 #[cfg(feature = "chrono")]
669 Expr::LitUtcTimeSChrono(d) => {
670 let mut out = Tokens::new();
671 let d = d.timestamp();
672 out.s(&format!("{}", d));
673 return empty_type!(out, SimpleSimpleType::UtcTimeSChrono);
674 },
675 #[cfg(feature = "chrono")]
676 Expr::LitUtcTimeMsChrono(d) => {
677 let mut out = Tokens::new();
678 let d = d.to_rfc3339();
679 out.s(&format!("'{}'", d));
680 return empty_type!(out, SimpleSimpleType::UtcTimeMsChrono);
681 },
682 #[cfg(feature = "chrono")]
683 Expr::LitFixedOffsetTimeMsChrono(d) => {
684 let mut out = Tokens::new();
685 let d = d.to_rfc3339();
686 out.s(&format!("'{}'", d));
687 return empty_type!(out, SimpleSimpleType::FixedOffsetTimeMsChrono);
688 },
689 #[cfg(feature = "jiff")]
690 Expr::LitUtcTimeSJiff(d) => {
691 let mut out = Tokens::new();
692 out.s(&format!("{}", d.as_second()));
693 return empty_type!(out, SimpleSimpleType::UtcTimeSJiff);
694 },
695 #[cfg(feature = "jiff")]
696 Expr::LitUtcTimeMsJiff(d) => {
697 let mut out = Tokens::new();
698 out.s(&format!("'{}'", d.to_string()));
699 return empty_type!(out, SimpleSimpleType::UtcTimeMsJiff);
700 },
701 Expr::Param { name: x, type_: t } => {
702 let path = path.push_back(format!("Param ({})", x));
703 let mut out = Tokens::new();
704 let mut errs = vec![];
705 let i = match ctx.rust_arg_lookup.entry(x.clone()) {
706 std::collections::hash_map::Entry::Occupied(e) => {
707 let (i, prev_t) = e.get();
708 if t != prev_t {
709 errs.push(
710 format!("Parameter {} specified with multiple types: {:?}, {:?}", x, t, prev_t),
711 );
712 }
713 *i
714 },
715 std::collections::hash_map::Entry::Vacant(e) => {
716 let i = ctx.query_args.len();
717 e.insert((i, t.clone()));
718 let rust_types = to_rust_types(&t.type_.type_);
719 let custom_trait_ident = rust_types.custom_trait;
720 let rust_type = rust_types.arg_type;
721 let ident = format_ident!("{}", sanitize_ident(x).1);
722 let (mut rust_type, mut rust_forward) = if let Some(custom) = &t.type_.custom {
723 let custom_ident = match syn::parse_str::<Path>(custom.as_str()) {
724 Ok(p) => p,
725 Err(e) => {
726 ctx.errs.err(&path, format!("Couldn't parse custom type {}: {:?}", custom, e));
727 return (ExprType(vec![]), Tokens::new());
728 },
729 }.to_token_stream();
730 let forward =
731 quote!(< #custom_ident as #custom_trait_ident < #custom_ident >>:: to_sql(& #ident));
732 (quote!(& #custom_ident), forward)
733 } else {
734 (rust_type, quote!(#ident))
735 };
736 rust_forward = match t.type_.type_ {
737 SimpleSimpleType::U32 => rust_forward,
738 SimpleSimpleType::I32 => rust_forward,
739 SimpleSimpleType::I64 => rust_forward,
740 SimpleSimpleType::F32 => rust_forward,
741 SimpleSimpleType::F64 => rust_forward,
742 SimpleSimpleType::Bool => rust_forward,
743 SimpleSimpleType::String => rust_forward,
744 SimpleSimpleType::Bytes => rust_forward,
745 #[cfg(feature = "chrono")]
746 SimpleSimpleType::UtcTimeSChrono => quote!(#rust_forward.timestamp()),
747 #[cfg(feature = "chrono")]
748 SimpleSimpleType::UtcTimeMsChrono => quote!(#rust_forward.to_rfc3339()),
749 #[cfg(feature = "chrono")]
750 SimpleSimpleType::FixedOffsetTimeMsChrono => quote!(#rust_forward.to_rfc3339()),
751 #[cfg(feature = "jiff")]
752 SimpleSimpleType::UtcTimeSJiff => quote!(#rust_forward.as_second()),
753 #[cfg(feature = "jiff")]
754 SimpleSimpleType::UtcTimeMsJiff => quote!(#rust_forward.to_string()),
755 };
756 if t.array {
757 rust_type = quote!(Vec < #rust_type >);
758 rust_forward =
759 quote!(
760 std:: rc:: Rc:: new(
761 #ident.into_iter(
762 ).map(
763 | #ident | rusqlite:: types:: Value:: from(#rust_forward)
764 ).collect::< Vec < _ >>()
765 )
766 );
767 }
768 if t.opt {
769 rust_type = quote!(Option < #rust_type >);
770 rust_forward = quote!(#ident.map(| #ident | #rust_forward));
771 }
772 ctx.rust_args.push(quote!(#ident: #rust_type));
773 ctx.query_args.push(quote!(#rust_forward));
774 i
775 },
776 };
777 for e in errs {
778 ctx.errs.err(&path, e);
779 }
780 if t.array {
781 out.s(&format!("rarray(${})", i + 1));
782 } else {
783 out.s(&format!("${}", i + 1));
784 }
785 return (ExprType(vec![(Binding::local(x.clone()), t.clone())]), out);
786 },
787 Expr::Binding(name) => {
788 let t = match scope.get(&name) {
789 Some(t) => t.clone(),
790 None => {
791 ctx
792 .errs
793 .err(
794 path,
795 format!(
796 "Expression references {} but this field isn't available here (available fields: {:?})",
797 name,
798 scope.iter().map(|e| e.0.to_string()).collect::<Vec<String>>()
799 ),
800 );
801 return (ExprType(vec![]), Tokens::new());
802 },
803 };
804 let mut out = Tokens::new();
805 if name.table_id != "" {
806 out.id(&name.table_id).s(".");
807 }
808 out.id(&name.id);
809 return (ExprType(vec![(name.clone(), t.clone())]), out);
810 },
811 Expr::BinOp { left, op, right } => {
812 return do_bin_op(
813 ctx,
814 &path.push_back(format!("Bin op {:?}", op)),
815 scope,
816 op,
817 &vec![left.as_ref().clone(), right.as_ref().clone()],
818 );
819 },
820 Expr::BinOpChain { op, exprs } => {
821 return do_bin_op(ctx, &path.push_back(format!("Chain bin op {:?}", op)), scope, op, exprs);
822 },
823 Expr::PrefixOp { op, right } => {
824 let path = path.push_back(format!("Prefix op {:?}", op));
825 let mut out = Tokens::new();
826 let res = right.build(ctx, &path, scope);
827 let (op_text, op_type) = match op {
828 PrefixOp::Not => {
829 check_bool(ctx, &path, &res.0);
830 ("not", SimpleSimpleType::Bool)
831 },
832 };
833 out.s(op_text).s(&res.1.to_string());
834 return empty_type!(out, op_type);
835 },
836 Expr::Call { func, args, compute_type } => {
837 let mut types = vec![];
838 let mut out = Tokens::new();
839 out.s(func);
840 out.s("(");
841 for (i, arg) in args.iter().enumerate() {
842 if i > 0 {
843 out.s(",");
844 }
845 let (arg_type, tokens) =
846 arg.build(ctx, &path.push_back(format!("Call [{}] arg {}", func, i)), scope);
847 types.push(arg_type);
848 out.s(&tokens.to_string());
849 }
850 out.s(")");
851 let type_ = match (compute_type.0)(ctx, &path, types) {
852 Some(t) => t,
853 None => {
854 return (ExprType(vec![]), Tokens::new());
855 },
856 };
857 return (ExprType(vec![(Binding::empty(), type_)]), out);
858 },
859 Expr::Window { expr, partition_by, order_by } => {
860 let mut out = Tokens::new();
861 let expr = expr.build(ctx, &path, &scope);
862 out.s(&expr.1.to_string());
863 out.s("over");
864 out.s("(");
865 if !partition_by.is_empty() {
866 out.s("partition by");
867 for (i, e) in partition_by.iter().enumerate() {
868 let path = path.push_back(format!("Partition by {}", i));
869 if i > 0 {
870 out.s(",");
871 }
872 let (_, p) = e.build(ctx, &path, &scope);
873 out.s(&p.to_string());
874 }
875 }
876 if !order_by.is_empty() {
877 out.s("order by");
878 for (i, o) in order_by.iter().enumerate() {
879 let path = path.push_back(format!("Order by clause {}", i));
880 if i > 0 {
881 out.s(",");
882 }
883 let (_, o_tokens) = o.0.build(ctx, &path, &scope);
884 out.s(&o_tokens.to_string());
885 out.s(match o.1 {
886 Order::Asc => "asc",
887 Order::Desc => "desc",
888 });
889 }
890 }
891 out.s(")");
892 return (expr.0, out);
893 },
894 Expr::Select { body, body_junctions } => {
895 let path = path.push_back(format!("Subselect"));
896 let mut out = Tokens::new();
897 let base = body.build(ctx, scope, &path, QueryResCount::Many);
898 out.s(&base.1.to_string());
899 out.s(&build_select_junction(ctx, &path, &base.0, &body_junctions).to_string());
900 return (base.0, out);
901 },
902 Expr::Exists { not, body, body_junctions } => {
903 let path = path.push_back(format!("(Not)Exists"));
904 let mut out = Tokens::new();
905 if *not {
906 out.s("not");
907 }
908 out.s("exists");
909 out.s("(");
910 let base = body.build(ctx, scope, &path, QueryResCount::Many);
911 out.s(&base.1.to_string());
912 out.s(&build_select_junction(ctx, &path, &base.0, &body_junctions).to_string());
913 out.s(")");
914 return (ExprType(vec![(Binding::empty(), Type {
915 type_: SimpleType {
916 type_: SimpleSimpleType::Bool,
917 custom: None,
918 },
919 opt: false,
920 array: false,
921 })]), out);
922 },
923 Expr::Cast(e, t) => {
924 let path = path.push_back(format!("Cast"));
925 let out = e.build(ctx, &path, scope);
926 let got_t = match out.0.assert_scalar(&mut ctx.errs, &path) {
927 Some(t) => t,
928 None => {
929 return (ExprType(vec![]), Tokens::new());
930 },
931 };
932 check_general_same_type(ctx, &path, t, &got_t.1);
933 return (ExprType(vec![(got_t.0, t.clone())]), out.1);
934 },
935 };
936 }
937}
938
939#[derive(Clone, Debug)]
946pub enum BinOp {
947 Plus,
948 Minus,
949 Multiply,
950 Divide,
951 And,
952 Or,
953 Equals,
954 NotEquals,
955 Is,
956 IsNot,
957 TzEquals,
958 TzNotEquals,
959 TzIs,
960 TzIsNot,
961 LessThan,
962 LessThanEqualTo,
963 GreaterThan,
964 GreaterThanEqualTo,
965 Like,
966 In,
967 NotIn,
968}
969
970#[derive(Clone, Debug)]
971pub enum PrefixOp {
972 Not,
973}