Skip to content

Commit

Permalink
Fix the conversion of list or tuple args to a SQL.
Browse files Browse the repository at this point in the history
When there is one element on the list, the generated SQL was
(1,) (python notation of a single element tuple, which is not
valid in SQL.
  • Loading branch information
gbandet committed Nov 4, 2013
1 parent c8b2744 commit 87d1145
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 3 deletions.
7 changes: 5 additions & 2 deletions MySQLdb/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,16 @@ def char_array(s):
def array2Str(o, d):
return Thing2Literal(o.tostring(), d)

def quote_tuple(t, d):
return "(%s)" % (','.join(escape_sequence(t, d)))

conversions = {
IntType: Thing2Str,
LongType: Long2Int,
FloatType: Float2Str,
NoneType: None2NULL,
TupleType: escape_sequence,
ListType: escape_sequence,
TupleType: quote_tuple,
ListType: quote_tuple,
DictType: escape_dict,
InstanceType: Instance2Str,
ArrayType: array2Str,
Expand Down
5 changes: 4 additions & 1 deletion MySQLdb/cursors.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,10 @@ def execute(self, query, args=None):
if isinstance(query, unicode):
query = query.encode(db.unicode_literal.charset)
if args is not None:
query = query % db.literal(args)
if isinstance(args, dict):
query = query % {key: db.literal(item) for key, item in args.iteritems()}
else:
query = query % tuple([db.literal(item) for item in args])

This comment has been minimized.

Copy link
@jonmauney

jonmauney Feb 20, 2014

The convention I used for string replacement in 1.2.4 no longer works in 1.2.5, I believe because of this commit.

Ex:

sql = "SELECT * FROM table_name WHERE column = %s"
cursor.execute(sql, 'passed_variable')

Is the new convention to pass in a single string as a dict?

This comment has been minimized.

Copy link
@rohitagarwal003

rohitagarwal003 Mar 3, 2014

I was facing the same issue.
You can fix this by explicitly using a sequence: cursor.execute(sql, ('passed_variable',))
The commit message seems to suggest that this won't work before 1.2.5. But it was working in both 1.2.3 and 1.2.5

This comment has been minimized.

Copy link
@skeleton9

skeleton9 May 22, 2014

Met the same problem. This is breaking many of our old code...

This comment has been minimized.

Copy link
@zew13

zew13 Jun 26, 2014

Met the same problem. This is breaking many of our old code...
!!!

try:
r = None
r = self._query(query)
Expand Down

1 comment on commit 87d1145

@gbandet
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was made to fix a problem with queries with "WHERE column IN %s" and the argument being a one element list, because it was then transformed in "WHERE column IN ('foo',)" which is not valid in SQL.

As the execute docstring says:

Execute a query.
query -- string, query to execute on server
args -- optional sequence or mapping, parameters to use with query.

I believe the fact that cursor.execute(sql, 'passed_variable') worked before was more a side effect of the previous implementation of execute than a wanted behaviour.

Also see the answer of @farcepest in #74

Please sign in to comment.