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.
- geovisio/__init__.py +30 -2
- geovisio/admin_cli/db.py +1 -1
- geovisio/db_migrations.py +2 -2
- geovisio/migrations/20221201_01_wpCGc-initial-schema.rollback.sql +9 -0
- geovisio/migrations/20221201_01_wpCGc-initial-schema.sql +71 -0
- geovisio/migrations/20221201_02_ZG8AR-camera-information.rollback.sql +5 -0
- geovisio/migrations/20221201_02_ZG8AR-camera-information.sql +10 -0
- geovisio/migrations/20221222_01_fsB6f-add-account.rollback.sql +7 -0
- geovisio/migrations/20221222_01_fsB6f-add-account.sql +33 -0
- geovisio/migrations/20230113_01_0co97-rm-metadata-duplicates.rollback.sql +5 -0
- geovisio/migrations/20230113_01_0co97-rm-metadata-duplicates.sql +5 -0
- geovisio/migrations/20230116_01_9PkjZ-add-oauth-provider.rollback.sql +12 -0
- geovisio/migrations/20230116_01_9PkjZ-add-oauth-provider.sql +10 -0
- geovisio/migrations/20230117_01_K71Pd-pictures-ts-index.rollback.sql +4 -0
- geovisio/migrations/20230117_01_K71Pd-pictures-ts-index.sql +4 -0
- geovisio/migrations/20230130_01_VRIv2-sequences-account.rollback.sql +5 -0
- geovisio/migrations/20230130_01_VRIv2-sequences-account.sql +25 -0
- geovisio/migrations/20230324_01_ba9WA-status.rollback.sql +35 -0
- geovisio/migrations/20230324_01_ba9WA-status.sql +11 -0
- geovisio/migrations/20230324_02_efgI6-picture-process.rollback.sql +20 -0
- geovisio/migrations/20230324_02_efgI6-picture-process.sql +44 -0
- geovisio/migrations/20230407_01_wofh1-computed-headings.rollback.sql +6 -0
- geovisio/migrations/20230407_01_wofh1-computed-headings.sql +6 -0
- geovisio/migrations/20230417_01_ZgLMY-add-exif-metadata-column-for-pictures.rollback.sql +4 -0
- geovisio/migrations/20230417_01_ZgLMY-add-exif-metadata-column-for-pictures.sql +4 -0
- geovisio/migrations/20230420_01_elaN3-remove-picture-and-sequence-file-paths.rollback.sql +5 -0
- geovisio/migrations/20230420_01_elaN3-remove-picture-and-sequence-file-paths.sql +5 -0
- geovisio/migrations/20230425_01_gYP77-pictures-edits-triggers.rollback.sql +5 -0
- geovisio/migrations/20230425_01_gYP77-pictures-edits-triggers.sql +64 -0
- geovisio/migrations/20230427_01_k5e5w-timestamps.rollback.sql +10 -0
- geovisio/migrations/20230427_01_k5e5w-timestamps.sql +19 -0
- geovisio/migrations/20230511_01_TdpKo-tokens.rollback.sql +7 -0
- geovisio/migrations/20230511_01_TdpKo-tokens.sql +34 -0
- geovisio/migrations/20230615_01_u7aRf-pic-delete-cascade.rollback.sql +10 -0
- geovisio/migrations/20230615_01_u7aRf-pic-delete-cascade.sql +12 -0
- geovisio/migrations/20230623_01_y1SiQ-pic-deletion-task.rollback.sql +39 -0
- geovisio/migrations/20230623_01_y1SiQ-pic-deletion-task.sql +36 -0
- geovisio/migrations/20230629_01_ZdB3i-compute-heading-0.sql +27 -0
- geovisio/migrations/20230711_01_JGSPB-inserted-at-index.rollback.sql +4 -0
- geovisio/migrations/20230711_01_JGSPB-inserted-at-index.sql +4 -0
- geovisio/migrations/20230720_01_EyQ0e-sequences-summary.rollback.sql +7 -0
- geovisio/migrations/20230720_01_EyQ0e-sequences-summary.sql +26 -0
- geovisio/migrations/20230803_01_aXusm-fix-sequence-computed.rollback.sql +4 -0
- geovisio/migrations/20230803_01_aXusm-fix-sequence-computed.sql +25 -0
- geovisio/migrations/20231018_01_4G3YE-pictures-exiv2.rollback.sql +165 -0
- geovisio/migrations/20231018_01_4G3YE-pictures-exiv2.sql +206 -0
- geovisio/migrations/20231103_01_ZVKEm-update-seq-on-pic-change.rollback.sql +7 -0
- geovisio/migrations/20231103_01_ZVKEm-update-seq-on-pic-change.sql +28 -0
- geovisio/migrations/20231110_01_3p070-jobs-error.rollback.sql +7 -0
- geovisio/migrations/20231110_01_3p070-jobs-error.sql +93 -0
- geovisio/migrations/20231121_01_v6oBF-more-specific-triggers.rollback.sql +36 -0
- geovisio/migrations/20231121_01_v6oBF-more-specific-triggers.sql +40 -0
- geovisio/migrations/20231121_02_1uZXT-deleted-tag.rollback.sql +19 -0
- geovisio/migrations/20231121_02_1uZXT-deleted-tag.sql +13 -0
- geovisio/migrations/20240115_01_FatLR-token-delete-cascade.rollback.sql +6 -0
- geovisio/migrations/20240115_01_FatLR-token-delete-cascade.sql +7 -0
- geovisio/migrations/20240220_01_9wZs0-sequence-current-sort.rollback.sql +6 -0
- geovisio/migrations/20240220_01_9wZs0-sequence-current-sort.sql +15 -0
- geovisio/migrations/20240223_01_LsMHB-remove-binary-fields.sql +80 -0
- geovisio/migrations/20240226_01_8iXl1-track-changes.rollback.sql +13 -0
- geovisio/migrations/20240226_01_8iXl1-track-changes.sql +123 -0
- geovisio/migrations/20240229_01_SgfQY-sequence-geom-multi-linestring.rollback.sql +67 -0
- geovisio/migrations/20240229_01_SgfQY-sequence-geom-multi-linestring.sql +101 -0
- geovisio/migrations/20240308_01_aF0Jb-migrate-sequence-geom-multi-linestring.sql +52 -0
- geovisio/migrations/20240409_01_jnhra-pictures-grid.rollback.sql +3 -0
- geovisio/migrations/20240409_01_jnhra-pictures-grid.sql +21 -0
- geovisio/migrations/20240416_01_FpyGs-pictures-stats-on-sequences.rollback.sql +7 -0
- geovisio/migrations/20240416_01_FpyGs-pictures-stats-on-sequences.sql +9 -0
- geovisio/migrations/20240416_02_A5KzC-fill-pictures-stats-on-sequences.rollback.sql +5 -0
- geovisio/migrations/20240416_02_A5KzC-fill-pictures-stats-on-sequences.sql +84 -0
- geovisio/migrations/20240507_01_eBfqZ-refresh-table.rollback.sql +5 -0
- geovisio/migrations/20240507_01_eBfqZ-refresh-table.sql +9 -0
- geovisio/migrations/20240507_02_dzVET-picture-grid-public.rollback.sql +21 -0
- geovisio/migrations/20240507_02_dzVET-picture-grid-public.sql +26 -0
- geovisio/migrations/20240514_01_IT7DD-picture-delete-cascade.rollback.sql +41 -0
- geovisio/migrations/20240514_01_IT7DD-picture-delete-cascade.sql +42 -0
- geovisio/migrations/20240611_01_jftHn-content-md5.rollback.sql +5 -0
- geovisio/migrations/20240611_01_jftHn-content-md5.sql +7 -0
- geovisio/migrations/20240612_01_yNcuE-upload-set.rollback.sql +6 -0
- geovisio/migrations/20240612_01_yNcuE-upload-set.sql +46 -0
- geovisio/migrations/20240617_01_tKtlx-md5-concurrent-index.rollback.sql +4 -0
- geovisio/migrations/20240617_01_tKtlx-md5-concurrent-index.sql +8 -0
- geovisio/migrations/20240625_01_XMZ24-fix-sequence-stat-on-pic-insertion.rollback.sql +30 -0
- geovisio/migrations/20240625_01_XMZ24-fix-sequence-stat-on-pic-insertion.sql +31 -0
- geovisio/migrations/20240708_01_Xn7IH-job-queue.rollback.sql +31 -0
- geovisio/migrations/20240708_01_Xn7IH-job-queue.sql +104 -0
- geovisio/migrations/20240715_01_Hca9V-upload-set-metadata.rollback.sql +4 -0
- geovisio/migrations/20240715_01_Hca9V-upload-set-metadata.sql +5 -0
- geovisio/migrations/20240723_01_ePGFe-upload-set-files.rollback.sql +7 -0
- geovisio/migrations/20240723_01_ePGFe-upload-set-files.sql +29 -0
- geovisio/migrations/20240729_01_HALjj-upload-set-sort.rollback.sql +18 -0
- geovisio/migrations/20240729_01_HALjj-upload-set-sort.sql +18 -0
- geovisio/migrations/20240730_01_2BaCy-improve-deletion-triggers.rollback.sql +34 -0
- geovisio/migrations/20240730_01_2BaCy-improve-deletion-triggers.sql +53 -0
- geovisio/migrations/20240730_02_aRymN-rejection-status.rollback.sql +10 -0
- geovisio/migrations/20240730_02_aRymN-rejection-status.sql +16 -0
- geovisio/migrations/20240801_01_DOqmf-reports.rollback.sql +11 -0
- geovisio/migrations/20240801_01_DOqmf-reports.sql +100 -0
- geovisio/migrations/20240801_01_uKqPo-remove-files-delete-cascade.rollback.sql +13 -0
- geovisio/migrations/20240801_01_uKqPo-remove-files-delete-cascade.sql +13 -0
- geovisio/migrations/20240813_01_T1XkO-sequences-geom-splits.rollback.sql +42 -0
- geovisio/migrations/20240813_01_T1XkO-sequences-geom-splits.sql +56 -0
- geovisio/migrations/20240820_01_aB2ZK-exclusion-zones.rollback.sql +6 -0
- geovisio/migrations/20240820_01_aB2ZK-exclusion-zones.sql +49 -0
- geovisio/migrations/20240902_01_MDqSj-user-agent.rollback.sql +5 -0
- geovisio/migrations/20240902_01_MDqSj-user-agent.sql +10 -0
- geovisio/migrations/20240904_01_gFjlV-files-rejection-msg.rollback.sql +4 -0
- geovisio/migrations/20240904_01_gFjlV-files-rejection-msg.sql +4 -0
- geovisio/migrations/20240905_01_C8F6U-conflicts.rollback.sql +13 -0
- geovisio/migrations/20240905_01_C8F6U-conflicts.sql +6 -0
- geovisio/migrations/20240905_01_E5Ki0-upload-set-delete.rollback.sql +5 -0
- geovisio/migrations/20240905_01_E5Ki0-upload-set-delete.sql +30 -0
- geovisio/migrations/20240909_01_Muc22-unique-grid-index.rollback.sql +4 -0
- geovisio/migrations/20240909_01_Muc22-unique-grid-index.sql +5 -0
- geovisio/migrations/20240912_01_dAALm-account-index.rollback.sql +4 -0
- geovisio/migrations/20240912_01_dAALm-account-index.sql +4 -0
- geovisio/migrations/20241004_01_d1zfe-pictures-grid-360.rollback.sql +22 -0
- geovisio/migrations/20241004_01_d1zfe-pictures-grid-360.sql +24 -0
- geovisio/migrations/20241011_01_e1j5C-pic-quality.rollback.sql +21 -0
- geovisio/migrations/20241011_01_e1j5C-pic-quality.sql +249 -0
- geovisio/migrations/20241017_01_GuOjF-pic-quality-update.rollback.sql +4 -0
- geovisio/migrations/20241017_01_GuOjF-pic-quality-update.sql +61 -0
- geovisio/migrations/20241017_01_RiFlm-pictures-to-delete.rollback.sql +43 -0
- geovisio/migrations/20241017_01_RiFlm-pictures-to-delete.sql +75 -0
- geovisio/migrations/20241104_01_yhRVu-rejection-details.rollback.sql +4 -0
- geovisio/migrations/20241104_01_yhRVu-rejection-details.sql +4 -0
- geovisio/migrations/20241128_01_ugthx-job-queue-args.rollback.sql +25 -0
- geovisio/migrations/20241128_01_ugthx-job-queue-args.sql +31 -0
- geovisio/migrations/20241224_01_xuN6n-delete-upload-set-on-last-picture-trg-statement.rollback.sql +27 -0
- geovisio/migrations/20241224_01_xuN6n-delete-upload-set-on-last-picture-trg-statement.sql +28 -0
- geovisio/migrations/20250102_01_EElhA-rm-cameras.rollback.sql +126 -0
- geovisio/migrations/20250102_01_EElhA-rm-cameras.sql +30 -0
- geovisio/migrations/20250107_01_EQN9v-tags-tables.rollback.sql +10 -0
- geovisio/migrations/20250107_01_EQN9v-tags-tables.sql +58 -0
- geovisio/migrations/20250109_01_4OOP4-pages.rollback.sql +4 -0
- geovisio/migrations/20250109_01_4OOP4-pages.sql +10 -0
- geovisio/migrations/20250114_01_ABaaL-collaborative-metadata-editing.rollback.sql +7 -0
- geovisio/migrations/20250114_01_ABaaL-collaborative-metadata-editing.sql +16 -0
- geovisio/migrations/20250123_01_Ececu-tos-acceptance.rollback.sql +5 -0
- geovisio/migrations/20250123_01_Ececu-tos-acceptance.sql +5 -0
- geovisio/migrations/20250206_01_PjrEL-annotation-semantics.rollback.sql +14 -0
- geovisio/migrations/20250206_01_PjrEL-annotation-semantics.sql +15 -0
- geovisio/migrations/20250306_01_58oju-semantics-views.rollback.sql +5 -0
- geovisio/migrations/20250306_01_58oju-semantics-views.sql +52 -0
- geovisio/migrations/20250318_01_pANl1-semantics-functions.rollback.sql +5 -0
- geovisio/migrations/20250318_01_pANl1-semantics-functions.sql +41 -0
- geovisio/migrations/20250331_01_kRKjo-store-detections-id.rollback.sql +7 -0
- geovisio/migrations/20250331_01_kRKjo-store-detections-id.sql +25 -0
- geovisio/migrations/20250424_01_RBGXC-semantics-indexes.rollback.sql +6 -0
- geovisio/migrations/20250424_01_RBGXC-semantics-indexes.sql +6 -0
- geovisio/migrations/20250502_01_ZNmkU-job-task-read-metadata.rollback.sql +24 -0
- geovisio/migrations/20250502_01_ZNmkU-job-task-read-metadata.sql +7 -0
- geovisio/migrations/20250509_01_kMatW-deactivate-upload-set-split-dedup.rollback.sql +12 -0
- geovisio/migrations/20250509_01_kMatW-deactivate-upload-set-split-dedup.sql +12 -0
- geovisio/migrations/20250509_01_s3hYk-semantic-delete-cascade.rollback.sql +11 -0
- geovisio/migrations/20250509_01_s3hYk-semantic-delete-cascade.sql +11 -0
- geovisio/migrations/20250513_01_8WkZC-upload-sets-default-config.rollback.sql +7 -0
- geovisio/migrations/20250513_01_8WkZC-upload-sets-default-config.sql +15 -0
- geovisio/migrations/20250523_01_b11eW-picture-update-index.rollback.sql +85 -0
- geovisio/migrations/20250523_01_b11eW-picture-update-index.sql +166 -0
- geovisio/migrations/20250523_02_5ZXXh-update-picture-updated-at.rollback.sql +4 -0
- geovisio/migrations/20250523_02_5ZXXh-update-picture-updated-at.sql +7 -0
- geovisio/migrations/20250624_01_SETp6-job-warnings.rollback.sql +4 -0
- geovisio/migrations/20250624_01_SETp6-job-warnings.sql +4 -0
- geovisio/migrations/20250701_01_kr371-upload-set-semantics.rollback.sql +6 -0
- geovisio/migrations/20250701_01_kr371-upload-set-semantics.sql +15 -0
- geovisio/migrations/20250703_01_p2WVV-sequence-upload-set-link.rollback.sql +4 -0
- geovisio/migrations/20250703_01_p2WVV-sequence-upload-set-link.sql +4 -0
- geovisio/migrations/20250703_02_q0s3D-sequence-upload-set-fill.rollback.sql +4 -0
- geovisio/migrations/20250703_02_q0s3D-sequence-upload-set-fill.sql +26 -0
- geovisio/migrations/20250716_01_f8tcJ-check-empty-annotation-late.rollback.sql +24 -0
- geovisio/migrations/20250716_01_f8tcJ-check-empty-annotation-late.sql +10 -0
- geovisio/migrations/20250728_01_2zgur-upload-set-relative-heading.rollback.sql +4 -0
- geovisio/migrations/20250728_01_2zgur-upload-set-relative-heading.sql +4 -0
- geovisio/migrations/20250825_01_nCgkN-file-deletion-after-delete-no-dup.rollback.sql +20 -0
- geovisio/migrations/20250825_01_nCgkN-file-deletion-after-delete-no-dup.sql +26 -0
- geovisio/migrations/20250902_01_k5UTq-visibility-status.rollback.sql +11 -0
- geovisio/migrations/20250902_01_k5UTq-visibility-status.sql +19 -0
- geovisio/migrations/20250904_01_3uVKX-visibility-functions.rollback.sql +20 -0
- geovisio/migrations/20250904_01_3uVKX-visibility-functions.sql +43 -0
- geovisio/migrations/20251110_01_bWEXo-report-visibility.rollback.sql +30 -0
- geovisio/migrations/20251110_01_bWEXo-report-visibility.sql +30 -0
- geovisio/migrations/20251124_01_0xdqi-page-updates.rollback.sql +6 -0
- geovisio/migrations/20251124_01_0xdqi-page-updates.sql +8 -0
- geovisio/migrations/20251127_01_S6Ci8-pictures-grid-visibility.rollback.sql +24 -0
- geovisio/migrations/20251127_01_S6Ci8-pictures-grid-visibility.sql +36 -0
- geovisio/migrations/20251202_01_Q3g59-pictures-grid-logged-only.rollback.sql +32 -0
- geovisio/migrations/20251202_01_Q3g59-pictures-grid-logged-only.sql +34 -0
- geovisio/templates/main.html +7 -58
- geovisio/templates/viewer.html +8 -15
- geovisio/translations/cy/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/cy/LC_MESSAGES/messages.po +839 -0
- geovisio/translations/en/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/en/LC_MESSAGES/messages.po +155 -149
- geovisio/translations/messages.pot +131 -150
- geovisio/utils/cql2.py +22 -17
- geovisio/utils/link.py +13 -3
- geovisio/utils/upload_set.py +42 -2
- geovisio/web/collections.py +80 -40
- geovisio/web/docs.py +1 -1
- geovisio/web/items.py +54 -4
- geovisio/web/upload_set.py +2 -3
- geovisio/web/users.py +1 -1
- {geovisio-2.11.0.dist-info → geovisio-2.12.0.dist-info}/METADATA +6 -26
- geovisio-2.12.0.dist-info/RECORD +305 -0
- geovisio-2.12.0.dist-info/entry_points.txt +3 -0
- geovisio-2.11.0.dist-info/RECORD +0 -117
- {geovisio-2.11.0.dist-info → geovisio-2.12.0.dist-info}/WHEEL +0 -0
- {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,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,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,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,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,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;
|