From b8112769625389a357947f0a48d9eb116fb46028 Mon Sep 17 00:00:00 2001 From: Charles Leifer Date: Thu, 21 May 2020 10:08:21 -0500 Subject: [PATCH] Apply upstream fix for bpo-39652 --- src/cursor.c | 29 ++++++++++++++++++++++------- test/regression.py | 2 +- test/ttypes.py | 4 ++-- test/userfunctions.py | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/cursor.c b/src/cursor.c index 1941786..4e801ae 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -193,22 +193,30 @@ pysqlite_build_row_cast_map(pysqlite_Cursor* self) } static PyObject * -_pysqlite_build_column_name(const char* colname) +_pysqlite_build_column_name(pysqlite_Cursor *self, const char *colname) { const char* pos; + Py_ssize_t len; if (!colname) { Py_RETURN_NONE; } - for (pos = colname;; pos++) { - if (*pos == 0 || *pos == '[') { - if ((*pos == '[') && (pos > colname) && (*(pos-1) == ' ')) { - pos--; + if (self->connection->detect_types & PARSE_COLNAMES) { + for (pos = colname; *pos; pos++) { + if (*pos == '[') { + if ((pos != colname) && (*(pos-1) == ' ')) { + pos--; + } + break; } - return PyUnicode_FromStringAndSize(colname, pos - colname); } + len = pos - colname; } + else { + len = strlen(colname); + } + return PyUnicode_FromStringAndSize(colname, len); } /* @@ -370,6 +378,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) PyObject* result; int numcols; PyObject* descriptor; + PyObject* column_name; PyObject* second_argument = NULL; sqlite_int64 lastrowid; @@ -536,7 +545,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) if (!descriptor) { goto error; } - PyTuple_SetItem(descriptor, 0, _pysqlite_build_column_name(sqlite3_column_name(self->statement->st, i))); + column_name = _pysqlite_build_column_name(self, + sqlite3_column_name(self->statement->st, i)); + if (!column_name) { + Py_DECREF(descriptor); + goto error; + } + PyTuple_SetItem(descriptor, 0, column_name); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None); diff --git a/test/regression.py b/test/regression.py index 83d2027..ca67059 100644 --- a/test/regression.py +++ b/test/regression.py @@ -68,7 +68,7 @@ class RegressionTests(unittest.TestCase): def CheckColumnNameWithSpaces(self): cur = self.con.cursor() cur.execute('select 1 as "foo bar [datetime]"') - self.assertEqual(cur.description[0][0], "foo bar") + self.assertEqual(cur.description[0][0], "foo bar [datetime]") cur.execute('select 1 as "foo baz"') self.assertEqual(cur.description[0][0], "foo baz") diff --git a/test/ttypes.py b/test/ttypes.py index 4cbeed1..78706b7 100644 --- a/test/ttypes.py +++ b/test/ttypes.py @@ -275,13 +275,13 @@ class ColNamesTests(unittest.TestCase): def CheckColName(self): self.cur.execute("insert into test(x) values (?)", ("xxx",)) - self.cur.execute('select x as "x [bar]" from test') + self.cur.execute('select x as "x y [bar]" from test') val = self.cur.fetchone()[0] self.assertEqual(val, "") # Check if the stripping of colnames works. Everything after the first # whitespace should be stripped. - self.assertEqual(self.cur.description[0][0], "x") + self.assertEqual(self.cur.description[0][0], "x y") def CheckCaseInConverterName(self): self.cur.execute("select 'other' as \"x [b1b1]\"") diff --git a/test/userfunctions.py b/test/userfunctions.py index d496de9..adcf2bc 100644 --- a/test/userfunctions.py +++ b/test/userfunctions.py @@ -286,7 +286,7 @@ class FunctionTests(unittest.TestCase): def CheckFuncDeterministic(self): mock = unittest.mock.Mock(return_value=None) self.con.create_function("deterministic", 0, mock, True) - self.con.execute("select deterministic() = deterministic()") + self.con.execute("select 1 where deterministic() AND deterministic()") self.assertEqual(mock.call_count, 1) @unittest.skipIf(sqlite.sqlite_version_info >= (3, 8, 3), "SQLite < 3.8.3 needed")