///|
// Closed BEGIN/START TRANSACTION mode grammar. Repeated categories are rejected
// conservatively instead of guessing precedence; commas may be omitted in PG.
fn classify_begin(words : ArrayView[String]) -> Command {
let seen : Map[String, Unit] = Map([])
let mut i = 0
let mut read_only = false
let mut deferrable = false
while i < words.length() {
let category = words[i]
if seen.contains(category) {
return Unsupported
}
match words[i:] {
["ISOLATION", "LEVEL", "SERIALIZABLE", ..] => i += 3
["ISOLATION", "LEVEL", "REPEATABLE", "READ", ..]
| ["ISOLATION", "LEVEL", "READ", "COMMITTED" | "UNCOMMITTED", ..] =>
i += 4
["READ", "ONLY" | "WRITE", ..] => {
read_only = words[i + 1] == "ONLY"
i += 2
}
["DEFERRABLE", ..] => {
deferrable = true
i += 1
}
["NOT", "DEFERRABLE", ..] => i += 2
_ => return Unsupported
}
let category = if category == "NOT" { "DEFERRABLE" } else { category }
if seen.contains(category) {
return Unsupported
}
seen[category] = ()
if words.get(i) == Some(",") {
i += 1
if i == words.length() {
return Unsupported
}
}
}
Begin(read_only~, deferrable~)
}