@@ -28,11 +28,8 @@ mod update_location;
28
28
mod update_properties;
29
29
mod upgrade_format_version;
30
30
31
- use std:: mem:: discriminant;
32
31
use std:: sync:: Arc ;
33
32
34
- use uuid:: Uuid ;
35
-
36
33
use crate :: error:: Result ;
37
34
use crate :: table:: Table ;
38
35
use crate :: transaction:: action:: BoxedTransactionAction ;
@@ -45,67 +42,49 @@ use crate::{Catalog, TableCommit, TableRequirement, TableUpdate};
45
42
46
43
/// Table transaction.
47
44
pub struct Transaction {
48
- base_table : Table ,
49
- current_table : Table ,
45
+ table : Table ,
50
46
actions : Vec < BoxedTransactionAction > ,
51
- updates : Vec < TableUpdate > ,
52
- requirements : Vec < TableRequirement > ,
53
47
}
54
48
55
49
impl Transaction {
56
50
/// Creates a new transaction.
57
51
pub fn new ( table : & Table ) -> Self {
58
52
Self {
59
- base_table : table. clone ( ) ,
60
- current_table : table. clone ( ) ,
53
+ table : table. clone ( ) ,
61
54
actions : vec ! [ ] ,
62
- updates : vec ! [ ] ,
63
- requirements : vec ! [ ] ,
64
55
}
65
56
}
66
57
67
- fn update_table_metadata ( & mut self , updates : & [ TableUpdate ] ) -> Result < ( ) > {
68
- let mut metadata_builder = self . current_table . metadata ( ) . clone ( ) . into_builder ( None ) ;
58
+ fn update_table_metadata ( table : Table , updates : & [ TableUpdate ] ) -> Result < Table > {
59
+ let mut metadata_builder = table . metadata ( ) . clone ( ) . into_builder ( None ) ;
69
60
for update in updates {
70
61
metadata_builder = update. clone ( ) . apply ( metadata_builder) ?;
71
62
}
72
63
73
- self . current_table
74
- . with_metadata ( Arc :: new ( metadata_builder. build ( ) ?. metadata ) ) ;
75
-
76
- Ok ( ( ) )
64
+ Ok ( table. with_metadata ( Arc :: new ( metadata_builder. build ( ) ?. metadata ) ) )
77
65
}
78
66
67
+ /// Applies an [`ActionCommit`] to the given [`Table`], returning a new [`Table`] with updated metadata.
68
+ /// Also appends any derived [`TableUpdate`]s and [`TableRequirement`]s to the provided vectors.
79
69
fn apply (
80
- & mut self ,
81
- updates : Vec < TableUpdate > ,
82
- requirements : Vec < TableRequirement > ,
83
- ) -> Result < ( ) > {
70
+ table : Table ,
71
+ mut action_commit : ActionCommit ,
72
+ existing_updates : & mut Vec < TableUpdate > ,
73
+ existing_requirements : & mut Vec < TableRequirement > ,
74
+ ) -> Result < Table > {
75
+ let updates = action_commit. take_updates ( ) ;
76
+ let requirements = action_commit. take_requirements ( ) ;
77
+
84
78
for requirement in & requirements {
85
- requirement. check ( Some ( self . current_table . metadata ( ) ) ) ?;
79
+ requirement. check ( Some ( table . metadata ( ) ) ) ?;
86
80
}
87
81
88
- self . update_table_metadata ( & updates) ?;
89
-
90
- self . updates . extend ( updates) ;
91
-
92
- // For the requirements, it does not make sense to add a requirement more than once
93
- // For example, you cannot assert that the current schema has two different IDs
94
- for new_requirement in requirements {
95
- if self
96
- . requirements
97
- . iter ( )
98
- . map ( discriminant)
99
- . all ( |d| d != discriminant ( & new_requirement) )
100
- {
101
- self . requirements . push ( new_requirement) ;
102
- }
103
- }
82
+ let updated_table = Self :: update_table_metadata ( table, & updates) ?;
104
83
105
- // # TODO
106
- // Support auto commit later.
84
+ existing_updates . extend ( updates ) ;
85
+ existing_requirements . extend ( requirements ) ;
107
86
108
- Ok ( ( ) )
87
+ Ok ( updated_table )
109
88
}
110
89
111
90
/// Sets table to a new version.
@@ -118,31 +97,9 @@ impl Transaction {
118
97
UpdatePropertiesAction :: new ( )
119
98
}
120
99
121
- fn generate_unique_snapshot_id ( & self ) -> i64 {
122
- let generate_random_id = || -> i64 {
123
- let ( lhs, rhs) = Uuid :: new_v4 ( ) . as_u64_pair ( ) ;
124
- let snapshot_id = ( lhs ^ rhs) as i64 ;
125
- if snapshot_id < 0 {
126
- -snapshot_id
127
- } else {
128
- snapshot_id
129
- }
130
- } ;
131
- let mut snapshot_id = generate_random_id ( ) ;
132
- while self
133
- . current_table
134
- . metadata ( )
135
- . snapshots ( )
136
- . any ( |s| s. snapshot_id ( ) == snapshot_id)
137
- {
138
- snapshot_id = generate_random_id ( ) ;
139
- }
140
- snapshot_id
141
- }
142
-
143
100
/// Creates a fast append action.
144
101
pub fn fast_append ( & self ) -> FastAppendAction {
145
- FastAppendAction :: new ( self . generate_unique_snapshot_id ( ) )
102
+ FastAppendAction :: new ( )
146
103
}
147
104
148
105
/// Creates replace sort order action.
@@ -157,41 +114,43 @@ impl Transaction {
157
114
158
115
/// Commit transaction.
159
116
pub async fn commit ( mut self , catalog : & dyn Catalog ) -> Result < Table > {
160
- if self . actions . is_empty ( ) && self . updates . is_empty ( ) {
117
+ if self . actions . is_empty ( ) {
161
118
// nothing to commit
162
- return Ok ( self . base_table . clone ( ) ) ;
119
+ return Ok ( self . table . clone ( ) ) ;
163
120
}
164
121
165
122
self . do_commit ( catalog) . await
166
123
}
167
124
168
125
async fn do_commit ( & mut self , catalog : & dyn Catalog ) -> Result < Table > {
169
- let base_table_identifier = self . base_table . identifier ( ) . to_owned ( ) ;
126
+ let refreshed = catalog . load_table ( self . table . identifier ( ) ) . await ? ;
170
127
171
- let refreshed = catalog. load_table ( & base_table_identifier. clone ( ) ) . await ?;
172
-
173
- if self . base_table . metadata ( ) != refreshed. metadata ( )
174
- || self . base_table . metadata_location ( ) != refreshed. metadata_location ( )
128
+ if self . table . metadata ( ) != refreshed. metadata ( )
129
+ || self . table . metadata_location ( ) != refreshed. metadata_location ( )
175
130
{
176
131
// current base is stale, use refreshed as base and re-apply transaction actions
177
- self . base_table = refreshed. clone ( ) ;
132
+ self . table = refreshed. clone ( ) ;
178
133
}
179
134
180
- let current_table = self . base_table . clone ( ) ;
181
-
182
- for action in self . actions . clone ( ) {
183
- let mut action_commit = action. commit ( & current_table) . await ?;
184
- // apply changes to current_table
185
- self . apply (
186
- action_commit. take_updates ( ) ,
187
- action_commit. take_requirements ( ) ,
135
+ let mut current_table = self . table . clone ( ) ;
136
+ let mut existing_updates: Vec < TableUpdate > = vec ! [ ] ;
137
+ let mut existing_requirements: Vec < TableRequirement > = vec ! [ ] ;
138
+
139
+ for action in & self . actions {
140
+ let action_commit = Arc :: clone ( action) . commit ( & current_table) . await ?;
141
+ // apply action commit to current_table
142
+ current_table = Self :: apply (
143
+ current_table,
144
+ action_commit,
145
+ & mut existing_updates,
146
+ & mut existing_requirements,
188
147
) ?;
189
148
}
190
149
191
150
let table_commit = TableCommit :: builder ( )
192
- . ident ( base_table_identifier )
193
- . updates ( self . updates . clone ( ) )
194
- . requirements ( self . requirements . clone ( ) )
151
+ . ident ( self . table . identifier ( ) . to_owned ( ) )
152
+ . updates ( existing_updates )
153
+ . requirements ( existing_requirements )
195
154
. build ( ) ;
196
155
197
156
catalog. update_table ( table_commit) . await
0 commit comments