Skip to content

Commit a89eebf

Browse files
committed
feat: add CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT django setting
1 parent 4b066d4 commit a89eebf

File tree

7 files changed

+54
-2
lines changed

7 files changed

+54
-2
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### 1.1.6
2+
3+
- add `CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT` django setting.
4+
15
### 1.1.5
26
- refactor: refactor uniq aggregate function.
37
- feat: add some ClickHouse tuple and hash functions.

clickhouse_backend/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from clickhouse_backend.utils.version import get_version
22

3-
VERSION = (1, 1, 5, "final", 0)
3+
VERSION = (1, 1, 6, "final", 0)
44

55
__version__ = get_version(VERSION)

clickhouse_backend/driver/connection.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from clickhouse_driver.dbapi import connection as dbapi_connection
66
from clickhouse_driver.dbapi import cursor, errors
77
from clickhouse_pool.pool import ChPoolError
8+
from django.conf import settings
89

910
from .escape import escape_params
1011
from .pool import ClickhousePool
@@ -93,7 +94,9 @@ def __del__(self):
9394

9495
def execute(self, operation, parameters=None):
9596
"""fix https://github.com/jayvynl/django-clickhouse-backend/issues/9"""
96-
if update_pattern.match(operation):
97+
if getattr(
98+
settings, "CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT", True
99+
) and update_pattern.match(operation):
97100
query = self._client.substitute_params(
98101
operation, parameters, self._client.connection.context
99102
)

docs/Configurations.md

+17
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,20 @@ If data insertions happen on multiple datacenter, server, process or thread, you
7373
Because work_id and datacenter_id are 5 bits, they should be an integer between 0 and 31. CLICKHOUSE_WORKER_ID default to 0, CLICKHOUSE_DATACENTER_ID will be generated randomly if not provided.
7474

7575
`clickhouse.idworker.snowflake.SnowflakeIDWorker` is not thread safe. You could inherit `clickhouse.idworker.base.BaseIDWorker` and implement one, then set `CLICKHOUSE_ID_WORKER` in `settings.py` to doted import path of your IDWorker instance.
76+
77+
### Other
78+
79+
#### CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT
80+
81+
*New in 1.1.6*
82+
83+
Whether returning rowcount when executing `update` query, default is `True`.
84+
85+
Django rely on [rowcount](https://peps.python.org/pep-0249/#rowcount) of [Python DBAPI 2.0](https://peps.python.org/pep-0249/) to get number of rows deleted or updated.
86+
However, clickhouse_driver always have rowcount equals -1 when updating and deleting.
87+
88+
Updating of Django builtin model instances will [work abnormally](https://github.com/jayvynl/django-clickhouse-backend/issues/9) when this feature is missing.
89+
To fix this issue, ClickHouse backend use a modified version of clickhouse_driver which execute count aggregation and set rowcount before updating.
90+
91+
However, this will cause another problem, count aggregation will be extremely slow sometimes, because it scans all affected rows.
92+
Set `CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT` to `False` when this feature is not needed.

tests/queries/__init__.py

Whitespace-only changes.

tests/queries/models.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.db import models
2+
3+
4+
class Author(models.Model):
5+
name = models.CharField(max_length=10)
6+
num = models.IntegerField()

tests/queries/tests.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from django.test import TestCase
2+
3+
from . import models
4+
5+
6+
class QueriesTests(TestCase):
7+
@classmethod
8+
def setUpTestData(cls):
9+
cls.a1 = models.Author.objects.create(name="a1", num=1001)
10+
11+
def test_update(self):
12+
with self.settings(CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT=True):
13+
self.assertEqual(models.Author.objects.update(name="a11"), 1)
14+
with self.assertNumQueries(1):
15+
self.a1.save()
16+
self.a1.refresh_from_db()
17+
with self.settings(CLICKHOUSE_ENABLE_UPDATE_ROWCOUNT=False):
18+
self.assertEqual(models.Author.objects.update(name="a11"), -1)
19+
with self.assertNumQueries(2):
20+
self.a1.save()
21+
with self.assertRaises(models.Author.MultipleObjectsReturned):
22+
self.a1.refresh_from_db()

0 commit comments

Comments
 (0)