Skip to content

Commit 2a7d88c

Browse files
Merge pull request #11 from Breeding-Insight/feature/BI-2779
BI-2779 - Observation levels data migration
2 parents 9cba318 + 0ff5b11 commit 2a7d88c

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
-- Create new observation level names for each unique observationLevel in
2+
-- the additional_info column of the observation_unit table
3+
--
4+
-- Assumption: all observation_unit.program_id have ids which is true for our
5+
-- usage. Database allows NULLs but we don't have to handle that
6+
--
7+
-- * The level order will be 0 for all of these indicating Exp Unit
8+
-- * All level names should be converted to lower case and combined
9+
-- in the case of different cases to reference the same level
10+
-- * Level names should be created for the program the observation unit is in, not globally
11+
INSERT INTO observation_unit_level_name (level_name, level_order, program_id)
12+
SELECT DISTINCT
13+
lower(btrim(ou.additional_info ->> 'observationLevel')) AS level_name,
14+
0 AS level_order,
15+
ou.program_id
16+
FROM observation_unit ou
17+
WHERE NULLIF(btrim(ou.additional_info ->> 'observationLevel'), '') IS NOT NULL
18+
AND ou.program_id IS NOT NULL
19+
ON CONFLICT (level_name, program_id) DO NOTHING;
20+
-- on conflict only relevant for test servers, won't have conflicts on prod because
21+
-- no additional observationlevelnames have been created other than global defaults from migration
22+
23+
-- Update global level references to newly created program scoped levels
24+
-- For prod, these will be:
25+
-- * plot
26+
-- * plant
27+
-- * fish
28+
-- * bine
29+
-- * tree
30+
-- There will be multiple instances as some levels are reused in different programs
31+
--
32+
-- Need to handle observation_unit_position, but can skip & observation_unit_level and
33+
-- study_observation_level. bi-api has never written study_observation_level and no records exist
34+
-- in prod. observation_unit_level only has rep and block global references and those were already
35+
-- updated in a previous migration.
36+
37+
-- Updates observation_unit_position.level_name to point to the program-scoped
38+
-- observation_unit_level_name record that matches the observation unit's
39+
-- additional_info.observationLevel value.
40+
--
41+
-- Only updates rows where:
42+
-- * additional_info.observationLevel is present and not blank
43+
-- * observation_unit.program_id is present
44+
-- * the current linked level is null or does not already match the target
45+
-- * some data like tree will point to plot due to how old data was written and will be fixed by this
46+
-- * some data has null levels due to how it was written and will be fixed by this
47+
WITH rows_to_update AS (
48+
SELECT
49+
oup.id AS observation_unit_position_id,
50+
target.id AS target_level_id
51+
FROM observation_unit_position oup
52+
JOIN observation_unit ou
53+
ON ou.id = oup.observation_unit_id
54+
JOIN observation_unit_level_name target
55+
ON target.program_id = ou.program_id
56+
AND target.level_name = lower(btrim(ou.additional_info ->> 'observationLevel'))
57+
WHERE NULLIF(btrim(ou.additional_info ->> 'observationLevel'), '') IS NOT NULL
58+
AND ou.program_id IS NOT NULL
59+
AND oup.level_name IS DISTINCT FROM target.id
60+
)
61+
UPDATE observation_unit_position oup
62+
SET level_name = rows_to_update.target_level_id
63+
FROM rows_to_update
64+
WHERE oup.id = rows_to_update.observation_unit_position_id;
65+
66+
-- Assertion to assure we don't remove additional_info.observationLevel where
67+
-- references can't be updated. For our prod data, shouldn't be any.
68+
DO $$
69+
BEGIN
70+
IF EXISTS (
71+
SELECT 1
72+
FROM observation_unit ou
73+
WHERE NULLIF(btrim(ou.additional_info ->> 'observationLevel'), '') IS NOT NULL
74+
AND (
75+
ou.program_id IS NULL
76+
OR NOT EXISTS (
77+
SELECT 1
78+
FROM observation_unit_level_name ouln
79+
WHERE ouln.program_id = ou.program_id
80+
AND ouln.level_name = lower(btrim(ou.additional_info ->> 'observationLevel'))
81+
)
82+
)
83+
) THEN
84+
RAISE EXCEPTION
85+
'V005.002 cannot remove observationLevel from observation_unit.additional_info because some rows could not be
86+
mapped';
87+
END IF;
88+
END $$;
89+
90+
-- Remove observationLevel from additional_info in observation_unit table as it is no longer needed
91+
UPDATE observation_unit
92+
SET additional_info = additional_info - 'observationLevel';
93+
94+
-- Remove unused global level names (will exclude rep & block). On prod, these will be removed:
95+
-- * entry
96+
-- * field
97+
-- * pot
98+
-- * sample
99+
-- * study
100+
-- * sub-block
101+
-- * sub-plot
102+
-- Level is unused if not referenced in tables:
103+
-- * observation_unit_position
104+
-- * observation_unit_level
105+
-- * study_observation_level has no existing data in prod but included
106+
DELETE FROM observation_unit_level_name ouln
107+
WHERE ouln.program_id IS NULL
108+
AND NOT EXISTS (
109+
SELECT 1 FROM observation_unit_position oup WHERE oup.level_name = ouln.id
110+
)
111+
AND NOT EXISTS (
112+
SELECT 1 FROM observation_unit_level oul WHERE oul.level_name = ouln.id
113+
)
114+
AND NOT EXISTS (
115+
SELECT 1 FROM study_observation_level sol WHERE sol.level_name = ouln.id
116+
);

0 commit comments

Comments
 (0)