Skip to content

Commit 5d8c271

Browse files
committed
Added mogrify support to Cursor (PyMySQL#476)
1 parent 24aaa72 commit 5d8c271

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

MySQLdb/cursors.py

+37-3
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,27 @@ def execute(self, query, args=None):
182182
"""
183183
while self.nextset():
184184
pass
185+
186+
mogrified_query = self._mogrify(query, args)
187+
188+
assert isinstance(mogrified_query, (bytes, bytearray))
189+
res = self._query(mogrified_query)
190+
return res
191+
192+
def _mogrify(self, query, args=None):
193+
"""Generates the query to be sent to the server with argument
194+
interpolation and proper encoding. This is for internal use, see
195+
mogrify() for the external API that returns a string.
196+
197+
query -- string, query to execute on server
198+
args -- optional sequence or mapping, parameters to use with query.
199+
200+
Note: If args is a sequence, then %s must be used as the
201+
parameter placeholder in the query. If a mapping is used,
202+
%(key)s must be used as the placeholder.
203+
204+
Returns bytes or bytearray representing the query
205+
"""
185206
db = self._get_db()
186207

187208
if isinstance(query, str):
@@ -202,9 +223,22 @@ def execute(self, query, args=None):
202223
except TypeError as m:
203224
raise ProgrammingError(str(m))
204225

205-
assert isinstance(query, (bytes, bytearray))
206-
res = self._query(query)
207-
return res
226+
return query
227+
228+
def mogrify(self, query, args=None):
229+
"""Get the query exactly as it would be sent to the database running the
230+
execute() method.
231+
232+
query -- string, query to execute on server
233+
args -- optional sequence or mapping, parameters to use with query.
234+
235+
Note: If args is a sequence, then %s must be used as the
236+
parameter placeholder in the query. If a mapping is used,
237+
%(key)s must be used as the placeholder.
238+
239+
Returns string representing query that would be executed by the server
240+
"""
241+
return self._mogrify(query, args).decode()
208242

209243
def executemany(self, query, args):
210244
# type: (str, list) -> int

tests/test_cursor.py

+36
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,39 @@ def test_dictcursor():
150150
names2 = sorted(rows[1])
151151
for a, b in zip(names1, names2):
152152
assert a is b
153+
154+
155+
def test_mogrify_without_args():
156+
conn = connect()
157+
cursor = conn.cursor()
158+
159+
query = "SELECT VERSION()"
160+
mogrified_query = cursor.mogrify(query)
161+
cursor.execute(query)
162+
163+
assert mogrified_query == query
164+
assert mogrified_query == cursor._executed.decode()
165+
166+
167+
def test_mogrify_with_tuple_args():
168+
conn = connect()
169+
cursor = conn.cursor()
170+
171+
query_with_args = "SELECT %s, %s", (1, 2)
172+
mogrified_query = cursor.mogrify(*query_with_args)
173+
cursor.execute(*query_with_args)
174+
175+
assert mogrified_query == "SELECT 1, 2"
176+
assert mogrified_query == cursor._executed.decode()
177+
178+
179+
def test_mogrify_with_dict_args():
180+
conn = connect()
181+
cursor = conn.cursor()
182+
183+
query_with_args = "SELECT %(a)s, %(b)s", {"a": 1, "b": 2}
184+
mogrified_query = cursor.mogrify(*query_with_args)
185+
cursor.execute(*query_with_args)
186+
187+
assert mogrified_query == "SELECT 1, 2"
188+
assert mogrified_query == cursor._executed.decode()

0 commit comments

Comments
 (0)