Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Issue 178: Fixed compilation issues with 4.6.2

Removed deprecated Row_slice.  The sequence structure changed this from an actual function
pointer to a void pointer.  GCC 4.6.2 would not allow the assignment of Row_slice to void*.
This may not build under 2.5.

Also eliminated a bunch of casts to see if newer GCC would uncover other issues.
  • Loading branch information...
commit b2dfac9a0b8858548294a5f382a6c52f0a9dbf3c 1 parent e81708a
@mkleehammer authored
View
2  setup.py
@@ -123,7 +123,7 @@ def get_compiler_settings(version_str):
'/wd4711', # function selected for automatic inline expansion
'/wd4100', # unreferenced formal parameter
'/wd4127', # "conditional expression is constant" testing compilation constants
- '/wd4191', # casts to PYCFunction, perhaps the extra parameters should be added
+ '/wd4191', # casts to PYCFunction which doesn't have the keywords parameter
]
settings['libraries'].append('odbc32')
settings['libraries'].append('advapi32')
View
197 src/connection.cpp
@@ -23,8 +23,7 @@ static char connection_doc[] =
"\n"
"Each manages a single ODBC HDBC.";
-static Connection*
-Connection_Validate(PyObject* self)
+static Connection* Connection_Validate(PyObject* self)
{
Connection* cnxn;
@@ -273,20 +272,22 @@ static char conv_clear_doc[] =
"clear_output_converters() --> None\n\n"
"Remove all output converter functions.";
-static PyObject*
-Connection_conv_clear(Connection* cnxn)
+static PyObject* Connection_conv_clear(PyObject* self, PyObject* args)
{
+ UNUSED(args);
+
+ Connection* cnxn = (Connection*)self;
_clear_conv(cnxn);
-
Py_RETURN_NONE;
}
-static int
-Connection_clear(Connection* cnxn)
+static int Connection_clear(PyObject* self)
{
// Internal method for closing the connection. (Not called close so it isn't confused with the external close
// method.)
+ Connection* cnxn = (Connection*)self;
+
if (cnxn->hdbc != SQL_NULL_HANDLE)
{
// REVIEW: Release threads? (But make sure you zero out hdbc *first*!
@@ -312,11 +313,9 @@ Connection_clear(Connection* cnxn)
return 0;
}
-static void
-Connection_dealloc(PyObject* self)
+static void Connection_dealloc(PyObject* self)
{
- Connection* cnxn = (Connection*)self;
- Connection_clear(cnxn);
+ Connection_clear(self);
PyObject_Del(self);
}
@@ -330,8 +329,7 @@ static char close_doc[] =
"Note that closing a connection without committing the changes first will cause\n"
"an implicit rollback to be performed.";
-static PyObject*
-Connection_close(PyObject* self, PyObject* args)
+static PyObject* Connection_close(PyObject* self, PyObject* args)
{
UNUSED(args);
@@ -339,13 +337,12 @@ Connection_close(PyObject* self, PyObject* args)
if (!cnxn)
return 0;
- Connection_clear(cnxn);
+ Connection_clear(self);
Py_RETURN_NONE;
}
-static PyObject*
-Connection_cursor(PyObject* self, PyObject* args)
+static PyObject* Connection_cursor(PyObject* self, PyObject* args)
{
UNUSED(args);
@@ -356,8 +353,7 @@ Connection_cursor(PyObject* self, PyObject* args)
return (PyObject*)Cursor_New(cnxn);
}
-static PyObject*
-Connection_execute(PyObject* self, PyObject* args)
+static PyObject* Connection_execute(PyObject* self, PyObject* args)
{
PyObject* result = 0;
@@ -537,8 +533,7 @@ static const GetInfoType aInfoTypes[] = {
{ SQL_XOPEN_CLI_YEAR, GI_STRING },
};
-static PyObject*
-Connection_getinfo(PyObject* self, PyObject* args)
+static PyObject* Connection_getinfo(PyObject* self, PyObject* args)
{
Connection* cnxn = Connection_Validate(self);
if (!cnxn)
@@ -607,8 +602,7 @@ Connection_getinfo(PyObject* self, PyObject* args)
}
-static PyObject*
-Connection_endtrans(PyObject* self, PyObject* args, SQLSMALLINT type)
+static PyObject* Connection_endtrans(PyObject* self, PyObject* args, SQLSMALLINT type)
{
UNUSED(args);
@@ -631,14 +625,12 @@ Connection_endtrans(PyObject* self, PyObject* args, SQLSMALLINT type)
Py_RETURN_NONE;
}
-static PyObject*
-Connection_commit(PyObject* self, PyObject* args)
+static PyObject* Connection_commit(PyObject* self, PyObject* args)
{
return Connection_endtrans(self, args, SQL_COMMIT);
}
-static PyObject*
-Connection_rollback(PyObject* self, PyObject* args)
+static PyObject* Connection_rollback(PyObject* self, PyObject* args)
{
return Connection_endtrans(self, args, SQL_ROLLBACK);
}
@@ -668,8 +660,7 @@ static char getinfo_doc[] =
"Calls SQLGetInfo, passing `type`, and returns the result formatted as a Python object.";
-PyObject*
-Connection_getautocommit(PyObject* self, void* closure)
+PyObject* Connection_getautocommit(PyObject* self, void* closure)
{
UNUSED(closure);
@@ -682,8 +673,7 @@ Connection_getautocommit(PyObject* self, void* closure)
return result;
}
-static int
-Connection_setautocommit(PyObject* self, PyObject* value, void* closure)
+static int Connection_setautocommit(PyObject* self, PyObject* value, void* closure)
{
UNUSED(closure);
@@ -714,33 +704,33 @@ Connection_setautocommit(PyObject* self, PyObject* value, void* closure)
}
-PyObject*
-Connection_getsearchescape(Connection* self, void* closure)
+static PyObject* Connection_getsearchescape(PyObject* self, void* closure)
{
UNUSED(closure);
- if (!self->searchescape)
+ Connection* cnxn = (Connection*)self;
+
+ if (!cnxn->searchescape)
{
char sz[8] = { 0 };
SQLSMALLINT cch = 0;
SQLRETURN ret;
Py_BEGIN_ALLOW_THREADS
- ret = SQLGetInfo(self->hdbc, SQL_SEARCH_PATTERN_ESCAPE, &sz, _countof(sz), &cch);
+ ret = SQLGetInfo(cnxn->hdbc, SQL_SEARCH_PATTERN_ESCAPE, &sz, _countof(sz), &cch);
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
- return RaiseErrorFromHandle("SQLGetInfo", self->hdbc, SQL_NULL_HANDLE);
+ return RaiseErrorFromHandle("SQLGetInfo", cnxn->hdbc, SQL_NULL_HANDLE);
- self->searchescape = PyString_FromStringAndSize(sz, (Py_ssize_t)cch);
+ cnxn->searchescape = PyString_FromStringAndSize(sz, (Py_ssize_t)cch);
}
- Py_INCREF(self->searchescape);
- return self->searchescape;
+ Py_INCREF(cnxn->searchescape);
+ return cnxn->searchescape;
}
-static PyObject*
-Connection_gettimeout(PyObject* self, void* closure)
+static PyObject* Connection_gettimeout(PyObject* self, void* closure)
{
UNUSED(closure);
@@ -751,8 +741,7 @@ Connection_gettimeout(PyObject* self, void* closure)
return PyInt_FromLong(cnxn->timeout);
}
-static int
-Connection_settimeout(PyObject* self, PyObject* value, void* closure)
+static int Connection_settimeout(PyObject* self, PyObject* value, void* closure)
{
UNUSED(closure);
@@ -789,8 +778,10 @@ Connection_settimeout(PyObject* self, PyObject* value, void* closure)
return 0;
}
-static bool _add_converter(Connection* cnxn, SQLSMALLINT sqltype, PyObject* func)
+static bool _add_converter(PyObject* self, SQLSMALLINT sqltype, PyObject* func)
{
+ Connection* cnxn = (Connection*)self;
+
if (cnxn->conv_count)
{
// If the sqltype is already registered, replace the old conversion function with the new.
@@ -862,30 +853,32 @@ static char conv_add_doc[] =
" parameter will be None. Otherwise it will be a Python string.";
-static PyObject*
-Connection_conv_add(Connection* cnxn, PyObject* args)
+static PyObject* Connection_conv_add(PyObject* self, PyObject* args)
{
int sqltype;
PyObject* func;
if (!PyArg_ParseTuple(args, "iO", &sqltype, &func))
return 0;
- if (!_add_converter(cnxn, (SQLSMALLINT)sqltype, func))
+ if (!_add_converter(self, (SQLSMALLINT)sqltype, func))
return 0;
Py_RETURN_NONE;
}
static char enter_doc[] = "__enter__() -> self.";
-static PyObject* Connection_enter(PyObject* self)
+static PyObject* Connection_enter(PyObject* self, PyObject* args)
{
+ UNUSED(args);
Py_INCREF(self);
return self;
}
static char exit_doc[] = "__exit__(*excinfo) -> None. Closes the connection.";
-static PyObject* Connection_exit(Connection* cnxn, PyObject* args)
+static PyObject* Connection_exit(PyObject* self, PyObject* args)
{
+ Connection* cnxn = (Connection*)self;
+
// If an error has occurred, `args` will be a tuple of 3 values. Otherwise it will be a tuple of 3 `None`s.
I(PyTuple_Check(args));
@@ -898,16 +891,16 @@ static PyObject* Connection_exit(Connection* cnxn, PyObject* args)
static struct PyMethodDef Connection_methods[] =
{
- { "cursor", (PyCFunction)Connection_cursor, METH_NOARGS, cursor_doc },
- { "close", (PyCFunction)Connection_close, METH_NOARGS, close_doc },
- { "execute", (PyCFunction)Connection_execute, METH_VARARGS, execute_doc },
- { "commit", (PyCFunction)Connection_commit, METH_NOARGS, commit_doc },
- { "rollback", (PyCFunction)Connection_rollback, METH_NOARGS, rollback_doc },
- { "getinfo", (PyCFunction)Connection_getinfo, METH_VARARGS, getinfo_doc },
- { "add_output_converter", (PyCFunction)Connection_conv_add, METH_VARARGS, conv_add_doc },
- { "clear_output_converters", (PyCFunction)Connection_conv_clear, METH_NOARGS, conv_clear_doc },
- { "__enter__", (PyCFunction)Connection_enter, METH_NOARGS, enter_doc },
- { "__exit__", (PyCFunction)Connection_exit, METH_VARARGS, exit_doc },
+ { "cursor", Connection_cursor, METH_NOARGS, cursor_doc },
+ { "close", Connection_close, METH_NOARGS, close_doc },
+ { "execute", Connection_execute, METH_VARARGS, execute_doc },
+ { "commit", Connection_commit, METH_NOARGS, commit_doc },
+ { "rollback", Connection_rollback, METH_NOARGS, rollback_doc },
+ { "getinfo", Connection_getinfo, METH_VARARGS, getinfo_doc },
+ { "add_output_converter", Connection_conv_add, METH_VARARGS, conv_add_doc },
+ { "clear_output_converters", Connection_conv_clear, METH_NOARGS, conv_clear_doc },
+ { "__enter__", Connection_enter, METH_NOARGS, enter_doc },
+ { "__exit__", Connection_exit, METH_VARARGS, exit_doc },
{ 0, 0, 0, 0 }
};
@@ -926,48 +919,48 @@ static PyGetSetDef Connection_getseters[] = {
PyTypeObject ConnectionType =
{
PyVarObject_HEAD_INIT(0, 0)
- "pyodbc.Connection", // tp_name
- sizeof(Connection), // tp_basicsize
- 0, // tp_itemsize
- (destructor)Connection_dealloc, // destructor tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- 0, // tp_compare
- 0, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- 0, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- 0, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT, // tp_flags
- connection_doc, // tp_doc
- 0, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- 0, // tp_weaklistoffset
- 0, // tp_iter
- 0, // tp_iternext
- Connection_methods, // tp_methods
- 0, // tp_members
- Connection_getseters, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
- 0, // tp_alloc
- 0, // tp_new
- 0, // tp_free
- 0, // tp_is_gc
- 0, // tp_bases
- 0, // tp_mro
- 0, // tp_cache
- 0, // tp_subclasses
- 0, // tp_weaklist
+ "pyodbc.Connection", // tp_name
+ sizeof(Connection), // tp_basicsize
+ 0, // tp_itemsize
+ Connection_dealloc, // destructor tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ connection_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ Connection_methods, // tp_methods
+ 0, // tp_members
+ Connection_getseters, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ 0, // tp_new
+ 0, // tp_free
+ 0, // tp_is_gc
+ 0, // tp_bases
+ 0, // tp_mro
+ 0, // tp_cache
+ 0, // tp_subclasses
+ 0, // tp_weaklist
};
View
292 src/cursor.cpp
@@ -3,7 +3,7 @@
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
@@ -34,29 +34,26 @@ enum
CURSOR_RAISE_ERROR = 0x00000010,
};
-inline bool
-StatementIsValid(Cursor* cursor)
+inline bool StatementIsValid(Cursor* cursor)
{
return cursor->cnxn != 0 && ((Connection*)cursor->cnxn)->hdbc != SQL_NULL_HANDLE && cursor->hstmt != SQL_NULL_HANDLE;
}
extern PyTypeObject CursorType;
-inline bool
-Cursor_Check(PyObject* o)
+inline bool Cursor_Check(PyObject* o)
{
return o != 0 && Py_TYPE(o) == &CursorType;
}
-
-Cursor* Cursor_Validate(PyObject* obj, DWORD flags)
+static Cursor* Cursor_Validate(PyObject* obj, DWORD flags)
{
// Validates that a PyObject is a Cursor (like Cursor_Check) and optionally some other requirements controlled by
// `flags`. If valid and all requirements (from the flags) are met, the cursor is returned, cast to Cursor*.
// Otherwise zero is returned.
- //
+ //
// Designed to be used at the top of methods to convert the PyObject pointer and perform necessary checks.
- //
+ //
// Valid flags are from the CURSOR_ enum above. Note that unless CURSOR_RAISE_ERROR is supplied, an exception
// will not be set. (When deallocating, we really don't want an exception.)
@@ -128,7 +125,7 @@ inline bool IsNumericType(SQLSMALLINT sqltype)
}
-PyObject* PythonTypeFromSqlType(Cursor* cur, const SQLCHAR* name, SQLSMALLINT type, bool unicode_results)
+static PyObject* PythonTypeFromSqlType(Cursor* cur, const SQLCHAR* name, SQLSMALLINT type, bool unicode_results)
{
// Returns a type object ('int', 'str', etc.) for the given ODBC C type. This is used to populate
// Cursor.description with the type of Python object that will be returned for each column.
@@ -176,28 +173,28 @@ PyObject* PythonTypeFromSqlType(Cursor* cur, const SQLCHAR* name, SQLSMALLINT ty
case SQL_TINYINT:
pytype = (PyObject*)&PyInt_Type;
break;
-
+
case SQL_TYPE_DATE:
pytype = (PyObject*)PyDateTimeAPI->DateType;
break;
-
+
case SQL_TYPE_TIME:
case SQL_SS_TIME2: // SQL Server 2008+
pytype = (PyObject*)PyDateTimeAPI->TimeType;
break;
-
+
case SQL_TYPE_TIMESTAMP:
pytype = (PyObject*)PyDateTimeAPI->DateTimeType;
break;
-
+
case SQL_BIGINT:
pytype = (PyObject*)&PyLong_Type;
break;
-
+
case SQL_BIT:
pytype = (PyObject*)&PyBool_Type;
break;
-
+
case SQL_BINARY:
case SQL_VARBINARY:
case SQL_LONGVARBINARY:
@@ -214,18 +211,17 @@ PyObject* PythonTypeFromSqlType(Cursor* cur, const SQLCHAR* name, SQLSMALLINT ty
case SQL_WLONGVARCHAR:
pytype = (PyObject*)&PyUnicode_Type;
break;
-
+
default:
return RaiseErrorV(0, 0, "ODBC data type %d is not supported. Cannot read column %s.", type, (const char*)name);
}
-
+
Py_INCREF(pytype);
return pytype;
}
-static bool
-create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
+static bool create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
{
// Called after an execute to construct the map shared by rows.
@@ -233,7 +229,7 @@ create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
PyObject *desc = 0, *colmap = 0, *colinfo = 0, *type = 0, *index = 0, *nullable_obj=0;
SQLRETURN ret;
- I(cur->hstmt != SQL_NULL_HANDLE && cur->colinfos != 0);
+ I(cur->hstmt != SQL_NULL_HANDLE && cur->colinfos != 0);
// These are the values we expect after free_results. If this function fails, we do not modify any members, so
// they should be set to something Cursor_close can deal with.
@@ -250,7 +246,7 @@ create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
colmap = PyDict_New();
if (!desc || !colmap)
goto done;
-
+
for (int i = 0; i < field_count; i++)
{
SQLCHAR name[300];
@@ -260,8 +256,8 @@ create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
SQLSMALLINT nullable;
Py_BEGIN_ALLOW_THREADS
- ret = SQLDescribeCol(cur->hstmt, (SQLUSMALLINT)(i + 1), name, _countof(name), 0, &nDataType, &nColSize, &cDecimalDigits, &nullable);
- Py_END_ALLOW_THREADS
+ ret = SQLDescribeCol(cur->hstmt, (SQLUSMALLINT)(i + 1), name, _countof(name), 0, &nDataType, &nColSize, &cDecimalDigits, &nullable);
+ Py_END_ALLOW_THREADS
if (cur->cnxn->hdbc == SQL_NULL_HANDLE)
{
@@ -280,7 +276,7 @@ create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
if (lower)
_strlwr((char*)name);
-
+
type = PythonTypeFromSqlType(cur, name, nDataType, cur->cnxn->unicode_results);
if (!type)
goto done;
@@ -319,7 +315,7 @@ create_name_map(Cursor* cur, SQLSMALLINT field_count, bool lower)
nColSize = 42;
}
}
-
+
colinfo = Py_BuildValue("(sOOiiiO)",
(char*)name,
type, // type_code
@@ -370,8 +366,7 @@ enum free_results_type
KEEP_STATEMENT
};
-static bool
-free_results(Cursor* self, free_results_type free_statement)
+static bool free_results(Cursor* self, free_results_type free_statement)
{
// Internal function called any time we need to free the memory associated with query results. It is safe to call
// this even when a query has not been executed.
@@ -384,7 +379,7 @@ free_results(Cursor* self, free_results_type free_statement)
pyodbc_free(self->colinfos);
self->colinfos = 0;
}
-
+
if (StatementIsValid(self))
{
if (free_statement == FREE_STATEMENT)
@@ -428,18 +423,17 @@ free_results(Cursor* self, free_results_type free_statement)
}
-static void
-closeimpl(Cursor* cur)
+static void closeimpl(Cursor* cur)
{
// An internal function for the shared 'closing' code used by Cursor_close and Cursor_dealloc.
- //
+ //
// This method releases the GIL lock while closing, so verify the HDBC still exists if you use it.
free_results(cur, FREE_STATEMENT);
FreeParameterInfo(cur);
FreeParameterData(cur);
-
+
if (StatementIsValid(cur))
{
HSTMT hstmt = cur->hstmt;
@@ -449,7 +443,7 @@ closeimpl(Cursor* cur)
Py_END_ALLOW_THREADS
}
-
+
Py_XDECREF(cur->pPreparedSQL);
Py_XDECREF(cur->description);
Py_XDECREF(cur->map_name_to_index);
@@ -462,15 +456,14 @@ closeimpl(Cursor* cur)
}
static char close_doc[] =
- "Close the cursor now (rather than whenever __del__ is called). The cursor will\n"
- "be unusable from this point forward; a ProgrammingError exception will be\n"
+ "Close the cursor now (rather than whenever __del__ is called). The cursor will\n"
+ "be unusable from this point forward; a ProgrammingError exception will be\n"
"raised if any operation is attempted with the cursor.";
-
-static PyObject*
-Cursor_close(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_close(PyObject* self, PyObject* args)
{
UNUSED(args);
-
+
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
if (!cursor)
return 0;
@@ -481,8 +474,7 @@ Cursor_close(PyObject* self, PyObject* args)
return Py_None;
}
-static void
-Cursor_dealloc(Cursor* cursor)
+static void Cursor_dealloc(Cursor* cursor)
{
if (Cursor_Validate((PyObject*)cursor, CURSOR_REQUIRE_CNXN))
{
@@ -493,16 +485,14 @@ Cursor_dealloc(Cursor* cursor)
}
-
-bool
-InitColumnInfo(Cursor* cursor, SQLUSMALLINT iCol, ColumnInfo* pinfo)
+bool InitColumnInfo(Cursor* cursor, SQLUSMALLINT iCol, ColumnInfo* pinfo)
{
// Initializes ColumnInfo from result set metadata.
SQLRETURN ret;
// REVIEW: This line fails on OS/X with the FileMaker driver : http://www.filemaker.com/support/updaters/xdbc_odbc_mac.html
- //
+ //
// I suspect the problem is that it doesn't allow NULLs in some of the parameters, so I'm going to supply them all
// to see what happens.
@@ -571,7 +561,7 @@ InitColumnInfo(Cursor* cursor, SQLUSMALLINT iCol, ColumnInfo* pinfo)
pinfo->is_unsigned = (f == SQL_TRUE);
break;
}
-
+
default:
pinfo->is_unsigned = false;
}
@@ -580,11 +570,10 @@ InitColumnInfo(Cursor* cursor, SQLUSMALLINT iCol, ColumnInfo* pinfo)
}
-static bool
-PrepareResults(Cursor* cur, int cCols)
+static bool PrepareResults(Cursor* cur, int cCols)
{
// Called after a SELECT has been executed to perform pre-fetch work.
- //
+ //
// Allocates the ColumnInfo structures describing the returned data.
int i;
@@ -610,14 +599,14 @@ PrepareResults(Cursor* cur, int cCols)
return true;
}
-static PyObject*
-execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
+
+static PyObject* execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
{
// Internal function to execute SQL, called by .execute and .executemany.
- //
+ //
// pSql
// A PyString, PyUnicode, or derived object containing the SQL.
- //
+ //
// params
// Pointer to an optional sequence of parameters, and possibly the SQL statement (see skip_first):
// (SQL, param1, param2) or (param1, param2).
@@ -633,7 +622,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
if (!PyTuple_Check(params) && !PyList_Check(params) && !Row_Check(params))
return RaiseErrorV(0, PyExc_TypeError, "Params must be in a list, tuple, or Row");
}
-
+
// Normalize the parameter variables.
int params_offset = skip_first ? 1 : 0;
@@ -653,7 +642,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
if (!PrepareAndBind(cur, pSql, params, skip_first))
return 0;
-
+
szLastFunction = "SQLExecute";
Py_BEGIN_ALLOW_THREADS
ret = SQLExecute(cur->hstmt);
@@ -686,7 +675,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
Py_END_ALLOW_THREADS
}
}
-
+
if (cur->cnxn->hdbc == SQL_NULL_HANDLE)
{
// The connection was closed by another thread in the ALLOW_THREADS block above.
@@ -702,7 +691,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
// FreeParameterData calls more ODBC functions.
return RaiseErrorFromHandle("SQLExecDirectW", cur->cnxn->hdbc, cur->hstmt);
}
-
+
while (ret == SQL_NEED_DATA)
{
// We have bound a PyObject* using SQL_LEN_DATA_AT_EXEC, so ODBC is asking us for the data now. We gave the
@@ -716,7 +705,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
if (ret != SQL_NEED_DATA && ret != SQL_NO_DATA && !SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLParamData", cur->cnxn->hdbc, cur->hstmt);
-
+
TRACE("SQLParamData() --> %d\n", ret);
if (ret == SQL_NEED_DATA)
@@ -830,13 +819,13 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
if (!SQL_SUCCEEDED(ret))
{
// Note: The SQL Server driver sometimes returns HY007 here if multiple statements (separated by ;) were
- // submitted. This is not documented, but I've seen it with multiple successful inserts.
-
+ // submitted. This is not documented, but I've seen it with multiple successful inserts.
+
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
}
TRACE("SQLNumResultCols: %d\n", cCols);
-
+
if (cur->cnxn->hdbc == SQL_NULL_HANDLE)
{
// The connection was closed by another thread in the ALLOW_THREADS block above.
@@ -845,7 +834,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLRowCount", cur->cnxn->hdbc, cur->hstmt);
-
+
if (cCols != 0)
{
// A result set was created.
@@ -861,6 +850,7 @@ execute(Cursor* cur, PyObject* pSql, PyObject* params, bool skip_first)
return (PyObject*)cur;
}
+
inline bool IsSequence(PyObject* p)
{
// Used to determine if the first parameter of execute is a collection of SQL parameters or is a SQL parameter
@@ -870,6 +860,7 @@ inline bool IsSequence(PyObject* p)
return PyList_Check(p) || PyTuple_Check(p) || Row_Check(p);
}
+
static char execute_doc[] =
"C.execute(sql, [params]) --> Cursor\n"
"\n"
@@ -929,8 +920,8 @@ PyObject* Cursor_execute(PyObject* self, PyObject* args)
return execute(cursor, pSql, params, skip_first);
}
-static PyObject*
-Cursor_executemany(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_executemany(PyObject* self, PyObject* args)
{
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
if (!cursor)
@@ -981,12 +972,11 @@ Cursor_executemany(PyObject* self, PyObject* args)
}
-static PyObject*
-Cursor_fetch(Cursor* cur)
+static PyObject* Cursor_fetch(Cursor* cur)
{
// Internal function to fetch a single row and construct a Row object from it. Used by all of the fetching
// functions.
- //
+ //
// Returns a Row object if successful. If there are no more rows, zero is returned. If an error occurs, an
// exception is set and zero is returned. (To differentiate between the last two, use PyErr_Occurred.)
@@ -1034,12 +1024,11 @@ Cursor_fetch(Cursor* cur)
}
-static PyObject*
-Cursor_fetchlist(Cursor* cur, Py_ssize_t max)
+static PyObject* Cursor_fetchlist(Cursor* cur, Py_ssize_t max)
{
// max
// The maximum number of rows to fetch. If -1, fetch all rows.
- //
+ //
// Returns a list of Rows. If there are no rows, an empty list is returned.
PyObject* results;
@@ -1073,16 +1062,15 @@ Cursor_fetchlist(Cursor* cur, Py_ssize_t max)
return results;
}
-static PyObject*
-Cursor_iter(PyObject* self)
+
+static PyObject* Cursor_iter(PyObject* self)
{
Py_INCREF(self);
return self;
}
-static PyObject*
-Cursor_iternext(PyObject* self)
+static PyObject* Cursor_iternext(PyObject* self)
{
// Implements the iterator protocol for cursors. Fetches the next row. Returns zero without setting an exception
// when there are no rows.
@@ -1099,11 +1087,11 @@ Cursor_iternext(PyObject* self)
return result;
}
-static PyObject*
-Cursor_fetchone(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_fetchone(PyObject* self, PyObject* args)
{
UNUSED(args);
-
+
PyObject* row;
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_RESULTS | CURSOR_RAISE_ERROR);
if (!cursor)
@@ -1121,11 +1109,11 @@ Cursor_fetchone(PyObject* self, PyObject* args)
return row;
}
-static PyObject*
-Cursor_fetchall(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_fetchall(PyObject* self, PyObject* args)
{
UNUSED(args);
-
+
PyObject* result;
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_RESULTS | CURSOR_RAISE_ERROR);
if (!cursor)
@@ -1136,8 +1124,8 @@ Cursor_fetchall(PyObject* self, PyObject* args)
return result;
}
-static PyObject*
-Cursor_fetchmany(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_fetchmany(PyObject* self, PyObject* args)
{
long rows;
PyObject* result;
@@ -1155,6 +1143,7 @@ Cursor_fetchmany(PyObject* self, PyObject* args)
return result;
}
+
static char tables_doc[] =
"C.tables(table=None, catalog=None, schema=None, tableType=None) --> self\n"
"\n"
@@ -1174,8 +1163,7 @@ static char tables_doc[] =
char* Cursor_tables_kwnames[] = { "table", "catalog", "schema", "tableType", 0 };
-static PyObject*
-Cursor_tables(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_tables(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szCatalog = 0;
const char* szSchema = 0;
@@ -1186,14 +1174,14 @@ Cursor_tables(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
- ret = SQLTables(cur->hstmt, (SQLCHAR*)szCatalog, SQL_NTS, (SQLCHAR*)szSchema, SQL_NTS,
+ ret = SQLTables(cur->hstmt, (SQLCHAR*)szCatalog, SQL_NTS, (SQLCHAR*)szSchema, SQL_NTS,
(SQLCHAR*)szTableName, SQL_NTS, (SQLCHAR*)szTableType, SQL_NTS);
Py_END_ALLOW_THREADS
@@ -1206,7 +1194,7 @@ Cursor_tables(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1244,8 +1232,7 @@ static char columns_doc[] =
char* Cursor_column_kwnames[] = { "table", "catalog", "schema", "column", 0 };
-static PyObject*
-Cursor_columns(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_columns(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szCatalog = 0;
const char* szSchema = 0;
@@ -1256,10 +1243,10 @@ Cursor_columns(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1275,7 +1262,7 @@ Cursor_columns(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1315,8 +1302,7 @@ static char statistics_doc[] =
char* Cursor_statistics_kwnames[] = { "table", "catalog", "schema", "unique", "quick", 0 };
-static PyObject*
-Cursor_statistics(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_statistics(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szCatalog = 0;
const char* szSchema = 0;
@@ -1329,17 +1315,17 @@ Cursor_statistics(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLUSMALLINT nUnique = (SQLUSMALLINT)(PyObject_IsTrue(pUnique) ? SQL_INDEX_UNIQUE : SQL_INDEX_ALL);
SQLUSMALLINT nReserved = (SQLUSMALLINT)(PyObject_IsTrue(pQuick) ? SQL_QUICK : SQL_ENSURE);
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
- ret = SQLStatistics(cur->hstmt, (SQLCHAR*)szCatalog, SQL_NTS, (SQLCHAR*)szSchema, SQL_NTS, (SQLCHAR*)szTable, SQL_NTS,
+ ret = SQLStatistics(cur->hstmt, (SQLCHAR*)szCatalog, SQL_NTS, (SQLCHAR*)szSchema, SQL_NTS, (SQLCHAR*)szTable, SQL_NTS,
nUnique, nReserved);
Py_END_ALLOW_THREADS
@@ -1352,7 +1338,7 @@ Cursor_statistics(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1395,8 +1381,7 @@ static char rowVerColumns_doc[] =
char* Cursor_specialColumn_kwnames[] = { "table", "catalog", "schema", "nullable", 0 };
-static PyObject*
-_specialColumns(PyObject* self, PyObject* args, PyObject* kwargs, SQLUSMALLINT nIdType)
+static PyObject* _specialColumns(PyObject* self, PyObject* args, PyObject* kwargs, SQLUSMALLINT nIdType)
{
const char* szTable;
const char* szCatalog = 0;
@@ -1407,10 +1392,10 @@ _specialColumns(PyObject* self, PyObject* args, PyObject* kwargs, SQLUSMALLINT n
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
SQLUSMALLINT nNullable = (SQLUSMALLINT)(PyObject_IsTrue(pNullable) ? SQL_NULLABLE : SQL_NO_NULLS);
@@ -1429,7 +1414,7 @@ _specialColumns(PyObject* self, PyObject* args, PyObject* kwargs, SQLUSMALLINT n
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1441,14 +1426,14 @@ _specialColumns(PyObject* self, PyObject* args, PyObject* kwargs, SQLUSMALLINT n
return (PyObject*)cur;
}
-static PyObject*
-Cursor_rowIdColumns(PyObject* self, PyObject* args, PyObject* kwargs)
+
+static PyObject* Cursor_rowIdColumns(PyObject* self, PyObject* args, PyObject* kwargs)
{
return _specialColumns(self, args, kwargs, SQL_BEST_ROWID);
}
-static PyObject*
-Cursor_rowVerColumns(PyObject* self, PyObject* args, PyObject* kwargs)
+
+static PyObject* Cursor_rowVerColumns(PyObject* self, PyObject* args, PyObject* kwargs)
{
return _specialColumns(self, args, kwargs, SQL_ROWVER);
}
@@ -1468,8 +1453,7 @@ static char primaryKeys_doc[] =
char* Cursor_primaryKeys_kwnames[] = { "table", "catalog", "schema", 0 };
-static PyObject*
-Cursor_primaryKeys(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_primaryKeys(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szTable;
const char* szCatalog = 0;
@@ -1479,10 +1463,10 @@ Cursor_primaryKeys(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1498,7 +1482,7 @@ Cursor_primaryKeys(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1536,8 +1520,7 @@ static char foreignKeys_doc[] =
char* Cursor_foreignKeys_kwnames[] = { "table", "catalog", "schema", "foreignTable", "foreignCatalog", "foreignSchema", 0 };
-static PyObject*
-Cursor_foreignKeys(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_foreignKeys(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szTable = 0;
const char* szCatalog = 0;
@@ -1551,10 +1534,10 @@ Cursor_foreignKeys(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1571,7 +1554,7 @@ Cursor_foreignKeys(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1609,21 +1592,20 @@ static char getTypeInfo_doc[] =
"17) num_prec_radix\n"
"18) interval_precision";
-static PyObject*
-Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* kwargs)
{
UNUSED(kwargs);
-
+
SQLSMALLINT nDataType = SQL_ALL_TYPES;
if (!PyArg_ParseTuple(args, "|i", &nDataType))
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1639,7 +1621,7 @@ Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1651,16 +1633,16 @@ Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* kwargs)
return (PyObject*)cur;
}
-static PyObject*
-Cursor_nextset(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_nextset(PyObject* self, PyObject* args)
{
UNUSED(args);
Cursor* cur = Cursor_Validate(self, 0);
-
+
if (!cur)
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1680,7 +1662,7 @@ Cursor_nextset(PyObject* self, PyObject* args)
if (!SQL_SUCCEEDED(ret))
{
// Note: The SQL Server driver sometimes returns HY007 here if multiple statements (separated by ;) were
- // submitted. This is not documented, but I've seen it with multiple successful inserts.
+ // submitted. This is not documented, but I've seen it with multiple successful inserts.
free_results(cur, FREE_STATEMENT);
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
@@ -1737,8 +1719,7 @@ static char procedureColumns_doc[] =
char* Cursor_procedureColumns_kwnames[] = { "procedure", "catalog", "schema", 0 };
-static PyObject*
-Cursor_procedureColumns(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_procedureColumns(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szProcedure = 0;
const char* szCatalog = 0;
@@ -1748,10 +1729,10 @@ Cursor_procedureColumns(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1768,7 +1749,7 @@ Cursor_procedureColumns(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1797,8 +1778,7 @@ static char procedures_doc[] =
char* Cursor_procedures_kwnames[] = { "procedure", "catalog", "schema", 0 };
-static PyObject*
-Cursor_procedures(PyObject* self, PyObject* args, PyObject* kwargs)
+static PyObject* Cursor_procedures(PyObject* self, PyObject* args, PyObject* kwargs)
{
const char* szProcedure = 0;
const char* szCatalog = 0;
@@ -1808,10 +1788,10 @@ Cursor_procedures(PyObject* self, PyObject* args, PyObject* kwargs)
return 0;
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN);
-
+
if (!free_results(cur, FREE_STATEMENT))
return 0;
-
+
SQLRETURN ret = 0;
Py_BEGIN_ALLOW_THREADS
@@ -1827,7 +1807,7 @@ Cursor_procedures(PyObject* self, PyObject* args, PyObject* kwargs)
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
return RaiseErrorFromHandle("SQLNumResultCols", cur->cnxn->hdbc, cur->hstmt);
-
+
if (!PrepareResults(cur, cCols))
return 0;
@@ -1874,13 +1854,14 @@ static PyObject* Cursor_skip(PyObject* self, PyObject* args)
Py_RETURN_NONE;
}
-static PyObject*
-Cursor_ignored(PyObject* self, PyObject* args)
+
+static PyObject* Cursor_ignored(PyObject* self, PyObject* args)
{
UNUSED(self, args);
Py_RETURN_NONE;
}
+
static char rowcount_doc[] =
"This read-only attribute specifies the number of rows the last DML statement\n"
" (INSERT, UPDATE, DELETE) affected. This is set to -1 for SELECT statements.";
@@ -1942,22 +1923,22 @@ static PyObject* Cursor_getnoscan(PyObject* self, void *closure)
if (noscan == SQL_NOSCAN_OFF)
Py_RETURN_FALSE;
-
+
Py_RETURN_TRUE;
}
-static PyObject* Cursor_setnoscan(PyObject* self, PyObject* value, void *closure)
+static int Cursor_setnoscan(PyObject* self, PyObject* value, void *closure)
{
UNUSED(closure);
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
if (!cursor)
- return 0;
+ return -1;
if (value == 0)
{
PyErr_SetString(PyExc_TypeError, "Cannot delete the noscan attribute");
- return 0;
+ return -1;
}
uintptr_t noscan = PyObject_IsTrue(value) ? SQL_NOSCAN_ON : SQL_NOSCAN_OFF;
@@ -1967,15 +1948,16 @@ static PyObject* Cursor_setnoscan(PyObject* self, PyObject* value, void *closure
Py_END_ALLOW_THREADS
if (!SQL_SUCCEEDED(ret))
{
- return RaiseErrorFromHandle("SQLSetStmtAttr(SQL_ATTR_NOSCAN)", cursor->cnxn->hdbc, cursor->hstmt);
+ RaiseErrorFromHandle("SQLSetStmtAttr(SQL_ATTR_NOSCAN)", cursor->cnxn->hdbc, cursor->hstmt);
+ return -1;
}
-
+
return 0;
}
static PyGetSetDef Cursor_getsetters[] =
{
- {"noscan", (getter)Cursor_getnoscan, (setter)Cursor_setnoscan, "NOSCAN statement attr", 0},
+ {"noscan", Cursor_getnoscan, Cursor_setnoscan, "NOSCAN statement attr", 0},
{ 0 }
};
@@ -1987,7 +1969,7 @@ static char executemany_doc[] =
"\n" \
"Only the result of the final execution is returned. See `execute` for a\n" \
"description of parameter passing the return value.";
-
+
static char nextset_doc[] = "nextset() --> True | None\n" \
"\n" \
"Jumps to the next resultset if the last sql has multiple resultset." \
@@ -2065,7 +2047,7 @@ static char cursor_doc[] =
" cursor.execute(sql)\n" \
" for row in cursor:\n" \
" print row[0]";
-
+
PyTypeObject CursorType =
{
PyVarObject_HEAD_INIT(0, 0)
@@ -2097,8 +2079,8 @@ PyTypeObject CursorType =
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
- (getiterfunc)Cursor_iter, // tp_iter
- (iternextfunc)Cursor_iternext, // tp_iternext
+ Cursor_iter, // tp_iter
+ Cursor_iternext, // tp_iternext
Cursor_methods, // tp_methods
Cursor_members, // tp_members
Cursor_getsetters, // tp_getset
@@ -2166,7 +2148,7 @@ Cursor_New(Connection* cnxn)
Py_BEGIN_ALLOW_THREADS
ret = SQLSetStmtAttr(cur->hstmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)cnxn->timeout, 0);
Py_END_ALLOW_THREADS
-
+
if (!SQL_SUCCEEDED(ret))
{
RaiseErrorFromHandle("SQLSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT)", cnxn->hdbc, cur->hstmt);
@@ -2183,6 +2165,6 @@ Cursor_New(Connection* cnxn)
void Cursor_init()
{
- PyDateTime_IMPORT;
+ PyDateTime_IMPORT;
}
View
25 src/errors.cpp
@@ -27,8 +27,7 @@ static const struct SqlStateMapping sql_state_mapping[] =
};
-static PyObject*
-ExceptionFromSqlState(const char* sqlstate)
+static PyObject* ExceptionFromSqlState(const char* sqlstate)
{
// Returns the appropriate Python exception class given a SQLSTATE value.
@@ -42,8 +41,8 @@ ExceptionFromSqlState(const char* sqlstate)
return Error;
}
-PyObject*
-RaiseErrorV(const char* sqlstate, PyObject* exc_class, const char* format, ...)
+
+PyObject* RaiseErrorV(const char* sqlstate, PyObject* exc_class, const char* format, ...)
{
PyObject *pAttrs = 0, *pError = 0;
@@ -78,7 +77,7 @@ RaiseErrorV(const char* sqlstate, PyObject* exc_class, const char* format, ...)
if (pError)
RaiseErrorFromException(pError);
}
-
+
Py_DECREF(pMsg);
Py_XDECREF(pAttrs);
Py_XDECREF(pError);
@@ -86,12 +85,14 @@ RaiseErrorV(const char* sqlstate, PyObject* exc_class, const char* format, ...)
return 0;
}
+
#if PY_MAJOR_VERSION < 3
#define PyString_CompareWithASCIIString(lhs, rhs) _strcmpi(PyString_AS_STRING(lhs), rhs)
#else
#define PyString_CompareWithASCIIString PyUnicode_CompareWithASCIIString
#endif
+
bool HasSqlState(PyObject* ex, const char* szSqlState)
{
// Returns true if `ex` is an exception and has the given SQLSTATE. It is safe to pass 0 for ex.
@@ -140,7 +141,7 @@ static PyObject* GetError(const char* sqlstate, PyObject* exc_class, PyObject* p
Py_DECREF(pMsg);
return 0;
}
-
+
PyTuple_SetItem(pAttrs, 1, pMsg); // pAttrs now owns the pMsg reference; steals a reference, does not increment
pSqlState = PyString_FromString(sqlstate);
@@ -149,7 +150,7 @@ static PyObject* GetError(const char* sqlstate, PyObject* exc_class, PyObject* p
Py_DECREF(pAttrs);
return 0;
}
-
+
PyTuple_SetItem(pAttrs, 0, pSqlState); // pAttrs now owns the pSqlState reference
pError = PyEval_CallObject(exc_class, pAttrs); // pError will incref pAttrs
@@ -159,6 +160,7 @@ static PyObject* GetError(const char* sqlstate, PyObject* exc_class, PyObject* p
return pError;
}
+
static const char* DEFAULT_ERROR = "The driver did not supply an error!";
PyObject* RaiseErrorFromHandle(const char* szFunction, HDBC hdbc, HSTMT hstmt)
@@ -172,16 +174,17 @@ PyObject* RaiseErrorFromHandle(const char* szFunction, HDBC hdbc, HSTMT hstmt)
RaiseErrorFromException(pError);
Py_DECREF(pError);
}
-
+
return 0;
}
+
PyObject* GetErrorFromHandle(const char* szFunction, HDBC hdbc, HSTMT hstmt)
{
TRACE("In RaiseError(%s)!\n", szFunction);
// Creates and returns an exception from ODBC error information.
- //
+ //
// ODBC can generate a chain of errors which we concatenate into one error message. We use the SQLSTATE from the
// first message, which seems to be the most detailed, to determine the class of exception.
//
@@ -250,7 +253,7 @@ PyObject* GetErrorFromHandle(const char* szFunction, HDBC hdbc, HSTMT hstmt)
// the calling function name.
memcpy(sqlstate, sqlstateT, sizeof(sqlstate[0]) * _countof(sqlstate));
-
+
pMsg = PyString_FromFormat("[%s] %s (%ld) (%s)", sqlstateT, szMsg, (long)nNativeError, szFunction);
if (pMsg == 0)
return 0;
@@ -292,6 +295,7 @@ PyObject* GetErrorFromHandle(const char* szFunction, HDBC hdbc, HSTMT hstmt)
return GetError(sqlstate, 0, pMsg);
}
+
static bool GetSqlState(HSTMT hstmt, char* szSqlState)
{
SQLCHAR szMsg[300];
@@ -306,6 +310,7 @@ static bool GetSqlState(HSTMT hstmt, char* szSqlState)
return SQL_SUCCEEDED(ret);
}
+
bool HasSqlState(HSTMT hstmt, const char* szSqlState)
{
char szActual[6];
View
4 src/getdata.cpp
@@ -411,8 +411,7 @@ static PyObject* GetDataString(Cursor* cur, Py_ssize_t iCol)
}
-static PyObject*
-GetDataUser(Cursor* cur, Py_ssize_t iCol, int conv)
+static PyObject* GetDataUser(Cursor* cur, Py_ssize_t iCol, int conv)
{
// conv
// The index into the connection's user-defined conversions `conv_types`.
@@ -426,6 +425,7 @@ GetDataUser(Cursor* cur, Py_ssize_t iCol, int conv)
return result;
}
+
#if PY_VERSION_HEX < 0x02060000
static PyObject* GetDataBuffer(Cursor* cur, Py_ssize_t iCol)
{
View
46 src/params.cpp
@@ -206,7 +206,7 @@ static bool GetUnicodeInfo(Cursor* cur, Py_ssize_t index, PyObject* param, Param
info.ParameterValuePtr = pch;
}
}
-
+
info.ParameterType = SQL_WVARCHAR;
info.StrLen_or_Ind = (SQLINTEGER)(len * sizeof(SQLWCHAR));
}
@@ -309,7 +309,7 @@ static bool GetIntInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo
#else
#error Unexpected LONG_BIT value
#endif
-
+
info.ParameterValuePtr = &info.Data.l;
return true;
}
@@ -536,7 +536,7 @@ static bool GetParameterInfo(Cursor* cur, Py_ssize_t index, PyObject* param, Par
// Hold a reference to param until info is freed, because info will often be holding data borrowed from param.
info.pParam = param;
-
+
if (param == Py_None)
return GetNullInfo(cur, index, info);
@@ -582,7 +582,7 @@ static bool GetParameterInfo(Cursor* cur, Py_ssize_t index, PyObject* param, Par
if (PyBuffer_Check(param))
return GetBufferInfo(cur, index, param, info);
#endif
-
+
RaiseErrorV("HY105", ProgrammingError, "Invalid parameter type. param-index=%zd param-type=%s", index, Py_TYPE(param)->tp_name);
return false;
}
@@ -832,23 +832,23 @@ PyTypeObject NullParamType =
PyVarObject_HEAD_INIT(NULL, 0)
"pyodbc.NullParam", // tp_name
sizeof(NullParam), // tp_basicsize
- 0, // tp_itemsize
- 0, // destructor tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- 0, // tp_compare
- 0, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- 0, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- 0, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT, // tp_flags
+ 0, // tp_itemsize
+ 0, // destructor tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
};
PyObject* null_binary;
@@ -857,11 +857,11 @@ bool Params_init()
{
if (PyType_Ready(&NullParamType) < 0)
return false;
-
+
null_binary = (PyObject*)PyObject_New(NullParam, &NullParamType);
if (null_binary == 0)
return false;
-
+
PyDateTime_IMPORT;
return true;
View
4 src/pyodbc.h
@@ -3,7 +3,7 @@
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
@@ -112,7 +112,7 @@ inline void _strlwr(char* name)
#ifdef PYODBC_TRACE
void DebugTrace(const char* szFmt, ...);
-#else
+#else
inline void DebugTrace(const char* szFmt, ...) { UNUSED(szFmt); }
#endif
#define TRACE DebugTrace
View
6 src/pyodbcmodule.cpp
@@ -366,8 +366,7 @@ static PyObject* mod_connect(PyObject* self, PyObject* args, PyObject* kwargs)
}
-static PyObject*
-mod_datasources(PyObject* self)
+static PyObject* mod_datasources(PyObject* self)
{
UNUSED(self);
@@ -430,18 +429,21 @@ static PyObject* mod_timefromticks(PyObject* self, PyObject* args)
return PyTime_FromTime(fields->tm_hour, fields->tm_min, fields->tm_sec, 0);
}
+
static PyObject* mod_datefromticks(PyObject* self, PyObject* args)
{
UNUSED(self);
return PyDate_FromTimestamp(args);
}
+
static PyObject* mod_timestampfromticks(PyObject* self, PyObject* args)
{
UNUSED(self);
return PyDateTime_FromTimestamp(args);
}
+
static char connect_doc[] =
"connect(str, autocommit=False, ansi=False, timeout=0, **kwargs) --> Connection\n"
"\n"
View
116 src/row.cpp
@@ -47,16 +47,19 @@ void FreeRowValues(Py_ssize_t cValues, PyObject** apValues)
}
}
-static void Row_dealloc(Row* self)
+static void Row_dealloc(PyObject* o)
{
// Note: Now that __newobj__ is available, our variables could be zero...
+ Row* self = (Row*)o;
+
Py_XDECREF(self->description);
Py_XDECREF(self->map_name_to_index);
FreeRowValues(self->cValues, self->apValues);
PyObject_Del(self);
}
+
Row* Row_New(PyObject* description, PyObject* map_name_to_index, Py_ssize_t cValues, PyObject** apValues)
{
// Called by other modules to create rows. Takes ownership of apValues.
@@ -86,6 +89,7 @@ Row* Row_New(PyObject* description, PyObject* map_name_to_index, Py_ssize_t cVal
return row;
}
+
static PyObject* Row_getattro(PyObject* o, PyObject* name)
{
// Called to handle 'row.colname'.
@@ -104,17 +108,20 @@ static PyObject* Row_getattro(PyObject* o, PyObject* name)
return PyObject_GenericGetAttr(o, name);
}
+
static Py_ssize_t Row_length(PyObject* self)
{
return ((Row*)self)->cValues;
}
-static int Row_contains(Row *self, PyObject *el)
+static int Row_contains(PyObject* o, PyObject* el)
{
// Implementation of contains. The documentation is not good (non-existent?), so I copied the following from the
// PySequence_Contains documentation: Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
+ Row* self = (Row*)o;
+
int cmp = 0;
for (Py_ssize_t i = 0, c = self->cValues ; cmp == 0 && i < c; ++i)
@@ -124,10 +131,12 @@ static int Row_contains(Row *self, PyObject *el)
}
-static PyObject* Row_item(Row* self, Py_ssize_t i)
+static PyObject* Row_item(PyObject* o, Py_ssize_t i)
{
// Apparently, negative indexes are handled by magic ;) -- they never make it here.
+ Row* self = (Row*)o;
+
if (i < 0 || i >= self->cValues)
{
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
@@ -139,10 +148,12 @@ static PyObject* Row_item(Row* self, Py_ssize_t i)
}
-static int Row_ass_item(Row* self, Py_ssize_t i, PyObject* v)
+static int Row_ass_item(PyObject* o, Py_ssize_t i, PyObject* v)
{
// Implements row[i] = value.
+ Row* self = (Row*)o;
+
if (i < 0 || i >= self->cValues)
{
PyErr_SetString(PyExc_IndexError, "Row assignment index out of range");
@@ -164,50 +175,12 @@ static int Row_setattro(PyObject* o, PyObject *name, PyObject* v)
PyObject* index = PyDict_GetItem(self->map_name_to_index, name);
if (index)
- return Row_ass_item(self, PyNumber_AsSsize_t(index, 0), v);
+ return Row_ass_item(o, PyNumber_AsSsize_t(index, 0), v);
return PyObject_GenericSetAttr(o, name, v);
}
-static PyObject* Row_slice(PyObject* o, Py_ssize_t iFirst, Py_ssize_t iMax)
-{
- // Note: Negative indexes will have already been converted to positive ones before this is called. It is possible
- // for the iMax value to be too high if row[:] or row[1:] is used.
- //
- // I don't think iFirst can ever be below zero, but the tuple slice function checks for it, so we will too.
-
- Row* self = (Row*)o;
-
- if (iFirst < 0)
- iFirst = 0;
- if (iMax > self->cValues)
- iMax = self->cValues;
- if (iMax < iFirst)
- iMax = iFirst;
-
- if (iFirst == 0 && iMax == self->cValues)
- {
- Py_INCREF(o);
- return o;
- }
-
- Py_ssize_t len = iMax - iFirst;
- PyObject* result = PyTuple_New(len);
- if (!result)
- return 0;
-
- for (Py_ssize_t i = 0; i < len; i++)
- {
- PyObject* item = self->apValues[iFirst + i];
- PyTuple_SET_ITEM(result, i, item);
- Py_INCREF(item);
- }
-
- return result;
-}
-
-
static PyObject* Row_repr(PyObject* o)
{
Row* self = (Row*)o;
@@ -237,7 +210,7 @@ static PyObject* Row_repr(PyObject* o)
// Need a trailing comma: (value,)
length += 2;
}
-
+
PyObject* result = Text_New(length);
if (!result)
return 0;
@@ -332,11 +305,11 @@ static PyObject* Row_subscript(PyObject* o, PyObject* key)
if (i < 0 || i >= row->cValues)
return PyErr_Format(PyExc_IndexError, "row index out of range index=%d len=%d", (int)i, (int)row->cValues);
-
+
Py_INCREF(row->apValues[i]);
return row->apValues[i];
}
-
+
if (PySlice_Check(key))
{
Py_ssize_t start, stop, step, slicelength;
@@ -372,17 +345,16 @@ static PyObject* Row_subscript(PyObject* o, PyObject* key)
}
-
static PySequenceMethods row_as_sequence =
{
- (lenfunc)Row_length, // sq_length
- 0, // sq_concat
- 0, // sq_repeat
- (ssizeargfunc)Row_item, // sq_item
- Row_slice, // sq_slice
- (ssizeobjargproc)Row_ass_item, // sq_ass_item
- 0, // sq_ass_slice
- (objobjproc)Row_contains, // sq_contains
+ Row_length, // sq_length
+ 0, // sq_concat
+ 0, // sq_repeat
+ Row_item, // sq_item
+ 0, // was_sq_slice
+ Row_ass_item, // sq_ass_item
+ 0, // sq_ass_slice
+ Row_contains, // sq_contains
};
@@ -433,7 +405,7 @@ PyTypeObject RowType =
"pyodbc.Row", // tp_name
sizeof(Row), // tp_basicsize
0, // tp_itemsize
- (destructor)Row_dealloc, // destructor tp_dealloc
+ Row_dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
@@ -458,20 +430,20 @@ PyTypeObject RowType =
0, // tp_iternext
0, // tp_methods
Row_members, // tp_members
- 0, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
- 0, // tp_alloc
- 0, // tp_new
- 0, // tp_free
- 0, // tp_is_gc
- 0, // tp_bases
- 0, // tp_mro
- 0, // tp_cache
- 0, // tp_subclasses
- 0, // tp_weaklist
+ // 0, // tp_getset
+ // 0, // tp_base
+ // 0, // tp_dict
+ // 0, // tp_descr_get
+ // 0, // tp_descr_set
+ // 0, // tp_dictoffset
+ // 0, // tp_init
+ // 0, // tp_alloc
+ // 0, // tp_new
+ // 0, // tp_free
+ // 0, // tp_is_gc
+ // 0, // tp_bases
+ // 0, // tp_mro
+ // 0, // tp_cache
+ // 0, // tp_subclasses
+ // 0, // tp_weaklist
};
View
BIN  tests2/sqlite.db
Binary file not shown
View
71 tests3/sqlitetests.py
@@ -44,7 +44,7 @@ def _generate_test_string(length):
if length <= len(_TESTSTR):
return _TESTSTR[:length]
- c = (length + len(_TESTSTR)-1) / len(_TESTSTR)
+ c = (length + len(_TESTSTR)-1) // len(_TESTSTR)
v = _TESTSTR * c
return v[:length]
@@ -53,9 +53,9 @@ class SqliteTestCase(unittest.TestCase):
SMALL_FENCEPOST_SIZES = [ 0, 1, 255, 256, 510, 511, 512, 1023, 1024, 2047, 2048, 4000 ]
LARGE_FENCEPOST_SIZES = [ 4095, 4096, 4097, 10 * 1024, 20 * 1024 ]
- ANSI_FENCEPOSTS = [ _generate_test_string(size) for size in SMALL_FENCEPOST_SIZES ]
- UNICODE_FENCEPOSTS = [ unicode(s) for s in ANSI_FENCEPOSTS ]
- IMAGE_FENCEPOSTS = ANSI_FENCEPOSTS + [ _generate_test_string(size) for size in LARGE_FENCEPOST_SIZES ]
+ STR_FENCEPOSTS = [ _generate_test_string(size) for size in SMALL_FENCEPOST_SIZES ]
+ BYTE_FENCEPOSTS = [ bytes(s, 'ascii') for s in STR_FENCEPOSTS ]
+ IMAGE_FENCEPOSTS = BYTE_FENCEPOSTS + [ bytes(_generate_test_string(size), 'ascii') for size in LARGE_FENCEPOST_SIZES ]
def __init__(self, method_name, connection_string):
unittest.TestCase.__init__(self, method_name)
@@ -121,22 +121,12 @@ def test_getinfo_bool(self):
def test_getinfo_int(self):
value = self.cnxn.getinfo(pyodbc.SQL_DEFAULT_TXN_ISOLATION)
- self.assert_(isinstance(value, (int, long)))
+ self.assert_(isinstance(value, int))
def test_getinfo_smallint(self):
value = self.cnxn.getinfo(pyodbc.SQL_CONCAT_NULL_BEHAVIOR)
self.assert_(isinstance(value, int))
- def test_fixed_unicode(self):
- value = u"t\xebsting"
- self.cursor.execute("create table t1(s nchar(7))")
- self.cursor.execute("insert into t1 values(?)", u"t\xebsting")
- v = self.cursor.execute("select * from t1").fetchone()[0]
- self.assertEqual(type(v), unicode)
- self.assertEqual(len(v), len(value)) # If we alloc'd wrong, the test below might work because of an embedded NULL
- self.assertEqual(v, value)
-
-
def _test_strtype(self, sqltype, value, colsize=None):
"""
The implementation for string, Unicode, and binary tests.
@@ -204,11 +194,11 @@ def _maketest(value):
def t(self):
self._test_strtype('text', value, len(value))
return t
- for value in UNICODE_FENCEPOSTS:
+ for value in STR_FENCEPOSTS:
locals()['test_text_%s' % len(value)] = _maketest(value)
def test_text_upperlatin(self):
- self._test_strtype('varchar', u'á')
+ self._test_strtype('varchar', 'á')
#
# blob
@@ -224,9 +214,9 @@ def test_large_null_blob(self):
# Generate a test for each fencepost size: test_unicode_0, etc.
def _maketest(value):
def t(self):
- self._test_strtype('blob', buffer(value), len(value))
+ self._test_strtype('blob', bytearray(value), len(value))
return t
- for value in ANSI_FENCEPOSTS:
+ for value in BYTE_FENCEPOSTS:
locals()['test_blob_%s' % len(value)] = _maketest(value)
def test_subquery_params(self):
@@ -262,13 +252,6 @@ def test_close_cnxn(self):
self.sql = "select * from t1"
self.assertRaises(pyodbc.ProgrammingError, self._exec)
- def test_empty_unicode(self):
- self.cursor.execute("create table t1(s nvarchar(20))")
- self.cursor.execute("insert into t1 values(?)", u"")
-
- def test_unicode_query(self):
- self.cursor.execute(u"select 1")
-
def test_negative_row_index(self):
self.cursor.execute("create table t1(s varchar(20))")
self.cursor.execute("insert into t1 values(?)", "1")
@@ -556,19 +539,6 @@ def test_autocommit(self):
othercnxn.autocommit = False
self.assertEqual(othercnxn.autocommit, False)
- def test_unicode_results(self):
- "Ensure unicode_results forces Unicode"
- othercnxn = pyodbc.connect(self.connection_string, unicode_results=True)
- othercursor = othercnxn.cursor()
-
- # ANSI data in an ANSI column ...
- othercursor.execute("create table t1(s varchar(20))")
- othercursor.execute("insert into t1 values(?)", 'test')
-
- # ... should be returned as Unicode
- value = othercursor.execute("select s from t1").fetchone()[0]
- self.assertEqual(value, u'test')
-
def test_skip(self):
# Insert 1, 2, and 3. Fetch 1, skip 2, fetch 3.
@@ -641,28 +611,10 @@ def test_description(self):
# text
t = self.cursor.description[1]
self.assertEqual(t[0], 's')
- self.assertEqual(t[1], unicode)
+ self.assertEqual(t[1], str)
self.assertEqual(t[5], 0) # scale
self.assertEqual(t[6], True) # nullable
- def test_none_param(self):
- "Ensure None can be used for params other than the first"
- # Some driver/db versions would fail if NULL was not the first parameter because SQLDescribeParam (only used
- # with NULL) could not be used after the first call to SQLBindParameter. This means None always worked for the
- # first column, but did not work for later columns.
- #
- # If SQLDescribeParam doesn't work, pyodbc would use VARCHAR which almost always worked. However,
- # binary/varbinary won't allow an implicit conversion.
-
- value = u'\x12abc'
- self.cursor.execute("create table t1(n int, b blob)")
- self.cursor.execute("insert into t1 values (1, ?)", value)
- row = self.cursor.execute("select * from t1").fetchone()
- self.assertEqual(row.n, 1)
- self.assertEqual(type(row.b), buffer)
- self.assertEqual(row.b, value)
-
-
def test_row_equal(self):
self.cursor.execute("create table t1(n int, s varchar(20))")
self.cursor.execute("insert into t1 values (1, 'test')")
@@ -701,7 +653,7 @@ def test_untyped_none(self):
def test_large_update_nodata(self):
self.cursor.execute('create table t1(a blob)')
- hundredkb = buffer('x'*100*1024)
+ hundredkb = bytearray('x'*100*1024)
self.cursor.execute('update t1 set a=? where 1=0', (hundredkb,))
def test_no_fetch(self):
@@ -725,7 +677,6 @@ def main():
if not args:
connection_string = load_setup_connection_string('sqlitetests')
- print 'connection_string:', connection_string
if not connection_string:
parser.print_help()
Please sign in to comment.
Something went wrong with that request. Please try again.