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,21 @@
1
+ -- pictures-grid
2
+ -- depends: 20240223_01_LsMHB-remove-binary-fields 20240308_01_aF0Jb-migrate-sequence-geom-multi-linestring
3
+
4
+ -- it's mandatory for a vaccum analyze to be done to be able to use `ST_EstimatedExtent`
5
+
6
+ CREATE MATERIALIZED VIEW pictures_grid AS
7
+ SELECT
8
+ row_number() over () as id,
9
+ count(*) as nb_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 pictures AS p ON p.geom && g.geom
17
+ JOIN sequences_pictures sp on sp.pic_id = p.id -- Added otherwise can't init from empty database
18
+ GROUP BY g.geom;
19
+
20
+ CREATE INDEX pictures_grid_id_idx ON pictures_grid(id);
21
+ CREATE INDEX pictures_grid_geom_idx ON pictures_grid USING GIST(geom);
@@ -0,0 +1,7 @@
1
+ -- pictures_stats_on_sequences
2
+ -- depends: 20240223_01_LsMHB-remove-binary-fields 20240308_01_aF0Jb-migrate-sequence-geom-multi-linestring
3
+
4
+ ALTER TABLE sequences DROP COLUMN min_picture_ts;
5
+ ALTER TABLE sequences DROP COLUMN max_picture_ts;
6
+ ALTER TABLE sequences DROP COLUMN nb_pictures;
7
+
@@ -0,0 +1,9 @@
1
+ -- pictures_stats_on_sequences
2
+ -- depends: 20240223_01_LsMHB-remove-binary-fields 20240308_01_aF0Jb-migrate-sequence-geom-multi-linestring
3
+
4
+ -- To avoid a costly join on sequence_pictures and picture, we add aggregated values at the sequence level, computed using triggers (in the next migration to split the table migration in 2 transactions)
5
+
6
+ ALTER TABLE sequences
7
+ ADD COLUMN min_picture_ts TIMESTAMPTZ,
8
+ ADD COLUMN max_picture_ts TIMESTAMPTZ,
9
+ ADD COLUMN nb_pictures BIGINT DEFAULT 0;
@@ -0,0 +1,5 @@
1
+ -- fill_pictures_stats_on_sequences
2
+ -- depends: 20240416_01_FpyGs-pictures-stats-on-sequences
3
+
4
+ DROP TRIGGER picture_insertion_update_sequence_trigger ON pictures CASCADE;
5
+ DROP TRIGGER seq_picture_deletion_update_sequence_trigger ON sequences_pictures CASCADE;
@@ -0,0 +1,84 @@
1
+ -- fill_pictures_stats_on_sequences
2
+ -- depends: 20240416_01_FpyGs-pictures-stats-on-sequences
3
+
4
+ -- disable triggers on the current transaction, to avoid activating from update triggers only for a populating query
5
+ -- (for example we don't want a sequence update_ts to be updated)
6
+ SET session_replication_role = replica;
7
+
8
+ WITH aggregated_pics AS (
9
+ SELECT sp.seq_id AS seq_id,
10
+ MIN(p.ts) AS min_picture_ts,
11
+ MAX(p.ts) AS max_picture_ts,
12
+ COUNT(p.*) AS nb_pictures
13
+ FROM sequences_pictures sp
14
+ JOIN pictures p ON sp.pic_id = p.id
15
+ GROUP BY sp.seq_id
16
+ )
17
+ UPDATE sequences SET
18
+ min_picture_ts = a.min_picture_ts,
19
+ max_picture_ts = a.max_picture_ts,
20
+ nb_pictures = a.nb_pictures
21
+ FROM aggregated_pics a
22
+ WHERE sequences.id = seq_id;
23
+
24
+ -- put back the triggers
25
+ SET session_replication_role = DEFAULT;
26
+
27
+ -- Also add Triggers to maintain those counters
28
+
29
+ -- On picture insertion (usually do nothing, we want pictures to be ready to count them)
30
+ CREATE OR REPLACE FUNCTION update_sequence_on_picture_insertion() RETURNS TRIGGER AS
31
+ $BODY$
32
+ BEGIN
33
+ UPDATE sequences
34
+ SET
35
+ nb_pictures = nb_pictures + 1,
36
+ min_picture_ts = LEAST(min_picture_ts, NEW.ts),
37
+ max_picture_ts = GREATEST(max_picture_ts, NEW.ts)
38
+ WHERE id IN (
39
+ SELECT DISTINCT(seq_id) FROM sequences_pictures WHERE pic_id = NEW.id
40
+ );
41
+
42
+ RETURN NULL;
43
+ END;
44
+ $BODY$
45
+ language plpgsql;
46
+
47
+ CREATE CONSTRAINT TRIGGER picture_insertion_update_sequence_trigger
48
+ AFTER INSERT ON pictures
49
+ DEFERRABLE INITIALLY DEFERRED -- check at end of transaction for picture to be linked to a sequence
50
+ FOR EACH ROW
51
+ EXECUTE PROCEDURE update_sequence_on_picture_insertion();
52
+
53
+ -- On picture deletion (don't try to do clever stuff, compute from scratch)
54
+ CREATE OR REPLACE FUNCTION update_sequence_on_sequences_pictures_deletion() RETURNS TRIGGER AS
55
+ $BODY$
56
+ BEGIN
57
+ WITH aggregated_pics AS (
58
+ SELECT sp.seq_id AS seq_id,
59
+ MIN(p.ts) AS min_picture_ts,
60
+ MAX(p.ts) AS max_picture_ts,
61
+ COUNT(p.*) AS nb_pictures
62
+ FROM sequences_pictures sp
63
+ JOIN pictures p ON sp.pic_id = p.id
64
+ WHERE sp.seq_id IN (
65
+ SELECT DISTINCT(seq_id) FROM old_table
66
+ )
67
+ GROUP BY sp.seq_id
68
+ )
69
+ UPDATE sequences SET
70
+ min_picture_ts = a.min_picture_ts,
71
+ max_picture_ts = a.max_picture_ts,
72
+ nb_pictures = a.nb_pictures
73
+ FROM aggregated_pics a
74
+ WHERE sequences.id = seq_id;
75
+ RETURN NULL;
76
+ END;
77
+ $BODY$
78
+ language plpgsql;
79
+
80
+ CREATE TRIGGER seq_picture_deletion_update_sequence_trigger
81
+ AFTER DELETE ON sequences_pictures
82
+ REFERENCING OLD TABLE AS old_table
83
+ FOR EACH STATEMENT -- run this for each statement
84
+ EXECUTE PROCEDURE update_sequence_on_sequences_pictures_deletion();
@@ -0,0 +1,5 @@
1
+ -- refresh_table
2
+ -- depends: 20240409_01_jnhra-pictures-grid 20240416_02_A5KzC-fill-pictures-stats-on-sequences
3
+
4
+
5
+ DROP TABLE refresh_database;
@@ -0,0 +1,9 @@
1
+ -- refresh_table
2
+ -- depends: 20240409_01_jnhra-pictures-grid 20240416_02_A5KzC-fill-pictures-stats-on-sequences
3
+
4
+
5
+ CREATE TABLE refresh_database(
6
+ refreshed_at TIMESTAMPTZ
7
+ );
8
+
9
+ INSERT INTO refresh_database(refreshed_at) VALUES (null);
@@ -0,0 +1,21 @@
1
+ -- picture_grid_public
2
+ -- depends: 20240507_01_eBfqZ-refresh-table
3
+
4
+ DROP MATERIALIZED VIEW pictures_grid;
5
+
6
+ CREATE MATERIALIZED VIEW pictures_grid AS
7
+ SELECT
8
+ row_number() over () as id,
9
+ count(*) as nb_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 pictures AS p ON p.geom && g.geom
17
+ JOIN sequences_pictures sp on sp.pic_id = p.id
18
+ GROUP BY g.geom;
19
+
20
+ CREATE INDEX pictures_grid_id_idx ON pictures_grid(id);
21
+ CREATE INDEX pictures_grid_geom_idx ON pictures_grid USING GIST(geom);
@@ -0,0 +1,26 @@
1
+ -- picture_grid_public
2
+ -- depends: 20240507_01_eBfqZ-refresh-table
3
+ -- transactional: false
4
+
5
+ BEGIN;
6
+
7
+ DROP MATERIALIZED VIEW pictures_grid;
8
+
9
+ --only consider public pictures in this view
10
+ CREATE MATERIALIZED VIEW pictures_grid AS
11
+ SELECT
12
+ row_number() over () as id,
13
+ count(*) as nb_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 pictures AS p ON p.geom && g.geom
21
+ JOIN sequences_pictures sp on sp.pic_id = p.id
22
+ JOIN sequences s ON s.id = sp.seq_id
23
+ WHERE p.status = 'ready' and s.status = 'ready'
24
+ GROUP BY g.geom;
25
+
26
+ COMMIT;
@@ -0,0 +1,41 @@
1
+ -- picture_delete_cascade
2
+ -- depends: 20240507_02_dzVET-picture-grid-public
3
+
4
+
5
+ -- only recompute sequences shape for non deleted sequences
6
+ CREATE OR REPLACE FUNCTION sequences_pictures_delete() RETURNS trigger AS $$
7
+ BEGIN
8
+ UPDATE sequences
9
+ SET
10
+ geom = compute_sequence_geom(id),
11
+ bbox = compute_sequence_bbox(id)
12
+ WHERE id IN (SELECT DISTINCT seq_id FROM old_table);
13
+
14
+ RETURN NULL;
15
+ END $$ LANGUAGE plpgsql;
16
+
17
+ CREATE OR REPLACE FUNCTION update_sequence_on_sequences_pictures_deletion() RETURNS TRIGGER AS
18
+ $BODY$
19
+ BEGIN
20
+ WITH aggregated_pics AS (
21
+ SELECT sp.seq_id AS seq_id,
22
+ MIN(p.ts) AS min_picture_ts,
23
+ MAX(p.ts) AS max_picture_ts,
24
+ COUNT(p.*) AS nb_pictures
25
+ FROM sequences_pictures sp
26
+ JOIN pictures p ON sp.pic_id = p.id
27
+ WHERE sp.seq_id IN (
28
+ SELECT DISTINCT(seq_id) FROM old_table
29
+ )
30
+ GROUP BY sp.seq_id
31
+ )
32
+ UPDATE sequences SET
33
+ min_picture_ts = a.min_picture_ts,
34
+ max_picture_ts = a.max_picture_ts,
35
+ nb_pictures = a.nb_pictures
36
+ FROM aggregated_pics a
37
+ WHERE sequences.id = seq_id;
38
+ RETURN NULL;
39
+ END;
40
+ $BODY$
41
+ language plpgsql;
@@ -0,0 +1,42 @@
1
+ -- picture_delete_cascade
2
+ -- depends: 20240507_02_dzVET-picture-grid-public
3
+
4
+
5
+ -- only recompute sequences shape for non deleted sequences
6
+ CREATE OR REPLACE FUNCTION sequences_pictures_delete() RETURNS trigger AS $$
7
+ BEGIN
8
+ UPDATE sequences
9
+ SET
10
+ geom = compute_sequence_geom(id),
11
+ bbox = compute_sequence_bbox(id)
12
+ WHERE id IN (SELECT DISTINCT seq_id FROM old_table) AND status <> 'deleted';
13
+
14
+ RETURN NULL;
15
+ END $$ LANGUAGE plpgsql;
16
+
17
+ CREATE OR REPLACE FUNCTION update_sequence_on_sequences_pictures_deletion() RETURNS TRIGGER AS
18
+ $BODY$
19
+ BEGIN
20
+ WITH aggregated_pics AS (
21
+ SELECT sp.seq_id AS seq_id,
22
+ MIN(p.ts) AS min_picture_ts,
23
+ MAX(p.ts) AS max_picture_ts,
24
+ COUNT(p.*) AS nb_pictures
25
+ FROM sequences_pictures sp
26
+ JOIN pictures p ON sp.pic_id = p.id
27
+ JOIN sequences s ON sp.seq_id = s.id
28
+ WHERE sp.seq_id IN (
29
+ SELECT DISTINCT(seq_id) FROM old_table
30
+ ) AND s.status <> 'deleted'
31
+ GROUP BY sp.seq_id
32
+ )
33
+ UPDATE sequences SET
34
+ min_picture_ts = a.min_picture_ts,
35
+ max_picture_ts = a.max_picture_ts,
36
+ nb_pictures = a.nb_pictures
37
+ FROM aggregated_pics a
38
+ WHERE sequences.id = seq_id;
39
+ RETURN NULL;
40
+ END;
41
+ $BODY$
42
+ language plpgsql;
@@ -0,0 +1,5 @@
1
+ -- content_md5
2
+ -- depends: 20240514_01_IT7DD-picture-delete-cascade
3
+
4
+ ALTER TABLE pictures DROP COLUMN IF EXISTS original_content_md5;
5
+
@@ -0,0 +1,7 @@
1
+ -- content_md5
2
+ -- depends: 20240514_01_IT7DD-picture-delete-cascade
3
+
4
+ -- concurrent index cannot be run inside a transaction
5
+ -- transactional: false
6
+
7
+ ALTER TABLE pictures ADD COLUMN IF NOT EXISTS original_content_md5 UUID;
@@ -0,0 +1,6 @@
1
+ -- upload_set
2
+ -- depends: 20240514_01_IT7DD-picture-delete-cascade
3
+
4
+ ALTER TABLE pictures DROP COLUMN IF EXISTS upload_set_id;
5
+ DROP TABLE upload_sets;
6
+ DROP TYPE upload_set_sort_method;
@@ -0,0 +1,46 @@
1
+ -- upload_set
2
+ -- depends: 20240514_01_IT7DD-picture-delete-cascade
3
+
4
+ --transactional: false
5
+
6
+ BEGIN;
7
+
8
+ CREATE TYPE upload_set_sort_method AS ENUM (
9
+ 'filename_asc',
10
+ 'filename_desc',
11
+ 'time_asc',
12
+ 'time_desc'
13
+ );
14
+
15
+
16
+ CREATE TABLE upload_sets(
17
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
18
+ account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
19
+ created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
20
+ completed BOOLEAN NOT NULL DEFAULT false,
21
+ dispatched BOOLEAN NOT NULL DEFAULT false,
22
+ estimated_nb_files INT,
23
+
24
+ sort_method upload_set_sort_method NOT NULL DEFAULT 'time_asc',
25
+ split_time INTERVAL DEFAULT INTERVAL '1 minute',
26
+ duplicate_distance real DEFAULT 1,
27
+ split_distance INT DEFAULT 100,
28
+ duplicate_rotation INT DEFAULT 30,
29
+
30
+ title VARCHAR NOT NULL
31
+ );
32
+
33
+ COMMENT ON COLUMN upload_sets.sort_method IS 'Strategy used for sorting your pictures. Either by filename or EXIF time, in ascending or descending order.';
34
+ COMMENT ON COLUMN upload_sets.split_distance IS 'Maximum distance between two pictures to be considered in the same sequence (in meters).';
35
+ COMMENT ON COLUMN upload_sets.split_time IS 'Maximum time interval between two pictures to be considered in the same sequence.';
36
+ COMMENT ON COLUMN upload_sets.duplicate_distance IS 'Maximum distance between two pictures to be considered as duplicates (in meters).';
37
+ COMMENT ON COLUMN upload_sets.duplicate_rotation IS 'Maximum angle of rotation for two too-close-pictures to be considered as duplicates (in degrees).';
38
+
39
+ ALTER TABLE pictures ADD COLUMN IF NOT EXISTS upload_set_id UUID;
40
+
41
+ ALTER TABLE pictures ADD CONSTRAINT upload_set_fk_id FOREIGN KEY (upload_set_id) REFERENCES upload_sets(id) NOT VALID;
42
+
43
+ COMMIT;
44
+
45
+ -- The foreign kye constraint is added as invalid first, then validated, since it will allow row updating while validating the constraint
46
+ ALTER TABLE pictures VALIDATE CONSTRAINT upload_set_fk_id;
@@ -0,0 +1,4 @@
1
+ -- md5_concurrent_index
2
+ -- depends: 20240611_01_jftHn-content-md5
3
+
4
+ DROP INDEX IF EXISTS pictures_original_content_md5_idx;
@@ -0,0 +1,8 @@
1
+ -- md5_concurrent_index
2
+ -- depends: 20240611_01_jftHn-content-md5
3
+
4
+ -- transactional: false
5
+
6
+
7
+ CREATE INDEX CONCURRENTLY pictures_original_content_md5_idx ON pictures(original_content_md5);
8
+
@@ -0,0 +1,30 @@
1
+ -- fix_sequence_stat_on_pic_insertion
2
+ -- depends: 20240612_01_yNcuE-upload-set 20240617_01_tKtlx-md5-concurrent-index
3
+
4
+ -- put back old triggers
5
+ DROP TRIGGER sequences_pictures_insertion_update_sequence_trigger ON sequences_pictures CASCADE;
6
+
7
+ -- DROP TRIGGER picture_insertion_update_sequence_trigger ON pictures CASCADE;
8
+ CREATE OR REPLACE FUNCTION update_sequence_on_picture_insertion() RETURNS TRIGGER AS
9
+ $BODY$
10
+ BEGIN
11
+ UPDATE sequences
12
+ SET
13
+ nb_pictures = nb_pictures + 1,
14
+ min_picture_ts = LEAST(min_picture_ts, NEW.ts),
15
+ max_picture_ts = GREATEST(max_picture_ts, NEW.ts)
16
+ WHERE id IN (
17
+ SELECT DISTINCT(seq_id) FROM sequences_pictures WHERE pic_id = NEW.id
18
+ );
19
+
20
+ RETURN NULL;
21
+ END;
22
+ $BODY$
23
+ language plpgsql;
24
+
25
+ CREATE CONSTRAINT TRIGGER picture_insertion_update_sequence_trigger
26
+ AFTER INSERT ON pictures
27
+ DEFERRABLE INITIALLY DEFERRED -- check at end of transaction for picture to be linked to a sequence
28
+ FOR EACH ROW
29
+ EXECUTE PROCEDURE update_sequence_on_picture_insertion();
30
+
@@ -0,0 +1,31 @@
1
+ -- fix_sequence_stat_on_pic_insertion
2
+ -- depends: 20240612_01_yNcuE-upload-set 20240617_01_tKtlx-md5-concurrent-index
3
+
4
+ -- drop old triggers on insertion on pictures table, we want the trigger to be on sequences_pictures instead
5
+
6
+ DROP TRIGGER picture_insertion_update_sequence_trigger ON pictures CASCADE;
7
+
8
+ CREATE OR REPLACE FUNCTION update_sequence_on_picture_insertion() RETURNS TRIGGER AS
9
+ $BODY$
10
+ BEGIN
11
+ WITH p AS (
12
+ SELECT NEW.seq_id, ts FROM pictures WHERE id = NEW.pic_id
13
+ )
14
+ UPDATE sequences
15
+ SET
16
+ nb_pictures = nb_pictures + 1,
17
+ min_picture_ts = LEAST(min_picture_ts, p.ts),
18
+ max_picture_ts = GREATEST(max_picture_ts, p.ts)
19
+ FROM p
20
+ WHERE id = p.seq_id;
21
+
22
+ RETURN NULL;
23
+ END;
24
+ $BODY$
25
+ language plpgsql;
26
+
27
+ CREATE CONSTRAINT TRIGGER sequences_pictures_insertion_update_sequence_trigger
28
+ AFTER INSERT ON sequences_pictures
29
+ DEFERRABLE INITIALLY DEFERRED -- check at end of transaction for picture to be linked to a sequence
30
+ FOR EACH ROW
31
+ EXECUTE PROCEDURE update_sequence_on_picture_insertion();
@@ -0,0 +1,31 @@
1
+ -- job_queue
2
+ -- depends: 20240625_01_XMZ24-fix-sequence-stat-on-pic-insertion
3
+
4
+ ALTER TABLE job_history DROP COLUMN job_id;
5
+ ALTER TABLE job_history DROP COLUMN upload_set_id;
6
+ ALTER TABLE job_history DROP COLUMN sequence_id;
7
+ ALTER TABLE job_history DROP COLUMN job_task;
8
+
9
+ DELETE FROM job_history WHERE picture_id IS NULL; -- remove new style job history
10
+ ALTER TABLE job_history ALTER COLUMN picture_id SET NOT NULL;
11
+
12
+ DROP VIEW pictures_to_process;
13
+ DROP TABLE job_queue;
14
+ DROP TYPE job_type;
15
+
16
+
17
+ -- put back old table
18
+ CREATE TABLE pictures_to_process(
19
+ picture_id UUID PRIMARY KEY,
20
+ ts TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
21
+ task picture_process_task DEFAULT 'prepare',
22
+ nb_errors INT NOT NULL DEFAULT 0
23
+ );
24
+ ALTER TABLE pictures_to_process ADD CONSTRAINT picture_id_fk FOREIGN KEY (picture_id) REFERENCES pictures (id);
25
+
26
+ CREATE INDEX pictures_to_process_nb_errors_ts_idx ON pictures_to_process(nb_errors, ts);
27
+
28
+ CREATE INDEX pictures_to_process_ts_idx ON pictures_to_process(ts);
29
+
30
+ DROP TRIGGER upload_sets_completion_trg ON upload_sets;
31
+ DROP COLLATION numeric_file_names;
@@ -0,0 +1,104 @@
1
+ -- job_queue
2
+ -- depends: 20240625_01_XMZ24-fix-sequence-stat-on-pic-insertion
3
+
4
+ CREATE TYPE job_type AS ENUM (
5
+ 'prepare', -- picture needs to be prepared to be published
6
+ 'delete', -- picture needs to be deleted
7
+ 'dispatch', -- upload set needs to be dispatched into several collections
8
+ 'finalize' -- finalize a collection
9
+ );
10
+
11
+ CREATE TABLE job_queue (
12
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
13
+
14
+ -- job can be linked to either a picture, an upload set or a sequence
15
+ picture_id UUID REFERENCES pictures(id) ON DELETE CASCADE,
16
+ upload_set_id UUID REFERENCES upload_sets(id) ON DELETE CASCADE,
17
+ sequence_id UUID REFERENCES sequences(id) ON DELETE CASCADE,
18
+
19
+ ts TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
20
+
21
+ -- If not null, this job will not be done before this timestamp
22
+ to_do_after_ts TIMESTAMPTZ,
23
+
24
+ nb_errors INT NOT NULL DEFAULT 0,
25
+
26
+ task job_type NOT NULL,
27
+
28
+ CONSTRAINT picture_id_unique UNIQUE (picture_id),
29
+ CONSTRAINT upload_set_id_unique UNIQUE (upload_set_id),
30
+ CONSTRAINT sequence_id_unique UNIQUE (sequence_id)
31
+ );
32
+
33
+ -- Add a constraint to ensure that one and only one of the three foreign keys is set
34
+ ALTER TABLE job_queue
35
+ ADD CONSTRAINT one_external_id CHECK (num_nonnulls(picture_id, upload_set_id, sequence_id) = 1);
36
+
37
+ CREATE INDEX job_queue_nb_errors_ts_idx ON job_queue(nb_errors, ts);
38
+
39
+ -- this index is used to handle a 'ON CONFLICT' clause in the collection delete
40
+ CREATE INDEX job_queue_picture_id_idx ON job_queue(picture_id);
41
+
42
+ INSERT INTO job_queue (picture_id, ts, task, nb_errors)
43
+ SELECT
44
+ picture_id,
45
+ ts,
46
+ case WHEN task = 'delete' THEN 'delete'::job_type ELSE 'prepare'::job_type END,
47
+ nb_errors
48
+ FROM pictures_to_process;
49
+
50
+ DROP TABLE pictures_to_process CASCADE;
51
+
52
+ CREATE VIEW pictures_to_process AS (
53
+ SELECT picture_id, ts, task, nb_errors FROM job_queue WHERE task IN ('prepare', 'delete')
54
+ );
55
+
56
+ -- we change the trigger that insert all new pictures into the pictures_to_process table
57
+ CREATE
58
+ OR REPLACE FUNCTION picture_insertion() RETURNS TRIGGER AS $BODY$ BEGIN
59
+ INSERT INTO
60
+ job_queue(picture_id, task)
61
+ VALUES
62
+ (NEW.id, 'prepare');
63
+ RETURN NEW;
64
+ END;
65
+ $BODY$ LANGUAGE plpgsql;
66
+
67
+ -- Link the job_history table to the new job_queue table
68
+
69
+ ALTER TABLE job_history ADD COLUMN job_id UUID; -- do not add a foreign key constraint yet since the job is only temporarily in the job_queue and cannot add non nullity for old history
70
+ ALTER TABLE job_history ADD COLUMN upload_set_id UUID REFERENCES upload_sets(id) ON DELETE CASCADE;
71
+ ALTER TABLE job_history ADD COLUMN sequence_id UUID REFERENCES sequences(id) ON DELETE CASCADE;
72
+
73
+ ALTER TABLE job_history ADD COLUMN job_task job_type NOT NULL DEFAULT 'prepare';
74
+ ALTER TABLE job_history ALTER COLUMN picture_id DROP NOT NULL;
75
+ ALTER TABLE job_history
76
+ ADD CONSTRAINT one_external_id CHECK (num_nonnulls(picture_id, upload_set_id, sequence_id) = 1);
77
+
78
+ UPDATE job_history SET job_task = case WHEN task = 'delete' THEN 'delete'::job_type ELSE 'prepare'::job_type END where job_task IS NULL;
79
+
80
+
81
+ CREATE INDEX job_history_upload_set_id_idx ON job_history(upload_set_id);
82
+ CREATE INDEX job_history_sequence_id_idx ON job_history(sequence_id);
83
+
84
+ -- add a trigger on upload_set completion to dispatch it
85
+ CREATE
86
+ OR REPLACE FUNCTION upload_set_completion() RETURNS TRIGGER AS $BODY$ BEGIN
87
+
88
+ IF NEW.completed THEN
89
+ INSERT INTO
90
+ job_queue(upload_set_id, task)
91
+ VALUES
92
+ (NEW.id, 'dispatch')
93
+ ON CONFLICT (upload_set_id) DO UPDATE SET ts = CURRENT_TIMESTAMP;
94
+ END IF;
95
+ RETURN NEW;
96
+ END;
97
+ $BODY$ LANGUAGE plpgsql;
98
+
99
+ CREATE TRIGGER upload_sets_completion_trg
100
+ AFTER UPDATE OF completed ON upload_sets
101
+ FOR EACH ROW EXECUTE FUNCTION upload_set_completion();
102
+
103
+ -- Create a collation to sort file names using natural sort (with numbers mixed with letters)
104
+ CREATE COLLATION numeric_file_names (provider = icu, locale = 'en@colNumeric=yes');
@@ -0,0 +1,4 @@
1
+ -- upload_set_metadata
2
+ -- depends: 20240708_01_Xn7IH-job-queue
3
+
4
+ ALTER TABLE upload_sets DROP COLUMN metadata;
@@ -0,0 +1,5 @@
1
+ -- upload_set_metadata
2
+ -- depends: 20240708_01_Xn7IH-job-queue
3
+
4
+ ALTER TABLE upload_sets
5
+ ADD COLUMN metadata jsonb;
@@ -0,0 +1,7 @@
1
+ -- upload_set files
2
+ -- depends: 20240715_01_Hca9V-upload-set-metadata
3
+
4
+ DROP TABLE files;
5
+ DROP TYPE file_type;
6
+
7
+ DROP INDEX pictures_upload_set_idx;
@@ -0,0 +1,29 @@
1
+ -- upload_set files
2
+ -- depends: 20240715_01_Hca9V-upload-set-metadata
3
+
4
+ -- transactional: false
5
+
6
+ BEGIN;
7
+ -- Note: for the moment we only support pictures, but later we might accept more kind of files (like gpx traces, video, ...)
8
+ CREATE TYPE file_type AS ENUM (
9
+ 'picture'
10
+ );
11
+
12
+ CREATE TABLE files(
13
+ upload_set_id UUID NOT NULL REFERENCES upload_sets(id) ON DELETE CASCADE,
14
+ picture_id UUID REFERENCES pictures(id) ON DELETE CASCADE, -- some files might not be associated to a picture
15
+ inserted_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
16
+ file_type file_type NOT NULL,
17
+ size INT NOT NULL,
18
+ file_name VARCHAR NOT NULL,
19
+ content_md5 UUID NOT NULL,
20
+ rejection_reason VARCHAR
21
+ );
22
+
23
+ -- We consider that the file_name should be unique for a given upload_set, this way we can detect if an upload is an update of an existing file
24
+ CREATE UNIQUE INDEX files_upload_set_name_idx ON files(upload_set_id, file_name);
25
+
26
+ COMMIT;
27
+
28
+ -- also add an index on upload_set_id for the pictures table
29
+ CREATE INDEX CONCURRENTLY pictures_upload_set_idx ON pictures(upload_set_id);
@@ -0,0 +1,18 @@
1
+ -- upload_set_sort
2
+ -- depends: 20240723_01_ePGFe-upload-set-files
3
+ CREATE TYPE upload_set_sort_method_new AS ENUM (
4
+ 'filename_asc',
5
+ 'filename_desc',
6
+ 'time_asc',
7
+ 'time_desc'
8
+ );
9
+ ALTER TABLE upload_sets
10
+ ALTER COLUMN sort_method DROP DEFAULT;
11
+ ALTER TABLE upload_sets
12
+ ALTER COLUMN sort_method TYPE upload_set_sort_method_new USING sort_method::text::upload_set_sort_method_new;
13
+ ALTER TABLE upload_sets
14
+ ALTER COLUMN sort_method
15
+ SET DEFAULT 'time_asc';
16
+ DROP TYPE upload_set_sort_method;
17
+ ALTER TYPE upload_set_sort_method_new
18
+ RENAME TO upload_set_sort_method;
@@ -0,0 +1,18 @@
1
+ -- upload_set_sort
2
+ -- depends: 20240723_01_ePGFe-upload-set-files
3
+ CREATE TYPE upload_set_sort_method_new AS ENUM (
4
+ 'filename-asc',
5
+ 'filename-desc',
6
+ 'time-asc',
7
+ 'time-desc'
8
+ );
9
+ ALTER TABLE upload_sets
10
+ ALTER COLUMN sort_method DROP DEFAULT;
11
+ ALTER TABLE upload_sets
12
+ ALTER COLUMN sort_method TYPE upload_set_sort_method_new USING sort_method::text::upload_set_sort_method_new;
13
+ ALTER TABLE upload_sets
14
+ ALTER COLUMN sort_method
15
+ SET DEFAULT 'time-asc';
16
+ DROP TYPE upload_set_sort_method;
17
+ ALTER TYPE upload_set_sort_method_new
18
+ RENAME TO upload_set_sort_method;