///|
fn pg_array(input : String, element : UInt) -> ReadOnlyArray[Cell] raise {
  let mut text = input[:]
  if text.has_prefix("[") {
    let mut end = 1
    while end < text.length() && text[end] != ']' {
      end += 1
    }
    if end + 1 >= text.length() || text[end + 1] != '=' {
      raise Conversion("array dimensions")
    }
    let dimensions = text[1:end].split(":").to_array()
    if dimensions.length() != 2 {
      raise Conversion("array dimensions")
    }
    for dimension in dimensions {
      lexmatch dimension {
        re"^-?[0-9]+$" => ()
        _ => raise Conversion("array bound")
      }
    }
    text = text[end + 2:]
  }
  if text.length() < 2 || !text.has_prefix("{") || !text.has_suffix("}") {
    raise Conversion("array braces or multiple dimensions")
  }
  if text.length() == 2 {
    return []
  }
  let values : Array[Cell] = []
  let value = StringBuilder()
  let mut quoted = false
  let mut escaped = false
  let mut was_quoted = false
  for ch in text[1:text.length() - 1].iter() {
    if escaped {
      value.write_char(ch)
      escaped = false
      continue
    }
    match ch {
      '\\' => escaped = true
      '"' => {
        quoted = !quoted
        was_quoted = true
      }
      '{' | '}' if !quoted =>
        raise Conversion("multidimensional array unsupported")
      ',' if !quoted => {
        let item = value.to_string()
        values.push(
          if !was_quoted && item.to_upper() == "NULL" {
            SqlNull
          } else {
            scalar_cell(element, item)
          },
        )
        value.reset()
        was_quoted = false
      }
      _ => value.write_char(ch)
    }
  }
  if quoted || escaped {
    raise Conversion("unterminated array quote or escape")
  }
  let item = value.to_string()
  values.push(
    if !was_quoted && item.to_upper() == "NULL" {
      SqlNull
    } else {
      scalar_cell(element, item)
    },
  )
  ReadOnlyArray::from_array(values)
}