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)]
7pub enum FrontendMessage {
8    /// Startup message
9    Startup {
10        /// Protocol version
11        version: i32,
12        /// Connection parameters
13        params: Vec<(String, String)>,
14    },
15
16    /// Password message
17    Password(String),
18
19    /// Query message
20    Query(String),
21
22    /// Terminate message
23    Terminate,
24
25    /// SASL initial response message
26    SaslInitialResponse {
27        /// SASL mechanism name (e.g., "SCRAM-SHA-256")
28        mechanism: String,
29        /// SASL client first message data
30        data: Vec<u8>,
31    },
32
33    /// SASL response message
34    SaslResponse {
35        /// SASL client final message data
36        data: Vec<u8>,
37    },
38
39    /// SSLRequest message (TLS negotiation)
40    SslRequest,
41}
42
43/// Backend message (server → client)
44#[derive(Debug, Clone)]
45pub enum BackendMessage {
46    /// Authentication request
47    Authentication(AuthenticationMessage),
48
49    /// Backend key data (for cancellation)
50    BackendKeyData {
51        /// Process ID
52        process_id: i32,
53        /// Secret key
54        secret_key: i32,
55    },
56
57    /// Command complete
58    CommandComplete(String),
59
60    /// Data row
61    DataRow(Vec<Option<Bytes>>),
62
63    /// Error response
64    ErrorResponse(ErrorFields),
65
66    /// Notice response
67    NoticeResponse(ErrorFields),
68
69    /// Parameter status
70    ParameterStatus {
71        /// Parameter name
72        name: String,
73        /// Parameter value
74        value: String,
75    },
76
77    /// Ready for query
78    ReadyForQuery {
79        /// Transaction status
80        status: u8,
81    },
82
83    /// Row description
84    RowDescription(Vec<FieldDescription>),
85}
86
87/// Authentication message types
88#[derive(Debug, Clone)]
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}