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,166 @@
1
+ -- picture_update_index
2
+ -- depends: 20250513_01_8WkZC-upload-sets-default-config
3
+
4
+ -- Add a `updated_at` column to pictures and all the necessary triggers to make it up to date
5
+ -- Note that this should only encompass user's changes (so update to the history table (pictures_change) + semantics (and annotations))
6
+
7
+ ALTER TABLE pictures ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP;
8
+
9
+ CREATE FUNCTION update_pictures_updated_at_on_pictures_change() RETURNS trigger AS $$
10
+ BEGIN
11
+ UPDATE pictures
12
+ SET updated_at = current_timestamp
13
+ WHERE id IN (
14
+ SELECT DISTINCT picture_id
15
+ FROM pictures_change_after
16
+ );
17
+ RETURN NULL;
18
+ END $$ LANGUAGE plpgsql;
19
+
20
+ CREATE TRIGGER pictures_updated_at_on_picture_change_trg
21
+ AFTER INSERT ON pictures_changes
22
+ REFERENCING NEW TABLE AS pictures_change_after
23
+ FOR EACH STATEMENT
24
+ EXECUTE FUNCTION update_pictures_updated_at_on_pictures_change();
25
+
26
+ CREATE FUNCTION update_pictures_updated_at_on_semantics() RETURNS trigger AS $$
27
+ BEGIN
28
+ UPDATE pictures
29
+ SET updated_at = current_timestamp
30
+ WHERE id IN (
31
+ SELECT DISTINCT picture_id
32
+ FROM pictures_sem_after
33
+ );
34
+ RETURN NULL;
35
+ END $$ LANGUAGE plpgsql;
36
+
37
+ CREATE TRIGGER pictures_updated_at_on_semantic_insert_trg
38
+ AFTER INSERT ON pictures_semantics
39
+ REFERENCING NEW TABLE AS pictures_sem_after
40
+ FOR EACH STATEMENT
41
+ EXECUTE FUNCTION update_pictures_updated_at_on_semantics();
42
+
43
+ CREATE TRIGGER pictures_updated_at_on_semantic_change_trg
44
+ AFTER UPDATE ON pictures_semantics
45
+ REFERENCING NEW TABLE AS pictures_sem_after
46
+ FOR EACH STATEMENT
47
+ EXECUTE FUNCTION update_pictures_updated_at_on_semantics();
48
+
49
+ CREATE TRIGGER pictures_updated_at_on_semantic_delete_trg
50
+ AFTER DELETE ON pictures_semantics
51
+ REFERENCING OLD TABLE AS pictures_sem_after
52
+ FOR EACH STATEMENT
53
+ EXECUTE FUNCTION update_pictures_updated_at_on_semantics();
54
+
55
+
56
+ CREATE FUNCTION update_pictures_updated_at_on_annotation() RETURNS trigger AS $$
57
+ BEGIN
58
+ UPDATE pictures
59
+ SET updated_at = current_timestamp
60
+ WHERE id IN (
61
+ SELECT DISTINCT a.picture_id
62
+ FROM annotation_sem_after s
63
+ JOIN annotations a ON a.id = s.annotation_id
64
+ );
65
+ RETURN NULL;
66
+ END $$ LANGUAGE plpgsql;
67
+
68
+ CREATE TRIGGER pictures_updated_at_on_annotation_insert_trg
69
+ AFTER INSERT ON annotations_semantics
70
+ REFERENCING NEW TABLE AS annotation_sem_after
71
+ FOR EACH STATEMENT
72
+ EXECUTE FUNCTION update_pictures_updated_at_on_annotation();
73
+
74
+ CREATE TRIGGER pictures_updated_at_on_annotation_change_trg
75
+ AFTER UPDATE ON annotations_semantics
76
+ REFERENCING NEW TABLE AS annotation_sem_after
77
+ FOR EACH STATEMENT
78
+ EXECUTE FUNCTION update_pictures_updated_at_on_annotation();
79
+
80
+ -- Note: this trigger is called a_ because PG call the trigger in alphabetical order, and we want to be called before the `delete_empty_annotation_trg`
81
+ -- that deletes the annotation
82
+ CREATE TRIGGER a_pictures_updated_at_on_annotation_delete_trg
83
+ AFTER DELETE ON annotations_semantics
84
+ REFERENCING OLD TABLE AS annotation_sem_after
85
+ FOR EACH STATEMENT
86
+ EXECUTE FUNCTION update_pictures_updated_at_on_annotation();
87
+
88
+
89
+
90
+ -- Drop old triggers updating the sequence 'updated_at' field, now we do this only when a picture 'updated_at' field is updated
91
+ DROP FUNCTION IF EXISTS pictures_updates_on_sequences CASCADE;
92
+ DROP TRIGGER IF EXISTS pictures_updates_on_sequences_trg ON pictures;
93
+
94
+ CREATE FUNCTION pictures_updates_on_sequences() RETURNS trigger AS $$
95
+ BEGIN
96
+ UPDATE sequences
97
+ SET updated_at = current_timestamp
98
+ WHERE id IN (
99
+ SELECT sp.seq_id
100
+ FROM sequences_pictures sp
101
+ WHERE sp.pic_id = NEW.id
102
+ );
103
+ RETURN NULL;
104
+ END $$ LANGUAGE plpgsql;
105
+
106
+ CREATE TRIGGER pictures_updates_on_sequences_trg
107
+ AFTER UPDATE OF updated_at ON pictures
108
+ FOR EACH ROW
109
+ EXECUTE FUNCTION pictures_updates_on_sequences();
110
+
111
+ -- for deletion use statement level triggers
112
+ CREATE FUNCTION pictures_deletions_updated_at_on_sequences() RETURNS trigger AS $$
113
+ BEGIN
114
+ UPDATE sequences
115
+ SET updated_at = current_timestamp
116
+ WHERE
117
+ status != 'deleted'
118
+ AND id IN (
119
+ SELECT DISTINCT sp.seq_id
120
+ FROM pictures_after p
121
+ JOIN sequences_pictures sp ON sp.pic_id = p.id
122
+ );
123
+ RETURN NULL;
124
+ END $$ LANGUAGE plpgsql;
125
+
126
+ CREATE TRIGGER pictures_deletes_on_sequences_trg
127
+ AFTER DELETE ON pictures
128
+ REFERENCING OLD TABLE AS pictures_after
129
+ FOR EACH STATEMENT
130
+ EXECUTE FUNCTION pictures_deletions_updated_at_on_sequences();
131
+
132
+ -- Also change the picture_changes trigger so that we do not consider the `updated_at` field
133
+ DROP FUNCTION picture_modification_history CASCADE;
134
+ CREATE FUNCTION picture_modification_history() RETURNS TRIGGER AS
135
+ $BODY$
136
+ DECLARE
137
+ previous_value_changed JSONB;
138
+ parent_sequence_change_id UUID;
139
+ BEGIN
140
+ previous_value_changed := jsonb_diff(to_jsonb(OLD), to_jsonb(NEW)) - 'last_account_to_edit' - 'updated_at';
141
+
142
+ -- if there is a sequence modified on the same transaction, we link the picture change to the sequence change.
143
+ IF EXISTS (
144
+ SELECT 1
145
+ FROM information_schema.tables
146
+ WHERE table_type = 'LOCAL TEMPORARY'
147
+ AND table_name = 'sequence_current_change'
148
+
149
+ ) THEN
150
+ SELECT change_id FROM sequence_current_change INTO parent_sequence_change_id;
151
+ END IF;
152
+
153
+ INSERT INTO pictures_changes (picture_id, account_id, previous_value_changed, sequences_changes_id)
154
+ VALUES (NEW.id, NEW.last_account_to_edit, previous_value_changed, parent_sequence_change_id);
155
+
156
+ RETURN NULL;
157
+ END;
158
+ $BODY$
159
+ language plpgsql;
160
+
161
+ CREATE TRIGGER picture_modification_history_trg
162
+ AFTER UPDATE OF
163
+ last_account_to_edit
164
+ ON pictures
165
+ FOR EACH ROW
166
+ EXECUTE PROCEDURE picture_modification_history();
@@ -0,0 +1,4 @@
1
+ -- update_picture_updated_at
2
+ -- depends: 20250523_01_b11eW-picture-update-index
3
+
4
+ DROP INDEX pictures_updated_at_idx;
@@ -0,0 +1,7 @@
1
+ -- update_picture_updated_at
2
+ -- depends: 20250523_01_b11eW-picture-update-index
3
+
4
+ -- transactional: false
5
+
6
+ CREATE INDEX CONCURRENTLY pictures_updated_at_idx ON pictures(updated_at);
7
+
@@ -0,0 +1,4 @@
1
+ -- job_warnings
2
+ -- depends: 20250523_02_5ZXXh-update-picture-updated-at
3
+
4
+ ALTER TABLE job_history DROP COLUMN warning;
@@ -0,0 +1,4 @@
1
+ -- job_warnings
2
+ -- depends: 20250523_02_5ZXXh-update-picture-updated-at
3
+
4
+ ALTER TABLE job_history ADD COLUMN warning TEXT;
@@ -0,0 +1,6 @@
1
+
2
+ -- upload_set_semantics
3
+ -- depends: 20250624_01_SETp6-job-warnings
4
+
5
+
6
+ DROP TABLE upload_sets_semantics CASCADE;
@@ -0,0 +1,15 @@
1
+ -- upload_set_semantics
2
+ -- depends: 20250624_01_SETp6-job-warnings
3
+
4
+
5
+ -- Upload set semantic is just a temporary bag of tags that will be copied into all the upload_set sequences.
6
+ -- We also keep the account_id to be able to track who added the tag.
7
+ CREATE TABLE upload_sets_semantics (
8
+ upload_set_id UUID NOT NULL References upload_sets(id) ON DELETE CASCADE,
9
+ key TEXT NOT NULL,
10
+ value TEXT NOT NULL,
11
+ account_id UUID REFERENCES accounts(id) ON DELETE SET NULL,
12
+ PRIMARY KEY (upload_set_id, key, value)
13
+ );
14
+
15
+ CREATE INDEX upload_sets_semantics_upload_set_id_idx ON upload_sets_semantics(upload_set_id);
@@ -0,0 +1,4 @@
1
+ -- sequence_upload_set_link
2
+ -- depends: 20250701_01_kr371-upload-set-semantics
3
+
4
+ ALTER TABLE sequences DROP COLUMN upload_set_id CASCADE;
@@ -0,0 +1,4 @@
1
+ -- sequence_upload_set_link
2
+ -- depends: 20250701_01_kr371-upload-set-semantics
3
+
4
+ ALTER TABLE sequences ADD COLUMN upload_set_id UUID REFERENCES upload_sets(id) ON DELETE SET NULL;
@@ -0,0 +1,4 @@
1
+ -- sequence_upload_set_fill
2
+ -- depends: 20250703_01_p2WVV-sequence-upload-set-link
3
+
4
+ DROP INDEX sequences_upload_set_id_idx;
@@ -0,0 +1,26 @@
1
+ -- sequence_upload_set_fill
2
+ -- depends: 20250703_01_p2WVV-sequence-upload-set-link
3
+ -- transactional: false
4
+
5
+ -- outside a transaction, we fill the link sequence/upload_set while disabling triggers (to speed up thing and not update the `updated_at` value for the sequence) and compute the index concurrently
6
+ -- Note: if the database does not support to set the replication role,
7
+ -- you'll need to disable the sequences_update_ts_trg trigger manually (and enable it after the update)
8
+
9
+ SET session_replication_role = replica;
10
+
11
+ -- big update to add upload_set_id to all sequences
12
+ WITH sequences_upload_set_link AS (
13
+ SELECT DISTINCT ON (sp.seq_id) sp.seq_id, p.upload_set_id
14
+ FROM sequences_pictures sp
15
+ JOIN pictures p ON sp.pic_id = p.id
16
+ WHERE p.upload_set_id IS NOT NULL
17
+ )
18
+ UPDATE sequences s
19
+ SET upload_set_id = link.upload_set_id
20
+ FROM sequences_upload_set_link link
21
+ WHERE s.id = link.seq_id;
22
+
23
+ -- put back the triggers
24
+ SET session_replication_role = DEFAULT;
25
+
26
+ CREATE INDEX CONCURRENTLY sequences_upload_set_id_idx ON sequences(upload_set_id);
@@ -0,0 +1,24 @@
1
+ -- check_empty_annotation_late
2
+ -- depends: 20250703_02_q0s3D-sequence-upload-set-fill
3
+
4
+ -- put back old trigger
5
+ DROP FUNCTION IF EXISTS delete_empty_annotations CASCADE;
6
+ CREATE FUNCTION delete_empty_annotations() RETURNS trigger AS $$
7
+ BEGIN
8
+ -- Delete annotations where no remaining semantics exist
9
+ DELETE FROM annotations a
10
+ WHERE a.id IN (
11
+ SELECT DISTINCT(deleted_as.annotation_id)
12
+ FROM deleted_annotations_semantics deleted_as
13
+ LEFT JOIN annotations_semantics ON deleted_as.annotation_id = annotations_semantics.annotation_id
14
+ WHERE annotations_semantics.annotation_id IS NULL
15
+ );
16
+ RETURN NULL;
17
+ END $$ LANGUAGE plpgsql;
18
+
19
+ -- trigger to delete annotation is there is no semantics tags
20
+ CREATE TRIGGER delete_empty_annotation_trg
21
+ AFTER DELETE ON annotations_semantics
22
+ REFERENCING OLD TABLE AS deleted_annotations_semantics
23
+ FOR EACH STATEMENT
24
+ EXECUTE FUNCTION delete_empty_annotations();
@@ -0,0 +1,10 @@
1
+ -- check_empty_annotation_late
2
+ -- depends: 20250703_02_q0s3D-sequence-upload-set-fill
3
+
4
+ -- We do not want triggers to remove empty annotations, as it needs to be done at the end of the transaction
5
+ -- and constraint triggers (that can be deffered) cannot be for each statement
6
+ -- and we fear this will be too slow when deleting lots of pictures (so lots of annotations, so lots of semantics)
7
+ -- This will be checked in the code, in the `update_tags` function, so we can better control this
8
+
9
+ DROP TRIGGER delete_empty_annotation_trg ON annotations_semantics;
10
+ DROP FUNCTION delete_empty_annotations();
@@ -0,0 +1,4 @@
1
+ -- upload_set_relative_heading
2
+ -- depends: 20250716_01_f8tcJ-check-empty-annotation-late
3
+
4
+ ALTER TABLE upload_sets DROP COLUMN relative_heading;
@@ -0,0 +1,4 @@
1
+ -- upload_set_relative_heading
2
+ -- depends: 20250716_01_f8tcJ-check-empty-annotation-late
3
+
4
+ ALTER TABLE upload_sets ADD COLUMN relative_heading integer;
@@ -0,0 +1,20 @@
1
+ -- file_deletion_after_delete_no_dup
2
+ -- depends: 20250728_01_2zgur-upload-set-relative-heading
3
+
4
+ DROP FUNCTION IF EXISTS ask_for_all_file_deletion_after_delete CASCADE;
5
+
6
+ CREATE FUNCTION ask_for_all_file_deletion_after_delete() RETURNS trigger AS $$
7
+ BEGIN
8
+ INSERT INTO job_queue(picture_to_delete_id, task)
9
+ SELECT p.id, 'delete' FROM deleted_pictures p;
10
+ RETURN NULL;
11
+
12
+ END $$ LANGUAGE plpgsql;
13
+
14
+ CREATE TRIGGER ask_for_all_file_deletion_after_delete_trg
15
+ AFTER DELETE ON pictures
16
+ REFERENCING OLD TABLE AS deleted_pictures
17
+ FOR EACH STATEMENT
18
+ EXECUTE FUNCTION ask_for_all_file_deletion_after_delete();
19
+
20
+ ALTER TABLE job_queue DROP CONSTRAINT picture_to_delete_id_unique;
@@ -0,0 +1,26 @@
1
+ -- file_deletion_after_delete_no_dup
2
+ -- depends: 20250728_01_2zgur-upload-set-relative-heading
3
+
4
+ -- We do not want to have several deletion jobs for a same picture
5
+ -- so we add a constraint to the job_queue table, and handle this in the trigger that ask for file deletion on picture's row deletion.
6
+
7
+ ALTER TABLE job_queue ADD CONSTRAINT picture_to_delete_id_unique UNIQUE (picture_to_delete_id);
8
+
9
+ DROP FUNCTION IF EXISTS ask_for_all_file_deletion_after_delete CASCADE;
10
+ CREATE FUNCTION ask_for_all_file_deletion_after_delete() RETURNS trigger AS $$
11
+ BEGIN
12
+ INSERT INTO job_queue(picture_to_delete_id, task)
13
+ SELECT p.id, 'delete' FROM deleted_pictures p
14
+ ON CONFLICT (picture_to_delete_id) DO NOTHING
15
+ ;
16
+ RETURN NULL;
17
+
18
+ END $$ LANGUAGE plpgsql;
19
+
20
+ CREATE TRIGGER ask_for_all_file_deletion_after_delete_trg
21
+ AFTER DELETE ON pictures
22
+ REFERENCING OLD TABLE AS deleted_pictures
23
+ FOR EACH STATEMENT
24
+ EXECUTE FUNCTION ask_for_all_file_deletion_after_delete();
25
+
26
+
@@ -0,0 +1,11 @@
1
+ -- visibility_status
2
+ -- depends: 20250825_01_nCgkN-file-deletion-after-delete-no-dup
3
+
4
+
5
+ ALTER TABLE upload_sets DROP COLUMN visibility;
6
+ ALTER TABLE pictures DROP COLUMN visibility;
7
+ ALTER TABLE sequences DROP COLUMN visibility;
8
+ ALTER TABLE accounts DROP COLUMN default_visibility;
9
+ ALTER TABLE configurations DROP COLUMN default_visibility;
10
+
11
+ DROP TYPE visibility_status;
@@ -0,0 +1,19 @@
1
+ -- visibility_status
2
+ -- depends: 20250825_01_nCgkN-file-deletion-after-delete-no-dup
3
+
4
+ CREATE TYPE visibility_status AS ENUM ('anyone', 'owner-only', 'logged-only');
5
+
6
+ ALTER TABLE upload_sets ADD COLUMN visibility visibility_status DEFAULT 'anyone';
7
+ ALTER TABLE pictures ADD COLUMN visibility visibility_status DEFAULT 'anyone';
8
+ ALTER TABLE sequences ADD COLUMN visibility visibility_status DEFAULT 'anyone';
9
+
10
+ -- Also add default values at the account/instance level
11
+ ALTER TABLE accounts ADD COLUMN default_visibility visibility_status;
12
+ ALTER TABLE configurations ADD COLUMN default_visibility visibility_status;
13
+
14
+ UPDATE pictures SET visibility = 'owner-only' WHERE status = 'hidden';
15
+ UPDATE sequences SET visibility = 'owner-only' WHERE status = 'hidden';
16
+
17
+ CREATE INDEX sequences_visibility_index ON sequences(visibility);
18
+ CREATE INDEX pictures_visibility_index ON pictures(visibility);
19
+ CREATE INDEX upload_sets_visibility_index ON upload_sets(visibility);
@@ -0,0 +1,20 @@
1
+ -- visibility_functions
2
+ -- depends: 20250902_01_k5UTq-visibility-status
3
+
4
+ CREATE OR REPLACE FUNCTION is_sequence_visible_by_user(seq sequences, account_id UUID) RETURNS boolean AS $$
5
+ SELECT seq.status != 'deleted' AND (seq.status = 'ready' OR seq.account_id = account_id);
6
+ $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE COST 10;
7
+
8
+ DROP FUNCTION is_picture_visible_by_user(pic pictures, account_id UUID);
9
+ DROP FUNCTION is_upload_set_visible_by_user(us upload_sets, account_id UUID);
10
+
11
+ CREATE OR REPLACE FUNCTION get_sequence_diffable_fields(IN seq sequences) RETURNS jsonb AS
12
+ $BODY$
13
+ SELECT jsonb_build_object(
14
+ 'status', seq.status,
15
+ 'current_sort', seq.current_sort
16
+ ) || seq.metadata;
17
+ $BODY$
18
+ LANGUAGE SQL IMMUTABLE STRICT;
19
+
20
+ COMMENT ON FUNCTION get_sequence_diffable_fields IS 'Short list the sequence fields we want to trank updates for';
@@ -0,0 +1,43 @@
1
+ -- visibility_functions
2
+ -- depends: 20250902_01_k5UTq-visibility-status
3
+
4
+
5
+ CREATE OR REPLACE FUNCTION is_sequence_visible_by_user(seq sequences, account_id UUID) RETURNS boolean AS $$
6
+ SELECT
7
+ seq.visibility IS NULL
8
+ OR seq.visibility = 'anyone'
9
+ OR (seq.visibility = 'logged-only' AND account_id IS NOT NULL)
10
+ OR (seq.visibility = 'owner-only' AND seq.account_id IS NOT DISTINCT FROM account_id)
11
+ ;
12
+ $$ LANGUAGE SQL STABLE PARALLEL SAFE COST 5;
13
+
14
+
15
+ CREATE OR REPLACE FUNCTION is_picture_visible_by_user(pic pictures, account_id UUID) RETURNS boolean AS $$
16
+ SELECT
17
+ pic.visibility IS NULL
18
+ OR pic.visibility = 'anyone'
19
+ OR (pic.visibility = 'logged-only' AND account_id IS NOT NULL)
20
+ OR (pic.visibility = 'owner-only' AND pic.account_id IS NOT DISTINCT FROM account_id)
21
+ ;
22
+ $$ LANGUAGE SQL STABLE PARALLEL SAFE COST 5;
23
+
24
+ CREATE OR REPLACE FUNCTION is_upload_set_visible_by_user(us upload_sets, account_id UUID) RETURNS boolean AS $$
25
+ SELECT
26
+ us.visibility IS NULL
27
+ OR us.visibility = 'anyone'
28
+ OR (us.visibility = 'logged-only' AND account_id IS NOT NULL)
29
+ OR (us.visibility = 'owner-only' AND us.account_id IS NOT DISTINCT FROM account_id)
30
+ ;
31
+ $$ LANGUAGE SQL STABLE PARALLEL SAFE COST 5;
32
+
33
+ -- We also update the `get_sequence_diffable_fields` function used to track changes on sequences, now we don't track the status field anymore, we only track the visibility field
34
+ CREATE OR REPLACE FUNCTION get_sequence_diffable_fields(IN seq sequences) RETURNS jsonb AS
35
+ $BODY$
36
+ SELECT jsonb_build_object(
37
+ 'visibility', seq.visibility,
38
+ 'current_sort', seq.current_sort
39
+ ) || seq.metadata;
40
+ $BODY$
41
+ LANGUAGE SQL IMMUTABLE STRICT;
42
+
43
+ COMMENT ON FUNCTION get_sequence_diffable_fields IS 'Short list the sequence fields we want to trank updates for';
@@ -0,0 +1,30 @@
1
+ -- report_visibility
2
+ -- depends: 20250904_01_3uVKX-visibility-functions
3
+
4
+ -- put back old trigger
5
+ DROP TRIGGER IF EXISTS trigger_report_auto_hide_picture ON reports;
6
+
7
+ CREATE OR REPLACE FUNCTION report_auto_hide_picture()
8
+ RETURNS TRIGGER AS $$
9
+ BEGIN
10
+ IF NEW.status = 'open' AND NEW.issue IN ('blur_missing', 'inappropriate', 'privacy', 'copyright') THEN
11
+ IF NEW.picture_id is NOT NULL THEN
12
+ UPDATE pictures
13
+ SET status = 'hidden'
14
+ WHERE id = NEW.picture_id;
15
+ NEW.status = 'open_autofix';
16
+ ELSIF NEW.sequence_id IS NOT NULL THEN
17
+ UPDATE sequences
18
+ SET status = 'hidden'
19
+ WHERE id = NEW.sequence_id;
20
+ NEW.status = 'open_autofix';
21
+ END IF;
22
+ END IF;
23
+ RETURN NEW;
24
+ END;
25
+ $$ LANGUAGE plpgsql;
26
+
27
+ CREATE TRIGGER trigger_report_auto_hide_picture
28
+ BEFORE INSERT ON reports
29
+ FOR EACH ROW
30
+ EXECUTE FUNCTION report_auto_hide_picture();
@@ -0,0 +1,30 @@
1
+ -- report_visibility
2
+ -- depends: 20250904_01_3uVKX-visibility-functions
3
+
4
+ -- drop old trigger and replace it using the new visibility field instead of the 'hidden' status
5
+ DROP TRIGGER IF EXISTS trigger_report_auto_hide_picture ON reports;
6
+
7
+ CREATE OR REPLACE FUNCTION report_auto_hide_picture()
8
+ RETURNS TRIGGER AS $$
9
+ BEGIN
10
+ IF NEW.status = 'open' AND NEW.issue IN ('blur_missing', 'inappropriate', 'privacy', 'copyright') THEN
11
+ IF NEW.picture_id is NOT NULL THEN
12
+ UPDATE pictures
13
+ SET visibility = 'owner-only', last_account_to_edit = (SELECT COALESCE(NEW.reporter_account_id, (SELECT id FROM accounts WHERE is_default)))
14
+ WHERE id = NEW.picture_id;
15
+ NEW.status = 'open_autofix';
16
+ ELSIF NEW.sequence_id IS NOT NULL THEN
17
+ UPDATE sequences
18
+ SET visibility = 'owner-only', last_account_to_edit = (SELECT COALESCE(NEW.reporter_account_id, (SELECT id FROM accounts WHERE is_default)))
19
+ WHERE id = NEW.sequence_id;
20
+ NEW.status = 'open_autofix';
21
+ END IF;
22
+ END IF;
23
+ RETURN NEW;
24
+ END;
25
+ $$ LANGUAGE plpgsql;
26
+
27
+ CREATE TRIGGER trigger_report_auto_hide_picture
28
+ BEFORE INSERT ON reports
29
+ FOR EACH ROW
30
+ EXECUTE FUNCTION report_auto_hide_picture();
@@ -0,0 +1,6 @@
1
+ -- page_updates
2
+ -- depends: 20251110_01_bWEXo-report-visibility
3
+
4
+ ALTER TABLE pages DROP COLUMN updated_at;
5
+
6
+ ALTER TABLE accounts DROP COLUMN tos_latest_change_read_at;
@@ -0,0 +1,8 @@
1
+ -- page_updates
2
+ -- depends: 20251110_01_bWEXo-report-visibility
3
+
4
+ ALTER TABLE pages ADD COLUMN updated_at TIMESTAMPTZ;
5
+
6
+ ALTER TABLE accounts ADD COLUMN tos_latest_change_read_at TIMESTAMPTZ;
7
+
8
+ UPDATE accounts SET tos_latest_change_read_at = tos_accepted_at;
@@ -0,0 +1,24 @@
1
+ -- pictures_grid_visibility
2
+ -- depends: 20221201_01_wpCGc-initial-schema 20251124_01_0xdqi-page-updates
3
+
4
+ CREATE MATERIALIZED VIEW pictures_grid_old AS
5
+ SELECT
6
+ row_number() over () as id,
7
+ count(*) as nb_pictures,
8
+ g.geom
9
+ FROM
10
+ ST_SquareGrid(
11
+ 0.1,
12
+ ST_SetSRID(ST_EstimatedExtent('public', 'pictures', 'geom'), 4326)
13
+ ) AS g
14
+ JOIN pictures AS p ON p.geom && g.geom
15
+ JOIN sequences_pictures sp on sp.pic_id = p.id
16
+ JOIN sequences s ON s.id = sp.seq_id
17
+ WHERE p.status = 'ready' and s.status = 'ready'
18
+ GROUP BY g.geom;
19
+
20
+ CREATE UNIQUE INDEX ON pictures_grid_old(id);
21
+
22
+ DROP MATERIALIZED VIEW pictures_grid;
23
+ ALTER MATERIALIZED VIEW pictures_grid_old RENAME TO pictures_grid;
24
+
@@ -0,0 +1,36 @@
1
+ -- pictures_grid_visibility
2
+ -- depends: 20221201_01_wpCGc-initial-schema 20251124_01_0xdqi-page-updates
3
+
4
+ -- CREATE new materialized view to not block during the migration
5
+ -- Compared to the new one, we want to use fully qualified path (`public.pictures` instead of `pictures`)
6
+ -- because of a strange problem that occurs in some server
7
+ -- We also want to take the new visibility into account not to show pictures that are not visible to everybody in the grid
8
+
9
+ CREATE MATERIALIZED VIEW pictures_grid_new AS
10
+ SELECT
11
+ row_number() over () as id,
12
+ count(*) as nb_pictures,
13
+ count(*) FILTER (WHERE p.metadata->>'type' = 'equirectangular') as nb_360_pictures,
14
+ g.geom
15
+ FROM
16
+ ST_SquareGrid(
17
+ 0.1,
18
+ ST_SetSRID(ST_EstimatedExtent('public', 'pictures', 'geom'), 4326)
19
+ ) AS g
20
+ JOIN public.pictures AS p ON p.geom && g.geom
21
+ JOIN public.sequences_pictures sp on sp.pic_id = p.id
22
+ JOIN public.sequences s ON s.id = sp.seq_id
23
+ LEFT JOIN public.upload_sets us ON us.id = s.upload_set_id
24
+ WHERE
25
+ p.status = 'ready' and s.status = 'ready'
26
+ AND is_picture_visible_by_user(p, NULL)
27
+ AND is_sequence_visible_by_user(s, NULL)
28
+ AND (us IS NULL OR is_upload_set_visible_by_user(us, NULL))
29
+ GROUP BY g.geom
30
+ ;
31
+
32
+ CREATE UNIQUE INDEX ON pictures_grid_new(id);
33
+
34
+ DROP MATERIALIZED VIEW pictures_grid;
35
+ ALTER MATERIALIZED VIEW pictures_grid_new RENAME TO pictures_grid;
36
+
@@ -0,0 +1,32 @@
1
+ -- pictures_grid_logged_only
2
+ -- depends: 20251127_01_S6Ci8-pictures-grid-visibility
3
+
4
+
5
+ CREATE MATERIALIZED VIEW pictures_grid_new AS
6
+ SELECT
7
+ row_number() over () as id,
8
+ count(*) as nb_pictures,
9
+ count(*) FILTER (WHERE p.metadata->>'type' = 'equirectangular') as nb_360_pictures,
10
+ g.geom
11
+ FROM
12
+ ST_SquareGrid(
13
+ 0.1,
14
+ ST_SetSRID(ST_EstimatedExtent('public', 'pictures', 'geom'), 4326)
15
+ ) AS g
16
+ JOIN public.pictures AS p ON p.geom && g.geom
17
+ JOIN public.sequences_pictures sp on sp.pic_id = p.id
18
+ JOIN public.sequences s ON s.id = sp.seq_id
19
+ LEFT JOIN public.upload_sets us ON us.id = s.upload_set_id
20
+ WHERE
21
+ p.status = 'ready' and s.status = 'ready'
22
+ AND is_picture_visible_by_user(p, NULL)
23
+ AND is_sequence_visible_by_user(s, NULL)
24
+ AND (us IS NULL OR is_upload_set_visible_by_user(us, NULL))
25
+ GROUP BY g.geom
26
+ ;
27
+
28
+ CREATE UNIQUE INDEX ON pictures_grid_new(id);
29
+
30
+ DROP MATERIALIZED VIEW pictures_grid;
31
+ ALTER MATERIALIZED VIEW pictures_grid_new RENAME TO pictures_grid;
32
+