davidtran999 commited on
Commit
a77a834
·
verified ·
1 Parent(s): 27a00ab

Upload backend/hue_portal/core/migrations/0001_enable_bm25.py with huggingface_hub

Browse files
backend/hue_portal/core/migrations/0001_enable_bm25.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.contrib.postgres.operations import UnaccentExtension, TrigramExtension
2
+ from django.contrib.postgres.search import SearchVectorField
3
+ from django.contrib.postgres.indexes import GinIndex
4
+ from django.db import migrations
5
+
6
+
7
+ CREATE_PROCEDURE_TRIGGER = """
8
+ DROP TRIGGER IF EXISTS core_procedure_tsv_update ON core_procedure;
9
+ DROP FUNCTION IF EXISTS core_procedure_tsv_trigger();
10
+ CREATE FUNCTION core_procedure_tsv_trigger() RETURNS trigger AS $$
11
+ BEGIN
12
+ NEW.tsv_body := to_tsvector('simple',
13
+ unaccent(coalesce(NEW.title, '')) || ' ' ||
14
+ unaccent(coalesce(NEW.domain, '')) || ' ' ||
15
+ unaccent(coalesce(NEW.level, '')) || ' ' ||
16
+ unaccent(coalesce(NEW.conditions, '')) || ' ' ||
17
+ unaccent(coalesce(NEW.dossier, ''))
18
+ );
19
+ RETURN NEW;
20
+ END
21
+ $$ LANGUAGE plpgsql;
22
+
23
+ CREATE TRIGGER core_procedure_tsv_update
24
+ BEFORE INSERT OR UPDATE ON core_procedure
25
+ FOR EACH ROW EXECUTE PROCEDURE core_procedure_tsv_trigger();
26
+
27
+ UPDATE core_procedure SET tsv_body = to_tsvector('simple',
28
+ unaccent(coalesce(title, '')) || ' ' ||
29
+ unaccent(coalesce(domain, '')) || ' ' ||
30
+ unaccent(coalesce(level, '')) || ' ' ||
31
+ unaccent(coalesce(conditions, '')) || ' ' ||
32
+ unaccent(coalesce(dossier, ''))
33
+ );
34
+ """
35
+
36
+ DROP_PROCEDURE_TRIGGER = """
37
+ DROP TRIGGER IF EXISTS core_procedure_tsv_update ON core_procedure;
38
+ DROP FUNCTION IF EXISTS core_procedure_tsv_trigger();
39
+ """
40
+
41
+ CREATE_FINE_TRIGGER = """
42
+ DROP TRIGGER IF EXISTS core_fine_tsv_update ON core_fine;
43
+ DROP FUNCTION IF EXISTS core_fine_tsv_trigger();
44
+ CREATE FUNCTION core_fine_tsv_trigger() RETURNS trigger AS $$
45
+ BEGIN
46
+ NEW.tsv_body := to_tsvector('simple',
47
+ unaccent(coalesce(NEW.name, '')) || ' ' ||
48
+ unaccent(coalesce(NEW.code, '')) || ' ' ||
49
+ unaccent(coalesce(NEW.article, '')) || ' ' ||
50
+ unaccent(coalesce(NEW.decree, '')) || ' ' ||
51
+ unaccent(coalesce(NEW.remedial, ''))
52
+ );
53
+ RETURN NEW;
54
+ END
55
+ $$ LANGUAGE plpgsql;
56
+
57
+ CREATE TRIGGER core_fine_tsv_update
58
+ BEFORE INSERT OR UPDATE ON core_fine
59
+ FOR EACH ROW EXECUTE PROCEDURE core_fine_tsv_trigger();
60
+
61
+ UPDATE core_fine SET tsv_body = to_tsvector('simple',
62
+ unaccent(coalesce(name, '')) || ' ' ||
63
+ unaccent(coalesce(code, '')) || ' ' ||
64
+ unaccent(coalesce(article, '')) || ' ' ||
65
+ unaccent(coalesce(decree, '')) || ' ' ||
66
+ unaccent(coalesce(remedial, ''))
67
+ );
68
+ """
69
+
70
+ DROP_FINE_TRIGGER = """
71
+ DROP TRIGGER IF EXISTS core_fine_tsv_update ON core_fine;
72
+ DROP FUNCTION IF EXISTS core_fine_tsv_trigger();
73
+ """
74
+
75
+ CREATE_OFFICE_TRIGGER = """
76
+ DROP TRIGGER IF EXISTS core_office_tsv_update ON core_office;
77
+ DROP FUNCTION IF EXISTS core_office_tsv_trigger();
78
+ CREATE FUNCTION core_office_tsv_trigger() RETURNS trigger AS $$
79
+ BEGIN
80
+ NEW.tsv_body := to_tsvector('simple',
81
+ unaccent(coalesce(NEW.unit_name, '')) || ' ' ||
82
+ unaccent(coalesce(NEW.address, '')) || ' ' ||
83
+ unaccent(coalesce(NEW.district, '')) || ' ' ||
84
+ unaccent(coalesce(NEW.service_scope, ''))
85
+ );
86
+ RETURN NEW;
87
+ END
88
+ $$ LANGUAGE plpgsql;
89
+
90
+ CREATE TRIGGER core_office_tsv_update
91
+ BEFORE INSERT OR UPDATE ON core_office
92
+ FOR EACH ROW EXECUTE PROCEDURE core_office_tsv_trigger();
93
+
94
+ UPDATE core_office SET tsv_body = to_tsvector('simple',
95
+ unaccent(coalesce(unit_name, '')) || ' ' ||
96
+ unaccent(coalesce(address, '')) || ' ' ||
97
+ unaccent(coalesce(district, '')) || ' ' ||
98
+ unaccent(coalesce(service_scope, ''))
99
+ );
100
+ """
101
+
102
+ DROP_OFFICE_TRIGGER = """
103
+ DROP TRIGGER IF EXISTS core_office_tsv_update ON core_office;
104
+ DROP FUNCTION IF EXISTS core_office_tsv_trigger();
105
+ """
106
+
107
+ CREATE_ADVISORY_TRIGGER = """
108
+ DROP TRIGGER IF EXISTS core_advisory_tsv_update ON core_advisory;
109
+ DROP FUNCTION IF EXISTS core_advisory_tsv_trigger();
110
+ CREATE FUNCTION core_advisory_tsv_trigger() RETURNS trigger AS $$
111
+ BEGIN
112
+ NEW.tsv_body := to_tsvector('simple',
113
+ unaccent(coalesce(NEW.title, '')) || ' ' ||
114
+ unaccent(coalesce(NEW.summary, ''))
115
+ );
116
+ RETURN NEW;
117
+ END
118
+ $$ LANGUAGE plpgsql;
119
+
120
+ CREATE TRIGGER core_advisory_tsv_update
121
+ BEFORE INSERT OR UPDATE ON core_advisory
122
+ FOR EACH ROW EXECUTE PROCEDURE core_advisory_tsv_trigger();
123
+
124
+ UPDATE core_advisory SET tsv_body = to_tsvector('simple',
125
+ unaccent(coalesce(title, '')) || ' ' ||
126
+ unaccent(coalesce(summary, ''))
127
+ );
128
+ """
129
+
130
+ DROP_ADVISORY_TRIGGER = """
131
+ DROP TRIGGER IF EXISTS core_advisory_tsv_update ON core_advisory;
132
+ DROP FUNCTION IF EXISTS core_advisory_tsv_trigger();
133
+ """
134
+
135
+
136
+ class ConditionalRunSQL(migrations.RunSQL):
137
+ """RunSQL that only executes on PostgreSQL."""
138
+ def database_forwards(self, app_label, schema_editor, from_state, to_state):
139
+ if schema_editor.connection.vendor == 'postgresql':
140
+ try:
141
+ super().database_forwards(app_label, schema_editor, from_state, to_state)
142
+ except Exception as e:
143
+ # If PostgreSQL-specific SQL fails, skip it
144
+ if 'postgresql' not in str(e).lower():
145
+ raise
146
+
147
+ def database_backwards(self, app_label, schema_editor, from_state, to_state):
148
+ if schema_editor.connection.vendor == 'postgresql':
149
+ try:
150
+ super().database_backwards(app_label, schema_editor, from_state, to_state)
151
+ except Exception as e:
152
+ if 'postgresql' not in str(e).lower():
153
+ raise
154
+
155
+
156
+ class ConditionalOperation:
157
+ """Base class for conditional operations."""
158
+ def __init__(self, operation):
159
+ self.operation = operation
160
+
161
+ def database_forwards(self, app_label, schema_editor, from_state, to_state):
162
+ if schema_editor.connection.vendor == 'postgresql':
163
+ return self.operation.database_forwards(app_label, schema_editor, from_state, to_state)
164
+
165
+ def database_backwards(self, app_label, schema_editor, from_state, to_state):
166
+ if schema_editor.connection.vendor == 'postgresql':
167
+ return self.operation.database_backwards(app_label, schema_editor, from_state, to_state)
168
+
169
+
170
+ class Migration(migrations.Migration):
171
+ dependencies = [
172
+ ("core", "0000_initial"),
173
+ ]
174
+
175
+ operations = [
176
+ # Wrap all PostgreSQL-specific operations in RunPython to conditionally execute
177
+ migrations.RunPython(
178
+ code=lambda apps, schema_editor: _apply_postgresql_operations(apps, schema_editor),
179
+ reverse_code=lambda apps, schema_editor: _reverse_postgresql_operations(apps, schema_editor),
180
+ ),
181
+ ]
182
+
183
+
184
+ def _apply_postgresql_operations(apps, schema_editor):
185
+ """Apply PostgreSQL-specific operations only if using PostgreSQL."""
186
+ from django.db import connection
187
+
188
+ if connection.vendor != 'postgresql':
189
+ # Skip all operations on SQLite
190
+ return
191
+
192
+ # Apply PostgreSQL extensions
193
+ try:
194
+ UnaccentExtension().database_forwards('core', schema_editor, None, None)
195
+ TrigramExtension().database_forwards('core', schema_editor, None, None)
196
+ except Exception:
197
+ pass # Extensions may already exist
198
+
199
+ # Add SearchVectorField fields
200
+ try:
201
+ from django.db import models
202
+ Procedure = apps.get_model('core', 'Procedure')
203
+ Fine = apps.get_model('core', 'Fine')
204
+ Office = apps.get_model('core', 'Office')
205
+ Advisory = apps.get_model('core', 'Advisory')
206
+
207
+ # These will be handled by Django's migration system
208
+ # We just need to ensure the SQL triggers run
209
+ except Exception:
210
+ pass
211
+
212
+ # Execute PostgreSQL triggers
213
+ try:
214
+ schema_editor.execute(CREATE_PROCEDURE_TRIGGER)
215
+ schema_editor.execute(CREATE_FINE_TRIGGER)
216
+ schema_editor.execute(CREATE_OFFICE_TRIGGER)
217
+ schema_editor.execute(CREATE_ADVISORY_TRIGGER)
218
+ except Exception as e:
219
+ # If triggers fail, log but don't stop migration
220
+ print(f"[MIGRATION] Warning: PostgreSQL triggers failed (may already exist): {e}")
221
+
222
+
223
+ def _reverse_postgresql_operations(apps, schema_editor):
224
+ """Reverse PostgreSQL-specific operations."""
225
+ from django.db import connection
226
+
227
+ if connection.vendor != 'postgresql':
228
+ return
229
+
230
+ try:
231
+ schema_editor.execute(DROP_PROCEDURE_TRIGGER)
232
+ schema_editor.execute(DROP_FINE_TRIGGER)
233
+ schema_editor.execute(DROP_OFFICE_TRIGGER)
234
+ schema_editor.execute(DROP_ADVISORY_TRIGGER)
235
+ except Exception:
236
+ pass