|
| 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