Skip to content

Commit 6b2b7e4

Browse files
fix: use single quotes for SQL literals (PostgreSQL compatibility)
- condition.py: Use single quotes for string literals in WHERE clauses (double quotes are column identifiers in PostgreSQL) - declare.py: Use single quotes for DEFAULT values - dependencies.py: Escape % in LIKE patterns for psycopg2 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8a8423b commit 6b2b7e4

File tree

3 files changed

+8
-5
lines changed

3 files changed

+8
-5
lines changed

src/datajoint/condition.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,12 @@ def prep_value(k, v):
330330
list,
331331
),
332332
):
333-
return f'{k}="{v}"'
333+
# Use single quotes for string literals (works for both MySQL and PostgreSQL)
334+
return f"{k}='{v}'"
334335
if isinstance(v, str):
335-
v = v.replace("%", "%%").replace("\\", "\\\\")
336-
return f'{k}="{v}"'
336+
# Escape single quotes by doubling them, and escape % for driver
337+
v = v.replace("'", "''").replace("%", "%%").replace("\\", "\\\\")
338+
return f"{k}='{v}'"
337339
return f"{k}={v}"
338340

339341
def combine_conditions(negate, conditions):

src/datajoint/declare.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,8 @@ def compile_attribute(
850850
else:
851851
if match["default"]:
852852
quote = match["default"].split("(")[0].upper() not in CONSTANT_LITERALS and match["default"][0] not in "\"'"
853-
match["default"] = "NOT NULL DEFAULT " + ('"%s"' if quote else "%s") % match["default"]
853+
# Use single quotes for default values (works for both MySQL and PostgreSQL)
854+
match["default"] = "NOT NULL DEFAULT " + ("'%s'" if quote else "%s") % match["default"]
854855
else:
855856
match["default"] = "NOT NULL"
856857

src/datajoint/dependencies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def load(self, force: bool = True) -> None:
169169
# PostgreSQL
170170
tab_expr = "'\"' || table_schema || '\".\"' || table_name || '\"'"
171171
ref_tab_expr = "'\"' || referenced_table_schema || '\".\"' || referenced_table_name || '\"'"
172-
like_pattern = "'~%'" # PostgreSQL doesn't need escaping
172+
like_pattern = "'~%%'" # psycopg2 also uses %s placeholders, so escape %
173173

174174
# load primary key info
175175
keys = self._conn.query(

0 commit comments

Comments
 (0)