Commit Graph
43 Commits
Author SHA1 Message Date
David Cain 48fac8856b Downgrade CREATE_INDEX_EXCLUSIVE to a warning
While it's always a dangerous *pattern* to create an index while a
transaction is open & holds an exclusive lock, in practice it's not
always a big deal (for example, indexing a table with very few rows can
be fast). Accordingly, downgrade to a warning.
2023-07-09 14:42:35 +02:00
David Cain 0c5519d9dc Add new check for indexing with atomic=True
Briefly, this check helps prevent a long-running index creation from
preventing all reads and writes to a table.

This supplements an existing check
==================================
There is an existing check, `CREATE_INDEX` which warns about creating
indices without the `CONCURRENTLY` argument. It's a helpful check!

However, there are some valid reasons to prefer non-concurrent index
creation. For example, concurrent index creation may struggle to
complete when applied to write-heavy tables (since Postgres will have to
make repeated passes on the table to accommodate the new reads since the
last round).

The danger of `EXCLUSIVE` locks
===============================
If you *do* want to create indices nonconcurrently, there is still a
**huge footgun** to be aware of -- locks which are held in a transaction
are not released until the transaction closes.

Dangerous Django defaults
=========================
By default, any time you add a new Django field with `db_index=True` or
`unique=True`, the automatically generated `Migration` has:

- implicit setting of `atomic=True` (transactions are on)
- an `ALTER TABLE...ADD COLUMN` call (exclusively locks the table)
- a `CREATE INDEX` invocation (*hopefully* quick, due to nullable
  columns)

It's even more dangerous if you combine an `ALTER TABLE` call with
`CREATE INDEX` of an existing, non-nullable column.

Favor `atomic=False` if you must index
======================================
Index-creating migrations should have few `operations`. Since index
creation does not modify row-level data (and only requires locking
against writes), there's no reason to use transactions.

It's prudent to bypass the default `atomic=True` for index creation.
2023-07-09 14:42:35 +02:00
David Cain 9fdfa06845 Fix error output when warnings are found
We should log the *warnings* found, not errors!
2023-07-09 14:42:35 +02:00
David Wobrock 97a1f5c6c9 Fix #250 -- Don't consider partial index creation as making a column not nullable. 2023-07-03 20:41:03 +02:00
David Wobrock 2ee7dac3b3 Add internal classes and add type hints + mypy. 2022-12-26 16:26:24 +01:00
David Wobrock e8f83708b0 Run black. 2022-11-03 22:00:00 +01:00
Sondre Lillebø Gundersen bd4eb89b8c chore: Upgrade Python syntax with pyupgrade
Run with the following pre-commit configuration:

```
repos:
  - repo: https://github.com/asottile/pyupgrade
    rev: v3.1.0
    hooks:
      - id: pyupgrade
        args: [ "--py3-plus", "--py36-plus", "--py37-plus" ]
```

The rationale for every change can be found at https://github.com/asottile/pyupgrade
2022-11-03 22:00:00 +01:00
Sören Wegener a3fc5f1a50 Improve error message when an unsupported database vendor/SQL analyser was selected. 2022-10-03 15:48:11 +02:00
David Wobrock 76a55dbb12 Raise when unsupported db vendor, and add option to specify SQL analyser 2022-01-30 15:20:18 +01:00
David Wobrock 3219f9cf8a Handle creating a unique index as adding a unique constraint 2022-01-28 21:23:44 +01:00
David Wobrock 7674a51bc9 Fix #178 -- Don't detect an index creation when the table is being created 2021-12-20 22:38:54 +01:00
Christian Bundy 397c1f0e16 Default ends_with_default to False
Problem: Previously in gh-117 we aimed to solve gh-115, which described a problem where we used `SET DEFAULT` and then `DROP DEFAULT` immediately afterward. The solution was to track whether any defaults are retained, but the `ends_with_default` variable is initialized as `None` rather than `False`. At the end of the function we check whether `ends_with_default is False`, never occurs unless a default is set.

Solution: Assume that there is no default unless proven otherwise, and iniitializie `ends_with_default` to `False` instead of `None`.

