Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Doc/library/sqlite3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1950,7 +1950,7 @@ question marks (qmark style) or named placeholders (named style).
For the qmark style, *parameters* must be a
:term:`sequence` whose length must match the number of placeholders,
or a :exc:`ProgrammingError` is raised.
For the named style, *parameters* should be
For the named style, *parameters* must be
an instance of a :class:`dict` (or a subclass),
which must contain keys for all named parameters;
any extra items are ignored.
Expand Down Expand Up @@ -1980,6 +1980,12 @@ Here's an example of both styles:

[('C', 1972)]

.. deprecated-removed:: 3.12 3.14

If named placeholders are used and *parameters* is a sequence,
:exc:`DeprecationWarning` is raised.
Starting with Python 3.14, :exc:`ProgrammingError` will be raised.

.. note::

:pep:`249` numeric placeholders are *not* supported.
Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,13 @@ Deprecated
and tailor them to your needs.
(Contributed by Erlend E. Aasland in :gh:`90016`.)

* In :meth:`~sqlite3.Cursor.execute`, :exc:`DeprecationWarning` is now raised
when :ref:`named placeholders <sqlite3-placeholders>` are used together with
parameters supplied as a :term:`sequence`.
Starting from Python 3.14, using named placeholders with parameters supplied
as a sequence will raise a :exc:`~sqlite3.ProgrammingError`.
(Contributed by Erlend E. Aasland in :gh:`101698`.)

* The 3-arg signatures (type, value, traceback) of :meth:`~coroutine.throw`,
:meth:`~generator.throw` and :meth:`~agen.athrow` are deprecated and
may be removed in a future version of Python. Use the single-arg versions
Expand Down
14 changes: 14 additions & 0 deletions Lib/test/test_sqlite3/test_dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,20 @@ def __getitem__(slf, x):
with self.assertRaises(ZeroDivisionError):
self.cu.execute("select name from test where name=?", L())

def test_execute_named_param_and_sequence(self):
dataset = (
("select :a", (1,)),
("select :a, ?, ?", (1, 2, 3)),
("select ?, :b, ?", (1, 2, 3)),
("select ?, ?, :c", (1, 2, 3)),
)
msg = "Binding.*is a named parameter"
for query, params in dataset:
with self.subTest(query=query, params=params):
with self.assertWarnsRegex(DeprecationWarning, msg) as cm:
self.cu.execute(query, params)
self.assertEqual(cm.filename, __file__)

def test_execute_too_many_params(self):
category = sqlite.SQLITE_LIMIT_VARIABLE_NUMBER
msg = "too many SQL variables"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
In :meth:`sqlite3.Cursor.execute`, :exc:`DeprecationWarning` is now raised
when :ref:`named placeholders <sqlite3-placeholders>` are used together with
parameters supplied as a :term:`sequence`.
Starting from Python 3.14, using named placeholders with parameters supplied
as a sequence will raise a :exc:`~sqlite3.ProgrammingError`.
Patch by Erlend E. Aasland.
11 changes: 11 additions & 0 deletions Modules/_sqlite/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,17 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
return;
}
for (i = 0; i < num_params; i++) {
const char *name = sqlite3_bind_parameter_name(self->st, i+1);
if (name != NULL) {
PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"Binding %d ('%s') is a named parameter, "
"but you supplied a sequence which requires "
"nameless (qmark) placeholders. "
"Starting with Python 3.14 an "
"sqlite3.ProgrammingError will be raised.",
i+1, name);
}

if (PyTuple_CheckExact(parameters)) {
PyObject *item = PyTuple_GET_ITEM(parameters, i);
current_param = Py_NewRef(item);
Expand Down