django-migrate-sql-deux 0.4.0__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_migrate_sql_deux-0.5.2/LICENSE +13 -0
- django_migrate_sql_deux-0.5.2/PKG-INFO +302 -0
- django_migrate_sql_deux-0.5.2/django_migrate_sql_deux.egg-info/PKG-INFO +302 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/django_migrate_sql_deux.egg-info/SOURCES.txt +2 -0
- django_migrate_sql_deux-0.5.2/migrate_sql/__init__.py +1 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/management/commands/makemigrations.py +2 -1
- django_migrate_sql_deux-0.5.2/pyproject.toml +25 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/setup.py +0 -1
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_project/settings.py +1 -0
- django-migrate-sql-deux-0.4.0/PKG-INFO +0 -295
- django-migrate-sql-deux-0.4.0/django_migrate_sql_deux.egg-info/PKG-INFO +0 -295
- django-migrate-sql-deux-0.4.0/migrate_sql/__init__.py +0 -1
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/README.rst +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/django_migrate_sql_deux.egg-info/dependency_links.txt +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/django_migrate_sql_deux.egg-info/not-zip-safe +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/django_migrate_sql_deux.egg-info/top_level.txt +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/autodetector.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/config.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/graph.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/management/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/management/commands/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/migrate_sql/operations.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/setup.cfg +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/manage.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/apps.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_change/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_change/0002_auto_20151224_1827.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_change/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_delete/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_delete/0002_auto_20160106_0947.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_delete/0003_auto_20160108_0048.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_delete/0004_auto_20160108_0048.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_delete/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_update/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_update/0002_auto_20160106_0947.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_deps_update/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_recreate/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_recreate/0002_auto_20151224_1827.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_recreate/0003_auto_20160106_1038.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/migrations_recreate/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/models.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/sql_config.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/test_migrations.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/test_utils.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app/urls.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/apps.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/migrations/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/migrations_deps_delete/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/migrations_deps_delete/0002_auto_20160108_0041.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/migrations_deps_delete/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/migrations_deps_update/0001_initial.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/migrations_deps_update/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/models.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/sql_config.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_app2/urls.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_project/__init__.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_project/urls.py +0 -0
- {django-migrate-sql-deux-0.4.0 → django_migrate_sql_deux-0.5.2}/tests/test_project/wsgi.py +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright (c) 2016, Bogdan Klichuk <klichukb@gmail.com>
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-migrate-sql-deux
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: Migration support for raw SQL in Django
|
|
5
|
+
Home-page: https://github.com/festicket/django-migrate-sql
|
|
6
|
+
Author: Festicket
|
|
7
|
+
Author-email: dev@festicket.com
|
|
8
|
+
License: BSD
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Framework :: Django
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Framework :: Django :: 2.1
|
|
17
|
+
Classifier: Framework :: Django :: 2.2
|
|
18
|
+
Classifier: Framework :: Django :: 3.0
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: summary
|
|
28
|
+
|
|
29
|
+
django-migrate-sql-deux
|
|
30
|
+
=======================
|
|
31
|
+
|
|
32
|
+
.. note::
|
|
33
|
+
|
|
34
|
+
This package is a fork of the ``django-migrate-sql`` package, originally published
|
|
35
|
+
by Bogdan Klichuk. This package appears unmaintained, so we decided to start a fork
|
|
36
|
+
as we depended on it. Most of the code is from him.
|
|
37
|
+
|
|
38
|
+
|Build Status| |codecov.io|
|
|
39
|
+
|
|
40
|
+
Django Migrations support for raw SQL.
|
|
41
|
+
|
|
42
|
+
About
|
|
43
|
+
-----
|
|
44
|
+
|
|
45
|
+
This tool implements mechanism for managing changes to custom SQL
|
|
46
|
+
entities (functions, types, indices, triggers) using built-in migration
|
|
47
|
+
mechanism. Technically creates a sophistication layer on top of the
|
|
48
|
+
``RunSQL`` Django operation.
|
|
49
|
+
|
|
50
|
+
What it does
|
|
51
|
+
------------
|
|
52
|
+
|
|
53
|
+
- Makes maintaining your SQL functions, custom composite types, indices
|
|
54
|
+
and triggers easier.
|
|
55
|
+
- Structures SQL into configuration of **SQL items**, that are
|
|
56
|
+
identified by names and divided among apps, just like models.
|
|
57
|
+
- Automatically gathers and persists changes of your custom SQL into
|
|
58
|
+
migrations using ``makemigrations``.
|
|
59
|
+
- Properly executes backwards/forwards keeping integrity of database.
|
|
60
|
+
- Create -> Drop -> Recreate approach for changes to items that do not
|
|
61
|
+
support altering and require dropping and recreating.
|
|
62
|
+
- Dependencies system for SQL items, which solves the problem of
|
|
63
|
+
updating items, that rely on others (for example custom
|
|
64
|
+
types/functions that use other custom types), and require dropping
|
|
65
|
+
all dependency tree previously with further recreation.
|
|
66
|
+
|
|
67
|
+
What it does not
|
|
68
|
+
----------------
|
|
69
|
+
|
|
70
|
+
- Does not parse SQL nor validate queries during ``makemigrations`` or
|
|
71
|
+
``migrate`` because is database-agnostic. For this same reason
|
|
72
|
+
setting up proper dependencies is user's responsibility.
|
|
73
|
+
- Does not create ``ALTER`` queries for items that support this, for
|
|
74
|
+
example ``ALTER TYPE`` in Postgre SQL, because is database-agnostic.
|
|
75
|
+
In case your tools allow rolling all the changes through ``ALTER``
|
|
76
|
+
queries, you can consider not using this app **or** restructure
|
|
77
|
+
migrations manually after creation by nesting generated operations
|
|
78
|
+
into ```state_operations`` of
|
|
79
|
+
``RunSQL`` <https://docs.djangoproject.com/en/1.8/ref/migration-operations/#runsql>`__
|
|
80
|
+
that does ``ALTER``.
|
|
81
|
+
- (**TODO**)During ``migrate`` does not restore full state of items for
|
|
82
|
+
analysis, thus does not notify about existing changes to schema that
|
|
83
|
+
are not migrated **nor** does not recognize circular dependencies
|
|
84
|
+
during migration execution.
|
|
85
|
+
|
|
86
|
+
Installation
|
|
87
|
+
------------
|
|
88
|
+
|
|
89
|
+
Install from PyPi:
|
|
90
|
+
|
|
91
|
+
::
|
|
92
|
+
|
|
93
|
+
$ pip install django-migrate-sql-deux
|
|
94
|
+
|
|
95
|
+
Add ``migrate_sql`` to ``INSTALLED_APPS``:
|
|
96
|
+
|
|
97
|
+
.. code:: python
|
|
98
|
+
|
|
99
|
+
INSTALLED_APPS = [
|
|
100
|
+
# ...
|
|
101
|
+
'migrate_sql',
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
App defines a custom ``makemigrations`` command, that inherits from
|
|
105
|
+
Django's core one, so in order ``migrate_sql`` app to kick in put it
|
|
106
|
+
after any other apps that redefine ``makemigrations`` command too.
|
|
107
|
+
|
|
108
|
+
Usage
|
|
109
|
+
-----
|
|
110
|
+
|
|
111
|
+
1) Create ``sql_config.py`` module to root of a target app you want to
|
|
112
|
+
manage custom SQL for.
|
|
113
|
+
|
|
114
|
+
2) Define SQL items in it (``sql_items``), for example:
|
|
115
|
+
|
|
116
|
+
.. code:: python
|
|
117
|
+
|
|
118
|
+
# PostgreSQL example.
|
|
119
|
+
# Let's define a simple function and let `migrate_sql` manage it's changes.
|
|
120
|
+
|
|
121
|
+
from migrate_sql.config import SQLItem
|
|
122
|
+
|
|
123
|
+
sql_items = [
|
|
124
|
+
SQLItem(
|
|
125
|
+
'make_sum', # name of the item
|
|
126
|
+
'create or replace function make_sum(a int, b int) returns int as $$ '
|
|
127
|
+
'begin return a + b; end; '
|
|
128
|
+
'$$ language plpgsql;', # forward sql
|
|
129
|
+
reverse_sql='drop function make_sum(int, int);', # sql for removal
|
|
130
|
+
),
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
3) Create migration ``./manage.py makemigrations``:
|
|
134
|
+
|
|
135
|
+
::
|
|
136
|
+
|
|
137
|
+
Migrations for 'app_name':
|
|
138
|
+
0002_auto_xxxx.py:
|
|
139
|
+
- Create SQL "make_sum"
|
|
140
|
+
|
|
141
|
+
You can take a look at content this generated:
|
|
142
|
+
|
|
143
|
+
.. code:: python
|
|
144
|
+
|
|
145
|
+
# -*- coding: utf-8 -*-
|
|
146
|
+
from __future__ import unicode_literals
|
|
147
|
+
from django.db import migrations, models
|
|
148
|
+
import migrate_sql.operations
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Migration(migrations.Migration):
|
|
152
|
+
dependencies = [
|
|
153
|
+
('app_name', '0001_initial'),
|
|
154
|
+
]
|
|
155
|
+
operations = [
|
|
156
|
+
migrate_sql.operations.CreateSQL(
|
|
157
|
+
name='make_sum',
|
|
158
|
+
sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',
|
|
159
|
+
reverse_sql='drop function make_sum(int, int);',
|
|
160
|
+
),
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
4) Execute migration ``./manage.py migrate``:
|
|
164
|
+
|
|
165
|
+
::
|
|
166
|
+
|
|
167
|
+
Operations to perform:
|
|
168
|
+
Apply all migrations: app_name
|
|
169
|
+
Running migrations:
|
|
170
|
+
Rendering model states... DONE
|
|
171
|
+
Applying app_name.0002_xxxx... OK
|
|
172
|
+
|
|
173
|
+
Check result in ``./manage.py dbshell``:
|
|
174
|
+
|
|
175
|
+
::
|
|
176
|
+
|
|
177
|
+
db_name=# select make_sum(12, 15);
|
|
178
|
+
make_sum
|
|
179
|
+
----------
|
|
180
|
+
27
|
|
181
|
+
(1 row)
|
|
182
|
+
|
|
183
|
+
Now, say, you want to change the function implementation so that it
|
|
184
|
+
takes a custom type as argument:
|
|
185
|
+
|
|
186
|
+
5) Edit your ``sql_config.py``:
|
|
187
|
+
|
|
188
|
+
.. code:: python
|
|
189
|
+
|
|
190
|
+
# PostgreSQL example #2.
|
|
191
|
+
# Function and custom type.
|
|
192
|
+
|
|
193
|
+
from migrate_sql.config import SQLItem
|
|
194
|
+
|
|
195
|
+
sql_items = [
|
|
196
|
+
SQLItem(
|
|
197
|
+
'make_sum', # name of the item
|
|
198
|
+
'create or replace function make_sum(a mynum, b mynum) returns mynum as $$ '
|
|
199
|
+
'begin return (a.num + b.num, 'result')::mynum; end; '
|
|
200
|
+
'$$ language plpgsql;', # forward sql
|
|
201
|
+
reverse_sql='drop function make_sum(mynum, mynum);', # sql for removal
|
|
202
|
+
# depends on `mynum` since takes it as argument. we won't be able to drop function
|
|
203
|
+
# without dropping `mynum` first.
|
|
204
|
+
dependencies=[('app_name', 'mynum')],
|
|
205
|
+
),
|
|
206
|
+
SQLItem(
|
|
207
|
+
'mynum' # name of the item
|
|
208
|
+
'create type mynum as (num int, name varchar(20));', # forward sql
|
|
209
|
+
reverse_sql='drop type mynum;', # sql for removal
|
|
210
|
+
),
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
6) Generate migration ``./manage.py makemigrations``:
|
|
214
|
+
|
|
215
|
+
::
|
|
216
|
+
|
|
217
|
+
Migrations for 'app_name':
|
|
218
|
+
0003_xxxx:
|
|
219
|
+
- Reverse alter SQL "make_sum"
|
|
220
|
+
- Create SQL "mynum"
|
|
221
|
+
- Alter SQL "make_sum"
|
|
222
|
+
- Alter SQL state "make_sum"
|
|
223
|
+
|
|
224
|
+
You can take a look at the content this generated:
|
|
225
|
+
|
|
226
|
+
.. code:: python
|
|
227
|
+
|
|
228
|
+
# -*- coding: utf-8 -*-
|
|
229
|
+
from __future__ import unicode_literals
|
|
230
|
+
from django.db import migrations, models
|
|
231
|
+
import migrate_sql.operations
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Migration(migrations.Migration):
|
|
235
|
+
dependencies = [
|
|
236
|
+
('app_name', '0002_xxxx'),
|
|
237
|
+
]
|
|
238
|
+
operations = [
|
|
239
|
+
migrate_sql.operations.ReverseAlterSQL(
|
|
240
|
+
name='make_sum',
|
|
241
|
+
sql='drop function make_sum(int, int);',
|
|
242
|
+
reverse_sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',
|
|
243
|
+
),
|
|
244
|
+
migrate_sql.operations.CreateSQL(
|
|
245
|
+
name='mynum',
|
|
246
|
+
sql='create type mynum as (num int, name varchar(20));',
|
|
247
|
+
reverse_sql='drop type mynum;',
|
|
248
|
+
),
|
|
249
|
+
migrate_sql.operations.AlterSQL(
|
|
250
|
+
name='make_sum',
|
|
251
|
+
sql='create or replace function make_sum(a mynum, b mynum) returns mynum as $$ begin return (a.num + b.num, \'result\')::mynum; end; $$ language plpgsql;',
|
|
252
|
+
reverse_sql='drop function make_sum(mynum, mynum);',
|
|
253
|
+
),
|
|
254
|
+
migrate_sql.operations.AlterSQLState(
|
|
255
|
+
name='make_sum',
|
|
256
|
+
add_dependencies=(('app_name', 'mynum'),),
|
|
257
|
+
),
|
|
258
|
+
]
|
|
259
|
+
|
|
260
|
+
***NOTE:** Previous function is completely dropped before creation
|
|
261
|
+
because definition of it changed. ``CREATE OR REPLACE`` would create
|
|
262
|
+
another version of it, so ``DROP`` makes it clean.*
|
|
263
|
+
|
|
264
|
+
***If you put ``replace=True`` as kwarg to an ``SQLItem`` definition, it
|
|
265
|
+
will NOT drop + create it, but just rerun forward SQL, which is
|
|
266
|
+
``CREATE OR REPLACE`` in this example.***
|
|
267
|
+
|
|
268
|
+
7) Execute migration ``./manage.py migrate``:
|
|
269
|
+
|
|
270
|
+
::
|
|
271
|
+
|
|
272
|
+
Operations to perform:
|
|
273
|
+
Apply all migrations: app_name
|
|
274
|
+
Running migrations:
|
|
275
|
+
Rendering model states... DONE
|
|
276
|
+
Applying brands.0003_xxxx... OK
|
|
277
|
+
|
|
278
|
+
Check results:
|
|
279
|
+
|
|
280
|
+
::
|
|
281
|
+
|
|
282
|
+
db_name=# select make_sum((5, 'a')::mynum, (3, 'b')::mynum);
|
|
283
|
+
make_sum
|
|
284
|
+
------------
|
|
285
|
+
(8,result)
|
|
286
|
+
(1 row)
|
|
287
|
+
|
|
288
|
+
db_name=# select make_sum(12, 15);
|
|
289
|
+
ERROR: function make_sum(integer, integer) does not exist
|
|
290
|
+
LINE 1: select make_sum(12, 15);
|
|
291
|
+
^
|
|
292
|
+
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
293
|
+
|
|
294
|
+
For more examples see ``tests``.
|
|
295
|
+
|
|
296
|
+
Feel free to `open new
|
|
297
|
+
issues <https://github.com/klichukb/django-migrate-sql/issues>`__.
|
|
298
|
+
|
|
299
|
+
.. |Build Status| image:: https://travis-ci.org/klichukb/django-migrate-sql.svg?branch=master
|
|
300
|
+
:target: https://travis-ci.org/klichukb/django-migrate-sql
|
|
301
|
+
.. |codecov.io| image:: https://img.shields.io/codecov/c/github/klichukb/django-migrate-sql/master.svg
|
|
302
|
+
:target: https://codecov.io/github/klichukb/django-migrate-sql?branch=master
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-migrate-sql-deux
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: Migration support for raw SQL in Django
|
|
5
|
+
Home-page: https://github.com/festicket/django-migrate-sql
|
|
6
|
+
Author: Festicket
|
|
7
|
+
Author-email: dev@festicket.com
|
|
8
|
+
License: BSD
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Framework :: Django
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Framework :: Django :: 2.1
|
|
17
|
+
Classifier: Framework :: Django :: 2.2
|
|
18
|
+
Classifier: Framework :: Django :: 3.0
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: summary
|
|
28
|
+
|
|
29
|
+
django-migrate-sql-deux
|
|
30
|
+
=======================
|
|
31
|
+
|
|
32
|
+
.. note::
|
|
33
|
+
|
|
34
|
+
This package is a fork of the ``django-migrate-sql`` package, originally published
|
|
35
|
+
by Bogdan Klichuk. This package appears unmaintained, so we decided to start a fork
|
|
36
|
+
as we depended on it. Most of the code is from him.
|
|
37
|
+
|
|
38
|
+
|Build Status| |codecov.io|
|
|
39
|
+
|
|
40
|
+
Django Migrations support for raw SQL.
|
|
41
|
+
|
|
42
|
+
About
|
|
43
|
+
-----
|
|
44
|
+
|
|
45
|
+
This tool implements mechanism for managing changes to custom SQL
|
|
46
|
+
entities (functions, types, indices, triggers) using built-in migration
|
|
47
|
+
mechanism. Technically creates a sophistication layer on top of the
|
|
48
|
+
``RunSQL`` Django operation.
|
|
49
|
+
|
|
50
|
+
What it does
|
|
51
|
+
------------
|
|
52
|
+
|
|
53
|
+
- Makes maintaining your SQL functions, custom composite types, indices
|
|
54
|
+
and triggers easier.
|
|
55
|
+
- Structures SQL into configuration of **SQL items**, that are
|
|
56
|
+
identified by names and divided among apps, just like models.
|
|
57
|
+
- Automatically gathers and persists changes of your custom SQL into
|
|
58
|
+
migrations using ``makemigrations``.
|
|
59
|
+
- Properly executes backwards/forwards keeping integrity of database.
|
|
60
|
+
- Create -> Drop -> Recreate approach for changes to items that do not
|
|
61
|
+
support altering and require dropping and recreating.
|
|
62
|
+
- Dependencies system for SQL items, which solves the problem of
|
|
63
|
+
updating items, that rely on others (for example custom
|
|
64
|
+
types/functions that use other custom types), and require dropping
|
|
65
|
+
all dependency tree previously with further recreation.
|
|
66
|
+
|
|
67
|
+
What it does not
|
|
68
|
+
----------------
|
|
69
|
+
|
|
70
|
+
- Does not parse SQL nor validate queries during ``makemigrations`` or
|
|
71
|
+
``migrate`` because is database-agnostic. For this same reason
|
|
72
|
+
setting up proper dependencies is user's responsibility.
|
|
73
|
+
- Does not create ``ALTER`` queries for items that support this, for
|
|
74
|
+
example ``ALTER TYPE`` in Postgre SQL, because is database-agnostic.
|
|
75
|
+
In case your tools allow rolling all the changes through ``ALTER``
|
|
76
|
+
queries, you can consider not using this app **or** restructure
|
|
77
|
+
migrations manually after creation by nesting generated operations
|
|
78
|
+
into ```state_operations`` of
|
|
79
|
+
``RunSQL`` <https://docs.djangoproject.com/en/1.8/ref/migration-operations/#runsql>`__
|
|
80
|
+
that does ``ALTER``.
|
|
81
|
+
- (**TODO**)During ``migrate`` does not restore full state of items for
|
|
82
|
+
analysis, thus does not notify about existing changes to schema that
|
|
83
|
+
are not migrated **nor** does not recognize circular dependencies
|
|
84
|
+
during migration execution.
|
|
85
|
+
|
|
86
|
+
Installation
|
|
87
|
+
------------
|
|
88
|
+
|
|
89
|
+
Install from PyPi:
|
|
90
|
+
|
|
91
|
+
::
|
|
92
|
+
|
|
93
|
+
$ pip install django-migrate-sql-deux
|
|
94
|
+
|
|
95
|
+
Add ``migrate_sql`` to ``INSTALLED_APPS``:
|
|
96
|
+
|
|
97
|
+
.. code:: python
|
|
98
|
+
|
|
99
|
+
INSTALLED_APPS = [
|
|
100
|
+
# ...
|
|
101
|
+
'migrate_sql',
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
App defines a custom ``makemigrations`` command, that inherits from
|
|
105
|
+
Django's core one, so in order ``migrate_sql`` app to kick in put it
|
|
106
|
+
after any other apps that redefine ``makemigrations`` command too.
|
|
107
|
+
|
|
108
|
+
Usage
|
|
109
|
+
-----
|
|
110
|
+
|
|
111
|
+
1) Create ``sql_config.py`` module to root of a target app you want to
|
|
112
|
+
manage custom SQL for.
|
|
113
|
+
|
|
114
|
+
2) Define SQL items in it (``sql_items``), for example:
|
|
115
|
+
|
|
116
|
+
.. code:: python
|
|
117
|
+
|
|
118
|
+
# PostgreSQL example.
|
|
119
|
+
# Let's define a simple function and let `migrate_sql` manage it's changes.
|
|
120
|
+
|
|
121
|
+
from migrate_sql.config import SQLItem
|
|
122
|
+
|
|
123
|
+
sql_items = [
|
|
124
|
+
SQLItem(
|
|
125
|
+
'make_sum', # name of the item
|
|
126
|
+
'create or replace function make_sum(a int, b int) returns int as $$ '
|
|
127
|
+
'begin return a + b; end; '
|
|
128
|
+
'$$ language plpgsql;', # forward sql
|
|
129
|
+
reverse_sql='drop function make_sum(int, int);', # sql for removal
|
|
130
|
+
),
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
3) Create migration ``./manage.py makemigrations``:
|
|
134
|
+
|
|
135
|
+
::
|
|
136
|
+
|
|
137
|
+
Migrations for 'app_name':
|
|
138
|
+
0002_auto_xxxx.py:
|
|
139
|
+
- Create SQL "make_sum"
|
|
140
|
+
|
|
141
|
+
You can take a look at content this generated:
|
|
142
|
+
|
|
143
|
+
.. code:: python
|
|
144
|
+
|
|
145
|
+
# -*- coding: utf-8 -*-
|
|
146
|
+
from __future__ import unicode_literals
|
|
147
|
+
from django.db import migrations, models
|
|
148
|
+
import migrate_sql.operations
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Migration(migrations.Migration):
|
|
152
|
+
dependencies = [
|
|
153
|
+
('app_name', '0001_initial'),
|
|
154
|
+
]
|
|
155
|
+
operations = [
|
|
156
|
+
migrate_sql.operations.CreateSQL(
|
|
157
|
+
name='make_sum',
|
|
158
|
+
sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',
|
|
159
|
+
reverse_sql='drop function make_sum(int, int);',
|
|
160
|
+
),
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
4) Execute migration ``./manage.py migrate``:
|
|
164
|
+
|
|
165
|
+
::
|
|
166
|
+
|
|
167
|
+
Operations to perform:
|
|
168
|
+
Apply all migrations: app_name
|
|
169
|
+
Running migrations:
|
|
170
|
+
Rendering model states... DONE
|
|
171
|
+
Applying app_name.0002_xxxx... OK
|
|
172
|
+
|
|
173
|
+
Check result in ``./manage.py dbshell``:
|
|
174
|
+
|
|
175
|
+
::
|
|
176
|
+
|
|
177
|
+
db_name=# select make_sum(12, 15);
|
|
178
|
+
make_sum
|
|
179
|
+
----------
|
|
180
|
+
27
|
|
181
|
+
(1 row)
|
|
182
|
+
|
|
183
|
+
Now, say, you want to change the function implementation so that it
|
|
184
|
+
takes a custom type as argument:
|
|
185
|
+
|
|
186
|
+
5) Edit your ``sql_config.py``:
|
|
187
|
+
|
|
188
|
+
.. code:: python
|
|
189
|
+
|
|
190
|
+
# PostgreSQL example #2.
|
|
191
|
+
# Function and custom type.
|
|
192
|
+
|
|
193
|
+
from migrate_sql.config import SQLItem
|
|
194
|
+
|
|
195
|
+
sql_items = [
|
|
196
|
+
SQLItem(
|
|
197
|
+
'make_sum', # name of the item
|
|
198
|
+
'create or replace function make_sum(a mynum, b mynum) returns mynum as $$ '
|
|
199
|
+
'begin return (a.num + b.num, 'result')::mynum; end; '
|
|
200
|
+
'$$ language plpgsql;', # forward sql
|
|
201
|
+
reverse_sql='drop function make_sum(mynum, mynum);', # sql for removal
|
|
202
|
+
# depends on `mynum` since takes it as argument. we won't be able to drop function
|
|
203
|
+
# without dropping `mynum` first.
|
|
204
|
+
dependencies=[('app_name', 'mynum')],
|
|
205
|
+
),
|
|
206
|
+
SQLItem(
|
|
207
|
+
'mynum' # name of the item
|
|
208
|
+
'create type mynum as (num int, name varchar(20));', # forward sql
|
|
209
|
+
reverse_sql='drop type mynum;', # sql for removal
|
|
210
|
+
),
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
6) Generate migration ``./manage.py makemigrations``:
|
|
214
|
+
|
|
215
|
+
::
|
|
216
|
+
|
|
217
|
+
Migrations for 'app_name':
|
|
218
|
+
0003_xxxx:
|
|
219
|
+
- Reverse alter SQL "make_sum"
|
|
220
|
+
- Create SQL "mynum"
|
|
221
|
+
- Alter SQL "make_sum"
|
|
222
|
+
- Alter SQL state "make_sum"
|
|
223
|
+
|
|
224
|
+
You can take a look at the content this generated:
|
|
225
|
+
|
|
226
|
+
.. code:: python
|
|
227
|
+
|
|
228
|
+
# -*- coding: utf-8 -*-
|
|
229
|
+
from __future__ import unicode_literals
|
|
230
|
+
from django.db import migrations, models
|
|
231
|
+
import migrate_sql.operations
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Migration(migrations.Migration):
|
|
235
|
+
dependencies = [
|
|
236
|
+
('app_name', '0002_xxxx'),
|
|
237
|
+
]
|
|
238
|
+
operations = [
|
|
239
|
+
migrate_sql.operations.ReverseAlterSQL(
|
|
240
|
+
name='make_sum',
|
|
241
|
+
sql='drop function make_sum(int, int);',
|
|
242
|
+
reverse_sql='create or replace function make_sum(a int, b int) returns int as $$ begin return a + b; end; $$ language plpgsql;',
|
|
243
|
+
),
|
|
244
|
+
migrate_sql.operations.CreateSQL(
|
|
245
|
+
name='mynum',
|
|
246
|
+
sql='create type mynum as (num int, name varchar(20));',
|
|
247
|
+
reverse_sql='drop type mynum;',
|
|
248
|
+
),
|
|
249
|
+
migrate_sql.operations.AlterSQL(
|
|
250
|
+
name='make_sum',
|
|
251
|
+
sql='create or replace function make_sum(a mynum, b mynum) returns mynum as $$ begin return (a.num + b.num, \'result\')::mynum; end; $$ language plpgsql;',
|
|
252
|
+
reverse_sql='drop function make_sum(mynum, mynum);',
|
|
253
|
+
),
|
|
254
|
+
migrate_sql.operations.AlterSQLState(
|
|
255
|
+
name='make_sum',
|
|
256
|
+
add_dependencies=(('app_name', 'mynum'),),
|
|
257
|
+
),
|
|
258
|
+
]
|
|
259
|
+
|
|
260
|
+
***NOTE:** Previous function is completely dropped before creation
|
|
261
|
+
because definition of it changed. ``CREATE OR REPLACE`` would create
|
|
262
|
+
another version of it, so ``DROP`` makes it clean.*
|
|
263
|
+
|
|
264
|
+
***If you put ``replace=True`` as kwarg to an ``SQLItem`` definition, it
|
|
265
|
+
will NOT drop + create it, but just rerun forward SQL, which is
|
|
266
|
+
``CREATE OR REPLACE`` in this example.***
|
|
267
|
+
|
|
268
|
+
7) Execute migration ``./manage.py migrate``:
|
|
269
|
+
|
|
270
|
+
::
|
|
271
|
+
|
|
272
|
+
Operations to perform:
|
|
273
|
+
Apply all migrations: app_name
|
|
274
|
+
Running migrations:
|
|
275
|
+
Rendering model states... DONE
|
|
276
|
+
Applying brands.0003_xxxx... OK
|
|
277
|
+
|
|
278
|
+
Check results:
|
|
279
|
+
|
|
280
|
+
::
|
|
281
|
+
|
|
282
|
+
db_name=# select make_sum((5, 'a')::mynum, (3, 'b')::mynum);
|
|
283
|
+
make_sum
|
|
284
|
+
------------
|
|
285
|
+
(8,result)
|
|
286
|
+
(1 row)
|
|
287
|
+
|
|
288
|
+
db_name=# select make_sum(12, 15);
|
|
289
|
+
ERROR: function make_sum(integer, integer) does not exist
|
|
290
|
+
LINE 1: select make_sum(12, 15);
|
|
291
|
+
^
|
|
292
|
+
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
293
|
+
|
|
294
|
+
For more examples see ``tests``.
|
|
295
|
+
|
|
296
|
+
Feel free to `open new
|
|
297
|
+
issues <https://github.com/klichukb/django-migrate-sql/issues>`__.
|
|
298
|
+
|
|
299
|
+
.. |Build Status| image:: https://travis-ci.org/klichukb/django-migrate-sql.svg?branch=master
|
|
300
|
+
:target: https://travis-ci.org/klichukb/django-migrate-sql
|
|
301
|
+
.. |codecov.io| image:: https://img.shields.io/codecov/c/github/klichukb/django-migrate-sql/master.svg
|
|
302
|
+
:target: https://codecov.io/github/klichukb/django-migrate-sql?branch=master
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.5.2'
|
|
@@ -8,7 +8,7 @@ import sys
|
|
|
8
8
|
from django.core.management.commands.makemigrations import Command as MakeMigrationsCommand
|
|
9
9
|
from django.db.migrations.loader import MigrationLoader
|
|
10
10
|
from django.db.migrations import Migration
|
|
11
|
-
from django.core.management.base import CommandError
|
|
11
|
+
from django.core.management.base import CommandError, no_translations
|
|
12
12
|
from django.db.migrations.questioner import InteractiveMigrationQuestioner
|
|
13
13
|
from django.apps import apps
|
|
14
14
|
from django.db.migrations.state import ProjectState
|
|
@@ -19,6 +19,7 @@ from migrate_sql.graph import build_current_graph
|
|
|
19
19
|
|
|
20
20
|
class Command(MakeMigrationsCommand):
|
|
21
21
|
|
|
22
|
+
@no_translations
|
|
22
23
|
def handle(self, *app_labels, **options):
|
|
23
24
|
|
|
24
25
|
self.verbosity = options.get('verbosity')
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[tool.semantic_release]
|
|
2
|
+
tag_format = "v{version}"
|
|
3
|
+
version_variables = [ "migrate_sql/__init__.py:__version__" ]
|
|
4
|
+
build_command = """
|
|
5
|
+
pip install build
|
|
6
|
+
python -m build
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
[tool.semantic_release.changelog]
|
|
10
|
+
mode = "update"
|
|
11
|
+
exclude_commit_patterns = [
|
|
12
|
+
"chore.*",
|
|
13
|
+
"ci.*",
|
|
14
|
+
"Merge pull request .*",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[tool.semantic_release.changelog.environment]
|
|
18
|
+
keep_trailing_newline = true
|
|
19
|
+
|
|
20
|
+
[tool.semantic_release.branches.main]
|
|
21
|
+
match = "main"
|
|
22
|
+
|
|
23
|
+
[tool.semantic_release.branches.noop]
|
|
24
|
+
match = "(?!main$)"
|
|
25
|
+
prerelease = true
|