#33815: Oracle sql tracking incorrectly substitutes in parameters when 10 or
more
parameters are used.
-----------------------------------------+------------------------
Reporter: Brian | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: dev
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
Since Django 3.0, the variable substitution performed in the Oracle
backend's `last_executed_query` function can incorrectly track the sql
statements issued to the backend. Here's the method copied from
https://github.com/django/django/blob/main/django/db/backends/oracle/operations.py#L304:
{{{
def last_executed_query(self, cursor, sql, params):
# https://cx-
oracle.readthedocs.io/en/latest/api_manual/cursor.html#Cursor.statement
# The DB API definition does not define this attribute.
statement = cursor.statement
# Unlike Psycopg's `query` and MySQLdb`'s `_executed`, cx_Oracle's
# `statement` doesn't contain the query parameters. Substitute
# parameters manually.
if isinstance(params, (tuple, list)):
for i, param in enumerate(params):
statement = statement.replace(
":arg%d" % i, force_str(param, errors="replace")
)
elif isinstance(params, dict):
for key, param in params.items():
statement = statement.replace(
":%s" % key, force_str(param, errors="replace")
)
return statement
}}}
The problem is that `statement.replace` will end up replacing all matches
in the statement, even those that are not a full match for the argument
identifier. This can result in values that are a mashup of the subbed in
value and the argument identifiers. For example, if you have values A-L
that need to be substituted into a query, you'd have 12 arguments that
would need to be substituted in, and the following scenario would occur:
Statement Pre-substitution:
{{{
SELECT
"EMPLOYEE"."ID",
"EMPLOYEE"."USERNAME",
"EMPLOYEE"."NAME",
"EMPLOYEE"."EMAIL"
FROM "EMPLOYEE"
WHERE "EMPLOYEE"."ID" IN (:arg0, :arg1, :arg2, :arg3, :arg4, :arg5,
:arg6, :arg7, :arg8, :arg9 :arg10, :arg11)
}}}
Statement Post-substitution:
{{{
SELECT
"EMPLOYEE"."ID",
"EMPLOYEE"."USERNAME",
"EMPLOYEE"."NAME",
"EMPLOYEE"."EMAIL"
FROM "EMPLOYEE"
WHERE "EMPLOYEE"."ID" IN (A, B, C, D, E, F, G, H, I , J, B0, B1)
}}}
Expected Output:
{{{
SELECT
"EMPLOYEE"."ID",
"EMPLOYEE"."USERNAME",
"EMPLOYEE"."NAME",
"EMPLOYEE"."EMAIL"
FROM "EMPLOYEE"
WHERE "EMPLOYEE"."ID" IN (A, B, C, D, E, F, G, H, I , J, K, L)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33815>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070181b07e4bf7-411574cc-ac17-49c7-8c23-01b7bcafe73b-000000%40eu-central-1.amazonses.com.