1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use {
    crate::{
        bitflags::{CursorTypeFlags, StmtExecuteParamFlags, StmtExecuteParamsFlags},
        connection::{types::NullBitmap, MAX_PAYLOAD_LEN},
        types::{SimpleValue, Value},
        Command, Serialize,
    },
    bytes::BufMut,
};

#[derive(Debug)]
pub struct StmtExecuteRequest<'a, V: SimpleValue> {
    stmt_id: u32,
    flags: CursorTypeFlags,
    iteration_count: u32,
    bitmap: Vec<u8>,
    params_flags: StmtExecuteParamsFlags,
    params: &'a [V],
    as_long_data: bool,
}

impl<'a, V: SimpleValue> StmtExecuteRequest<'a, V> {
    pub fn new(id: u32, params: &'a [V]) -> Self {
        let mut bitmap = NullBitmap::<true, Vec<u8>>::new(params.len());
        let meta_len = params.len() * 2;

        let mut data_len = 0;
        for (i, param) in params.iter().enumerate() {
            match param.value().bin_len() as usize {
                0 => bitmap.set(i, true),
                x => data_len += x,
            }
        }

        let total_len = 10 + bitmap.len() + 1 + meta_len + data_len;
        let as_long_data = total_len > MAX_PAYLOAD_LEN;

        Self {
            stmt_id: id,
            flags: CursorTypeFlags::NO_CURSOR,
            iteration_count: 1,
            params_flags: StmtExecuteParamsFlags::NEW_PARAMS_BOUND,
            bitmap: bitmap.into_bytes(),
            params,
            as_long_data,
        }
    }

    pub fn as_long_data(&self) -> bool {
        self.as_long_data
    }
}

impl<V: SimpleValue> Serialize for StmtExecuteRequest<'_, V> {
    fn serialize(&self, buf: &mut Vec<u8>) {
        (Command::StmtExecute as u8).serialize(&mut *buf);
        self.stmt_id.serialize(&mut *buf);
        self.flags.serialize(&mut *buf);
        self.iteration_count.serialize(&mut *buf);

        if !self.params.is_empty() {
            buf.put_slice(&self.bitmap);
            self.params_flags.serialize(&mut *buf);
        }

        for param in self.params {
            let column_type = param.value().column_type();
            let flags = if param.value().is_unsigned() {
                StmtExecuteParamFlags::UNSIGNED
            } else {
                StmtExecuteParamFlags::empty()
            };

            buf.put_slice(&[column_type as u8, flags.bits()]);
        }

        for param in self.params {
            match *param.value() {
                Value::Bytes(_) if !self.as_long_data => param.value().serialize(buf),
                Value::Bytes(_) | Value::Null => {}
                _ => param.value().serialize(buf),
            }
        }
    }
}