Skip to content

Commit ce44500

Browse files
committed
fix(django-spanner): backslash-escape string literals in quote_value
1 parent d4f8a57 commit ce44500

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

packages/django-google-spanner/django_spanner/schema.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,10 @@ def add_index(self, model, index):
450450
def quote_value(self, value):
451451
# A more complete implementation isn't currently required.
452452
if isinstance(value, str):
453-
return "'%s'" % value.replace("'", "''")
453+
# GoogleSQL string literals use backslash escaping; '' quote
454+
# doubling is not recognized, so escape the backslash first and
455+
# then the quote (matching the db_default/generated inlining above).
456+
return "'%s'" % value.replace("\\", "\\\\").replace("'", "\\'")
454457
if isinstance(value, bool):
455458
return "TRUE" if value else "FALSE"
456459
return str(value)

packages/django-google-spanner/tests/unit/django_spanner/test_schema.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ def test_quote_value(self):
4040
schema_editor = DatabaseSchemaEditor(self.connection)
4141
self.assertEqual(schema_editor.quote_value(value=1.1), "1.1")
4242

43+
def test_quote_value_escapes_string(self):
44+
"""
45+
String literals must be backslash-escaped for GoogleSQL. A quote or
46+
backslash in the value must not be able to terminate the literal.
47+
"""
48+
schema_editor = DatabaseSchemaEditor(self.connection)
49+
self.assertEqual(schema_editor.quote_value(value="o'brien"), "'o\\'brien'")
50+
self.assertEqual(schema_editor.quote_value(value="a\\b"), "'a\\\\b'")
51+
self.assertEqual(
52+
schema_editor.quote_value(value="\\'; DROP TABLE t; --"),
53+
"'\\\\\\'; DROP TABLE t; --'",
54+
)
55+
4356
def test_skip_default(self):
4457
"""
4558
Tries skipping default as Cloud spanner doesn't support it.

0 commit comments

Comments
 (0)