mysql_connector/connection/packets/
stmt_execute_request.rs

1use {
2    crate::{
3        bitflags::{CursorTypeFlags, StmtExecuteParamFlags, StmtExecuteParamsFlags},
4        connection::{types::NullBitmap, MAX_PAYLOAD_LEN},
5        types::{SimpleValue, Value},
6        Command, Serialize,
7    },
8    bytes::BufMut,
9};
10
11#[derive(Debug)]
12pub struct StmtExecuteRequest<'a, V: SimpleValue> {
13    stmt_id: u32,
14    flags: CursorTypeFlags,
15    iteration_count: u32,
16    bitmap: Vec<u8>,
17    params_flags: StmtExecuteParamsFlags,
18    params: &'a [V],
19    as_long_data: bool,
20}
21
22impl<'a, V: SimpleValue> StmtExecuteRequest<'a, V> {
23    pub fn new(id: u32, params: &'a [V]) -> Self {
24        let mut bitmap = NullBitmap::<true, Vec<u8>>::new(params.len());
25        let meta_len = params.len() * 2;
26
27        let mut data_len = 0;
28        for (i, param) in params.iter().enumerate() {
29            match param.value().bin_len() as usize {
30                0 => bitmap.set(i, true),
31                x => data_len += x,
32            }
33        }
34
35        let total_len = 10 + bitmap.len() + 1 + meta_len + data_len;
36        let as_long_data = total_len > MAX_PAYLOAD_LEN;
37
38        Self {
39            stmt_id: id,
40            flags: CursorTypeFlags::NO_CURSOR,
41            iteration_count: 1,
42            params_flags: StmtExecuteParamsFlags::NEW_PARAMS_BOUND,
43            bitmap: bitmap.into_bytes(),
44            params,
45            as_long_data,
46        }
47    }
48
49    pub fn as_long_data(&self) -> bool {
50        self.as_long_data
51    }
52}
53
54impl<V: SimpleValue> Serialize for StmtExecuteRequest<'_, V> {
55    fn serialize(&self, buf: &mut Vec<u8>) {
56        (Command::StmtExecute as u8).serialize(&mut *buf);
57        self.stmt_id.serialize(&mut *buf);
58        self.flags.serialize(&mut *buf);
59        self.iteration_count.serialize(&mut *buf);
60
61        if !self.params.is_empty() {
62            buf.put_slice(&self.bitmap);
63            self.params_flags.serialize(&mut *buf);
64        }
65
66        for param in self.params {
67            let column_type = param.value().column_type();
68            let flags = if param.value().is_unsigned() {
69                StmtExecuteParamFlags::UNSIGNED
70            } else {
71                StmtExecuteParamFlags::empty()
72            };
73
74            buf.put_slice(&[column_type as u8, flags.bits()]);
75        }
76
77        for param in self.params {
78            match *param.value() {
79                Value::Bytes(_) if !self.as_long_data => param.value().serialize(buf),
80                Value::Bytes(_) | Value::Null => {}
81                _ => param.value().serialize(buf),
82            }
83        }
84    }
85}