pgwire/messages/
data.rs

1use bytes::{Buf, BufMut, BytesMut};
2
3use super::{codec, DecodeContext, Message};
4use crate::error::PgWireResult;
5
6pub const FORMAT_CODE_TEXT: i16 = 0;
7pub const FORMAT_CODE_BINARY: i16 = 1;
8
9#[non_exhaustive]
10#[derive(PartialEq, Eq, Debug, Default, new)]
11pub struct FieldDescription {
12    // the field name
13    pub name: String,
14    // the object ID of table, default to 0 if not a table
15    pub table_id: i32,
16    // the attribute number of the column, default to 0 if not a column from table
17    pub column_id: i16,
18    // the object ID of the data type
19    pub type_id: u32,
20    // the size of data type, negative values denote variable-width types
21    pub type_size: i16,
22    // the type modifier
23    pub type_modifier: i32,
24    // the format code being used for the filed, will be 0 or 1 for now
25    pub format_code: i16,
26}
27
28#[non_exhaustive]
29#[derive(PartialEq, Eq, Debug, Default, new)]
30pub struct RowDescription {
31    pub fields: Vec<FieldDescription>,
32}
33
34pub const MESSAGE_TYPE_BYTE_ROW_DESCRITION: u8 = b'T';
35
36impl Message for RowDescription {
37    #[inline]
38    fn message_type() -> Option<u8> {
39        Some(MESSAGE_TYPE_BYTE_ROW_DESCRITION)
40    }
41
42    #[inline]
43    fn max_message_length() -> usize {
44        super::LONG_BACKEND_PACKET_SIZE_LIMIT
45    }
46
47    fn message_length(&self) -> usize {
48        4 + 2
49            + self
50                .fields
51                .iter()
52                .map(|f| f.name.len() + 1 + 4 + 2 + 4 + 2 + 4 + 2)
53                .sum::<usize>()
54    }
55
56    fn encode_body(&self, buf: &mut BytesMut) -> PgWireResult<()> {
57        buf.put_i16(self.fields.len() as i16);
58
59        for field in &self.fields {
60            codec::put_cstring(buf, &field.name);
61            buf.put_i32(field.table_id);
62            buf.put_i16(field.column_id);
63            buf.put_u32(field.type_id);
64            buf.put_i16(field.type_size);
65            buf.put_i32(field.type_modifier);
66            buf.put_i16(field.format_code);
67        }
68
69        Ok(())
70    }
71
72    fn decode_body(buf: &mut BytesMut, _: usize, _ctx: &DecodeContext) -> PgWireResult<Self> {
73        let fields_len = buf.get_i16();
74        let mut fields = Vec::with_capacity(fields_len as usize);
75
76        for _ in 0..fields_len {
77            let field = FieldDescription {
78                name: codec::get_cstring(buf).unwrap_or_else(|| "".to_owned()),
79                table_id: buf.get_i32(),
80                column_id: buf.get_i16(),
81                type_id: buf.get_u32(),
82                type_size: buf.get_i16(),
83                type_modifier: buf.get_i32(),
84                format_code: buf.get_i16(),
85            };
86
87            fields.push(field);
88        }
89
90        Ok(RowDescription { fields })
91    }
92}
93
94/// Data structure returned when frontend describes a statement
95#[non_exhaustive]
96#[derive(PartialEq, Eq, Debug, Default, new, Clone)]
97pub struct ParameterDescription {
98    /// parameter types
99    pub types: Vec<u32>,
100}
101
102pub const MESSAGE_TYPE_BYTE_PARAMETER_DESCRITION: u8 = b't';
103
104impl Message for ParameterDescription {
105    #[inline]
106    fn message_type() -> Option<u8> {
107        Some(MESSAGE_TYPE_BYTE_PARAMETER_DESCRITION)
108    }
109
110    #[inline]
111    fn max_message_length() -> usize {
112        super::SMALL_BACKEND_PACKET_SIZE_LIMIT
113    }
114
115    fn message_length(&self) -> usize {
116        4 + 2 + self.types.len() * 4
117    }
118
119    fn encode_body(&self, buf: &mut BytesMut) -> PgWireResult<()> {
120        buf.put_u16(self.types.len() as u16);
121
122        for t in &self.types {
123            buf.put_i32(*t as i32);
124        }
125
126        Ok(())
127    }
128
129    fn decode_body(buf: &mut BytesMut, _: usize, _ctx: &DecodeContext) -> PgWireResult<Self> {
130        let types_len = buf.get_u16();
131        let mut types = Vec::with_capacity(types_len as usize);
132
133        for _ in 0..types_len {
134            types.push(buf.get_i32() as u32);
135        }
136
137        Ok(ParameterDescription { types })
138    }
139}
140
141/// Data structure for postgresql wire protocol `DataRow` message.
142///
143/// Data can be represented as text or binary format as specified by format
144/// codes from previous `RowDescription` message.
145#[non_exhaustive]
146#[derive(PartialEq, Eq, Debug, Default, new, Clone)]
147pub struct DataRow {
148    pub data: BytesMut,
149    pub field_count: i16,
150}
151
152impl DataRow {}
153
154pub const MESSAGE_TYPE_BYTE_DATA_ROW: u8 = b'D';
155
156impl Message for DataRow {
157    #[inline]
158    fn message_type() -> Option<u8> {
159        Some(MESSAGE_TYPE_BYTE_DATA_ROW)
160    }
161
162    #[inline]
163    fn max_message_length() -> usize {
164        super::LONG_BACKEND_PACKET_SIZE_LIMIT
165    }
166
167    fn message_length(&self) -> usize {
168        4 + 2 + self.data.len()
169    }
170
171    fn encode_body(&self, buf: &mut BytesMut) -> PgWireResult<()> {
172        buf.put_i16(self.field_count);
173        buf.reserve(self.data.len());
174        buf.put_slice(&self.data);
175
176        Ok(())
177    }
178
179    fn decode_body(buf: &mut BytesMut, msg_len: usize, _ctx: &DecodeContext) -> PgWireResult<Self> {
180        let field_count = buf.get_i16();
181        // get body size from packet
182        let data = buf.split_to(msg_len - 4 - 2);
183
184        Ok(DataRow { data, field_count })
185    }
186}
187
188/// postgres response when query returns no data, sent from backend to frontend
189/// in extended query
190#[non_exhaustive]
191#[derive(PartialEq, Eq, Debug, Default, new)]
192pub struct NoData;
193
194pub const MESSAGE_TYPE_BYTE_NO_DATA: u8 = b'n';
195
196impl Message for NoData {
197    #[inline]
198    fn message_type() -> Option<u8> {
199        Some(MESSAGE_TYPE_BYTE_NO_DATA)
200    }
201
202    #[inline]
203    fn max_message_length() -> usize {
204        super::SMALL_BACKEND_PACKET_SIZE_LIMIT
205    }
206
207    fn message_length(&self) -> usize {
208        4
209    }
210
211    fn encode_body(&self, _buf: &mut BytesMut) -> PgWireResult<()> {
212        Ok(())
213    }
214
215    fn decode_body(_buf: &mut BytesMut, _: usize, _ctx: &DecodeContext) -> PgWireResult<Self> {
216        Ok(NoData::new())
217    }
218}