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,93 @@
|
|
|
1
|
+
-- jobs_error
|
|
2
|
+
-- depends: 20231103_01_ZVKEm-update-seq-on-pic-change
|
|
3
|
+
-- transactional: false
|
|
4
|
+
-- Note: this migration is not in a transaction, since the transactions will be created inside it to update the `pictures` table (which can be very big) in batches
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
-- Add a job_history tables to log all async jobs
|
|
8
|
+
-- Note: error replace `pictures.process_error` and `pictures_to_process.nb_errors` replace `pictures.nb_errors`
|
|
9
|
+
-- Those fields are note removed right away for a smooth database migration transition, but should be removed afterward
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
CREATE TABLE job_history(
|
|
13
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
14
|
+
picture_id UUID NOT NULL REFERENCES pictures(id) ON DELETE CASCADE,
|
|
15
|
+
task picture_process_task,
|
|
16
|
+
started_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
17
|
+
finished_at TIMESTAMPTZ,
|
|
18
|
+
error VARCHAR
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
CREATE INDEX job_history_picture_id_idx ON job_history(picture_id);
|
|
24
|
+
|
|
25
|
+
ALTER TABLE pictures_to_process ADD COLUMN nb_errors INT NOT NULL DEFAULT 0;
|
|
26
|
+
|
|
27
|
+
CREATE INDEX pictures_to_process_nb_errors_ts_idx ON pictures_to_process(nb_errors, ts);
|
|
28
|
+
|
|
29
|
+
CREATE TYPE picture_preparing_status AS ENUM (
|
|
30
|
+
'not-processed', -- Default state, the picture has not been processed yet
|
|
31
|
+
'prepared', -- State when the picture has been correctly prepared
|
|
32
|
+
'broken' -- State when the picture has not been correctly processed
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
ALTER TABLE pictures ADD COLUMN preparing_status picture_preparing_status NOT NULL DEFAULT 'not-processed';
|
|
36
|
+
|
|
37
|
+
CREATE OR REPLACE PROCEDURE update_all_pictures_preparing_status() AS
|
|
38
|
+
$$
|
|
39
|
+
DECLARE
|
|
40
|
+
last_inserted_at TIMESTAMPTZ;
|
|
41
|
+
BEGIN
|
|
42
|
+
SELECT min(inserted_at) - INTERVAL '1 minute' FROM pictures INTO last_inserted_at;
|
|
43
|
+
|
|
44
|
+
WHILE last_inserted_at IS NOT NULL LOOP
|
|
45
|
+
|
|
46
|
+
-- remove triggers on picture before updating the table
|
|
47
|
+
DROP TRIGGER pictures_update_sequences_trg ON pictures;
|
|
48
|
+
DROP TRIGGER pictures_updates_on_sequences_trg ON pictures;
|
|
49
|
+
|
|
50
|
+
WITH
|
|
51
|
+
pic_to_update AS (
|
|
52
|
+
SELECT id, inserted_at from pictures where inserted_at > last_inserted_at ORDER BY inserted_at ASC LIMIT 100000
|
|
53
|
+
)
|
|
54
|
+
, updated_pic AS (
|
|
55
|
+
-- Populate table with values based on the `status` column
|
|
56
|
+
UPDATE pictures
|
|
57
|
+
SET preparing_status =
|
|
58
|
+
CASE
|
|
59
|
+
WHEN status IN ('hidden', 'ready') THEN 'prepared'::picture_preparing_status
|
|
60
|
+
WHEN status = 'broken' THEN 'broken'::picture_preparing_status
|
|
61
|
+
ELSE 'not-processed'
|
|
62
|
+
END
|
|
63
|
+
WHERE id in (SELECT id FROM pic_to_update)
|
|
64
|
+
)
|
|
65
|
+
SELECT MAX(inserted_at) FROM pic_to_update INTO last_inserted_at;
|
|
66
|
+
|
|
67
|
+
RAISE NOTICE 'max insertion date is now %', last_inserted_at;
|
|
68
|
+
|
|
69
|
+
-- put back triggers
|
|
70
|
+
CREATE TRIGGER pictures_updates_on_sequences_trg
|
|
71
|
+
AFTER UPDATE ON pictures
|
|
72
|
+
REFERENCING NEW TABLE AS pictures_after
|
|
73
|
+
FOR EACH STATEMENT
|
|
74
|
+
EXECUTE FUNCTION pictures_updates_on_sequences();
|
|
75
|
+
|
|
76
|
+
CREATE TRIGGER pictures_update_sequences_trg
|
|
77
|
+
AFTER UPDATE ON pictures
|
|
78
|
+
REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
|
|
79
|
+
FOR EACH STATEMENT EXECUTE FUNCTION pictures_update_sequence();
|
|
80
|
+
|
|
81
|
+
-- commit batch of change
|
|
82
|
+
COMMIT;
|
|
83
|
+
END LOOP;
|
|
84
|
+
|
|
85
|
+
RAISE NOTICE 'update finished';
|
|
86
|
+
END
|
|
87
|
+
$$ LANGUAGE plpgsql;
|
|
88
|
+
|
|
89
|
+
CALL update_all_pictures_preparing_status();
|
|
90
|
+
|
|
91
|
+
DROP PROCEDURE update_all_pictures_preparing_status;
|
|
92
|
+
|
|
93
|
+
CREATE INDEX pictures_preparing_status_idx ON pictures(preparing_status);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- more specific triggers
|
|
2
|
+
-- depends: 20231110_01_3p070-jobs-error
|
|
3
|
+
|
|
4
|
+
-- put old version of the triggers
|
|
5
|
+
|
|
6
|
+
DROP FUNCTION IF EXISTS pictures_update_sequence CASCADE;
|
|
7
|
+
CREATE FUNCTION pictures_update_sequence() RETURNS trigger AS $$
|
|
8
|
+
BEGIN
|
|
9
|
+
UPDATE sequences
|
|
10
|
+
SET geom = s.geom
|
|
11
|
+
FROM (
|
|
12
|
+
SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
|
|
13
|
+
FROM (
|
|
14
|
+
SELECT sp.seq_id, sp.rank, p.geom
|
|
15
|
+
FROM sequences_pictures sp
|
|
16
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
17
|
+
WHERE sp.seq_id IN (
|
|
18
|
+
SELECT DISTINCT sequences_pictures.seq_id
|
|
19
|
+
FROM old_table
|
|
20
|
+
JOIN new_table USING (id)
|
|
21
|
+
JOIN sequences_pictures ON sequences_pictures.pic_id = new_table.id
|
|
22
|
+
WHERE new_table.status != old_table.status OR NOT ST_Equals(old_table.geom, new_table.geom)
|
|
23
|
+
)
|
|
24
|
+
ORDER BY sp.seq_id, sp.rank
|
|
25
|
+
) sp
|
|
26
|
+
GROUP BY seq_id
|
|
27
|
+
) s
|
|
28
|
+
WHERE sequences.id = s.seq_id;
|
|
29
|
+
RETURN NULL;
|
|
30
|
+
END $$ LANGUAGE plpgsql;
|
|
31
|
+
|
|
32
|
+
CREATE TRIGGER pictures_update_sequences_trg
|
|
33
|
+
AFTER UPDATE ON pictures
|
|
34
|
+
REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
|
|
35
|
+
FOR EACH STATEMENT EXECUTE FUNCTION pictures_update_sequence();
|
|
36
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
-- more specific triggers
|
|
2
|
+
-- depends: 20231110_01_3p070-jobs-error
|
|
3
|
+
|
|
4
|
+
-- Add more specific names and conditions on the trigger on pictures
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
-- This trigger only update the sequence geometry, so we can fire it only on update of geom
|
|
8
|
+
DROP TRIGGER pictures_update_sequences_trg ON pictures;
|
|
9
|
+
|
|
10
|
+
-- The function need to be changed since we now only triggers it from 1 column change, and in the meantime rename the function to a more specific name
|
|
11
|
+
-- In the meantime, rename the function to be more specific
|
|
12
|
+
DROP FUNCTION IF EXISTS pictures_update_sequence CASCADE;
|
|
13
|
+
DROP FUNCTION IF EXISTS pictures_update_geom_sequence CASCADE;
|
|
14
|
+
CREATE FUNCTION pictures_update_geom_sequence() RETURNS trigger AS $$
|
|
15
|
+
BEGIN
|
|
16
|
+
UPDATE sequences
|
|
17
|
+
SET geom = s.geom
|
|
18
|
+
FROM (
|
|
19
|
+
SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
|
|
20
|
+
FROM (
|
|
21
|
+
SELECT sp.seq_id, p.geom
|
|
22
|
+
FROM sequences_pictures sp
|
|
23
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
24
|
+
WHERE sp.seq_id IN (
|
|
25
|
+
SELECT DISTINCT sequences_pictures.seq_id
|
|
26
|
+
FROM sequences_pictures
|
|
27
|
+
WHERE sequences_pictures.pic_id = NEW.id
|
|
28
|
+
)
|
|
29
|
+
ORDER BY sp.seq_id, sp.rank
|
|
30
|
+
) sp
|
|
31
|
+
GROUP BY seq_id
|
|
32
|
+
) s
|
|
33
|
+
WHERE sequences.id = s.seq_id;
|
|
34
|
+
RETURN NULL;
|
|
35
|
+
END $$ LANGUAGE plpgsql;
|
|
36
|
+
|
|
37
|
+
CREATE TRIGGER pictures_update_sequences_geom_trg
|
|
38
|
+
AFTER UPDATE OF geom ON pictures
|
|
39
|
+
FOR EACH ROW EXECUTE FUNCTION pictures_update_geom_sequence();
|
|
40
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- deleted_tag
|
|
2
|
+
-- depends: 20231121_01_v6oBF-more-specific-triggers
|
|
3
|
+
|
|
4
|
+
-- since PG does not support removing values from enum, we create a new sequence status with old values
|
|
5
|
+
|
|
6
|
+
CREATE TYPE sequence_status_new AS ENUM (
|
|
7
|
+
'preparing',
|
|
8
|
+
'broken',
|
|
9
|
+
'ready',
|
|
10
|
+
'hidden',
|
|
11
|
+
'waiting-for-process'
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
alter table sequences ALTER COLUMN status DROP DEFAULT;
|
|
15
|
+
alter table sequences ALTER COLUMN status TYPE sequence_status_new USING status::text::sequence_status_new;
|
|
16
|
+
alter table sequences ALTER COLUMN status SET DEFAULT 'waiting-for-process';
|
|
17
|
+
|
|
18
|
+
DROP TYPE sequence_status;
|
|
19
|
+
ALTER TYPE sequence_status_new RENAME TO sequence_status;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- deleted_tag
|
|
2
|
+
-- depends: 20231121_01_v6oBF-more-specific-triggers
|
|
3
|
+
|
|
4
|
+
-- type cannot be altered in a transaction, so we ask yolo not to create one
|
|
5
|
+
-- transactional: false
|
|
6
|
+
|
|
7
|
+
ALTER TYPE sequence_status ADD VALUE 'deleted';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
CREATE OR REPLACE FUNCTION is_sequence_visible_by_user(seq sequences, account_id UUID) RETURNS boolean AS $$
|
|
11
|
+
SELECT seq.status != 'deleted' AND (seq.status = 'ready' OR seq.account_id = account_id);
|
|
12
|
+
$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE COST 10;
|
|
13
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- sequence_current_sort
|
|
2
|
+
-- depends: 20240115_01_FatLR-token-delete-cascade
|
|
3
|
+
|
|
4
|
+
CREATE TYPE sequence_sort AS ENUM (
|
|
5
|
+
'+filedate', -- Sort by ascending camera date
|
|
6
|
+
'+filename', -- Sort by ascending filename
|
|
7
|
+
'+gpsdate', -- Sort by ascending gps date
|
|
8
|
+
'-filedate', -- Sort by descending camera date
|
|
9
|
+
'-filename', -- Sort by descending filename
|
|
10
|
+
'-gpsdate' -- Sort by descending gps date
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
-- Add a column to persist the user defined sort
|
|
14
|
+
-- nullable since by default no sort is chosen
|
|
15
|
+
ALTER TABLE sequences ADD COLUMN current_sort sequence_sort;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
-- remove_binary_fields
|
|
2
|
+
-- depends: 20240115_01_FatLR-token-delete-cascade
|
|
3
|
+
|
|
4
|
+
-- We want to run a vacuum after the migration, we cannot have a transaction around it
|
|
5
|
+
-- transactional: false
|
|
6
|
+
|
|
7
|
+
CREATE OR REPLACE PROCEDURE remove_maker_notes_from_all_pictures() AS
|
|
8
|
+
$$
|
|
9
|
+
DECLARE
|
|
10
|
+
last_inserted_at TIMESTAMPTZ;
|
|
11
|
+
BEGIN
|
|
12
|
+
SELECT min(inserted_at) - INTERVAL '1 minute' FROM pictures INTO last_inserted_at;
|
|
13
|
+
|
|
14
|
+
WHILE last_inserted_at IS NOT NULL LOOP
|
|
15
|
+
|
|
16
|
+
-- Temporary removal of all update triggers
|
|
17
|
+
DROP TRIGGER pictures_updates_on_sequences_trg ON pictures;
|
|
18
|
+
|
|
19
|
+
WITH
|
|
20
|
+
-- get a batch of 100 000 pictures to update
|
|
21
|
+
pic_to_update AS (
|
|
22
|
+
SELECT id, inserted_at from pictures where inserted_at > last_inserted_at ORDER BY inserted_at ASC LIMIT 100000
|
|
23
|
+
)
|
|
24
|
+
, updated_pic AS (
|
|
25
|
+
-- List of binary fields to remove.
|
|
26
|
+
-- The most important here is `MakerNote` that takes a lot of useless space, but we decided not to store any binary fields, as they will be difficult to use
|
|
27
|
+
-- Note: they are still in the pictures if needed
|
|
28
|
+
UPDATE pictures
|
|
29
|
+
SET
|
|
30
|
+
exif = exif - ARRAY[
|
|
31
|
+
'Exif.Photo.MakerNote',
|
|
32
|
+
'Exif.Photo.0xea1c',
|
|
33
|
+
'Exif.Image.0xea1c',
|
|
34
|
+
'Exif.Canon.CameraInfo',
|
|
35
|
+
'Exif.Image.PrintImageMatching',
|
|
36
|
+
'Exif.Image.0xc6d3',
|
|
37
|
+
'Exif.Panasonic.FaceDetInfo',
|
|
38
|
+
'Exif.Panasonic.DataDump',
|
|
39
|
+
'Exif.Image.0xc6d2',
|
|
40
|
+
'Exif.Canon.CustomFunctions',
|
|
41
|
+
'Exif.Canon.AFInfo',
|
|
42
|
+
'Exif.Canon.0x4011',
|
|
43
|
+
'Exif.Canon.0x4019',
|
|
44
|
+
'Exif.Canon.ColorData',
|
|
45
|
+
'Exif.Canon.DustRemovalData',
|
|
46
|
+
'Exif.Canon.VignettingCorr',
|
|
47
|
+
'Exif.Canon.AFInfo3',
|
|
48
|
+
'Exif.Canon.0x001f',
|
|
49
|
+
'Exif.Canon.0x0018',
|
|
50
|
+
'Exif.Canon.ContrastInfo',
|
|
51
|
+
'Exif.Canon.0x002e',
|
|
52
|
+
'Exif.Canon.0x0022',
|
|
53
|
+
'Exif.Photo.0x9aaa'
|
|
54
|
+
]
|
|
55
|
+
WHERE id in (SELECT id FROM pic_to_update)
|
|
56
|
+
)
|
|
57
|
+
SELECT MAX(inserted_at) FROM pic_to_update INTO last_inserted_at;
|
|
58
|
+
|
|
59
|
+
RAISE NOTICE 'max insertion date is now %', last_inserted_at;
|
|
60
|
+
|
|
61
|
+
-- Restore all deactivated triggers
|
|
62
|
+
CREATE TRIGGER pictures_updates_on_sequences_trg
|
|
63
|
+
AFTER UPDATE ON pictures
|
|
64
|
+
REFERENCING NEW TABLE AS pictures_after
|
|
65
|
+
FOR EACH STATEMENT
|
|
66
|
+
EXECUTE FUNCTION pictures_updates_on_sequences();
|
|
67
|
+
|
|
68
|
+
-- commit transaction (as a procedure is in an implicit transaction, it will start a new transaction after this)
|
|
69
|
+
COMMIT;
|
|
70
|
+
END LOOP;
|
|
71
|
+
|
|
72
|
+
-- After this, we need to do a full vacuum to clean dead tuples
|
|
73
|
+
RAISE NOTICE 'Binary fields removed, you should run `VACUUM FULL pictures;` afterward (or use something like pg_repack)';
|
|
74
|
+
|
|
75
|
+
END
|
|
76
|
+
$$ LANGUAGE plpgsql;
|
|
77
|
+
|
|
78
|
+
CALL remove_maker_notes_from_all_pictures();
|
|
79
|
+
DROP PROCEDURE remove_maker_notes_from_all_pictures;
|
|
80
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- track_changes
|
|
2
|
+
-- depends: 20240220_01_9wZs0-sequence-current-sort
|
|
3
|
+
|
|
4
|
+
DROP TABLE sequences_changes CASCADE;
|
|
5
|
+
DROP TABLE pictures_changes CASCADE;
|
|
6
|
+
|
|
7
|
+
DROP TRIGGER picture_modification_history_trg ON pictures;
|
|
8
|
+
DROP TRIGGER sequence_modification_history_trg ON sequences;
|
|
9
|
+
|
|
10
|
+
DROP FUNCTION IF EXISTS jsonb_diff, get_sequence_diffable_fields, sequence_modification_history, picture_modification_history CASCADE;
|
|
11
|
+
|
|
12
|
+
ALTER TABLE sequences DROP COLUMN IF EXISTS last_account_to_edit;
|
|
13
|
+
ALTER TABLE pictures DROP COLUMN IF EXISTS last_account_to_edit;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
-- track_changes
|
|
2
|
+
-- depends: 20240220_01_9wZs0-sequence-current-sort
|
|
3
|
+
|
|
4
|
+
CREATE TABLE sequences_changes(
|
|
5
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
6
|
+
sequence_id UUID NOT NULL REFERENCES sequences(id) ON DELETE CASCADE,
|
|
7
|
+
account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
|
8
|
+
|
|
9
|
+
-- json will contains all modified keys, with old db values
|
|
10
|
+
previous_value_changed JSONB,
|
|
11
|
+
|
|
12
|
+
ts TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX sequences_changes_seq_id_idx ON sequences_changes(sequence_id);
|
|
16
|
+
|
|
17
|
+
CREATE TABLE pictures_changes(
|
|
18
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
19
|
+
picture_id UUID NOT NULL REFERENCES pictures(id) ON DELETE CASCADE,
|
|
20
|
+
account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
|
21
|
+
-- If the changes is part of global changes on a sequence, id of that change
|
|
22
|
+
sequences_changes_id UUID REFERENCES sequences_changes(id),
|
|
23
|
+
|
|
24
|
+
-- json will contains all modified keys, with old db values
|
|
25
|
+
previous_value_changed JSONB,
|
|
26
|
+
|
|
27
|
+
ts TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
28
|
+
);
|
|
29
|
+
CREATE INDEX pictures_changes_pic_id_idx ON pictures_changes(picture_id);
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
ALTER TABLE sequences ADD COLUMN IF NOT EXISTS last_account_to_edit UUID;
|
|
33
|
+
ALTER TABLE sequences ADD CONSTRAINT last_account_to_edit_fk_id FOREIGN KEY (last_account_to_edit) REFERENCES accounts (id) ON DELETE CASCADE;
|
|
34
|
+
|
|
35
|
+
ALTER TABLE pictures ADD COLUMN IF NOT EXISTS last_account_to_edit UUID;
|
|
36
|
+
ALTER TABLE pictures ADD CONSTRAINT last_account_to_edit_fk_id FOREIGN KEY (last_account_to_edit) REFERENCES accounts (id) ON DELETE CASCADE;
|
|
37
|
+
|
|
38
|
+
CREATE OR REPLACE FUNCTION jsonb_diff(IN a jsonb, IN b jsonb) RETURNS jsonb AS
|
|
39
|
+
$BODY$
|
|
40
|
+
SELECT jsonb_object_agg(key, value)
|
|
41
|
+
FROM (
|
|
42
|
+
SELECT * FROM jsonb_each(to_jsonb(a))
|
|
43
|
+
EXCEPT SELECT * FROM jsonb_each(to_jsonb(b))
|
|
44
|
+
) as t;
|
|
45
|
+
$BODY$
|
|
46
|
+
LANGUAGE SQL IMMUTABLE STRICT;
|
|
47
|
+
|
|
48
|
+
COMMENT ON FUNCTION jsonb_diff IS 'Create a Json with all the key/values that are in the first one and not in the second. Only works for top level fields';
|
|
49
|
+
|
|
50
|
+
-- We only consider a specified set of fields. If we want to track the history of a new field, a new migration should add them here
|
|
51
|
+
-- We also put the metadata fields at the same level in order not to have a nested `metadata` field inside, since it would make comparison more difficult
|
|
52
|
+
CREATE OR REPLACE FUNCTION get_sequence_diffable_fields(IN seq sequences) RETURNS jsonb AS
|
|
53
|
+
$BODY$
|
|
54
|
+
SELECT jsonb_build_object(
|
|
55
|
+
'status', seq.status,
|
|
56
|
+
'current_sort', seq.current_sort
|
|
57
|
+
) || seq.metadata;
|
|
58
|
+
$BODY$
|
|
59
|
+
LANGUAGE SQL IMMUTABLE STRICT;
|
|
60
|
+
|
|
61
|
+
COMMENT ON FUNCTION get_sequence_diffable_fields IS 'Short list the sequence fields we want to trank updates for';
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
-- Create a trigger to track the history of the change
|
|
65
|
+
CREATE OR REPLACE FUNCTION sequence_modification_history() RETURNS TRIGGER AS
|
|
66
|
+
$BODY$
|
|
67
|
+
DECLARE
|
|
68
|
+
previous_value_changed JSONB;
|
|
69
|
+
change_id UUID;
|
|
70
|
+
BEGIN
|
|
71
|
+
previous_value_changed := jsonb_diff(get_sequence_diffable_fields(OLD), get_sequence_diffable_fields(NEW));
|
|
72
|
+
|
|
73
|
+
INSERT INTO sequences_changes (sequence_id, account_id, previous_value_changed)
|
|
74
|
+
VALUES (NEW.id, NEW.last_account_to_edit, previous_value_changed) RETURNING id INTO change_id;
|
|
75
|
+
|
|
76
|
+
CREATE TEMP TABLE IF NOT EXISTS sequence_current_change ON COMMIT DROP AS SELECT change_id;
|
|
77
|
+
|
|
78
|
+
RETURN NULL;
|
|
79
|
+
END;
|
|
80
|
+
$BODY$
|
|
81
|
+
language plpgsql;
|
|
82
|
+
|
|
83
|
+
CREATE OR REPLACE FUNCTION picture_modification_history() RETURNS TRIGGER AS
|
|
84
|
+
$BODY$
|
|
85
|
+
DECLARE
|
|
86
|
+
previous_value_changed JSONB;
|
|
87
|
+
parent_sequence_change_id UUID;
|
|
88
|
+
BEGIN
|
|
89
|
+
previous_value_changed := jsonb_diff(to_jsonb(OLD), to_jsonb(NEW)) - 'last_account_to_edit';
|
|
90
|
+
|
|
91
|
+
-- if there is a sequence modified on the same transaction, we link the picture change to the sequence change.
|
|
92
|
+
IF EXISTS (
|
|
93
|
+
SELECT 1
|
|
94
|
+
FROM information_schema.tables
|
|
95
|
+
WHERE table_type = 'LOCAL TEMPORARY'
|
|
96
|
+
AND table_name = 'sequence_current_change'
|
|
97
|
+
|
|
98
|
+
) THEN
|
|
99
|
+
SELECT change_id FROM sequence_current_change INTO parent_sequence_change_id;
|
|
100
|
+
END IF;
|
|
101
|
+
|
|
102
|
+
INSERT INTO pictures_changes (picture_id, account_id, previous_value_changed, sequences_changes_id)
|
|
103
|
+
VALUES (NEW.id, NEW.last_account_to_edit, previous_value_changed, parent_sequence_change_id);
|
|
104
|
+
|
|
105
|
+
RETURN NULL;
|
|
106
|
+
END;
|
|
107
|
+
$BODY$
|
|
108
|
+
language plpgsql;
|
|
109
|
+
|
|
110
|
+
-- We only trigger this for updates of last_account_to_edit. All changes that needs to be tracked need to set this field.
|
|
111
|
+
CREATE TRIGGER sequence_modification_history_trg
|
|
112
|
+
AFTER UPDATE OF
|
|
113
|
+
last_account_to_edit
|
|
114
|
+
ON sequences
|
|
115
|
+
FOR EACH ROW
|
|
116
|
+
EXECUTE PROCEDURE sequence_modification_history();
|
|
117
|
+
|
|
118
|
+
CREATE TRIGGER picture_modification_history_trg
|
|
119
|
+
AFTER UPDATE OF
|
|
120
|
+
last_account_to_edit
|
|
121
|
+
ON pictures
|
|
122
|
+
FOR EACH ROW
|
|
123
|
+
EXECUTE PROCEDURE picture_modification_history();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
-- sequence_geom_multi_linestring
|
|
2
|
+
-- depends: 20240220_01_9wZs0-sequence-current-sort
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
ALTER TABLE sequences
|
|
6
|
+
ALTER COLUMN geom TYPE GEOMETRY(LineString, 4326),
|
|
7
|
+
DROP COLUMN bbox;
|
|
8
|
+
DROP FUNCTION compute_sequence_bbox;
|
|
9
|
+
|
|
10
|
+
DROP FUNCTION compute_sequence_geom;
|
|
11
|
+
|
|
12
|
+
-- put back old functions
|
|
13
|
+
DROP FUNCTION IF EXISTS pictures_update_geom_sequence CASCADE;
|
|
14
|
+
CREATE FUNCTION pictures_update_geom_sequence() RETURNS trigger AS $$
|
|
15
|
+
BEGIN
|
|
16
|
+
UPDATE sequences
|
|
17
|
+
SET geom = s.geom
|
|
18
|
+
FROM (
|
|
19
|
+
SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
|
|
20
|
+
FROM (
|
|
21
|
+
SELECT sp.seq_id, p.geom
|
|
22
|
+
FROM sequences_pictures sp
|
|
23
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
24
|
+
WHERE sp.seq_id IN (
|
|
25
|
+
SELECT DISTINCT sequences_pictures.seq_id
|
|
26
|
+
FROM sequences_pictures
|
|
27
|
+
WHERE sequences_pictures.pic_id = NEW.id
|
|
28
|
+
)
|
|
29
|
+
ORDER BY sp.seq_id, sp.rank
|
|
30
|
+
) sp
|
|
31
|
+
GROUP BY seq_id
|
|
32
|
+
) s
|
|
33
|
+
WHERE sequences.id = s.seq_id;
|
|
34
|
+
RETURN NULL;
|
|
35
|
+
END $$ LANGUAGE plpgsql;
|
|
36
|
+
|
|
37
|
+
CREATE TRIGGER pictures_update_sequences_geom_trg
|
|
38
|
+
AFTER UPDATE OF geom ON pictures
|
|
39
|
+
FOR EACH ROW EXECUTE FUNCTION pictures_update_geom_sequence();
|
|
40
|
+
|
|
41
|
+
DROP FUNCTION IF EXISTS sequences_pictures_delete CASCADE;
|
|
42
|
+
CREATE FUNCTION sequences_pictures_delete() RETURNS trigger AS $$
|
|
43
|
+
BEGIN
|
|
44
|
+
UPDATE sequences
|
|
45
|
+
SET geom = s.geom
|
|
46
|
+
FROM (
|
|
47
|
+
SELECT seq_id, ST_MakeLine(array_agg(geom)) AS geom
|
|
48
|
+
FROM (
|
|
49
|
+
SELECT sp.seq_id, sp.rank, p.geom
|
|
50
|
+
FROM sequences_pictures sp
|
|
51
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
52
|
+
WHERE sp.seq_id IN (
|
|
53
|
+
SELECT DISTINCT seq_id
|
|
54
|
+
FROM old_table
|
|
55
|
+
)
|
|
56
|
+
ORDER BY sp.seq_id, sp.rank
|
|
57
|
+
) sp
|
|
58
|
+
GROUP BY seq_id
|
|
59
|
+
) s
|
|
60
|
+
WHERE sequences.id = s.seq_id;
|
|
61
|
+
RETURN NULL;
|
|
62
|
+
END $$ LANGUAGE plpgsql;
|
|
63
|
+
|
|
64
|
+
CREATE TRIGGER sequences_pictures_delete_trg
|
|
65
|
+
AFTER DELETE ON sequences_pictures
|
|
66
|
+
REFERENCING OLD TABLE AS old_table
|
|
67
|
+
FOR EACH STATEMENT EXECUTE FUNCTION sequences_pictures_delete();
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
-- sequence_geom_multi_linestring
|
|
2
|
+
-- depends: 20240220_01_9wZs0-sequence-current-sort
|
|
3
|
+
|
|
4
|
+
ALTER TABLE sequences
|
|
5
|
+
ALTER COLUMN geom TYPE GEOMETRY(MultiLineString, 4326) USING ST_Multi(geom),
|
|
6
|
+
-- Since some geometries can now be null (if all points are too far appart)
|
|
7
|
+
-- We store a bounding box of the geometry, always computed with the pictures of the geometry
|
|
8
|
+
ADD COLUMN IF NOT EXISTS bbox box2d;
|
|
9
|
+
|
|
10
|
+
CREATE FUNCTION compute_sequence_geom(IN sequence_id UUID) RETURNS GEOMETRY(MultiLineString, 4326) AS $$
|
|
11
|
+
WITH
|
|
12
|
+
all_pics AS (
|
|
13
|
+
SELECT p.geom AS geom, sp.seq_id
|
|
14
|
+
FROM sequences_pictures sp
|
|
15
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
16
|
+
WHERE sp.seq_id = sequence_id
|
|
17
|
+
ORDER BY sp.rank
|
|
18
|
+
)
|
|
19
|
+
, pic_as_line AS (
|
|
20
|
+
SELECT seq_id, ST_MakeLine(geom) AS geom
|
|
21
|
+
FROM all_pics
|
|
22
|
+
GROUP BY seq_id
|
|
23
|
+
)
|
|
24
|
+
, segments as (
|
|
25
|
+
SELECT
|
|
26
|
+
seq_id,
|
|
27
|
+
(ST_DumpSegments(geom)).geom AS segment
|
|
28
|
+
FROM pic_as_line
|
|
29
|
+
)
|
|
30
|
+
-- make a multiline geometry for the sequence, spliting each pictures separated by more than 50 meters
|
|
31
|
+
, seq_geom as (
|
|
32
|
+
SELECT
|
|
33
|
+
seq_id,
|
|
34
|
+
ST_LineMerge(ST_Collect(segment)) as geom
|
|
35
|
+
FROM segments
|
|
36
|
+
WHERE ST_Length(segment::geography) < 50
|
|
37
|
+
GROUP BY seq_id
|
|
38
|
+
)
|
|
39
|
+
, seq_multi_ls_geom as (
|
|
40
|
+
SELECT
|
|
41
|
+
seq_id,
|
|
42
|
+
ST_Multi(geom) as geom
|
|
43
|
+
FROM seq_geom
|
|
44
|
+
WHERE NOT ST_IsEmpty(geom)
|
|
45
|
+
)
|
|
46
|
+
SELECT seq_multi_ls_geom.geom
|
|
47
|
+
FROM seq_multi_ls_geom;
|
|
48
|
+
$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
CREATE FUNCTION compute_sequence_bbox(IN sequence_id UUID) RETURNS box2d AS $$
|
|
52
|
+
SELECT
|
|
53
|
+
ST_Extent(geom)
|
|
54
|
+
FROM sequences_pictures sp
|
|
55
|
+
JOIN pictures p ON sp.pic_id = p.id
|
|
56
|
+
WHERE sp.seq_id = sequence_id;
|
|
57
|
+
$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
-- update bbox in sequences
|
|
61
|
+
UPDATE sequences
|
|
62
|
+
SET
|
|
63
|
+
bbox = compute_sequence_bbox(id);
|
|
64
|
+
|
|
65
|
+
-- change sql function called by trigger on picture's geom update
|
|
66
|
+
DROP FUNCTION IF EXISTS pictures_update_geom_sequence CASCADE;
|
|
67
|
+
CREATE FUNCTION pictures_update_geom_sequence() RETURNS trigger AS $$
|
|
68
|
+
BEGIN
|
|
69
|
+
UPDATE sequences
|
|
70
|
+
SET
|
|
71
|
+
geom = compute_sequence_geom(id),
|
|
72
|
+
bbox = compute_sequence_bbox(id)
|
|
73
|
+
WHERE id IN (
|
|
74
|
+
SELECT DISTINCT sequences_pictures.seq_id
|
|
75
|
+
FROM sequences_pictures
|
|
76
|
+
WHERE sequences_pictures.pic_id = NEW.id
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
RETURN NULL;
|
|
80
|
+
END $$ LANGUAGE plpgsql;
|
|
81
|
+
|
|
82
|
+
CREATE TRIGGER pictures_update_sequences_geom_trg
|
|
83
|
+
AFTER UPDATE OF geom ON pictures
|
|
84
|
+
FOR EACH ROW EXECUTE FUNCTION pictures_update_geom_sequence();
|
|
85
|
+
|
|
86
|
+
DROP FUNCTION IF EXISTS sequences_pictures_delete CASCADE;
|
|
87
|
+
CREATE FUNCTION sequences_pictures_delete() RETURNS trigger AS $$
|
|
88
|
+
BEGIN
|
|
89
|
+
UPDATE sequences
|
|
90
|
+
SET
|
|
91
|
+
geom = compute_sequence_geom(id),
|
|
92
|
+
bbox = compute_sequence_bbox(id)
|
|
93
|
+
WHERE id IN (SELECT DISTINCT seq_id FROM old_table);
|
|
94
|
+
|
|
95
|
+
RETURN NULL;
|
|
96
|
+
END $$ LANGUAGE plpgsql;
|
|
97
|
+
|
|
98
|
+
CREATE TRIGGER sequences_pictures_delete_trg
|
|
99
|
+
AFTER DELETE ON sequences_pictures
|
|
100
|
+
REFERENCING OLD TABLE AS old_table
|
|
101
|
+
FOR EACH STATEMENT EXECUTE FUNCTION sequences_pictures_delete();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- migrate_sequence_geom_multi_linestring
|
|
2
|
+
-- depends: 20240226_01_8iXl1-track-changes 20240229_01_SgfQY-sequence-geom-multi-linestring
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
-- We do not want a transaction around this, as we'll be commiting batches of geometry updates
|
|
7
|
+
-- transactional: false
|
|
8
|
+
|
|
9
|
+
CREATE OR REPLACE PROCEDURE migrate_sequences_split_geom() AS
|
|
10
|
+
$$
|
|
11
|
+
DECLARE
|
|
12
|
+
last_inserted_at TIMESTAMPTZ;
|
|
13
|
+
BEGIN
|
|
14
|
+
SELECT min(inserted_at) - INTERVAL '1 minute' FROM sequences INTO last_inserted_at;
|
|
15
|
+
|
|
16
|
+
WHILE last_inserted_at IS NOT NULL LOOP
|
|
17
|
+
|
|
18
|
+
-- Temporary removal of all update triggers
|
|
19
|
+
DROP TRIGGER sequences_update_ts_trg ON sequences;
|
|
20
|
+
|
|
21
|
+
WITH
|
|
22
|
+
-- get a batch of 1 000 sequences to update
|
|
23
|
+
seq_to_update AS (
|
|
24
|
+
SELECT id, inserted_at from sequences where inserted_at > last_inserted_at ORDER BY inserted_at ASC LIMIT 1000
|
|
25
|
+
)
|
|
26
|
+
, updated_seq AS (
|
|
27
|
+
UPDATE sequences
|
|
28
|
+
SET
|
|
29
|
+
geom = compute_sequence_geom(id)
|
|
30
|
+
WHERE id in (SELECT id FROM seq_to_update)
|
|
31
|
+
)
|
|
32
|
+
SELECT MAX(inserted_at) FROM seq_to_update INTO last_inserted_at;
|
|
33
|
+
|
|
34
|
+
RAISE NOTICE 'max insertion date is now %', last_inserted_at;
|
|
35
|
+
|
|
36
|
+
-- Restore all deactivated triggers
|
|
37
|
+
CREATE TRIGGER sequences_update_ts_trg
|
|
38
|
+
BEFORE UPDATE ON sequences
|
|
39
|
+
FOR EACH ROW EXECUTE FUNCTION sequences_update_ts();
|
|
40
|
+
|
|
41
|
+
-- commit transaction (as a procedure is in an implicit transaction, it will start a new transaction after this)
|
|
42
|
+
COMMIT;
|
|
43
|
+
END LOOP;
|
|
44
|
+
|
|
45
|
+
-- After this, we need to do a full vacuum to clean dead tuples
|
|
46
|
+
RAISE NOTICE 'Geometry fields updated, you should run `VACUUM FULL sequences;` afterward (or use something like pg_repack)';
|
|
47
|
+
|
|
48
|
+
END
|
|
49
|
+
$$ LANGUAGE plpgsql;
|
|
50
|
+
|
|
51
|
+
CALL migrate_sequences_split_geom();
|
|
52
|
+
DROP PROCEDURE migrate_sequences_split_geom;
|