Change UniqueConstraint for wider database support (#6607)

This fixes #6393 by modifying the constraint to use an IN condition
which supports both Postgres and SQL Server. Previously, the `|` (OR)
condition was only supported by Postgres because SQL Server only
supports AND conditions.

The implementation follows suggestions from @gasman in
https://github.com/wagtail/wagtail/issues/6393#issuecomment-732161057:

* Migration 0050 is modified to not break on SQL Server
* Added migration 0060 to add or replace the constraint

Additionally, this allows for and documents a `DATABASE_DRIVER` env
variable to be set for testing, to allow a different SQL Server driver
(e.g. FreeTDS on Mac/Linux); and adds the specific `host_is_server`
option for FreeTDS (won't affect SQL Server Native Client on CI).
pull/6676/head
David Beitey 2020-12-03 17:36:47 +10:00 zatwierdzone przez Matt Westcott
rodzic 9f4fe2104e
commit 3a5b7255ad
7 zmienionych plików z 30 dodań i 4 usunięć

Wyświetl plik

@ -15,6 +15,7 @@ Changelog
* Fix: Stop menu icon overlapping the breadcrumb on small viewport widths in page editor (Karran Besen)
* Fix: Make sure document chooser pagination preserves the selected collection when moving between pages (Alex Sa)
* Fix: Gracefully handle oEmbed endpoints returning non-JSON responses (Matt Westcott)
* Fix: Fix unique constraint on WorkflowState for SQL Server compatibility (David Beitey)
2.11.3 (10.12.2020)

Wyświetl plik

@ -147,6 +147,8 @@ If you need to use different connection settings, use the following environment
* ``DATABASE_PORT``
It is also possible to set ``DATABASE_DRIVER``, which corresponds to the `driver` value within `OPTIONS` if an SQL Server engine is used.
Testing Elasticsearch
---------------------

Wyświetl plik

@ -43,6 +43,7 @@ Bug fixes
* Stop menu icon overlapping the breadcrumb on small viewport widths in page editor (Karran Besen)
* Make sure document chooser pagination preserves the selected collection when moving between pages (Alex Sa)
* Gracefully handle oEmbed endpoints returning non-JSON responses (Matt Westcott)
* Fix unique constraint on WorkflowState for SQL Server compatibility (David Beitey)
Upgrade considerations

Wyświetl plik

@ -21,6 +21,6 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='workflowstate',
constraint=models.UniqueConstraint(condition=models.Q(('status', 'in_progress'), ('status', 'needs_changes'), _connector='OR'), fields=('page',), name='unique_in_progress_workflow'),
constraint=models.UniqueConstraint(condition=models.Q(status__in=('in_progress', 'needs_changes')), fields=('page',), name='unique_in_progress_workflow'),
),
]

Wyświetl plik

@ -0,0 +1,21 @@
# Generated by Django 3.1.3 on 2020-11-27 01:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0059_apply_collection_ordering'),
]
operations = [
migrations.RemoveConstraint(
model_name='workflowstate',
name='unique_in_progress_workflow',
),
migrations.AddConstraint(
model_name='workflowstate',
constraint=models.UniqueConstraint(condition=models.Q(status__in=('in_progress', 'needs_changes')), fields=('page',), name='unique_in_progress_workflow'),
),
]

Wyświetl plik

@ -4316,9 +4316,9 @@ class WorkflowState(models.Model):
class Meta:
verbose_name = _('Workflow state')
verbose_name_plural = _('Workflow states')
# prevent multiple STATUS_IN_PROGRESS/STATUS_NEEDS_CHANGES workflows for the same page. This is not supported by MySQL, so is checked additionally on save.
# prevent multiple STATUS_IN_PROGRESS/STATUS_NEEDS_CHANGES workflows for the same page. This is only supported by specific databases (e.g. Postgres, SQL Server), so is checked additionally on save.
constraints = [
models.UniqueConstraint(fields=['page'], condition=(Q(status='in_progress') | Q(status='needs_changes')), name='unique_in_progress_workflow')
models.UniqueConstraint(fields=['page'], condition=Q(status__in=('in_progress', 'needs_changes')), name='unique_in_progress_workflow')
]

Wyświetl plik

@ -33,8 +33,9 @@ if DATABASES['default']['ENGINE'] != 'django.db.backends.sqlite3':
# Add extra options when mssql is used (on for example appveyor)
if DATABASES['default']['ENGINE'] == 'sql_server.pyodbc':
DATABASES['default']['OPTIONS'] = {
'driver': 'SQL Server Native Client 11.0',
'driver': os.environ.get('DATABASE_DRIVER', 'SQL Server Native Client 11.0'),
'MARS_Connection': 'True',
'host_is_server': True, # Applies to FreeTDS driver only
}