1pub mod auth_response;
4pub mod batch;
5pub mod execute;
6pub mod options;
7pub mod prepare;
8pub mod query;
9pub mod register;
10pub mod startup;
11
12use batch::BatchTypeParseError;
13use thiserror::Error;
14
15use crate::Consistency;
16use crate::frame::protocol_features::ProtocolFeatures;
17use crate::frame::request::execute::ExecuteV2;
18use crate::serialize::row::SerializedValues;
19use bytes::Bytes;
20
21pub use auth_response::AuthResponse;
22pub use batch::Batch;
23#[expect(deprecated)]
24pub use execute::Execute;
25pub use options::Options;
26pub use prepare::Prepare;
27pub use query::Query;
28pub use startup::Startup;
29
30use self::batch::BatchStatement;
31
32use super::TryFromPrimitiveError;
33use super::frame_errors::{CqlRequestSerializationError, LowLevelDeserializationError};
34use super::types::SerialConsistency;
35
36pub use scylla_cql_core::frame::request::CqlRequestKind;
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
41#[repr(u8)]
42pub enum RequestOpcode {
43 Startup = 0x01,
45 Options = 0x05,
47 Query = 0x07,
49 Prepare = 0x09,
51 Execute = 0x0A,
53 Register = 0x0B,
55 Batch = 0x0D,
57 AuthResponse = 0x0F,
59}
60
61impl TryFrom<u8> for RequestOpcode {
62 type Error = TryFromPrimitiveError<u8>;
63
64 fn try_from(value: u8) -> Result<Self, Self::Error> {
65 match value {
66 0x01 => Ok(Self::Startup),
67 0x05 => Ok(Self::Options),
68 0x07 => Ok(Self::Query),
69 0x09 => Ok(Self::Prepare),
70 0x0A => Ok(Self::Execute),
71 0x0B => Ok(Self::Register),
72 0x0D => Ok(Self::Batch),
73 0x0F => Ok(Self::AuthResponse),
74 _ => Err(TryFromPrimitiveError::new("RequestOpcode", value)),
75 }
76 }
77}
78
79pub trait SerializableRequest {
81 const OPCODE: RequestOpcode;
83
84 fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), CqlRequestSerializationError>;
86
87 fn to_bytes(&self) -> Result<Bytes, CqlRequestSerializationError> {
89 let mut v = Vec::new();
90 self.serialize(&mut v)?;
91 Ok(v.into())
92 }
93}
94
95pub trait DeserializableRequest: SerializableRequest + Sized {
100 #[deprecated(since = "1.4.0", note = "Use deserialize_with_features instead")]
104 fn deserialize(buf: &mut &[u8]) -> Result<Self, RequestDeserializationError>;
105
106 fn deserialize_with_features(
107 buf: &mut &[u8],
108 #[allow(unused_variables)] features: &ProtocolFeatures,
109 ) -> Result<Self, RequestDeserializationError> {
110 #[expect(deprecated)]
111 Self::deserialize(buf)
112 }
113}
114
115#[doc(hidden)]
119#[derive(Debug, Error)]
120pub enum RequestDeserializationError {
121 #[error("Low level deser error: {0}")]
122 LowLevelDeserialization(#[from] LowLevelDeserializationError),
123 #[error("Io error: {0}")]
124 IoError(#[from] std::io::Error),
125 #[error("Specified flags are not recognised: {:02x}", flags)]
126 UnknownFlags { flags: u8 },
127 #[error("Named values in frame are currently unsupported")]
128 NamedValuesUnsupported,
129 #[error("Expected SerialConsistency, got regular Consistency: {0}")]
130 ExpectedSerialConsistency(Consistency),
131 #[error(transparent)]
132 BatchTypeParse(#[from] BatchTypeParseError),
133 #[error("Unexpected batch statement kind: {0}")]
134 UnexpectedBatchStatementKind(u8),
135}
136
137#[non_exhaustive] #[deprecated(
140 since = "1.4.0",
141 note = "Does not support Scylla metadata id extension. Use RequestV2 instead."
142)]
143pub enum Request<'r> {
144 Query(Query<'r>),
146 #[expect(deprecated)]
148 Execute(Execute<'r>),
149 Batch(Batch<'r, BatchStatement<'r>, Vec<SerializedValues>>),
152}
153
154#[expect(deprecated)]
155impl Request<'_> {
156 pub fn deserialize(
158 buf: &mut &[u8],
159 opcode: RequestOpcode,
160 ) -> Result<Self, RequestDeserializationError> {
161 match opcode {
162 RequestOpcode::Query => Query::deserialize(buf).map(Self::Query),
163 RequestOpcode::Execute => Execute::deserialize(buf).map(Self::Execute),
164 RequestOpcode::Batch => Batch::deserialize(buf).map(Self::Batch),
165 _ => unimplemented!(
166 "Deserialization of opcode {:?} is not yet supported",
167 opcode
168 ),
169 }
170 }
171
172 pub fn get_consistency(&self) -> Option<Consistency> {
174 match self {
175 Request::Query(q) => Some(q.parameters.consistency),
176 Request::Execute(e) => Some(e.parameters.consistency),
177 Request::Batch(b) => Some(b.consistency),
178 #[expect(unreachable_patterns)] _ => None,
180 }
181 }
182
183 pub fn get_serial_consistency(&self) -> Option<Option<SerialConsistency>> {
185 match self {
186 Request::Query(q) => Some(q.parameters.serial_consistency),
187 Request::Execute(e) => Some(e.parameters.serial_consistency),
188 Request::Batch(b) => Some(b.serial_consistency),
189 #[expect(unreachable_patterns)] _ => None,
191 }
192 }
193}
194
195#[non_exhaustive] pub enum RequestV2<'r> {
198 Query(Query<'r>),
200 Execute(ExecuteV2<'r>),
202 Batch(Batch<'r, BatchStatement<'r>, Vec<SerializedValues>>),
205}
206
207impl RequestV2<'_> {
208 pub fn deserialize(
210 buf: &mut &[u8],
211 opcode: RequestOpcode,
212 features: &ProtocolFeatures,
213 ) -> Result<Self, RequestDeserializationError> {
214 match opcode {
215 RequestOpcode::Query => {
216 Query::deserialize_with_features(buf, features).map(Self::Query)
217 }
218 RequestOpcode::Execute => {
219 ExecuteV2::deserialize_with_features(buf, features).map(Self::Execute)
220 }
221 RequestOpcode::Batch => {
222 Batch::deserialize_with_features(buf, features).map(Self::Batch)
223 }
224 _ => unimplemented!(
225 "Deserialization of opcode {:?} is not yet supported",
226 opcode
227 ),
228 }
229 }
230
231 pub fn get_consistency(&self) -> Option<Consistency> {
233 match self {
234 Self::Query(q) => Some(q.parameters.consistency),
235 Self::Execute(e) => Some(e.parameters.consistency),
236 Self::Batch(b) => Some(b.consistency),
237 #[expect(unreachable_patterns)] _ => None,
239 }
240 }
241
242 pub fn get_serial_consistency(&self) -> Option<Option<SerialConsistency>> {
244 match self {
245 Self::Query(q) => Some(q.parameters.serial_consistency),
246 Self::Execute(e) => Some(e.parameters.serial_consistency),
247 Self::Batch(b) => Some(b.serial_consistency),
248 #[expect(unreachable_patterns)] _ => None,
250 }
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use std::{borrow::Cow, ops::Deref};
257
258 use bytes::Bytes;
259
260 use super::query::PagingState;
261 use crate::Consistency;
262 use crate::frame::protocol_features::ProtocolFeatures;
263 use crate::frame::request::batch::{Batch, BatchStatement, BatchType};
264 #[expect(deprecated)]
265 use crate::frame::request::execute::Execute;
266 use crate::frame::request::execute::ExecuteV2;
267 use crate::frame::request::query::{Query, QueryParameters};
268 use crate::frame::request::{DeserializableRequest, SerializableRequest};
269 use crate::frame::response::result::{ColumnType, NativeType};
270 use crate::frame::types::{self, SerialConsistency};
271 use crate::serialize::row::SerializedValues;
272
273 #[test]
274 fn request_ser_de_identity() {
275 let contents = Cow::Borrowed("SELECT host_id from system.peers");
277 let parameters = QueryParameters {
278 consistency: Consistency::All,
279 serial_consistency: Some(SerialConsistency::Serial),
280 timestamp: None,
281 page_size: Some(323),
282 paging_state: PagingState::new_from_raw_bytes(&[2_u8, 1, 3, 7] as &[u8]),
283 skip_metadata: false,
284 values: {
285 let mut vals = SerializedValues::new();
286 vals.add_value(&2137, &ColumnType::Native(NativeType::Int))
287 .unwrap();
288 Cow::Owned(vals)
289 },
290 };
291 let query = Query {
292 contents,
293 parameters,
294 };
295
296 {
297 let mut buf = Vec::new();
298 query.serialize(&mut buf).unwrap();
299
300 let query_deserialized =
301 Query::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap();
302 assert_eq!(&query_deserialized, &query);
303 }
304
305 let id: Bytes = vec![2, 4, 5, 2, 6, 7, 3, 1].into();
307 let parameters = QueryParameters {
308 consistency: Consistency::Any,
309 serial_consistency: None,
310 timestamp: Some(3423434),
311 page_size: None,
312 paging_state: PagingState::start(),
313 skip_metadata: false,
314 values: {
315 let mut vals = SerializedValues::new();
316 vals.add_value(&42, &ColumnType::Native(NativeType::Int))
317 .unwrap();
318 vals.add_value(&2137, &ColumnType::Native(NativeType::Int))
319 .unwrap();
320 Cow::Owned(vals)
321 },
322 };
323
324 #[expect(deprecated)]
325 let execute = Execute {
326 id,
327 parameters: parameters.clone(),
328 };
329 {
330 let mut buf = Vec::new();
331 execute.serialize(&mut buf).unwrap();
332
333 #[expect(deprecated)]
334 let execute_deserialized =
335 Execute::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap();
336 assert_eq!(&execute_deserialized, &execute);
337 }
338
339 let id = [2, 4, 5, 2, 6, 7, 3, 1].as_slice().into();
341 let result_metadata_id = Some([2, 4, 5, 2, 6, 7, 3, 1].as_slice().into());
342 let execute_with_id = ExecuteV2 {
343 id,
344 result_metadata_id,
345 parameters,
346 tablet_version_block: None,
347 };
348 {
349 let mut buf = Vec::new();
350 execute_with_id.serialize(&mut buf).unwrap();
351
352 let features = {
353 let mut default = ProtocolFeatures::default();
354 default.scylla_metadata_id_supported = true;
355 default
356 };
357 let execute_deserialized =
358 ExecuteV2::deserialize_with_features(&mut &buf[..], &features).unwrap();
359 assert_eq!(&execute_deserialized, &execute_with_id);
360 }
361
362 let statements = vec![
364 BatchStatement::Query {
365 text: query.contents,
366 },
367 BatchStatement::Prepared {
368 id: Cow::Borrowed(execute_with_id.id.as_ref()),
369 },
370 ];
371 let batch = Batch {
372 statements: Cow::Owned(statements),
373 batch_type: BatchType::Logged,
374 consistency: Consistency::EachQuorum,
375 serial_consistency: Some(SerialConsistency::LocalSerial),
376 timestamp: Some(32432),
377
378 values: vec![
380 query.parameters.values.deref().clone(),
381 query.parameters.values.deref().clone(),
382 ],
383 };
384 {
385 let mut buf = Vec::new();
386 batch.serialize(&mut buf).unwrap();
387
388 let batch_deserialized =
389 Batch::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap();
390 assert_eq!(&batch_deserialized, &batch);
391 }
392 }
393
394 #[test]
395 fn deser_rejects_unknown_flags() {
396 let contents = Cow::Borrowed("SELECT host_id from system.peers");
398 let parameters = QueryParameters {
399 consistency: Default::default(),
400 serial_consistency: Some(SerialConsistency::LocalSerial),
401 timestamp: None,
402 page_size: None,
403 paging_state: PagingState::start(),
404 skip_metadata: false,
405 values: Cow::Borrowed(SerializedValues::EMPTY),
406 };
407 let query = Query {
408 contents: contents.clone(),
409 parameters,
410 };
411
412 {
413 let mut buf = Vec::new();
414 query.serialize(&mut buf).unwrap();
415
416 let query_deserialized =
418 Query::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap();
419 assert_eq!(&query_deserialized.contents, &query.contents);
420 assert_eq!(&query_deserialized.parameters, &query.parameters);
421
422 let mut buf_ptr = buf.as_slice();
425 let serialised_contents = types::read_long_string(&mut buf_ptr).unwrap();
426 assert_eq!(serialised_contents, contents);
427
428 let consistency = types::read_consistency(&mut buf_ptr).unwrap();
430 assert_eq!(consistency, Consistency::default());
431
432 let flags_idx = buf.len() - buf_ptr.len();
434 let flags_mut = &mut buf[flags_idx];
435
436 *flags_mut |= 0x80;
438
439 let _parse_error =
442 Query::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap_err();
443 }
444
445 let statements = vec![BatchStatement::Query {
447 text: query.contents,
448 }];
449 let batch = Batch {
450 statements: Cow::Owned(statements),
451 batch_type: BatchType::Logged,
452 consistency: Consistency::EachQuorum,
453 serial_consistency: None,
454 timestamp: None,
455
456 values: vec![query.parameters.values.deref().clone()],
457 };
458 {
459 let mut buf = Vec::new();
460 batch.serialize(&mut buf).unwrap();
461
462 let batch_deserialized =
464 Batch::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap();
465 assert_eq!(batch, batch_deserialized);
466
467 let buf_len = buf.len();
470 let flags_mut = &mut buf[buf_len - 1];
471 *flags_mut |= 0x80;
473
474 let _parse_error =
477 Batch::deserialize_with_features(&mut &buf[..], &Default::default()).unwrap_err();
478 }
479 }
480}