mz_pgwire/
message.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use enum_kinds::EnumKind;
11use itertools::Itertools;
12use mz_adapter::session::TransactionCode;
13use mz_pgwire_common::ErrorResponse;
14use mz_repr::{ColumnName, RelationDesc};
15
16/// Internal representation of a backend [message]
17///
18/// [message]: https://www.postgresql.org/docs/11/protocol-message-formats.html
19#[derive(Debug, EnumKind)]
20#[enum_kind(BackendMessageKind)]
21pub enum BackendMessage {
22    AuthenticationOk,
23    AuthenticationCleartextPassword,
24    AuthenticationSASL,
25    AuthenticationSASLContinue(SASLServerFirstMessage),
26    AuthenticationSASLFinal(SASLServerFinalMessage),
27    CommandComplete {
28        tag: String,
29    },
30    EmptyQueryResponse,
31    ReadyForQuery(TransactionCode),
32    RowDescription(Vec<FieldDescription>),
33    DataRow(Vec<Option<mz_pgrepr::Value>>),
34    ParameterStatus(&'static str, String),
35    BackendKeyData {
36        conn_id: u32,
37        secret_key: u32,
38    },
39    ParameterDescription(Vec<mz_pgrepr::Type>),
40    PortalSuspended,
41    NoData,
42    ParseComplete,
43    BindComplete,
44    CloseComplete,
45    ErrorResponse(ErrorResponse),
46    CopyInResponse {
47        overall_format: mz_pgwire_common::Format,
48        column_formats: Vec<mz_pgwire_common::Format>,
49    },
50    CopyOutResponse {
51        overall_format: mz_pgwire_common::Format,
52        column_formats: Vec<mz_pgwire_common::Format>,
53    },
54    CopyData(Vec<u8>),
55    CopyDone,
56}
57
58impl From<ErrorResponse> for BackendMessage {
59    fn from(err: ErrorResponse) -> BackendMessage {
60        BackendMessage::ErrorResponse(err)
61    }
62}
63
64#[derive(Debug)]
65pub struct SASLServerFirstMessage {
66    pub iteration_count: usize,
67    pub nonce: String,
68    pub salt: String,
69}
70
71#[derive(Debug)]
72pub struct FieldDescription {
73    pub name: ColumnName,
74    pub table_id: u32,
75    pub column_id: u16,
76    pub type_oid: u32,
77    pub type_len: i16,
78    pub type_mod: i32,
79    pub format: mz_pgwire_common::Format,
80}
81
82#[derive(Debug)]
83pub enum SASLServerFinalMessageKinds {
84    Verifier(String),
85    // The spec specifies an Error kind here but PG just uses
86    // its own error handling
87}
88
89#[derive(Debug)]
90pub struct SASLServerFinalMessage {
91    pub kind: SASLServerFinalMessageKinds,
92    pub extensions: Vec<String>,
93}
94
95pub fn encode_row_description(
96    desc: &RelationDesc,
97    formats: &[mz_pgwire_common::Format],
98) -> Vec<FieldDescription> {
99    desc.iter()
100        .zip_eq(formats)
101        .map(|((name, typ), format)| {
102            let pg_type = mz_pgrepr::Type::from(&typ.scalar_type);
103            FieldDescription {
104                name: name.clone(),
105                table_id: 0,
106                column_id: 0,
107                type_oid: pg_type.oid(),
108                type_len: pg_type.typlen(),
109                type_mod: pg_type.typmod(),
110                format: *format,
111            }
112        })
113        .collect()
114}