Skip to content

Commit 5e7752a

Browse files
committed
Ensure existing mat view has data populated when definition isn't changed
If MATERIALIZED_VIEWS_CHECK_SQL_CHANGED is enabled and view definition has not changed, and view does not have with_data = False, and somehow the view does not have data populated, perform a refresh to make sure the data is there.
1 parent ac2222b commit 5e7752a

File tree

4 files changed

+41
-1
lines changed

4 files changed

+41
-1
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,9 @@ check the indexes on the table and delete any extra indexes and create any missi
330330
is done through the index name, so if you use custom names for your indexes, it might happen that it won't get updated
331331
on change of the content but not the name.
332332

333+
With data is also respected: if the view definition did not change, but data is not populated and the view class says data should be populated,
334+
a refresh will happen to ensure the view is populated.
335+
333336
#### Refreshing dependencies / dependants
334337

335338
The `refresh` method on `MaterializedView` only refreshes the given view, not dependencies or dependants.

django_pgviews/management/operations/create_materialized.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,18 @@ def create_materialized_view(
170170

171171
if definitions[0] == definitions[1]:
172172
_ensure_indexes(connection, cursor, view_cls, schema_name_log)
173+
174+
if view_cls.with_data:
175+
definitions_where, definitions_params = _make_where(schemaname=vschema, matviewname=[vname])
176+
cursor.execute(
177+
f"SELECT ispopulated FROM pg_catalog.pg_matviews WHERE {definitions_where}",
178+
definitions_params,
179+
)
180+
has_data = cursor.fetchone()[0]
181+
182+
if not has_data:
183+
view_cls.refresh(concurrently=False)
184+
173185
return "EXISTS"
174186

175187
if view_exists:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "django-pgviews-redux"
3-
version = "1.0.1"
3+
version = "1.1.0"
44
description = "Create and manage Postgres SQL Views in Django"
55
authors = ["Mikuláš Poul <mikulas.poul@xelix.com>"]
66
readme = "README.md"

tests/test_project/viewtest/test_views.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,31 @@ def test_refresh_pgviews(self):
324324

325325
@pytest.mark.django_db
326326
class TestMaterializedViewsCheckSQLSettings:
327+
def test_migrate_materialized_views_check_sql_set_to_true_no_data(self, settings: SettingsWrapper) -> None:
328+
settings.MATERIALIZED_VIEWS_CHECK_SQL_CHANGED = True
329+
330+
assert models.TestModel.objects.count() == 0
331+
assert models.MaterializedRelatedView.objects.count() == 0
332+
333+
models.TestModel.objects.create(name="Test")
334+
call_command("migrate")
335+
assert models.MaterializedRelatedView.objects.count() == 0
336+
337+
# create it with no data
338+
with connection.cursor() as cursor:
339+
cursor.execute("DROP MATERIALIZED VIEW viewtest_materializedrelatedview CASCADE;")
340+
cursor.execute(
341+
"""
342+
CREATE MATERIALIZED VIEW viewtest_materializedrelatedview as
343+
SELECT id AS model_id, id FROM viewtest_testmodel
344+
WITH NO DATA
345+
"""
346+
)
347+
348+
# view didn't change but it's not populated, but as it's configured to have data it got refreshed
349+
call_command("migrate")
350+
assert models.MaterializedRelatedView.objects.count() == 1
351+
327352
def test_migrate_materialized_views_check_sql_set_to_true(self, settings: SettingsWrapper) -> None:
328353
settings.MATERIALIZED_VIEWS_CHECK_SQL_CHANGED = True
329354

0 commit comments

Comments
 (0)