mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-26 11:31:08 +00:00
Define author_search_vector_trigger
via Author.Meta.triggers
Previously, triggers lived only in a particular migration file. With this change, code for the triggers resides in the model, and their lifecycle is managed through normal Django migrations.
This commit is contained in:
parent
44ef928c3c
commit
416a6caf2d
5 changed files with 103 additions and 0 deletions
|
@ -0,0 +1,50 @@
|
||||||
|
# Generated by Django 3.2.20 on 2023-11-25 00:47
|
||||||
|
|
||||||
|
from importlib import import_module
|
||||||
|
import re
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
import pgtrigger.compiler
|
||||||
|
import pgtrigger.migrations
|
||||||
|
|
||||||
|
trigger_migration = import_module("bookwyrm.migrations.0077_auto_20210623_2155")
|
||||||
|
|
||||||
|
# it's _very_ convenient for development that this migration be reversible
|
||||||
|
search_vector_trigger = trigger_migration.Migration.operations[4]
|
||||||
|
author_search_vector_trigger = trigger_migration.Migration.operations[5]
|
||||||
|
|
||||||
|
|
||||||
|
assert re.search(r"\bCREATE TRIGGER search_vector_trigger\b", search_vector_trigger.sql)
|
||||||
|
assert re.search(
|
||||||
|
r"\bCREATE TRIGGER author_search_vector_trigger\b",
|
||||||
|
author_search_vector_trigger.sql,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0190_book_search_updates"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
pgtrigger.migrations.AddTrigger(
|
||||||
|
model_name="author",
|
||||||
|
trigger=pgtrigger.compiler.Trigger(
|
||||||
|
name="reset_search_vector_on_author_edit",
|
||||||
|
sql=pgtrigger.compiler.UpsertTriggerSql(
|
||||||
|
func="WITH book AS (SELECT bookwyrm_book.id AS row_id FROM bookwyrm_author LEFT OUTER JOIN bookwyrm_book_authors ON bookwyrm_book_authors.id = new.id LEFT OUTER JOIN bookwyrm_book ON bookwyrm_book.id = bookwyrm_book_authors.book_id) UPDATE bookwyrm_book SET search_vector = '' FROM book WHERE id = book.row_id;RETURN NEW;",
|
||||||
|
hash="9c0a472e2bf60e63d593cce49f47972c7b227a00",
|
||||||
|
operation='UPDATE OF "name"',
|
||||||
|
pgid="pgtrigger_reset_search_vector_on_author_edit_a447c",
|
||||||
|
table="bookwyrm_author",
|
||||||
|
when="AFTER",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RunSQL(
|
||||||
|
sql="""DROP TRIGGER IF EXISTS author_search_vector_trigger ON bookwyrm_author;
|
||||||
|
DROP FUNCTION IF EXISTS author_trigger;
|
||||||
|
""",
|
||||||
|
reverse_sql=author_search_vector_trigger.sql,
|
||||||
|
),
|
||||||
|
]
|
|
@ -3,9 +3,11 @@ import re
|
||||||
from typing import Tuple, Any
|
from typing import Tuple, Any
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
import pgtrigger
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import DOMAIN
|
from bookwyrm.settings import DOMAIN
|
||||||
|
from bookwyrm.utils.db import format_trigger
|
||||||
|
|
||||||
from .book import BookDataModel
|
from .book import BookDataModel
|
||||||
from . import fields
|
from . import fields
|
||||||
|
@ -66,4 +68,31 @@ class Author(BookDataModel):
|
||||||
"""editions and works both use "book" instead of model_name"""
|
"""editions and works both use "book" instead of model_name"""
|
||||||
return f"https://{DOMAIN}/author/{self.id}"
|
return f"https://{DOMAIN}/author/{self.id}"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""sets up indexes and triggers"""
|
||||||
|
|
||||||
|
triggers = [
|
||||||
|
pgtrigger.Trigger(
|
||||||
|
name="reset_search_vector_on_author_edit",
|
||||||
|
when=pgtrigger.After,
|
||||||
|
operation=pgtrigger.UpdateOf("name"),
|
||||||
|
func=format_trigger(
|
||||||
|
"""WITH book AS (
|
||||||
|
SELECT bookwyrm_book.id AS row_id
|
||||||
|
FROM bookwyrm_author
|
||||||
|
LEFT OUTER JOIN bookwyrm_book_authors
|
||||||
|
ON bookwyrm_book_authors.id = new.id
|
||||||
|
LEFT OUTER JOIN bookwyrm_book
|
||||||
|
ON bookwyrm_book.id = bookwyrm_book_authors.book_id
|
||||||
|
)
|
||||||
|
UPDATE bookwyrm_book
|
||||||
|
SET search_vector = ''
|
||||||
|
FROM book
|
||||||
|
WHERE id = book.row_id;
|
||||||
|
RETURN new;
|
||||||
|
"""
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
activity_serializer = activitypub.Author
|
activity_serializer = activitypub.Author
|
||||||
|
|
|
@ -104,6 +104,7 @@ INSTALLED_APPS = [
|
||||||
"celery",
|
"celery",
|
||||||
"django_celery_beat",
|
"django_celery_beat",
|
||||||
"imagekit",
|
"imagekit",
|
||||||
|
"pgtrigger",
|
||||||
"storages",
|
"storages",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
22
bookwyrm/utils/db.py
Normal file
22
bookwyrm/utils/db.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
""" Database utilities """
|
||||||
|
|
||||||
|
from typing import cast
|
||||||
|
import sqlparse # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def format_trigger(sql: str) -> str:
|
||||||
|
"""format SQL trigger before storing
|
||||||
|
|
||||||
|
we remove whitespace and use consistent casing so as to avoid migrations
|
||||||
|
due to formatting changes.
|
||||||
|
"""
|
||||||
|
return cast(
|
||||||
|
str,
|
||||||
|
sqlparse.format(
|
||||||
|
sql,
|
||||||
|
strip_comments=True,
|
||||||
|
strip_whitespace=True,
|
||||||
|
keyword_case="upper",
|
||||||
|
identifier_case="lower",
|
||||||
|
),
|
||||||
|
)
|
|
@ -7,6 +7,7 @@ django-celery-beat==2.4.0
|
||||||
django-compressor==4.3.1
|
django-compressor==4.3.1
|
||||||
django-imagekit==4.1.0
|
django-imagekit==4.1.0
|
||||||
django-model-utils==4.3.1
|
django-model-utils==4.3.1
|
||||||
|
django-pgtrigger==4.10.0
|
||||||
django-sass-processor==1.2.2
|
django-sass-processor==1.2.2
|
||||||
django-csp==3.7
|
django-csp==3.7
|
||||||
environs==9.5.0
|
environs==9.5.0
|
||||||
|
|
Loading…
Reference in a new issue