cassandra_protocol/query/
query_params.rs

1use std::collections::HashMap;
2use std::io::Cursor;
3
4use crate::consistency::Consistency;
5use crate::frame::traits::FromCursor;
6use crate::frame::{Serialize, Version};
7use crate::query::query_flags::QueryFlags;
8use crate::query::query_values::QueryValues;
9use crate::types::{from_cursor_str, serialize_str, value::Value, CInt, CIntShort};
10use crate::types::{CBytes, CLong};
11use crate::Error;
12
13/// Parameters of Query for query operation.
14#[derive(Debug, Default, Clone, PartialEq, Eq)]
15pub struct QueryParams {
16    /// Cassandra consistency level.
17    pub consistency: Consistency,
18    /// Were values provided with names
19    pub with_names: bool,
20    /// Array of values.
21    pub values: Option<QueryValues>,
22    /// Page size.
23    pub page_size: Option<CInt>,
24    /// Array of bytes which represents paging state.
25    pub paging_state: Option<CBytes>,
26    /// Serial `Consistency`.
27    pub serial_consistency: Option<Consistency>,
28    /// Timestamp.
29    pub timestamp: Option<CLong>,
30    /// Keyspace indicating the keyspace that the query should be executed in. It supersedes the
31    /// keyspace that the connection is bound to, if any.
32    pub keyspace: Option<String>,
33    /// Represents the current time (now) for the query. Affects TTL cell liveness in read queries
34    /// and local deletion time for tombstones and TTL cells in update requests.
35    pub now_in_seconds: Option<CInt>,
36}
37
38impl QueryParams {
39    fn flags(&self) -> QueryFlags {
40        let mut flags = QueryFlags::empty();
41
42        if self.values.is_some() {
43            flags.insert(QueryFlags::VALUE);
44        }
45
46        if self.with_names {
47            flags.insert(QueryFlags::WITH_NAMES_FOR_VALUES);
48        }
49
50        if self.page_size.is_some() {
51            flags.insert(QueryFlags::PAGE_SIZE);
52        }
53
54        if self.paging_state.is_some() {
55            flags.insert(QueryFlags::WITH_PAGING_STATE);
56        }
57
58        if self.serial_consistency.is_some() {
59            flags.insert(QueryFlags::WITH_SERIAL_CONSISTENCY);
60        }
61
62        if self.timestamp.is_some() {
63            flags.insert(QueryFlags::WITH_DEFAULT_TIMESTAMP);
64        }
65
66        if self.keyspace.is_some() {
67            flags.insert(QueryFlags::WITH_KEYSPACE);
68        }
69
70        if self.now_in_seconds.is_some() {
71            flags.insert(QueryFlags::WITH_NOW_IN_SECONDS);
72        }
73
74        flags
75    }
76}
77
78impl Serialize for QueryParams {
79    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
80        let consistency: CIntShort = self.consistency.into();
81        consistency.serialize(cursor, version);
82
83        let flag_bits = self.flags().bits();
84        if version >= Version::V5 {
85            flag_bits.serialize(cursor, version);
86        } else {
87            (flag_bits as u8).serialize(cursor, version);
88        };
89
90        if let Some(values) = &self.values {
91            let len = values.len() as CIntShort;
92            len.serialize(cursor, version);
93            values.serialize(cursor, version);
94        }
95
96        if let Some(page_size) = self.page_size {
97            page_size.serialize(cursor, version);
98        }
99
100        if let Some(paging_state) = &self.paging_state {
101            paging_state.serialize(cursor, version);
102        }
103
104        if let Some(serial_consistency) = self.serial_consistency {
105            let serial_consistency: CIntShort = serial_consistency.into();
106            serial_consistency.serialize(cursor, version);
107        }
108
109        if let Some(timestamp) = self.timestamp {
110            timestamp.serialize(cursor, version);
111        }
112
113        if let Some(keyspace) = &self.keyspace {
114            serialize_str(cursor, keyspace.as_str(), version);
115        }
116
117        if let Some(now_in_seconds) = self.now_in_seconds {
118            now_in_seconds.serialize(cursor, version);
119        }
120    }
121}
122
123impl FromCursor for QueryParams {
124    fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> Result<QueryParams, Error> {
125        let consistency = Consistency::from_cursor(cursor, version)?;
126        let flags = QueryFlags::from_cursor(cursor, version)?;
127
128        let values = if flags.contains(QueryFlags::VALUE) {
129            let number_of_values = CIntShort::from_cursor(cursor, version)?;
130
131            if flags.contains(QueryFlags::WITH_NAMES_FOR_VALUES) {
132                let mut map = HashMap::with_capacity(number_of_values as usize);
133                for _ in 0..number_of_values {
134                    map.insert(
135                        from_cursor_str(cursor)?.to_string(),
136                        Value::from_cursor(cursor, version)?,
137                    );
138                }
139                Some(QueryValues::NamedValues(map))
140            } else {
141                let mut vec = Vec::with_capacity(number_of_values as usize);
142                for _ in 0..number_of_values {
143                    vec.push(Value::from_cursor(cursor, version)?);
144                }
145                Some(QueryValues::SimpleValues(vec))
146            }
147        } else {
148            None
149        };
150
151        let page_size = if flags.contains(QueryFlags::PAGE_SIZE) {
152            Some(CInt::from_cursor(cursor, version)?)
153        } else {
154            None
155        };
156
157        let paging_state = if flags.contains(QueryFlags::WITH_PAGING_STATE) {
158            Some(CBytes::from_cursor(cursor, version)?)
159        } else {
160            None
161        };
162
163        let serial_consistency = if flags.contains(QueryFlags::WITH_SERIAL_CONSISTENCY) {
164            Some(Consistency::from_cursor(cursor, version)?)
165        } else {
166            None
167        };
168
169        let timestamp = if flags.contains(QueryFlags::WITH_DEFAULT_TIMESTAMP) {
170            Some(CLong::from_cursor(cursor, version)?)
171        } else {
172            None
173        };
174
175        let keyspace = if flags.contains(QueryFlags::WITH_KEYSPACE) {
176            Some(from_cursor_str(cursor)?.to_string())
177        } else {
178            None
179        };
180
181        let now_in_seconds = if flags.contains(QueryFlags::WITH_NOW_IN_SECONDS) {
182            Some(CInt::from_cursor(cursor, version)?)
183        } else {
184            None
185        };
186
187        let with_names = flags.contains(QueryFlags::WITH_NAMES_FOR_VALUES);
188
189        Ok(QueryParams {
190            consistency,
191            with_names,
192            values,
193            page_size,
194            paging_state,
195            serial_consistency,
196            timestamp,
197            keyspace,
198            now_in_seconds,
199        })
200    }
201}