sqlx_core_oldapi/mssql/
arguments.rs1use crate::arguments::Arguments;
2use crate::encode::Encode;
3use crate::mssql::database::Mssql;
4use crate::mssql::io::MssqlBufMutExt;
5use crate::mssql::protocol::rpc::StatusFlags;
6use crate::types::Type;
7use std::fmt::{self, Write};
8
9#[derive(Default, Clone)]
10pub struct MssqlArguments {
11 pub(crate) ordinal: usize,
13 name: String,
15 pub(crate) data: Vec<u8>,
16 pub(crate) declarations: String,
17}
18
19impl MssqlArguments {
20 pub(crate) fn add_named<'q, T: Encode<'q, Mssql> + Type<Mssql>>(
21 &mut self,
22 name: &str,
23 value: T,
24 ) {
25 let ty = value.produces().unwrap_or_else(T::type_info);
26
27 let mut ty_name = String::new();
28 ty.0.fmt(&mut ty_name);
29
30 self.data.put_b_varchar(name); self.data.push(0); ty.0.put(&mut self.data); ty.0.put_value(&mut self.data, value); }
36
37 pub(crate) fn add_unnamed<'q, T: Encode<'q, Mssql> + Type<Mssql>>(&mut self, value: T) {
38 self.add_named("", value);
39 }
40
41 pub(crate) fn declare<'q, T: Encode<'q, Mssql> + Type<Mssql>>(
42 &mut self,
43 name: &str,
44 initial_value: T,
45 ) {
46 let ty = initial_value.produces().unwrap_or_else(T::type_info);
47
48 let mut ty_name = String::new();
49 ty.0.fmt(&mut ty_name);
50
51 self.data.put_b_varchar(name); self.data.push(StatusFlags::BY_REF_VALUE.bits()); ty.0.put(&mut self.data); ty.0.put_value(&mut self.data, initial_value); }
57
58 pub(crate) fn append(&mut self, arguments: &mut MssqlArguments) {
59 self.ordinal += arguments.ordinal;
60 self.data.append(&mut arguments.data);
61 }
62
63 pub(crate) fn add<'q, T>(&mut self, value: T)
64 where
65 T: Encode<'q, Mssql> + Type<Mssql>,
66 {
67 let ty = value.produces().unwrap_or_else(T::type_info);
68 let declaration_ty = if ty.0.is_null() {
71 T::type_info()
72 } else {
73 ty.clone()
74 };
75
76 self.name.clear();
80 self.name.push_str("@p");
81
82 self.ordinal += 1;
83 self.name.push_str(itoa::Buffer::new().format(self.ordinal));
84
85 let MssqlArguments {
86 ref name,
87 ref mut declarations,
88 ref mut data,
89 ..
90 } = self;
91
92 if !declarations.is_empty() {
96 declarations.push(',');
97 }
98
99 declarations.push_str(name);
100 declarations.push(' ');
101 declaration_ty.0.fmt(declarations);
102
103 data.put_b_varchar(name); data.push(0); ty.0.put(data); ty.0.put_value(data, value); }
111}
112
113impl<'q> Arguments<'q> for MssqlArguments {
114 type Database = Mssql;
115
116 fn reserve(&mut self, _additional: usize, size: usize) {
117 self.data.reserve(size + 10); }
119
120 fn add<T>(&mut self, value: T)
121 where
122 T: 'q + Encode<'q, Self::Database> + Type<Mssql>,
123 {
124 self.add(value)
125 }
126
127 fn format_placeholder<W: Write>(&self, writer: &mut W) -> fmt::Result {
128 writer.write_str("@p")?;
132 writer.write_str(itoa::Buffer::new().format(self.ordinal))
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use crate::query_builder::QueryBuilder;
140
141 #[test]
142 fn test_format_placeholder_method() {
143 let mut args = MssqlArguments::default(); let mut buffer = String::new();
145
146 args.add(123i32); args.format_placeholder(&mut buffer).unwrap(); assert_eq!(buffer, "@p1");
154
155 buffer.clear();
156
157 args.add("test_val".to_string()); args.format_placeholder(&mut buffer).unwrap(); assert_eq!(buffer, "@p2");
161 }
162
163 #[test]
164 fn test_query_builder_with_mssql_placeholders() {
165 let id = 100;
167 let mut builder = QueryBuilder::<Mssql>::new("SELECT * FROM table ");
168 builder
169 .push("WHERE id=")
170 .push_bind(id)
171 .push(" AND name=")
172 .push_bind("test");
173 let sql = builder.sql(); assert_eq!(sql, "SELECT * FROM table WHERE id=@p1 AND name=@p2");
176 }
177}