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}