From 131a90f2e217af8fdcc292935f45803c6fea6b63 Mon Sep 17 00:00:00 2001 From: Andy Maloney <60523020+ndmlny-qs@users.noreply.github.com> Date: Tue, 5 Sep 2023 17:46:45 -0500 Subject: [PATCH] Add numpy --- setup.py | 15 +++++++++++++-- src/cursor.cpp | 2 +- src/cursor.h | 9 +++++++++ src/npcontainer.cpp | 33 ++++++++++++++++++++++++++++++--- src/npcontainer.h | 2 +- 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index b6b7fd84..148431b9 100755 --- a/setup.py +++ b/setup.py @@ -8,6 +8,8 @@ from setuptools import setup from setuptools.extension import Extension +HAS_NUMPY = False + def _getversion(): # CAREFUL: We need the version in this file so we can set it in a C macro to set @@ -34,7 +36,16 @@ def _getversion(): def main(): settings = get_compiler_settings() - files = [relpath(join('src', f)) for f in os.listdir('src') if f.endswith('.cpp')] + try: + import numpy + HAS_NUMPY = True + except ImportWarning: + raise ImportWarning("NumPy was not found, compiling pyodbc without NumPy support.") + + files = [ + relpath(join('src', f)) for f in os.listdir('src') if f.endswith('.cpp') + and (f != 'npcontainer.cpp' or HAS_NUMPY) + ] if exists('MANIFEST'): os.remove('MANIFEST') @@ -82,7 +93,7 @@ def get_compiler_settings(): 'include_dirs': [], 'define_macros': [('PYODBC_VERSION', VERSION)] } - if numpy: + if HAS_NUMPY: settings['include_dirs'].append(numpy.get_include()) settings['define_macros'].append(('WITH_NUMPY', '1')) diff --git a/src/cursor.cpp b/src/cursor.cpp index fdd52f57..6c147190 100644 --- a/src/cursor.cpp +++ b/src/cursor.cpp @@ -49,7 +49,7 @@ inline bool Cursor_Check(PyObject* o) return o != 0 && Py_TYPE(o) == &CursorType; } -static Cursor* Cursor_Validate(PyObject* obj, DWORD flags) +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*. diff --git a/src/cursor.h b/src/cursor.h index b9fa43c2..aa40f01a 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -13,6 +13,14 @@ #ifndef CURSOR_H #define CURSOR_H +enum +{ + CURSOR_REQUIRE_CNXN = 0x00000001, + CURSOR_REQUIRE_OPEN = 0x00000003, // includes _CNXN + CURSOR_REQUIRE_RESULTS = 0x00000007, // includes _OPEN + CURSOR_RAISE_ERROR = 0x00000010, +}; + struct Connection; struct ColumnInfo @@ -160,5 +168,6 @@ void Cursor_init(); Cursor* Cursor_New(Connection* cnxn); PyObject* Cursor_execute(PyObject* self, PyObject* args); +Cursor* Cursor_Validate(PyObject* obj, DWORD flags); #endif diff --git a/src/npcontainer.cpp b/src/npcontainer.cpp index 7f3d9b4b..16faa962 100644 --- a/src/npcontainer.cpp +++ b/src/npcontainer.cpp @@ -11,6 +11,8 @@ #include #include "pyodbc.h" +#include "wrapper.h" +#include "textenc.h" #include "cursor.h" #include "pyodbcmodule.h" #include "connection.h" @@ -27,6 +29,28 @@ Py_ssize_t iopro_text_limit = -1; // ----------------------------------------------------------------------------- +bool pyodbc_tracing_enabled = false; + +void pyodbc_trace_func(const char* file, int line, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + if (0 != file) { + const char* rel_file = strstr(file, "dbadapter"); + printf("%s:%d\n", rel_file, line); + } + vprintf(fmt, args); +} + +#define TRACE_NOLOC(...) \ + if (pyodbc_tracing_enabled) \ + pyodbc_trace_func(NULL, 0, __VA_ARGS__) + +#define GUARDED_ALLOC(...) malloc(__VA_ARGS__) +#define GUARDED_DEALLOC(...) free(__VA_ARGS__) + +#define CHECK_ALLOC_GUARDS(...) {} namespace { inline size_t @@ -1320,7 +1344,9 @@ static int perform_array_query(query_desc& result, Cursor* cur, npy_intp nrows, bool lower, bool want_nulls) { SQLRETURN rc; - bool use_unicode = cur->cnxn->unicode_results; + /* XXX is true a good default? + was: bool use_unicode = cur->cnxn->unicode_results; */ + bool use_unicode = true; size_t outsize, chunk_size; if (nrows < 0) { @@ -1366,7 +1392,8 @@ perform_array_query(query_desc& result, Cursor* cur, npy_intp nrows, bool lower, // multiple statements (separated by ;) were submitted. This // is not documented, but I've seen it with multiple // successful inserts. - return 0 == RaiseErrorFromHandle("ODBC failed to describe the resulting columns", + return 0 == RaiseErrorFromHandle(cur->cnxn, + "ODBC failed to describe the resulting columns", cur->cnxn->hdbc, cur->hstmt); } @@ -1403,7 +1430,7 @@ perform_array_query(query_desc& result, Cursor* cur, npy_intp nrows, bool lower, rc = result.bind_cols(); if (!SQL_SUCCEEDED(rc)) { - return 0 == RaiseErrorFromHandle("ODBC failed when binding columns", + return 0 == RaiseErrorFromHandle(cur->cnxn, "ODBC failed when binding columns", cur->cnxn->hdbc, cur->hstmt); } diff --git a/src/npcontainer.h b/src/npcontainer.h index 9456dc3e..262bce4e 100644 --- a/src/npcontainer.h +++ b/src/npcontainer.h @@ -12,7 +12,7 @@ PyObject* Cursor_fetchsarray(PyObject* self, PyObject* args, PyObject *kwargs); PyObject* Cursor_fetchdictarray(PyObject* self, PyObject* args, PyObject *kwargs); -char *fetchdictarray_doc; +extern char fetchdictarray_doc[]; extern Py_ssize_t iopro_text_limit;