geovisio 2.11.0__py3-none-any.whl → 2.12.0__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.
Files changed (209) hide show
  1. geovisio/__init__.py +30 -2
  2. geovisio/admin_cli/db.py +1 -1
  3. geovisio/db_migrations.py +2 -2
  4. geovisio/migrations/20221201_01_wpCGc-initial-schema.rollback.sql +9 -0
  5. geovisio/migrations/20221201_01_wpCGc-initial-schema.sql +71 -0
  6. geovisio/migrations/20221201_02_ZG8AR-camera-information.rollback.sql +5 -0
  7. geovisio/migrations/20221201_02_ZG8AR-camera-information.sql +10 -0
  8. geovisio/migrations/20221222_01_fsB6f-add-account.rollback.sql +7 -0
  9. geovisio/migrations/20221222_01_fsB6f-add-account.sql +33 -0
  10. geovisio/migrations/20230113_01_0co97-rm-metadata-duplicates.rollback.sql +5 -0
  11. geovisio/migrations/20230113_01_0co97-rm-metadata-duplicates.sql +5 -0
  12. geovisio/migrations/20230116_01_9PkjZ-add-oauth-provider.rollback.sql +12 -0
  13. geovisio/migrations/20230116_01_9PkjZ-add-oauth-provider.sql +10 -0
  14. geovisio/migrations/20230117_01_K71Pd-pictures-ts-index.rollback.sql +4 -0
  15. geovisio/migrations/20230117_01_K71Pd-pictures-ts-index.sql +4 -0
  16. geovisio/migrations/20230130_01_VRIv2-sequences-account.rollback.sql +5 -0
  17. geovisio/migrations/20230130_01_VRIv2-sequences-account.sql +25 -0
  18. geovisio/migrations/20230324_01_ba9WA-status.rollback.sql +35 -0
  19. geovisio/migrations/20230324_01_ba9WA-status.sql +11 -0
  20. geovisio/migrations/20230324_02_efgI6-picture-process.rollback.sql +20 -0
  21. geovisio/migrations/20230324_02_efgI6-picture-process.sql +44 -0
  22. geovisio/migrations/20230407_01_wofh1-computed-headings.rollback.sql +6 -0
  23. geovisio/migrations/20230407_01_wofh1-computed-headings.sql +6 -0
  24. geovisio/migrations/20230417_01_ZgLMY-add-exif-metadata-column-for-pictures.rollback.sql +4 -0
  25. geovisio/migrations/20230417_01_ZgLMY-add-exif-metadata-column-for-pictures.sql +4 -0
  26. geovisio/migrations/20230420_01_elaN3-remove-picture-and-sequence-file-paths.rollback.sql +5 -0
  27. geovisio/migrations/20230420_01_elaN3-remove-picture-and-sequence-file-paths.sql +5 -0
  28. geovisio/migrations/20230425_01_gYP77-pictures-edits-triggers.rollback.sql +5 -0
  29. geovisio/migrations/20230425_01_gYP77-pictures-edits-triggers.sql +64 -0
  30. geovisio/migrations/20230427_01_k5e5w-timestamps.rollback.sql +10 -0
  31. geovisio/migrations/20230427_01_k5e5w-timestamps.sql +19 -0
  32. geovisio/migrations/20230511_01_TdpKo-tokens.rollback.sql +7 -0
  33. geovisio/migrations/20230511_01_TdpKo-tokens.sql +34 -0
  34. geovisio/migrations/20230615_01_u7aRf-pic-delete-cascade.rollback.sql +10 -0
  35. geovisio/migrations/20230615_01_u7aRf-pic-delete-cascade.sql +12 -0
  36. geovisio/migrations/20230623_01_y1SiQ-pic-deletion-task.rollback.sql +39 -0
  37. geovisio/migrations/20230623_01_y1SiQ-pic-deletion-task.sql +36 -0
  38. geovisio/migrations/20230629_01_ZdB3i-compute-heading-0.sql +27 -0
  39. geovisio/migrations/20230711_01_JGSPB-inserted-at-index.rollback.sql +4 -0
  40. geovisio/migrations/20230711_01_JGSPB-inserted-at-index.sql +4 -0
  41. geovisio/migrations/20230720_01_EyQ0e-sequences-summary.rollback.sql +7 -0
  42. geovisio/migrations/20230720_01_EyQ0e-sequences-summary.sql +26 -0
  43. geovisio/migrations/20230803_01_aXusm-fix-sequence-computed.rollback.sql +4 -0
  44. geovisio/migrations/20230803_01_aXusm-fix-sequence-computed.sql +25 -0
  45. geovisio/migrations/20231018_01_4G3YE-pictures-exiv2.rollback.sql +165 -0
  46. geovisio/migrations/20231018_01_4G3YE-pictures-exiv2.sql +206 -0
  47. geovisio/migrations/20231103_01_ZVKEm-update-seq-on-pic-change.rollback.sql +7 -0
  48. geovisio/migrations/20231103_01_ZVKEm-update-seq-on-pic-change.sql +28 -0
  49. geovisio/migrations/20231110_01_3p070-jobs-error.rollback.sql +7 -0
  50. geovisio/migrations/20231110_01_3p070-jobs-error.sql +93 -0
  51. geovisio/migrations/20231121_01_v6oBF-more-specific-triggers.rollback.sql +36 -0
  52. geovisio/migrations/20231121_01_v6oBF-more-specific-triggers.sql +40 -0
  53. geovisio/migrations/20231121_02_1uZXT-deleted-tag.rollback.sql +19 -0
  54. geovisio/migrations/20231121_02_1uZXT-deleted-tag.sql +13 -0
  55. geovisio/migrations/20240115_01_FatLR-token-delete-cascade.rollback.sql +6 -0
  56. geovisio/migrations/20240115_01_FatLR-token-delete-cascade.sql +7 -0
  57. geovisio/migrations/20240220_01_9wZs0-sequence-current-sort.rollback.sql +6 -0
  58. geovisio/migrations/20240220_01_9wZs0-sequence-current-sort.sql +15 -0
  59. geovisio/migrations/20240223_01_LsMHB-remove-binary-fields.sql +80 -0
  60. geovisio/migrations/20240226_01_8iXl1-track-changes.rollback.sql +13 -0
  61. geovisio/migrations/20240226_01_8iXl1-track-changes.sql +123 -0
  62. geovisio/migrations/20240229_01_SgfQY-sequence-geom-multi-linestring.rollback.sql +67 -0
  63. geovisio/migrations/20240229_01_SgfQY-sequence-geom-multi-linestring.sql +101 -0
  64. geovisio/migrations/20240308_01_aF0Jb-migrate-sequence-geom-multi-linestring.sql +52 -0
  65. geovisio/migrations/20240409_01_jnhra-pictures-grid.rollback.sql +3 -0
  66. geovisio/migrations/20240409_01_jnhra-pictures-grid.sql +21 -0
  67. geovisio/migrations/20240416_01_FpyGs-pictures-stats-on-sequences.rollback.sql +7 -0
  68. geovisio/migrations/20240416_01_FpyGs-pictures-stats-on-sequences.sql +9 -0
  69. geovisio/migrations/20240416_02_A5KzC-fill-pictures-stats-on-sequences.rollback.sql +5 -0
  70. geovisio/migrations/20240416_02_A5KzC-fill-pictures-stats-on-sequences.sql +84 -0
  71. geovisio/migrations/20240507_01_eBfqZ-refresh-table.rollback.sql +5 -0
  72. geovisio/migrations/20240507_01_eBfqZ-refresh-table.sql +9 -0
  73. geovisio/migrations/20240507_02_dzVET-picture-grid-public.rollback.sql +21 -0
  74. geovisio/migrations/20240507_02_dzVET-picture-grid-public.sql +26 -0
  75. geovisio/migrations/20240514_01_IT7DD-picture-delete-cascade.rollback.sql +41 -0
  76. geovisio/migrations/20240514_01_IT7DD-picture-delete-cascade.sql +42 -0
  77. geovisio/migrations/20240611_01_jftHn-content-md5.rollback.sql +5 -0
  78. geovisio/migrations/20240611_01_jftHn-content-md5.sql +7 -0
  79. geovisio/migrations/20240612_01_yNcuE-upload-set.rollback.sql +6 -0
  80. geovisio/migrations/20240612_01_yNcuE-upload-set.sql +46 -0
  81. geovisio/migrations/20240617_01_tKtlx-md5-concurrent-index.rollback.sql +4 -0
  82. geovisio/migrations/20240617_01_tKtlx-md5-concurrent-index.sql +8 -0
  83. geovisio/migrations/20240625_01_XMZ24-fix-sequence-stat-on-pic-insertion.rollback.sql +30 -0
  84. geovisio/migrations/20240625_01_XMZ24-fix-sequence-stat-on-pic-insertion.sql +31 -0
  85. geovisio/migrations/20240708_01_Xn7IH-job-queue.rollback.sql +31 -0
  86. geovisio/migrations/20240708_01_Xn7IH-job-queue.sql +104 -0
  87. geovisio/migrations/20240715_01_Hca9V-upload-set-metadata.rollback.sql +4 -0
  88. geovisio/migrations/20240715_01_Hca9V-upload-set-metadata.sql +5 -0
  89. geovisio/migrations/20240723_01_ePGFe-upload-set-files.rollback.sql +7 -0
  90. geovisio/migrations/20240723_01_ePGFe-upload-set-files.sql +29 -0
  91. geovisio/migrations/20240729_01_HALjj-upload-set-sort.rollback.sql +18 -0
  92. geovisio/migrations/20240729_01_HALjj-upload-set-sort.sql +18 -0
  93. geovisio/migrations/20240730_01_2BaCy-improve-deletion-triggers.rollback.sql +34 -0
  94. geovisio/migrations/20240730_01_2BaCy-improve-deletion-triggers.sql +53 -0
  95. geovisio/migrations/20240730_02_aRymN-rejection-status.rollback.sql +10 -0
  96. geovisio/migrations/20240730_02_aRymN-rejection-status.sql +16 -0
  97. geovisio/migrations/20240801_01_DOqmf-reports.rollback.sql +11 -0
  98. geovisio/migrations/20240801_01_DOqmf-reports.sql +100 -0
  99. geovisio/migrations/20240801_01_uKqPo-remove-files-delete-cascade.rollback.sql +13 -0
  100. geovisio/migrations/20240801_01_uKqPo-remove-files-delete-cascade.sql +13 -0
  101. geovisio/migrations/20240813_01_T1XkO-sequences-geom-splits.rollback.sql +42 -0
  102. geovisio/migrations/20240813_01_T1XkO-sequences-geom-splits.sql +56 -0
  103. geovisio/migrations/20240820_01_aB2ZK-exclusion-zones.rollback.sql +6 -0
  104. geovisio/migrations/20240820_01_aB2ZK-exclusion-zones.sql +49 -0
  105. geovisio/migrations/20240902_01_MDqSj-user-agent.rollback.sql +5 -0
  106. geovisio/migrations/20240902_01_MDqSj-user-agent.sql +10 -0
  107. geovisio/migrations/20240904_01_gFjlV-files-rejection-msg.rollback.sql +4 -0
  108. geovisio/migrations/20240904_01_gFjlV-files-rejection-msg.sql +4 -0
  109. geovisio/migrations/20240905_01_C8F6U-conflicts.rollback.sql +13 -0
  110. geovisio/migrations/20240905_01_C8F6U-conflicts.sql +6 -0
  111. geovisio/migrations/20240905_01_E5Ki0-upload-set-delete.rollback.sql +5 -0
  112. geovisio/migrations/20240905_01_E5Ki0-upload-set-delete.sql +30 -0
  113. geovisio/migrations/20240909_01_Muc22-unique-grid-index.rollback.sql +4 -0
  114. geovisio/migrations/20240909_01_Muc22-unique-grid-index.sql +5 -0
  115. geovisio/migrations/20240912_01_dAALm-account-index.rollback.sql +4 -0
  116. geovisio/migrations/20240912_01_dAALm-account-index.sql +4 -0
  117. geovisio/migrations/20241004_01_d1zfe-pictures-grid-360.rollback.sql +22 -0
  118. geovisio/migrations/20241004_01_d1zfe-pictures-grid-360.sql +24 -0
  119. geovisio/migrations/20241011_01_e1j5C-pic-quality.rollback.sql +21 -0
  120. geovisio/migrations/20241011_01_e1j5C-pic-quality.sql +249 -0
  121. geovisio/migrations/20241017_01_GuOjF-pic-quality-update.rollback.sql +4 -0
  122. geovisio/migrations/20241017_01_GuOjF-pic-quality-update.sql +61 -0
  123. geovisio/migrations/20241017_01_RiFlm-pictures-to-delete.rollback.sql +43 -0
  124. geovisio/migrations/20241017_01_RiFlm-pictures-to-delete.sql +75 -0
  125. geovisio/migrations/20241104_01_yhRVu-rejection-details.rollback.sql +4 -0
  126. geovisio/migrations/20241104_01_yhRVu-rejection-details.sql +4 -0
  127. geovisio/migrations/20241128_01_ugthx-job-queue-args.rollback.sql +25 -0
  128. geovisio/migrations/20241128_01_ugthx-job-queue-args.sql +31 -0
  129. geovisio/migrations/20241224_01_xuN6n-delete-upload-set-on-last-picture-trg-statement.rollback.sql +27 -0
  130. geovisio/migrations/20241224_01_xuN6n-delete-upload-set-on-last-picture-trg-statement.sql +28 -0
  131. geovisio/migrations/20250102_01_EElhA-rm-cameras.rollback.sql +126 -0
  132. geovisio/migrations/20250102_01_EElhA-rm-cameras.sql +30 -0
  133. geovisio/migrations/20250107_01_EQN9v-tags-tables.rollback.sql +10 -0
  134. geovisio/migrations/20250107_01_EQN9v-tags-tables.sql +58 -0
  135. geovisio/migrations/20250109_01_4OOP4-pages.rollback.sql +4 -0
  136. geovisio/migrations/20250109_01_4OOP4-pages.sql +10 -0
  137. geovisio/migrations/20250114_01_ABaaL-collaborative-metadata-editing.rollback.sql +7 -0
  138. geovisio/migrations/20250114_01_ABaaL-collaborative-metadata-editing.sql +16 -0
  139. geovisio/migrations/20250123_01_Ececu-tos-acceptance.rollback.sql +5 -0
  140. geovisio/migrations/20250123_01_Ececu-tos-acceptance.sql +5 -0
  141. geovisio/migrations/20250206_01_PjrEL-annotation-semantics.rollback.sql +14 -0
  142. geovisio/migrations/20250206_01_PjrEL-annotation-semantics.sql +15 -0
  143. geovisio/migrations/20250306_01_58oju-semantics-views.rollback.sql +5 -0
  144. geovisio/migrations/20250306_01_58oju-semantics-views.sql +52 -0
  145. geovisio/migrations/20250318_01_pANl1-semantics-functions.rollback.sql +5 -0
  146. geovisio/migrations/20250318_01_pANl1-semantics-functions.sql +41 -0
  147. geovisio/migrations/20250331_01_kRKjo-store-detections-id.rollback.sql +7 -0
  148. geovisio/migrations/20250331_01_kRKjo-store-detections-id.sql +25 -0
  149. geovisio/migrations/20250424_01_RBGXC-semantics-indexes.rollback.sql +6 -0
  150. geovisio/migrations/20250424_01_RBGXC-semantics-indexes.sql +6 -0
  151. geovisio/migrations/20250502_01_ZNmkU-job-task-read-metadata.rollback.sql +24 -0
  152. geovisio/migrations/20250502_01_ZNmkU-job-task-read-metadata.sql +7 -0
  153. geovisio/migrations/20250509_01_kMatW-deactivate-upload-set-split-dedup.rollback.sql +12 -0
  154. geovisio/migrations/20250509_01_kMatW-deactivate-upload-set-split-dedup.sql +12 -0
  155. geovisio/migrations/20250509_01_s3hYk-semantic-delete-cascade.rollback.sql +11 -0
  156. geovisio/migrations/20250509_01_s3hYk-semantic-delete-cascade.sql +11 -0
  157. geovisio/migrations/20250513_01_8WkZC-upload-sets-default-config.rollback.sql +7 -0
  158. geovisio/migrations/20250513_01_8WkZC-upload-sets-default-config.sql +15 -0
  159. geovisio/migrations/20250523_01_b11eW-picture-update-index.rollback.sql +85 -0
  160. geovisio/migrations/20250523_01_b11eW-picture-update-index.sql +166 -0
  161. geovisio/migrations/20250523_02_5ZXXh-update-picture-updated-at.rollback.sql +4 -0
  162. geovisio/migrations/20250523_02_5ZXXh-update-picture-updated-at.sql +7 -0
  163. geovisio/migrations/20250624_01_SETp6-job-warnings.rollback.sql +4 -0
  164. geovisio/migrations/20250624_01_SETp6-job-warnings.sql +4 -0
  165. geovisio/migrations/20250701_01_kr371-upload-set-semantics.rollback.sql +6 -0
  166. geovisio/migrations/20250701_01_kr371-upload-set-semantics.sql +15 -0
  167. geovisio/migrations/20250703_01_p2WVV-sequence-upload-set-link.rollback.sql +4 -0
  168. geovisio/migrations/20250703_01_p2WVV-sequence-upload-set-link.sql +4 -0
  169. geovisio/migrations/20250703_02_q0s3D-sequence-upload-set-fill.rollback.sql +4 -0
  170. geovisio/migrations/20250703_02_q0s3D-sequence-upload-set-fill.sql +26 -0
  171. geovisio/migrations/20250716_01_f8tcJ-check-empty-annotation-late.rollback.sql +24 -0
  172. geovisio/migrations/20250716_01_f8tcJ-check-empty-annotation-late.sql +10 -0
  173. geovisio/migrations/20250728_01_2zgur-upload-set-relative-heading.rollback.sql +4 -0
  174. geovisio/migrations/20250728_01_2zgur-upload-set-relative-heading.sql +4 -0
  175. geovisio/migrations/20250825_01_nCgkN-file-deletion-after-delete-no-dup.rollback.sql +20 -0
  176. geovisio/migrations/20250825_01_nCgkN-file-deletion-after-delete-no-dup.sql +26 -0
  177. geovisio/migrations/20250902_01_k5UTq-visibility-status.rollback.sql +11 -0
  178. geovisio/migrations/20250902_01_k5UTq-visibility-status.sql +19 -0
  179. geovisio/migrations/20250904_01_3uVKX-visibility-functions.rollback.sql +20 -0
  180. geovisio/migrations/20250904_01_3uVKX-visibility-functions.sql +43 -0
  181. geovisio/migrations/20251110_01_bWEXo-report-visibility.rollback.sql +30 -0
  182. geovisio/migrations/20251110_01_bWEXo-report-visibility.sql +30 -0
  183. geovisio/migrations/20251124_01_0xdqi-page-updates.rollback.sql +6 -0
  184. geovisio/migrations/20251124_01_0xdqi-page-updates.sql +8 -0
  185. geovisio/migrations/20251127_01_S6Ci8-pictures-grid-visibility.rollback.sql +24 -0
  186. geovisio/migrations/20251127_01_S6Ci8-pictures-grid-visibility.sql +36 -0
  187. geovisio/migrations/20251202_01_Q3g59-pictures-grid-logged-only.rollback.sql +32 -0
  188. geovisio/migrations/20251202_01_Q3g59-pictures-grid-logged-only.sql +34 -0
  189. geovisio/templates/main.html +7 -58
  190. geovisio/templates/viewer.html +8 -15
  191. geovisio/translations/cy/LC_MESSAGES/messages.mo +0 -0
  192. geovisio/translations/cy/LC_MESSAGES/messages.po +839 -0
  193. geovisio/translations/en/LC_MESSAGES/messages.mo +0 -0
  194. geovisio/translations/en/LC_MESSAGES/messages.po +155 -149
  195. geovisio/translations/messages.pot +131 -150
  196. geovisio/utils/cql2.py +22 -17
  197. geovisio/utils/link.py +13 -3
  198. geovisio/utils/upload_set.py +42 -2
  199. geovisio/web/collections.py +80 -40
  200. geovisio/web/docs.py +1 -1
  201. geovisio/web/items.py +54 -4
  202. geovisio/web/upload_set.py +2 -3
  203. geovisio/web/users.py +1 -1
  204. {geovisio-2.11.0.dist-info → geovisio-2.12.0.dist-info}/METADATA +6 -26
  205. geovisio-2.12.0.dist-info/RECORD +305 -0
  206. geovisio-2.12.0.dist-info/entry_points.txt +3 -0
  207. geovisio-2.11.0.dist-info/RECORD +0 -117
  208. {geovisio-2.11.0.dist-info → geovisio-2.12.0.dist-info}/WHEEL +0 -0
  209. {geovisio-2.11.0.dist-info → geovisio-2.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,93 @@
1
+ -- jobs_error
2
+ -- depends: 20231103_01_ZVKEm-update-seq-on-pic-change
3
+ -- transactional: false
4
+ -- Note: this migration is not in a transaction, since the transactions will be created inside it to update the `pictures` table (which can be very big) in batches
5
+
6
+
7
+ -- Add a job_history tables to log all async jobs
8
+ -- Note: error replace `pictures.process_error` and `pictures_to_process.nb_errors` replace `pictures.nb_errors`
9
+ -- Those fields are note removed right away for a smooth database migration transition, but should be removed afterward
10
+
11
+
12
+ CREATE TABLE job_history(
13
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
14
+ picture_id UUID NOT NULL REFERENCES pictures(id) ON DELETE CASCADE,
15
+ task picture_process_task,
16
+ started_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
17
+ finished_at TIMESTAMPTZ,
18
+ error VARCHAR
19
+ );
20
+
21
+
22
+
23
+ CREATE INDEX job_history_picture_id_idx ON job_history(picture_id);
24
+
25
+ ALTER TABLE pictures_to_process ADD COLUMN nb_errors INT NOT NULL DEFAULT 0;
26
+
27
+ CREATE INDEX pictures_to_process_nb_errors_ts_idx ON pictures_to_process(nb_errors, ts);
28
+
29
+ CREATE TYPE picture_preparing_status AS ENUM (
30
+ 'not-processed', -- Default state, the picture has not been processed yet
31
+ 'prepared', -- State when the picture has been correctly prepared
32
+ 'broken' -- State when the picture has not been correctly processed
33
+ );
34
+
35
+ ALTER TABLE pictures ADD COLUMN preparing_status picture_preparing_status NOT NULL DEFAULT 'not-processed';
36
+
37
+ CREATE OR REPLACE PROCEDURE update_all_pictures_preparing_status() AS
38
+ $$
39
+ DECLARE
40
+ last_inserted_at TIMESTAMPTZ;
41
+ BEGIN
42
+ SELECT min(inserted_at) - INTERVAL '1 minute' FROM pictures INTO last_inserted_at;
43
+
44
+ WHILE last_inserted_at IS NOT NULL LOOP
45
+
46
+ -- remove triggers on picture before updating the table
47
+ DROP TRIGGER pictures_update_sequences_trg ON pictures;
48
+ DROP TRIGGER pictures_updates_on_sequences_trg ON pictures;
49
+
50
+ WITH
51
+ pic_to_update AS (
52
+ SELECT id, inserted_at from pictures where inserted_at > last_inserted_at ORDER BY inserted_at ASC LIMIT 100000
53
+ )
54
+ , updated_pic AS (
55
+ -- Populate table with values based on the `status` column
56
+ UPDATE pictures
57
+ SET preparing_status =
58
+ CASE
59
+ WHEN status IN ('hidden', 'ready') THEN 'prepared'::picture_preparing_status
60
+ WHEN status = 'broken' THEN 'broken'::picture_preparing_status
61
+ ELSE 'not-processed'
62
+ END
63
+ WHERE id in (SELECT id FROM pic_to_update)
64
+ )
65
+ SELECT MAX(inserted_at) FROM pic_to_update INTO last_inserted_at;
66
+
67
+ RAISE NOTICE 'max insertion date is now %', last_inserted_at;
68
+
69
+ -- put back triggers
70
+ CREATE TRIGGER pictures_updates_on_sequences_trg
71
+ AFTER UPDATE ON pictures
72
+ REFERENCING NEW TABLE AS pictures_after
73
+ FOR EACH STATEMENT
74
+ EXECUTE FUNCTION pictures_updates_on_sequences();
75
+
76
+ CREATE TRIGGER pictures_update_sequences_trg
77
+ AFTER UPDATE ON pictures
78
+ REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
79
+ FOR EACH STATEMENT EXECUTE FUNCTION pictures_update_sequence();
80
+
81
+ -- commit batch of change
82
+ COMMIT;
83
+ END LOOP;
84
+
85
+ RAISE NOTICE 'update finished';
86
+ END
87
+ $$ LANGUAGE plpgsql;
88
+
89
+ CALL update_all_pictures_preparing_status();
90
+
91
+ DROP PROCEDURE update_all_pictures_preparing_status;
92
+
93
+ CREATE INDEX pictures_preparing_status_idx ON pictures(preparing_status);
@@ -0,0 +1,36 @@
1
+ -- more specific triggers
2
+ -- depends: 20231110_01_3p070-jobs-error
3
+
4
+ -- put old version of the triggers
5
+
6
+ DROP FUNCTION IF EXISTS pictures_update_sequence CASCADE;
7
+ CREATE FUNCTION pictures_update_sequence() RETURNS trigger AS $$
8
+ BEGIN
9
+ UPDATE sequences
10
+ SET geom = s.geom
11
+ FROM (
12
+ SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
13
+ FROM (
14
+ SELECT sp.seq_id, sp.rank, p.geom
15
+ FROM sequences_pictures sp
16
+ JOIN pictures p ON sp.pic_id = p.id
17
+ WHERE sp.seq_id IN (
18
+ SELECT DISTINCT sequences_pictures.seq_id
19
+ FROM old_table
20
+ JOIN new_table USING (id)
21
+ JOIN sequences_pictures ON sequences_pictures.pic_id = new_table.id
22
+ WHERE new_table.status != old_table.status OR NOT ST_Equals(old_table.geom, new_table.geom)
23
+ )
24
+ ORDER BY sp.seq_id, sp.rank
25
+ ) sp
26
+ GROUP BY seq_id
27
+ ) s
28
+ WHERE sequences.id = s.seq_id;
29
+ RETURN NULL;
30
+ END $$ LANGUAGE plpgsql;
31
+
32
+ CREATE TRIGGER pictures_update_sequences_trg
33
+ AFTER UPDATE ON pictures
34
+ REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
35
+ FOR EACH STATEMENT EXECUTE FUNCTION pictures_update_sequence();
36
+
@@ -0,0 +1,40 @@
1
+ -- more specific triggers
2
+ -- depends: 20231110_01_3p070-jobs-error
3
+
4
+ -- Add more specific names and conditions on the trigger on pictures
5
+
6
+
7
+ -- This trigger only update the sequence geometry, so we can fire it only on update of geom
8
+ DROP TRIGGER pictures_update_sequences_trg ON pictures;
9
+
10
+ -- The function need to be changed since we now only triggers it from 1 column change, and in the meantime rename the function to a more specific name
11
+ -- In the meantime, rename the function to be more specific
12
+ DROP FUNCTION IF EXISTS pictures_update_sequence CASCADE;
13
+ DROP FUNCTION IF EXISTS pictures_update_geom_sequence CASCADE;
14
+ CREATE FUNCTION pictures_update_geom_sequence() RETURNS trigger AS $$
15
+ BEGIN
16
+ UPDATE sequences
17
+ SET geom = s.geom
18
+ FROM (
19
+ SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
20
+ FROM (
21
+ SELECT sp.seq_id, p.geom
22
+ FROM sequences_pictures sp
23
+ JOIN pictures p ON sp.pic_id = p.id
24
+ WHERE sp.seq_id IN (
25
+ SELECT DISTINCT sequences_pictures.seq_id
26
+ FROM sequences_pictures
27
+ WHERE sequences_pictures.pic_id = NEW.id
28
+ )
29
+ ORDER BY sp.seq_id, sp.rank
30
+ ) sp
31
+ GROUP BY seq_id
32
+ ) s
33
+ WHERE sequences.id = s.seq_id;
34
+ RETURN NULL;
35
+ END $$ LANGUAGE plpgsql;
36
+
37
+ CREATE TRIGGER pictures_update_sequences_geom_trg
38
+ AFTER UPDATE OF geom ON pictures
39
+ FOR EACH ROW EXECUTE FUNCTION pictures_update_geom_sequence();
40
+
@@ -0,0 +1,19 @@
1
+ -- deleted_tag
2
+ -- depends: 20231121_01_v6oBF-more-specific-triggers
3
+
4
+ -- since PG does not support removing values from enum, we create a new sequence status with old values
5
+
6
+ CREATE TYPE sequence_status_new AS ENUM (
7
+ 'preparing',
8
+ 'broken',
9
+ 'ready',
10
+ 'hidden',
11
+ 'waiting-for-process'
12
+ );
13
+
14
+ alter table sequences ALTER COLUMN status DROP DEFAULT;
15
+ alter table sequences ALTER COLUMN status TYPE sequence_status_new USING status::text::sequence_status_new;
16
+ alter table sequences ALTER COLUMN status SET DEFAULT 'waiting-for-process';
17
+
18
+ DROP TYPE sequence_status;
19
+ ALTER TYPE sequence_status_new RENAME TO sequence_status;
@@ -0,0 +1,13 @@
1
+ -- deleted_tag
2
+ -- depends: 20231121_01_v6oBF-more-specific-triggers
3
+
4
+ -- type cannot be altered in a transaction, so we ask yolo not to create one
5
+ -- transactional: false
6
+
7
+ ALTER TYPE sequence_status ADD VALUE 'deleted';
8
+
9
+
10
+ CREATE OR REPLACE FUNCTION is_sequence_visible_by_user(seq sequences, account_id UUID) RETURNS boolean AS $$
11
+ SELECT seq.status != 'deleted' AND (seq.status = 'ready' OR seq.account_id = account_id);
12
+ $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE COST 10;
13
+
@@ -0,0 +1,6 @@
1
+ -- token_delete_cascade
2
+ -- depends: 20231121_02_1uZXT-deleted-tag
3
+
4
+ ALTER TABLE tokens
5
+ DROP CONSTRAINT account_fk_id ,
6
+ ADD CONSTRAINT account_fk_id FOREIGN KEY (account_id) REFERENCES accounts(id);
@@ -0,0 +1,7 @@
1
+ -- token_delete_cascade
2
+ -- depends: 20231121_02_1uZXT-deleted-tag
3
+
4
+
5
+ ALTER TABLE tokens
6
+ DROP CONSTRAINT account_fk_id ,
7
+ ADD CONSTRAINT account_fk_id FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE;
@@ -0,0 +1,6 @@
1
+ -- sequence_current_sort
2
+ -- depends: 20240115_01_FatLR-token-delete-cascade
3
+
4
+ ALTER TABLE sequences DROP COLUMN current_sort;
5
+
6
+ DROP TYPE sequence_sort;
@@ -0,0 +1,15 @@
1
+ -- sequence_current_sort
2
+ -- depends: 20240115_01_FatLR-token-delete-cascade
3
+
4
+ CREATE TYPE sequence_sort AS ENUM (
5
+ '+filedate', -- Sort by ascending camera date
6
+ '+filename', -- Sort by ascending filename
7
+ '+gpsdate', -- Sort by ascending gps date
8
+ '-filedate', -- Sort by descending camera date
9
+ '-filename', -- Sort by descending filename
10
+ '-gpsdate' -- Sort by descending gps date
11
+ );
12
+
13
+ -- Add a column to persist the user defined sort
14
+ -- nullable since by default no sort is chosen
15
+ ALTER TABLE sequences ADD COLUMN current_sort sequence_sort;
@@ -0,0 +1,80 @@
1
+ -- remove_binary_fields
2
+ -- depends: 20240115_01_FatLR-token-delete-cascade
3
+
4
+ -- We want to run a vacuum after the migration, we cannot have a transaction around it
5
+ -- transactional: false
6
+
7
+ CREATE OR REPLACE PROCEDURE remove_maker_notes_from_all_pictures() AS
8
+ $$
9
+ DECLARE
10
+ last_inserted_at TIMESTAMPTZ;
11
+ BEGIN
12
+ SELECT min(inserted_at) - INTERVAL '1 minute' FROM pictures INTO last_inserted_at;
13
+
14
+ WHILE last_inserted_at IS NOT NULL LOOP
15
+
16
+ -- Temporary removal of all update triggers
17
+ DROP TRIGGER pictures_updates_on_sequences_trg ON pictures;
18
+
19
+ WITH
20
+ -- get a batch of 100 000 pictures to update
21
+ pic_to_update AS (
22
+ SELECT id, inserted_at from pictures where inserted_at > last_inserted_at ORDER BY inserted_at ASC LIMIT 100000
23
+ )
24
+ , updated_pic AS (
25
+ -- List of binary fields to remove.
26
+ -- The most important here is `MakerNote` that takes a lot of useless space, but we decided not to store any binary fields, as they will be difficult to use
27
+ -- Note: they are still in the pictures if needed
28
+ UPDATE pictures
29
+ SET
30
+ exif = exif - ARRAY[
31
+ 'Exif.Photo.MakerNote',
32
+ 'Exif.Photo.0xea1c',
33
+ 'Exif.Image.0xea1c',
34
+ 'Exif.Canon.CameraInfo',
35
+ 'Exif.Image.PrintImageMatching',
36
+ 'Exif.Image.0xc6d3',
37
+ 'Exif.Panasonic.FaceDetInfo',
38
+ 'Exif.Panasonic.DataDump',
39
+ 'Exif.Image.0xc6d2',
40
+ 'Exif.Canon.CustomFunctions',
41
+ 'Exif.Canon.AFInfo',
42
+ 'Exif.Canon.0x4011',
43
+ 'Exif.Canon.0x4019',
44
+ 'Exif.Canon.ColorData',
45
+ 'Exif.Canon.DustRemovalData',
46
+ 'Exif.Canon.VignettingCorr',
47
+ 'Exif.Canon.AFInfo3',
48
+ 'Exif.Canon.0x001f',
49
+ 'Exif.Canon.0x0018',
50
+ 'Exif.Canon.ContrastInfo',
51
+ 'Exif.Canon.0x002e',
52
+ 'Exif.Canon.0x0022',
53
+ 'Exif.Photo.0x9aaa'
54
+ ]
55
+ WHERE id in (SELECT id FROM pic_to_update)
56
+ )
57
+ SELECT MAX(inserted_at) FROM pic_to_update INTO last_inserted_at;
58
+
59
+ RAISE NOTICE 'max insertion date is now %', last_inserted_at;
60
+
61
+ -- Restore all deactivated triggers
62
+ CREATE TRIGGER pictures_updates_on_sequences_trg
63
+ AFTER UPDATE ON pictures
64
+ REFERENCING NEW TABLE AS pictures_after
65
+ FOR EACH STATEMENT
66
+ EXECUTE FUNCTION pictures_updates_on_sequences();
67
+
68
+ -- commit transaction (as a procedure is in an implicit transaction, it will start a new transaction after this)
69
+ COMMIT;
70
+ END LOOP;
71
+
72
+ -- After this, we need to do a full vacuum to clean dead tuples
73
+ RAISE NOTICE 'Binary fields removed, you should run `VACUUM FULL pictures;` afterward (or use something like pg_repack)';
74
+
75
+ END
76
+ $$ LANGUAGE plpgsql;
77
+
78
+ CALL remove_maker_notes_from_all_pictures();
79
+ DROP PROCEDURE remove_maker_notes_from_all_pictures;
80
+
@@ -0,0 +1,13 @@
1
+ -- track_changes
2
+ -- depends: 20240220_01_9wZs0-sequence-current-sort
3
+
4
+ DROP TABLE sequences_changes CASCADE;
5
+ DROP TABLE pictures_changes CASCADE;
6
+
7
+ DROP TRIGGER picture_modification_history_trg ON pictures;
8
+ DROP TRIGGER sequence_modification_history_trg ON sequences;
9
+
10
+ DROP FUNCTION IF EXISTS jsonb_diff, get_sequence_diffable_fields, sequence_modification_history, picture_modification_history CASCADE;
11
+
12
+ ALTER TABLE sequences DROP COLUMN IF EXISTS last_account_to_edit;
13
+ ALTER TABLE pictures DROP COLUMN IF EXISTS last_account_to_edit;
@@ -0,0 +1,123 @@
1
+ -- track_changes
2
+ -- depends: 20240220_01_9wZs0-sequence-current-sort
3
+
4
+ CREATE TABLE sequences_changes(
5
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
6
+ sequence_id UUID NOT NULL REFERENCES sequences(id) ON DELETE CASCADE,
7
+ account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
8
+
9
+ -- json will contains all modified keys, with old db values
10
+ previous_value_changed JSONB,
11
+
12
+ ts TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
13
+ );
14
+
15
+ CREATE INDEX sequences_changes_seq_id_idx ON sequences_changes(sequence_id);
16
+
17
+ CREATE TABLE pictures_changes(
18
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
19
+ picture_id UUID NOT NULL REFERENCES pictures(id) ON DELETE CASCADE,
20
+ account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
21
+ -- If the changes is part of global changes on a sequence, id of that change
22
+ sequences_changes_id UUID REFERENCES sequences_changes(id),
23
+
24
+ -- json will contains all modified keys, with old db values
25
+ previous_value_changed JSONB,
26
+
27
+ ts TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
28
+ );
29
+ CREATE INDEX pictures_changes_pic_id_idx ON pictures_changes(picture_id);
30
+
31
+
32
+ ALTER TABLE sequences ADD COLUMN IF NOT EXISTS last_account_to_edit UUID;
33
+ ALTER TABLE sequences ADD CONSTRAINT last_account_to_edit_fk_id FOREIGN KEY (last_account_to_edit) REFERENCES accounts (id) ON DELETE CASCADE;
34
+
35
+ ALTER TABLE pictures ADD COLUMN IF NOT EXISTS last_account_to_edit UUID;
36
+ ALTER TABLE pictures ADD CONSTRAINT last_account_to_edit_fk_id FOREIGN KEY (last_account_to_edit) REFERENCES accounts (id) ON DELETE CASCADE;
37
+
38
+ CREATE OR REPLACE FUNCTION jsonb_diff(IN a jsonb, IN b jsonb) RETURNS jsonb AS
39
+ $BODY$
40
+ SELECT jsonb_object_agg(key, value)
41
+ FROM (
42
+ SELECT * FROM jsonb_each(to_jsonb(a))
43
+ EXCEPT SELECT * FROM jsonb_each(to_jsonb(b))
44
+ ) as t;
45
+ $BODY$
46
+ LANGUAGE SQL IMMUTABLE STRICT;
47
+
48
+ COMMENT ON FUNCTION jsonb_diff IS 'Create a Json with all the key/values that are in the first one and not in the second. Only works for top level fields';
49
+
50
+ -- We only consider a specified set of fields. If we want to track the history of a new field, a new migration should add them here
51
+ -- We also put the metadata fields at the same level in order not to have a nested `metadata` field inside, since it would make comparison more difficult
52
+ CREATE OR REPLACE FUNCTION get_sequence_diffable_fields(IN seq sequences) RETURNS jsonb AS
53
+ $BODY$
54
+ SELECT jsonb_build_object(
55
+ 'status', seq.status,
56
+ 'current_sort', seq.current_sort
57
+ ) || seq.metadata;
58
+ $BODY$
59
+ LANGUAGE SQL IMMUTABLE STRICT;
60
+
61
+ COMMENT ON FUNCTION get_sequence_diffable_fields IS 'Short list the sequence fields we want to trank updates for';
62
+
63
+
64
+ -- Create a trigger to track the history of the change
65
+ CREATE OR REPLACE FUNCTION sequence_modification_history() RETURNS TRIGGER AS
66
+ $BODY$
67
+ DECLARE
68
+ previous_value_changed JSONB;
69
+ change_id UUID;
70
+ BEGIN
71
+ previous_value_changed := jsonb_diff(get_sequence_diffable_fields(OLD), get_sequence_diffable_fields(NEW));
72
+
73
+ INSERT INTO sequences_changes (sequence_id, account_id, previous_value_changed)
74
+ VALUES (NEW.id, NEW.last_account_to_edit, previous_value_changed) RETURNING id INTO change_id;
75
+
76
+ CREATE TEMP TABLE IF NOT EXISTS sequence_current_change ON COMMIT DROP AS SELECT change_id;
77
+
78
+ RETURN NULL;
79
+ END;
80
+ $BODY$
81
+ language plpgsql;
82
+
83
+ CREATE OR REPLACE FUNCTION picture_modification_history() RETURNS TRIGGER AS
84
+ $BODY$
85
+ DECLARE
86
+ previous_value_changed JSONB;
87
+ parent_sequence_change_id UUID;
88
+ BEGIN
89
+ previous_value_changed := jsonb_diff(to_jsonb(OLD), to_jsonb(NEW)) - 'last_account_to_edit';
90
+
91
+ -- if there is a sequence modified on the same transaction, we link the picture change to the sequence change.
92
+ IF EXISTS (
93
+ SELECT 1
94
+ FROM information_schema.tables
95
+ WHERE table_type = 'LOCAL TEMPORARY'
96
+ AND table_name = 'sequence_current_change'
97
+
98
+ ) THEN
99
+ SELECT change_id FROM sequence_current_change INTO parent_sequence_change_id;
100
+ END IF;
101
+
102
+ INSERT INTO pictures_changes (picture_id, account_id, previous_value_changed, sequences_changes_id)
103
+ VALUES (NEW.id, NEW.last_account_to_edit, previous_value_changed, parent_sequence_change_id);
104
+
105
+ RETURN NULL;
106
+ END;
107
+ $BODY$
108
+ language plpgsql;
109
+
110
+ -- We only trigger this for updates of last_account_to_edit. All changes that needs to be tracked need to set this field.
111
+ CREATE TRIGGER sequence_modification_history_trg
112
+ AFTER UPDATE OF
113
+ last_account_to_edit
114
+ ON sequences
115
+ FOR EACH ROW
116
+ EXECUTE PROCEDURE sequence_modification_history();
117
+
118
+ CREATE TRIGGER picture_modification_history_trg
119
+ AFTER UPDATE OF
120
+ last_account_to_edit
121
+ ON pictures
122
+ FOR EACH ROW
123
+ EXECUTE PROCEDURE picture_modification_history();
@@ -0,0 +1,67 @@
1
+ -- sequence_geom_multi_linestring
2
+ -- depends: 20240220_01_9wZs0-sequence-current-sort
3
+
4
+
5
+ ALTER TABLE sequences
6
+ ALTER COLUMN geom TYPE GEOMETRY(LineString, 4326),
7
+ DROP COLUMN bbox;
8
+ DROP FUNCTION compute_sequence_bbox;
9
+
10
+ DROP FUNCTION compute_sequence_geom;
11
+
12
+ -- put back old functions
13
+ DROP FUNCTION IF EXISTS pictures_update_geom_sequence CASCADE;
14
+ CREATE FUNCTION pictures_update_geom_sequence() RETURNS trigger AS $$
15
+ BEGIN
16
+ UPDATE sequences
17
+ SET geom = s.geom
18
+ FROM (
19
+ SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
20
+ FROM (
21
+ SELECT sp.seq_id, p.geom
22
+ FROM sequences_pictures sp
23
+ JOIN pictures p ON sp.pic_id = p.id
24
+ WHERE sp.seq_id IN (
25
+ SELECT DISTINCT sequences_pictures.seq_id
26
+ FROM sequences_pictures
27
+ WHERE sequences_pictures.pic_id = NEW.id
28
+ )
29
+ ORDER BY sp.seq_id, sp.rank
30
+ ) sp
31
+ GROUP BY seq_id
32
+ ) s
33
+ WHERE sequences.id = s.seq_id;
34
+ RETURN NULL;
35
+ END $$ LANGUAGE plpgsql;
36
+
37
+ CREATE TRIGGER pictures_update_sequences_geom_trg
38
+ AFTER UPDATE OF geom ON pictures
39
+ FOR EACH ROW EXECUTE FUNCTION pictures_update_geom_sequence();
40
+
41
+ DROP FUNCTION IF EXISTS sequences_pictures_delete CASCADE;
42
+ CREATE FUNCTION sequences_pictures_delete() RETURNS trigger AS $$
43
+ BEGIN
44
+ UPDATE sequences
45
+ SET geom = s.geom
46
+ FROM (
47
+ SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
48
+ FROM (
49
+ SELECT sp.seq_id, sp.rank, p.geom
50
+ FROM sequences_pictures sp
51
+ JOIN pictures p ON sp.pic_id = p.id
52
+ WHERE sp.seq_id IN (
53
+ SELECT DISTINCT seq_id
54
+ FROM old_table
55
+ )
56
+ ORDER BY sp.seq_id, sp.rank
57
+ ) sp
58
+ GROUP BY seq_id
59
+ ) s
60
+ WHERE sequences.id = s.seq_id;
61
+ RETURN NULL;
62
+ END $$ LANGUAGE plpgsql;
63
+
64
+ CREATE TRIGGER sequences_pictures_delete_trg
65
+ AFTER DELETE ON sequences_pictures
66
+ REFERENCING OLD TABLE AS old_table
67
+ FOR EACH STATEMENT EXECUTE FUNCTION sequences_pictures_delete();
@@ -0,0 +1,101 @@
1
+ -- sequence_geom_multi_linestring
2
+ -- depends: 20240220_01_9wZs0-sequence-current-sort
3
+
4
+ ALTER TABLE sequences
5
+ ALTER COLUMN geom TYPE GEOMETRY(MultiLineString, 4326) USING ST_Multi(geom),
6
+ -- Since some geometries can now be null (if all points are too far appart)
7
+ -- We store a bounding box of the geometry, always computed with the pictures of the geometry
8
+ ADD COLUMN IF NOT EXISTS bbox box2d;
9
+
10
+ CREATE FUNCTION compute_sequence_geom(IN sequence_id UUID) RETURNS GEOMETRY(MultiLineString, 4326) AS $$
11
+ WITH
12
+ all_pics AS (
13
+ SELECT p.geom AS geom, sp.seq_id
14
+ FROM sequences_pictures sp
15
+ JOIN pictures p ON sp.pic_id = p.id
16
+ WHERE sp.seq_id = sequence_id
17
+ ORDER BY sp.rank
18
+ )
19
+ , pic_as_line AS (
20
+ SELECT seq_id, ST_MakeLine(geom) AS geom
21
+ FROM all_pics
22
+ GROUP BY seq_id
23
+ )
24
+ , segments as (
25
+ SELECT
26
+ seq_id,
27
+ (ST_DumpSegments(geom)).geom AS segment
28
+ FROM pic_as_line
29
+ )
30
+ -- make a multiline geometry for the sequence, spliting each pictures separated by more than 50 meters
31
+ , seq_geom as (
32
+ SELECT
33
+ seq_id,
34
+ ST_LineMerge(ST_Collect(segment)) as geom
35
+ FROM segments
36
+ WHERE ST_Length(segment::geography) < 50
37
+ GROUP BY seq_id
38
+ )
39
+ , seq_multi_ls_geom as (
40
+ SELECT
41
+ seq_id,
42
+ ST_Multi(geom) as geom
43
+ FROM seq_geom
44
+ WHERE NOT ST_IsEmpty(geom)
45
+ )
46
+ SELECT seq_multi_ls_geom.geom
47
+ FROM seq_multi_ls_geom;
48
+ $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
49
+
50
+
51
+ CREATE FUNCTION compute_sequence_bbox(IN sequence_id UUID) RETURNS box2d AS $$
52
+ SELECT
53
+ ST_Extent(geom)
54
+ FROM sequences_pictures sp
55
+ JOIN pictures p ON sp.pic_id = p.id
56
+ WHERE sp.seq_id = sequence_id;
57
+ $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
58
+
59
+
60
+ -- update bbox in sequences
61
+ UPDATE sequences
62
+ SET
63
+ bbox = compute_sequence_bbox(id);
64
+
65
+ -- change sql function called by trigger on picture's geom update
66
+ DROP FUNCTION IF EXISTS pictures_update_geom_sequence CASCADE;
67
+ CREATE FUNCTION pictures_update_geom_sequence() RETURNS trigger AS $$
68
+ BEGIN
69
+ UPDATE sequences
70
+ SET
71
+ geom = compute_sequence_geom(id),
72
+ bbox = compute_sequence_bbox(id)
73
+ WHERE id IN (
74
+ SELECT DISTINCT sequences_pictures.seq_id
75
+ FROM sequences_pictures
76
+ WHERE sequences_pictures.pic_id = NEW.id
77
+ );
78
+
79
+ RETURN NULL;
80
+ END $$ LANGUAGE plpgsql;
81
+
82
+ CREATE TRIGGER pictures_update_sequences_geom_trg
83
+ AFTER UPDATE OF geom ON pictures
84
+ FOR EACH ROW EXECUTE FUNCTION pictures_update_geom_sequence();
85
+
86
+ DROP FUNCTION IF EXISTS sequences_pictures_delete CASCADE;
87
+ CREATE FUNCTION sequences_pictures_delete() RETURNS trigger AS $$
88
+ BEGIN
89
+ UPDATE sequences
90
+ SET
91
+ geom = compute_sequence_geom(id),
92
+ bbox = compute_sequence_bbox(id)
93
+ WHERE id IN (SELECT DISTINCT seq_id FROM old_table);
94
+
95
+ RETURN NULL;
96
+ END $$ LANGUAGE plpgsql;
97
+
98
+ CREATE TRIGGER sequences_pictures_delete_trg
99
+ AFTER DELETE ON sequences_pictures
100
+ REFERENCING OLD TABLE AS old_table
101
+ FOR EACH STATEMENT EXECUTE FUNCTION sequences_pictures_delete();
@@ -0,0 +1,52 @@
1
+ -- migrate_sequence_geom_multi_linestring
2
+ -- depends: 20240226_01_8iXl1-track-changes 20240229_01_SgfQY-sequence-geom-multi-linestring
3
+
4
+
5
+
6
+ -- We do not want a transaction around this, as we'll be commiting batches of geometry updates
7
+ -- transactional: false
8
+
9
+ CREATE OR REPLACE PROCEDURE migrate_sequences_split_geom() AS
10
+ $$
11
+ DECLARE
12
+ last_inserted_at TIMESTAMPTZ;
13
+ BEGIN
14
+ SELECT min(inserted_at) - INTERVAL '1 minute' FROM sequences INTO last_inserted_at;
15
+
16
+ WHILE last_inserted_at IS NOT NULL LOOP
17
+
18
+ -- Temporary removal of all update triggers
19
+ DROP TRIGGER sequences_update_ts_trg ON sequences;
20
+
21
+ WITH
22
+ -- get a batch of 1 000 sequences to update
23
+ seq_to_update AS (
24
+ SELECT id, inserted_at from sequences where inserted_at > last_inserted_at ORDER BY inserted_at ASC LIMIT 1000
25
+ )
26
+ , updated_seq AS (
27
+ UPDATE sequences
28
+ SET
29
+ geom = compute_sequence_geom(id)
30
+ WHERE id in (SELECT id FROM seq_to_update)
31
+ )
32
+ SELECT MAX(inserted_at) FROM seq_to_update INTO last_inserted_at;
33
+
34
+ RAISE NOTICE 'max insertion date is now %', last_inserted_at;
35
+
36
+ -- Restore all deactivated triggers
37
+ CREATE TRIGGER sequences_update_ts_trg
38
+ BEFORE UPDATE ON sequences
39
+ FOR EACH ROW EXECUTE FUNCTION sequences_update_ts();
40
+
41
+ -- commit transaction (as a procedure is in an implicit transaction, it will start a new transaction after this)
42
+ COMMIT;
43
+ END LOOP;
44
+
45
+ -- After this, we need to do a full vacuum to clean dead tuples
46
+ RAISE NOTICE 'Geometry fields updated, you should run `VACUUM FULL sequences;` afterward (or use something like pg_repack)';
47
+
48
+ END
49
+ $$ LANGUAGE plpgsql;
50
+
51
+ CALL migrate_sequences_split_geom();
52
+ DROP PROCEDURE migrate_sequences_split_geom;
@@ -0,0 +1,3 @@
1
+ -- pictures-grid
2
+ -- depends: 20240223_01_LsMHB-remove-binary-fields 20240308_01_aF0Jb-migrate-sequence-geom-multi-linestring
3
+ DROP MATERIALIZED VIEW pictures_grid;