1use crate::api::Handle;
2use crate::attr::{Attr, AttrGet, AttrLen, AttrZeroAssert, Void};
3use crate::convert::AsMutSQLPOINTER;
4use crate::env::OdbcVersion;
5use crate::handle::SQLHSTMT;
6use crate::str::{OdbcChar, OdbcStr};
7use crate::{
8 sqlreturn::SQLRETURN, Def, Ident, OdbcDefined, Scalar, SQLCHAR, SQLINTEGER, SQLLEN, SQLPOINTER,
9 SQLSMALLINT, SQLWCHAR,
10};
11use core::mem::MaybeUninit;
12use rs_odbc_derive::{odbc_type, Ident};
13
14pub trait DiagField<H: Handle, D: Ident>: Attr<D> + AttrLen<Self::DefinedBy, SQLSMALLINT> {
15 }
21
22pub const SQLSTATE_SIZE: usize = 5;
23
24#[repr(transparent)]
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub struct SQLSTATE<C: OdbcChar>([C; SQLSTATE_SIZE + 1]);
27impl SQLSTATE<SQLCHAR> {
28 pub fn new(init: &str) -> SQLSTATE<SQLCHAR> {
29 let bytes = init.as_bytes();
30
31 assert_eq!(
32 SQLSTATE_SIZE,
33 bytes.len(),
34 "SQLSTATE({}) len != {}",
35 init,
36 SQLSTATE_SIZE
37 );
38
39 let mut sqlstate = [SQLCHAR::default(); SQLSTATE_SIZE + 1];
40 for (s, i) in sqlstate.iter_mut().zip(bytes.iter()) {
41 *s = *i;
42 }
43
44 Self(sqlstate)
45 }
46}
47impl SQLSTATE<SQLWCHAR> {
48 pub fn new(init: &str) -> SQLSTATE<SQLWCHAR> {
49 let bytes = init.as_bytes();
50
51 assert_eq!(
52 SQLSTATE_SIZE,
53 bytes.len(),
54 "SQLSTATE({}) len != {}",
55 init,
56 SQLSTATE_SIZE
57 );
58
59 let mut sqlstate = [SQLWCHAR::default(); SQLSTATE_SIZE + 1];
60 for (s, i) in sqlstate.iter_mut().zip(bytes.iter()) {
61 *s = *i as u16;
62 }
63
64 Self(sqlstate)
65 }
66}
67unsafe impl<C: OdbcChar> AsMutSQLPOINTER for SQLSTATE<C> {
68 fn as_mut_SQLPOINTER(&mut self) -> SQLPOINTER {
69 (self as *mut Self).cast()
70 }
71}
72unsafe impl<C: OdbcChar> AsMutSQLPOINTER for MaybeUninit<SQLSTATE<C>> {
73 fn as_mut_SQLPOINTER(&mut self) -> SQLPOINTER {
74 self.as_mut_ptr().cast()
75 }
76}
77impl PartialEq<&str> for SQLSTATE<SQLCHAR> {
78 fn eq(&self, other: &&str) -> bool {
79 *self == SQLSTATE::<SQLCHAR>::new(other)
80 }
81}
82impl PartialEq<&str> for SQLSTATE<SQLWCHAR> {
83 fn eq(&self, other: &&str) -> bool {
84 *self == SQLSTATE::<SQLWCHAR>::new(other)
85 }
86}
87impl<'a, C: OdbcChar> PartialEq<SQLSTATE<C>> for &'a str
88where
89 SQLSTATE<C>: PartialEq<&'a str>,
90{
91 fn eq(&self, other: &SQLSTATE<C>) -> bool {
92 other == self
93 }
94}
95impl<C: OdbcChar> AttrZeroAssert for SQLSTATE<C> {
96 }
98unsafe impl<C: OdbcChar> AttrLen<OdbcDefined, SQLSMALLINT> for SQLSTATE<C>
99where
100 MaybeUninit<SQLSTATE<C>>: AttrLen<OdbcDefined, SQLSMALLINT>,
101{
102 type StrLen = Void;
103
104 fn len(&self) -> SQLSMALLINT {
105 <MaybeUninit<SQLSTATE<C>>>::len(unsafe { core::mem::transmute(self) })
107 }
108}
109unsafe impl<AD: Def> AttrLen<AD, SQLSMALLINT> for MaybeUninit<SQLSTATE<SQLCHAR>> {
110 type StrLen = Void;
111
112 fn len(&self) -> SQLSMALLINT {
113 (SQLSTATE_SIZE + 1) as SQLSMALLINT
114 }
115}
116unsafe impl<AD: Def> AttrLen<AD, SQLSMALLINT> for MaybeUninit<SQLSTATE<SQLWCHAR>> {
117 type StrLen = Void;
118
119 fn len(&self) -> SQLSMALLINT {
120 (core::mem::size_of::<SQLWCHAR>() * (SQLSTATE_SIZE + 1)) as SQLSMALLINT
121 }
122}
123
124impl<D: Ident, T: Scalar, H: Handle> DiagField<H, D> for MaybeUninit<T>
126where
127 T: DiagField<H, D> + AttrGet<D>,
128 Self: AttrLen<Self::DefinedBy, SQLSMALLINT>,
129{
130}
131
132impl<D: Ident, T: Scalar, H: Handle> DiagField<H, D> for [MaybeUninit<T>]
133where
134 [T]: DiagField<H, D> + AttrGet<D>,
135 Self: AttrLen<Self::DefinedBy, SQLSMALLINT>,
136{
137}
138
139impl<D: Ident, H: Handle> DiagField<H, D> for OdbcStr<MaybeUninit<SQLCHAR>> where
140 OdbcStr<SQLCHAR>: DiagField<H, D> + AttrGet<D>
141{
142}
143impl<D: Ident, H: Handle> DiagField<H, D> for OdbcStr<MaybeUninit<SQLWCHAR>> where
144 OdbcStr<SQLWCHAR>: DiagField<H, D> + AttrGet<D>
145{
146}
147
148#[derive(Ident)]
156#[identifier(SQLSMALLINT, -1249)]
157#[allow(non_camel_case_types)]
158pub struct SQL_DIAG_CURSOR_ROW_COUNT;
159unsafe impl Attr<SQL_DIAG_CURSOR_ROW_COUNT> for SQLLEN {
160 type DefinedBy = OdbcDefined;
161}
162impl<V: OdbcVersion> DiagField<SQLHSTMT<'_, '_, '_, V>, SQL_DIAG_CURSOR_ROW_COUNT> for SQLLEN {}
163unsafe impl AttrGet<SQL_DIAG_CURSOR_ROW_COUNT> for SQLLEN {}
164
165#[derive(Ident)]
166#[identifier(SQLSMALLINT, 7)]
167#[allow(non_camel_case_types)]
168pub struct SQL_DIAG_DYNAMIC_FUNCTION;
169unsafe impl Attr<SQL_DIAG_DYNAMIC_FUNCTION> for OdbcStr<SQLCHAR> {
170 type DefinedBy = OdbcDefined;
171}
172impl<V: OdbcVersion> DiagField<SQLHSTMT<'_, '_, '_, V>, SQL_DIAG_DYNAMIC_FUNCTION>
173 for OdbcStr<SQLCHAR>
174{
175}
176unsafe impl AttrGet<SQL_DIAG_DYNAMIC_FUNCTION> for OdbcStr<SQLCHAR> {}
177
178#[derive(Ident)]
179#[identifier(SQLSMALLINT, 12)]
180#[allow(non_camel_case_types)]
181pub struct SQL_DIAG_DYNAMIC_FUNCTION_CODE;
182unsafe impl Attr<SQL_DIAG_DYNAMIC_FUNCTION_CODE> for DiagDynamicFunctionCode {
183 type DefinedBy = OdbcDefined;
184}
185impl<V: OdbcVersion> DiagField<SQLHSTMT<'_, '_, '_, V>, SQL_DIAG_DYNAMIC_FUNCTION_CODE>
186 for DiagDynamicFunctionCode
187{
188}
189unsafe impl AttrGet<SQL_DIAG_DYNAMIC_FUNCTION_CODE> for DiagDynamicFunctionCode {}
190
191#[derive(Ident)]
192#[identifier(SQLSMALLINT, 2)]
193#[allow(non_camel_case_types)]
194pub struct SQL_DIAG_NUMBER;
195unsafe impl Attr<SQL_DIAG_NUMBER> for SQLINTEGER {
196 type DefinedBy = OdbcDefined;
197}
198impl<H: Handle> DiagField<H, SQL_DIAG_NUMBER> for SQLINTEGER {}
199unsafe impl AttrGet<SQL_DIAG_NUMBER> for SQLINTEGER {}
200
201#[derive(Ident)]
202#[identifier(SQLSMALLINT, 1)]
203#[allow(non_camel_case_types)]
204pub struct SQL_DIAG_RETURNCODE;
205unsafe impl Attr<SQL_DIAG_RETURNCODE> for SQLRETURN {
206 type DefinedBy = OdbcDefined;
207}
208impl<H: Handle> DiagField<H, SQL_DIAG_RETURNCODE> for SQLRETURN {}
209unsafe impl AttrGet<SQL_DIAG_RETURNCODE> for SQLRETURN {}
210
211#[derive(Ident)]
212#[identifier(SQLSMALLINT, 3)]
213#[allow(non_camel_case_types)]
214pub struct SQL_DIAG_ROW_COUNT;
215unsafe impl Attr<SQL_DIAG_ROW_COUNT> for SQLLEN {
216 type DefinedBy = OdbcDefined;
217}
218impl<V: OdbcVersion> DiagField<SQLHSTMT<'_, '_, '_, V>, SQL_DIAG_ROW_COUNT> for SQLLEN {}
219unsafe impl AttrGet<SQL_DIAG_ROW_COUNT> for SQLLEN {}
220
221#[derive(Ident)]
226#[identifier(SQLSMALLINT, 8)]
227#[allow(non_camel_case_types)]
228pub struct SQL_DIAG_CLASS_ORIGIN;
229unsafe impl Attr<SQL_DIAG_CLASS_ORIGIN> for OdbcStr<SQLCHAR> {
230 type DefinedBy = OdbcDefined;
231}
232impl<H: Handle> DiagField<H, SQL_DIAG_CLASS_ORIGIN> for OdbcStr<SQLCHAR> {}
233unsafe impl AttrGet<SQL_DIAG_CLASS_ORIGIN> for OdbcStr<SQLCHAR> {}
234
235#[derive(Ident)]
236#[identifier(SQLSMALLINT, -1247)]
237#[allow(non_camel_case_types)]
238pub struct SQL_DIAG_COLUMN_NUMBER;
239unsafe impl Attr<SQL_DIAG_COLUMN_NUMBER> for DiagColumnNumber {
240 type DefinedBy = OdbcDefined;
241}
242impl<V: OdbcVersion> DiagField<SQLHSTMT<'_, '_, '_, V>, SQL_DIAG_COLUMN_NUMBER>
243 for DiagColumnNumber
244{
245}
246unsafe impl AttrGet<SQL_DIAG_COLUMN_NUMBER> for DiagColumnNumber {}
247
248#[derive(Ident)]
249#[identifier(SQLSMALLINT, 10)]
250#[allow(non_camel_case_types)]
251pub struct SQL_DIAG_CONNECTION_NAME;
252unsafe impl Attr<SQL_DIAG_CONNECTION_NAME> for OdbcStr<SQLCHAR> {
253 type DefinedBy = OdbcDefined;
254}
255impl<H: Handle> DiagField<H, SQL_DIAG_CONNECTION_NAME> for OdbcStr<SQLCHAR> {}
256unsafe impl AttrGet<SQL_DIAG_CONNECTION_NAME> for OdbcStr<SQLCHAR> {}
257
258#[derive(Ident)]
259#[identifier(SQLSMALLINT, 6)]
260#[allow(non_camel_case_types)]
261pub struct SQL_DIAG_MESSAGE_TEXT;
262unsafe impl Attr<SQL_DIAG_MESSAGE_TEXT> for OdbcStr<SQLCHAR> {
263 type DefinedBy = OdbcDefined;
264}
265impl<H: Handle> DiagField<H, SQL_DIAG_MESSAGE_TEXT> for OdbcStr<SQLCHAR> {}
266unsafe impl AttrGet<SQL_DIAG_MESSAGE_TEXT> for OdbcStr<SQLCHAR> {}
267
268#[derive(Ident)]
269#[identifier(SQLSMALLINT, 5)]
270#[allow(non_camel_case_types)]
271pub struct SQL_DIAG_NATIVE;
272unsafe impl Attr<SQL_DIAG_NATIVE> for SQLINTEGER {
273 type DefinedBy = OdbcDefined;
274}
275impl<H: Handle> DiagField<H, SQL_DIAG_NATIVE> for SQLINTEGER {}
276unsafe impl AttrGet<SQL_DIAG_NATIVE> for SQLINTEGER {}
277
278#[derive(Ident)]
279#[identifier(SQLSMALLINT, -1248)]
280#[allow(non_camel_case_types)]
281pub struct SQL_DIAG_ROW_NUMBER;
282unsafe impl Attr<SQL_DIAG_ROW_NUMBER> for DiagRowNumber {
283 type DefinedBy = OdbcDefined;
284}
285impl<V: OdbcVersion> DiagField<SQLHSTMT<'_, '_, '_, V>, SQL_DIAG_ROW_NUMBER> for DiagRowNumber {}
286unsafe impl AttrGet<SQL_DIAG_ROW_NUMBER> for DiagRowNumber {}
287
288#[derive(Ident)]
289#[identifier(SQLSMALLINT, 11)]
290#[allow(non_camel_case_types)]
291pub struct SQL_DIAG_SERVER_NAME;
292unsafe impl Attr<SQL_DIAG_SERVER_NAME> for OdbcStr<SQLCHAR> {
293 type DefinedBy = OdbcDefined;
294}
295impl<H: Handle> DiagField<H, SQL_DIAG_SERVER_NAME> for OdbcStr<SQLCHAR> {}
296unsafe impl AttrGet<SQL_DIAG_SERVER_NAME> for OdbcStr<SQLCHAR> {}
297
298#[derive(Ident)]
299#[identifier(SQLSMALLINT, 4)]
300#[allow(non_camel_case_types)]
301pub struct SQL_DIAG_SQLSTATE;
302unsafe impl<C: OdbcChar> Attr<SQL_DIAG_SQLSTATE> for SQLSTATE<C> {
303 type DefinedBy = OdbcDefined;
304}
305impl<H: Handle> DiagField<H, SQL_DIAG_SQLSTATE> for SQLSTATE<SQLCHAR> {}
306impl<H: Handle> DiagField<H, SQL_DIAG_SQLSTATE> for SQLSTATE<SQLWCHAR> {}
307unsafe impl<C: OdbcChar> AttrGet<SQL_DIAG_SQLSTATE> for SQLSTATE<C> {}
308
309#[derive(Ident)]
310#[identifier(SQLSMALLINT, 9)]
311#[allow(non_camel_case_types)]
312pub struct SQL_DIAG_SUBCLASS_ORIGIN;
313unsafe impl Attr<SQL_DIAG_SUBCLASS_ORIGIN> for OdbcStr<SQLCHAR> {
314 type DefinedBy = OdbcDefined;
315}
316impl<H: Handle> DiagField<H, SQL_DIAG_SUBCLASS_ORIGIN> for OdbcStr<SQLCHAR> {}
317unsafe impl AttrGet<SQL_DIAG_SUBCLASS_ORIGIN> for OdbcStr<SQLCHAR> {}
318
319#[odbc_type(SQLINTEGER)]
322pub struct DiagDynamicFunctionCode;
323pub const SQL_DIAG_ALTER_DOMAIN: DiagDynamicFunctionCode = DiagDynamicFunctionCode(3);
324pub const SQL_DIAG_ALTER_TABLE: DiagDynamicFunctionCode = DiagDynamicFunctionCode(4);
325pub const SQL_DIAG_CREATE_ASSERTION: DiagDynamicFunctionCode = DiagDynamicFunctionCode(6);
326pub const SQL_DIAG_CREATE_CHARACTER_SET: DiagDynamicFunctionCode = DiagDynamicFunctionCode(8);
327pub const SQL_DIAG_CREATE_COLLATION: DiagDynamicFunctionCode = DiagDynamicFunctionCode(10);
328pub const SQL_DIAG_CREATE_DOMAIN: DiagDynamicFunctionCode = DiagDynamicFunctionCode(23);
329pub const SQL_DIAG_CREATE_INDEX: DiagDynamicFunctionCode = DiagDynamicFunctionCode(-1);
330pub const SQL_DIAG_CREATE_TABLE: DiagDynamicFunctionCode = DiagDynamicFunctionCode(77);
331pub const SQL_DIAG_CREATE_VIEW: DiagDynamicFunctionCode = DiagDynamicFunctionCode(84);
332pub const SQL_DIAG_SELECT_CURSOR: DiagDynamicFunctionCode = DiagDynamicFunctionCode(85);
333pub const SQL_DIAG_DYNAMIC_DELETE_CURSOR: DiagDynamicFunctionCode = DiagDynamicFunctionCode(38);
334pub const SQL_DIAG_DELETE_WHERE: DiagDynamicFunctionCode = DiagDynamicFunctionCode(19);
335pub const SQL_DIAG_DROP_ASSERTION: DiagDynamicFunctionCode = DiagDynamicFunctionCode(24);
336pub const SQL_DIAG_DROP_CHARACTER_SET: DiagDynamicFunctionCode = DiagDynamicFunctionCode(25);
337pub const SQL_DIAG_DROP_COLLATION: DiagDynamicFunctionCode = DiagDynamicFunctionCode(26);
338pub const SQL_DIAG_DROP_DOMAIN: DiagDynamicFunctionCode = DiagDynamicFunctionCode(27);
339pub const SQL_DIAG_DROP_INDEX: DiagDynamicFunctionCode = DiagDynamicFunctionCode(-2);
340pub const SQL_DIAG_DROP_SCHEMA: DiagDynamicFunctionCode = DiagDynamicFunctionCode(31);
341pub const SQL_DIAG_DROP_TABLE: DiagDynamicFunctionCode = DiagDynamicFunctionCode(32);
342pub const SQL_DIAG_DROP_TRANSLATION: DiagDynamicFunctionCode = DiagDynamicFunctionCode(33);
343pub const SQL_DIAG_DROP_VIEW: DiagDynamicFunctionCode = DiagDynamicFunctionCode(36);
344pub const SQL_DIAG_GRANT: DiagDynamicFunctionCode = DiagDynamicFunctionCode(48);
345pub const SQL_DIAG_INSERT: DiagDynamicFunctionCode = DiagDynamicFunctionCode(50);
346pub const SQL_DIAG_CALL: DiagDynamicFunctionCode = DiagDynamicFunctionCode(7);
347pub const SQL_DIAG_REVOKE: DiagDynamicFunctionCode = DiagDynamicFunctionCode(59);
348pub const SQL_DIAG_CREATE_SCHEMA: DiagDynamicFunctionCode = DiagDynamicFunctionCode(64);
349pub const SQL_DIAG_CREATE_TRANSLATION: DiagDynamicFunctionCode = DiagDynamicFunctionCode(79);
350pub const SQL_DIAG_DYNAMIC_UPDATE_CURSOR: DiagDynamicFunctionCode = DiagDynamicFunctionCode(81);
351pub const SQL_DIAG_UPDATE_WHERE: DiagDynamicFunctionCode = DiagDynamicFunctionCode(82);
352pub const SQL_DIAG_UNKNOWN_STATEMENT: DiagDynamicFunctionCode = DiagDynamicFunctionCode(0);
353
354#[odbc_type(SQLINTEGER)]
355pub struct DiagColumnNumber;
356pub const SQL_NO_COLUMN_NUMBER: DiagColumnNumber = DiagColumnNumber(-1);
357pub const SQL_COLUMN_NUMBER_UNKNOWN: DiagColumnNumber = DiagColumnNumber(-2);
358
359#[odbc_type(SQLLEN)]
360pub struct DiagRowNumber;
361pub const SQL_NO_ROW_NUMBER: DiagRowNumber = DiagRowNumber(-1);
362pub const SQL_ROW_NUMBER_UNKNOWN: DiagRowNumber = DiagRowNumber(-2);
363
364#[cfg(test)]
368mod test {
369 #![allow(non_snake_case)]
370
371 use super::*;
372
373 #[test]
374 fn new_sqlstate_SQLCHAR() {
375 let sqlstate = SQLSTATE::<SQLCHAR>::new("12345");
376
377 assert_eq!(6, sqlstate.len());
378 assert_eq!([49, 50, 51, 52, 53, 0].as_ref(), sqlstate.0);
379 }
380
381 #[test]
382 fn new_sqlstate_SQLWCHAR() {
383 let sqlstate = SQLSTATE::<SQLWCHAR>::new("12345");
384
385 assert_eq!(12, sqlstate.len());
386 assert_eq!([49, 50, 51, 52, 53, 0].as_ref(), sqlstate.0);
387 }
388
389 #[test]
390 #[should_panic]
391 fn new_sqlstate_SQLCHAR_size_4() {
392 SQLSTATE::<SQLCHAR>::new("0000");
393 }
394
395 #[test]
396 #[should_panic]
397 fn new_sqlstate_SQLWCHAR_size_4() {
398 SQLSTATE::<SQLWCHAR>::new("0000");
399 }
400
401 #[test]
402 fn sqlstate_SQLCHAR_cmp() {
403 let sqlstate = SQLSTATE::<SQLCHAR>::new("12345");
404
405 assert_eq!("12345", sqlstate);
406 assert_eq!(sqlstate, "12345");
407 }
408
409 #[test]
410 fn sqlstate_SQLWCHAR_cmp() {
411 let sqlstate = SQLSTATE::<SQLWCHAR>::new("12345");
412
413 assert_eq!("12345", sqlstate);
414 assert_eq!(sqlstate, "12345");
415 }
416}