mysql_connector/connection/packets/
stmt_execute_request.rs1use {
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}