rs_odbc/
c_types.rs

1use crate::convert::AsSQLPOINTER;
2use crate::env::{OdbcVersion, SQL_OV_ODBC3_80, SQL_OV_ODBC4};
3use crate::handle::{RefSQLHDESC, RefUnsafeSQLHDESC};
4use crate::sql_types::*;
5use crate::str::{OdbcChar, OdbcStr};
6use crate::Ident;
7use crate::SQLPOINTER;
8use crate::{
9    SQLBIGINT, SQLCHAR, SQLDOUBLE, SQLINTEGER, SQLLEN, SQLREAL, SQLSCHAR, SQLSMALLINT, SQLUBIGINT,
10    SQLUINTEGER, SQLUSMALLINT, SQLWCHAR,
11};
12use core::{cell::UnsafeCell, mem::MaybeUninit};
13
14pub trait CData<TT: Ident, V: OdbcVersion>: CDataLen {}
15
16/// Care must be taken because references to DeferredBuf might be written to
17// TODO: Do I need to disambiguate between BindCol and BindParameters deferred buffers
18// TODO: add bound D: Descriptor
19pub unsafe trait DeferredBuf<D, TT: Ident, V: OdbcVersion>: CDataLen + AsSQLPOINTER {}
20
21impl<TT: Ident, T: CScalar, V: OdbcVersion> CData<TT, V> for MaybeUninit<T> where T: CData<TT, V> {}
22
23impl<TT: Ident, T, V: OdbcVersion> CData<TT, V> for [MaybeUninit<T>] where [T]: CData<TT, V> {}
24
25impl<TT: Ident, T: OdbcChar, V: OdbcVersion> CData<TT, V> for OdbcStr<MaybeUninit<T>> where
26    OdbcStr<T>: CData<TT, V>
27{
28}
29
30unsafe impl<DT, TT: Ident, T: CScalar, V: OdbcVersion> DeferredBuf<RefSQLHDESC<'_, DT, V>, TT, V>
31    for UnsafeCell<T>
32where
33    T: CData<TT, V>,
34{
35}
36unsafe impl<DT, TT: Ident, CH: OdbcChar, V: OdbcVersion> DeferredBuf<RefSQLHDESC<'_, DT, V>, TT, V>
37    for OdbcStr<UnsafeCell<CH>>
38where
39    OdbcStr<CH>: CData<TT, V>,
40{
41}
42
43unsafe impl<'conn, DT, TT: Ident, T: CScalar, V: OdbcVersion>
44    DeferredBuf<RefUnsafeSQLHDESC<'conn, DT, V>, TT, V> for UnsafeCell<T>
45where
46    T: DeferredBuf<RefSQLHDESC<'conn, DT, V>, TT, V>,
47{
48}
49unsafe impl<'conn, DT, TT: Ident, T: CScalar, V: OdbcVersion>
50    DeferredBuf<RefUnsafeSQLHDESC<'conn, DT, V>, TT, V> for [UnsafeCell<T>]
51where
52    [T]: DeferredBuf<RefSQLHDESC<'conn, DT, V>, TT, V>,
53{
54}
55unsafe impl<'conn, DT, TT: Ident, CH: OdbcChar, V: OdbcVersion>
56    DeferredBuf<RefUnsafeSQLHDESC<'conn, DT, V>, TT, V> for OdbcStr<UnsafeCell<CH>>
57where
58    OdbcStr<CH>: DeferredBuf<RefSQLHDESC<'conn, DT, V>, TT, V>,
59{
60}
61unsafe impl<DT, TT: Ident, V: OdbcVersion> DeferredBuf<RefUnsafeSQLHDESC<'_, DT, V>, TT, V>
62    for (SQLPOINTER, SQLLEN)
63{
64}
65
66#[repr(transparent)]
67#[derive(Clone, Copy)]
68pub struct StrLenOrInd(pub(crate) SQLLEN);
69impl StrLenOrInd {
70    pub unsafe fn set_len(&mut self, len: SQLLEN) {
71        if len < 0 {
72            panic!("len must be non-negative: {}", len);
73        }
74
75        self.0 = len;
76    }
77}
78pub const SQL_NULL_DATA: StrLenOrInd = StrLenOrInd(-1);
79// Output constants
80pub const SQL_NO_TOTAL: StrLenOrInd = StrLenOrInd(-4);
81// Input constants
82pub const SQL_NTS: StrLenOrInd = StrLenOrInd(-3);
83pub const SQL_DATA_AT_EXEC: StrLenOrInd = StrLenOrInd(-2);
84pub const SQL_COLUMN_IGNORE: StrLenOrInd = StrLenOrInd(-6);
85
86// TODO: Do something
87// pub fn SQL_LEN_DATA_AT_EXEC(length: LEN) -> LEN {
88//    const SQL_LEN_DATA_AT_EXEC_OFFSET: LEN = -100;
89//    (-length).checked_add(SQL_LEN_DATA_AT_EXEC_OFFSET).expect()
90//}
91
92// SQLBindParameter only
93pub const SQL_DEFAULT_PARAM: StrLenOrInd = StrLenOrInd(-5);
94
95const SQL_UNSIGNED_OFFSET: SQLSMALLINT = -22;
96const SQL_SIGNED_OFFSET: SQLSMALLINT = -20;
97const SQL_C_SHORT: SQLSMALLINT = SqlTypeV3::identifier(&SQL_SMALLINT);
98const SQL_C_LONG: SQLSMALLINT = SqlTypeV3::identifier(&SQL_INTEGER);
99const SQL_C_TINYINT: SQLSMALLINT = SqlTypeV3::identifier(&SQL_TINYINT);
100
101// TODO: This value is discouraged from being used
102//#[derive(Ident)]
103//#[identifier(SQLSMALLINT, 99)]
104//#[allow(non_camel_case_types)]
105//struct SQL_C_DEFAULT;
106
107#[allow(non_camel_case_types)]
108pub struct SQL_C_CHAR;
109impl Ident for SQL_C_CHAR {
110    type Type = SQLSMALLINT;
111    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_CHAR);
112}
113impl<V: OdbcVersion> CData<SQL_C_CHAR, V> for OdbcStr<SQLCHAR> {}
114
115#[allow(non_camel_case_types)]
116pub struct SQL_C_WCHAR;
117impl Ident for SQL_C_WCHAR {
118    type Type = SQLSMALLINT;
119    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_WCHAR);
120}
121impl<V: OdbcVersion> CData<SQL_C_WCHAR, V> for OdbcStr<SQLWCHAR> {}
122
123#[allow(non_camel_case_types)]
124pub struct SQL_C_SSHORT;
125impl Ident for SQL_C_SSHORT {
126    type Type = SQLSMALLINT;
127    const IDENTIFIER: Self::Type = SQL_C_SHORT + SQL_SIGNED_OFFSET;
128}
129impl<V: OdbcVersion> CData<SQL_C_SSHORT, V> for SQLSMALLINT {}
130
131#[allow(non_camel_case_types)]
132pub struct SQL_C_USHORT;
133impl Ident for SQL_C_USHORT {
134    type Type = SQLSMALLINT;
135    const IDENTIFIER: Self::Type = SQL_C_SHORT + SQL_UNSIGNED_OFFSET;
136}
137impl<V: OdbcVersion> CData<SQL_C_USHORT, V> for SQLUSMALLINT {}
138
139#[allow(non_camel_case_types)]
140pub struct SQL_C_SLONG;
141impl Ident for SQL_C_SLONG {
142    type Type = SQLSMALLINT;
143    const IDENTIFIER: Self::Type = SQL_C_LONG + SQL_SIGNED_OFFSET;
144}
145impl<V: OdbcVersion> CData<SQL_C_SLONG, V> for SQLINTEGER {}
146
147#[allow(non_camel_case_types)]
148pub struct SQL_C_ULONG;
149impl Ident for SQL_C_ULONG {
150    type Type = SQLSMALLINT;
151    const IDENTIFIER: Self::Type = SQL_C_LONG + SQL_UNSIGNED_OFFSET;
152}
153impl<V: OdbcVersion> CData<SQL_C_ULONG, V> for SQLUINTEGER {}
154
155#[allow(non_camel_case_types)]
156pub struct SQL_C_FLOAT;
157impl Ident for SQL_C_FLOAT {
158    type Type = SQLSMALLINT;
159    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_REAL);
160}
161impl<V: OdbcVersion> CData<SQL_C_FLOAT, V> for SQLREAL {}
162
163#[allow(non_camel_case_types)]
164pub struct SQL_C_DOUBLE;
165impl Ident for SQL_C_DOUBLE {
166    type Type = SQLSMALLINT;
167    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_DOUBLE);
168}
169impl<V: OdbcVersion> CData<SQL_C_DOUBLE, V> for SQLDOUBLE {}
170
171#[allow(non_camel_case_types)]
172pub struct SQL_C_BIT;
173impl Ident for SQL_C_BIT {
174    type Type = SQLSMALLINT;
175    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_BIT);
176}
177impl<V: OdbcVersion> CData<SQL_C_BIT, V> for SQLCHAR {}
178
179#[allow(non_camel_case_types)]
180pub struct SQL_C_STINYINT;
181impl Ident for SQL_C_STINYINT {
182    type Type = SQLSMALLINT;
183    const IDENTIFIER: Self::Type = SQL_C_TINYINT + SQL_SIGNED_OFFSET;
184}
185impl<V: OdbcVersion> CData<SQL_C_STINYINT, V> for SQLSCHAR {}
186
187#[allow(non_camel_case_types)]
188pub struct SQL_C_UTINYINT;
189impl Ident for SQL_C_UTINYINT {
190    type Type = SQLSMALLINT;
191    const IDENTIFIER: Self::Type = SQL_C_TINYINT + SQL_UNSIGNED_OFFSET;
192}
193impl<V: OdbcVersion> CData<SQL_C_UTINYINT, V> for SQLCHAR {}
194
195#[allow(non_camel_case_types)]
196pub struct SQL_C_SBIGINT;
197impl Ident for SQL_C_SBIGINT {
198    type Type = SQLSMALLINT;
199    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_BIGINT);
200}
201impl<V: OdbcVersion> CData<SQL_C_SBIGINT, V> for SQLBIGINT {}
202
203#[allow(non_camel_case_types)]
204pub struct SQL_C_UBIGINT;
205impl Ident for SQL_C_UBIGINT {
206    type Type = SQLSMALLINT;
207    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_BIGINT);
208}
209impl<V: OdbcVersion> CData<SQL_C_UBIGINT, V> for SQLUBIGINT {}
210
211#[allow(non_camel_case_types)]
212pub struct SQL_C_BINARY;
213impl Ident for SQL_C_BINARY {
214    type Type = SQLSMALLINT;
215    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_BINARY);
216}
217impl<V: OdbcVersion> CData<SQL_C_BINARY, V> for OdbcStr<SQLCHAR> {}
218
219// TODO: Weird?
220pub use SQL_C_BINARY as SQL_C_VARBOOKMARK;
221
222#[allow(non_camel_case_types)]
223pub struct SQL_C_NUMERIC;
224impl Ident for SQL_C_NUMERIC {
225    type Type = SQLSMALLINT;
226    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_NUMERIC);
227}
228impl<V: OdbcVersion> CData<SQL_C_NUMERIC, V> for SQL_NUMERIC_STRUCT {}
229
230// TODO: This is 3.5
231#[allow(non_camel_case_types)]
232pub struct SQL_C_GUID;
233impl Ident for SQL_C_GUID {
234    type Type = SQLSMALLINT;
235    const IDENTIFIER: Self::Type = SqlTypeV3_8::identifier(&SQL_GUID);
236}
237impl CData<SQL_C_GUID, SQL_OV_ODBC3_80> for SQLGUID {}
238
239#[allow(non_camel_case_types)]
240pub struct SQL_C_TYPE_DATE;
241impl Ident for SQL_C_TYPE_DATE {
242    type Type = SQLSMALLINT;
243    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_TYPE_DATE);
244}
245impl<V: OdbcVersion> CData<SQL_C_TYPE_DATE, V> for SQL_DATE_STRUCT {}
246
247#[allow(non_camel_case_types)]
248pub struct SQL_C_TYPE_TIME;
249impl Ident for SQL_C_TYPE_TIME {
250    type Type = SQLSMALLINT;
251    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_TYPE_TIME);
252}
253impl<V: OdbcVersion> CData<SQL_C_TYPE_TIME, V> for SQL_TIME_STRUCT {}
254
255#[allow(non_camel_case_types)]
256pub struct SQL_C_TYPE_TIMESTAMP;
257impl Ident for SQL_C_TYPE_TIMESTAMP {
258    type Type = SQLSMALLINT;
259    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_TYPE_TIMESTAMP);
260}
261impl<V: OdbcVersion> CData<SQL_C_TYPE_TIMESTAMP, V> for SQL_TIMESTAMP_STRUCT {}
262
263#[allow(non_camel_case_types)]
264pub struct SQL_C_TYPE_TIME_WITH_TIMEZONE;
265impl Ident for SQL_C_TYPE_TIME_WITH_TIMEZONE {
266    type Type = SQLSMALLINT;
267    const IDENTIFIER: SQLSMALLINT = SqlTypeV4::identifier(&SQL_TYPE_TIME_WITH_TIMEZONE);
268}
269impl CData<SQL_C_TYPE_TIME_WITH_TIMEZONE, SQL_OV_ODBC4> for SQL_TIME_WITH_TIMEZONE_STRUCT {}
270
271#[allow(non_camel_case_types)]
272pub struct SQL_C_TYPE_TIMESTAMP_WITH_TIMEZONE;
273impl Ident for SQL_C_TYPE_TIMESTAMP_WITH_TIMEZONE {
274    type Type = SQLSMALLINT;
275    const IDENTIFIER: SQLSMALLINT = SqlTypeV4::identifier(&SQL_TYPE_TIMESTAMP_WITH_TIMEZONE);
276}
277impl CData<SQL_C_TYPE_TIMESTAMP_WITH_TIMEZONE, SQL_OV_ODBC4>
278    for SQL_TIMESTAMP_WITH_TIMEZONE_STRUCT
279{
280}
281
282#[allow(non_camel_case_types)]
283pub struct SQL_C_INTERVAL_YEAR;
284impl Ident for SQL_C_INTERVAL_YEAR {
285    type Type = SQLSMALLINT;
286    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_YEAR);
287}
288impl<V: OdbcVersion> CData<SQL_C_INTERVAL_YEAR, V> for SQL_INTERVAL_STRUCT {}
289
290#[allow(non_camel_case_types)]
291pub struct SQL_C_INTERVAL_MONTH;
292impl Ident for SQL_C_INTERVAL_MONTH {
293    type Type = SQLSMALLINT;
294    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_MONTH);
295}
296impl<V: OdbcVersion> CData<SQL_C_INTERVAL_MONTH, V> for SQL_INTERVAL_STRUCT {}
297
298#[allow(non_camel_case_types)]
299pub struct SQL_C_INTERVAL_DAY;
300impl Ident for SQL_C_INTERVAL_DAY {
301    type Type = SQLSMALLINT;
302    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_DAY);
303}
304impl<V: OdbcVersion> CData<SQL_C_INTERVAL_DAY, V> for SQL_INTERVAL_STRUCT {}
305
306#[allow(non_camel_case_types)]
307pub struct SQL_C_INTERVAL_HOUR;
308impl Ident for SQL_C_INTERVAL_HOUR {
309    type Type = SQLSMALLINT;
310    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_HOUR);
311}
312impl<V: OdbcVersion> CData<SQL_C_INTERVAL_HOUR, V> for SQL_INTERVAL_STRUCT {}
313
314#[allow(non_camel_case_types)]
315pub struct SQL_C_INTERVAL_MINUTE;
316impl Ident for SQL_C_INTERVAL_MINUTE {
317    type Type = SQLSMALLINT;
318    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_MINUTE);
319}
320impl<V: OdbcVersion> CData<SQL_C_INTERVAL_MINUTE, V> for SQL_INTERVAL_STRUCT {}
321
322#[allow(non_camel_case_types)]
323pub struct SQL_C_INTERVAL_SECOND;
324impl Ident for SQL_C_INTERVAL_SECOND {
325    type Type = SQLSMALLINT;
326    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_SECOND);
327}
328impl<V: OdbcVersion> CData<SQL_C_INTERVAL_SECOND, V> for SQL_INTERVAL_STRUCT {}
329
330#[allow(non_camel_case_types)]
331pub struct SQL_C_INTERVAL_YEAR_TO_MONTH;
332impl Ident for SQL_C_INTERVAL_YEAR_TO_MONTH {
333    type Type = SQLSMALLINT;
334    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_YEAR_TO_MONTH);
335}
336impl<V: OdbcVersion> CData<SQL_C_INTERVAL_YEAR_TO_MONTH, V> for SQL_INTERVAL_STRUCT {}
337
338#[allow(non_camel_case_types)]
339pub struct SQL_C_INTERVAL_DAY_TO_HOUR;
340impl Ident for SQL_C_INTERVAL_DAY_TO_HOUR {
341    type Type = SQLSMALLINT;
342    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_DAY_TO_HOUR);
343}
344impl<V: OdbcVersion> CData<SQL_C_INTERVAL_DAY_TO_HOUR, V> for SQL_INTERVAL_STRUCT {}
345
346#[allow(non_camel_case_types)]
347pub struct SQL_C_INTERVAL_DAY_TO_MINUTE;
348impl Ident for SQL_C_INTERVAL_DAY_TO_MINUTE {
349    type Type = SQLSMALLINT;
350    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_DAY_TO_MINUTE);
351}
352impl<V: OdbcVersion> CData<SQL_C_INTERVAL_DAY_TO_MINUTE, V> for SQL_INTERVAL_STRUCT {}
353
354#[allow(non_camel_case_types)]
355pub struct SQL_C_INTERVAL_DAY_TO_SECOND;
356impl Ident for SQL_C_INTERVAL_DAY_TO_SECOND {
357    type Type = SQLSMALLINT;
358    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_DAY_TO_SECOND);
359}
360impl<V: OdbcVersion> CData<SQL_C_INTERVAL_DAY_TO_SECOND, V> for SQL_INTERVAL_STRUCT {}
361
362#[allow(non_camel_case_types)]
363pub struct SQL_C_INTERVAL_HOUR_TO_MINUTE;
364impl Ident for SQL_C_INTERVAL_HOUR_TO_MINUTE {
365    type Type = SQLSMALLINT;
366    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_HOUR_TO_MINUTE);
367}
368impl<V: OdbcVersion> CData<SQL_C_INTERVAL_HOUR_TO_MINUTE, V> for SQL_INTERVAL_STRUCT {}
369
370#[allow(non_camel_case_types)]
371pub struct SQL_C_INTERVAL_HOUR_TO_SECOND;
372impl Ident for SQL_C_INTERVAL_HOUR_TO_SECOND {
373    type Type = SQLSMALLINT;
374    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_HOUR_TO_SECOND);
375}
376impl<V: OdbcVersion> CData<SQL_C_INTERVAL_HOUR_TO_SECOND, V> for SQL_INTERVAL_STRUCT {}
377
378#[allow(non_camel_case_types)]
379pub struct SQL_C_INTERVAL_MINUTE_TO_SECOND;
380impl Ident for SQL_C_INTERVAL_MINUTE_TO_SECOND {
381    type Type = SQLSMALLINT;
382    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_INTERVAL_MINUTE_TO_SECOND);
383}
384impl<V: OdbcVersion> CData<SQL_C_INTERVAL_MINUTE_TO_SECOND, V> for SQL_INTERVAL_STRUCT {}
385
386// TODO: Test if these types are required or user can achieve the same goal via some other way
387// If SQL_ARD_TYPE and SQL_APD_TYPE are allowed, SQLGetData would have to be unsafe
388// Also, these types can only be used for SQLGetData so be careful to implement only for CData<TT>
389// because it'll get imeplemented for DeferredBuf automatically. In this case some restructuring
390// would be required but it would be transparent to the users of the library
391//#[allow(non_camel_case_types)]
392//pub struct SQL_ARD_TYPE;
393//impl Ident for SQL_ARD_TYPE {
394//    type Type = SQLSMALLINT;
395//    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_ARD_TYPE);
396//}
397//
398//#[allow(non_camel_case_types)]
399//pub struct SQL_APD_TYPE;
400//impl Ident for SQL_APD_TYPE {
401//    type Type = SQLSMALLINT;
402//    const IDENTIFIER: Self::Type = SqlTypeV3::identifier(&SQL_APD_TYPE);
403//}
404
405// =================================================================================== //
406
407pub const SQL_MAX_NUMERIC_LEN: usize = 16;
408
409#[repr(C)]
410#[allow(non_camel_case_types)]
411#[derive(Debug, PartialEq, Eq, Clone, Copy)]
412pub struct SQL_NUMERIC_STRUCT {
413    pub precision: SQLCHAR,
414    pub scale: SQLSCHAR,
415    /// The sign field is 1 if positive, 0 if negative.
416    pub sign: SQLCHAR,
417    pub val: [SQLCHAR; SQL_MAX_NUMERIC_LEN],
418}
419
420#[repr(C)]
421#[allow(non_camel_case_types, non_snake_case)]
422#[derive(Debug, PartialEq, Eq, Clone, Copy)]
423pub struct SQLGUID {
424    pub Data1: u32,
425    pub Data2: u16,
426    pub Data3: u16,
427    pub Data4: [u8; 8],
428}
429
430#[repr(C)]
431#[allow(non_camel_case_types)]
432#[derive(Debug, PartialEq, Eq, Clone, Copy)]
433pub struct SQL_DATE_STRUCT {
434    pub year: SQLSMALLINT,
435    pub month: SQLUSMALLINT,
436    pub day: SQLUSMALLINT,
437}
438
439#[repr(C)]
440#[allow(non_camel_case_types)]
441#[derive(Debug, PartialEq, Eq, Clone, Copy)]
442pub struct SQL_TIME_STRUCT {
443    pub hour: SQLUSMALLINT,
444    pub minute: SQLUSMALLINT,
445    pub second: SQLUSMALLINT,
446}
447
448#[repr(C)]
449#[allow(non_camel_case_types)]
450#[derive(Debug, PartialEq, Eq, Clone, Copy)]
451pub struct SQL_TIMESTAMP_STRUCT {
452    pub year: SQLSMALLINT,
453    pub month: SQLUSMALLINT,
454    pub day: SQLUSMALLINT,
455    pub hour: SQLUSMALLINT,
456    pub minute: SQLUSMALLINT,
457    pub second: SQLUSMALLINT,
458    /// Number of billionths of a second and ranges from 0 through 999,999,999
459    pub fraction: SQLUINTEGER,
460}
461
462#[repr(C)]
463#[allow(non_camel_case_types)]
464#[derive(Debug, PartialEq, Eq, Clone, Copy)]
465pub struct SQL_TIME_WITH_TIMEZONE_STRUCT {
466    pub hour: SQLUSMALLINT,
467    pub minute: SQLUSMALLINT,
468    pub second: SQLUSMALLINT,
469    pub timezone_hours: SQLSMALLINT,
470    pub timezone_minutes: SQLUSMALLINT,
471}
472
473#[repr(C)]
474#[allow(non_camel_case_types)]
475#[derive(Debug, PartialEq, Eq, Clone, Copy)]
476pub struct SQL_TIMESTAMP_WITH_TIMEZONE_STRUCT {
477    pub year: SQLSMALLINT,
478    pub month: SQLUSMALLINT,
479    pub day: SQLUSMALLINT,
480    pub hour: SQLUSMALLINT,
481    pub minute: SQLUSMALLINT,
482    pub second: SQLUSMALLINT,
483    /// Number of billionths of a second and ranges from 0 through 999,999,999
484    pub fraction: SQLUINTEGER,
485    pub timezone_hours: SQLSMALLINT,
486    pub timezone_minutes: SQLUSMALLINT,
487}
488
489#[repr(C)]
490#[allow(non_camel_case_types)]
491#[derive(Clone, Copy)]
492pub struct SQL_INTERVAL_STRUCT {
493    pub interval_type: SQLINTERVAL,
494    pub interval_sign: SQLSMALLINT,
495    // TODO: Make public
496    interval: IntervalUnion,
497}
498impl Eq for SQL_INTERVAL_STRUCT {}
499impl PartialEq<SQL_INTERVAL_STRUCT> for SQL_INTERVAL_STRUCT {
500    fn eq(&self, _: &SQL_INTERVAL_STRUCT) -> bool {
501        unimplemented!()
502    }
503}
504impl core::fmt::Debug for SQL_INTERVAL_STRUCT {
505    fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
506        unimplemented!()
507    }
508}
509
510// TODO: Probably shouldn't use an enum with C FFI
511// But it's literally defined as enum in ODBC
512#[repr(C)]
513#[allow(non_camel_case_types)]
514#[derive(Debug, PartialEq, Eq, Clone, Copy)]
515pub enum SQLINTERVAL {
516    SQL_IS_YEAR = 1,
517    SQL_IS_MONTH = 2,
518    SQL_IS_DAY = 3,
519    SQL_IS_HOUR = 4,
520    SQL_IS_MINUTE = 5,
521    SQL_IS_SECOND = 6,
522    SQL_IS_YEAR_TO_MONTH = 7,
523    SQL_IS_DAY_TO_HOUR = 8,
524    SQL_IS_DAY_TO_MINUTE = 9,
525    SQL_IS_DAY_TO_SECOND = 10,
526    SQL_IS_HOUR_TO_MINUTE = 11,
527    SQL_IS_HOUR_TO_SECOND = 12,
528    SQL_IS_MINUTE_TO_SECOND = 13,
529}
530
531#[repr(C)]
532// TODO: Should this be public?
533// TODO: Remove Copy
534#[derive(Clone, Copy)]
535union IntervalUnion {
536    pub year_month: SQL_YEAR_MONTH_STRUCT,
537    pub day_second: SQL_DAY_SECOND_STRUCT,
538}
539
540// TODO: Must be copy because it's used in uinon
541// Maybe it would be ok in nightly
542#[repr(C)]
543#[derive(Debug, PartialEq, Eq, Clone, Copy)]
544#[allow(non_camel_case_types)]
545struct SQL_YEAR_MONTH_STRUCT {
546    pub year: SQLUINTEGER,
547    pub month: SQLUINTEGER,
548}
549
550// TODO: Must be copy because it's used in uinon
551// Maybe it would be ok in nightly
552#[repr(C)]
553#[derive(Debug, PartialEq, Eq, Clone, Copy)]
554#[allow(non_camel_case_types)]
555struct SQL_DAY_SECOND_STRUCT {
556    pub day: SQLUINTEGER,
557    pub month: SQLUINTEGER,
558    pub minute: SQLUINTEGER,
559    pub second: SQLUINTEGER,
560    pub fraction: SQLUINTEGER,
561}
562
563/// CScalar must be repr(C) and have
564/// the same representation as SQLPOINTER
565pub unsafe trait CScalar {}
566
567unsafe impl CScalar for SQLSMALLINT {}
568unsafe impl CScalar for SQLUSMALLINT {}
569unsafe impl CScalar for SQLUINTEGER {}
570unsafe impl CScalar for SQLINTEGER {}
571unsafe impl CScalar for SQLREAL {}
572unsafe impl CScalar for SQLDOUBLE {}
573unsafe impl CScalar for SQLCHAR {}
574unsafe impl CScalar for SQLSCHAR {}
575unsafe impl CScalar for SQLBIGINT {}
576unsafe impl CScalar for SQLUBIGINT {}
577unsafe impl CScalar for SQLGUID {}
578unsafe impl CScalar for SQL_NUMERIC_STRUCT {}
579unsafe impl CScalar for SQL_INTERVAL_STRUCT {}
580unsafe impl CScalar for SQL_DATE_STRUCT {}
581unsafe impl CScalar for SQL_TIME_STRUCT {}
582unsafe impl CScalar for SQL_TIMESTAMP_STRUCT {}
583unsafe impl CScalar for SQL_TIME_WITH_TIMEZONE_STRUCT {}
584unsafe impl CScalar for SQL_TIMESTAMP_WITH_TIMEZONE_STRUCT {}
585
586pub trait CDataLen {
587    fn len(&self) -> SQLLEN;
588}
589
590impl<T: CScalar> CDataLen for T {
591    fn len(&self) -> SQLLEN {
592        0
593    }
594}
595impl<T: CScalar> CDataLen for UnsafeCell<T> {
596    fn len(&self) -> SQLLEN {
597        0
598    }
599}
600impl<T: CScalar> CDataLen for MaybeUninit<T> {
601    fn len(&self) -> SQLLEN {
602        0
603    }
604}
605// TODO:
606//impl<T: CScalar> CDataLen for UnsafeCell<MaybeUninit<T>> {
607//    fn len(&self) -> SQLLEN {
608//        0
609//    }
610//}
611impl<T> CDataLen for [T] {
612    fn len(&self) -> SQLLEN {
613        self.len()
614            .try_into()
615            .expect("Buffer length greater than SQLLEN max")
616    }
617}
618impl<T> CDataLen for OdbcStr<T> {
619    fn len(&self) -> SQLLEN {
620        <[T] as CDataLen>::len(self)
621    }
622}
623impl CDataLen for (SQLPOINTER, SQLLEN) {
624    fn len(&self) -> SQLLEN {
625        self.1
626    }
627}
628
629//impl<T> ParameterDir<SQL_PARAM_INPUT> for [T] where [T]: DeferredBuf {}
630//impl<T> ParameterDir<SQL_PARAM_OUTPUT> for [MaybeUninit<T>] where [T]: DeferredBuf {}
631//impl<T> ParameterDir<SQL_PARAM_INPUT_OUTPUT> for [MaybeUninit<T>] where
632//    [T]: ParameterDir<SQL_PARAM_INPUT> {}