Skip to main content

fraiseql_wire/protocol/
message.rs

1//! Protocol message types
2
3use bytes::Bytes;
4
5/// Frontend message (client → server)
6#[derive(Debug, Clone)]
7#[non_exhaustive]
8pub enum FrontendMessage {
9    /// Startup message
10    Startup {
11        /// Protocol version
12        version: i32,
13        /// Connection parameters
14        params: Vec<(String, String)>,
15    },
16
17    /// Password message
18    Password(String),
19
20    /// Query message
21    Query(String),
22
23    /// Terminate message
24    Terminate,
25
26    /// SASL initial response message
27    SaslInitialResponse {
28        /// SASL mechanism name (e.g., "SCRAM-SHA-256")
29        mechanism: String,
30        /// SASL client first message data
31        data: Vec<u8>,
32    },
33
34    /// SASL response message
35    SaslResponse {
36        /// SASL client final message data
37        data: Vec<u8>,
38    },
39}
40
41/// Backend message (server → client)
42#[derive(Debug, Clone)]
43#[non_exhaustive]
44pub enum BackendMessage {
45    /// Authentication request
46    Authentication(AuthenticationMessage),
47
48    /// Backend key data (for cancellation)
49    BackendKeyData {
50        /// Process ID
51        process_id: i32,
52        /// Secret key
53        secret_key: i32,
54    },
55
56    /// Command complete
57    CommandComplete(String),
58
59    /// Data row
60    DataRow(Vec<Option<Bytes>>),
61
62    /// Error response
63    ErrorResponse(ErrorFields),
64
65    /// Notice response
66    NoticeResponse(ErrorFields),
67
68    /// Parameter status
69    ParameterStatus {
70        /// Parameter name
71        name: String,
72        /// Parameter value
73        value: String,
74    },
75
76    /// Ready for query
77    ReadyForQuery {
78        /// Transaction status
79        status: u8,
80    },
81
82    /// Row description
83    RowDescription(Vec<FieldDescription>),
84}
85
86/// Authentication message types
87#[derive(Debug, Clone)]
88#[non_exhaustive]
89pub enum AuthenticationMessage {
90    /// Authentication OK
91    Ok,
92
93    /// Cleartext password required
94    CleartextPassword,
95
96    /// MD5 password required
97    Md5Password {
98        /// Salt for MD5 hash
99        salt: [u8; 4],
100    },
101
102    /// SASL authentication mechanisms available (Postgres 10+)
103    Sasl {
104        /// List of SASL mechanism names (e.g., ["SCRAM-SHA-256"])
105        mechanisms: Vec<String>,
106    },
107
108    /// SASL continuation message (server challenge)
109    SaslContinue {
110        /// SASL server first/continue message data
111        data: Vec<u8>,
112    },
113
114    /// SASL final message (server verification)
115    SaslFinal {
116        /// SASL server final message data
117        data: Vec<u8>,
118    },
119}
120
121/// Field description (column metadata)
122#[derive(Debug, Clone)]
123pub struct FieldDescription {
124    /// Column name
125    pub name: String,
126    /// Table OID (0 if not a table column)
127    pub table_oid: i32,
128    /// Column attribute number (0 if not a table column)
129    pub column_attr: i16,
130    /// Data type OID
131    pub type_oid: u32,
132    /// Data type size
133    pub type_size: i16,
134    /// Type modifier
135    pub type_modifier: i32,
136    /// Format code (0 = text, 1 = binary)
137    pub format_code: i16,
138}
139
140/// Error/notice fields
141#[derive(Debug, Clone, Default)]
142pub struct ErrorFields {
143    /// Severity (ERROR, WARNING, etc.)
144    pub severity: Option<String>,
145    /// SQLSTATE code
146    pub code: Option<String>,
147    /// Human-readable message
148    pub message: Option<String>,
149    /// Additional detail
150    pub detail: Option<String>,
151    /// Hint
152    pub hint: Option<String>,
153    /// Position in query string
154    pub position: Option<String>,
155}
156
157impl std::fmt::Display for ErrorFields {
158    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159        if let Some(ref msg) = self.message {
160            write!(f, "{}", msg)?;
161        }
162        if let Some(ref code) = self.code {
163            write!(f, " ({})", code)?;
164        }
165        Ok(())
166    }
167}