Skip to content

Commit a5d0061

Browse files
committed
fix(#99): fix update value containing "where" cause exception.
1 parent 86512a9 commit a5d0061

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### unreleased
2+
3+
- fix: #99 fix update value containing "where" cause exception.
4+
15
### 1.3.0
26

37
- fix #92 last_executed_query() when params is a mappinglast_executed_query() when params is a mapping.

clickhouse_backend/backend/introspection.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
TableInfo = namedtuple("TableInfo", BaseTableInfo._fields + ("comment",))
1313

1414
constraint_pattern = re.compile(
15-
r"CONSTRAINT (`)?((?(1)(?:[^\\`]|\\.)+|\S+))(?(1)`|) (CHECK .+?),?\n"
15+
r"CONSTRAINT (`)?((?(1)(?:\\.|[^`])+|\S+))(?(1)`|) (CHECK .+?),?\n"
1616
)
1717
index_pattern = re.compile(
18-
r"INDEX (`)?((?(1)(?:[^\\`]|\\.)+|\S+))(?(1)`|) (.+? TYPE ([a-zA-Z_][0-9a-zA-Z_]*)\(.+?\) GRANULARITY \d+)"
18+
r"INDEX (`)?((?(1)(?:\\.|[^`])+|\S+))(?(1)`|) (.+? TYPE ([a-zA-Z_][0-9a-zA-Z_]*)\(.+?\) GRANULARITY \d+)"
1919
)
2020

2121

clickhouse_backend/driver/connection.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
from .escape import escape_params
99
from .pool import ClickhousePool
1010

11-
update_pattern = re.compile(
12-
r"^\s*alter\s+table\s+(\S+)\s+.*?update.+?where\s+(.+?)(?:settings\s+.+)?$",
13-
flags=re.IGNORECASE,
14-
)
11+
name_regex = r'"(?:[^"]|\\.)+"'
12+
value_regex = r"(')?(?(1)(?:[^']|\\.)+|\S+)(?(1)'|)"
13+
name_value_regex = f"{name_regex} = {value_regex}"
14+
update_pattern = re.compile(f"^ALTER TABLE ({name_regex}) UPDATE ")
1515

1616

1717
def send_query(self, query, query_id=None, params=None):
@@ -95,11 +95,20 @@ def execute(self, operation, parameters=None):
9595
query = self._client.substitute_params(
9696
operation, parameters, self._client.connection.context
9797
)
98-
table, where = update_pattern.match(query).groups()
99-
super().execute(f"select count(*) from {table} where {where}")
100-
(rowcount,) = self.fetchone()
101-
self._reset_state()
102-
self._rowcount = rowcount
98+
m = update_pattern.match(query)
99+
table = m.group(1)
100+
query_upper = query.upper()
101+
i = query_upper.rfind(" WHERE ")
102+
if i > 0:
103+
j = query_upper.rfind(" SETTINGS ", i + 7)
104+
if j > 0:
105+
where = query[i + 7 : j]
106+
else:
107+
where = query[i + 7 :]
108+
super().execute(f"select count(*) from {table} where {where}")
109+
(rowcount,) = self.fetchone()
110+
self._reset_state()
111+
self._rowcount = rowcount
103112
super().execute(operation, parameters)
104113

105114

tests/queries/tests.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,10 @@ def test_update(self):
2020
self.a1.save()
2121
with self.assertRaises(models.Author.MultipleObjectsReturned):
2222
self.a1.refresh_from_db()
23+
24+
# regression test for https://github.com/jayvynl/django-clickhouse-backend/issues/99
25+
def test_update_special_string_val(self):
26+
self.a1.name = "where **"
27+
self.a1.save()
28+
self.a1.refresh_from_db()
29+
self.assertEqual(self.a1.name, "where **")

0 commit comments

Comments
 (0)