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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
use super::*; use sys::*; use std::marker::PhantomData; /// An `Environment` is a global context, in which to access data. /// /// Associated with an `Environment` is any information that is global in nature, such as: /// /// * The `Environment`'s state /// * The current environment-level diagnostics /// * The handles of connections currently allocated on the environment /// * The current stetting of each environment attribute /// /// See: [Environment Handles in the ODBC Reference][1] /// [1]: https://docs.microsoft.com/sql/odbc/reference/develop-app/environment-handles #[derive(Debug)] pub struct Environment<V> { version: PhantomData<V>, /// Invariant: Should always point to a valid ODBC Environment with Version declared as V or /// `NoVersion` handle: HEnv, } impl<V> Environment<V> { /// Provides access to the raw ODBC environment handle. pub fn as_raw(&self) -> SQLHENV { self.handle.as_raw() } /// Express state transiton fn transit<Other>(self) -> Environment<Other> { Environment { version: PhantomData, handle: self.handle, } } } impl<V: Version> Environment<V> { /// Used by `Connection`s constructor pub(crate) fn as_henv(&self) -> &HEnv { &self.handle } /// Fills buffers with information about the available datasources /// /// A 32 / 64 Bit Application will only return information about either 32 or 64 Bit /// DataSources. /// /// # Returns /// /// (server_name_length, description_length) /// /// See [SQLDataSources][1] /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldatasources-function pub fn data_sources( &mut self, direction: FetchOrientation, server_name: &mut [u8], description: &mut [u8], ) -> ReturnOption<(SQLSMALLINT, SQLSMALLINT)> { self.handle.data_sources( direction, server_name, description, ) } /// Fills buffers with information about the available datasources /// /// A 32 / 64 Bit Application will only return information about either 32 or 64 Bit /// DataSources. /// /// # Returns /// /// (description_length, attributes_length) /// /// See [SQLDrivers][1] /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldrivers-function pub fn drivers( &mut self, direction: FetchOrientation, description: &mut [u8], attributes: &mut [u8], ) -> ReturnOption<(SQLSMALLINT, SQLSMALLINT)> { self.handle.drivers(direction, description, attributes) } } impl Environment<NoVersion> { /// Allocates a new `Environment` pub fn new() -> Return<Self> { HEnv::allocate().map(|handle| { Environment { version: PhantomData, handle: handle, } }) } /// Before an application allocates a connection which specification it follows. Currently /// these bindings only support ODBC 3.x. /// /// It is valid to specify ODBC 3.x even then connecting to an ODBC 2.x driver. Applications /// must however avoid calling 3.x functionality on 2.x drivers. Since drivers are connected at /// runtime, these kind of errors can not be catched by the type system. pub fn declare_version<V: Version>(mut self) -> Return<Environment<V>, Environment<NoVersion>> { let result = self.handle.declare_version(V::constant()); match result { Success(()) => Success(self.transit()), Info(()) => Success(self.transit()), Error(()) => Success(self.transit()), } } /// Before an application allocates a connection which specification it follows. Currently /// these bindings only support ODBC 3.x. /// /// It is valid to specify ODBC 3.x even then connecting to an ODBC 2.x driver. Applications /// must however avoid calling 3.x functionality on 2.x drivers. Since drivers are connected at /// runtime, these kind of errors can not be catched by the type system. /// /// This method is a shorthand for `declare_version::<Odbc3m8>`. pub fn declare_version_3_8(self) -> Return<Environment<Odbc3m8>, Environment<NoVersion>> { self.declare_version() } /// Before an application allocates a connection which specification it follows. Currently /// these bindings only support ODBC 3.x. /// /// It is valid to specify ODBC 3.x even then connecting to an ODBC 2.x driver. Applications /// must however avoid calling 3.x functionality on 2.x drivers. Since drivers are connected at /// runtime, these kind of errors can not be catched by the type system. /// /// This method is a shorthand for `declare_version::<Odbc3>`. pub fn declare_version_3(self) -> Return<Environment<Odbc3>, Environment<NoVersion>> { self.declare_version() } } impl<V> Diagnostics for Environment<V> { fn diagnostics( &self, rec_number: SQLSMALLINT, message_text: &mut [SQLCHAR], ) -> ReturnOption<DiagResult> { self.handle.diagnostics(rec_number, message_text) } }