My favorites | Sign in
Project Home Downloads Wiki Issues Source
Repository:
Checkout   Browse   Changes   Clones  
Changes to /src/pyodbcmodule.cpp
b2dfac9a0b88 vs. 7555f7da7d11 Compare: vs.  Format:
Revision 7555f7da7d11
Go to: 
Sign in to write a code review
/src/pyodbcmodule.cpp   b2dfac9a0b88 /src/pyodbcmodule.cpp   7555f7da7d11
1 1
2 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 2 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
3 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 3 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
4 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 4 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
5 // permit persons to whom the Software is furnished to do so. 5 // permit persons to whom the Software is furnished to do so.
6 // 6 //
7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
8 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 8 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
9 // OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 9 // OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
10 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 11
12 #include "pyodbc.h" 12 #include "pyodbc.h"
13 #include "pyodbcmodule.h" 13 #include "pyodbcmodule.h"
14 #include "connection.h" 14 #include "connection.h"
15 #include "cursor.h" 15 #include "cursor.h"
16 #include "row.h" 16 #include "row.h"
17 #include "wrapper.h" 17 #include "wrapper.h"
18 #include "errors.h" 18 #include "errors.h"
19 #include "getdata.h" 19 #include "getdata.h"
20 #include "cnxninfo.h" 20 #include "cnxninfo.h"
21 #include "params.h" 21 #include "params.h"
22 #include "dbspecific.h" 22 #include "dbspecific.h"
23 #include <datetime.h> 23 #include <datetime.h>
24 24
25 #include <time.h> 25 #include <time.h>
26 #include <stdarg.h> 26 #include <stdarg.h>
27 27
28 static PyObject* MakeConnectionString(PyObject* existing, PyObject* parts); 28 static PyObject* MakeConnectionString(PyObject* existing, PyObject* parts);
29 29
30 PyObject* pModule = 0; 30 PyObject* pModule = 0;
31 31
32 static char module_doc[] = 32 static char module_doc[] =
33 "A database module for accessing databases via ODBC.\n" 33 "A database module for accessing databases via ODBC.\n"
34 "\n" 34 "\n"
35 "This module conforms to the DB API 2.0 specification while providing\n" 35 "This module conforms to the DB API 2.0 specification while providing\n"
36 "non-standard convenience features. Only standard Python data types are used\n" 36 "non-standard convenience features. Only standard Python data types are used\n"
37 "so additional DLLs are not required.\n" 37 "so additional DLLs are not required.\n"
38 "\n" 38 "\n"
39 "Static Variables:\n\n" 39 "Static Variables:\n\n"
40 "version\n" 40 "version\n"
41 " The module version string. Official builds will have a version in the format\n" 41 " The module version string. Official builds will have a version in the format\n"
42 " `major.minor.revision`, such as 2.1.7. Beta versions will have -beta appended,\n" 42 " `major.minor.revision`, such as 2.1.7. Beta versions will have -beta appended,\n"
43 " such as 2.1.8-beta03. (This would be a build before the official 2.1.8 release.)\n" 43 " such as 2.1.8-beta03. (This would be a build before the official 2.1.8 release.)\n"
44 " Some special test builds will have a test name (the git branch name) prepended,\n" 44 " Some special test builds will have a test name (the git branch name) prepended,\n"
45 " such as fixissue90-2.1.8-beta03.\n" 45 " such as fixissue90-2.1.8-beta03.\n"
46 "\n" 46 "\n"
47 "apilevel\n" 47 "apilevel\n"
48 " The string constant '2.0' indicating this module supports DB API level 2.0.\n" 48 " The string constant '2.0' indicating this module supports DB API level 2.0.\n"
49 "\n" 49 "\n"
50 "lowercase\n" 50 "lowercase\n"
51 " A Boolean that controls whether column names in result rows are lowercased.\n" 51 " A Boolean that controls whether column names in result rows are lowercased.\n"
52 " This can be changed any time and affects queries executed after the change.\n" 52 " This can be changed any time and affects queries executed after the change.\n"
53 " The default is False. This can be useful when database columns have\n" 53 " The default is False. This can be useful when database columns have\n"
54 " inconsistent capitalization.\n" 54 " inconsistent capitalization.\n"
55 "\n" 55 "\n"
56 "pooling\n" 56 "pooling\n"
57 " A Boolean indicating whether connection pooling is enabled. This is a\n" 57 " A Boolean indicating whether connection pooling is enabled. This is a\n"
58 " global (HENV) setting, so it can only be modified before the first\n" 58 " global (HENV) setting, so it can only be modified before the first\n"
59 " connection is made. The default is True, which enables ODBC connection\n" 59 " connection is made. The default is True, which enables ODBC connection\n"
60 " pooling.\n" 60 " pooling.\n"
61 "\n" 61 "\n"
62 "threadsafety\n" 62 "threadsafety\n"
63 " The integer 1, indicating that threads may share the module but not\n" 63 " The integer 1, indicating that threads may share the module but not\n"
64 " connections. Note that connections and cursors may be used by different\n" 64 " connections. Note that connections and cursors may be used by different\n"
65 " threads, just not at the same time.\n" 65 " threads, just not at the same time.\n"
66 "\n" 66 "\n"
67 "qmark\n" 67 "qmark\n"
68 " The string constant 'qmark' to indicate parameters are identified using\n" 68 " The string constant 'qmark' to indicate parameters are identified using\n"
69 " question marks."; 69 " question marks.";
70 70
71 PyObject* Error; 71 PyObject* Error;
72 PyObject* Warning; 72 PyObject* Warning;
73 PyObject* InterfaceError; 73 PyObject* InterfaceError;
74 PyObject* DatabaseError; 74 PyObject* DatabaseError;
75 PyObject* InternalError; 75 PyObject* InternalError;
76 PyObject* OperationalError; 76 PyObject* OperationalError;
77 PyObject* ProgrammingError; 77 PyObject* ProgrammingError;
78 PyObject* IntegrityError; 78 PyObject* IntegrityError;
79 PyObject* DataError; 79 PyObject* DataError;
80 PyObject* NotSupportedError; 80 PyObject* NotSupportedError;
81 81
82 struct ExcInfo 82 struct ExcInfo
83 { 83 {
84 const char* szName; 84 const char* szName;
85 const char* szFullName; 85 const char* szFullName;
86 PyObject** ppexc; 86 PyObject** ppexc;
87 PyObject** ppexcParent; 87 PyObject** ppexcParent;
88 const char* szDoc; 88 const char* szDoc;
89 }; 89 };
90 90
91 #define MAKEEXCINFO(name, parent, doc) { #name, "pyodbc." #name, &name, &parent, doc } 91 #define MAKEEXCINFO(name, parent, doc) { #name, "pyodbc." #name, &name, &parent, doc }
92 92
93 static ExcInfo aExcInfos[] = { 93 static ExcInfo aExcInfos[] = {
94 MAKEEXCINFO(Error, PyExc_Exception, 94 MAKEEXCINFO(Error, PyExc_Exception,
95 "Exception that is the base class of all other error exceptions. You can use\n" 95 "Exception that is the base class of all other error exceptions. You can use\n"
96 "this to catch all errors with one single 'except' statement."), 96 "this to catch all errors with one single 'except' statement."),
97 MAKEEXCINFO(Warning, PyExc_Exception, 97 MAKEEXCINFO(Warning, PyExc_Exception,
98 "Exception raised for important warnings like data truncations while inserting,\n" 98 "Exception raised for important warnings like data truncations while inserting,\n"
99 " etc."), 99 " etc."),
100 MAKEEXCINFO(InterfaceError, Error, 100 MAKEEXCINFO(InterfaceError, Error,
101 "Exception raised for errors that are related to the database interface rather\n" 101 "Exception raised for errors that are related to the database interface rather\n"
102 "than the database itself."), 102 "than the database itself."),
103 MAKEEXCINFO(DatabaseError, Error, "Exception raised for errors that are related to the database."), 103 MAKEEXCINFO(DatabaseError, Error, "Exception raised for errors that are related to the database."),
104 MAKEEXCINFO(DataError, DatabaseError, 104 MAKEEXCINFO(DataError, DatabaseError,
105 "Exception raised for errors that are due to problems with the processed data\n" 105 "Exception raised for errors that are due to problems with the processed data\n"
106 "like division by zero, numeric value out of range, etc."), 106 "like division by zero, numeric value out of range, etc."),
107 MAKEEXCINFO(OperationalError, DatabaseError, 107 MAKEEXCINFO(OperationalError, DatabaseError,
108 "Exception raised for errors that are related to the database's operation and\n" 108 "Exception raised for errors that are related to the database's operation and\n"
109 "not necessarily under the control of the programmer, e.g. an unexpected\n" 109 "not necessarily under the control of the programmer, e.g. an unexpected\n"
110 "disconnect occurs, the data source name is not found, a transaction could not\n" 110 "disconnect occurs, the data source name is not found, a transaction could not\n"
111 "be processed, a memory allocation error occurred during processing, etc."), 111 "be processed, a memory allocation error occurred during processing, etc."),
112 MAKEEXCINFO(IntegrityError, DatabaseError, 112 MAKEEXCINFO(IntegrityError, DatabaseError,
113 "Exception raised when the relational integrity of the database is affected,\n" 113 "Exception raised when the relational integrity of the database is affected,\n"
114 "e.g. a foreign key check fails."), 114 "e.g. a foreign key check fails."),
115 MAKEEXCINFO(InternalError, DatabaseError, 115 MAKEEXCINFO(InternalError, DatabaseError,
116 "Exception raised when the database encounters an internal error, e.g. the\n" 116 "Exception raised when the database encounters an internal error, e.g. the\n"
117 "cursor is not valid anymore, the transaction is out of sync, etc."), 117 "cursor is not valid anymore, the transaction is out of sync, etc."),
118 MAKEEXCINFO(ProgrammingError, DatabaseError, 118 MAKEEXCINFO(ProgrammingError, DatabaseError,
119 "Exception raised for programming errors, e.g. table not found or already\n" 119 "Exception raised for programming errors, e.g. table not found or already\n"
120 "exists, syntax error in the SQL statement, wrong number of parameters\n" 120 "exists, syntax error in the SQL statement, wrong number of parameters\n"
121 "specified, etc."), 121 "specified, etc."),
122 MAKEEXCINFO(NotSupportedError, DatabaseError, 122 MAKEEXCINFO(NotSupportedError, DatabaseError,
123 "Exception raised in case a method or database API was used which is not\n" 123 "Exception raised in case a method or database API was used which is not\n"
124 "supported by the database, e.g. requesting a .rollback() on a connection that\n" 124 "supported by the database, e.g. requesting a .rollback() on a connection that\n"
125 "does not support transaction or has transactions turned off.") 125 "does not support transaction or has transactions turned off.")
126 }; 126 };
127 127
128 128
129 PyObject* decimal_type; 129 PyObject* decimal_type;
130 130
131 HENV henv = SQL_NULL_HANDLE; 131 HENV henv = SQL_NULL_HANDLE;
132 132
133 Py_UNICODE chDecimal = '.'; 133 Py_UNICODE chDecimal = '.';
134 134
135 // Initialize the global decimal character and thousands separator character, used when parsing decimal 135 // Initialize the global decimal character and thousands separator character, used when parsing decimal
136 // objects. 136 // objects.
137 // 137 //
138 static void init_locale_info() 138 static void init_locale_info()
139 { 139 {
140 Object module = PyImport_ImportModule("locale"); 140 Object module = PyImport_ImportModule("locale");
141 if (!module) 141 if (!module)
142 { 142 {
143 PyErr_Clear(); 143 PyErr_Clear();
144 return; 144 return;
145 } 145 }
146 146
147 Object ldict = PyObject_CallMethod(module, "localeconv", 0); 147 Object ldict = PyObject_CallMethod(module, "localeconv", 0);
148 if (!ldict) 148 if (!ldict)
149 { 149 {
150 PyErr_Clear(); 150 PyErr_Clear();
151 return; 151 return;
152 } 152 }
153 153
154 PyObject* value = PyDict_GetItemString(ldict, "decimal_point"); 154 PyObject* value = PyDict_GetItemString(ldict, "decimal_point");
155 if (value) 155 if (value)
156 { 156 {
157 if (PyBytes_Check(value) && PyBytes_Size(value) == 1) 157 if (PyBytes_Check(value) && PyBytes_Size(value) == 1)
158 chDecimal = (Py_UNICODE)PyBytes_AS_STRING(value)[0]; 158 chDecimal = (Py_UNICODE)PyBytes_AS_STRING(value)[0];
159 if (PyUnicode_Check(value) && PyUnicode_GET_SIZE(value) == 1) 159 if (PyUnicode_Check(value) && PyUnicode_GET_SIZE(value) == 1)
160 chDecimal = PyUnicode_AS_UNICODE(value)[0]; 160 chDecimal = PyUnicode_AS_UNICODE(value)[0];
161 } 161 }
162 } 162 }
163 163
164 164
165 static bool import_types() 165 static bool import_types()
166 { 166 {
167 // In Python 2.5 final, PyDateTime_IMPORT no longer works unless the datetime module was previously 167 // In Python 2.5 final, PyDateTime_IMPORT no longer works unless the datetime module was previously
168 // imported (among other problems). 168 // imported (among other problems).
169 169
170 PyObject* pdt = PyImport_ImportModule("datetime"); 170 PyObject* pdt = PyImport_ImportModule("datetime");
171 171
172 if (!pdt) 172 if (!pdt)
173 return false; 173 return false;
174 174
175 PyDateTime_IMPORT; 175 PyDateTime_IMPORT;
176 176
177 Cursor_init(); 177 Cursor_init();
178 CnxnInfo_init(); 178 CnxnInfo_init();
179 GetData_init(); 179 GetData_init();
180 if (!Params_init()) 180 if (!Params_init())
181 return false; 181 return false;
182 182
183 PyObject* decimalmod = PyImport_ImportModule("decimal"); 183 PyObject* decimalmod = PyImport_ImportModule("decimal");
184 if (!decimalmod) 184 if (!decimalmod)
185 { 185 {
186 PyErr_SetString(PyExc_RuntimeError, "Unable to import decimal"); 186 PyErr_SetString(PyExc_RuntimeError, "Unable to import decimal");
187 return false; 187 return false;
188 } 188 }
189 189
190 decimal_type = PyObject_GetAttrString(decimalmod, "Decimal"); 190 decimal_type = PyObject_GetAttrString(decimalmod, "Decimal");
191 Py_DECREF(decimalmod); 191 Py_DECREF(decimalmod);
192 192
193 if (decimal_type == 0) 193 if (decimal_type == 0)
194 PyErr_SetString(PyExc_RuntimeError, "Unable to import decimal.Decimal."); 194 PyErr_SetString(PyExc_RuntimeError, "Unable to import decimal.Decimal.");
195 195
196 return decimal_type != 0; 196 return decimal_type != 0;
197 } 197 }
198 198
199 199
200 static bool AllocateEnv() 200 static bool AllocateEnv()
201 { 201 {
202 PyObject* pooling = PyObject_GetAttrString(pModule, "pooling"); 202 PyObject* pooling = PyObject_GetAttrString(pModule, "pooling");
203 bool bPooling = pooling == Py_True; 203 bool bPooling = pooling == Py_True;
204 Py_DECREF(pooling); 204 Py_DECREF(pooling);
205 205
206 if (bPooling) 206 if (bPooling)
207 { 207 {
208 if (!SQL_SUCCEEDED(SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)SQL_CP_ONE_PER_HENV, sizeof(int)))) 208 if (!SQL_SUCCEEDED(SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)SQL_CP_ONE_PER_HENV, sizeof(int))))
209 { 209 {
210 Py_FatalError("Unable to set SQL_ATTR_CONNECTION_POOLING attribute."); 210 Py_FatalError("Unable to set SQL_ATTR_CONNECTION_POOLING attribute.");
211 return false; 211 return false;
212 } 212 }
213 } 213 }
214 214
215 if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv))) 215 if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv)))
216 { 216 {
217 Py_FatalError("Can't initialize module pyodbc. SQLAllocEnv failed."); 217 Py_FatalError("Can't initialize module pyodbc. SQLAllocEnv failed.");
218 return false; 218 return false;
219 } 219 }
220 220
221 if (!SQL_SUCCEEDED(SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, sizeof(int)))) 221 if (!SQL_SUCCEEDED(SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, sizeof(int))))
222 { 222 {
223 Py_FatalError("Unable to set SQL_ATTR_ODBC_VERSION attribute."); 223 Py_FatalError("Unable to set SQL_ATTR_ODBC_VERSION attribute.");
224 return false; 224 return false;
225 } 225 }
226 226
227 return true; 227 return true;
228 } 228 }
229 229
230 // Map DB API recommended keywords to ODBC keywords. 230 // Map DB API recommended keywords to ODBC keywords.
231 231
232 struct keywordmap 232 struct keywordmap
233 { 233 {
234 const char* oldname; 234 const char* oldname;
235 const char* newname; 235 const char* newname;
236 PyObject* newnameObject; // PyString object version of newname, created as needed. 236 PyObject* newnameObject; // PyString object version of newname, created as needed.
237 }; 237 };
238 238
239 static keywordmap keywordmaps[] = 239 static keywordmap keywordmaps[] =
240 { 240 {
241 { "user", "uid", 0 }, 241 { "user", "uid", 0 },
242 { "password", "pwd", 0 }, 242 { "password", "pwd", 0 },
243 { "host", "server", 0 }, 243 { "host", "server", 0 },
244 }; 244 };
245 245
246 246
247 static PyObject* mod_connect(PyObject* self, PyObject* args, PyObject* kwargs) 247 static PyObject* mod_connect(PyObject* self, PyObject* args, PyObject* kwargs)
248 { 248 {
249 UNUSED(self); 249 UNUSED(self);
250 250
251 Object pConnectString = 0; 251 Object pConnectString = 0;
252 int fAutoCommit = 0; 252 int fAutoCommit = 0;
253 int fAnsi = 0; // force ansi 253 int fAnsi = 0; // force ansi
254 int fUnicodeResults = 0; 254 int fUnicodeResults = 0;
255 int fReadOnly = 0;
255 long timeout = 0; 256 long timeout = 0;
256 257
257 Py_ssize_t size = args ? PyTuple_Size(args) : 0; 258 Py_ssize_t size = args ? PyTuple_Size(args) : 0;
258 259
259 if (size > 1) 260 if (size > 1)
260 { 261 {
261 PyErr_SetString(PyExc_TypeError, "function takes at most 1 non-keyword argument"); 262 PyErr_SetString(PyExc_TypeError, "function takes at most 1 non-keyword argument");
262 return 0; 263 return 0;
263 } 264 }
264 265
265 if (size == 1) 266 if (size == 1)
266 { 267 {
267 if (!PyString_Check(PyTuple_GET_ITEM(args, 0)) && !PyUnicode_Check(PyTuple_GET_ITEM(args, 0))) 268 if (!PyString_Check(PyTuple_GET_ITEM(args, 0)) && !PyUnicode_Check(PyTuple_GET_ITEM(args, 0)))
268 return PyErr_Format(PyExc_TypeError, "argument 1 must be a string or unicode object"); 269 return PyErr_Format(PyExc_TypeError, "argument 1 must be a string or unicode object");
269 270
270 pConnectString.Attach(PyUnicode_FromObject(PyTuple_GetItem(args, 0))); 271 pConnectString.Attach(PyUnicode_FromObject(PyTuple_GetItem(args, 0)));
271 if (!pConnectString.IsValid()) 272 if (!pConnectString.IsValid())
272 return 0; 273 return 0;
273 } 274 }
274 275
275 if (kwargs && PyDict_Size(kwargs) > 0) 276 if (kwargs && PyDict_Size(kwargs) > 0)
276 { 277 {
277 Object partsdict(PyDict_New()); 278 Object partsdict(PyDict_New());
278 if (!partsdict.IsValid()) 279 if (!partsdict.IsValid())
279 return 0; 280 return 0;
280 281
281 Py_ssize_t pos = 0; 282 Py_ssize_t pos = 0;
282 PyObject* key = 0; 283 PyObject* key = 0;
283 PyObject* value = 0; 284 PyObject* value = 0;
284 285
285 Object okey; // in case we need to allocate a new key 286 Object okey; // in case we need to allocate a new key
286 287
287 while (PyDict_Next(kwargs, &pos, &key, &value)) 288 while (PyDict_Next(kwargs, &pos, &key, &value))
288 { 289 {
289 if (!Text_Check(key)) 290 if (!Text_Check(key))
290 return PyErr_Format(PyExc_TypeError, "Dictionary items passed to connect must be strings"); 291 return PyErr_Format(PyExc_TypeError, "Dictionary items passed to connect must be strings");
291 292
292 // // Note: key and value are *borrowed*. 293 // // Note: key and value are *borrowed*.
293 // 294 //
294 // // Check for the two non-connection string keywords we accept. (If we get many more of these, create something 295 // // Check for the two non-connection string keywords we accept. (If we get many more of these, create something
295 // // table driven. Are we sure there isn't a Python function to parse keywords but leave those it doesn't know?) 296 // // table driven. Are we sure there isn't a Python function to parse keywords but leave those it doesn't know?)
296 // const char* szKey = PyString_AsString(key); 297 // const char* szKey = PyString_AsString(key);
297 298
298 if (Text_EqualsI(key, "autocommit")) 299 if (Text_EqualsI(key, "autocommit"))
299 { 300 {
300 fAutoCommit = PyObject_IsTrue(value); 301 fAutoCommit = PyObject_IsTrue(value);
301 continue; 302 continue;
302 } 303 }
303 if (Text_EqualsI(key, "ansi")) 304 if (Text_EqualsI(key, "ansi"))
304 { 305 {
305 fAnsi = PyObject_IsTrue(value); 306 fAnsi = PyObject_IsTrue(value);
306 continue; 307 continue;
307 } 308 }
308 if (Text_EqualsI(key, "unicode_results")) 309 if (Text_EqualsI(key, "unicode_results"))
309 { 310 {
310 fUnicodeResults = PyObject_IsTrue(value); 311 fUnicodeResults = PyObject_IsTrue(value);
311 continue; 312 continue;
312 } 313 }
313 if (Text_EqualsI(key, "timeout")) 314 if (Text_EqualsI(key, "timeout"))
314 { 315 {
315 timeout = PyInt_AsLong(value); 316 timeout = PyInt_AsLong(value);
316 if (PyErr_Occurred()) 317 if (PyErr_Occurred())
317 return 0; 318 return 0;
318 continue; 319 continue;
319 } 320 }
321 if (Text_EqualsI(key, "readonly"))
322 {
323 fReadOnly = PyObject_IsTrue(value);
324 continue;
325 }
320 326
321 // Map DB API recommended names to ODBC names (e.g. user --> uid). 327 // Map DB API recommended names to ODBC names (e.g. user --> uid).
322 328
323 for (size_t i = 0; i < _countof(keywordmaps); i++) 329 for (size_t i = 0; i < _countof(keywordmaps); i++)
324 { 330 {
325 if (Text_EqualsI(key, keywordmaps[i].oldname)) 331 if (Text_EqualsI(key, keywordmaps[i].oldname))
326 { 332 {
327 if (keywordmaps[i].newnameObject == 0) 333 if (keywordmaps[i].newnameObject == 0)
328 { 334 {
329 keywordmaps[i].newnameObject = PyString_FromString(keywordmaps[i].newname); 335 keywordmaps[i].newnameObject = PyString_FromString(keywordmaps[i].newname);
330 if (keywordmaps[i].newnameObject == 0) 336 if (keywordmaps[i].newnameObject == 0)
331 return 0; 337 return 0;
332 } 338 }
333 339
334 key = keywordmaps[i].newnameObject; 340 key = keywordmaps[i].newnameObject;
335 break; 341 break;
336 } 342 }
337 } 343 }
338 344
339 PyObject* str = PyObject_Str(value); // convert if necessary 345 PyObject* str = PyObject_Str(value); // convert if necessary
340 if (!str) 346 if (!str)
341 return 0; 347 return 0;
342 348
343 if (PyDict_SetItem(partsdict.Get(), key, str) == -1) 349 if (PyDict_SetItem(partsdict.Get(), key, str) == -1)
344 { 350 {
345 Py_XDECREF(str); 351 Py_XDECREF(str);
346 return 0; 352 return 0;
347 } 353 }
348 354
349 Py_XDECREF(str); 355 Py_XDECREF(str);
350 } 356 }
351 357
352 if (PyDict_Size(partsdict.Get())) 358 if (PyDict_Size(partsdict.Get()))
353 pConnectString.Attach(MakeConnectionString(pConnectString.Get(), partsdict)); 359 pConnectString.Attach(MakeConnectionString(pConnectString.Get(), partsdict));
354 } 360 }
355 361
356 if (!pConnectString.IsValid()) 362 if (!pConnectString.IsValid())
357 return PyErr_Format(PyExc_TypeError, "no connection information was passed"); 363 return PyErr_Format(PyExc_TypeError, "no connection information was passed");
358 364
359 if (henv == SQL_NULL_HANDLE) 365 if (henv == SQL_NULL_HANDLE)
360 { 366 {
361 if (!AllocateEnv()) 367 if (!AllocateEnv())
362 return 0; 368 return 0;
363 } 369 }
364 370
365 return (PyObject*)Connection_New(pConnectString.Get(), fAutoCommit != 0, fAnsi != 0, fUnicodeResults != 0, timeout); 371 return (PyObject*)Connection_New(pConnectString.Get(), fAutoCommit != 0, fAnsi != 0, fUnicodeResults != 0, timeout, fReadOnly != 0);
366 } 372 }
367 373
368 374
369 static PyObject* mod_datasources(PyObject* self) 375 static PyObject* mod_datasources(PyObject* self)
370 { 376 {
371 UNUSED(self); 377 UNUSED(self);
372 378
373 if (henv == SQL_NULL_HANDLE && !AllocateEnv()) 379 if (henv == SQL_NULL_HANDLE && !AllocateEnv())
374 return 0; 380 return 0;
375 381
376 PyObject* result = PyDict_New(); 382 PyObject* result = PyDict_New();
377 if (!result) 383 if (!result)
378 return 0; 384 return 0;
379 385
380 SQLCHAR szDSN[SQL_MAX_DSN_LENGTH]; 386 SQLCHAR szDSN[SQL_MAX_DSN_LENGTH];
381 SWORD cbDSN; 387 SWORD cbDSN;
382 SQLCHAR szDesc[200]; 388 SQLCHAR szDesc[200];
383 SWORD cbDesc; 389 SWORD cbDesc;
384 390
385 SQLUSMALLINT nDirection = SQL_FETCH_FIRST; 391 SQLUSMALLINT nDirection = SQL_FETCH_FIRST;
386 392
387 SQLRETURN ret; 393 SQLRETURN ret;
388 394
389 for (;;) 395 for (;;)
390 { 396 {
391 Py_BEGIN_ALLOW_THREADS 397 Py_BEGIN_ALLOW_THREADS
392 ret = SQLDataSources(henv, nDirection, szDSN, _countof(szDSN), &cbDSN, szDesc, _countof(szDesc), &cbDesc); 398 ret = SQLDataSources(henv, nDirection, szDSN, _countof(szDSN), &cbDSN, szDesc, _countof(szDesc), &cbDesc);
393 Py_END_ALLOW_THREADS 399 Py_END_ALLOW_THREADS
394 if (!SQL_SUCCEEDED(ret)) 400 if (!SQL_SUCCEEDED(ret))
395 break; 401 break;
396 402
397 PyDict_SetItemString(result, (const char*)szDSN, PyString_FromString((const char*)szDesc)); 403 PyDict_SetItemString(result, (const char*)szDSN, PyString_FromString((const char*)szDesc));
398 nDirection = SQL_FETCH_NEXT; 404 nDirection = SQL_FETCH_NEXT;
399 } 405 }
400 406
401 if (ret != SQL_NO_DATA) 407 if (ret != SQL_NO_DATA)
402 { 408 {
403 Py_DECREF(result); 409 Py_DECREF(result);
404 return RaiseErrorFromHandle("SQLDataSources", SQL_NULL_HANDLE, SQL_NULL_HANDLE); 410 return RaiseErrorFromHandle("SQLDataSources", SQL_NULL_HANDLE, SQL_NULL_HANDLE);
405 } 411 }
406 412
407 return result; 413 return result;
408 } 414 }
409 415
410 416
411 static PyObject* mod_timefromticks(PyObject* self, PyObject* args) 417 static PyObject* mod_timefromticks(PyObject* self, PyObject* args)
412 { 418 {
413 UNUSED(self); 419 UNUSED(self);
414 420
415 PyObject* num; 421 PyObject* num;
416 if (!PyArg_ParseTuple(args, "O", &num)) 422 if (!PyArg_ParseTuple(args, "O", &num))
417 return 0; 423 return 0;
418 424
419 if (!PyNumber_Check(num)) 425 if (!PyNumber_Check(num))
420 return PyErr_Format(PyExc_TypeError, "TimeFromTicks requires a number."); 426 return PyErr_Format(PyExc_TypeError, "TimeFromTicks requires a number.");
421 427
422 Object l(PyNumber_Long(num)); 428 Object l(PyNumber_Long(num));
423 if (!l) 429 if (!l)
424 return 0; 430 return 0;
425 431
426 time_t t = PyLong_AsLong(num); 432 time_t t = PyLong_AsLong(num);
427 struct tm* fields = localtime(&t); 433 struct tm* fields = localtime(&t);
428 434
429 return PyTime_FromTime(fields->tm_hour, fields->tm_min, fields->tm_sec, 0); 435 return PyTime_FromTime(fields->tm_hour, fields->tm_min, fields->tm_sec, 0);
430 } 436 }
431 437
432 438
433 static PyObject* mod_datefromticks(PyObject* self, PyObject* args) 439 static PyObject* mod_datefromticks(PyObject* self, PyObject* args)
434 { 440 {
435 UNUSED(self); 441 UNUSED(self);
436 return PyDate_FromTimestamp(args); 442 return PyDate_FromTimestamp(args);
437 } 443 }
438 444
439 445
440 static PyObject* mod_timestampfromticks(PyObject* self, PyObject* args) 446 static PyObject* mod_timestampfromticks(PyObject* self, PyObject* args)
441 { 447 {
442 UNUSED(self); 448 UNUSED(self);
443 return PyDateTime_FromTimestamp(args); 449 return PyDateTime_FromTimestamp(args);
444 } 450 }
445 451
446 452
447 static char connect_doc[] = 453 static char connect_doc[] =
448 "connect(str, autocommit=False, ansi=False, timeout=0, **kwargs) --> Connection\n" 454 "connect(str, autocommit=False, ansi=False, timeout=0, **kwargs) --> Connection\n"
449 "\n" 455 "\n"
450 "Accepts an ODBC connection string and returns a new Connection object.\n" 456 "Accepts an ODBC connection string and returns a new Connection object.\n"
451 "\n" 457 "\n"
452 "The connection string will be passed to SQLDriverConnect, so a DSN connection\n" 458 "The connection string will be passed to SQLDriverConnect, so a DSN connection\n"
453 "can be created using:\n" 459 "can be created using:\n"
454 "\n" 460 "\n"
455 " cnxn = pyodbc.connect('DSN=DataSourceName;UID=user;PWD=password')\n" 461 " cnxn = pyodbc.connect('DSN=DataSourceName;UID=user;PWD=password')\n"
456 "\n" 462 "\n"
457 "To connect without requiring a DSN, specify the driver and connection\n" 463 "To connect without requiring a DSN, specify the driver and connection\n"
458 "information:\n" 464 "information:\n"
459 "\n" 465 "\n"
460 " DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=user;PWD=password\n" 466 " DRIVER={SQL Server};SERVER=localhost;DATABASE=testdb;UID=user;PWD=password\n"
461 "\n" 467 "\n"
462 "Note the use of braces when a value contains spaces. Refer to SQLDriverConnect\n" 468 "Note the use of braces when a value contains spaces. Refer to SQLDriverConnect\n"
463 "documentation or the documentation of your ODBC driver for details.\n" 469 "documentation or the documentation of your ODBC driver for details.\n"
464 "\n" 470 "\n"
465 "The connection string can be passed as the string `str`, as a list of keywords,\n" 471 "The connection string can be passed as the string `str`, as a list of keywords,\n"
466 "or a combination of the two. Any keywords except autocommit, ansi, and timeout\n" 472 "or a combination of the two. Any keywords except autocommit, ansi, and timeout\n"
467 "(see below) are simply added to the connection string.\n" 473 "(see below) are simply added to the connection string.\n"
468 "\n" 474 "\n"
469 " connect('server=localhost;user=me')\n" 475 " connect('server=localhost;user=me')\n"
470 " connect(server='localhost', user='me')\n" 476 " connect(server='localhost', user='me')\n"
471 " connect('server=localhost', user='me')\n" 477 " connect('server=localhost', user='me')\n"
472 "\n" 478 "\n"
473 "The DB API recommends the keywords 'user', 'password', and 'host', but these\n" 479 "The DB API recommends the keywords 'user', 'password', and 'host', but these\n"
474 "are not valid ODBC keywords, so these will be converted to 'uid', 'pwd', and\n" 480 "are not valid ODBC keywords, so these will be converted to 'uid', 'pwd', and\n"
475 "'server'.\n" 481 "'server'.\n"
476 "\n" 482 "\n"
477 "Special Keywords\n" 483 "Special Keywords\n"
478 "\n" 484 "\n"
479 "The following specal keywords are processed by pyodbc and are not added to the\n" 485 "The following specal keywords are processed by pyodbc and are not added to the\n"
480 "connection string. (If you must use these in your connection string, pass them\n" 486 "connection string. (If you must use these in your connection string, pass them\n"
481 "as a string, not as keywords.)\n" 487 "as a string, not as keywords.)\n"
482 "\n" 488 "\n"
483 " autocommit\n" 489 " autocommit\n"
484 " If False or zero, the default, transactions are created automatically as\n" 490 " If False or zero, the default, transactions are created automatically as\n"
485 " defined in the DB API 2. If True or non-zero, the connection is put into\n" 491 " defined in the DB API 2. If True or non-zero, the connection is put into\n"
486 " ODBC autocommit mode and statements are committed automatically.\n" 492 " ODBC autocommit mode and statements are committed automatically.\n"
487 " \n" 493 " \n"
488 " ansi\n" 494 " ansi\n"
489 " By default, pyodbc first attempts to connect using the Unicode version of\n" 495 " By default, pyodbc first attempts to connect using the Unicode version of\n"
490 " SQLDriverConnectW. If the driver returns IM001 indicating it does not\n" 496 " SQLDriverConnectW. If the driver returns IM001 indicating it does not\n"
491 " support the Unicode version, the ANSI version is tried. Any other SQLSTATE\n" 497 " support the Unicode version, the ANSI version is tried. Any other SQLSTATE\n"
492 " is turned into an exception. Setting ansi to true skips the Unicode\n" 498 " is turned into an exception. Setting ansi to true skips the Unicode\n"
493 " attempt and only connects using the ANSI version. This is useful for\n" 499 " attempt and only connects using the ANSI version. This is useful for\n"
494 " drivers that return the wrong SQLSTATE (or if pyodbc is out of date and\n" 500 " drivers that return the wrong SQLSTATE (or if pyodbc is out of date and\n"
495 " should support other SQLSTATEs).\n" 501 " should support other SQLSTATEs).\n"
496 " \n" 502 " \n"
497 " timeout\n" 503 " timeout\n"
498 " An integer login timeout in seconds, used to set the SQL_ATTR_LOGIN_TIMEOUT\n" 504 " An integer login timeout in seconds, used to set the SQL_ATTR_LOGIN_TIMEOUT\n"
499 " attribute of the connection. The default is 0 which means the database's\n" 505 " attribute of the connection. The default is 0 which means the database's\n"
500 " default timeout, if any, is used.\n"; 506 " default timeout, if any, is used.\n";
501 507
502 static char timefromticks_doc[] = 508 static char timefromticks_doc[] =
503 "TimeFromTicks(ticks) --> datetime.time\n" 509 "TimeFromTicks(ticks) --> datetime.time\n"
504 "\n" 510 "\n"
505 "Returns a time object initialized from the given ticks value (number of seconds\n" 511 "Returns a time object initialized from the given ticks value (number of seconds\n"
506 "since the epoch; see the documentation of the standard Python time module for\n" 512 "since the epoch; see the documentation of the standard Python time module for\n"
507 "details)."; 513 "details).";
508 514
509 static char datefromticks_doc[] = 515 static char datefromticks_doc[] =
510 "DateFromTicks(ticks) --> datetime.date\n" \ 516 "DateFromTicks(ticks) --> datetime.date\n" \
511 "\n" \ 517 "\n" \
512 "Returns a date object initialized from the given ticks value (number of seconds\n" \ 518 "Returns a date object initialized from the given ticks value (number of seconds\n" \
513 "since the epoch; see the documentation of the standard Python time module for\n" \ 519 "since the epoch; see the documentation of the standard Python time module for\n" \
514 "details)."; 520 "details).";
515 521
516 static char timestampfromticks_doc[] = 522 static char timestampfromticks_doc[] =
517 "TimestampFromTicks(ticks) --> datetime.datetime\n" \ 523 "TimestampFromTicks(ticks) --> datetime.datetime\n" \
518 "\n" \ 524 "\n" \
519 "Returns a datetime object initialized from the given ticks value (number of\n" \ 525 "Returns a datetime object initialized from the given ticks value (number of\n" \
520 "seconds since the epoch; see the documentation of the standard Python time\n" \ 526 "seconds since the epoch; see the documentation of the standard Python time\n" \
521 "module for details"; 527 "module for details";
522 528
523 static char datasources_doc[] = 529 static char datasources_doc[] =
524 "dataSources() -> { DSN : Description }\n" \ 530 "dataSources() -> { DSN : Description }\n" \
525 "\n" \ 531 "\n" \
526 "Returns a dictionary mapping available DSNs to their descriptions."; 532 "Returns a dictionary mapping available DSNs to their descriptions.";
527 533
528 534
529 #ifdef PYODBC_LEAK_CHECK 535 #ifdef PYODBC_LEAK_CHECK
530 static PyObject* mod_leakcheck(PyObject* self, PyObject* args) 536 static PyObject* mod_leakcheck(PyObject* self, PyObject* args)
531 { 537 {
532 UNUSED(self, args); 538 UNUSED(self, args);
533 pyodbc_leak_check(); 539 pyodbc_leak_check();
534 Py_RETURN_NONE; 540 Py_RETURN_NONE;
535 } 541 }
536 #endif 542 #endif
537 543
538 #ifdef WINVER 544 #ifdef WINVER
539 static char drivers_doc[] = "drivers() -> [ driver, ... ]\n\nReturns a list of installed drivers"; 545 static char drivers_doc[] = "drivers() -> [ driver, ... ]\n\nReturns a list of installed drivers";
540 546
541 static PyObject* mod_drivers(PyObject* self, PyObject* args) 547 static PyObject* mod_drivers(PyObject* self, PyObject* args)
542 { 548 {
543 UNUSED(self, args); 549 UNUSED(self, args);
544 550
545 RegKey key; 551 RegKey key;
546 long ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers", 0, KEY_QUERY_VALUE, &key.hkey); 552 long ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers", 0, KEY_QUERY_VALUE, &key.hkey);
547 if (ret != ERROR_SUCCESS) 553 if (ret != ERROR_SUCCESS)
548 return PyErr_Format(PyExc_RuntimeError, "Unable to access the driver list in the registry. error=%ld", ret); 554 return PyErr_Format(PyExc_RuntimeError, "Unable to access the driver list in the registry. error=%ld", ret);
549 555
550 Object results(PyList_New(0)); 556 Object results(PyList_New(0));
551 DWORD index = 0; 557 DWORD index = 0;
552 char name[255]; 558 char name[255];
553 DWORD length = _countof(name); 559 DWORD length = _countof(name);
554 560
555 while (RegEnumValue(key, index++, name, &length, 0, 0, 0, 0) == ERROR_SUCCESS) 561 while (RegEnumValue(key, index++, name, &length, 0, 0, 0, 0) == ERROR_SUCCESS)
556 { 562 {
557 if (ret != ERROR_SUCCESS) 563 if (ret != ERROR_SUCCESS)
558 return PyErr_Format(PyExc_RuntimeError, "RegEnumKeyEx failed with error %ld\n", ret); 564 return PyErr_Format(PyExc_RuntimeError, "RegEnumKeyEx failed with error %ld\n", ret);
559 565
560 PyObject* oname = PyString_FromStringAndSize(name, (Py_ssize_t)length); 566 PyObject* oname = PyString_FromStringAndSize(name, (Py_ssize_t)length);
561 if (!oname) 567 if (!oname)
562 return 0; 568 return 0;
563 569
564 if (PyList_Append(results.Get(), oname) != 0) 570 if (PyList_Append(results.Get(), oname) != 0)
565 { 571 {
566 Py_DECREF(oname); 572 Py_DECREF(oname);
567 return 0; 573 return 0;
568 } 574 }
569 length = _countof(name); 575 length = _countof(name);
570 } 576 }
571 577
572 return results.Detach(); 578 return results.Detach();
573 } 579 }
574 #endif 580 #endif
575 581
576 static PyMethodDef pyodbc_methods[] = 582 static PyMethodDef pyodbc_methods[] =
577 { 583 {
578 { "connect", (PyCFunction)mod_connect, METH_VARARGS|METH_KEYWORDS, connect_doc }, 584 { "connect", (PyCFunction)mod_connect, METH_VARARGS|METH_KEYWORDS, connect_doc },
579 { "TimeFromTicks", (PyCFunction)mod_timefromticks, METH_VARARGS, timefromticks_doc }, 585 { "TimeFromTicks", (PyCFunction)mod_timefromticks, METH_VARARGS, timefromticks_doc },
580 { "DateFromTicks", (PyCFunction)mod_datefromticks, METH_VARARGS, datefromticks_doc }, 586 { "DateFromTicks", (PyCFunction)mod_datefromticks, METH_VARARGS, datefromticks_doc },
581 { "TimestampFromTicks", (PyCFunction)mod_timestampfromticks, METH_VARARGS, timestampfromticks_doc }, 587 { "TimestampFromTicks", (PyCFunction)mod_timestampfromticks, METH_VARARGS, timestampfromticks_doc },
582 { "dataSources", (PyCFunction)mod_datasources, METH_NOARGS, datasources_doc }, 588 { "dataSources", (PyCFunction)mod_datasources, METH_NOARGS, datasources_doc },
583 589
584 #ifdef WINVER 590 #ifdef WINVER
585 { "drivers", (PyCFunction)mod_drivers, METH_NOARGS, drivers_doc }, 591 { "drivers", (PyCFunction)mod_drivers, METH_NOARGS, drivers_doc },
586 #endif 592 #endif
587 593
588 #ifdef PYODBC_LEAK_CHECK 594 #ifdef PYODBC_LEAK_CHECK
589 { "leakcheck", (PyCFunction)mod_leakcheck, METH_NOARGS, 0 }, 595 { "leakcheck", (PyCFunction)mod_leakcheck, METH_NOARGS, 0 },
590 #endif 596 #endif
591 597
592 { 0, 0, 0, 0 } 598 { 0, 0, 0, 0 }
593 }; 599 };
594 600
595 601
596 static void ErrorInit() 602 static void ErrorInit()
597 { 603 {
598 // Called during startup to initialize any variables that will be freed by ErrorCleanup. 604 // Called during startup to initialize any variables that will be freed by ErrorCleanup.
599 605
600 Error = 0; 606 Error = 0;
601 Warning = 0; 607 Warning = 0;
602 InterfaceError = 0; 608 InterfaceError = 0;
603 DatabaseError = 0; 609 DatabaseError = 0;
604 InternalError = 0; 610 InternalError = 0;
605 OperationalError = 0; 611 OperationalError = 0;
606 ProgrammingError = 0; 612 ProgrammingError = 0;
607 IntegrityError = 0; 613 IntegrityError = 0;
608 DataError = 0; 614 DataError = 0;
609 NotSupportedError = 0; 615 NotSupportedError = 0;
610 decimal_type = 0; 616 decimal_type = 0;
611 } 617 }
612 618
613 619
614 static void ErrorCleanup() 620 static void ErrorCleanup()
615 { 621 {
616 // Called when an error occurs during initialization to release any objects we may have accessed. Make sure each 622 // Called when an error occurs during initialization to release any objects we may have accessed. Make sure each
617 // item released was initialized to zero. (Static objects are -- non-statics should be initialized in ErrorInit.) 623 // item released was initialized to zero. (Static objects are -- non-statics should be initialized in ErrorInit.)
618 624
619 Py_XDECREF(Error); 625 Py_XDECREF(Error);
620 Py_XDECREF(Warning); 626 Py_XDECREF(Warning);
621 Py_XDECREF(InterfaceError); 627 Py_XDECREF(InterfaceError);
622 Py_XDECREF(DatabaseError); 628 Py_XDECREF(DatabaseError);
623 Py_XDECREF(InternalError); 629 Py_XDECREF(InternalError);
624 Py_XDECREF(OperationalError); 630 Py_XDECREF(OperationalError);
625 Py_XDECREF(ProgrammingError); 631 Py_XDECREF(ProgrammingError);
626 Py_XDECREF(IntegrityError); 632 Py_XDECREF(IntegrityError);
627 Py_XDECREF(DataError); 633 Py_XDECREF(DataError);
628 Py_XDECREF(NotSupportedError); 634 Py_XDECREF(NotSupportedError);
629 Py_XDECREF(decimal_type); 635 Py_XDECREF(decimal_type);
630 } 636 }
631 637
632 struct ConstantDef 638 struct ConstantDef
633 { 639 {
634 const char* szName; 640 const char* szName;
635 int value; 641 int value;
636 }; 642 };
637 643
638 #define MAKECONST(v) { #v, v } 644 #define MAKECONST(v) { #v, v }
639 645
640 static const ConstantDef aConstants[] = { 646 static const ConstantDef aConstants[] = {
641 MAKECONST(SQL_UNKNOWN_TYPE), 647 MAKECONST(SQL_UNKNOWN_TYPE),
642 MAKECONST(SQL_CHAR), 648 MAKECONST(SQL_CHAR),
643 MAKECONST(SQL_VARCHAR), 649 MAKECONST(SQL_VARCHAR),
644 MAKECONST(SQL_LONGVARCHAR), 650 MAKECONST(SQL_LONGVARCHAR),
645 MAKECONST(SQL_WCHAR), 651 MAKECONST(SQL_WCHAR),
646 MAKECONST(SQL_WVARCHAR), 652 MAKECONST(SQL_WVARCHAR),
647 MAKECONST(SQL_WLONGVARCHAR), 653 MAKECONST(SQL_WLONGVARCHAR),
648 MAKECONST(SQL_DECIMAL), 654 MAKECONST(SQL_DECIMAL),
649 MAKECONST(SQL_NUMERIC), 655 MAKECONST(SQL_NUMERIC),
650 MAKECONST(SQL_SMALLINT), 656 MAKECONST(SQL_SMALLINT),
651 MAKECONST(SQL_INTEGER), 657 MAKECONST(SQL_INTEGER),
652 MAKECONST(SQL_REAL), 658 MAKECONST(SQL_REAL),
653 MAKECONST(SQL_FLOAT), 659 MAKECONST(SQL_FLOAT),
654 MAKECONST(SQL_DOUBLE), 660 MAKECONST(SQL_DOUBLE),
655 MAKECONST(SQL_BIT), 661 MAKECONST(SQL_BIT),
656 MAKECONST(SQL_TINYINT), 662 MAKECONST(SQL_TINYINT),
657 MAKECONST(SQL_BIGINT), 663 MAKECONST(SQL_BIGINT),
658 MAKECONST(SQL_BINARY), 664 MAKECONST(SQL_BINARY),
659 MAKECONST(SQL_VARBINARY), 665 MAKECONST(SQL_VARBINARY),
660 MAKECONST(SQL_LONGVARBINARY), 666 MAKECONST(SQL_LONGVARBINARY),
661 MAKECONST(SQL_TYPE_DATE), 667 MAKECONST(SQL_TYPE_DATE),
662 MAKECONST(SQL_TYPE_TIME), 668 MAKECONST(SQL_TYPE_TIME),
663 MAKECONST(SQL_TYPE_TIMESTAMP), 669 MAKECONST(SQL_TYPE_TIMESTAMP),
664 MAKECONST(SQL_SS_TIME2), 670 MAKECONST(SQL_SS_TIME2),
665 MAKECONST(SQL_SS_XML), 671 MAKECONST(SQL_SS_XML),
666 MAKECONST(SQL_INTERVAL_MONTH), 672 MAKECONST(SQL_INTERVAL_MONTH),
667 MAKECONST(SQL_INTERVAL_YEAR), 673 MAKECONST(SQL_INTERVAL_YEAR),
668 MAKECONST(SQL_INTERVAL_YEAR_TO_MONTH), 674 MAKECONST(SQL_INTERVAL_YEAR_TO_MONTH),
669 MAKECONST(SQL_INTERVAL_DAY), 675 MAKECONST(SQL_INTERVAL_DAY),
670 MAKECONST(SQL_INTERVAL_HOUR), 676 MAKECONST(SQL_INTERVAL_HOUR),
671 MAKECONST(SQL_INTERVAL_MINUTE), 677 MAKECONST(SQL_INTERVAL_MINUTE),
672 MAKECONST(SQL_INTERVAL_SECOND), 678 MAKECONST(SQL_INTERVAL_SECOND),
673 MAKECONST(SQL_INTERVAL_DAY_TO_HOUR), 679 MAKECONST(SQL_INTERVAL_DAY_TO_HOUR),
674 MAKECONST(SQL_INTERVAL_DAY_TO_MINUTE), 680 MAKECONST(SQL_INTERVAL_DAY_TO_MINUTE),
675 MAKECONST(SQL_INTERVAL_DAY_TO_SECOND), 681 MAKECONST(SQL_INTERVAL_DAY_TO_SECOND),
676 MAKECONST(SQL_INTERVAL_HOUR_TO_MINUTE), 682 MAKECONST(SQL_INTERVAL_HOUR_TO_MINUTE),
677 MAKECONST(SQL_INTERVAL_HOUR_TO_SECOND), 683 MAKECONST(SQL_INTERVAL_HOUR_TO_SECOND),
678 MAKECONST(SQL_INTERVAL_MINUTE_TO_SECOND), 684 MAKECONST(SQL_INTERVAL_MINUTE_TO_SECOND),
679 MAKECONST(SQL_GUID), 685 MAKECONST(SQL_GUID),
680 MAKECONST(SQL_NULLABLE), 686 MAKECONST(SQL_NULLABLE),
681 MAKECONST(SQL_NO_NULLS), 687 MAKECONST(SQL_NO_NULLS),
682 MAKECONST(SQL_NULLABLE_UNKNOWN), 688 MAKECONST(SQL_NULLABLE_UNKNOWN),
683 // MAKECONST(SQL_INDEX_BTREE), 689 // MAKECONST(SQL_INDEX_BTREE),
684 // MAKECONST(SQL_INDEX_CLUSTERED), 690 // MAKECONST(SQL_INDEX_CLUSTERED),
685 // MAKECONST(SQL_INDEX_CONTENT), 691 // MAKECONST(SQL_INDEX_CONTENT),
686 // MAKECONST(SQL_INDEX_HASHED), 692 // MAKECONST(SQL_INDEX_HASHED),
687 // MAKECONST(SQL_INDEX_OTHER), 693 // MAKECONST(SQL_INDEX_OTHER),
688 MAKECONST(SQL_SCOPE_CURROW), 694 MAKECONST(SQL_SCOPE_CURROW),
689 MAKECONST(SQL_SCOPE_TRANSACTION), 695 MAKECONST(SQL_SCOPE_TRANSACTION),
690 MAKECONST(SQL_SCOPE_SESSION), 696 MAKECONST(SQL_SCOPE_SESSION),
691 MAKECONST(SQL_PC_UNKNOWN), 697 MAKECONST(SQL_PC_UNKNOWN),
692 MAKECONST(SQL_PC_NOT_PSEUDO), 698 MAKECONST(SQL_PC_NOT_PSEUDO),
693 MAKECONST(SQL_PC_PSEUDO), 699 MAKECONST(SQL_PC_PSEUDO),
694 700
695 // SQLGetInfo 701 // SQLGetInfo
696 MAKECONST(SQL_ACCESSIBLE_PROCEDURES), 702 MAKECONST(SQL_ACCESSIBLE_PROCEDURES),
697 MAKECONST(SQL_ACCESSIBLE_TABLES), 703 MAKECONST(SQL_ACCESSIBLE_TABLES),
698 MAKECONST(SQL_ACTIVE_ENVIRONMENTS), 704 MAKECONST(SQL_ACTIVE_ENVIRONMENTS),
699 MAKECONST(SQL_AGGREGATE_FUNCTIONS), 705 MAKECONST(SQL_AGGREGATE_FUNCTIONS),
700 MAKECONST(SQL_ALTER_DOMAIN), 706 MAKECONST(SQL_ALTER_DOMAIN),
701 MAKECONST(SQL_ALTER_TABLE), 707 MAKECONST(SQL_ALTER_TABLE),
702 MAKECONST(SQL_ASYNC_MODE), 708 MAKECONST(SQL_ASYNC_MODE),
703 MAKECONST(SQL_BATCH_ROW_COUNT), 709 MAKECONST(SQL_BATCH_ROW_COUNT),
704 MAKECONST(SQL_BATCH_SUPPORT), 710 MAKECONST(SQL_BATCH_SUPPORT),
705 MAKECONST(SQL_BOOKMARK_PERSISTENCE), 711 MAKECONST(SQL_BOOKMARK_PERSISTENCE),
706 MAKECONST(SQL_CATALOG_LOCATION), 712 MAKECONST(SQL_CATALOG_LOCATION),
707 MAKECONST(SQL_CATALOG_NAME), 713 MAKECONST(SQL_CATALOG_NAME),
708 MAKECONST(SQL_CATALOG_NAME_SEPARATOR), 714 MAKECONST(SQL_CATALOG_NAME_SEPARATOR),
709 MAKECONST(SQL_CATALOG_TERM), 715 MAKECONST(SQL_CATALOG_TERM),
710 MAKECONST(SQL_CATALOG_USAGE), 716 MAKECONST(SQL_CATALOG_USAGE),
711 MAKECONST(SQL_COLLATION_SEQ), 717 MAKECONST(SQL_COLLATION_SEQ),
712 MAKECONST(SQL_COLUMN_ALIAS), 718 MAKECONST(SQL_COLUMN_ALIAS),
713 MAKECONST(SQL_CONCAT_NULL_BEHAVIOR), 719 MAKECONST(SQL_CONCAT_NULL_BEHAVIOR),
714 MAKECONST(SQL_CONVERT_FUNCTIONS), 720 MAKECONST(SQL_CONVERT_FUNCTIONS),
715 MAKECONST(SQL_CONVERT_VARCHAR), 721 MAKECONST(SQL_CONVERT_VARCHAR),
716 MAKECONST(SQL_CORRELATION_NAME), 722 MAKECONST(SQL_CORRELATION_NAME),
717 MAKECONST(SQL_CREATE_ASSERTION), 723 MAKECONST(SQL_CREATE_ASSERTION),
718 MAKECONST(SQL_CREATE_CHARACTER_SET), 724 MAKECONST(SQL_CREATE_CHARACTER_SET),
719 MAKECONST(SQL_CREATE_COLLATION), 725 MAKECONST(SQL_CREATE_COLLATION),
720 MAKECONST(SQL_CREATE_DOMAIN), 726 MAKECONST(SQL_CREATE_DOMAIN),
721 MAKECONST(SQL_CREATE_SCHEMA), 727 MAKECONST(SQL_CREATE_SCHEMA),
722 MAKECONST(SQL_CREATE_TABLE), 728 MAKECONST(SQL_CREATE_TABLE),
723 MAKECONST(SQL_CREATE_TRANSLATION), 729 MAKECONST(SQL_CREATE_TRANSLATION),
724 MAKECONST(SQL_CREATE_VIEW), 730 MAKECONST(SQL_CREATE_VIEW),
725 MAKECONST(SQL_CURSOR_COMMIT_BEHAVIOR), 731 MAKECONST(SQL_CURSOR_COMMIT_BEHAVIOR),
726 MAKECONST(SQL_CURSOR_ROLLBACK_BEHAVIOR), 732 MAKECONST(SQL_CURSOR_ROLLBACK_BEHAVIOR),
727 // MAKECONST(SQL_CURSOR_ROLLBACK_SQL_CURSOR_SENSITIVITY), 733 // MAKECONST(SQL_CURSOR_ROLLBACK_SQL_CURSOR_SENSITIVITY),
728 MAKECONST(SQL_DATABASE_NAME), 734 MAKECONST(SQL_DATABASE_NAME),
729 MAKECONST(SQL_DATA_SOURCE_NAME), 735 MAKECONST(SQL_DATA_SOURCE_NAME),
730 MAKECONST(SQL_DATA_SOURCE_READ_ONLY), 736 MAKECONST(SQL_DATA_SOURCE_READ_ONLY),
731 MAKECONST(SQL_DATETIME_LITERALS), 737 MAKECONST(SQL_DATETIME_LITERALS),
732 MAKECONST(SQL_DBMS_NAME), 738 MAKECONST(SQL_DBMS_NAME),
733 MAKECONST(SQL_DBMS_VER), 739 MAKECONST(SQL_DBMS_VER),
734 MAKECONST(SQL_DDL_INDEX), 740 MAKECONST(SQL_DDL_INDEX),
735 MAKECONST(SQL_DEFAULT_TXN_ISOLATION), 741 MAKECONST(SQL_DEFAULT_TXN_ISOLATION),
736 MAKECONST(SQL_DESCRIBE_PARAMETER), 742 MAKECONST(SQL_DESCRIBE_PARAMETER),
737 MAKECONST(SQL_DM_VER), 743 MAKECONST(SQL_DM_VER),
738 MAKECONST(SQL_DRIVER_HDESC), 744 MAKECONST(SQL_DRIVER_HDESC),
739 MAKECONST(SQL_DRIVER_HENV), 745 MAKECONST(SQL_DRIVER_HENV),
740 MAKECONST(SQL_DRIVER_HLIB), 746 MAKECONST(SQL_DRIVER_HLIB),
741 MAKECONST(SQL_DRIVER_HSTMT), 747 MAKECONST(SQL_DRIVER_HSTMT),
742 MAKECONST(SQL_DRIVER_NAME), 748 MAKECONST(SQL_DRIVER_NAME),
743 MAKECONST(SQL_DRIVER_ODBC_VER), 749 MAKECONST(SQL_DRIVER_ODBC_VER),
744 MAKECONST(SQL_DRIVER_VER), 750 MAKECONST(SQL_DRIVER_VER),
745 MAKECONST(SQL_DROP_ASSERTION), 751 MAKECONST(SQL_DROP_ASSERTION),
746 MAKECONST(SQL_DROP_CHARACTER_SET), 752 MAKECONST(SQL_DROP_CHARACTER_SET),
747 MAKECONST(SQL_DROP_COLLATION), 753 MAKECONST(SQL_DROP_COLLATION),
748 MAKECONST(SQL_DROP_DOMAIN), 754 MAKECONST(SQL_DROP_DOMAIN),
749 MAKECONST(SQL_DROP_SCHEMA), 755 MAKECONST(SQL_DROP_SCHEMA),
750 MAKECONST(SQL_DROP_TABLE), 756 MAKECONST(SQL_DROP_TABLE),
751 MAKECONST(SQL_DROP_TRANSLATION), 757 MAKECONST(SQL_DROP_TRANSLATION),
752 MAKECONST(SQL_DROP_VIEW), 758 MAKECONST(SQL_DROP_VIEW),
753 MAKECONST(SQL_DYNAMIC_CURSOR_ATTRIBUTES1), 759 MAKECONST(SQL_DYNAMIC_CURSOR_ATTRIBUTES1),
754 MAKECONST(SQL_DYNAMIC_CURSOR_ATTRIBUTES2), 760 MAKECONST(SQL_DYNAMIC_CURSOR_ATTRIBUTES2),
755 MAKECONST(SQL_EXPRESSIONS_IN_ORDERBY), 761 MAKECONST(SQL_EXPRESSIONS_IN_ORDERBY),
756 MAKECONST(SQL_FILE_USAGE), 762 MAKECONST(SQL_FILE_USAGE),
757 MAKECONST(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1), 763 MAKECONST(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1),
758 MAKECONST(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2), 764 MAKECONST(SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2),
759 MAKECONST(SQL_GETDATA_EXTENSIONS), 765 MAKECONST(SQL_GETDATA_EXTENSIONS),
760 MAKECONST(SQL_GROUP_BY), 766 MAKECONST(SQL_GROUP_BY),
761 MAKECONST(SQL_IDENTIFIER_CASE), 767 MAKECONST(SQL_IDENTIFIER_CASE),
762 MAKECONST(SQL_IDENTIFIER_QUOTE_CHAR), 768 MAKECONST(SQL_IDENTIFIER_QUOTE_CHAR),
763 MAKECONST(SQL_INDEX_KEYWORDS), 769 MAKECONST(SQL_INDEX_KEYWORDS),
764 MAKECONST(SQL_INFO_SCHEMA_VIEWS), 770 MAKECONST(SQL_INFO_SCHEMA_VIEWS),
765 MAKECONST(SQL_INSERT_STATEMENT), 771 MAKECONST(SQL_INSERT_STATEMENT),
766 MAKECONST(SQL_INTEGRITY), 772 MAKECONST(SQL_INTEGRITY),
767 MAKECONST(SQL_KEYSET_CURSOR_ATTRIBUTES1), 773 MAKECONST(SQL_KEYSET_CURSOR_ATTRIBUTES1),
768 MAKECONST(SQL_KEYSET_CURSOR_ATTRIBUTES2), 774 MAKECONST(SQL_KEYSET_CURSOR_ATTRIBUTES2),
769 MAKECONST(SQL_KEYWORDS), 775 MAKECONST(SQL_KEYWORDS),
770 MAKECONST(SQL_LIKE_ESCAPE_CLAUSE), 776 MAKECONST(SQL_LIKE_ESCAPE_CLAUSE),
771 MAKECONST(SQL_MAX_ASYNC_CONCURRENT_STATEMENTS), 777 MAKECONST(SQL_MAX_ASYNC_CONCURRENT_STATEMENTS),
772 MAKECONST(SQL_MAX_BINARY_LITERAL_LEN), 778 MAKECONST(SQL_MAX_BINARY_LITERAL_LEN),
773 MAKECONST(SQL_MAX_CATALOG_NAME_LEN), 779 MAKECONST(SQL_MAX_CATALOG_NAME_LEN),
774 MAKECONST(SQL_MAX_CHAR_LITERAL_LEN), 780 MAKECONST(SQL_MAX_CHAR_LITERAL_LEN),
775 MAKECONST(SQL_MAX_COLUMNS_IN_GROUP_BY), 781 MAKECONST(SQL_MAX_COLUMNS_IN_GROUP_BY),
776 MAKECONST(SQL_MAX_COLUMNS_IN_INDEX), 782 MAKECONST(SQL_MAX_COLUMNS_IN_INDEX),
777 MAKECONST(SQL_MAX_COLUMNS_IN_ORDER_BY), 783 MAKECONST(SQL_MAX_COLUMNS_IN_ORDER_BY),
778 MAKECONST(SQL_MAX_COLUMNS_IN_SELECT), 784 MAKECONST(SQL_MAX_COLUMNS_IN_SELECT),
779 MAKECONST(SQL_MAX_COLUMNS_IN_TABLE), 785 MAKECONST(SQL_MAX_COLUMNS_IN_TABLE),
780 MAKECONST(SQL_MAX_COLUMN_NAME_LEN), 786 MAKECONST(SQL_MAX_COLUMN_NAME_LEN),
781 MAKECONST(SQL_MAX_CONCURRENT_ACTIVITIES), 787 MAKECONST(SQL_MAX_CONCURRENT_ACTIVITIES),
782 MAKECONST(SQL_MAX_CURSOR_NAME_LEN), 788 MAKECONST(SQL_MAX_CURSOR_NAME_LEN),
783 MAKECONST(SQL_MAX_DRIVER_CONNECTIONS), 789 MAKECONST(SQL_MAX_DRIVER_CONNECTIONS),
784 MAKECONST(SQL_MAX_IDENTIFIER_LEN), 790 MAKECONST(SQL_MAX_IDENTIFIER_LEN),
785 MAKECONST(SQL_MAX_INDEX_SIZE), 791 MAKECONST(SQL_MAX_INDEX_SIZE),
786 MAKECONST(SQL_MAX_PROCEDURE_NAME_LEN), 792 MAKECONST(SQL_MAX_PROCEDURE_NAME_LEN),
787 MAKECONST(SQL_MAX_ROW_SIZE), 793 MAKECONST(SQL_MAX_ROW_SIZE),
788 MAKECONST(SQL_MAX_ROW_SIZE_INCLUDES_LONG), 794 MAKECONST(SQL_MAX_ROW_SIZE_INCLUDES_LONG),
789 MAKECONST(SQL_MAX_SCHEMA_NAME_LEN), 795 MAKECONST(SQL_MAX_SCHEMA_NAME_LEN),
790 MAKECONST(SQL_MAX_STATEMENT_LEN), 796 MAKECONST(SQL_MAX_STATEMENT_LEN),
791 MAKECONST(SQL_MAX_TABLES_IN_SELECT), 797 MAKECONST(SQL_MAX_TABLES_IN_SELECT),
792 MAKECONST(SQL_MAX_TABLE_NAME_LEN), 798 MAKECONST(SQL_MAX_TABLE_NAME_LEN),
793 MAKECONST(SQL_MAX_USER_NAME_LEN), 799 MAKECONST(SQL_MAX_USER_NAME_LEN),
794 MAKECONST(SQL_MULTIPLE_ACTIVE_TXN), 800 MAKECONST(SQL_MULTIPLE_ACTIVE_TXN),
795 MAKECONST(SQL_MULT_RESULT_SETS), 801 MAKECONST(SQL_MULT_RESULT_SETS),
796 MAKECONST(SQL_NEED_LONG_DATA_LEN), 802 MAKECONST(SQL_NEED_LONG_DATA_LEN),
797 MAKECONST(SQL_NON_NULLABLE_COLUMNS), 803 MAKECONST(SQL_NON_NULLABLE_COLUMNS),
798 MAKECONST(SQL_NULL_COLLATION), 804 MAKECONST(SQL_NULL_COLLATION),
799 MAKECONST(SQL_NUMERIC_FUNCTIONS), 805 MAKECONST(SQL_NUMERIC_FUNCTIONS),
800 MAKECONST(SQL_ODBC_INTERFACE_CONFORMANCE), 806 MAKECONST(SQL_ODBC_INTERFACE_CONFORMANCE),
801 MAKECONST(SQL_ODBC_VER), 807 MAKECONST(SQL_ODBC_VER),
802 MAKECONST(SQL_OJ_CAPABILITIES), 808 MAKECONST(SQL_OJ_CAPABILITIES),
803 MAKECONST(SQL_ORDER_BY_COLUMNS_IN_SELECT), 809 MAKECONST(SQL_ORDER_BY_COLUMNS_IN_SELECT),
804 MAKECONST(SQL_PARAM_ARRAY_ROW_COUNTS), 810 MAKECONST(SQL_PARAM_ARRAY_ROW_COUNTS),
805 MAKECONST(SQL_PARAM_ARRAY_SELECTS), 811 MAKECONST(SQL_PARAM_ARRAY_SELECTS),
806 MAKECONST(SQL_PARAM_TYPE_UNKNOWN), 812 MAKECONST(SQL_PARAM_TYPE_UNKNOWN),
807 MAKECONST(SQL_PARAM_INPUT), 813 MAKECONST(SQL_PARAM_INPUT),
808 MAKECONST(SQL_PARAM_INPUT_OUTPUT), 814 MAKECONST(SQL_PARAM_INPUT_OUTPUT),
809 MAKECONST(SQL_PARAM_OUTPUT), 815 MAKECONST(SQL_PARAM_OUTPUT),
810 MAKECONST(SQL_RETURN_VALUE), 816 MAKECONST(SQL_RETURN_VALUE),
811 MAKECONST(SQL_RESULT_COL), 817 MAKECONST(SQL_RESULT_COL),
812 MAKECONST(SQL_PROCEDURES), 818 MAKECONST(SQL_PROCEDURES),
813 MAKECONST(SQL_PROCEDURE_TERM), 819 MAKECONST(SQL_PROCEDURE_TERM),
814 MAKECONST(SQL_QUOTED_IDENTIFIER_CASE), 820 MAKECONST(SQL_QUOTED_IDENTIFIER_CASE),
815 MAKECONST(SQL_ROW_UPDATES), 821 MAKECONST(SQL_ROW_UPDATES),
816 MAKECONST(SQL_SCHEMA_TERM), 822 MAKECONST(SQL_SCHEMA_TERM),
817 MAKECONST(SQL_SCHEMA_USAGE), 823 MAKECONST(SQL_SCHEMA_USAGE),
818 MAKECONST(SQL_SCROLL_OPTIONS), 824 MAKECONST(SQL_SCROLL_OPTIONS),
819 MAKECONST(SQL_SEARCH_PATTERN_ESCAPE), 825 MAKECONST(SQL_SEARCH_PATTERN_ESCAPE),
820 MAKECONST(SQL_SERVER_NAME), 826 MAKECONST(SQL_SERVER_NAME),
821 MAKECONST(SQL_SPECIAL_CHARACTERS), 827 MAKECONST(SQL_SPECIAL_CHARACTERS),
822 MAKECONST(SQL_SQL92_DATETIME_FUNCTIONS), 828 MAKECONST(SQL_SQL92_DATETIME_FUNCTIONS),
823 MAKECONST(SQL_SQL92_FOREIGN_KEY_DELETE_RULE), 829 MAKECONST(SQL_SQL92_FOREIGN_KEY_DELETE_RULE),
824 MAKECONST(SQL_SQL92_FOREIGN_KEY_UPDATE_RULE), 830 MAKECONST(SQL_SQL92_FOREIGN_KEY_UPDATE_RULE),
825 MAKECONST(SQL_SQL92_GRANT), 831 MAKECONST(SQL_SQL92_GRANT),
826 MAKECONST(SQL_SQL92_NUMERIC_VALUE_FUNCTIONS), 832 MAKECONST(SQL_SQL92_NUMERIC_VALUE_FUNCTIONS),
827 MAKECONST(SQL_SQL92_PREDICATES), 833 MAKECONST(SQL_SQL92_PREDICATES),
828 MAKECONST(SQL_SQL92_RELATIONAL_JOIN_OPERATORS), 834 MAKECONST(SQL_SQL92_RELATIONAL_JOIN_OPERATORS),
829 MAKECONST(SQL_SQL92_REVOKE), 835 MAKECONST(SQL_SQL92_REVOKE),
830 MAKECONST(SQL_SQL92_ROW_VALUE_CONSTRUCTOR), 836 MAKECONST(SQL_SQL92_ROW_VALUE_CONSTRUCTOR),
831 MAKECONST(SQL_SQL92_STRING_FUNCTIONS), 837 MAKECONST(SQL_SQL92_STRING_FUNCTIONS),
832 MAKECONST(SQL_SQL92_VALUE_EXPRESSIONS), 838 MAKECONST(SQL_SQL92_VALUE_EXPRESSIONS),
833 MAKECONST(SQL_SQL_CONFORMANCE), 839 MAKECONST(SQL_SQL_CONFORMANCE),
834 MAKECONST(SQL_STANDARD_CLI_CONFORMANCE), 840 MAKECONST(SQL_STANDARD_CLI_CONFORMANCE),
835 MAKECONST(SQL_STATIC_CURSOR_ATTRIBUTES1), 841 MAKECONST(SQL_STATIC_CURSOR_ATTRIBUTES1),
836 MAKECONST(SQL_STATIC_CURSOR_ATTRIBUTES2), 842 MAKECONST(SQL_STATIC_CURSOR_ATTRIBUTES2),
837 MAKECONST(SQL_STRING_FUNCTIONS), 843 MAKECONST(SQL_STRING_FUNCTIONS),
838 MAKECONST(SQL_SUBQUERIES), 844 MAKECONST(SQL_SUBQUERIES),
839 MAKECONST(SQL_SYSTEM_FUNCTIONS), 845 MAKECONST(SQL_SYSTEM_FUNCTIONS),
840 MAKECONST(SQL_TABLE_TERM), 846 MAKECONST(SQL_TABLE_TERM),
841 MAKECONST(SQL_TIMEDATE_ADD_INTERVALS), 847 MAKECONST(SQL_TIMEDATE_ADD_INTERVALS),
842 MAKECONST(SQL_TIMEDATE_DIFF_INTERVALS), 848 MAKECONST(SQL_TIMEDATE_DIFF_INTERVALS),
843 MAKECONST(SQL_TIMEDATE_FUNCTIONS), 849 MAKECONST(SQL_TIMEDATE_FUNCTIONS),
844 MAKECONST(SQL_TXN_CAPABLE), 850 MAKECONST(SQL_TXN_CAPABLE),
845 MAKECONST(SQL_TXN_ISOLATION_OPTION), 851 MAKECONST(SQL_TXN_ISOLATION_OPTION),
846 MAKECONST(SQL_UNION), 852 MAKECONST(SQL_UNION),
847 MAKECONST(SQL_USER_NAME), 853 MAKECONST(SQL_USER_NAME),
848 MAKECONST(SQL_XOPEN_CLI_YEAR), 854 MAKECONST(SQL_XOPEN_CLI_YEAR),
849 }; 855 };
850 856
851 857
852 static bool CreateExceptions() 858 static bool CreateExceptions()
853 { 859 {
854 for (unsigned int i = 0; i < _countof(aExcInfos); i++) 860 for (unsigned int i = 0; i < _countof(aExcInfos); i++)
855 { 861 {
856 ExcInfo& info = aExcInfos[i]; 862 ExcInfo& info = aExcInfos[i];
857 863
858 PyObject* classdict = PyDict_New(); 864 PyObject* classdict = PyDict_New();
859 if (!classdict) 865 if (!classdict)
860 return false; 866 return false;
861 867
862 PyObject* doc = PyString_FromString(info.szDoc); 868 PyObject* doc = PyString_FromString(info.szDoc);
863 if (!doc) 869 if (!doc)
864 { 870 {
865 Py_DECREF(classdict); 871 Py_DECREF(classdict);
866 return false; 872 return false;
867 } 873 }
868 874
869 PyDict_SetItemString(classdict, "__doc__", doc); 875 PyDict_SetItemString(classdict, "__doc__", doc);
870 Py_DECREF(doc); 876 Py_DECREF(doc);
871 877
872 *info.ppexc = PyErr_NewException((char*)info.szFullName, *info.ppexcParent, classdict); 878 *info.ppexc = PyErr_NewException((char*)info.szFullName, *info.ppexcParent, classdict);
873 if (*info.ppexc == 0) 879 if (*info.ppexc == 0)
874 { 880 {
875 Py_DECREF(classdict); 881 Py_DECREF(classdict);
876 return false; 882 return false;
877 } 883 }
878 884
879 // Keep a reference for our internal (C++) use. 885 // Keep a reference for our internal (C++) use.
880 Py_INCREF(*info.ppexc); 886 Py_INCREF(*info.ppexc);
881 887
882 PyModule_AddObject(pModule, (char*)info.szName, *info.ppexc); 888 PyModule_AddObject(pModule, (char*)info.szName, *info.ppexc);
883 } 889 }
884 890
885 return true; 891 return true;
886 } 892 }
887 893
888 #if PY_MAJOR_VERSION >= 3 894 #if PY_MAJOR_VERSION >= 3
889 static struct PyModuleDef moduledef = { 895 static struct PyModuleDef moduledef = {
890 PyModuleDef_HEAD_INIT, 896 PyModuleDef_HEAD_INIT,
891 "pyodbc", // m_name 897 "pyodbc", // m_name
892 module_doc, 898 module_doc,
893 -1, // m_size 899 -1, // m_size
894 pyodbc_methods, // m_methods 900 pyodbc_methods, // m_methods
895 0, // m_reload 901 0, // m_reload
896 0, // m_traverse 902 0, // m_traverse
897 0, // m_clear 903 0, // m_clear
898 0, // m_free 904 0, // m_free
899 }; 905 };
900 #define MODRETURN(v) v 906 #define MODRETURN(v) v
901 #else 907 #else
902 #define MODRETURN(v) 908 #define MODRETURN(v)
903 #endif 909 #endif
904 910
905 PyMODINIT_FUNC 911 PyMODINIT_FUNC
906 #if PY_MAJOR_VERSION >= 3 912 #if PY_MAJOR_VERSION >= 3
907 PyInit_pyodbc() 913 PyInit_pyodbc()
908 #else 914 #else
909 initpyodbc(void) 915 initpyodbc(void)
910 #endif 916 #endif
911 { 917 {
912 ErrorInit(); 918 ErrorInit();
913 919
914 if (PyType_Ready(&ConnectionType) < 0 || PyType_Ready(&CursorType) < 0 || PyType_Ready(&RowType) < 0 || PyType_Ready(&CnxnInfoType) < 0) 920 if (PyType_Ready(&ConnectionType) < 0 || PyType_Ready(&CursorType) < 0 || PyType_Ready(&RowType) < 0 || PyType_Ready(&CnxnInfoType) < 0)
915 return MODRETURN(0); 921 return MODRETURN(0);
916 922
917 Object module; 923 Object module;
918 924
919 #if PY_MAJOR_VERSION >= 3 925 #if PY_MAJOR_VERSION >= 3
920 module.Attach(PyModule_Create(&moduledef)); 926 module.Attach(PyModule_Create(&moduledef));
921 #else 927 #else
922 module.Attach(Py_InitModule4("pyodbc", pyodbc_methods, module_doc, NULL, PYTHON_API_VERSION)); 928 module.Attach(Py_InitModule4("pyodbc", pyodbc_methods, module_doc, NULL, PYTHON_API_VERSION));
923 #endif 929 #endif
924 930
925 pModule = module.Get(); 931 pModule = module.Get();
926 932
927 if (!module || !import_types() || !CreateExceptions()) 933 if (!module || !import_types() || !CreateExceptions())
928 return MODRETURN(0); 934 return MODRETURN(0);
929 935
930 init_locale_info(); 936 init_locale_info();
931 937
932 const char* szVersion = TOSTRING(PYODBC_VERSION); 938 const char* szVersion = TOSTRING(PYODBC_VERSION);
933 PyModule_AddStringConstant(module, "version", (char*)szVersion); 939 PyModule_AddStringConstant(module, "version", (char*)szVersion);
934 940
935 PyModule_AddIntConstant(module, "threadsafety", 1); 941 PyModule_AddIntConstant(module, "threadsafety", 1);
936 PyModule_AddStringConstant(module, "apilevel", "2.0"); 942 PyModule_AddStringConstant(module, "apilevel", "2.0");
937 PyModule_AddStringConstant(module, "paramstyle", "qmark"); 943 PyModule_AddStringConstant(module, "paramstyle", "qmark");
938 PyModule_AddObject(module, "pooling", Py_True); 944 PyModule_AddObject(module, "pooling", Py_True);
939 Py_INCREF(Py_True); 945 Py_INCREF(Py_True);
940 PyModule_AddObject(module, "lowercase", Py_False); 946 PyModule_AddObject(module, "lowercase", Py_False);
941 Py_INCREF(Py_False); 947 Py_INCREF(Py_False);
942 948
943 PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType); 949 PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType);
944 Py_INCREF((PyObject*)&ConnectionType); 950 Py_INCREF((PyObject*)&ConnectionType);
945 PyModule_AddObject(module, "Cursor", (PyObject*)&CursorType); 951 PyModule_AddObject(module, "Cursor", (PyObject*)&CursorType);
946 Py_INCREF((PyObject*)&CursorType); 952 Py_INCREF((PyObject*)&CursorType);
947 PyModule_AddObject(module, "Row", (PyObject*)&RowType); 953 PyModule_AddObject(module, "Row", (PyObject*)&RowType);
948 Py_INCREF((PyObject*)&RowType); 954 Py_INCREF((PyObject*)&RowType);
949 955
950 // Add the SQL_XXX defines from ODBC. 956 // Add the SQL_XXX defines from ODBC.
951 for (unsigned int i = 0; i < _countof(aConstants); i++) 957 for (unsigned int i = 0; i < _countof(aConstants); i++)
952 PyModule_AddIntConstant(module, (char*)aConstants[i].szName, aConstants[i].value); 958 PyModule_AddIntConstant(module, (char*)aConstants[i].szName, aConstants[i].value);
953 959
954 PyModule_AddObject(module, "Date", (PyObject*)PyDateTimeAPI->DateType); 960 PyModule_AddObject(module, "Date", (PyObject*)PyDateTimeAPI->DateType);
955 Py_INCREF((PyObject*)PyDateTimeAPI->DateType); 961 Py_INCREF((PyObject*)PyDateTimeAPI->DateType);
956 PyModule_AddObject(module, "Time", (PyObject*)PyDateTimeAPI->TimeType); 962 PyModule_AddObject(module, "Time", (PyObject*)PyDateTimeAPI->TimeType);
957 Py_INCREF((PyObject*)PyDateTimeAPI->TimeType); 963 Py_INCREF((PyObject*)PyDateTimeAPI->TimeType);
958 PyModule_AddObject(module, "Timestamp", (PyObject*)PyDateTimeAPI->DateTimeType); 964 PyModule_AddObject(module, "Timestamp", (PyObject*)PyDateTimeAPI->DateTimeType);
959 Py_INCREF((PyObject*)PyDateTimeAPI->DateTimeType); 965 Py_INCREF((PyObject*)PyDateTimeAPI->DateTimeType);
960 PyModule_AddObject(module, "DATETIME", (PyObject*)PyDateTimeAPI->DateTimeType); 966 PyModule_AddObject(module, "DATETIME", (PyObject*)PyDateTimeAPI->DateTimeType);
961 Py_INCREF((PyObject*)PyDateTimeAPI->DateTimeType); 967 Py_INCREF((PyObject*)PyDateTimeAPI->DateTimeType);
962 PyModule_AddObject(module, "STRING", (PyObject*)&PyString_Type); 968 PyModule_AddObject(module, "STRING", (PyObject*)&PyString_Type);
963 Py_INCREF((PyObject*)&PyString_Type); 969 Py_INCREF((PyObject*)&PyString_Type);
964 PyModule_AddObject(module, "NUMBER", (PyObject*)&PyFloat_Type); 970 PyModule_AddObject(module, "NUMBER", (PyObject*)&PyFloat_Type);
965 Py_INCREF((PyObject*)&PyFloat_Type); 971 Py_INCREF((PyObject*)&PyFloat_Type);
966 PyModule_AddObject(module, "ROWID", (PyObject*)&PyInt_Type); 972 PyModule_AddObject(module, "ROWID", (PyObject*)&PyInt_Type);
967 Py_INCREF((PyObject*)&PyInt_Type); 973 Py_INCREF((PyObject*)&PyInt_Type);
968 974
969 PyObject* binary_type; 975 PyObject* binary_type;
970 #if PY_VERSION_HEX >= 0x02060000 976 #if PY_VERSION_HEX >= 0x02060000
971 binary_type = (PyObject*)&PyByteArray_Type; 977 binary_type = (PyObject*)&PyByteArray_Type;
972 #else 978 #else
973 binary_type = (PyObject*)&PyBuffer_Type; 979 binary_type = (PyObject*)&PyBuffer_Type;
974 #endif 980 #endif
975 PyModule_AddObject(module, "BINARY", binary_type); 981 PyModule_AddObject(module, "BINARY", binary_type);
976 Py_INCREF(binary_type); 982 Py_INCREF(binary_type);
977 PyModule_AddObject(module, "Binary", binary_type); 983 PyModule_AddObject(module, "Binary", binary_type);
978 Py_INCREF(binary_type); 984 Py_INCREF(binary_type);
979 985
980 I(null_binary != 0); // must be initialized first 986 I(null_binary != 0); // must be initialized first
981 PyModule_AddObject(module, "BinaryNull", null_binary); 987 PyModule_AddObject(module, "BinaryNull", null_binary);
982 988
983 PyModule_AddIntConstant(module, "UNICODE_SIZE", sizeof(Py_UNICODE)); 989 PyModule_AddIntConstant(module, "UNICODE_SIZE", sizeof(Py_UNICODE));
984 PyModule_AddIntConstant(module, "SQLWCHAR_SIZE", sizeof(SQLWCHAR)); 990 PyModule_AddIntConstant(module, "SQLWCHAR_SIZE", sizeof(SQLWCHAR));
985 991
986 if (!PyErr_Occurred()) 992 if (!PyErr_Occurred())
987 { 993 {
988 module.Detach(); 994 module.Detach();
989 } 995 }
990 else 996 else
991 { 997 {
992 ErrorCleanup(); 998 ErrorCleanup();
993 } 999 }
994 1000
995 return MODRETURN(pModule); 1001 return MODRETURN(pModule);
996 } 1002 }
997 1003
998 #ifdef WINVER 1004 #ifdef WINVER
999 BOOL WINAPI DllMain( 1005 BOOL WINAPI DllMain(
1000 HINSTANCE hMod, 1006 HINSTANCE hMod,
1001 DWORD fdwReason, 1007 DWORD fdwReason,
1002 LPVOID lpvReserved 1008 LPVOID lpvReserved
1003 ) 1009 )
1004 { 1010 {
1005 UNUSED(hMod, fdwReason, lpvReserved); 1011 UNUSED(hMod, fdwReason, lpvReserved);
1006 return TRUE; 1012 return TRUE;
1007 } 1013 }
1008 #endif 1014 #endif
1009 1015
1010 1016
1011 static PyObject* MakeConnectionString(PyObject* existing, PyObject* parts) 1017 static PyObject* MakeConnectionString(PyObject* existing, PyObject* parts)
1012 { 1018 {
1013 // Creates a connection string from an optional existing connection string plus a dictionary of keyword value 1019 // Creates a connection string from an optional existing connection string plus a dictionary of keyword value
1014 // pairs. 1020 // pairs.
1015 // 1021 //
1016 // existing 1022 // existing
1017 // Optional Unicode connection string we will be appending to. Used when a partial connection string is passed 1023 // Optional Unicode connection string we will be appending to. Used when a partial connection string is passed
1018 // in, followed by keyword parameters: 1024 // in, followed by keyword parameters:
1019 // 1025 //
1020 // connect("driver={x};database={y}", user='z') 1026 // connect("driver={x};database={y}", user='z')
1021 // 1027 //
1022 // parts 1028 // parts
1023 // A dictionary of text keywords and text values that will be appended. 1029 // A dictionary of text keywords and text values that will be appended.
1024 1030
1025 I(PyUnicode_Check(existing)); 1031 I(PyUnicode_Check(existing));
1026 1032
1027 Py_ssize_t length = 0; // length in *characters* 1033 Py_ssize_t length = 0; // length in *characters*
1028 if (existing) 1034 if (existing)
1029 length = Text_Size(existing) + 1; // + 1 to add a trailing semicolon 1035 length = Text_Size(existing) + 1; // + 1 to add a trailing semicolon
1030 1036
1031 Py_ssize_t pos = 0; 1037 Py_ssize_t pos = 0;
1032 PyObject* key = 0; 1038 PyObject* key = 0;
1033 PyObject* value = 0; 1039 PyObject* value = 0;
1034 1040
1035 while (PyDict_Next(parts, &pos, &key, &value)) 1041 while (PyDict_Next(parts, &pos, &key, &value))
1036 { 1042 {
1037 length += Text_Size(key) + 1 + Text_Size(value) + 1; // key=value; 1043 length += Text_Size(key) + 1 + Text_Size(value) + 1; // key=value;
1038 } 1044 }
1039 1045
1040 PyObject* result = PyUnicode_FromUnicode(0, length); 1046 PyObject* result = PyUnicode_FromUnicode(0, length);
1041 if (!result) 1047 if (!result)
1042 return 0; 1048 return 0;
1043 1049
1044 Py_UNICODE* buffer = PyUnicode_AS_UNICODE(result); 1050 Py_UNICODE* buffer = PyUnicode_AS_UNICODE(result);
1045 Py_ssize_t offset = 0; 1051 Py_ssize_t offset = 0;
1046 1052
1047 if (existing) 1053 if (existing)
1048 { 1054 {
1049 offset += TextCopyToUnicode(&buffer[offset], existing); 1055 offset += TextCopyToUnicode(&buffer[offset], existing);
1050 buffer[offset++] = (Py_UNICODE)';'; 1056 buffer[offset++] = (Py_UNICODE)';';
1051 } 1057 }
1052 1058
1053 pos = 0; 1059 pos = 0;
1054 while (PyDict_Next(parts, &pos, &key, &value)) 1060 while (PyDict_Next(parts, &pos, &key, &value))
1055 { 1061 {
1056 offset += TextCopyToUnicode(&buffer[offset], key); 1062 offset += TextCopyToUnicode(&buffer[offset], key);
1057 buffer[offset++] = (Py_UNICODE)'='; 1063 buffer[offset++] = (Py_UNICODE)'=';
1058 1064
1059 offset += TextCopyToUnicode(&buffer[offset], value); 1065 offset += TextCopyToUnicode(&buffer[offset], value);
1060 buffer[offset++] = (Py_UNICODE)';'; 1066 buffer[offset++] = (Py_UNICODE)';';
1061 } 1067 }
1062 1068
1063 I(offset == length); 1069 I(offset == length);
1064 1070
1065 return result; 1071 return result;
1066 } 1072 }
1067 1073
Powered by Google Project Hosting