Fixes: gh-158
2021-08-14 15:22:24 +02:00
David Wobrock fa56196f04 Add PG reindex linting warning and improve some smaller stuff 2021-06-19 18:15:40 +02:00
David Wobrock 27e492996c Apply black 2021-06-19 18:15:40 +02:00
David Wobrock 2bf87c0659 Add Postgresql warning when using DROP INDEX without CONCURRENTLY keyword 2021-06-19 18:15:40 +02:00
David Wobrock 343d163c88 Add Postgresql warning when using CREATE INDEX without CONCURRENTLY keyword 2021-06-19 18:15:40 +02:00
David-Wobrock 137089573c Implement include migration name options 2021-01-31 17:44:58 +01:00
David-Wobrock 6ab1d58c47 Apply isort to the project 2020-11-30 21:46:40 +01:00
David Wobrock f21ff2c278 Add (failing) tests cases for makeing a column not null with a Django default value 2020-06-20 18:08:16 +02:00
David Wobrock 31338714dd Fix #112 -- make the behaviour of --include-migrations-from more obvious
* Misspelled filename => fail (instead of linting all migrations and ignoring the error)
* An empty file/a file with no valid migration paths => lint no migrations (instead oflinting all migrations)
* If the option is not specified, keep the behaviour of linting all migrations
2020-06-17 22:32:42 +02:00
David Wobrock 813c5c8690 Remove apache license headers in each file. The one full copy of the license at the root of the repo shall define the license for all source files. 2020-01-11 22:08:33 +01:00
David Wobrock cbc5a623b0 Add unit tests on adding many to many field (by testing SQL directly) 2019-10-21 22:25:01 +02:00
David Wobrock e6e8cc7525 Update migrations list file behaviour
Instead of using the file path when the git commit is not
added, use the file and the migrations list no matter if we select
all migrations or just from a certain git commit.
And unit tests :)
2019-10-12 15:53:18 +02:00
David Wobrock 652031ce8d Add failing tests for unique_together condition 2019-07-30 10:47:20 +02:00
David Wobrock 19620d9996 Handle other strategy for sqlite in Django2.2 2019-07-29 21:05:12 +02:00
David Wobrock ef2052a7b0 Work on SQL Analyser module
* With database specific functions
* Functions that analyse the entire transaction
* Unit tests that only test this module
2019-07-29 21:05:12 +02:00
David Wobrock aa8043db74 Add unit test for exclude migration tests 2019-07-28 12:28:56 +02:00
David Wobrock 5561a308a3 Add tests for ignore applied/unapplied migrations 2019-06-06 22:54:08 +02:00
David Wobrock 5390fd507f Update Tests:
* don't use the project fixtures anymore but the one Django project
* update and refactor cache tests to be less brittle
* explicitly test mysql, postgresql and sqlite3 databases
* remove 'multiple_call' tests since it is not possible anymore
(with the Django singleton)
* update Travis and tox (dropping Python 3.4)
2019-05-12 15:32:57 +02:00
David-Wobrock f5a587c2be Fix split path function
So it also works on windows
and does not return empty stuff
and update tests
2019-02-24 15:55:05 +01:00
David Wobrock 009153fbf4 handle linting a project in pwd
When calling "django-migration-linter ."
be able to handle it (especially with cache)
2019-01-20 12:17:11 +01:00
Felix 3ae4840e34 Merge branch 'master' into do-not-check-git-folder 2019-01-07 12:19:25 +01:00
David-Wobrock 7a34ac9010 Fix tests and git migration gathering 2019-01-05 17:39:09 +01:00
David-Wobrock f0021dc139 Add test migration in folder 2019-01-04 22:00:19 +01:00
David-Wobrock 574af4b7fe Do not check if .git folder exists
git commands will fail anyway if not present
2019-01-04 21:42:39 +01:00
David-Wobrock 952e596d92 Bump copyright version to 2019 in files 2019-01-03 22:05:00 +01:00
Felix 4bcb67c9f2 Merge branch 'master' into cache 2018-12-23 22:40:29 +01:00
Felix 357f0aebf4 Adapt tests so that not relying on undefined
behaviour.
The app directories can appear in any order, we need to allow that
in tests.
2018-12-23 12:25:41 +01:00
Felix b68c0183bb Finish up cache and fix tests.
Still TODO: Merge with ignore functionality.
2018-12-20 14:45:35 +01:00
David-Wobrock 55e1e13ad5 Update copyright year to 2018 2018-01-07 12:15:23 +01:00
David Wobrock 50ce4f4cad Large code refactoring
* Add tests
* Remove git dependency (only needed when a git identifier is specified)
2017-11-29 23:57:23 +01:00
David-Wobrock 6f84056aeb Change git fixtures, do not use submodule or subtree
Just rename git folder when testing and delete them at the end
2017-11-01 15:28:17 +01:00
David-Wobrock 1cd36825c1 Start large refactoring of tests and project structure
* Put tests in tests/ diretory
* Write functional tests
* Create setup.py
* Put sources into django_migration_linter folder (for future PyPi publishing)
2017-10-30 23:31:13 +01:00