Skip to main content

eosio_chain/
mi.rs

1use crate::db::*;
2use crate::name::{
3    Name,
4};
5
6// use crate::{
7//     check,
8// };
9
10use crate::{
11    vec::Vec,
12};
13
14use crate::{
15    check,
16    serializer::Packer,
17};
18
19use crate::boxed::Box;
20///
21pub struct MultiIndex<T>
22where T: PrimaryValueInterface + SecondaryValueInterface + Packer + Default
23{
24    ///
25    pub code: Name,
26    ///
27    pub scope: Name,
28    ///
29    pub table: Name,
30    ///
31    pub db: TableI64<T>,
32    ///
33    pub idxdbs: Vec<Box<dyn IdxTable>>,
34    _marker: core::marker::PhantomData<T>,
35}
36
37impl<T> MultiIndex<T> 
38where T: PrimaryValueInterface + SecondaryValueInterface + Packer + Default
39{
40    ///
41    pub fn new(code: Name, scope: Name, table: Name, indices: &[SecondaryType]) -> Self {
42        let mut idxdbs: Vec<Box<dyn IdxTable>> = Vec::new();
43        let mut i: usize = 0;
44        let idx_table = table.value() & 0xfffffffffffffff0;
45        for idx in indices {
46            match idx {
47                SecondaryType::Idx64 => idxdbs.push(
48                    Box::new(
49                        Idx64Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
50                    )
51                ),
52                SecondaryType::Idx128 => idxdbs.push(
53                    Box::new(
54                        Idx128Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
55                    )
56                ),
57                SecondaryType::Idx256 => idxdbs.push(
58                    Box::new(
59                        Idx256Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
60                    )
61                ),
62                SecondaryType::IdxF64 => idxdbs.push(
63                    Box::new(
64                        IdxF64Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
65                    )
66                ),
67                SecondaryType::IdxF128 => idxdbs.push(
68                    Box::new(
69                        IdxF128Table::new(i, code, scope, Name::from_u64(idx_table + i as u64))
70                    )
71                ),
72                // _ => check(false, "unsupported secondary index type"),
73            }
74            i += 1;
75        }
76        MultiIndex {
77            code,
78            scope,
79            table,
80            db: TableI64::new(code, scope, table),
81            idxdbs,
82            _marker: core::marker::PhantomData::<T>{},
83        }
84    }
85
86    ///
87    pub fn store(&self, value: &T, payer: Name) -> Iterator<T> {
88        let primary = value.get_primary();
89        for i in 0..self.idxdbs.len() {
90            let v2 = value.get_secondary_value(i);
91            self.idxdbs[i].store(primary, v2, payer);
92        }
93        let it = self.db.store(&value, payer);
94        return it;
95    }
96
97    ///
98    pub fn find(&self, id: u64) -> Iterator<T> {
99        return self.db.find(id);
100    }
101
102    ///
103    pub fn update(&self, iterator: &Iterator<T>, value: &T, payer: Name) {
104        check(iterator.is_ok(), "MultiIndex::update: invalid iterator");
105        let primary = iterator.get_primary().unwrap();
106        self.db.update(&iterator, value, payer);
107        for i in 0..self.idxdbs.len() {
108            let v2 = value.get_secondary_value(i);
109            let (it_secondary, secondary_value) = self.idxdbs[i].find_primary(primary);
110            if secondary_value == v2 {
111                continue;
112            }
113            self.idxdbs[i].update(&it_secondary, v2, payer);
114        }
115    }
116
117    ///
118    pub fn remove(&self, iterator: &Iterator<T>) {
119        check(iterator.is_ok(), "remove: invalid iterator");
120        let primary = iterator.get_primary().unwrap();
121        for i in 0..self.idxdbs.len() {
122            let (it_secondary, _) = self.idxdbs[i].find_primary(primary);
123            self.idxdbs[i].remove(&it_secondary);
124        }
125        self.db.remove(&iterator);
126    }
127
128    ///
129    pub fn get(&self, iterator: &Iterator<T>) -> Option<T> {
130        if !iterator.is_ok() {
131            return None;
132        }
133        self.db.get(iterator)
134    }
135
136    ///
137    pub fn get_by_primary(&self, primary: u64) -> Option<T> {
138        let it = self.db.find(primary);
139        return self.get(&it);
140    }
141
142    ///
143    pub fn next(&self, iterator: &Iterator<T>) -> Iterator<T> {
144        return self.db.next(iterator);
145    }
146
147    ///
148    pub fn previous(&self, iterator: &Iterator<T>) -> Iterator<T> {
149        return self.db.previous(iterator);
150    }
151
152    ///
153    pub fn lower_bound(&self, id: u64) -> Iterator<T> {
154        return self.db.lower_bound(id);
155    }
156
157    ///
158    pub fn upper_bound(&self, id: u64) -> Iterator<T> {
159        return self.db.upper_bound(id);
160    }
161
162    ///
163    pub fn end(&self) -> Iterator<T> {
164        return self.db.end();
165    }
166
167    ///
168    pub fn get_idx_db(&self, i: usize) -> &dyn IdxTable {
169        return self.idxdbs[i].as_ref();
170    }
171
172    ///
173    pub fn idx_update(&self, it: &SecondaryIterator, value: SecondaryValue, payer: Name) {
174        let it_primary = self.find(it.primary).expect("idx_update: invalid primary");
175        if let Some(mut db_value) = it_primary.get_value() {
176            let idx_db = self.idxdbs[it.db_index].as_ref();
177            db_value.set_secondary_value(idx_db.get_db_index(), value);
178            self.update(&it_primary, &db_value, payer);
179            idx_db.update(it, value, payer);    
180        } else {
181        }
182    }
183}