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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-postpone-index
3
- Version: 0.0.3
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=pBZsQt6tlL02W-ri--X_4JCubpAK7jjCSnOmUp_isjc,704
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=Aeow27GSHCkklLnUAGnRwwaCaLrQ11b2Sg7vIZIybGg,3580
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=wYVPsQRs3LN-ZtvfSWrDDqFFp0OCkVxW9j7w9yqd47o,3823
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=qmJRxBCKfwWVrM7P2vSaaR4aAl_C6-2qMrKPiQQ9QpU,10383
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.3.dist-info/METADATA,sha256=aEo4ieeQpm90WE2j8ljOuz_F3m5pD1e0wzGBTBA4MIQ,12365
21
- django_postpone_index-0.0.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
22
- django_postpone_index-0.0.3.dist-info/top_level.txt,sha256=B6q_TICqApvruf_NJfnLFNLZLpxMLebQF6cPdKrWm5A,162
23
- django_postpone_index-0.0.3.dist-info/RECORD,,
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,,
@@ -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.3'
32
- __version_tuple__ = version_tuple = (0, 0, 3)
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
- # Table dropped cancels all postponed operations related
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 models, connections
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>[^\s]+))'
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>[^\s]+))'
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>[^\s]+))'
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>[^\s]+))'
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>[^\s]+))'
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