django-postpone-index 0.0.3__py3-none-any.whl → 0.0.4__py3-none-any.whl
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_postpone_index-0.0.3.dist-info → django_postpone_index-0.0.4.dist-info}/METADATA +2 -1
- {django_postpone_index-0.0.3.dist-info → django_postpone_index-0.0.4.dist-info}/RECORD +8 -8
- postpone_index/_version.py +2 -2
- postpone_index/contrib/postgres/schema.py +32 -1
- postpone_index/models.py +2 -1
- postpone_index/utils.py +23 -5
- {django_postpone_index-0.0.3.dist-info → django_postpone_index-0.0.4.dist-info}/WHEEL +0 -0
- {django_postpone_index-0.0.3.dist-info → django_postpone_index-0.0.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-postpone-index
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Postpone index creation to provide Zero Downtime Migration feature
|
|
5
5
|
Home-page: https://github.com/nnseva/django-postpone-index
|
|
6
6
|
Author: Vsevolod Novikov
|
|
@@ -105,6 +105,7 @@ The following complex use cases are processed by the package.
|
|
|
105
105
|
- Back Migration. The both, forward and backward migrations are processed.
|
|
106
106
|
- Implicit index drop while removing the table. The Django doesn't issue a separate SQL to drop indexes of the dropped table.
|
|
107
107
|
- Implicit index drop while removing the field. The Django doesn't issue a separate SQL to drop indexes related to the dropped column.
|
|
108
|
+
- Rename field (column) name or model (table) name
|
|
108
109
|
|
|
109
110
|
## Using
|
|
110
111
|
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
postpone_index/__init__.py,sha256=s1NgdtOn7SO7scs-uAaq1134F7Luh-JjB5Ghra3D2fQ,84
|
|
2
|
-
postpone_index/_version.py,sha256=
|
|
2
|
+
postpone_index/_version.py,sha256=QlXZ5JTjE_pgpDaeHk0GTExkc75xUZFmd0hA7kGYCJ0,704
|
|
3
3
|
postpone_index/admin.py,sha256=TAZxaciQkEBNhReYulsU5VopPCyABtMLZvCSxk0CfYE,820
|
|
4
4
|
postpone_index/apps.py,sha256=1ap2HY49uXVXjY9UWK3___fjPe22wqFOSOnuH2kIAxs,200
|
|
5
5
|
postpone_index/migration_utils.py,sha256=02rm77mz_MAufl5vdqKPV1CAd1-3bRk6kSy4MIxKsEo,752
|
|
6
|
-
postpone_index/models.py,sha256=
|
|
6
|
+
postpone_index/models.py,sha256=R_S8KBKlfPy6A6Urwdp17IINcd9VEZtkW5_cVbpKN-4,3581
|
|
7
7
|
postpone_index/testing_utils.py,sha256=ycxp7ovY6JceOvNpotK7OGAebhdHicXJ-0fWJmaq9fo,1224
|
|
8
|
-
postpone_index/utils.py,sha256=
|
|
8
|
+
postpone_index/utils.py,sha256=H_2M7IvSs1BKxvjkFanyBmX5I2iJB2KDDOAcINKlD04,4758
|
|
9
9
|
postpone_index/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
postpone_index/contrib/postgis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
postpone_index/contrib/postgis/base.py,sha256=a5h1k11BVSOflSSesTxObKAEYNWtisFLRbApzHeW3c0,289
|
|
12
12
|
postpone_index/contrib/postgis/schema.py,sha256=eantuNhFYWDngDnAeURJurpW58UztPnjTIySmUlXx7s,340
|
|
13
13
|
postpone_index/contrib/postgres/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
postpone_index/contrib/postgres/base.py,sha256=Xq90nJkxGSgR8Im9JPnFepeMb0-bur9sRjPpm3zMd6U,281
|
|
15
|
-
postpone_index/contrib/postgres/schema.py,sha256=
|
|
15
|
+
postpone_index/contrib/postgres/schema.py,sha256=tbqNy8l-YfR-h_snNaiHe2J4Uxb2JH5pZSzNDrfxtUQ,12690
|
|
16
16
|
postpone_index/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
postpone_index/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
18
|
postpone_index/management/commands/apply_postponed.py,sha256=wVbw0ugUyPuYwUikGnn5MvP9l9OsEIZja9sb6nsMtOw,9107
|
|
19
19
|
postpone_index/sql/start.sql,sha256=44yFbZTjknjXUvl7MpO1uuPv-CVBsZcnUDuKc8mVj3k,871
|
|
20
|
-
django_postpone_index-0.0.
|
|
21
|
-
django_postpone_index-0.0.
|
|
22
|
-
django_postpone_index-0.0.
|
|
23
|
-
django_postpone_index-0.0.
|
|
20
|
+
django_postpone_index-0.0.4.dist-info/METADATA,sha256=1ZnvVAhdApfcxVFNJkEKJn0m_r-1kMMHCzGB6xPrTV4,12416
|
|
21
|
+
django_postpone_index-0.0.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
22
|
+
django_postpone_index-0.0.4.dist-info/top_level.txt,sha256=B6q_TICqApvruf_NJfnLFNLZLpxMLebQF6cPdKrWm5A,162
|
|
23
|
+
django_postpone_index-0.0.4.dist-info/RECORD,,
|
postpone_index/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 4)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -118,7 +118,7 @@ class DatabaseSchemaEditorMixin(Utils):
|
|
|
118
118
|
logger.info('[%s] Removed all indexes on table %s from postponed', self.connection.alias, table_name)
|
|
119
119
|
return super().execute(sql, params)
|
|
120
120
|
elif match := self._drop_column_re.fullmatch(str(sql)):
|
|
121
|
-
#
|
|
121
|
+
# Column dropped cancels all postponed operations related
|
|
122
122
|
table_name = match.group('table_nameq') or match.group('table_name')
|
|
123
123
|
column_name = match.group('column_nameq') or match.group('column_name')
|
|
124
124
|
if PostponedSQL.objects.using(self.connection.alias).filter(
|
|
@@ -129,6 +129,37 @@ class DatabaseSchemaEditorMixin(Utils):
|
|
|
129
129
|
self.connection.alias, column_name, table_name
|
|
130
130
|
)
|
|
131
131
|
return super().execute(sql, params)
|
|
132
|
+
elif match := self._rename_column_re.fullmatch(str(sql)):
|
|
133
|
+
# Rename column changes the postponed indexes to alter SQL but not the index name
|
|
134
|
+
table_name = match.group('table_nameq') or match.group('table_name')
|
|
135
|
+
column_name = match.group('column_nameq') or match.group('column_name')
|
|
136
|
+
ncolumn_name = match.group('ncolumn_nameq') or match.group('ncolumn_name')
|
|
137
|
+
for postponed_sql in PostponedSQL.objects.using(self.connection.alias).filter(
|
|
138
|
+
table=table_name, fields__contains='"%s"' % column_name, done=False
|
|
139
|
+
):
|
|
140
|
+
logger.info(
|
|
141
|
+
'[%s] Reformat index %s SQL to rename column %s to %s of table %s from postponed',
|
|
142
|
+
self.connection.alias, postponed_sql.db_index, column_name, ncolumn_name, table_name,
|
|
143
|
+
)
|
|
144
|
+
postponed_sql.sql = postponed_sql.sql.replace('"%s"' % column_name, '"%s"' % ncolumn_name)
|
|
145
|
+
postponed_sql.fields = postponed_sql.fields.replace('"%s"' % column_name, '"%s"' % ncolumn_name)
|
|
146
|
+
postponed_sql.save(update_fields=['sql', 'fields'])
|
|
147
|
+
return super().execute(sql, params)
|
|
148
|
+
elif match := self._rename_table_re.fullmatch(str(sql)):
|
|
149
|
+
# Rename table changes the postponed indexes to alter SQL and table name but not anything other
|
|
150
|
+
table_name = match.group('table_nameq') or match.group('table_name')
|
|
151
|
+
ntable_name = match.group('ntable_nameq') or match.group('ntable_name')
|
|
152
|
+
for postponed_sql in PostponedSQL.objects.using(self.connection.alias).filter(
|
|
153
|
+
table=table_name, done=False
|
|
154
|
+
):
|
|
155
|
+
logger.info(
|
|
156
|
+
'[%s] Reformat index %s SQL to rename table %s to %s from postponed',
|
|
157
|
+
self.connection.alias, postponed_sql.db_index, table_name, ntable_name,
|
|
158
|
+
)
|
|
159
|
+
postponed_sql.sql = postponed_sql.sql.replace('"%s"' % table_name, '"%s"' % ntable_name)
|
|
160
|
+
postponed_sql.table = ntable_name
|
|
161
|
+
postponed_sql.save(update_fields=['sql', 'table'])
|
|
162
|
+
return super().execute(sql, params)
|
|
132
163
|
else:
|
|
133
164
|
logger.debug('[%s] No special statements: %s', self.connection.alias, sql)
|
|
134
165
|
return super().execute(sql, params)
|
postpone_index/models.py
CHANGED
|
@@ -4,9 +4,10 @@ import time
|
|
|
4
4
|
|
|
5
5
|
from unlimited_char.fields import CharField
|
|
6
6
|
|
|
7
|
-
from django.db import
|
|
7
|
+
from django.db import connections, models
|
|
8
8
|
from django.utils.translation import gettext_lazy as _
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
package_folder = os.path.dirname(os.path.abspath(__file__))
|
|
12
13
|
|
postpone_index/utils.py
CHANGED
|
@@ -26,7 +26,7 @@ class Utils:
|
|
|
26
26
|
r'^\s*CREATE\s+(?P<unique>UNIQUE\s+)?INDEX\s+(IF\s+NOT\s+EXISTS\s+)?'
|
|
27
27
|
r'(((?P<iq>")?(?P<index_nameq>[^"]+)(?P=iq))|(?P<index_name>[^\s]+))'
|
|
28
28
|
r'\s+ON\s+(?P<only>ONLY\s+)?'
|
|
29
|
-
r'(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[
|
|
29
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
30
30
|
r'(?P<rest>.*)$',
|
|
31
31
|
re.IGNORECASE | re.MULTILINE
|
|
32
32
|
)
|
|
@@ -38,13 +38,13 @@ class Utils:
|
|
|
38
38
|
)
|
|
39
39
|
_drop_table_re = re.compile(
|
|
40
40
|
r'^\s*DROP\s+TABLE\s+(IF\s+EXISTS\s+)?'
|
|
41
|
-
r'(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[
|
|
41
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
42
42
|
r'(?P<rest>.*)$',
|
|
43
43
|
re.IGNORECASE | re.MULTILINE
|
|
44
44
|
)
|
|
45
45
|
_add_constraint_re = re.compile(
|
|
46
46
|
r'^\s*ALTER\s+TABLE\s+'
|
|
47
|
-
r'(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[
|
|
47
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
48
48
|
r'\s+ADD\s+CONSTRAINT\s+'
|
|
49
49
|
r'(((?P<iq>")?(?P<index_nameq>[^"]+)(?P=iq))|(?P<index_name>[^\s]+))'
|
|
50
50
|
r'\s+UNIQUE\s+'
|
|
@@ -53,7 +53,7 @@ class Utils:
|
|
|
53
53
|
)
|
|
54
54
|
_drop_constraint_re = re.compile(
|
|
55
55
|
r'^\s*ALTER\s+TABLE\s+'
|
|
56
|
-
r'(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[
|
|
56
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
57
57
|
r'\s+DROP\s+CONSTRAINT\s+'
|
|
58
58
|
r'(((?P<iq>")?(?P<index_nameq>[^"]+)(?P=iq))|(?P<index_name>[^\s]+))'
|
|
59
59
|
r'(?P<rest>.*)$',
|
|
@@ -61,12 +61,30 @@ class Utils:
|
|
|
61
61
|
)
|
|
62
62
|
_drop_column_re = re.compile(
|
|
63
63
|
r'^\s*ALTER\s+TABLE\s+'
|
|
64
|
-
r'(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[
|
|
64
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
65
65
|
r'\s+DROP\s+COLUMN\s+'
|
|
66
66
|
r'(((?P<cq>")?(?P<column_nameq>[^"]+)(?P=cq))|(?P<column_name>[^\s]+))'
|
|
67
67
|
r'(?P<rest>.*)$',
|
|
68
68
|
re.IGNORECASE | re.MULTILINE
|
|
69
69
|
)
|
|
70
|
+
_rename_column_re = re.compile(
|
|
71
|
+
r'^\s*ALTER\s+TABLE\s+'
|
|
72
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
73
|
+
r'\s+RENAME\s+COLUMN\s+'
|
|
74
|
+
r'(((?P<cq>")?(?P<column_nameq>[^"]+)(?P=cq))|(?P<column_name>[^\s]+))'
|
|
75
|
+
r'\s+TO\s+'
|
|
76
|
+
r'(((?P<nq>")?(?P<ncolumn_nameq>[^"]+)(?P=nq))|(?P<ncolumn_name>[^\s]+))'
|
|
77
|
+
r'(?P<rest>.*)$',
|
|
78
|
+
re.IGNORECASE | re.MULTILINE
|
|
79
|
+
)
|
|
80
|
+
_rename_table_re = re.compile(
|
|
81
|
+
r'^\s*ALTER\s+TABLE\s+'
|
|
82
|
+
r'(("?)public("?)\.)?(((?P<tq>")?(?P<table_nameq>[^"]+)(?P=tq))|(?P<table_name>[_a-zA-Z0-9]+))'
|
|
83
|
+
r'\s+RENAME\s+TO\s+'
|
|
84
|
+
r'(((?P<nq>")?(?P<ntable_nameq>[^"]+)(?P=nq))|(?P<ntable_name>[^\s]+))'
|
|
85
|
+
r'(?P<rest>.*)$',
|
|
86
|
+
re.IGNORECASE | re.MULTILINE
|
|
87
|
+
)
|
|
70
88
|
_column_name_re = re.compile(
|
|
71
89
|
r'(((?P<cq>")(?P<column_nameq>[^"]+)(?P=cq))|(?P<column_name>[^\s]+))',
|
|
72
90
|
re.IGNORECASE | re.MULTILINE
|
|
File without changes
|
{django_postpone_index-0.0.3.dist-info → django_postpone_index-0.0.4.dist-info}/top_level.txt
RENAMED
|
File without changes
|