Skip to content

Commit 50d84eb

Browse files
committed
Fix Copilot review: escape strings, update README
- Escape backslashes and quotes in DATE_FORMAT format strings - Escape backslashes and quotes in FILTER expression values - Update README: OR with date functions raises ValueError
1 parent 1621b15 commit 50d84eb

4 files changed

Lines changed: 15 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ SELECT name, DATE_FORMAT(created_at, '%Y-%m-%d') AS date FROM events
234234

235235
- `NOT YEAR(field) = 2024` is not supported (raises `ValueError`)
236236
- `DATE_FORMAT()` is only supported in SELECT, not in WHERE (raises `ValueError`)
237-
- Date functions with `OR` require careful handling
237+
- Date functions combined with `OR` are not supported (raises `ValueError`)
238238

239239
### GEO Field Support
240240

sql_redis/translator.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,11 @@ def _build_aggregate(
390390
if redis_func:
391391
if date_func.function == "DATE_FORMAT" and date_func.format_string:
392392
# DATE_FORMAT(field, format) -> timefmt(@field, format)
393-
expression = (
394-
f'{redis_func}(@{date_func.field}, "{date_func.format_string}")'
393+
# Escape backslashes and quotes in format string
394+
escaped_fmt = date_func.format_string.replace("\\", "\\\\").replace(
395+
'"', '\\"'
395396
)
397+
expression = f'{redis_func}(@{date_func.field}, "{escaped_fmt}")'
396398
else:
397399
# Simple date extraction: YEAR(field) -> year(@field)
398400
expression = f"{redis_func}(@{date_func.field})"
@@ -640,5 +642,7 @@ def _normalize_filter_value(self, value: object) -> str:
640642
"""
641643
if isinstance(value, (int, float)):
642644
return str(value)
643-
# Quote string values for FILTER
644-
return f'"{value}"'
645+
# Quote string values for FILTER, escaping backslashes and double quotes
646+
str_value = str(value)
647+
escaped_value = str_value.replace("\\", "\\\\").replace('"', '\\"')
648+
return f'"{escaped_value}"'

tests/test_redis_queries.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@ def test_between_and_greater_than(
278278
row_dict = dict(zip(row[::2], row[1::2]))
279279
if "price" in row_dict:
280280
price = float(row_dict["price"])
281-
assert (
282-
100 <= price <= 500
283-
), f"Price {price} should be between 100 and 500"
281+
assert 100 <= price <= 500, (
282+
f"Price {price} should be between 100 and 500"
283+
)
284284

285285

286286
class TestTagFieldMultiValueSearch:

tests/test_sql_queries.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@ def test_in_clause_with_or(self, executor: Executor, products_data: str):
248248
WHERE tags IN ('sale', 'featured') OR category = 'electronics'
249249
"""
250250
)
251-
assert (
252-
len(result.rows) >= 1
253-
), "Should return products matching tag OR conditions"
251+
assert len(result.rows) >= 1, (
252+
"Should return products matching tag OR conditions"
253+
)
254254

255255
def test_tag_in_clause_only(self, executor: Executor, products_data: str):
256256
"""IN clause on TAG field without OR."""

0 commit comments

Comments
 (0)