odbc_safe/environment.rs
1use super::*;
2use sys::*;
3use std::marker::PhantomData;
4use version::VersionOption;
5
6/// An `Environment` is a global context, in which to access data.
7///
8/// Associated with an `Environment` is any information that is global in nature, such as:
9///
10/// * The `Environment`'s state
11/// * The current environment-level diagnostics
12/// * The handles of connections currently allocated on the environment
13/// * The current stetting of each environment attribute
14///
15/// See: [Environment Handles in the ODBC Reference][1]
16/// [1]: https://docs.microsoft.com/sql/odbc/reference/develop-app/environment-handles
17#[derive(Debug)]
18pub struct Environment<V: VersionOption> {
19 version: PhantomData<V>,
20 /// Invariant: Should always point to a valid ODBC Environment with Version declared as V or
21 /// `NoVersion`
22 handle: HEnv,
23}
24
25impl<V: VersionOption> Environment<V> {
26 /// Provides access to the raw ODBC environment handle.
27 pub fn as_raw(&self) -> SQLHENV {
28 self.handle.as_raw()
29 }
30
31 /// Express state transiton
32 fn transit<Other: VersionOption>(self) -> Environment<Other> {
33 Environment {
34 version: PhantomData,
35 handle: self.handle,
36 }
37 }
38}
39
40impl<V: Version> Environment<V> {
41 /// Used by `Connection`s constructor
42 pub(crate) fn as_henv(&self) -> &HEnv {
43 &self.handle
44 }
45
46 /// Fills buffers with information about the available datasources
47 ///
48 /// A 32 / 64 Bit Application will only return information about either 32 or 64 Bit
49 /// DataSources.
50 ///
51 /// # Returns
52 ///
53 /// (server_name_length, description_length)
54 ///
55 /// See [SQLDataSources][1]
56 /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldatasources-function
57 pub fn data_sources(
58 &mut self,
59 direction: FetchOrientation,
60 server_name: &mut [u8],
61 description: &mut [u8],
62 ) -> ReturnOption<(SQLSMALLINT, SQLSMALLINT)> {
63 self.handle.data_sources(
64 direction,
65 server_name,
66 description,
67 )
68 }
69
70 /// Fills buffers with information about the available datasources
71 ///
72 /// A 32 / 64 Bit Application will only return information about either 32 or 64 Bit
73 /// DataSources.
74 ///
75 /// # Returns
76 ///
77 /// (description_length, attributes_length)
78 ///
79 /// See [SQLDrivers][1]
80 /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldrivers-function
81 pub fn drivers(
82 &mut self,
83 direction: FetchOrientation,
84 description: &mut [u8],
85 attributes: &mut [u8],
86 ) -> ReturnOption<(SQLSMALLINT, SQLSMALLINT)> {
87 self.handle.drivers(direction, description, attributes)
88 }
89}
90
91impl Environment<NoVersion> {
92 /// Allocates a new `Environment`
93 pub fn new() -> Return<Self> {
94 HEnv::allocate().map(|handle| {
95 Environment {
96 version: PhantomData,
97 handle: handle,
98 }
99 })
100 }
101
102 /// Before an application allocates a connection which specification it follows. Currently
103 /// these bindings only support ODBC 3.x.
104 ///
105 /// It is valid to specify ODBC 3.x even then connecting to an ODBC 2.x driver. Applications
106 /// must however avoid calling 3.x functionality on 2.x drivers. Since drivers are connected at
107 /// runtime, these kind of errors can not be catched by the type system.
108 pub fn declare_version<V: Version>(mut self) -> Return<Environment<V>, Environment<NoVersion>> {
109 let result = self.handle.declare_version(V::constant());
110 match result {
111 Success(()) => Success(self.transit()),
112 Info(()) => Success(self.transit()),
113 Error(()) => Success(self.transit()),
114 }
115 }
116
117 /// Before an application allocates a connection which specification it follows. Currently
118 /// these bindings only support ODBC 3.x.
119 ///
120 /// It is valid to specify ODBC 3.x even then connecting to an ODBC 2.x driver. Applications
121 /// must however avoid calling 3.x functionality on 2.x drivers. Since drivers are connected at
122 /// runtime, these kind of errors can not be catched by the type system.
123 ///
124 /// This method is a shorthand for `declare_version::<Odbc3m8>`.
125 pub fn declare_version_3_8(self) -> Return<Environment<Odbc3m8>, Environment<NoVersion>> {
126 self.declare_version()
127 }
128
129 /// Before an application allocates a connection which specification it follows. Currently
130 /// these bindings only support ODBC 3.x.
131 ///
132 /// It is valid to specify ODBC 3.x even then connecting to an ODBC 2.x driver. Applications
133 /// must however avoid calling 3.x functionality on 2.x drivers. Since drivers are connected at
134 /// runtime, these kind of errors can not be catched by the type system.
135 ///
136 /// This method is a shorthand for `declare_version::<Odbc3>`.
137 pub fn declare_version_3(self) -> Return<Environment<Odbc3>, Environment<NoVersion>> {
138 self.declare_version()
139 }
140}
141
142impl<V: VersionOption> Diagnostics for Environment<V> {
143 fn diagnostics(
144 &self,
145 rec_number: SQLSMALLINT,
146 message_text: &mut [SQLCHAR],
147 ) -> ReturnOption<DiagResult> {
148 self.handle.diagnostics(rec_number, message_text)
149 }
150}