My favorites | Sign in
Project Home Downloads Wiki Issues Source
Repository:
Checkout   Browse   Changes   Clones  
Changes to /src/connection.cpp
7555f7da7d11 vs. b456b9f0cfd8 Compare: vs.  Format:
Revision b456b9f0cfd8
Go to: 
Sign in to write a code review
/src/connection.cpp   7555f7da7d11 /src/connection.cpp   b456b9f0cfd8
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 "connection.h" 13 #include "connection.h"
14 #include "cursor.h" 14 #include "cursor.h"
15 #include "pyodbcmodule.h" 15 #include "pyodbcmodule.h"
16 #include "errors.h" 16 #include "errors.h"
17 #include "wrapper.h" 17 #include "wrapper.h"
18 #include "cnxninfo.h" 18 #include "cnxninfo.h"
19 #include "sqlwchar.h" 19 #include "sqlwchar.h"
20 20
21 static char connection_doc[] = 21 static char connection_doc[] =
22 "Connection objects manage connections to the database.\n" 22 "Connection objects manage connections to the database.\n"
23 "\n" 23 "\n"
24 "Each manages a single ODBC HDBC."; 24 "Each manages a single ODBC HDBC.";
25 25
26 static Connection* Connection_Validate(PyObject* self) 26 static Connection* Connection_Validate(PyObject* self)
27 { 27 {
28 Connection* cnxn; 28 Connection* cnxn;
29 29
30 if (self == 0 || !Connection_Check(self)) 30 if (self == 0 || !Connection_Check(self))
31 { 31 {
32 PyErr_SetString(PyExc_TypeError, "Connection object required"); 32 PyErr_SetString(PyExc_TypeError, "Connection object required");
33 return 0; 33 return 0;
34 } 34 }
35 35
36 cnxn = (Connection*)self; 36 cnxn = (Connection*)self;
37 37
38 if (cnxn->hdbc == SQL_NULL_HANDLE) 38 if (cnxn->hdbc == SQL_NULL_HANDLE)
39 { 39 {
40 PyErr_SetString(ProgrammingError, "Attempt to use a closed connection."); 40 PyErr_SetString(ProgrammingError, "Attempt to use a closed connection.");
41 return 0; 41 return 0;
42 } 42 }
43 43
44 return cnxn; 44 return cnxn;
45 } 45 }
46 46
47 static bool Connect(PyObject* pConnectString, HDBC hdbc, bool fAnsi, long timeout) 47 static bool Connect(PyObject* pConnectString, HDBC hdbc, bool fAnsi, long timeout)
48 { 48 {
49 // This should have been checked by the global connect function. 49 // This should have been checked by the global connect function.
50 I(PyString_Check(pConnectString) || PyUnicode_Check(pConnectString)); 50 I(PyString_Check(pConnectString) || PyUnicode_Check(pConnectString));
51 51
52 const int cchMax = 600; 52 const int cchMax = 600;
53 53
54 if (PySequence_Length(pConnectString) >= cchMax) 54 if (PySequence_Length(pConnectString) >= cchMax)
55 { 55 {
56 PyErr_SetString(PyExc_TypeError, "connection string too long"); 56 PyErr_SetString(PyExc_TypeError, "connection string too long");
57 return false; 57 return false;
58 } 58 }
59 59
60 // The driver manager determines if the app is a Unicode app based on whether we call SQLDriverConnectA or 60 // The driver manager determines if the app is a Unicode app based on whether we call SQLDriverConnectA or
61 // SQLDriverConnectW. Some drivers, notably Microsoft Access/Jet, change their behavior based on this, so we try 61 // SQLDriverConnectW. Some drivers, notably Microsoft Access/Jet, change their behavior based on this, so we try
62 // the Unicode version first. (The Access driver only supports Unicode text, but SQLDescribeCol returns SQL_CHAR 62 // the Unicode version first. (The Access driver only supports Unicode text, but SQLDescribeCol returns SQL_CHAR
63 // instead of SQL_WCHAR if we connect with the ANSI version. Obviously this causes lots of errors since we believe 63 // instead of SQL_WCHAR if we connect with the ANSI version. Obviously this causes lots of errors since we believe
64 // what it tells us (SQL_CHAR).) 64 // what it tells us (SQL_CHAR).)
65 65
66 // Python supports only UCS-2 and UCS-4, so we shouldn't need to worry about receiving surrogate pairs. However, 66 // Python supports only UCS-2 and UCS-4, so we shouldn't need to worry about receiving surrogate pairs. However,
67 // Windows does use UCS-16, so it is possible something would be misinterpreted as one. We may need to examine 67 // Windows does use UCS-16, so it is possible something would be misinterpreted as one. We may need to examine
68 // this more. 68 // this more.
69 69
70 SQLRETURN ret; 70 SQLRETURN ret;
71 71
72 if (timeout > 0) 72 if (timeout > 0)
73 { 73 {
74 Py_BEGIN_ALLOW_THREADS 74 Py_BEGIN_ALLOW_THREADS
75 ret = SQLSetConnectAttr(hdbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)timeout, SQL_IS_UINTEGER); 75 ret = SQLSetConnectAttr(hdbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)timeout, SQL_IS_UINTEGER);
76 Py_END_ALLOW_THREADS 76 Py_END_ALLOW_THREADS
77 if (!SQL_SUCCEEDED(ret)) 77 if (!SQL_SUCCEEDED(ret))
78 RaiseErrorFromHandle("SQLSetConnectAttr(SQL_ATTR_LOGIN_TIMEOUT)", hdbc, SQL_NULL_HANDLE); 78 RaiseErrorFromHandle("SQLSetConnectAttr(SQL_ATTR_LOGIN_TIMEOUT)", hdbc, SQL_NULL_HANDLE);
79 } 79 }
80 80
81 if (!fAnsi) 81 if (!fAnsi)
82 { 82 {
83 SQLWChar connectString(pConnectString); 83 SQLWChar connectString(pConnectString);
84 Py_BEGIN_ALLOW_THREADS 84 Py_BEGIN_ALLOW_THREADS
85 ret = SQLDriverConnectW(hdbc, 0, connectString, (SQLSMALLINT)connectString.size(), 0, 0, 0, SQL_DRIVER_NOPROMPT); 85 ret = SQLDriverConnectW(hdbc, 0, connectString, (SQLSMALLINT)connectString.size(), 0, 0, 0, SQL_DRIVER_NOPROMPT);
86 Py_END_ALLOW_THREADS 86 Py_END_ALLOW_THREADS
87 if (SQL_SUCCEEDED(ret)) 87 if (SQL_SUCCEEDED(ret))
88 return true; 88 return true;
89 89
90 // The Unicode function failed. If the error is that the driver doesn't have a Unicode version (IM001), continue 90 // The Unicode function failed. If the error is that the driver doesn't have a Unicode version (IM001), continue
91 // to the ANSI version. 91 // to the ANSI version.
92 // 92 //
93 // I've commented this out since a number of common drivers are returning different errors. The MySQL 5 93 // I've commented this out since a number of common drivers are returning different errors. The MySQL 5
94 // driver, for example, returns IM002 "Data source name not found...". 94 // driver, for example, returns IM002 "Data source name not found...".
95 // 95 //
96 // PyObject* error = GetErrorFromHandle("SQLDriverConnectW", hdbc, SQL_NULL_HANDLE); 96 // PyObject* error = GetErrorFromHandle("SQLDriverConnectW", hdbc, SQL_NULL_HANDLE);
97 // if (!HasSqlState(error, "IM001")) 97 // if (!HasSqlState(error, "IM001"))
98 // { 98 // {
99 // RaiseErrorFromException(error); 99 // RaiseErrorFromException(error);
100 // return false; 100 // return false;
101 // } 101 // }
102 // Py_XDECREF(error); 102 // Py_XDECREF(error);
103 } 103 }
104 104
105 SQLCHAR szConnect[cchMax]; 105 SQLCHAR szConnect[cchMax];
106 if (PyUnicode_Check(pConnectString)) 106 if (PyUnicode_Check(pConnectString))
107 { 107 {
108 Py_UNICODE* p = PyUnicode_AS_UNICODE(pConnectString); 108 Py_UNICODE* p = PyUnicode_AS_UNICODE(pConnectString);
109 for (Py_ssize_t i = 0, c = PyUnicode_GET_SIZE(pConnectString); i <= c; i++) 109 for (Py_ssize_t i = 0, c = PyUnicode_GET_SIZE(pConnectString); i <= c; i++)
110 { 110 {
111 if (p[i] > 0xFF) 111 if (p[i] > 0xFF)
112 { 112 {
113 PyErr_SetString(PyExc_TypeError, "A Unicode connection string was supplied but the driver does " 113 PyErr_SetString(PyExc_TypeError, "A Unicode connection string was supplied but the driver does "
114 "not have a Unicode connect function"); 114 "not have a Unicode connect function");
115 return false; 115 return false;
116 } 116 }
117 szConnect[i] = (SQLCHAR)p[i]; 117 szConnect[i] = (SQLCHAR)p[i];
118 } 118 }
119 } 119 }
120 else 120 else
121 { 121 {
122 #if PY_MAJOR_VERSION < 3 122 #if PY_MAJOR_VERSION < 3
123 const char* p = PyString_AS_STRING(pConnectString); 123 const char* p = PyString_AS_STRING(pConnectString);
124 memcpy(szConnect, p, (size_t)(PyString_GET_SIZE(pConnectString) + 1)); 124 memcpy(szConnect, p, (size_t)(PyString_GET_SIZE(pConnectString) + 1));
125 #else 125 #else
126 PyErr_SetString(PyExc_TypeError, "Connection strings must be Unicode"); 126 PyErr_SetString(PyExc_TypeError, "Connection strings must be Unicode");
127 return false; 127 return false;
128 #endif 128 #endif
129 } 129 }
130 130
131 Py_BEGIN_ALLOW_THREADS 131 Py_BEGIN_ALLOW_THREADS
132 ret = SQLDriverConnect(hdbc, 0, szConnect, SQL_NTS, 0, 0, 0, SQL_DRIVER_NOPROMPT); 132 ret = SQLDriverConnect(hdbc, 0, szConnect, SQL_NTS, 0, 0, 0, SQL_DRIVER_NOPROMPT);
133 Py_END_ALLOW_THREADS 133 Py_END_ALLOW_THREADS
134 if (SQL_SUCCEEDED(ret)) 134 if (SQL_SUCCEEDED(ret))
135 return true; 135 return true;
136 136
137 RaiseErrorFromHandle("SQLDriverConnect", hdbc, SQL_NULL_HANDLE); 137 RaiseErrorFromHandle("SQLDriverConnect", hdbc, SQL_NULL_HANDLE);
138 138
139 return false; 139 return false;
140 } 140 }
141 141
142 142
143 PyObject* Connection_New(PyObject* pConnectString, bool fAutoCommit, bool fAnsi, bool fUnicodeResults, long timeout, bool fReadOnly) 143 PyObject* Connection_New(PyObject* pConnectString, bool fAutoCommit, bool fAnsi, bool fUnicodeResults, long timeout, bool fReadOnly)
144 { 144 {
145 // pConnectString 145 // pConnectString
146 // A string or unicode object. (This must be checked by the caller.) 146 // A string or unicode object. (This must be checked by the caller.)
147 // 147 //
148 // fAnsi 148 // fAnsi
149 // If true, do not attempt a Unicode connection. 149 // If true, do not attempt a Unicode connection.
150 // 150 //
151 // fUnicodeResults 151 // fUnicodeResults
152 // If true, return strings in rows as unicode objects. 152 // If true, return strings in rows as unicode objects.
153 153
154 // 154 //
155 // Allocate HDBC and connect 155 // Allocate HDBC and connect
156 // 156 //
157 157
158 HDBC hdbc = SQL_NULL_HANDLE; 158 HDBC hdbc = SQL_NULL_HANDLE;
159 SQLRETURN ret; 159 SQLRETURN ret;
160 Py_BEGIN_ALLOW_THREADS 160 Py_BEGIN_ALLOW_THREADS
161 ret = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); 161 ret = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
162 Py_END_ALLOW_THREADS 162 Py_END_ALLOW_THREADS
163 if (!SQL_SUCCEEDED(ret)) 163 if (!SQL_SUCCEEDED(ret))
164 return RaiseErrorFromHandle("SQLAllocHandle", SQL_NULL_HANDLE, SQL_NULL_HANDLE); 164 return RaiseErrorFromHandle("SQLAllocHandle", SQL_NULL_HANDLE, SQL_NULL_HANDLE);
165 165
166 if (!Connect(pConnectString, hdbc, fAnsi, timeout)) 166 if (!Connect(pConnectString, hdbc, fAnsi, timeout))
167 { 167 {
168 // Connect has already set an exception. 168 // Connect has already set an exception.
169 Py_BEGIN_ALLOW_THREADS 169 Py_BEGIN_ALLOW_THREADS
170 SQLFreeHandle(SQL_HANDLE_DBC, hdbc); 170 SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
171 Py_END_ALLOW_THREADS 171 Py_END_ALLOW_THREADS
172 return 0; 172 return 0;
173 } 173 }
174 174
175 // 175 //
176 // Connected, so allocate the Connection object. 176 // Connected, so allocate the Connection object.
177 // 177 //
178 178
179 // Set all variables to something valid, so we don't crash in dealloc if this function fails. 179 // Set all variables to something valid, so we don't crash in dealloc if this function fails.
180 180
181 #ifdef _MSC_VER 181 #ifdef _MSC_VER
182 #pragma warning(disable : 4365) 182 #pragma warning(disable : 4365)
183 #endif 183 #endif
184 Connection* cnxn = PyObject_NEW(Connection, &ConnectionType); 184 Connection* cnxn = PyObject_NEW(Connection, &ConnectionType);
185 #ifdef _MSC_VER 185 #ifdef _MSC_VER
186 #pragma warning(default : 4365) 186 #pragma warning(default : 4365)
187 #endif 187 #endif
188 188
189 if (cnxn == 0) 189 if (cnxn == 0)
190 { 190 {
191 Py_BEGIN_ALLOW_THREADS 191 Py_BEGIN_ALLOW_THREADS
192 SQLFreeHandle(SQL_HANDLE_DBC, hdbc); 192 SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
193 Py_END_ALLOW_THREADS 193 Py_END_ALLOW_THREADS
194 return 0; 194 return 0;
195 } 195 }
196 196
197 cnxn->hdbc = hdbc; 197 cnxn->hdbc = hdbc;
198 cnxn->nAutoCommit = fAutoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; 198 cnxn->nAutoCommit = fAutoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
199 cnxn->searchescape = 0; 199 cnxn->searchescape = 0;
200 cnxn->timeout = 0; 200 cnxn->timeout = 0;
201 cnxn->unicode_results = fUnicodeResults; 201 cnxn->unicode_results = fUnicodeResults;
202 cnxn->conv_count = 0; 202 cnxn->conv_count = 0;
203 cnxn->conv_types = 0; 203 cnxn->conv_types = 0;
204 cnxn->conv_funcs = 0; 204 cnxn->conv_funcs = 0;
205 205
206 // 206 //
207 // Initialize autocommit mode. 207 // Initialize autocommit mode.
208 // 208 //
209 209
210 // The DB API says we have to default to manual-commit, but ODBC defaults to auto-commit. We also provide a 210 // The DB API says we have to default to manual-commit, but ODBC defaults to auto-commit. We also provide a
211 // keyword parameter that allows the user to override the DB API and force us to start in auto-commit (in which 211 // keyword parameter that allows the user to override the DB API and force us to start in auto-commit (in which
212 // case we don't have to do anything). 212 // case we don't have to do anything).
213 213
214 if (fAutoCommit == false) 214 if (fAutoCommit == false)
215 { 215 {
216 SQLRETURN ret; 216 SQLRETURN ret;
217 Py_BEGIN_ALLOW_THREADS 217 Py_BEGIN_ALLOW_THREADS
218 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)cnxn->nAutoCommit, SQL_IS_UINTEGER); 218 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)cnxn->nAutoCommit, SQL_IS_UINTEGER);
219 Py_END_ALLOW_THREADS 219 Py_END_ALLOW_THREADS
220 220
221 if (!SQL_SUCCEEDED(ret)) 221 if (!SQL_SUCCEEDED(ret))
222 { 222 {
223 RaiseErrorFromHandle("SQLSetConnnectAttr(SQL_ATTR_AUTOCOMMIT)", cnxn->hdbc, SQL_NULL_HANDLE); 223 RaiseErrorFromHandle("SQLSetConnnectAttr(SQL_ATTR_AUTOCOMMIT)", cnxn->hdbc, SQL_NULL_HANDLE);
224 Py_DECREF(cnxn); 224 Py_DECREF(cnxn);
225 return 0; 225 return 0;
226 } 226 }
227 } 227 }
228 228
229 if (fReadOnly) 229 if (fReadOnly)
230 { 230 {
231 SQLRETURN ret; 231 SQLRETURN ret;
232 Py_BEGIN_ALLOW_THREADS 232 Py_BEGIN_ALLOW_THREADS
233 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER)SQL_MODE_READ_ONLY, 0); 233 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER)SQL_MODE_READ_ONLY, 0);
234 Py_END_ALLOW_THREADS 234 Py_END_ALLOW_THREADS
235 235
236 if (!SQL_SUCCEEDED(ret)) 236 if (!SQL_SUCCEEDED(ret))
237 { 237 {
238 RaiseErrorFromHandle("SQLSetConnnectAttr(SQL_ATTR_ACCESS_MODE)", cnxn->hdbc, SQL_NULL_HANDLE); 238 RaiseErrorFromHandle("SQLSetConnnectAttr(SQL_ATTR_ACCESS_MODE)", cnxn->hdbc, SQL_NULL_HANDLE);
239 Py_DECREF(cnxn); 239 Py_DECREF(cnxn);
240 return 0; 240 return 0;
241 } 241 }
242 } 242 }
243 243
244 TRACE("cnxn.new cnxn=%p hdbc=%d\n", cnxn, cnxn->hdbc); 244 TRACE("cnxn.new cnxn=%p hdbc=%d\n", cnxn, cnxn->hdbc);
245 245
246 // 246 //
247 // Gather connection-level information we'll need later. 247 // Gather connection-level information we'll need later.
248 // 248 //
249 249
250 Object info(GetConnectionInfo(pConnectString, cnxn)); 250 Object info(GetConnectionInfo(pConnectString, cnxn));
251 251
252 if (!info.IsValid()) 252 if (!info.IsValid())
253 { 253 {
254 Py_DECREF(cnxn); 254 Py_DECREF(cnxn);
255 return 0; 255 return 0;
256 } 256 }
257 257
258 CnxnInfo* p = (CnxnInfo*)info.Get(); 258 CnxnInfo* p = (CnxnInfo*)info.Get();
259 cnxn->odbc_major = p->odbc_major; 259 cnxn->odbc_major = p->odbc_major;
260 cnxn->odbc_minor = p->odbc_minor; 260 cnxn->odbc_minor = p->odbc_minor;
261 cnxn->supports_describeparam = p->supports_describeparam; 261 cnxn->supports_describeparam = p->supports_describeparam;
262 cnxn->datetime_precision = p->datetime_precision; 262 cnxn->datetime_precision = p->datetime_precision;
263 cnxn->varchar_maxlength = p->varchar_maxlength; 263 cnxn->varchar_maxlength = p->varchar_maxlength;
264 cnxn->wvarchar_maxlength = p->wvarchar_maxlength; 264 cnxn->wvarchar_maxlength = p->wvarchar_maxlength;
265 cnxn->binary_maxlength = p->binary_maxlength; 265 cnxn->binary_maxlength = p->binary_maxlength;
266 266
267 return reinterpret_cast<PyObject*>(cnxn); 267 return reinterpret_cast<PyObject*>(cnxn);
268 } 268 }
269 269
270 static void _clear_conv(Connection* cnxn) 270 static void _clear_conv(Connection* cnxn)
271 { 271 {
272 if (cnxn->conv_count != 0) 272 if (cnxn->conv_count != 0)
273 { 273 {
274 pyodbc_free(cnxn->conv_types); 274 pyodbc_free(cnxn->conv_types);
275 cnxn->conv_types = 0; 275 cnxn->conv_types = 0;
276 276
277 for (int i = 0; i < cnxn->conv_count; i++) 277 for (int i = 0; i < cnxn->conv_count; i++)
278 Py_XDECREF(cnxn->conv_funcs[i]); 278 Py_XDECREF(cnxn->conv_funcs[i]);
279 pyodbc_free(cnxn->conv_funcs); 279 pyodbc_free(cnxn->conv_funcs);
280 cnxn->conv_funcs = 0; 280 cnxn->conv_funcs = 0;
281 281
282 cnxn->conv_count = 0; 282 cnxn->conv_count = 0;
283 } 283 }
284 } 284 }
285 285
286 static char conv_clear_doc[] = 286 static char conv_clear_doc[] =
287 "clear_output_converters() --> None\n\n" 287 "clear_output_converters() --> None\n\n"
288 "Remove all output converter functions."; 288 "Remove all output converter functions.";
289 289
290 static PyObject* Connection_conv_clear(PyObject* self, PyObject* args) 290 static PyObject* Connection_conv_clear(PyObject* self, PyObject* args)
291 { 291 {
292 UNUSED(args); 292 UNUSED(args);
293 293
294 Connection* cnxn = (Connection*)self; 294 Connection* cnxn = (Connection*)self;
295 _clear_conv(cnxn); 295 _clear_conv(cnxn);
296 Py_RETURN_NONE; 296 Py_RETURN_NONE;
297 } 297 }
298 298
299 static int Connection_clear(PyObject* self) 299 static int Connection_clear(PyObject* self)
300 { 300 {
301 // Internal method for closing the connection. (Not called close so it isn't confused with the external close 301 // Internal method for closing the connection. (Not called close so it isn't confused with the external close
302 // method.) 302 // method.)
303 303
304 Connection* cnxn = (Connection*)self; 304 Connection* cnxn = (Connection*)self;
305 305
306 if (cnxn->hdbc != SQL_NULL_HANDLE) 306 if (cnxn->hdbc != SQL_NULL_HANDLE)
307 { 307 {
308 // REVIEW: Release threads? (But make sure you zero out hdbc *first*! 308 // REVIEW: Release threads? (But make sure you zero out hdbc *first*!
309 309
310 TRACE("cnxn.clear cnxn=%p hdbc=%d\n", cnxn, cnxn->hdbc); 310 TRACE("cnxn.clear cnxn=%p hdbc=%d\n", cnxn, cnxn->hdbc);
311 311
312 Py_BEGIN_ALLOW_THREADS 312 Py_BEGIN_ALLOW_THREADS
313 if (cnxn->nAutoCommit == SQL_AUTOCOMMIT_OFF) 313 if (cnxn->nAutoCommit == SQL_AUTOCOMMIT_OFF)
314 SQLEndTran(SQL_HANDLE_DBC, cnxn->hdbc, SQL_ROLLBACK); 314 SQLEndTran(SQL_HANDLE_DBC, cnxn->hdbc, SQL_ROLLBACK);
315 315
316 SQLDisconnect(cnxn->hdbc); 316 SQLDisconnect(cnxn->hdbc);
317 SQLFreeHandle(SQL_HANDLE_DBC, cnxn->hdbc); 317 SQLFreeHandle(SQL_HANDLE_DBC, cnxn->hdbc);
318 Py_END_ALLOW_THREADS 318 Py_END_ALLOW_THREADS
319 319
320 cnxn->hdbc = SQL_NULL_HANDLE; 320 cnxn->hdbc = SQL_NULL_HANDLE;
321 } 321 }
322 322
323 Py_XDECREF(cnxn->searchescape); 323 Py_XDECREF(cnxn->searchescape);
324 cnxn->searchescape = 0; 324 cnxn->searchescape = 0;
325 325
326 _clear_conv(cnxn); 326 _clear_conv(cnxn);
327 327
328 return 0; 328 return 0;
329 } 329 }
330 330
331 static void Connection_dealloc(PyObject* self) 331 static void Connection_dealloc(PyObject* self)
332 { 332 {
333 Connection_clear(self); 333 Connection_clear(self);
334 PyObject_Del(self); 334 PyObject_Del(self);
335 } 335 }
336 336
337 static char close_doc[] = 337 static char close_doc[] =
338 "Close the connection now (rather than whenever __del__ is called).\n" 338 "Close the connection now (rather than whenever __del__ is called).\n"
339 "\n" 339 "\n"
340 "The connection will be unusable from this point forward and a ProgrammingError\n" 340 "The connection will be unusable from this point forward and a ProgrammingError\n"
341 "will be raised if any operation is attempted with the connection. The same\n" 341 "will be raised if any operation is attempted with the connection. The same\n"
342 "applies to all cursor objects trying to use the connection.\n" 342 "applies to all cursor objects trying to use the connection.\n"
343 "\n" 343 "\n"
344 "Note that closing a connection without committing the changes first will cause\n" 344 "Note that closing a connection without committing the changes first will cause\n"
345 "an implicit rollback to be performed."; 345 "an implicit rollback to be performed.";
346 346
347 static PyObject* Connection_close(PyObject* self, PyObject* args) 347 static PyObject* Connection_close(PyObject* self, PyObject* args)
348 { 348 {
349 UNUSED(args); 349 UNUSED(args);
350 350
351 Connection* cnxn = Connection_Validate(self); 351 Connection* cnxn = Connection_Validate(self);
352 if (!cnxn) 352 if (!cnxn)
353 return 0; 353 return 0;
354 354
355 Connection_clear(self); 355 Connection_clear(self);
356 356
357 Py_RETURN_NONE; 357 Py_RETURN_NONE;
358 } 358 }
359 359
360 static PyObject* Connection_cursor(PyObject* self, PyObject* args) 360 static PyObject* Connection_cursor(PyObject* self, PyObject* args)
361 { 361 {
362 UNUSED(args); 362 UNUSED(args);
363 363
364 Connection* cnxn = Connection_Validate(self); 364 Connection* cnxn = Connection_Validate(self);
365 if (!cnxn) 365 if (!cnxn)
366 return 0; 366 return 0;
367 367
368 return (PyObject*)Cursor_New(cnxn); 368 return (PyObject*)Cursor_New(cnxn);
369 } 369 }
370 370
371 static PyObject* Connection_execute(PyObject* self, PyObject* args) 371 static PyObject* Connection_execute(PyObject* self, PyObject* args)
372 { 372 {
373 PyObject* result = 0; 373 PyObject* result = 0;
374 374
375 Cursor* cursor; 375 Cursor* cursor;
376 Connection* cnxn = Connection_Validate(self); 376 Connection* cnxn = Connection_Validate(self);
377 377
378 if (!cnxn) 378 if (!cnxn)
379 return 0; 379 return 0;
380 380
381 cursor = Cursor_New(cnxn); 381 cursor = Cursor_New(cnxn);
382 if (!cursor) 382 if (!cursor)
383 return 0; 383 return 0;
384 384
385 result = Cursor_execute((PyObject*)cursor, args); 385 result = Cursor_execute((PyObject*)cursor, args);
386 386
387 Py_DECREF((PyObject*)cursor); 387 Py_DECREF((PyObject*)cursor);
388 388
389 return result; 389 return result;
390 } 390 }
391 391
392 enum 392 enum
393 { 393 {
394 GI_YESNO, 394 GI_YESNO,
395 GI_STRING, 395 GI_STRING,
396 GI_UINTEGER, 396 GI_UINTEGER,
397 GI_USMALLINT, 397 GI_USMALLINT,
398 }; 398 };
399 399
400 struct GetInfoType 400 struct GetInfoType
401 { 401 {
402 SQLUSMALLINT infotype; 402 SQLUSMALLINT infotype;
403 int datatype; // GI_XXX 403 int datatype; // GI_XXX
404 }; 404 };
405 405
406 static const GetInfoType aInfoTypes[] = { 406 static const GetInfoType aInfoTypes[] = {
407 { SQL_ACCESSIBLE_PROCEDURES, GI_YESNO }, 407 { SQL_ACCESSIBLE_PROCEDURES, GI_YESNO },
408 { SQL_ACCESSIBLE_TABLES, GI_YESNO }, 408 { SQL_ACCESSIBLE_TABLES, GI_YESNO },
409 { SQL_ACTIVE_ENVIRONMENTS, GI_USMALLINT }, 409 { SQL_ACTIVE_ENVIRONMENTS, GI_USMALLINT },
410 { SQL_AGGREGATE_FUNCTIONS, GI_UINTEGER }, 410 { SQL_AGGREGATE_FUNCTIONS, GI_UINTEGER },
411 { SQL_ALTER_DOMAIN, GI_UINTEGER }, 411 { SQL_ALTER_DOMAIN, GI_UINTEGER },
412 { SQL_ALTER_TABLE, GI_UINTEGER }, 412 { SQL_ALTER_TABLE, GI_UINTEGER },
413 { SQL_ASYNC_MODE, GI_UINTEGER }, 413 { SQL_ASYNC_MODE, GI_UINTEGER },
414 { SQL_BATCH_ROW_COUNT, GI_UINTEGER }, 414 { SQL_BATCH_ROW_COUNT, GI_UINTEGER },
415 { SQL_BATCH_SUPPORT, GI_UINTEGER }, 415 { SQL_BATCH_SUPPORT, GI_UINTEGER },
416 { SQL_BOOKMARK_PERSISTENCE, GI_UINTEGER }, 416 { SQL_BOOKMARK_PERSISTENCE, GI_UINTEGER },
417 { SQL_CATALOG_LOCATION, GI_USMALLINT }, 417 { SQL_CATALOG_LOCATION, GI_USMALLINT },
418 { SQL_CATALOG_NAME, GI_YESNO }, 418 { SQL_CATALOG_NAME, GI_YESNO },
419 { SQL_CATALOG_NAME_SEPARATOR, GI_STRING }, 419 { SQL_CATALOG_NAME_SEPARATOR, GI_STRING },
420 { SQL_CATALOG_TERM, GI_STRING }, 420 { SQL_CATALOG_TERM, GI_STRING },
421 { SQL_CATALOG_USAGE, GI_UINTEGER }, 421 { SQL_CATALOG_USAGE, GI_UINTEGER },
422 { SQL_COLLATION_SEQ, GI_STRING }, 422 { SQL_COLLATION_SEQ, GI_STRING },
423 { SQL_COLUMN_ALIAS, GI_YESNO }, 423 { SQL_COLUMN_ALIAS, GI_YESNO },
424 { SQL_CONCAT_NULL_BEHAVIOR, GI_USMALLINT }, 424 { SQL_CONCAT_NULL_BEHAVIOR, GI_USMALLINT },
425 { SQL_CONVERT_FUNCTIONS, GI_UINTEGER }, 425 { SQL_CONVERT_FUNCTIONS, GI_UINTEGER },
426 { SQL_CONVERT_VARCHAR, GI_UINTEGER }, 426 { SQL_CONVERT_VARCHAR, GI_UINTEGER },
427 { SQL_CORRELATION_NAME, GI_USMALLINT }, 427 { SQL_CORRELATION_NAME, GI_USMALLINT },
428 { SQL_CREATE_ASSERTION, GI_UINTEGER }, 428 { SQL_CREATE_ASSERTION, GI_UINTEGER },
429 { SQL_CREATE_CHARACTER_SET, GI_UINTEGER }, 429 { SQL_CREATE_CHARACTER_SET, GI_UINTEGER },
430 { SQL_CREATE_COLLATION, GI_UINTEGER }, 430 { SQL_CREATE_COLLATION, GI_UINTEGER },
431 { SQL_CREATE_DOMAIN, GI_UINTEGER }, 431 { SQL_CREATE_DOMAIN, GI_UINTEGER },
432 { SQL_CREATE_SCHEMA, GI_UINTEGER }, 432 { SQL_CREATE_SCHEMA, GI_UINTEGER },
433 { SQL_CREATE_TABLE, GI_UINTEGER }, 433 { SQL_CREATE_TABLE, GI_UINTEGER },
434 { SQL_CREATE_TRANSLATION, GI_UINTEGER }, 434 { SQL_CREATE_TRANSLATION, GI_UINTEGER },
435 { SQL_CREATE_VIEW, GI_UINTEGER }, 435 { SQL_CREATE_VIEW, GI_UINTEGER },
436 { SQL_CURSOR_COMMIT_BEHAVIOR, GI_USMALLINT }, 436 { SQL_CURSOR_COMMIT_BEHAVIOR, GI_USMALLINT },
437 { SQL_CURSOR_ROLLBACK_BEHAVIOR, GI_USMALLINT }, 437 { SQL_CURSOR_ROLLBACK_BEHAVIOR, GI_USMALLINT },
438 { SQL_DATABASE_NAME, GI_STRING }, 438 { SQL_DATABASE_NAME, GI_STRING },
439 { SQL_DATA_SOURCE_NAME, GI_STRING }, 439 { SQL_DATA_SOURCE_NAME, GI_STRING },
440 { SQL_DATA_SOURCE_READ_ONLY, GI_YESNO }, 440 { SQL_DATA_SOURCE_READ_ONLY, GI_YESNO },
441 { SQL_DATETIME_LITERALS, GI_UINTEGER }, 441 { SQL_DATETIME_LITERALS, GI_UINTEGER },
442 { SQL_DBMS_NAME, GI_STRING }, 442 { SQL_DBMS_NAME, GI_STRING },
443 { SQL_DBMS_VER, GI_STRING }, 443 { SQL_DBMS_VER, GI_STRING },
444 { SQL_DDL_INDEX, GI_UINTEGER }, 444 { SQL_DDL_INDEX, GI_UINTEGER },
445 { SQL_DEFAULT_TXN_ISOLATION, GI_UINTEGER }, 445 { SQL_DEFAULT_TXN_ISOLATION, GI_UINTEGER },
446 { SQL_DESCRIBE_PARAMETER, GI_YESNO }, 446 { SQL_DESCRIBE_PARAMETER, GI_YESNO },
447 { SQL_DM_VER, GI_STRING }, 447 { SQL_DM_VER, GI_STRING },
448 { SQL_DRIVER_NAME, GI_STRING }, 448 { SQL_DRIVER_NAME, GI_STRING },
449 { SQL_DRIVER_ODBC_VER, GI_STRING }, 449 { SQL_DRIVER_ODBC_VER, GI_STRING },
450 { SQL_DRIVER_VER, GI_STRING }, 450 { SQL_DRIVER_VER, GI_STRING },
451 { SQL_DROP_ASSERTION, GI_UINTEGER }, 451 { SQL_DROP_ASSERTION, GI_UINTEGER },
452 { SQL_DROP_CHARACTER_SET, GI_UINTEGER }, 452 { SQL_DROP_CHARACTER_SET, GI_UINTEGER },
453 { SQL_DROP_COLLATION, GI_UINTEGER }, 453 { SQL_DROP_COLLATION, GI_UINTEGER },
454 { SQL_DROP_DOMAIN, GI_UINTEGER }, 454 { SQL_DROP_DOMAIN, GI_UINTEGER },
455 { SQL_DROP_SCHEMA, GI_UINTEGER }, 455 { SQL_DROP_SCHEMA, GI_UINTEGER },
456 { SQL_DROP_TABLE, GI_UINTEGER }, 456 { SQL_DROP_TABLE, GI_UINTEGER },
457 { SQL_DROP_TRANSLATION, GI_UINTEGER }, 457 { SQL_DROP_TRANSLATION, GI_UINTEGER },
458 { SQL_DROP_VIEW, GI_UINTEGER }, 458 { SQL_DROP_VIEW, GI_UINTEGER },
459 { SQL_DYNAMIC_CURSOR_ATTRIBUTES1, GI_UINTEGER }, 459 { SQL_DYNAMIC_CURSOR_ATTRIBUTES1, GI_UINTEGER },
460 { SQL_DYNAMIC_CURSOR_ATTRIBUTES2, GI_UINTEGER }, 460 { SQL_DYNAMIC_CURSOR_ATTRIBUTES2, GI_UINTEGER },
461 { SQL_EXPRESSIONS_IN_ORDERBY, GI_YESNO }, 461 { SQL_EXPRESSIONS_IN_ORDERBY, GI_YESNO },
462 { SQL_FILE_USAGE, GI_USMALLINT }, 462 { SQL_FILE_USAGE, GI_USMALLINT },
463 { SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, GI_UINTEGER }, 463 { SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, GI_UINTEGER },
464 { SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2, GI_UINTEGER }, 464 { SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2, GI_UINTEGER },
465 { SQL_GETDATA_EXTENSIONS, GI_UINTEGER }, 465 { SQL_GETDATA_EXTENSIONS, GI_UINTEGER },
466 { SQL_GROUP_BY, GI_USMALLINT }, 466 { SQL_GROUP_BY, GI_USMALLINT },
467 { SQL_IDENTIFIER_CASE, GI_USMALLINT }, 467 { SQL_IDENTIFIER_CASE, GI_USMALLINT },
468 { SQL_IDENTIFIER_QUOTE_CHAR, GI_STRING }, 468 { SQL_IDENTIFIER_QUOTE_CHAR, GI_STRING },
469 { SQL_INDEX_KEYWORDS, GI_UINTEGER }, 469 { SQL_INDEX_KEYWORDS, GI_UINTEGER },
470 { SQL_INFO_SCHEMA_VIEWS, GI_UINTEGER }, 470 { SQL_INFO_SCHEMA_VIEWS, GI_UINTEGER },
471 { SQL_INSERT_STATEMENT, GI_UINTEGER }, 471 { SQL_INSERT_STATEMENT, GI_UINTEGER },
472 { SQL_INTEGRITY, GI_YESNO }, 472 { SQL_INTEGRITY, GI_YESNO },
473 { SQL_KEYSET_CURSOR_ATTRIBUTES1, GI_UINTEGER }, 473 { SQL_KEYSET_CURSOR_ATTRIBUTES1, GI_UINTEGER },
474 { SQL_KEYSET_CURSOR_ATTRIBUTES2, GI_UINTEGER }, 474 { SQL_KEYSET_CURSOR_ATTRIBUTES2, GI_UINTEGER },
475 { SQL_KEYWORDS, GI_STRING }, 475 { SQL_KEYWORDS, GI_STRING },
476 { SQL_LIKE_ESCAPE_CLAUSE, GI_YESNO }, 476 { SQL_LIKE_ESCAPE_CLAUSE, GI_YESNO },
477 { SQL_MAX_ASYNC_CONCURRENT_STATEMENTS, GI_UINTEGER }, 477 { SQL_MAX_ASYNC_CONCURRENT_STATEMENTS, GI_UINTEGER },
478 { SQL_MAX_BINARY_LITERAL_LEN, GI_UINTEGER }, 478 { SQL_MAX_BINARY_LITERAL_LEN, GI_UINTEGER },
479 { SQL_MAX_CATALOG_NAME_LEN, GI_USMALLINT }, 479 { SQL_MAX_CATALOG_NAME_LEN, GI_USMALLINT },
480 { SQL_MAX_CHAR_LITERAL_LEN, GI_UINTEGER }, 480 { SQL_MAX_CHAR_LITERAL_LEN, GI_UINTEGER },
481 { SQL_MAX_COLUMNS_IN_GROUP_BY, GI_USMALLINT }, 481 { SQL_MAX_COLUMNS_IN_GROUP_BY, GI_USMALLINT },
482 { SQL_MAX_COLUMNS_IN_INDEX, GI_USMALLINT }, 482 { SQL_MAX_COLUMNS_IN_INDEX, GI_USMALLINT },
483 { SQL_MAX_COLUMNS_IN_ORDER_BY, GI_USMALLINT }, 483 { SQL_MAX_COLUMNS_IN_ORDER_BY, GI_USMALLINT },
484 { SQL_MAX_COLUMNS_IN_SELECT, GI_USMALLINT }, 484 { SQL_MAX_COLUMNS_IN_SELECT, GI_USMALLINT },
485 { SQL_MAX_COLUMNS_IN_TABLE, GI_USMALLINT }, 485 { SQL_MAX_COLUMNS_IN_TABLE, GI_USMALLINT },
486 { SQL_MAX_COLUMN_NAME_LEN, GI_USMALLINT }, 486 { SQL_MAX_COLUMN_NAME_LEN, GI_USMALLINT },
487 { SQL_MAX_CONCURRENT_ACTIVITIES, GI_USMALLINT }, 487 { SQL_MAX_CONCURRENT_ACTIVITIES, GI_USMALLINT },
488 { SQL_MAX_CURSOR_NAME_LEN, GI_USMALLINT }, 488 { SQL_MAX_CURSOR_NAME_LEN, GI_USMALLINT },
489 { SQL_MAX_DRIVER_CONNECTIONS, GI_USMALLINT }, 489 { SQL_MAX_DRIVER_CONNECTIONS, GI_USMALLINT },
490 { SQL_MAX_IDENTIFIER_LEN, GI_USMALLINT }, 490 { SQL_MAX_IDENTIFIER_LEN, GI_USMALLINT },
491 { SQL_MAX_INDEX_SIZE, GI_UINTEGER }, 491 { SQL_MAX_INDEX_SIZE, GI_UINTEGER },
492 { SQL_MAX_PROCEDURE_NAME_LEN, GI_USMALLINT }, 492 { SQL_MAX_PROCEDURE_NAME_LEN, GI_USMALLINT },
493 { SQL_MAX_ROW_SIZE, GI_UINTEGER }, 493 { SQL_MAX_ROW_SIZE, GI_UINTEGER },
494 { SQL_MAX_ROW_SIZE_INCLUDES_LONG, GI_YESNO }, 494 { SQL_MAX_ROW_SIZE_INCLUDES_LONG, GI_YESNO },
495 { SQL_MAX_SCHEMA_NAME_LEN, GI_USMALLINT }, 495 { SQL_MAX_SCHEMA_NAME_LEN, GI_USMALLINT },
496 { SQL_MAX_STATEMENT_LEN, GI_UINTEGER }, 496 { SQL_MAX_STATEMENT_LEN, GI_UINTEGER },
497 { SQL_MAX_TABLES_IN_SELECT, GI_USMALLINT }, 497 { SQL_MAX_TABLES_IN_SELECT, GI_USMALLINT },
498 { SQL_MAX_TABLE_NAME_LEN, GI_USMALLINT }, 498 { SQL_MAX_TABLE_NAME_LEN, GI_USMALLINT },
499 { SQL_MAX_USER_NAME_LEN, GI_USMALLINT }, 499 { SQL_MAX_USER_NAME_LEN, GI_USMALLINT },
500 { SQL_MULTIPLE_ACTIVE_TXN, GI_YESNO }, 500 { SQL_MULTIPLE_ACTIVE_TXN, GI_YESNO },
501 { SQL_MULT_RESULT_SETS, GI_YESNO }, 501 { SQL_MULT_RESULT_SETS, GI_YESNO },
502 { SQL_NEED_LONG_DATA_LEN, GI_YESNO }, 502 { SQL_NEED_LONG_DATA_LEN, GI_YESNO },
503 { SQL_NON_NULLABLE_COLUMNS, GI_USMALLINT }, 503 { SQL_NON_NULLABLE_COLUMNS, GI_USMALLINT },
504 { SQL_NULL_COLLATION, GI_USMALLINT }, 504 { SQL_NULL_COLLATION, GI_USMALLINT },
505 { SQL_NUMERIC_FUNCTIONS, GI_UINTEGER }, 505 { SQL_NUMERIC_FUNCTIONS, GI_UINTEGER },
506 { SQL_ODBC_INTERFACE_CONFORMANCE, GI_UINTEGER }, 506 { SQL_ODBC_INTERFACE_CONFORMANCE, GI_UINTEGER },
507 { SQL_ODBC_VER, GI_STRING }, 507 { SQL_ODBC_VER, GI_STRING },
508 { SQL_OJ_CAPABILITIES, GI_UINTEGER }, 508 { SQL_OJ_CAPABILITIES, GI_UINTEGER },
509 { SQL_ORDER_BY_COLUMNS_IN_SELECT, GI_YESNO }, 509 { SQL_ORDER_BY_COLUMNS_IN_SELECT, GI_YESNO },
510 { SQL_PARAM_ARRAY_ROW_COUNTS, GI_UINTEGER }, 510 { SQL_PARAM_ARRAY_ROW_COUNTS, GI_UINTEGER },
511 { SQL_PARAM_ARRAY_SELECTS, GI_UINTEGER }, 511 { SQL_PARAM_ARRAY_SELECTS, GI_UINTEGER },
512 { SQL_PROCEDURES, GI_YESNO }, 512 { SQL_PROCEDURES, GI_YESNO },
513 { SQL_PROCEDURE_TERM, GI_STRING }, 513 { SQL_PROCEDURE_TERM, GI_STRING },
514 { SQL_QUOTED_IDENTIFIER_CASE, GI_USMALLINT }, 514 { SQL_QUOTED_IDENTIFIER_CASE, GI_USMALLINT },
515 { SQL_ROW_UPDATES, GI_YESNO }, 515 { SQL_ROW_UPDATES, GI_YESNO },
516 { SQL_SCHEMA_TERM, GI_STRING }, 516 { SQL_SCHEMA_TERM, GI_STRING },
517 { SQL_SCHEMA_USAGE, GI_UINTEGER }, 517 { SQL_SCHEMA_USAGE, GI_UINTEGER },
518 { SQL_SCROLL_OPTIONS, GI_UINTEGER }, 518 { SQL_SCROLL_OPTIONS, GI_UINTEGER },
519 { SQL_SEARCH_PATTERN_ESCAPE, GI_STRING }, 519 { SQL_SEARCH_PATTERN_ESCAPE, GI_STRING },
520 { SQL_SERVER_NAME, GI_STRING }, 520 { SQL_SERVER_NAME, GI_STRING },
521 { SQL_SPECIAL_CHARACTERS, GI_STRING }, 521 { SQL_SPECIAL_CHARACTERS, GI_STRING },
522 { SQL_SQL92_DATETIME_FUNCTIONS, GI_UINTEGER }, 522 { SQL_SQL92_DATETIME_FUNCTIONS, GI_UINTEGER },
523 { SQL_SQL92_FOREIGN_KEY_DELETE_RULE, GI_UINTEGER }, 523 { SQL_SQL92_FOREIGN_KEY_DELETE_RULE, GI_UINTEGER },
524 { SQL_SQL92_FOREIGN_KEY_UPDATE_RULE, GI_UINTEGER }, 524 { SQL_SQL92_FOREIGN_KEY_UPDATE_RULE, GI_UINTEGER },
525 { SQL_SQL92_GRANT, GI_UINTEGER }, 525 { SQL_SQL92_GRANT, GI_UINTEGER },
526 { SQL_SQL92_NUMERIC_VALUE_FUNCTIONS, GI_UINTEGER }, 526 { SQL_SQL92_NUMERIC_VALUE_FUNCTIONS, GI_UINTEGER },
527 { SQL_SQL92_PREDICATES, GI_UINTEGER }, 527 { SQL_SQL92_PREDICATES, GI_UINTEGER },
528 { SQL_SQL92_RELATIONAL_JOIN_OPERATORS, GI_UINTEGER }, 528 { SQL_SQL92_RELATIONAL_JOIN_OPERATORS, GI_UINTEGER },
529 { SQL_SQL92_REVOKE, GI_UINTEGER }, 529 { SQL_SQL92_REVOKE, GI_UINTEGER },
530 { SQL_SQL92_ROW_VALUE_CONSTRUCTOR, GI_UINTEGER }, 530 { SQL_SQL92_ROW_VALUE_CONSTRUCTOR, GI_UINTEGER },
531 { SQL_SQL92_STRING_FUNCTIONS, GI_UINTEGER }, 531 { SQL_SQL92_STRING_FUNCTIONS, GI_UINTEGER },
532 { SQL_SQL92_VALUE_EXPRESSIONS, GI_UINTEGER }, 532 { SQL_SQL92_VALUE_EXPRESSIONS, GI_UINTEGER },
533 { SQL_SQL_CONFORMANCE, GI_UINTEGER }, 533 { SQL_SQL_CONFORMANCE, GI_UINTEGER },
534 { SQL_STANDARD_CLI_CONFORMANCE, GI_UINTEGER }, 534 { SQL_STANDARD_CLI_CONFORMANCE, GI_UINTEGER },
535 { SQL_STATIC_CURSOR_ATTRIBUTES1, GI_UINTEGER }, 535 { SQL_STATIC_CURSOR_ATTRIBUTES1, GI_UINTEGER },
536 { SQL_STATIC_CURSOR_ATTRIBUTES2, GI_UINTEGER }, 536 { SQL_STATIC_CURSOR_ATTRIBUTES2, GI_UINTEGER },
537 { SQL_STRING_FUNCTIONS, GI_UINTEGER }, 537 { SQL_STRING_FUNCTIONS, GI_UINTEGER },
538 { SQL_SUBQUERIES, GI_UINTEGER }, 538 { SQL_SUBQUERIES, GI_UINTEGER },
539 { SQL_SYSTEM_FUNCTIONS, GI_UINTEGER }, 539 { SQL_SYSTEM_FUNCTIONS, GI_UINTEGER },
540 { SQL_TABLE_TERM, GI_STRING }, 540 { SQL_TABLE_TERM, GI_STRING },
541 { SQL_TIMEDATE_ADD_INTERVALS, GI_UINTEGER }, 541 { SQL_TIMEDATE_ADD_INTERVALS, GI_UINTEGER },
542 { SQL_TIMEDATE_DIFF_INTERVALS, GI_UINTEGER }, 542 { SQL_TIMEDATE_DIFF_INTERVALS, GI_UINTEGER },
543 { SQL_TIMEDATE_FUNCTIONS, GI_UINTEGER }, 543 { SQL_TIMEDATE_FUNCTIONS, GI_UINTEGER },
544 { SQL_TXN_CAPABLE, GI_USMALLINT }, 544 { SQL_TXN_CAPABLE, GI_USMALLINT },
545 { SQL_TXN_ISOLATION_OPTION, GI_UINTEGER }, 545 { SQL_TXN_ISOLATION_OPTION, GI_UINTEGER },
546 { SQL_UNION, GI_UINTEGER }, 546 { SQL_UNION, GI_UINTEGER },
547 { SQL_USER_NAME, GI_STRING }, 547 { SQL_USER_NAME, GI_STRING },
548 { SQL_XOPEN_CLI_YEAR, GI_STRING }, 548 { SQL_XOPEN_CLI_YEAR, GI_STRING },
549 }; 549 };
550 550
551 static PyObject* Connection_getinfo(PyObject* self, PyObject* args) 551 static PyObject* Connection_getinfo(PyObject* self, PyObject* args)
552 { 552 {
553 Connection* cnxn = Connection_Validate(self); 553 Connection* cnxn = Connection_Validate(self);
554 if (!cnxn) 554 if (!cnxn)
555 return 0; 555 return 0;
556 556
557 unsigned long infotype; 557 unsigned long infotype;
558 if (!PyArg_ParseTuple(args, "k", &infotype)) 558 if (!PyArg_ParseTuple(args, "k", &infotype))
559 return 0; 559 return 0;
560 560
561 unsigned int i = 0; 561 unsigned int i = 0;
562 for (; i < _countof(aInfoTypes); i++) 562 for (; i < _countof(aInfoTypes); i++)
563 { 563 {
564 if (aInfoTypes[i].infotype == infotype) 564 if (aInfoTypes[i].infotype == infotype)
565 break; 565 break;
566 } 566 }
567 567
568 if (i == _countof(aInfoTypes)) 568 if (i == _countof(aInfoTypes))
569 return RaiseErrorV(0, ProgrammingError, "Invalid getinfo value: %d", infotype); 569 return RaiseErrorV(0, ProgrammingError, "Invalid getinfo value: %d", infotype);
570 570
571 char szBuffer[0x1000]; 571 char szBuffer[0x1000];
572 SQLSMALLINT cch = 0; 572 SQLSMALLINT cch = 0;
573 573
574 SQLRETURN ret; 574 SQLRETURN ret;
575 Py_BEGIN_ALLOW_THREADS 575 Py_BEGIN_ALLOW_THREADS
576 ret = SQLGetInfo(cnxn->hdbc, (SQLUSMALLINT)infotype, szBuffer, sizeof(szBuffer), &cch); 576 ret = SQLGetInfo(cnxn->hdbc, (SQLUSMALLINT)infotype, szBuffer, sizeof(szBuffer), &cch);
577 Py_END_ALLOW_THREADS 577 Py_END_ALLOW_THREADS
578 if (!SQL_SUCCEEDED(ret)) 578 if (!SQL_SUCCEEDED(ret))
579 { 579 {
580 RaiseErrorFromHandle("SQLGetInfo", cnxn->hdbc, SQL_NULL_HANDLE); 580 RaiseErrorFromHandle("SQLGetInfo", cnxn->hdbc, SQL_NULL_HANDLE);
581 return 0; 581 return 0;
582 } 582 }
583 583
584 PyObject* result = 0; 584 PyObject* result = 0;
585 585
586 switch (aInfoTypes[i].datatype) 586 switch (aInfoTypes[i].datatype)
587 { 587 {
588 case GI_YESNO: 588 case GI_YESNO:
589 result = (szBuffer[0] == 'Y') ? Py_True : Py_False; 589 result = (szBuffer[0] == 'Y') ? Py_True : Py_False;
590 Py_INCREF(result); 590 Py_INCREF(result);
591 break; 591 break;
592 592
593 case GI_STRING: 593 case GI_STRING:
594 result = PyString_FromStringAndSize(szBuffer, (Py_ssize_t)cch); 594 result = PyString_FromStringAndSize(szBuffer, (Py_ssize_t)cch);
595 break; 595 break;
596 596
597 case GI_UINTEGER: 597 case GI_UINTEGER:
598 { 598 {
599 SQLUINTEGER n = *(SQLUINTEGER*)szBuffer; // Does this work on PPC or do we need a union? 599 SQLUINTEGER n = *(SQLUINTEGER*)szBuffer; // Does this work on PPC or do we need a union?
600 #if PY_MAJOR_VERSION >= 3 600 #if PY_MAJOR_VERSION >= 3
601 result = PyLong_FromLong((long)n); 601 result = PyLong_FromLong((long)n);
602 #else 602 #else
603 if (n <= (SQLUINTEGER)PyInt_GetMax()) 603 if (n <= (SQLUINTEGER)PyInt_GetMax())
604 result = PyInt_FromLong((long)n); 604 result = PyInt_FromLong((long)n);
605 else 605 else
606 result = PyLong_FromUnsignedLong(n); 606 result = PyLong_FromUnsignedLong(n);
607 #endif 607 #endif
608 break; 608 break;
609 } 609 }
610 610
611 case GI_USMALLINT: 611 case GI_USMALLINT:
612 result = PyInt_FromLong(*(SQLUSMALLINT*)szBuffer); 612 result = PyInt_FromLong(*(SQLUSMALLINT*)szBuffer);
613 break; 613 break;
614 } 614 }
615 615
616 return result; 616 return result;
617 } 617 }
618 618
619 619 PyObject* Connection_endtrans(Connection* cnxn, SQLSMALLINT type)
620 static PyObject* Connection_endtrans(PyObject* self, PyObject* args, SQLSMALLINT type)
621 { 620 {
622 UNUSED(args); 621 // If called from Cursor.commit, it is possible that `cnxn` is deleted by another thread when we release them
623 622 // below. (The cursor has had its reference incremented by the method it is calling, but nothing has incremented
624 Connection* cnxn = Connection_Validate(self); 623 // the connections count. We could, but we really only need the HDBC.)
625 if (!cnxn) 624 HDBC hdbc = cnxn->hdbc;
626 return 0;
627
628 TRACE("%s: cnxn=%p hdbc=%d\n", (type == SQL_COMMIT) ? "commit" : "rollback", cnxn, cnxn->hdbc);
629 625
630 SQLRETURN ret; 626 SQLRETURN ret;
631 Py_BEGIN_ALLOW_THREADS 627 Py_BEGIN_ALLOW_THREADS
632 ret = SQLEndTran(SQL_HANDLE_DBC, cnxn->hdbc, type); 628 ret = SQLEndTran(SQL_HANDLE_DBC, hdbc, type);
633 Py_END_ALLOW_THREADS 629 Py_END_ALLOW_THREADS
630
634 if (!SQL_SUCCEEDED(ret)) 631 if (!SQL_SUCCEEDED(ret))
635 { 632 {
636 RaiseErrorFromHandle("SQLEndTran", cnxn->hdbc, SQL_NULL_HANDLE); 633 RaiseErrorFromHandle("SQLEndTran", hdbc, SQL_NULL_HANDLE);
637 return 0; 634 return 0;
638 } 635 }
639 636
640 Py_RETURN_NONE; 637 Py_RETURN_NONE;
641 } 638 }
642 639
643 static PyObject* Connection_commit(PyObject* self, PyObject* args) 640 static PyObject* Connection_commit(PyObject* self, PyObject* args)
644 { 641 {
645 return Connection_endtrans(self, args, SQL_COMMIT); 642 UNUSED(args);
643
644 Connection* cnxn = Connection_Validate(self);
645 if (!cnxn)
646 return 0;
647
648 TRACE("commit: cnxn=%p hdbc=%d\n", cnxn, cnxn->hdbc);
649
650 return Connection_endtrans(cnxn, SQL_COMMIT);
646 } 651 }
647 652
648 static PyObject* Connection_rollback(PyObject* self, PyObject* args) 653 static PyObject* Connection_rollback(PyObject* self, PyObject* args)
649 { 654 {
650 return Connection_endtrans(self, args, SQL_ROLLBACK); 655 UNUSED(args);
656
657 Connection* cnxn = Connection_Validate(self);
658 if (!cnxn)
659 return 0;
660
661 TRACE("rollback: cnxn=%p hdbc=%d\n", cnxn, cnxn->hdbc);
662
663 return Connection_endtrans(cnxn, SQL_ROLLBACK);
651 } 664 }
652 665
653 static char cursor_doc[] = 666 static char cursor_doc[] =
654 "Return a new Cursor object using the connection."; 667 "Return a new Cursor object using the connection.";
655 668
656 static char execute_doc[] = 669 static char execute_doc[] =
657 "execute(sql, [params]) --> Cursor\n" 670 "execute(sql, [params]) --> Cursor\n"
658 "\n" 671 "\n"
659 "Create a new Cursor object, call its execute method, and return it. See\n" 672 "Create a new Cursor object, call its execute method, and return it. See\n"
660 "Cursor.execute for more details.\n" 673 "Cursor.execute for more details.\n"
661 "\n" 674 "\n"
662 "This is a convenience method that is not part of the DB API. Since a new\n" 675 "This is a convenience method that is not part of the DB API. Since a new\n"
663 "Cursor is allocated by each call, this should not be used if more than one SQL\n" 676 "Cursor is allocated by each call, this should not be used if more than one SQL\n"
664 "statement needs to be executed."; 677 "statement needs to be executed.";
665 678
666 static char commit_doc[] = 679 static char commit_doc[] =
667 "Commit any pending transaction to the database."; 680 "Commit any pending transaction to the database.";
668 681
669 static char rollback_doc[] = 682 static char rollback_doc[] =
670 "Causes the the database to roll back to the start of any pending transaction."; 683 "Causes the the database to roll back to the start of any pending transaction.";
671 684
672 static char getinfo_doc[] = 685 static char getinfo_doc[] =
673 "getinfo(type) --> str | int | bool\n" 686 "getinfo(type) --> str | int | bool\n"
674 "\n" 687 "\n"
675 "Calls SQLGetInfo, passing `type`, and returns the result formatted as a Python object."; 688 "Calls SQLGetInfo, passing `type`, and returns the result formatted as a Python object.";
676 689
677 690
678 PyObject* Connection_getautocommit(PyObject* self, void* closure) 691 PyObject* Connection_getautocommit(PyObject* self, void* closure)
679 { 692 {
680 UNUSED(closure); 693 UNUSED(closure);
681 694
682 Connection* cnxn = Connection_Validate(self); 695 Connection* cnxn = Connection_Validate(self);
683 if (!cnxn) 696 if (!cnxn)
684 return 0; 697 return 0;
685 698
686 PyObject* result = (cnxn->nAutoCommit == SQL_AUTOCOMMIT_ON) ? Py_True : Py_False; 699 PyObject* result = (cnxn->nAutoCommit == SQL_AUTOCOMMIT_ON) ? Py_True : Py_False;
687 Py_INCREF(result); 700 Py_INCREF(result);
688 return result; 701 return result;
689 } 702 }
690 703
691 static int Connection_setautocommit(PyObject* self, PyObject* value, void* closure) 704 static int Connection_setautocommit(PyObject* self, PyObject* value, void* closure)
692 { 705 {
693 UNUSED(closure); 706 UNUSED(closure);
694 707
695 Connection* cnxn = Connection_Validate(self); 708 Connection* cnxn = Connection_Validate(self);
696 if (!cnxn) 709 if (!cnxn)
697 return -1; 710 return -1;
698 711
699 if (value == 0) 712 if (value == 0)
700 { 713 {
701 PyErr_SetString(PyExc_TypeError, "Cannot delete the autocommit attribute."); 714 PyErr_SetString(PyExc_TypeError, "Cannot delete the autocommit attribute.");
702 return -1; 715 return -1;
703 } 716 }
704 717
705 uintptr_t nAutoCommit = PyObject_IsTrue(value) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; 718 uintptr_t nAutoCommit = PyObject_IsTrue(value) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
706 SQLRETURN ret; 719 SQLRETURN ret;
707 Py_BEGIN_ALLOW_THREADS 720 Py_BEGIN_ALLOW_THREADS
708 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)nAutoCommit, SQL_IS_UINTEGER); 721 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)nAutoCommit, SQL_IS_UINTEGER);
709 Py_END_ALLOW_THREADS 722 Py_END_ALLOW_THREADS
710 if (!SQL_SUCCEEDED(ret)) 723 if (!SQL_SUCCEEDED(ret))
711 { 724 {
712 RaiseErrorFromHandle("SQLSetConnectAttr", cnxn->hdbc, SQL_NULL_HANDLE); 725 RaiseErrorFromHandle("SQLSetConnectAttr", cnxn->hdbc, SQL_NULL_HANDLE);
713 return -1; 726 return -1;
714 } 727 }
715 728
716 cnxn->nAutoCommit = nAutoCommit; 729 cnxn->nAutoCommit = nAutoCommit;
717 730
718 return 0; 731 return 0;
719 } 732 }
720 733
721 734
722 static PyObject* Connection_getsearchescape(PyObject* self, void* closure) 735 static PyObject* Connection_getsearchescape(PyObject* self, void* closure)
723 { 736 {
724 UNUSED(closure); 737 UNUSED(closure);
725 738
726 Connection* cnxn = (Connection*)self; 739 Connection* cnxn = (Connection*)self;
727 740
728 if (!cnxn->searchescape) 741 if (!cnxn->searchescape)
729 { 742 {
730 char sz[8] = { 0 }; 743 char sz[8] = { 0 };
731 SQLSMALLINT cch = 0; 744 SQLSMALLINT cch = 0;
732 745
733 SQLRETURN ret; 746 SQLRETURN ret;
734 Py_BEGIN_ALLOW_THREADS 747 Py_BEGIN_ALLOW_THREADS
735 ret = SQLGetInfo(cnxn->hdbc, SQL_SEARCH_PATTERN_ESCAPE, &sz, _countof(sz), &cch); 748 ret = SQLGetInfo(cnxn->hdbc, SQL_SEARCH_PATTERN_ESCAPE, &sz, _countof(sz), &cch);
736 Py_END_ALLOW_THREADS 749 Py_END_ALLOW_THREADS
737 if (!SQL_SUCCEEDED(ret)) 750 if (!SQL_SUCCEEDED(ret))
738 return RaiseErrorFromHandle("SQLGetInfo", cnxn->hdbc, SQL_NULL_HANDLE); 751 return RaiseErrorFromHandle("SQLGetInfo", cnxn->hdbc, SQL_NULL_HANDLE);
739 752
740 cnxn->searchescape = PyString_FromStringAndSize(sz, (Py_ssize_t)cch); 753 cnxn->searchescape = PyString_FromStringAndSize(sz, (Py_ssize_t)cch);
741 } 754 }
742 755
743 Py_INCREF(cnxn->searchescape); 756 Py_INCREF(cnxn->searchescape);
744 return cnxn->searchescape; 757 return cnxn->searchescape;
745 } 758 }
746 759
747 760
748 static PyObject* Connection_gettimeout(PyObject* self, void* closure) 761 static PyObject* Connection_gettimeout(PyObject* self, void* closure)
749 { 762 {
750 UNUSED(closure); 763 UNUSED(closure);
751 764
752 Connection* cnxn = Connection_Validate(self); 765 Connection* cnxn = Connection_Validate(self);
753 if (!cnxn) 766 if (!cnxn)
754 return 0; 767 return 0;
755 768
756 return PyInt_FromLong(cnxn->timeout); 769 return PyInt_FromLong(cnxn->timeout);
757 } 770 }
758 771
759 static int Connection_settimeout(PyObject* self, PyObject* value, void* closure) 772 static int Connection_settimeout(PyObject* self, PyObject* value, void* closure)
760 { 773 {
761 UNUSED(closure); 774 UNUSED(closure);
762 775
763 Connection* cnxn = Connection_Validate(self); 776 Connection* cnxn = Connection_Validate(self);
764 if (!cnxn) 777 if (!cnxn)
765 return -1; 778 return -1;
766 779
767 if (value == 0) 780 if (value == 0)
768 { 781 {
769 PyErr_SetString(PyExc_TypeError, "Cannot delete the timeout attribute."); 782 PyErr_SetString(PyExc_TypeError, "Cannot delete the timeout attribute.");
770 return -1; 783 return -1;
771 } 784 }
772 intptr_t timeout = PyInt_AsLong(value); 785 intptr_t timeout = PyInt_AsLong(value);
773 if (timeout == -1 && PyErr_Occurred()) 786 if (timeout == -1 && PyErr_Occurred())
774 return -1; 787 return -1;
775 if (timeout < 0) 788 if (timeout < 0)
776 { 789 {
777 PyErr_SetString(PyExc_ValueError, "Cannot set a negative timeout."); 790 PyErr_SetString(PyExc_ValueError, "Cannot set a negative timeout.");
778 return -1; 791 return -1;
779 } 792 }
780 793
781 SQLRETURN ret; 794 SQLRETURN ret;
782 Py_BEGIN_ALLOW_THREADS 795 Py_BEGIN_ALLOW_THREADS
783 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)timeout, SQL_IS_UINTEGER); 796 ret = SQLSetConnectAttr(cnxn->hdbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)timeout, SQL_IS_UINTEGER);
784 Py_END_ALLOW_THREADS 797 Py_END_ALLOW_THREADS
785 if (!SQL_SUCCEEDED(ret)) 798 if (!SQL_SUCCEEDED(ret))
786 { 799 {
787 RaiseErrorFromHandle("SQLSetConnectAttr", cnxn->hdbc, SQL_NULL_HANDLE); 800 RaiseErrorFromHandle("SQLSetConnectAttr", cnxn->hdbc, SQL_NULL_HANDLE);
788 return -1; 801 return -1;
789 } 802 }
790 803
791 cnxn->timeout = timeout; 804 cnxn->timeout = timeout;
792 805
793 return 0; 806 return 0;
794 } 807 }
795 808
796 static bool _add_converter(PyObject* self, SQLSMALLINT sqltype, PyObject* func) 809 static bool _add_converter(PyObject* self, SQLSMALLINT sqltype, PyObject* func)
797 { 810 {
798 Connection* cnxn = (Connection*)self; 811 Connection* cnxn = (Connection*)self;
799 812
800 if (cnxn->conv_count) 813 if (cnxn->conv_count)
801 { 814 {
802 // If the sqltype is already registered, replace the old conversion function with the new. 815 // If the sqltype is already registered, replace the old conversion function with the new.
803 for (int i = 0; i < cnxn->conv_count; i++) 816 for (int i = 0; i < cnxn->conv_count; i++)
804 { 817 {
805 if (cnxn->conv_types[i] == sqltype) 818 if (cnxn->conv_types[i] == sqltype)
806 { 819 {
807 Py_XDECREF(cnxn->conv_funcs[i]); 820 Py_XDECREF(cnxn->conv_funcs[i]);
808 cnxn->conv_funcs[i] = func; 821 cnxn->conv_funcs[i] = func;
809 Py_INCREF(func); 822 Py_INCREF(func);
810 return true; 823 return true;
811 } 824 }
812 } 825 }
813 } 826 }
814 827
815 int oldcount = cnxn->conv_count; 828 int oldcount = cnxn->conv_count;
816 SQLSMALLINT* oldtypes = cnxn->conv_types; 829 SQLSMALLINT* oldtypes = cnxn->conv_types;
817 PyObject** oldfuncs = cnxn->conv_funcs; 830 PyObject** oldfuncs = cnxn->conv_funcs;
818 831
819 int newcount = oldcount + 1; 832 int newcount = oldcount + 1;
820 SQLSMALLINT* newtypes = (SQLSMALLINT*)pyodbc_malloc(sizeof(SQLSMALLINT) * newcount); 833 SQLSMALLINT* newtypes = (SQLSMALLINT*)pyodbc_malloc(sizeof(SQLSMALLINT) * newcount);
821 PyObject** newfuncs = (PyObject**)pyodbc_malloc(sizeof(PyObject*) * newcount); 834 PyObject** newfuncs = (PyObject**)pyodbc_malloc(sizeof(PyObject*) * newcount);
822 835
823 if (newtypes == 0 || newfuncs == 0) 836 if (newtypes == 0 || newfuncs == 0)
824 { 837 {
825 if (newtypes) 838 if (newtypes)
826 pyodbc_free(newtypes); 839 pyodbc_free(newtypes);
827 if (newfuncs) 840 if (newfuncs)
828 pyodbc_free(newfuncs); 841 pyodbc_free(newfuncs);
829 PyErr_NoMemory(); 842 PyErr_NoMemory();
830 return false; 843 return false;
831 } 844 }
832 845
833 newtypes[0] = sqltype; 846 newtypes[0] = sqltype;
834 newfuncs[0] = func; 847 newfuncs[0] = func;
835 Py_INCREF(func); 848 Py_INCREF(func);
836 849
837 cnxn->conv_count = newcount; 850 cnxn->conv_count = newcount;
838 cnxn->conv_types = newtypes; 851 cnxn->conv_types = newtypes;
839 cnxn->conv_funcs = newfuncs; 852 cnxn->conv_funcs = newfuncs;
840 853
841 if (oldcount != 0) 854 if (oldcount != 0)
842 { 855 {
843 // copy old items 856 // copy old items
844 memcpy(&newtypes[1], oldtypes, sizeof(int) * oldcount); 857 memcpy(&newtypes[1], oldtypes, sizeof(int) * oldcount);
845 memcpy(&newfuncs[1], oldfuncs, sizeof(PyObject*) * oldcount); 858 memcpy(&newfuncs[1], oldfuncs, sizeof(PyObject*) * oldcount);
846 859
847 pyodbc_free(oldtypes); 860 pyodbc_free(oldtypes);
848 pyodbc_free(oldfuncs); 861 pyodbc_free(oldfuncs);
849 } 862 }
850 863
851 return true; 864 return true;
852 } 865 }
853 866
854 static char conv_add_doc[] = 867 static char conv_add_doc[] =
855 "add_output_converter(sqltype, func) --> None\n" 868 "add_output_converter(sqltype, func) --> None\n"
856 "\n" 869 "\n"
857 "Register an output converter function that will be called whenever a value with\n" 870 "Register an output converter function that will be called whenever a value with\n"
858 "the given SQL type is read from the database.\n" 871 "the given SQL type is read from the database.\n"
859 "\n" 872 "\n"
860 "sqltype\n" 873 "sqltype\n"
861 " The integer SQL type value to convert, which can be one of the defined\n" 874 " The integer SQL type value to convert, which can be one of the defined\n"
862 " standard constants (e.g. pyodbc.SQL_VARCHAR) or a database-specific value\n" 875 " standard constants (e.g. pyodbc.SQL_VARCHAR) or a database-specific value\n"
863 " (e.g. -151 for the SQL Server 2008 geometry data type).\n" 876 " (e.g. -151 for the SQL Server 2008 geometry data type).\n"
864 "\n" 877 "\n"
865 "func\n" 878 "func\n"
866 " The converter function which will be called with a single parameter, the\n" 879 " The converter function which will be called with a single parameter, the\n"
867 " value, and should return the converted value. If the value is NULL, the\n" 880 " value, and should return the converted value. If the value is NULL, the\n"
868 " parameter will be None. Otherwise it will be a Python string."; 881 " parameter will be None. Otherwise it will be a Python string.";
869 882
870 883
871 static PyObject* Connection_conv_add(PyObject* self, PyObject* args) 884 static PyObject* Connection_conv_add(PyObject* self, PyObject* args)
872 { 885 {
873 int sqltype; 886 int sqltype;
874 PyObject* func; 887 PyObject* func;
875 if (!PyArg_ParseTuple(args, "iO", &sqltype, &func)) 888 if (!PyArg_ParseTuple(args, "iO", &sqltype, &func))
876 return 0; 889 return 0;
877 890
878 if (!_add_converter(self, (SQLSMALLINT)sqltype, func)) 891 if (!_add_converter(self, (SQLSMALLINT)sqltype, func))
879 return 0; 892 return 0;
880 893
881 Py_RETURN_NONE; 894 Py_RETURN_NONE;
882 } 895 }
883 896
884 static char enter_doc[] = "__enter__() -> self."; 897 static char enter_doc[] = "__enter__() -> self.";
885 static PyObject* Connection_enter(PyObject* self, PyObject* args) 898 static PyObject* Connection_enter(PyObject* self, PyObject* args)
886 { 899 {
887 UNUSED(args); 900 UNUSED(args);
888 Py_INCREF(self); 901 Py_INCREF(self);
889 return self; 902 return self;
890 } 903 }
891 904
892 static char exit_doc[] = "__exit__(*excinfo) -> None. Closes the connection."; 905 static char exit_doc[] = "__exit__(*excinfo) -> None. Closes the connection.";
893 static PyObject* Connection_exit(PyObject* self, PyObject* args) 906 static PyObject* Connection_exit(PyObject* self, PyObject* args)
894 { 907 {
895 Connection* cnxn = (Connection*)self; 908 Connection* cnxn = (Connection*)self;
896 909
897 // If an error has occurred, `args` will be a tuple of 3 values. Otherwise it will be a tuple of 3 `None`s. 910 // If an error has occurred, `args` will be a tuple of 3 values. Otherwise it will be a tuple of 3 `None`s.
898 I(PyTuple_Check(args)); 911 I(PyTuple_Check(args));
899 912
900 if (cnxn->nAutoCommit == SQL_AUTOCOMMIT_OFF && PyTuple_GetItem(args, 0) == Py_None) 913 if (cnxn->nAutoCommit == SQL_AUTOCOMMIT_OFF && PyTuple_GetItem(args, 0) == Py_None)
901 SQLEndTran(SQL_HANDLE_DBC, cnxn->hdbc, SQL_COMMIT); 914 SQLEndTran(SQL_HANDLE_DBC, cnxn->hdbc, SQL_COMMIT);
902 915
903 Py_RETURN_NONE; 916 Py_RETURN_NONE;
904 } 917 }
905 918
906 919
907 static struct PyMethodDef Connection_methods[] = 920 static struct PyMethodDef Connection_methods[] =
908 { 921 {
909 { "cursor", Connection_cursor, METH_NOARGS, cursor_doc }, 922 { "cursor", Connection_cursor, METH_NOARGS, cursor_doc },
910 { "close", Connection_close, METH_NOARGS, close_doc }, 923 { "close", Connection_close, METH_NOARGS, close_doc },
911 { "execute", Connection_execute, METH_VARARGS, execute_doc }, 924 { "execute", Connection_execute, METH_VARARGS, execute_doc },
912 { "commit", Connection_commit, METH_NOARGS, commit_doc }, 925 { "commit", Connection_commit, METH_NOARGS, commit_doc },
913 { "rollback", Connection_rollback, METH_NOARGS, rollback_doc }, 926 { "rollback", Connection_rollback, METH_NOARGS, rollback_doc },
914 { "getinfo", Connection_getinfo, METH_VARARGS, getinfo_doc }, 927 { "getinfo", Connection_getinfo, METH_VARARGS, getinfo_doc },
915 { "add_output_converter", Connection_conv_add, METH_VARARGS, conv_add_doc }, 928 { "add_output_converter", Connection_conv_add, METH_VARARGS, conv_add_doc },
916 { "clear_output_converters", Connection_conv_clear, METH_NOARGS, conv_clear_doc }, 929 { "clear_output_converters", Connection_conv_clear, METH_NOARGS, conv_clear_doc },
917 { "__enter__", Connection_enter, METH_NOARGS, enter_doc }, 930 { "__enter__", Connection_enter, METH_NOARGS, enter_doc },
918 { "__exit__", Connection_exit, METH_VARARGS, exit_doc }, 931 { "__exit__", Connection_exit, METH_VARARGS, exit_doc },
919 932
920 { 0, 0, 0, 0 } 933 { 0, 0, 0, 0 }
921 }; 934 };
922 935
923 static PyGetSetDef Connection_getseters[] = { 936 static PyGetSetDef Connection_getseters[] = {
924 { "searchescape", (getter)Connection_getsearchescape, 0, 937 { "searchescape", (getter)Connection_getsearchescape, 0,
925 "The ODBC search pattern escape character, as returned by\n" 938 "The ODBC search pattern escape character, as returned by\n"
926 "SQLGetInfo(SQL_SEARCH_PATTERN_ESCAPE). These are driver specific.", 0 }, 939 "SQLGetInfo(SQL_SEARCH_PATTERN_ESCAPE). These are driver specific.", 0 },
927 { "autocommit", Connection_getautocommit, Connection_setautocommit, 940 { "autocommit", Connection_getautocommit, Connection_setautocommit,
928 "Returns True if the connection is in autocommit mode; False otherwise.", 0 }, 941 "Returns True if the connection is in autocommit mode; False otherwise.", 0 },
929 { "timeout", Connection_gettimeout, Connection_settimeout, 942 { "timeout", Connection_gettimeout, Connection_settimeout,
930 "The timeout in seconds, zero means no timeout.", 0 }, 943 "The timeout in seconds, zero means no timeout.", 0 },
931 { 0 } 944 { 0 }
932 }; 945 };
933 946
934 PyTypeObject ConnectionType = 947 PyTypeObject ConnectionType =
935 { 948 {
936 PyVarObject_HEAD_INIT(0, 0) 949 PyVarObject_HEAD_INIT(0, 0)
937 "pyodbc.Connection", // tp_name 950 "pyodbc.Connection", // tp_name
938 sizeof(Connection), // tp_basicsize 951 sizeof(Connection), // tp_basicsize
939 0, // tp_itemsize 952 0, // tp_itemsize
940 Connection_dealloc, // destructor tp_dealloc 953 Connection_dealloc, // destructor tp_dealloc
941 0, // tp_print 954 0, // tp_print
942 0, // tp_getattr 955 0, // tp_getattr
943 0, // tp_setattr 956 0, // tp_setattr
944 0, // tp_compare 957 0, // tp_compare
945 0, // tp_repr 958 0, // tp_repr
946 0, // tp_as_number 959 0, // tp_as_number
947 0, // tp_as_sequence 960 0, // tp_as_sequence
948 0, // tp_as_mapping 961 0, // tp_as_mapping
949 0, // tp_hash 962 0, // tp_hash
950 0, // tp_call 963 0, // tp_call
951 0, // tp_str 964 0, // tp_str
952 0, // tp_getattro 965 0, // tp_getattro
953 0, // tp_setattro 966 0, // tp_setattro
954 0, // tp_as_buffer 967 0, // tp_as_buffer
955 Py_TPFLAGS_DEFAULT, // tp_flags 968 Py_TPFLAGS_DEFAULT, // tp_flags
956 connection_doc, // tp_doc 969 connection_doc, // tp_doc
957 0, // tp_traverse 970 0, // tp_traverse
958 0, // tp_clear 971 0, // tp_clear
959 0, // tp_richcompare 972 0, // tp_richcompare
960 0, // tp_weaklistoffset 973 0, // tp_weaklistoffset
961 0, // tp_iter 974 0, // tp_iter
962 0, // tp_iternext 975 0, // tp_iternext
963 Connection_methods, // tp_methods 976 Connection_methods, // tp_methods
964 0, // tp_members 977 0, // tp_members
965 Connection_getseters, // tp_getset 978 Connection_getseters, // tp_getset
966 0, // tp_base 979 0, // tp_base
967 0, // tp_dict 980 0, // tp_dict
968 0, // tp_descr_get 981 0, // tp_descr_get
969 0, // tp_descr_set 982 0, // tp_descr_set
970 0, // tp_dictoffset 983 0, // tp_dictoffset
971 0, // tp_init 984 0, // tp_init
972 0, // tp_alloc 985 0, // tp_alloc
973 0, // tp_new 986 0, // tp_new
974 0, // tp_free 987 0, // tp_free
975 0, // tp_is_gc 988 0, // tp_is_gc
976 0, // tp_bases 989 0, // tp_bases
977 0, // tp_mro 990 0, // tp_mro
978 0, // tp_cache 991 0, // tp_cache
979 0, // tp_subclasses 992 0, // tp_subclasses
980 0, // tp_weaklist 993 0, // tp_weaklist
981 }; 994 };
Powered by Google Project Hosting