From 8c57d73d7f7bfe36354cd8fdd3d7f9f4b9e669f3 Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Thu, 6 Oct 2022 11:52:53 -0700 Subject: [PATCH 1/2] Escape single quotes with 2 backslashes --- src/databricks/sql/utils.py | 4 ++-- tests/e2e/driver_tests.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/databricks/sql/utils.py b/src/databricks/sql/utils.py index 2961a1f5..fc033564 100644 --- a/src/databricks/sql/utils.py +++ b/src/databricks/sql/utils.py @@ -144,9 +144,9 @@ def escape_string(self, item): if isinstance(item, bytes): item = item.decode("utf-8") # This is good enough when backslashes are literal, newlines are just followed, and the way - # to escape a single quote is to put two single quotes. + # to escape a single quote is to put precede it with 2 backslashes. # (i.e. only special character is single quote) - return "'{}'".format(item.replace("'", "''")) + return "'{}'".format(item.replace("'", "\\'")) def escape_sequence(self, item): l = map(str, map(self.escape_item, item)) diff --git a/tests/e2e/driver_tests.py b/tests/e2e/driver_tests.py index 9e400770..43973724 100644 --- a/tests/e2e/driver_tests.py +++ b/tests/e2e/driver_tests.py @@ -288,6 +288,20 @@ def test_get_columns(self): for table in table_names: cursor.execute('DROP TABLE IF EXISTS {}'.format(table)) + def test_escape_single_quotes(self): + with self.cursor({}) as cursor: + table_name = 'table_{uuid}'.format(uuid=str(uuid4()).replace('-', '_')) + # Test escape syntax directly + cursor.execute("CREATE TABLE IF NOT EXISTS {} AS (SELECT 'you\\'re' AS col_1)".format(table_name)) + cursor.execute("SELECT * FROM {} WHERE col_1 LIKE 'you\\'re'".format(table_name)) + rows = cursor.fetchall() + assert rows[0]["col_1"] == "you're" + + # Test escape syntax in parameter + cursor.execute("SELECT * FROM {} WHERE {}.col_1 LIKE %(var)s".format(table_name, table_name), parameters={"var": "you're"}) + rows = cursor.fetchall() + assert rows[0]["col_1"] == "you're" + def test_get_schemas(self): with self.cursor({}) as cursor: database_name = 'db_{uuid}'.format(uuid=str(uuid4()).replace('-', '_')) From c03a5e72f5754f5cfea046662c9b40e8157bc26f Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Thu, 6 Oct 2022 11:58:40 -0700 Subject: [PATCH 2/2] Fix comment --- src/databricks/sql/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/databricks/sql/utils.py b/src/databricks/sql/utils.py index fc033564..87eae8c5 100644 --- a/src/databricks/sql/utils.py +++ b/src/databricks/sql/utils.py @@ -144,7 +144,7 @@ def escape_string(self, item): if isinstance(item, bytes): item = item.decode("utf-8") # This is good enough when backslashes are literal, newlines are just followed, and the way - # to escape a single quote is to put precede it with 2 backslashes. + # to escape a single quote is to precede it with 2 backslashes. # (i.e. only special character is single quote) return "'{}'".format(item.replace("'", "\\'"))