-
Notifications
You must be signed in to change notification settings - Fork 124
fix(udb): fix postgres driver impl #3035
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
How to use the Graphite Merge QueueAdd the label merge-queue to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
commit: |
baabddc
to
7329d90
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
7329d90
to
570f2d3
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
if self.committed.load(Ordering::SeqCst) { | ||
return Ok(()); | ||
} | ||
self.committed.store(true, Ordering::SeqCst); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider moving the committed.store(true, Ordering::SeqCst)
line after the successful commit operation to prevent a potential race condition. If the commit fails, the transaction would be incorrectly marked as committed, which could lead to unexpected behavior in error recovery scenarios.
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
570f2d3
to
8e04f9c
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
8e04f9c
to
b9aa0d1
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
b9aa0d1
to
2d256a1
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
2d256a1
to
ea5bccd
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
Merge activity
|
ea5bccd
to
60a09d5
Compare
Claude encountered an error —— View job I'll analyze this and get back to you. |
async fn handle_get_range( | ||
&mut self, | ||
tx: &Transaction<'_>, | ||
begin_key: Vec<u8>, | ||
begin_or_equal: bool, | ||
begin_offset: i32, | ||
end_key: Vec<u8>, | ||
end_or_equal: bool, | ||
end_offset: i32, | ||
limit: Option<usize>, | ||
reverse: bool, | ||
) -> Result<Values> { | ||
// Determine SQL operators based on key selector types | ||
// For begin selector: | ||
// first_greater_or_equal: or_equal = false, offset = 1 -> ">=" | ||
// first_greater_than: or_equal = true, offset = 1 -> ">" | ||
let begin_op = if begin_offset == 1 { | ||
if begin_or_equal { ">" } else { ">=" } | ||
} else { | ||
// This shouldn't happen for begin in range queries | ||
">=" | ||
}; | ||
|
||
// For end selector: | ||
// first_greater_than: or_equal = true, offset = 1 -> "<=" | ||
// first_greater_or_equal: or_equal = false, offset = 1 -> "<" | ||
let end_op = if end_offset == 1 { | ||
if end_or_equal { "<=" } else { "<" } | ||
} else { | ||
// This shouldn't happen for end in range queries | ||
"<" | ||
}; | ||
|
||
// Build query with CTE that adds conflict range | ||
let query = if reverse { | ||
if let Some(limit) = limit { | ||
format!( | ||
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key DESC LIMIT {limit}" | ||
) | ||
} else { | ||
format!( | ||
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key DESC" | ||
) | ||
} | ||
} else if let Some(limit) = limit { | ||
format!( | ||
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key LIMIT {limit}" | ||
) | ||
} else { | ||
format!( | ||
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key" | ||
) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PostgreSQL implementation of handle_get_range
doesn't add conflict ranges for read operations, unlike the RocksDB implementation. This inconsistency could lead to transaction anomalies when using serializable isolation. Consider adding code to insert conflict ranges for range reads, similar to how it's done in the RocksDB driver:
// Add read conflict range for this range
if let IsolationLevel::Serializable = isolation_level {
// Insert conflict range for the read operation
let query = "INSERT INTO conflict_ranges (range_data, conflict_type, start_version, commit_version)
VALUES (bytearange($1, $2, '[)'), 'read', $3, $4)";
// Execute with appropriate parameters
}
This would ensure consistent behavior between database backends and proper serializable isolation semantics.
async fn handle_get_range( | |
&mut self, | |
tx: &Transaction<'_>, | |
begin_key: Vec<u8>, | |
begin_or_equal: bool, | |
begin_offset: i32, | |
end_key: Vec<u8>, | |
end_or_equal: bool, | |
end_offset: i32, | |
limit: Option<usize>, | |
reverse: bool, | |
) -> Result<Values> { | |
// Determine SQL operators based on key selector types | |
// For begin selector: | |
// first_greater_or_equal: or_equal = false, offset = 1 -> ">=" | |
// first_greater_than: or_equal = true, offset = 1 -> ">" | |
let begin_op = if begin_offset == 1 { | |
if begin_or_equal { ">" } else { ">=" } | |
} else { | |
// This shouldn't happen for begin in range queries | |
">=" | |
}; | |
// For end selector: | |
// first_greater_than: or_equal = true, offset = 1 -> "<=" | |
// first_greater_or_equal: or_equal = false, offset = 1 -> "<" | |
let end_op = if end_offset == 1 { | |
if end_or_equal { "<=" } else { "<" } | |
} else { | |
// This shouldn't happen for end in range queries | |
"<" | |
}; | |
// Build query with CTE that adds conflict range | |
let query = if reverse { | |
if let Some(limit) = limit { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key DESC LIMIT {limit}" | |
) | |
} else { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key DESC" | |
) | |
} | |
} else if let Some(limit) = limit { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key LIMIT {limit}" | |
) | |
} else { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key" | |
) | |
}; | |
async fn handle_get_range( | |
&mut self, | |
tx: &Transaction<'_>, | |
begin_key: Vec<u8>, | |
begin_or_equal: bool, | |
begin_offset: i32, | |
end_key: Vec<u8>, | |
end_or_equal: bool, | |
end_offset: i32, | |
limit: Option<usize>, | |
reverse: bool, | |
) -> Result<Values> { | |
// Determine SQL operators based on key selector types | |
// For begin selector: | |
// first_greater_or_equal: or_equal = false, offset = 1 -> ">=" | |
// first_greater_than: or_equal = true, offset = 1 -> ">" | |
let begin_op = if begin_offset == 1 { | |
if begin_or_equal { ">" } else { ">=" } | |
} else { | |
// This shouldn't happen for begin in range queries | |
">=" | |
}; | |
// For end selector: | |
// first_greater_than: or_equal = true, offset = 1 -> "<=" | |
// first_greater_or_equal: or_equal = false, offset = 1 -> "<" | |
let end_op = if end_offset == 1 { | |
if end_or_equal { "<=" } else { "<" } | |
} else { | |
// This shouldn't happen for end in range queries | |
"<" | |
}; | |
// Add read conflict range for this range if using serializable isolation | |
if let IsolationLevel::Serializable = self.isolation_level { | |
let conflict_query = "INSERT INTO conflict_ranges (range_data, conflict_type, start_version, commit_version) | |
VALUES (bytearange($1, $2, '[)'), 'read', $3, $4)"; | |
tx.execute( | |
conflict_query, | |
&[&begin_key, &end_key, &self.start_version, &self.commit_version], | |
) | |
.await | |
.map_err(|e| Error::DatabaseError(e.to_string()))?; | |
} | |
// Build query with CTE that adds conflict range | |
let query = if reverse { | |
if let Some(limit) = limit { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key DESC LIMIT {limit}" | |
) | |
} else { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key DESC" | |
) | |
} | |
} else if let Some(limit) = limit { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key LIMIT {limit}" | |
) | |
} else { | |
format!( | |
"SELECT key, value FROM kv WHERE key {begin_op} $1 AND key {end_op} $2 ORDER BY key" | |
) | |
}; | |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
No description provided.