Close #399.
prematurely (:ticket:`#382`).
- Fix regression introduced in 3.1 with different named tuples mangling rules
for non-ascii attribute names (:ticket:`#386`).
+- Fix handling of queries with escaped percent signs (``%%``) in `ClientCursor`
+ (:ticket:`#399`).
Current release
"""
Convert Python query and params into a template to perform client-side binding
"""
- parts = _split_query(query, encoding)
+ parts = _split_query(query, encoding, collapse_double_percent=False)
order: Optional[List[str]] = None
chunks: List[bytes] = []
)
-def _split_query(query: bytes, encoding: str = "ascii") -> List[QueryPart]:
+def _split_query(
+ query: bytes, encoding: str = "ascii", collapse_double_percent: bool = True
+) -> List[QueryPart]:
parts: List[Tuple[bytes, Optional[Match[bytes]]]] = []
cur = 0
ph = m.group(0)
if ph == b"%%":
- # unescape '%%' to '%' and merge the parts
+ # unescape '%%' to '%' if necessary, then merge the parts
+ if collapse_double_percent:
+ ph = b"%"
pre1, m1 = parts[i + 1]
- parts[i + 1] = (pre + b"%" + pre1, m1)
+ parts[i + 1] = (pre + ph + pre1, m1)
del parts[i]
continue
("select 'hello'", (), "select 'hello'"),
("select %s, %s", ([1, dt.date(2020, 1, 1)],), "select 1, '2020-01-01'::date"),
("select %(foo)s, %(foo)s", ({"foo": "x"},), "select 'x', 'x'"),
+ ("select %%", (), "select %%"),
+ ("select %%, %s", (["a"],), "select %, 'a'"),
+ ("select %%, %(foo)s", ({"foo": "x"},), "select %, 'x'"),
+ ("select %%s, %(foo)s", ({"foo": "x"},), "select %s, 'x'"),
],
)
def test_mogrify(conn, query, params, want):
("select 'hello'", (), "select 'hello'"),
("select %s, %s", ([1, dt.date(2020, 1, 1)],), "select 1, '2020-01-01'::date"),
("select %(foo)s, %(foo)s", ({"foo": "x"},), "select 'x', 'x'"),
+ ("select %%", (), "select %%"),
+ ("select %%, %s", (["a"],), "select %, 'a'"),
+ ("select %%, %(foo)s", ({"foo": "x"},), "select %, 'x'"),
+ ("select %%s, %(foo)s", ({"foo": "x"},), "select %s, 'x'"),
],
)
async def test_mogrify(aconn, query, params, want):