///|
priv enum LockMode {
AccessShare
RowShare
RowExclusive
ShareUpdateExclusive
Share
ShareRowExclusive
Exclusive
AccessExclusive
}
///|
fn LockMode::name(self : LockMode) -> String {
match self {
AccessShare => "ACCESS SHARE"
RowShare => "ROW SHARE"
RowExclusive => "ROW EXCLUSIVE"
ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE"
Share => "SHARE"
ShareRowExclusive => "SHARE ROW EXCLUSIVE"
Exclusive => "EXCLUSIVE"
AccessExclusive => "ACCESS EXCLUSIVE"
}
}
///|
fn LockMode::impact(self : LockMode) -> String {
match self {
AccessShare => "conflicts with ACCESS EXCLUSIVE operations"
RowShare => "conflicts with EXCLUSIVE and ACCESS EXCLUSIVE operations"
RowExclusive =>
"allows ordinary concurrent writes but conflicts with SHARE and stronger lock modes"
ShareUpdateExclusive =>
"allows ordinary concurrent writes but can conflict with concurrent maintenance and schema operations"
Share | ShareRowExclusive =>
"can block ordinary writes while allowing ordinary reads"
Exclusive =>
"can block ordinary writes and locking reads while allowing ordinary non-locking reads"
AccessExclusive => "can block ordinary reads and writes"
}
}
///|
// Closed grammar: every relation and option is consumed. Catalog-qualified names
// and ONLY (name) are outside the supported subset, not partially interpreted.
fn classify_lock(words : ArrayView[String]) -> Command {
let mut i = 1
if words.get(i) == Some("TABLE") {
i += 1
}
let mut count = 0
while i < words.length() {
let only = words.get(i) == Some("ONLY")
if only {
i += 1
}
if i >= words.length() || !index_identifier(words[i]) {
return Unsupported
}
i += 1
if words.get(i) == Some(".") {
i += 1
if i >= words.length() || !index_identifier(words[i]) {
return Unsupported
}
i += 1
}
if words.get(i) == Some("*") {
if only {
return Unsupported
}
i += 1
}
count += 1
if words.get(i) != Some(",") {
break
}
i += 1
if i == words.length() {
return Unsupported
}
}
if count == 0 {
return Unsupported
}
let nowait = i < words.length() && words.last() == Some("NOWAIT")
let end = words.length() - (if nowait { 1 } else { 0 })
let mode : LockMode = match words[i:end] {
[] => AccessExclusive
["IN", "ACCESS", "SHARE", "MODE"] => AccessShare
["IN", "ROW", "SHARE", "MODE"] => RowShare
["IN", "ROW", "EXCLUSIVE", "MODE"] => RowExclusive
["IN", "SHARE", "UPDATE", "EXCLUSIVE", "MODE"] => ShareUpdateExclusive
["IN", "SHARE", "MODE"] => Share
["IN", "SHARE", "ROW", "EXCLUSIVE", "MODE"] => ShareRowExclusive
["IN", "EXCLUSIVE", "MODE"] => Exclusive
["IN", "ACCESS", "EXCLUSIVE", "MODE"] => AccessExclusive
_ => return Unsupported
}
LockTable(mode, nowait)
}