1use super::{LogicCondition, OrderTerm, ParsedParams, PreferOptions, RpcParams, SelectItem};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35pub enum Operation {
36 Select(ParsedParams, Option<PreferOptions>),
38 Insert(InsertParams, Option<PreferOptions>),
40 Update(UpdateParams, Option<PreferOptions>),
42 Delete(DeleteParams, Option<PreferOptions>),
44 Rpc(RpcParams, Option<PreferOptions>),
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
64pub struct ResolvedTable {
65 pub schema: String,
67 pub name: String,
69}
70
71impl ResolvedTable {
72 pub fn new(schema: impl Into<String>, name: impl Into<String>) -> Self {
74 Self {
75 schema: schema.into(),
76 name: name.into(),
77 }
78 }
79
80 pub fn qualified_name(&self) -> String {
82 format!("\"{}\".\"{}\"", self.schema, self.name)
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
114pub struct InsertParams {
115 pub values: InsertValues,
117 pub columns: Option<Vec<String>>,
119 pub on_conflict: Option<OnConflict>,
121 pub returning: Option<Vec<SelectItem>>,
123}
124
125impl InsertParams {
126 pub fn new(values: InsertValues) -> Self {
128 Self {
129 values,
130 columns: None,
131 on_conflict: None,
132 returning: None,
133 }
134 }
135
136 pub fn with_columns(mut self, columns: Vec<String>) -> Self {
138 self.columns = Some(columns);
139 self
140 }
141
142 pub fn with_on_conflict(mut self, on_conflict: OnConflict) -> Self {
144 self.on_conflict = Some(on_conflict);
145 self
146 }
147
148 pub fn with_returning(mut self, returning: Vec<SelectItem>) -> Self {
150 self.returning = Some(returning);
151 self
152 }
153}
154
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
179pub enum InsertValues {
180 Single(HashMap<String, serde_json::Value>),
182 Bulk(Vec<HashMap<String, serde_json::Value>>),
184}
185
186impl InsertValues {
187 pub fn len(&self) -> usize {
189 match self {
190 InsertValues::Single(_) => 1,
191 InsertValues::Bulk(rows) => rows.len(),
192 }
193 }
194
195 pub fn is_empty(&self) -> bool {
197 match self {
198 InsertValues::Single(map) => map.is_empty(),
199 InsertValues::Bulk(rows) => rows.is_empty(),
200 }
201 }
202
203 pub fn get_columns(&self) -> Vec<String> {
205 match self {
206 InsertValues::Single(map) => {
207 let mut cols: Vec<String> = map.keys().cloned().collect();
208 cols.sort();
209 cols
210 }
211 InsertValues::Bulk(rows) => {
212 if let Some(first) = rows.first() {
213 let mut cols: Vec<String> = first.keys().cloned().collect();
214 cols.sort();
215 cols
216 } else {
217 Vec::new()
218 }
219 }
220 }
221 }
222}
223
224#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
255pub struct OnConflict {
256 pub columns: Vec<String>,
258 pub action: ConflictAction,
260 pub where_clause: Option<Vec<LogicCondition>>,
264 pub update_columns: Option<Vec<String>>,
268}
269
270impl OnConflict {
271 pub fn do_nothing(columns: Vec<String>) -> Self {
273 Self {
274 columns,
275 action: ConflictAction::DoNothing,
276 where_clause: None,
277 update_columns: None,
278 }
279 }
280
281 pub fn do_update(columns: Vec<String>) -> Self {
283 Self {
284 columns,
285 action: ConflictAction::DoUpdate,
286 where_clause: None,
287 update_columns: None,
288 }
289 }
290
291 pub fn with_where_clause(mut self, where_clause: Vec<LogicCondition>) -> Self {
293 self.where_clause = Some(where_clause);
294 self
295 }
296
297 pub fn with_update_columns(mut self, update_columns: Vec<String>) -> Self {
299 self.update_columns = Some(update_columns);
300 self
301 }
302}
303
304#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
306pub enum ConflictAction {
307 DoNothing,
309 DoUpdate,
311}
312
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
339pub struct UpdateParams {
340 pub set_values: HashMap<String, serde_json::Value>,
342 pub filters: Vec<LogicCondition>,
344 pub order: Vec<OrderTerm>,
346 pub limit: Option<u64>,
348 pub returning: Option<Vec<SelectItem>>,
350}
351
352impl UpdateParams {
353 pub fn new(set_values: HashMap<String, serde_json::Value>) -> Self {
355 Self {
356 set_values,
357 filters: Vec::new(),
358 order: Vec::new(),
359 limit: None,
360 returning: None,
361 }
362 }
363
364 pub fn with_filters(mut self, filters: Vec<LogicCondition>) -> Self {
366 self.filters = filters;
367 self
368 }
369
370 pub fn with_order(mut self, order: Vec<OrderTerm>) -> Self {
372 self.order = order;
373 self
374 }
375
376 pub fn with_limit(mut self, limit: u64) -> Self {
378 self.limit = Some(limit);
379 self
380 }
381
382 pub fn with_returning(mut self, returning: Vec<SelectItem>) -> Self {
384 self.returning = Some(returning);
385 self
386 }
387
388 pub fn has_filters(&self) -> bool {
390 !self.filters.is_empty()
391 }
392
393 pub fn is_set_empty(&self) -> bool {
395 self.set_values.is_empty()
396 }
397}
398
399#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
430pub struct DeleteParams {
431 pub filters: Vec<LogicCondition>,
433 pub order: Vec<OrderTerm>,
435 pub limit: Option<u64>,
437 pub returning: Option<Vec<SelectItem>>,
439}
440
441impl DeleteParams {
442 pub fn new() -> Self {
444 Self {
445 filters: Vec::new(),
446 order: Vec::new(),
447 limit: None,
448 returning: None,
449 }
450 }
451
452 pub fn with_filters(mut self, filters: Vec<LogicCondition>) -> Self {
454 self.filters = filters;
455 self
456 }
457
458 pub fn with_order(mut self, order: Vec<OrderTerm>) -> Self {
460 self.order = order;
461 self
462 }
463
464 pub fn with_limit(mut self, limit: u64) -> Self {
466 self.limit = Some(limit);
467 self
468 }
469
470 pub fn with_returning(mut self, returning: Vec<SelectItem>) -> Self {
472 self.returning = Some(returning);
473 self
474 }
475
476 pub fn has_filters(&self) -> bool {
478 !self.filters.is_empty()
479 }
480}
481
482impl Default for DeleteParams {
483 fn default() -> Self {
484 Self::new()
485 }
486}
487
488#[cfg(test)]
489mod tests {
490 use super::*;
491 use serde_json::json;
492
493 #[test]
494 fn test_resolved_table_new() {
495 let table = ResolvedTable::new("public", "users");
496 assert_eq!(table.schema, "public");
497 assert_eq!(table.name, "users");
498 }
499
500 #[test]
501 fn test_resolved_table_qualified_name() {
502 let table = ResolvedTable::new("auth", "users");
503 assert_eq!(table.qualified_name(), "\"auth\".\"users\"");
504 }
505
506 #[test]
507 fn test_insert_params_new() {
508 let mut map = HashMap::new();
509 map.insert("name".to_string(), json!("Alice"));
510 let params = InsertParams::new(InsertValues::Single(map));
511 assert!(params.columns.is_none());
512 assert!(params.on_conflict.is_none());
513 assert!(params.returning.is_none());
514 }
515
516 #[test]
517 fn test_insert_params_with_columns() {
518 let mut map = HashMap::new();
519 map.insert("name".to_string(), json!("Alice"));
520 let params = InsertParams::new(InsertValues::Single(map))
521 .with_columns(vec!["name".to_string(), "email".to_string()]);
522 assert_eq!(params.columns.as_ref().unwrap().len(), 2);
523 }
524
525 #[test]
526 fn test_insert_params_with_on_conflict() {
527 let mut map = HashMap::new();
528 map.insert("email".to_string(), json!("alice@example.com"));
529 let conflict = OnConflict::do_update(vec!["email".to_string()]);
530 let params = InsertParams::new(InsertValues::Single(map)).with_on_conflict(conflict);
531 assert!(params.on_conflict.is_some());
532 assert_eq!(params.on_conflict.unwrap().action, ConflictAction::DoUpdate);
533 }
534
535 #[test]
536 fn test_insert_values_single_len() {
537 let mut map = HashMap::new();
538 map.insert("name".to_string(), json!("Alice"));
539 let values = InsertValues::Single(map);
540 assert_eq!(values.len(), 1);
541 assert!(!values.is_empty());
542 }
543
544 #[test]
545 fn test_insert_values_bulk_len() {
546 let mut map1 = HashMap::new();
547 map1.insert("name".to_string(), json!("Alice"));
548 let mut map2 = HashMap::new();
549 map2.insert("name".to_string(), json!("Bob"));
550 let values = InsertValues::Bulk(vec![map1, map2]);
551 assert_eq!(values.len(), 2);
552 assert!(!values.is_empty());
553 }
554
555 #[test]
556 fn test_insert_values_get_columns() {
557 let mut map = HashMap::new();
558 map.insert("name".to_string(), json!("Alice"));
559 map.insert("age".to_string(), json!(30));
560 let values = InsertValues::Single(map);
561 let columns = values.get_columns();
562 assert_eq!(columns.len(), 2);
563 assert!(columns.contains(&"name".to_string()));
564 assert!(columns.contains(&"age".to_string()));
565 }
566
567 #[test]
568 fn test_on_conflict_do_nothing() {
569 let conflict = OnConflict::do_nothing(vec!["email".to_string()]);
570 assert_eq!(conflict.columns.len(), 1);
571 assert_eq!(conflict.action, ConflictAction::DoNothing);
572 }
573
574 #[test]
575 fn test_on_conflict_do_update() {
576 let conflict = OnConflict::do_update(vec!["email".to_string()]);
577 assert_eq!(conflict.action, ConflictAction::DoUpdate);
578 }
579
580 #[test]
581 fn test_update_params_new() {
582 let mut map = HashMap::new();
583 map.insert("status".to_string(), json!("active"));
584 let params = UpdateParams::new(map);
585 assert_eq!(params.set_values.len(), 1);
586 assert!(params.filters.is_empty());
587 assert!(params.order.is_empty());
588 assert!(params.limit.is_none());
589 }
590
591 #[test]
592 fn test_update_params_with_limit() {
593 let mut map = HashMap::new();
594 map.insert("status".to_string(), json!("active"));
595 let params = UpdateParams::new(map).with_limit(10);
596 assert_eq!(params.limit, Some(10));
597 }
598
599 #[test]
600 fn test_update_params_has_filters() {
601 let mut map = HashMap::new();
602 map.insert("status".to_string(), json!("active"));
603 let params = UpdateParams::new(map);
604 assert!(!params.has_filters());
605 }
606
607 #[test]
608 fn test_update_params_is_set_empty() {
609 let params = UpdateParams::new(HashMap::new());
610 assert!(params.is_set_empty());
611 }
612
613 #[test]
614 fn test_delete_params_new() {
615 let params = DeleteParams::new();
616 assert!(params.filters.is_empty());
617 assert!(params.order.is_empty());
618 assert!(params.limit.is_none());
619 assert!(params.returning.is_none());
620 }
621
622 #[test]
623 fn test_delete_params_with_limit() {
624 let params = DeleteParams::new().with_limit(5);
625 assert_eq!(params.limit, Some(5));
626 }
627
628 #[test]
629 fn test_delete_params_has_filters() {
630 let params = DeleteParams::new();
631 assert!(!params.has_filters());
632 }
633
634 #[test]
635 fn test_delete_params_default() {
636 let params = DeleteParams::default();
637 assert!(params.filters.is_empty());
638 }
639
640 #[test]
641 fn test_resolved_table_serialization() {
642 let table = ResolvedTable::new("public", "users");
643 let json = serde_json::to_string(&table).unwrap();
644 assert!(json.contains("public"));
645 assert!(json.contains("users"));
646 }
647
648 #[test]
649 fn test_insert_params_serialization() {
650 let mut map = HashMap::new();
651 map.insert("name".to_string(), json!("Alice"));
652 let params = InsertParams::new(InsertValues::Single(map));
653 let json = serde_json::to_string(¶ms).unwrap();
654 assert!(json.contains("Alice"));
655 }
656
657 #[test]
658 fn test_update_params_serialization() {
659 let mut map = HashMap::new();
660 map.insert("status".to_string(), json!("active"));
661 let params = UpdateParams::new(map);
662 let json = serde_json::to_string(¶ms).unwrap();
663 assert!(json.contains("active"));
664 }
665
666 #[test]
667 fn test_delete_params_serialization() {
668 let params = DeleteParams::new();
669 let json = serde_json::to_string(¶ms).unwrap();
670 assert!(json.contains("filters"));
671 }
672
673 #[test]
674 fn test_conflict_action_serialization() {
675 let action = ConflictAction::DoNothing;
676 let json = serde_json::to_string(&action).unwrap();
677 assert!(json.contains("DoNothing"));
678 }
679
680 #[test]
681 fn test_insert_values_empty_map() {
682 let values = InsertValues::Single(HashMap::new());
683 assert!(values.is_empty());
684 assert_eq!(values.len(), 1); }
686
687 #[test]
688 fn test_insert_values_empty_bulk() {
689 let values = InsertValues::Bulk(Vec::new());
690 assert!(values.is_empty());
691 assert_eq!(values.len(), 0);
692 }
693
694 #[test]
695 fn test_bulk_insert_get_columns() {
696 let mut map1 = HashMap::new();
697 map1.insert("name".to_string(), json!("Alice"));
698 map1.insert("age".to_string(), json!(30));
699 let mut map2 = HashMap::new();
700 map2.insert("name".to_string(), json!("Bob"));
701 map2.insert("age".to_string(), json!(25));
702 let values = InsertValues::Bulk(vec![map1, map2]);
703 let columns = values.get_columns();
704 assert_eq!(columns.len(), 2);
705 }
706}