Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 870 lines (733 sloc) 27.572 kB
c278e74 @mkleehammer Single source base for Python 2 and 3
authored
1
2 #include "pyodbc.h"
3 #include "pyodbcmodule.h"
4 #include "params.h"
5 #include "cursor.h"
6 #include "connection.h"
7 #include "buffer.h"
8 #include "wrapper.h"
9 #include "errors.h"
10 #include "dbspecific.h"
11 #include "sqlwchar.h"
12 #include <datetime.h>
13
14
15 inline Connection* GetConnection(Cursor* cursor)
16 {
17 return (Connection*)cursor->cnxn;
18 }
19
20 static bool GetParamType(Cursor* cur, Py_ssize_t iParam, SQLSMALLINT& type);
21
22 static void FreeInfos(ParamInfo* a, Py_ssize_t count)
23 {
24 for (Py_ssize_t i = 0; i < count; i++)
25 {
26 if (a[i].allocated)
27 pyodbc_free(a[i].ParameterValuePtr);
28 Py_XDECREF(a[i].pParam);
29 }
30 pyodbc_free(a);
31 }
32
33 #define _MAKESTR(n) case n: return #n
34 static const char* SqlTypeName(SQLSMALLINT n)
35 {
36 switch (n)
37 {
38 _MAKESTR(SQL_UNKNOWN_TYPE);
39 _MAKESTR(SQL_CHAR);
40 _MAKESTR(SQL_VARCHAR);
41 _MAKESTR(SQL_LONGVARCHAR);
42 _MAKESTR(SQL_NUMERIC);
43 _MAKESTR(SQL_DECIMAL);
44 _MAKESTR(SQL_INTEGER);
45 _MAKESTR(SQL_SMALLINT);
46 _MAKESTR(SQL_FLOAT);
47 _MAKESTR(SQL_REAL);
48 _MAKESTR(SQL_DOUBLE);
49 _MAKESTR(SQL_DATETIME);
50 _MAKESTR(SQL_WCHAR);
51 _MAKESTR(SQL_WVARCHAR);
52 _MAKESTR(SQL_WLONGVARCHAR);
53 _MAKESTR(SQL_TYPE_DATE);
54 _MAKESTR(SQL_TYPE_TIME);
55 _MAKESTR(SQL_TYPE_TIMESTAMP);
56 _MAKESTR(SQL_SS_TIME2);
57 _MAKESTR(SQL_SS_XML);
58 _MAKESTR(SQL_BINARY);
59 _MAKESTR(SQL_VARBINARY);
60 _MAKESTR(SQL_LONGVARBINARY);
61 }
62 return "unknown";
63 }
64
65 static const char* CTypeName(SQLSMALLINT n)
66 {
67 switch (n)
68 {
69 _MAKESTR(SQL_C_CHAR);
70 _MAKESTR(SQL_C_WCHAR);
71 _MAKESTR(SQL_C_LONG);
72 _MAKESTR(SQL_C_SHORT);
73 _MAKESTR(SQL_C_FLOAT);
74 _MAKESTR(SQL_C_DOUBLE);
75 _MAKESTR(SQL_C_NUMERIC);
76 _MAKESTR(SQL_C_DEFAULT);
77 _MAKESTR(SQL_C_DATE);
78 _MAKESTR(SQL_C_TIME);
79 _MAKESTR(SQL_C_TIMESTAMP);
80 _MAKESTR(SQL_C_TYPE_DATE);
81 _MAKESTR(SQL_C_TYPE_TIME);
82 _MAKESTR(SQL_C_TYPE_TIMESTAMP);
83 _MAKESTR(SQL_C_INTERVAL_YEAR);
84 _MAKESTR(SQL_C_INTERVAL_MONTH);
85 _MAKESTR(SQL_C_INTERVAL_DAY);
86 _MAKESTR(SQL_C_INTERVAL_HOUR);
87 _MAKESTR(SQL_C_INTERVAL_MINUTE);
88 _MAKESTR(SQL_C_INTERVAL_SECOND);
89 _MAKESTR(SQL_C_INTERVAL_YEAR_TO_MONTH);
90 _MAKESTR(SQL_C_INTERVAL_DAY_TO_HOUR);
91 _MAKESTR(SQL_C_INTERVAL_DAY_TO_MINUTE);
92 _MAKESTR(SQL_C_INTERVAL_DAY_TO_SECOND);
93 _MAKESTR(SQL_C_INTERVAL_HOUR_TO_MINUTE);
94 _MAKESTR(SQL_C_INTERVAL_HOUR_TO_SECOND);
95 _MAKESTR(SQL_C_INTERVAL_MINUTE_TO_SECOND);
96 _MAKESTR(SQL_C_BINARY);
97 _MAKESTR(SQL_C_BIT);
98 _MAKESTR(SQL_C_SBIGINT);
99 _MAKESTR(SQL_C_UBIGINT);
100 _MAKESTR(SQL_C_TINYINT);
101 _MAKESTR(SQL_C_SLONG);
102 _MAKESTR(SQL_C_SSHORT);
103 _MAKESTR(SQL_C_STINYINT);
104 _MAKESTR(SQL_C_ULONG);
105 _MAKESTR(SQL_C_USHORT);
106 _MAKESTR(SQL_C_UTINYINT);
107 _MAKESTR(SQL_C_GUID);
108 }
109 return "unknown";
110 }
111
112 static bool GetNullInfo(Cursor* cur, Py_ssize_t index, ParamInfo& info)
113 {
114 if (!GetParamType(cur, index, info.ParameterType))
115 return false;
116
117 info.ValueType = SQL_C_DEFAULT;
118 info.ColumnSize = 1;
119 info.StrLen_or_Ind = SQL_NULL_DATA;
120 return true;
121 }
122
892d79e @mkleehammer Issue 198: Added binaryNull object for binding NULL binary parameters.
authored
123 static bool GetNullBinaryInfo(Cursor* cur, Py_ssize_t index, ParamInfo& info)
124 {
125 info.ValueType = SQL_C_BINARY;
126 info.ParameterType = SQL_BINARY;
127 info.ColumnSize = 1;
128 info.ParameterValuePtr = 0;
129 info.StrLen_or_Ind = SQL_NULL_DATA;
130 return true;
131 }
132
133
c278e74 @mkleehammer Single source base for Python 2 and 3
authored
134 static bool GetBytesInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
135 {
136 // In Python 2, a bytes object (ANSI string) is passed as varchar. In Python 3, it is passed as binary.
137
138 Py_ssize_t len = PyBytes_GET_SIZE(param);
139
140 #if PY_MAJOR_VERSION >= 3
141 info.ValueType = SQL_C_BINARY;
142 info.ColumnSize = (SQLUINTEGER)max(len, 1);
143
144 if (len <= cur->cnxn->binary_maxlength)
145 {
146 info.ParameterType = SQL_VARBINARY;
147 info.StrLen_or_Ind = len;
148 info.ParameterValuePtr = PyBytes_AS_STRING(param);
149 }
150 else
151 {
152 // Too long to pass all at once, so we'll provide the data at execute.
153 info.ParameterType = SQL_LONGVARBINARY;
154 info.StrLen_or_Ind = SQL_LEN_DATA_AT_EXEC((SQLLEN)len);
155 info.ParameterValuePtr = param;
156 }
157
158 #else
159 info.ValueType = SQL_C_CHAR;
160 info.ColumnSize = (SQLUINTEGER)max(len, 1);
161
162 if (len <= cur->cnxn->varchar_maxlength)
163 {
164 info.ParameterType = SQL_VARCHAR;
165 info.StrLen_or_Ind = len;
166 info.ParameterValuePtr = PyBytes_AS_STRING(param);
167 }
168 else
169 {
170 // Too long to pass all at once, so we'll provide the data at execute.
171 info.ParameterType = SQL_LONGVARCHAR;
172 info.StrLen_or_Ind = SQL_LEN_DATA_AT_EXEC((SQLLEN)len);
173 info.ParameterValuePtr = param;
174 }
175 #endif
176
177 return true;
178 }
179
180 static bool GetUnicodeInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
181 {
182 Py_UNICODE* pch = PyUnicode_AsUnicode(param);
183 Py_ssize_t len = PyUnicode_GET_SIZE(param);
184
185 info.ValueType = SQL_C_WCHAR;
186 info.ColumnSize = (SQLUINTEGER)max(len, 1);
187
188 if (len <= cur->cnxn->wvarchar_maxlength)
189 {
190 if (SQLWCHAR_SIZE == Py_UNICODE_SIZE)
191 {
192 info.ParameterValuePtr = pch;
193 }
194 else
195 {
196 // SQLWCHAR and Py_UNICODE are not the same size, so we need to allocate and copy a buffer.
197 if (len > 0)
198 {
199 info.ParameterValuePtr = SQLWCHAR_FromUnicode(pch, len);
200 if (info.ParameterValuePtr == 0)
201 return false;
202 info.allocated = true;
203 }
204 else
205 {
206 info.ParameterValuePtr = pch;
207 }
208 }
209
210 info.ParameterType = SQL_WVARCHAR;
211 info.StrLen_or_Ind = (SQLINTEGER)(len * sizeof(SQLWCHAR));
212 }
213 else
214 {
215 // Too long to pass all at once, so we'll provide the data at execute.
216
217 info.ParameterType = SQL_WLONGVARCHAR;
218 info.StrLen_or_Ind = SQL_LEN_DATA_AT_EXEC((SQLLEN)(len * sizeof(SQLWCHAR)));
219 info.ParameterValuePtr = param;
220 }
221
222 return true;
223 }
224
225 static bool GetBooleanInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
226 {
227 info.ValueType = SQL_C_BIT;
228 info.ParameterType = SQL_BIT;
229 info.StrLen_or_Ind = 1;
230 info.Data.ch = (unsigned char)(param == Py_True ? 1 : 0);
231 info.ParameterValuePtr = &info.Data.ch;
232 return true;
233 }
234
235 static bool GetDateTimeInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
236 {
237 info.Data.timestamp.year = (SQLSMALLINT) PyDateTime_GET_YEAR(param);
238 info.Data.timestamp.month = (SQLUSMALLINT)PyDateTime_GET_MONTH(param);
239 info.Data.timestamp.day = (SQLUSMALLINT)PyDateTime_GET_DAY(param);
240 info.Data.timestamp.hour = (SQLUSMALLINT)PyDateTime_DATE_GET_HOUR(param);
241 info.Data.timestamp.minute = (SQLUSMALLINT)PyDateTime_DATE_GET_MINUTE(param);
242 info.Data.timestamp.second = (SQLUSMALLINT)PyDateTime_DATE_GET_SECOND(param);
243
244 // SQL Server chokes if the fraction has more data than the database supports. We expect other databases to be the
245 // same, so we reduce the value to what the database supports. http://support.microsoft.com/kb/263872
246
247 int precision = ((Connection*)cur->cnxn)->datetime_precision - 20; // (20 includes a separating period)
248 if (precision <= 0)
249 {
250 info.Data.timestamp.fraction = 0;
251 }
252 else
253 {
254 info.Data.timestamp.fraction = (SQLUINTEGER)(PyDateTime_DATE_GET_MICROSECOND(param) * 1000); // 1000 == micro -> nano
255
256 // (How many leading digits do we want to keep? With SQL Server 2005, this should be 3: 123000000)
257 int keep = (int)pow(10.0, 9-min(9, precision));
258 info.Data.timestamp.fraction = info.Data.timestamp.fraction / keep * keep;
259 info.DecimalDigits = (SQLSMALLINT)precision;
260 }
261
262 info.ValueType = SQL_C_TIMESTAMP;
263 info.ParameterType = SQL_TIMESTAMP;
264 info.ColumnSize = (SQLUINTEGER)((Connection*)cur->cnxn)->datetime_precision;
265 info.StrLen_or_Ind = sizeof(TIMESTAMP_STRUCT);
266 info.ParameterValuePtr = &info.Data.timestamp;
267 return true;
268 }
269
270 static bool GetDateInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
271 {
272 info.Data.date.year = (SQLSMALLINT) PyDateTime_GET_YEAR(param);
273 info.Data.date.month = (SQLUSMALLINT)PyDateTime_GET_MONTH(param);
274 info.Data.date.day = (SQLUSMALLINT)PyDateTime_GET_DAY(param);
275
276 info.ValueType = SQL_C_TYPE_DATE;
277 info.ParameterType = SQL_TYPE_DATE;
278 info.ColumnSize = 10;
279 info.ParameterValuePtr = &info.Data.date;
280 info.StrLen_or_Ind = sizeof(DATE_STRUCT);
281 return true;
282 }
283
284 static bool GetTimeInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
285 {
286 info.Data.time.hour = (SQLUSMALLINT)PyDateTime_TIME_GET_HOUR(param);
287 info.Data.time.minute = (SQLUSMALLINT)PyDateTime_TIME_GET_MINUTE(param);
288 info.Data.time.second = (SQLUSMALLINT)PyDateTime_TIME_GET_SECOND(param);
289
290 info.ValueType = SQL_C_TYPE_TIME;
291 info.ParameterType = SQL_TYPE_TIME;
292 info.ColumnSize = 8;
293 info.ParameterValuePtr = &info.Data.time;
294 info.StrLen_or_Ind = sizeof(TIME_STRUCT);
295 return true;
296 }
297
298 #if PY_MAJOR_VERSION < 3
299 static bool GetIntInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
300 {
301 info.Data.l = PyInt_AsLong(param);
302
303 #if LONG_BIT == 64
304 info.ValueType = SQL_C_SBIGINT;
305 info.ParameterType = SQL_BIGINT;
306 #elif LONG_BIT == 32
307 info.ValueType = SQL_C_LONG;
308 info.ParameterType = SQL_INTEGER;
309 #else
310 #error Unexpected LONG_BIT value
311 #endif
312
313 info.ParameterValuePtr = &info.Data.l;
314 return true;
315 }
316 #endif
317
318 static bool GetLongInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
319 {
320 // TODO: Overflow?
321 info.Data.i64 = (INT64)PyLong_AsLongLong(param);
322
323 info.ValueType = SQL_C_SBIGINT;
324 info.ParameterType = SQL_BIGINT;
325 info.ParameterValuePtr = &info.Data.i64;
326 return true;
327 }
328
329 static bool GetFloatInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
330 {
331 // TODO: Overflow?
332 info.Data.dbl = PyFloat_AsDouble(param);
333
334 info.ValueType = SQL_C_DOUBLE;
335 info.ParameterType = SQL_DOUBLE;
336 info.ParameterValuePtr = &info.Data.dbl;
337 info.ColumnSize = 15;
338 return true;
339 }
340
341 static char* CreateDecimalString(long sign, PyObject* digits, long exp)
342 {
343 long count = (long)PyTuple_GET_SIZE(digits);
344
345 char* pch;
346 int len;
347
348 if (exp >= 0)
349 {
350 // (1 2 3) exp = 2 --> '12300'
351
352 len = sign + count + exp + 1; // 1: NULL
353 pch = (char*)pyodbc_malloc((size_t)len);
354 if (pch)
355 {
356 char* p = pch;
357 if (sign)
358 *p++ = '-';
359 for (long i = 0; i < count; i++)
360 *p++ = (char)('0' + PyInt_AS_LONG(PyTuple_GET_ITEM(digits, i)));
361 for (long i = 0; i < exp; i++)
362 *p++ = '0';
363 *p = 0;
364 }
365 }
366 else if (-exp < count)
367 {
368 // (1 2 3) exp = -2 --> 1.23 : prec = 3, scale = 2
369
370 len = sign + count + 2; // 2: decimal + NULL
371 pch = (char*)pyodbc_malloc((size_t)len);
372 if (pch)
373 {
374 char* p = pch;
375 if (sign)
376 *p++ = '-';
377 int i = 0;
378 for (; i < (count + exp); i++)
379 *p++ = (char)('0' + PyInt_AS_LONG(PyTuple_GET_ITEM(digits, i)));
380 *p++ = '.';
381 for (; i < count; i++)
382 *p++ = (char)('0' + PyInt_AS_LONG(PyTuple_GET_ITEM(digits, i)));
383 *p++ = 0;
384 }
385 }
386 else
387 {
388 // (1 2 3) exp = -5 --> 0.00123 : prec = 5, scale = 5
389
390 len = sign + -exp + 3; // 3: leading zero + decimal + NULL
391
392 pch = (char*)pyodbc_malloc((size_t)len);
393 if (pch)
394 {
395 char* p = pch;
396 if (sign)
397 *p++ = '-';
398 *p++ = '0';
399 *p++ = '.';
400
401 for (int i = 0; i < -(exp + count); i++)
402 *p++ = '0';
403
404 for (int i = 0; i < count; i++)
405 *p++ = (char)('0' + PyInt_AS_LONG(PyTuple_GET_ITEM(digits, i)));
406 *p++ = 0;
407 }
408 }
409
410 I(pch == 0 || (int)(strlen(pch) + 1) == len);
411
412 return pch;
413 }
414
415 static bool GetDecimalInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
416 {
417 // The NUMERIC structure never works right with SQL Server and probably a lot of other drivers. We'll bind as a
418 // string. Unfortunately, the Decimal class doesn't seem to have a way to force it to return a string without
419 // exponents, so we'll have to build it ourselves.
420
421 Object t = PyObject_CallMethod(param, "as_tuple", 0);
422 if (!t)
423 return false;
424
425 long sign = PyInt_AsLong(PyTuple_GET_ITEM(t.Get(), 0));
426 PyObject* digits = PyTuple_GET_ITEM(t.Get(), 1);
427 long exp = PyInt_AsLong(PyTuple_GET_ITEM(t.Get(), 2));
428
429 Py_ssize_t count = PyTuple_GET_SIZE(digits);
430
431 info.ValueType = SQL_C_CHAR;
432 info.ParameterType = SQL_NUMERIC;
433
434 if (exp >= 0)
435 {
436 // (1 2 3) exp = 2 --> '12300'
437
438 info.ColumnSize = (SQLUINTEGER)count + exp;
439 info.DecimalDigits = 0;
440
441 }
442 else if (-exp <= count)
443 {
444 // (1 2 3) exp = -2 --> 1.23 : prec = 3, scale = 2
445 info.ColumnSize = (SQLUINTEGER)count;
446 info.DecimalDigits = (SQLSMALLINT)-exp;
447 }
448 else
449 {
450 // (1 2 3) exp = -5 --> 0.00123 : prec = 5, scale = 5
451 info.ColumnSize = (SQLUINTEGER)(count + (-exp));
452 info.DecimalDigits = (SQLSMALLINT)info.ColumnSize;
453 }
454
455 I(info.ColumnSize >= (SQLULEN)info.DecimalDigits);
456
457 info.ParameterValuePtr = CreateDecimalString(sign, digits, exp);
458 if (!info.ParameterValuePtr)
459 {
460 PyErr_NoMemory();
461 return false;
462 }
463 info.allocated = true;
464
465 info.StrLen_or_Ind = (SQLINTEGER)strlen((char*)info.ParameterValuePtr);
466
467 return true;
468 }
469
470 #if PY_MAJOR_VERSION < 3
471 static bool GetBufferInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
472 {
473 info.ValueType = SQL_C_BINARY;
474
475 const char* pb;
476 Py_ssize_t cb = PyBuffer_GetMemory(param, &pb);
477
478 if (cb != -1 && cb <= cur->cnxn->binary_maxlength)
479 {
480 // There is one segment, so we can bind directly into the buffer object.
481
482 info.ParameterType = SQL_VARBINARY;
483 info.ParameterValuePtr = (SQLPOINTER)pb;
484 info.BufferLength = cb;
485 info.ColumnSize = (SQLUINTEGER)max(cb, 1);
486 info.StrLen_or_Ind = cb;
487 }
488 else
489 {
490 // There are multiple segments, so we'll provide the data at execution time. Pass the PyObject pointer as
491 // the parameter value which will be pased back to us when the data is needed. (If we release threads, we
492 // need to up the refcount!)
493
494 info.ParameterType = SQL_LONGVARBINARY;
495 info.ParameterValuePtr = param;
496 info.ColumnSize = (SQLUINTEGER)PyBuffer_Size(param);
497 info.BufferLength = sizeof(PyObject*); // How big is ParameterValuePtr; ODBC copies it and gives it back in SQLParamData
498 info.StrLen_or_Ind = SQL_LEN_DATA_AT_EXEC(PyBuffer_Size(param));
499 }
500
501 return true;
502 }
503 #endif
504
505 #if PY_VERSION_HEX >= 0x02060000
506 static bool GetByteArrayInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
507 {
508 info.ValueType = SQL_C_BINARY;
509
510 Py_ssize_t cb = PyByteArray_Size(param);
511 if (cb <= cur->cnxn->binary_maxlength)
512 {
513 info.ParameterType = SQL_VARBINARY;
514 info.ParameterValuePtr = (SQLPOINTER)PyByteArray_AsString(param);
515 info.BufferLength = cb;
516 info.ColumnSize = (SQLUINTEGER)max(cb, 1);
517 info.StrLen_or_Ind = cb;
518 }
519 else
520 {
521 info.ParameterType = SQL_LONGVARBINARY;
522 info.ParameterValuePtr = param;
523 info.ColumnSize = (SQLUINTEGER)cb;
524 info.BufferLength = sizeof(PyObject*); // How big is ParameterValuePtr; ODBC copies it and gives it back in SQLParamData
525 info.StrLen_or_Ind = SQL_LEN_DATA_AT_EXEC(cb);
526 }
527 return true;
528 }
529 #endif
530
531 static bool GetParameterInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
532 {
533 // Determines the type of SQL parameter that will be used for this parameter based on the Python data type.
534 //
535 // Populates `info`.
536
537 // Hold a reference to param until info is freed, because info will often be holding data borrowed from param.
538 info.pParam = param;
539
540 if (param == Py_None)
541 return GetNullInfo(cur, index, info);
542
892d79e @mkleehammer Issue 198: Added binaryNull object for binding NULL binary parameters.
authored
543 if (param == null_binary)
544 return GetNullBinaryInfo(cur, index, info);
545
c278e74 @mkleehammer Single source base for Python 2 and 3
authored
546 if (PyBytes_Check(param))
547 return GetBytesInfo(cur, index, param, info);
548
549 if (PyUnicode_Check(param))
550 return GetUnicodeInfo(cur, index, param, info);
551
552 if (PyBool_Check(param))
553 return GetBooleanInfo(cur, index, param, info);
554
555 if (PyDateTime_Check(param))
556 return GetDateTimeInfo(cur, index, param, info);
557
558 if (PyDate_Check(param))
559 return GetDateInfo(cur, index, param, info);
560
561 if (PyTime_Check(param))
562 return GetTimeInfo(cur, index, param, info);
563
564 if (PyLong_Check(param))
565 return GetLongInfo(cur, index, param, info);
566
567 if (PyFloat_Check(param))
568 return GetFloatInfo(cur, index, param, info);
569
570 if (PyDecimal_Check(param))
571 return GetDecimalInfo(cur, index, param, info);
572
573 #if PY_VERSION_HEX >= 0x02060000
574 if (PyByteArray_Check(param))
575 return GetByteArrayInfo(cur, index, param, info);
576 #endif
577
578 #if PY_MAJOR_VERSION < 3
579 if (PyInt_Check(param))
580 return GetIntInfo(cur, index, param, info);
581
582 if (PyBuffer_Check(param))
583 return GetBufferInfo(cur, index, param, info);
584 #endif
585
586 RaiseErrorV("HY105", ProgrammingError, "Invalid parameter type. param-index=%zd param-type=%s", index, Py_TYPE(param)->tp_name);
587 return false;
588 }
589
590 bool BindParameter(Cursor* cur, Py_ssize_t index, ParamInfo& info)
591 {
592 TRACE("BIND: param=%d ValueType=%d (%s) ParameterType=%d (%s) ColumnSize=%d DecimalDigits=%d BufferLength=%d *pcb=%d\n",
593 (index+1), info.ValueType, CTypeName(info.ValueType), info.ParameterType, SqlTypeName(info.ParameterType), info.ColumnSize,
594 info.DecimalDigits, info.BufferLength, info.StrLen_or_Ind);
595
596 SQLRETURN ret = -1;
597 Py_BEGIN_ALLOW_THREADS
598 ret = SQLBindParameter(cur->hstmt, (SQLUSMALLINT)(index + 1), SQL_PARAM_INPUT, info.ValueType, info.ParameterType, info.ColumnSize, info.DecimalDigits, info.ParameterValuePtr, info.BufferLength, &info.StrLen_or_Ind);
599 Py_END_ALLOW_THREADS;
600
601 if (GetConnection(cur)->hdbc == SQL_NULL_HANDLE)
602 {
603 // The connection was closed by another thread in the ALLOW_THREADS block above.
604 RaiseErrorV(0, ProgrammingError, "The cursor's connection was closed.");
605 return false;
606 }
607
608 if (!SQL_SUCCEEDED(ret))
609 {
610 RaiseErrorFromHandle("SQLBindParameter", GetConnection(cur)->hdbc, cur->hstmt);
611 return false;
612 }
613
614 return true;
615 }
616
617
618 void FreeParameterData(Cursor* cur)
619 {
620 // Unbinds the parameters and frees the parameter buffer.
621
622 if (cur->paramInfos)
623 {
624 // MS ODBC will crash if we use an HSTMT after the HDBC has been freed.
625 if (cur->cnxn->hdbc != SQL_NULL_HANDLE)
626 {
627 Py_BEGIN_ALLOW_THREADS
628 SQLFreeStmt(cur->hstmt, SQL_RESET_PARAMS);
629 Py_END_ALLOW_THREADS
630 }
631
632 FreeInfos(cur->paramInfos, cur->paramcount);
633 cur->paramInfos = 0;
634 }
635 }
636
637 void FreeParameterInfo(Cursor* cur)
638 {
639 // Internal function to free just the cached parameter information. This is not used by the general cursor code
640 // since this information is also freed in the less granular free_results function that clears everything.
641
642 Py_XDECREF(cur->pPreparedSQL);
643 pyodbc_free(cur->paramtypes);
644 cur->pPreparedSQL = 0;
645 cur->paramtypes = 0;
646 cur->paramcount = 0;
647 }
648
649 bool PrepareAndBind(Cursor* cur, PyObject* pSql, PyObject* original_params, bool skip_first)
650 {
651 #if PY_MAJOR_VERSION >= 3
652 if (!PyUnicode_Check(pSql))
653 {
654 PyErr_SetString(PyExc_TypeError, "SQL must be a Unicode string");
655 return false;
656 }
657 #endif
658
659 //
660 // Normalize the parameter variables.
661 //
662
663 // Since we may replace parameters (we replace objects with Py_True/Py_False when writing to a bit/bool column),
664 // allocate an array and use it instead of the original sequence
665
666 int params_offset = skip_first ? 1 : 0;
667 Py_ssize_t cParams = original_params == 0 ? 0 : PySequence_Length(original_params) - params_offset;
668
669 //
670 // Prepare the SQL if necessary.
671 //
672
673 if (pSql != cur->pPreparedSQL)
674 {
675 FreeParameterInfo(cur);
676
677 SQLRETURN ret = 0;
678 SQLSMALLINT cParamsT = 0;
679 const char* szErrorFunc = "SQLPrepare";
680
681 if (PyUnicode_Check(pSql))
682 {
683 SQLWChar sql(pSql);
684 Py_BEGIN_ALLOW_THREADS
685 ret = SQLPrepareW(cur->hstmt, sql, SQL_NTS);
686 if (SQL_SUCCEEDED(ret))
687 {
688 szErrorFunc = "SQLNumParams";
689 ret = SQLNumParams(cur->hstmt, &cParamsT);
690 }
691 Py_END_ALLOW_THREADS
692 }
693 #if PY_MAJOR_VERSION < 3
694 else
695 {
696 TRACE("SQLPrepare(%s)\n", PyString_AS_STRING(pSql));
697 Py_BEGIN_ALLOW_THREADS
698 ret = SQLPrepare(cur->hstmt, (SQLCHAR*)PyString_AS_STRING(pSql), SQL_NTS);
699 if (SQL_SUCCEEDED(ret))
700 {
701 szErrorFunc = "SQLNumParams";
702 ret = SQLNumParams(cur->hstmt, &cParamsT);
703 }
704 Py_END_ALLOW_THREADS
705 }
706 #endif
707
708 if (cur->cnxn->hdbc == SQL_NULL_HANDLE)
709 {
710 // The connection was closed by another thread in the ALLOW_THREADS block above.
711 RaiseErrorV(0, ProgrammingError, "The cursor's connection was closed.");
712 return false;
713 }
714
715 if (!SQL_SUCCEEDED(ret))
716 {
717 RaiseErrorFromHandle(szErrorFunc, GetConnection(cur)->hdbc, cur->hstmt);
718 return false;
719 }
720
721 cur->paramcount = (int)cParamsT;
722
723 cur->pPreparedSQL = pSql;
724 Py_INCREF(cur->pPreparedSQL);
725 }
726
727 if (cParams != cur->paramcount)
728 {
729 RaiseErrorV(0, ProgrammingError, "The SQL contains %d parameter markers, but %d parameters were supplied",
730 cur->paramcount, cParams);
731 return false;
732 }
733
734 cur->paramInfos = (ParamInfo*)pyodbc_malloc(sizeof(ParamInfo) * cParams);
735 if (cur->paramInfos == 0)
736 {
737 PyErr_NoMemory();
738 return 0;
739 }
740 memset(cur->paramInfos, 0, sizeof(ParamInfo) * cParams);
741
742 // Since you can't call SQLDesribeParam *after* calling SQLBindParameter, we'll loop through all of the
743 // GetParameterInfos first, then bind.
744
745 for (Py_ssize_t i = 0; i < cParams; i++)
746 {
747 // PySequence_GetItem returns a *new* reference, which GetParameterInfo will take ownership of. It is stored
748 // in paramInfos and will be released in FreeInfos (which is always eventually called).
749
750 PyObject* param = PySequence_GetItem(original_params, i + params_offset);
751 if (!GetParameterInfo(cur, i, param, cur->paramInfos[i]))
752 {
753 FreeInfos(cur->paramInfos, cParams);
754 cur->paramInfos = 0;
755 return false;
756 }
757 }
758
759 for (Py_ssize_t i = 0; i < cParams; i++)
760 {
761 if (!BindParameter(cur, i, cur->paramInfos[i]))
762 {
763 FreeInfos(cur->paramInfos, cParams);
764 cur->paramInfos = 0;
765 return false;
766 }
767 }
768
769 return true;
770 }
771
772 static bool GetParamType(Cursor* cur, Py_ssize_t index, SQLSMALLINT& type)
773 {
774 // Returns the ODBC type of the of given parameter.
775 //
776 // Normally we set the parameter type based on the parameter's Python object type (e.g. str --> SQL_CHAR), so this
777 // is only called when the parameter is None. In that case, we can't guess the type and have to use
778 // SQLDescribeParam.
779 //
780 // If the database doesn't support SQLDescribeParam, we return SQL_VARCHAR since it converts to most other types.
781 // However, it will not usually work if the target column is a binary column.
782
783 if (!GetConnection(cur)->supports_describeparam || cur->paramcount == 0)
784 {
785 type = SQL_VARCHAR;
786 return true;
787 }
788
789 if (cur->paramtypes == 0)
790 {
791 cur->paramtypes = reinterpret_cast<SQLSMALLINT*>(pyodbc_malloc(sizeof(SQLSMALLINT) * cur->paramcount));
792 if (cur->paramtypes == 0)
793 {
794 PyErr_NoMemory();
795 return false;
796 }
797
798 // SQL_UNKNOWN_TYPE is zero, so zero out all columns since we haven't looked any up yet.
799 memset(cur->paramtypes, 0, sizeof(SQLSMALLINT) * cur->paramcount);
800 }
801
802 if (cur->paramtypes[index] == SQL_UNKNOWN_TYPE)
803 {
804 SQLULEN ParameterSizePtr;
805 SQLSMALLINT DecimalDigitsPtr;
806 SQLSMALLINT NullablePtr;
807 SQLRETURN ret;
808
809 Py_BEGIN_ALLOW_THREADS
810 ret = SQLDescribeParam(cur->hstmt, (SQLUSMALLINT)(index + 1), &cur->paramtypes[index], &ParameterSizePtr, &DecimalDigitsPtr, &NullablePtr);
811 Py_END_ALLOW_THREADS
812
813 if (!SQL_SUCCEEDED(ret))
814 {
815 // This can happen with ("select ?", None). We'll default to VARCHAR which works with most types.
816 cur->paramtypes[index] = SQL_VARCHAR;
817 }
818 }
819
820 type = cur->paramtypes[index];
821 return true;
822 }
892d79e @mkleehammer Issue 198: Added binaryNull object for binding NULL binary parameters.
authored
823
824 struct NullParam
825 {
826 PyObject_HEAD
827 };
828
829
830 PyTypeObject NullParamType =
831 {
832 PyVarObject_HEAD_INIT(NULL, 0)
833 "pyodbc.NullParam", // tp_name
834 sizeof(NullParam), // tp_basicsize
835 0, // tp_itemsize
836 0, // destructor tp_dealloc
837 0, // tp_print
838 0, // tp_getattr
839 0, // tp_setattr
840 0, // tp_compare
841 0, // tp_repr
842 0, // tp_as_number
843 0, // tp_as_sequence
844 0, // tp_as_mapping
845 0, // tp_hash
846 0, // tp_call
847 0, // tp_str
848 0, // tp_getattro
849 0, // tp_setattro
850 0, // tp_as_buffer
851 Py_TPFLAGS_DEFAULT, // tp_flags
852 };
853
854 PyObject* null_binary;
855
856 bool Params_init()
857 {
858 if (PyType_Ready(&NullParamType) < 0)
859 return false;
860
861 null_binary = (PyObject*)PyObject_New(NullParam, &NullParamType);
862 if (null_binary == 0)
863 return false;
864
865 PyDateTime_IMPORT;
866
867 return true;
868 }
869
Something went wrong with that request. Please try again.