summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_sqlite3/test_dbapi.py14
-rw-r--r--Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst2
-rw-r--r--Modules/_sqlite/cursor.c2
3 files changed, 17 insertions, 1 deletions
diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py
index 4182de2..6d8744c 100644
--- a/Lib/test/test_sqlite3/test_dbapi.py
+++ b/Lib/test/test_sqlite3/test_dbapi.py
@@ -28,6 +28,7 @@ import sys
import threading
import unittest
import urllib.parse
+import warnings
from test.support import (
SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess,
@@ -887,6 +888,19 @@ class CursorTests(unittest.TestCase):
self.cu.execute(query, params)
self.assertEqual(cm.filename, __file__)
+ def test_execute_indexed_nameless_params(self):
+ # See gh-117995: "'?1' is considered a named placeholder"
+ for query, params, expected in (
+ ("select ?1, ?2", (1, 2), (1, 2)),
+ ("select ?2, ?1", (1, 2), (2, 1)),
+ ):
+ with self.subTest(query=query, params=params):
+ with warnings.catch_warnings():
+ warnings.simplefilter("error", DeprecationWarning)
+ cu = self.cu.execute(query, params)
+ actual, = cu.fetchall()
+ self.assertEqual(actual, expected)
+
def test_execute_too_many_params(self):
category = sqlite.SQLITE_LIMIT_VARIABLE_NUMBER
msg = "too many SQL variables"
diff --git a/Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst b/Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst
new file mode 100644
index 0000000..a289939
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst
@@ -0,0 +1,2 @@
+Don't raise :exc:`DeprecationWarning` when a :term:`sequence` of parameters
+is used to bind indexed, nameless placeholders. See also :gh:`100668`.
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index f95df61..950596e 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -669,7 +669,7 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
}
for (i = 0; i < num_params; i++) {
const char *name = sqlite3_bind_parameter_name(self->st, i+1);
- if (name != NULL) {
+ if (name != NULL && name[0] != '?') {
int ret = PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"Binding %d ('%s') is a named parameter, but you "
"supplied a sequence which requires nameless (qmark) "