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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML
><HEAD
><TITLE
>Ada95 aspects of the ODBC binding</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="GNADE User's Guide"
HREF="gnade.html"><LINK
REL="UP"
TITLE="ODBC bindings for Ada 95"
HREF="odbc.html"><LINK
REL="PREVIOUS"
TITLE="Building ODBC based programs"
HREF="odbc_ch02.html"><LINK
REL="NEXT"
TITLE="Native Bindings"
HREF="bindings.html"></HEAD
><BODY
CLASS="CHAPTER"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>GNADE User's Guide: GNADE, The GNat Ada Database Environment; Version 1.5.0; Document Revision $Revision: 1.42 $</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="odbc_ch02.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="bindings.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="CHAPTER"
><H1
><A
NAME="ADAODBC"
></A
>Chapter 16. Ada95 aspects of the ODBC binding</H1
><P
>The ODBC API typically maintains a set of resources on behalf of the
calling application, such as an ODBC Environment, Connections, Statements
etc. All those resources have attributes that can be set or get by an
application. These attributes have different data types.</P
><P
>As a rather low level API ODBC is oriented to wards low level languages like C.
For the above mentioned access to the attributes of various resources the API
implements calls in such a way that you have to specify a pointer to a chunk
of memory and a parameter containing the length of this area in bytes and
then the API fills the area of memory with data or reads data from the area.
It's up to the caller to make sure that the so described memory area contains
valid data of a type expected by the call. A "C" language prototype of a
typical call of this category looks like this:
<PRE
CLASS="PROGRAMLISTING"
>SQLRETURN SQLGetConnectAttr(
SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER Value,
SQLINTEGER BufferLength,
SQLINTEGER *StringLength);
SQLRETURN SQLSetConnectAttr(
SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER Value,
SQLINTEGER StringLength);</PRE
></P
><P
>The parameter "Attribute" is actually an enumeration. An integer number denotes
the attribute you're interested in. Different attributes have different
data types and there is no rule for the mapping of attributes to their type. You
have to read the documentation!</P
><P
>We think this is not the level of type safety we should provide to Ada95 clients
of this API. We therefore implemented the following scheme to deal with this
mapping problem. We will not describe the internals of this scheme here, but
how to use it in your application.</P
><P
>The core of the mapping mechanism is the generic package GNU.DB.SQLCLI.Dispatch
which you never will instantiate directly. Lets for example take the connection
attributes of the ODBC API to demonstrate the use. You'll find the connection
attribute handling in the package GNU.DB.SQLCLI.Connection_Attribute. What you
find there is an enumeration type named SQL_CONNECTION_ATTRIBUTE. This type
represents the plain SQLINTEGER parameter of the above mentioned C API call. In
this package you'll find these instantiations:
<PRE
CLASS="PROGRAMLISTING"
> package Connection_Attributes is
new GNU.DB.SQLCLI.Generic_Attr (Context => SQLHDBC,
T => SQL_CONNECTION_ATTRIBUTE,
Base => SQLINTEGER,
Get => Get_Connect_Attr,
Set => Set_Connect_Attr,
Default_Context => Null_Handle);
subtype Connection_Attribute is
Connection_Attributes.Attribute_Value_Pair;
package Dispatch is new GNU.DB.SQLCLI (Connection_Attribute);</PRE
>
The generic package GNU.DB.SQLCLI.Generic_Attr defines an abstract tagged type
Attribute_Value_Pair. This type has a single component: "Attribute", which is of the
enumeration type to be mapped (formal parameter T in the above
instantiation). There exist derived types from this abstract type for the
various data types that are possible as attributes (bitmap, boolean,
boolean_string, context, enumerated, integer, pointer, string, unsigned). All
these derived types add one additional component to the abstract base type:
"Value" whose type is selected according to the needs of the attribute to be
mapped.</P
><P
>The dispatch package has the instantiation of the generic as parameter and does
set up internally all mappings necessary to return a correctly typed
Attribute_Value_Pair'Class for an attribute enumeration value. The C API calls
now translate into these Ada95 calls:
<PRE
CLASS="PROGRAMLISTING"
> function SQLGetConnectAttr
(ConnectionHandle : SQLHDBC;
Attribute : SQL_CONNECTION_ATTRIBUTE;
MaxLength : SQLSMALLINT := SQL_MAX_OPTION_STRING_LENGTH)
return Connection_Attribute'Class;
procedure SQLSetConnectAttr
(ConnectionHandle : in SQLHDBC;
AttrRec : in Connection_Attribute'Class);</PRE
>
If you look into the package GNU.DB.SQLCLI.Connection_Attribute you for example
find there this definition
<PRE
CLASS="PROGRAMLISTING"
> type ACCESS_MODE is (SQL_MODE_READ_WRITE,
SQL_MODE_READ_ONLY);
for ACCESS_MODE'Size use SQLINTEGER'Size;
SQL_MODE_DEFAULT : constant ACCESS_MODE := SQL_MODE_READ_WRITE;
package Dsp_Access_Mode is new
Dispatch.A_Enumerated (SQL_ATTR_ACCESS_MODE,
ACCESS_MODE,
SQLINTEGER,
"ACCESS_MODE");
subtype Connection_Attribute_Mode is Dsp_Access_Mode.Info;</PRE
>
From this you can see that the connection attribute SQL_ATTR_ACCESS_MODE is
mapped to an enumerated type ACCESS_MODE. So a call to set the access mode looks
like this:
<PRE
CLASS="PROGRAMLISTING"
> SQLSetConnectAttr (connHandle,
Connection_Attribute_Mode'(
Attribute => SQL_ATTR_ACCESS_MODE,
Value => SQL_MODE_READ_ONLY)
);</PRE
>
and a call to get the attribute may look like this:
<PRE
CLASS="PROGRAMLISTING"
> declare
attr : Connection_Attribute_Mode;
begin
attr := Connection_Attribute_Mode(
SQLGetConnectAttr (connHandle, SQL_ATTR_ACCESS_MODE)
);
end;</PRE
>
Note that the type conversion is required to do the dynamic type check of the
function return which returns a Connection_Attribute'Class value.</P
><P
>You'll find this technique in these packages:
<P
></P
><UL
><LI
STYLE="list-style-type: opencircle"
><P
> GNU.DB.SQLCLI.Info
</P
></LI
><LI
STYLE="list-style-type: opencircle"
><P
> GNU.DB.SQLCLI.Connection_Attribute
</P
></LI
><LI
STYLE="list-style-type: opencircle"
><P
> GNU.DB.SQLCLI.Statement_Attribute
</P
></LI
><LI
STYLE="list-style-type: opencircle"
><P
> GNU.DB.SQLCLI.Environment_Attribute
</P
></LI
></UL
></P
><P
>Due to the dynamic type checking implemented for the attribute handling, all
calls dealing with attributes will cost some more cycles than a direct call to
the plain C API. All other ODBC calls are a very thin layer around the C
API. As attribute set/get calls are rare compared to queries etc. this is
acceptable. But it explains while a - in theory - thin binding is compiled into
a rather huge library. This is because all the type mapping information is
compiled into the library.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="odbc_ch02.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="gnade.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="bindings.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Building ODBC based programs</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="odbc.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Native Bindings</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
|