8000 Merge pull request #427 from peopledoc/fix-psycopg-percent-query-409 · Develop-Python/procrastinate@74c50b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 74c50b6

Browse files
author
Joachim Jablon
authored
Merge pull request procrastinate-org#427 from peopledoc/fix-psycopg-percent-query-409
Psycopg2: % in queries need to be escaped
2 parents e83e356 + 0f44aca commit 74c50b6

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

procrastinate/psycopg2_connector.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import contextlib
22
import functools
33
import logging
4+
import re
45
from typing import Any, Callable, Dict, Optional
56

67
import psycopg2
@@ -66,6 +67,9 @@ def wrapped(*args, **kwargs):
6667
return wrapped
6768

6869

70+
PERCENT_PATTERN = re.compile(r"%(?![\(s])")
71+
72+
6973
class Psycopg2Connector(connector.BaseConnector):
7074
@wrap_exceptions
7175
def __init__(
@@ -201,20 +205,26 @@ def _connection(self) -> psycopg2.extensions.connection:
201205
def execute_query(self, query: str, **arguments: Any) -> None:
202206
with self._connection() as connection:
203207
with connection.cursor() as cursor:
204-
cursor.execute(query, self._wrap_json(arguments))
208+
cursor.execute(
209+
PERCENT_PATTERN.sub("%%", query), self._wrap_json(arguments)
210+
)
205211

206212
@wrap_exceptions
207213
@wrap_query_exceptions
208214
def execute_query_one(self, query: str, **arguments: Any) -> Dict[str, Any]:
209215
with self._connection() as connection:
210216
with connection.cursor() as cursor:
211-
cursor.execute(query, self._wrap_json(arguments))
217+
cursor.execute(
218+
PERCENT_PATTERN.sub("%%", query), self._wrap_json(arguments)
219+
)
212220
return cursor.fetchone()
213221

214222
@wrap_exceptions
215223
@wrap_query_exceptions
216224
def execute_query_all(self, query: str, **arguments: Any) -> Dict[str, Any]:
217225
with self._connection() as connection:
218226
with connection.cursor() as cursor:
219-
cursor.execute(query, self._wrap_json(arguments))
227+
cursor.execute(
228+
PERCENT_PATTERN.sub("%%", query), self._wrap_json(arguments)
229+
)
220230
return cursor.fetchall()

tests/integration/test_psycopg2_connector.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,24 @@ def test_execute_query(psycopg2_connector):
9191
assert result == [{"obj_description": "foo"}]
9292

9393

94+
def test_execute_query_percent(psycopg2_connector):
95+
psycopg2_connector.execute_query("SELECT '%'")
96+
result = psycopg2_connector.execute_query_one("SELECT '%'")
97+
assert result == {"?column?": "%"}
98+
99+
result = psycopg2_connector.execute_query_all("SELECT '%'")
100+
assert result == [{"?column?": "%"}]
101+
102+
103+
def test_execute_query_arg(psycopg2_connector):
104+
psycopg2_connector.execute_query("SELECT %(arg)s", arg=1)
105+
result = psycopg2_connector.execute_query_one("SELECT %(arg)s", arg=1)
106+
assert result == {"?column?": 1}
107+
108+
result = psycopg2_connector.execute_query_all("SELECT %(arg)s", arg=1)
109+
assert result == [{"?column?": 1}]
110+
111+
94112
def test_close(psycopg2_connector):
95113
pool = psycopg2_connector._pool
96114
psycopg2_connector.close()

0 commit comments

Comments
 (0)
0