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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::collections::HashMap;

use versatile_data::{Activity, KeyValue, Operation, Term};

use crate::{
    session::{SessionCollectionRow, SessionData, SessionOperation},
    CollectionRow, Database,
};

pub fn commit(
    main_database: &mut Database,
    session_data: &SessionData,
) -> Result<(), std::io::Error> {
    let mut session_collection_row_map: HashMap<u32, CollectionRow> = HashMap::new();

    let mut session_relation: HashMap<u32, Vec<(u32, SessionCollectionRow)>> = HashMap::new();
    for row in 1..session_data.relation.rows.session_row.max_rows() {
        if let (Some(session_row), Some(depend)) = (
            session_data.relation.rows.session_row.value(row),
            session_data.relation.rows.depend.value(row),
        ) {
            let m = session_relation.entry(session_row).or_insert(Vec::new());
            m.push((row, depend));
        }
    }
    for session_row in 1..session_data.sequence.max_rows() {
        if let (Some(op), Some(collection_id), Some(row)) = (
            session_data.operation.value(session_row),
            session_data.collection_id.value(session_row),
            session_data.row.value(session_row),
        ) {
            if let Some(collection) = main_database.collection_mut(collection_id) {
                match op {
                    SessionOperation::New | SessionOperation::Update => {
                        let mut fields: Vec<KeyValue> = Vec::new();
                        for (key, ref field_data) in &session_data.fields {
                            if let Some(val) = field_data.get(session_row) {
                                fields.push(KeyValue::new(key, val));
                            }
                        }
                        let activity = if session_data.activity.value(session_row).unwrap() == 1 {
                            Activity::Active
                        } else {
                            Activity::Inactive
                        };
                        let term_begin =
                            Term::Overwrite(session_data.term_begin.value(session_row).unwrap());
                        let term_end =
                            Term::Overwrite(session_data.term_end.value(session_row).unwrap());
                        let collection_row = if row == 0 {
                            //new
                            let row=collection.create_row(&activity, &term_begin, &term_end, &fields);
                            CollectionRow::new(collection_id, row)
                        } else {
                            if row<0{
                                //update new data in session.
                                if let Some(master_collection_row)=session_collection_row_map.get(&(-row as u32)){
                                    let row=master_collection_row.row();
                                    collection.update_row(row, &activity, &term_begin, &term_end, &fields);
                                    CollectionRow::new(master_collection_row.collection_id(), row)
                                }else{
                                    panic!("crash");
                                }
                            }else{
                                //update
                                let row = row as u32;
                                collection.update_row(row, &activity, &term_begin, &term_end, &fields);
                                CollectionRow::new(collection_id, row)
                            }
                        };
                        main_database.relation.delete_by_collection_row(collection_row);
                        session_collection_row_map.insert(session_row, collection_row);
                        if let Some(depend_rows) = session_relation.get(&session_row) {
                            for (session_row, depend) in depend_rows {
                                let key =
                                    session_data.relation.rows.key.value(*session_row).unwrap();
                                let key = unsafe { session_data.relation.key_names.str(key) };

                                if depend.row < 0 {
                                    if let Some(depend) =
                                        session_collection_row_map.get(&((-depend.row) as u32))
                                    {
                                        main_database.relation.insert(
                                            key,
                                            *depend,
                                            collection_row,
                                        )?;
                                    }
                                } else {
                                    main_database.relation.insert(
                                        key,
                                        CollectionRow::new(depend.collection_id, depend.row as u32),
                                        collection_row,
                                    )?;
                                };
                            }
                        }
                    }
                    SessionOperation::Delete => {
                        //todo!("セッション考慮の削除処理");
                        delete_recursive(
                            main_database,
                            &SessionCollectionRow::new(collection_id, row),
                        );
                    }
                }
            }
        }
    }
    Ok(())
}

pub(super) fn delete_recursive(database: &mut Database, target: &SessionCollectionRow) {
    if target.row > 0 {
        let depend = CollectionRow::new(target.collection_id, target.row as u32);
        let c = database.relation.index_depend().select_by_value(&depend);
        for relation_row in c {
            if let Some(collection_row) = database.relation.index_pend().value(relation_row) {
                delete_recursive(
                    database,
                    &SessionCollectionRow::new(
                        collection_row.collection_id(),
                        collection_row.row() as i64,
                    ),
                );
                if let Some(collection) = database.collection_mut(collection_row.collection_id()) {
                    collection.update(&Operation::Delete {
                        row: collection_row.row(),
                    });
                }
            }
            database.relation.delete(relation_row);
        }
    }
}