1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::{RecordFilter, WriteArgs};
use query_structure::{FieldSelection, Filter, Model, ScalarFieldRef};

#[derive(Debug, Clone)]
pub struct NativeUpsert {
    name: String,
    model: Model,
    record_filter: RecordFilter,
    create: WriteArgs,
    update: WriteArgs,
    selected_fields: FieldSelection,
    selection_order: Vec<String>,
}

impl NativeUpsert {
    pub fn new(
        name: String,
        model: Model,
        record_filter: RecordFilter,
        create: WriteArgs,
        update: WriteArgs,
        selected_fields: FieldSelection,
        selection_order: Vec<String>,
    ) -> Self {
        Self {
            name,
            model,
            record_filter,
            create,
            update,
            selected_fields,
            selection_order,
        }
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn model(&self) -> &Model {
        &self.model
    }

    pub fn update(&self) -> &WriteArgs {
        &self.update
    }

    pub fn create(&self) -> &WriteArgs {
        &self.create
    }

    pub fn unique_constraints(&self) -> Vec<ScalarFieldRef> {
        let compound_indexes = self.model.unique_indexes();
        let scalars = self.record_filter.filter.scalars();
        let unique_index = compound_indexes.into_iter().find(|index| {
            index
                .fields()
                .all(|f| scalars.contains(&ScalarFieldRef::from((self.model.dm.clone(), f))))
        });

        if let Some(index) = unique_index {
            return index
                .fields()
                .map(|f| ScalarFieldRef::from((self.model.dm.clone(), f)))
                .collect();
        }

        if let Some(ids) = self.model.fields().compound_id() {
            if ids.clone().all(|f| scalars.contains(&f)) {
                return ids.collect();
            }
        }

        self.record_filter.filter.unique_scalars()
    }

    pub fn filter(&self) -> &Filter {
        &self.record_filter.filter
    }

    pub fn selected_fields(&self) -> &FieldSelection {
        &self.selected_fields
    }

    pub fn selection_order(&self) -> &[String] {
        &self.selection_order
    }

    pub fn record_filter(&self) -> &RecordFilter {
        &self.record_filter
    }
}