Skip to content

Commit 5b59319

Browse files
committed
Skip REMOVE operation in additional cases.
1 parent e03f440 commit 5b59319

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

crates/core/src/operations.rs

+30-14
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,11 @@ FROM json_each(?) e",
6363
// language=SQLite
6464
let supersede_statement = db.prepare_v2(
6565
"\
66-
UPDATE ps_oplog SET
67-
superseded = 1,
68-
op = 2,
69-
data = NULL
66+
DELETE FROM ps_oplog
7067
WHERE ps_oplog.superseded = 0
7168
AND unlikely(ps_oplog.bucket = ?1)
72-
AND ps_oplog.key = ?2",
69+
AND ps_oplog.key = ?2
70+
RETURNING op_id, hash",
7371
)?;
7472
supersede_statement.bind_text(1, bucket, sqlite::Destructor::STATIC)?;
7573

@@ -110,21 +108,39 @@ INSERT INTO ps_oplog(bucket, op_id, op, key, row_type, row_id, data, hash, super
110108

111109
last_op = Some(op_id);
112110

113-
let mut key: String = "".to_string();
114-
115111
if op == "PUT" || op == "REMOVE" {
112+
let key: String;
116113
if let (Ok(object_type), Ok(object_id)) = (object_type.as_ref(), object_id.as_ref()) {
117114
let subkey = iterate_statement.column_text(6).unwrap_or("null");
118-
let populated_key = format!("{}/{}/{}", &object_type, &object_id, subkey);
115+
key = format!("{}/{}/{}", &object_type, &object_id, subkey);
116+
} else {
117+
key = String::from("");
118+
}
119119

120-
supersede_statement.bind_text(2, &populated_key, sqlite::Destructor::STATIC)?;
121-
supersede_statement.exec()?;
120+
supersede_statement.bind_text(2, &key, sqlite::Destructor::STATIC)?;
122121

123-
key = populated_key;
122+
let mut superseded = false;
123+
124+
while (supersede_statement.step()? == ResultCode::ROW) {
125+
// Superseded (deleted) a previous operation, add the checksum
126+
let supersede_checksum = supersede_statement.column_int(1)?;
127+
add_checksum = add_checksum.wrapping_add(supersede_checksum);
128+
// Superseded an operation, only skip if the bucket was empty
129+
superseded = true;
130+
}
131+
supersede_statement.reset()?;
132+
133+
let should_skip_remove = (is_empty || !superseded) && op == "REMOVE";
134+
if (should_skip_remove) {
135+
// If a REMOVE statement did not replace (supersede) any previous
136+
// operations, we do not need to persist it.
137+
// The same applies if the bucket was not synced to the local db yet,
138+
// even if it did supersede another operation.
139+
// Handle the same as MOVE.
140+
add_checksum = add_checksum.wrapping_add(checksum);
141+
continue;
124142
}
125-
}
126143

127-
if op == "PUT" || (op == "REMOVE" && !is_empty) {
128144
let opi = if op == "PUT" { 3 } else { 4 };
129145
insert_statement.bind_int64(2, op_id)?;
130146
insert_statement.bind_int(3, opi)?;
@@ -149,7 +165,7 @@ INSERT INTO ps_oplog(bucket, op_id, op, key, row_type, row_id, data, hash, super
149165

150166
insert_statement.bind_int(8, checksum)?;
151167
insert_statement.exec()?;
152-
} else if op == "MOVE" || (is_empty && op == "REMOVE") {
168+
} else if op == "MOVE" {
153169
add_checksum = add_checksum.wrapping_add(checksum);
154170
} else if op == "CLEAR" {
155171
// Any remaining PUT operations should get an implicit REMOVE

0 commit comments

Comments
 (0)