d781df3f2d5d52fadfe794193db5f4ffab0e9684
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / XXXX.schema.record-merge-tracking.sql
1
2 BEGIN;
3
4 -- SELECT evergreen.upgrade_deps_block_check('XXX', :eg_version);
5
6 ALTER TABLE biblio.record_entry
7     ADD COLUMN merge_date TIMESTAMP WITH TIME ZONE,
8     ADD COLUMN merged_to BIGINT REFERENCES biblio.record_entry(id);
9
10 CREATE OR REPLACE FUNCTION asset.merge_record_assets( target_record BIGINT, source_record BIGINT ) RETURNS INT AS $func$
11 DECLARE
12     moved_objects INT := 0;
13     source_cn     asset.call_number%ROWTYPE;
14     target_cn     asset.call_number%ROWTYPE;
15     metarec       metabib.metarecord%ROWTYPE;
16     hold          action.hold_request%ROWTYPE;
17     ser_rec       serial.record_entry%ROWTYPE;
18     ser_sub       serial.subscription%ROWTYPE;
19     acq_lineitem  acq.lineitem%ROWTYPE;
20     acq_request   acq.user_request%ROWTYPE;
21     booking       booking.resource_type%ROWTYPE;
22     source_part   biblio.monograph_part%ROWTYPE;
23     target_part   biblio.monograph_part%ROWTYPE;
24     multi_home    biblio.peer_bib_copy_map%ROWTYPE;
25     uri_count     INT := 0;
26     counter       INT := 0;
27     uri_datafield TEXT;
28     uri_text      TEXT := '';
29 BEGIN
30
31     -- move any 856 entries on records that have at least one MARC-mapped URI entry
32     SELECT  INTO uri_count COUNT(*)
33       FROM  asset.uri_call_number_map m
34             JOIN asset.call_number cn ON (m.call_number = cn.id)
35       WHERE cn.record = source_record;
36
37     IF uri_count > 0 THEN
38         
39         -- This returns more nodes than you might expect:
40         -- 7 instead of 1 for an 856 with $u $y $9
41         SELECT  COUNT(*) INTO counter
42           FROM  oils_xpath_table(
43                     'id',
44                     'marc',
45                     'biblio.record_entry',
46                     '//*[@tag="856"]',
47                     'id=' || source_record
48                 ) as t(i int,c text);
49     
50         FOR i IN 1 .. counter LOOP
51             SELECT  '<datafield xmlns="http://www.loc.gov/MARC21/slim"' || 
52                         ' tag="856"' ||
53                         ' ind1="' || FIRST(ind1) || '"'  ||
54                         ' ind2="' || FIRST(ind2) || '">' ||
55                         STRING_AGG(
56                             '<subfield code="' || subfield || '">' ||
57                             regexp_replace(
58                                 regexp_replace(
59                                     regexp_replace(data,'&','&amp;','g'),
60                                     '>', '&gt;', 'g'
61                                 ),
62                                 '<', '&lt;', 'g'
63                             ) || '</subfield>', ''
64                         ) || '</datafield>' INTO uri_datafield
65               FROM  oils_xpath_table(
66                         'id',
67                         'marc',
68                         'biblio.record_entry',
69                         '//*[@tag="856"][position()=' || i || ']/@ind1|' ||
70                         '//*[@tag="856"][position()=' || i || ']/@ind2|' ||
71                         '//*[@tag="856"][position()=' || i || ']/*/@code|' ||
72                         '//*[@tag="856"][position()=' || i || ']/*[@code]',
73                         'id=' || source_record
74                     ) as t(id int,ind1 text, ind2 text,subfield text,data text);
75
76             -- As most of the results will be NULL, protect against NULLifying
77             -- the valid content that we do generate
78             uri_text := uri_text || COALESCE(uri_datafield, '');
79         END LOOP;
80
81         IF uri_text <> '' THEN
82             UPDATE  biblio.record_entry
83               SET   marc = regexp_replace(marc,'(</[^>]*record>)', uri_text || E'\\1')
84               WHERE id = target_record;
85         END IF;
86
87     END IF;
88
89         -- Find and move metarecords to the target record
90         SELECT  INTO metarec *
91           FROM  metabib.metarecord
92           WHERE master_record = source_record;
93
94         IF FOUND THEN
95                 UPDATE  metabib.metarecord
96                   SET   master_record = target_record,
97                         mods = NULL
98                   WHERE id = metarec.id;
99
100                 moved_objects := moved_objects + 1;
101         END IF;
102
103         -- Find call numbers attached to the source ...
104         FOR source_cn IN SELECT * FROM asset.call_number WHERE record = source_record LOOP
105
106                 SELECT  INTO target_cn *
107                   FROM  asset.call_number
108                   WHERE label = source_cn.label
109             AND prefix = source_cn.prefix
110             AND suffix = source_cn.suffix
111                         AND owning_lib = source_cn.owning_lib
112                         AND record = target_record
113                         AND NOT deleted;
114
115                 -- ... and if there's a conflicting one on the target ...
116                 IF FOUND THEN
117
118                         -- ... move the copies to that, and ...
119                         UPDATE  asset.copy
120                           SET   call_number = target_cn.id
121                           WHERE call_number = source_cn.id;
122
123                         -- ... move V holds to the move-target call number
124                         FOR hold IN SELECT * FROM action.hold_request WHERE target = source_cn.id AND hold_type = 'V' LOOP
125                 
126                                 UPDATE  action.hold_request
127                                   SET   target = target_cn.id
128                                   WHERE id = hold.id;
129                 
130                                 moved_objects := moved_objects + 1;
131                         END LOOP;
132         
133             UPDATE asset.call_number SET deleted = TRUE WHERE id = source_cn.id;
134
135                 -- ... if not ...
136                 ELSE
137                         -- ... just move the call number to the target record
138                         UPDATE  asset.call_number
139                           SET   record = target_record
140                           WHERE id = source_cn.id;
141                 END IF;
142
143                 moved_objects := moved_objects + 1;
144         END LOOP;
145
146         -- Find T holds targeting the source record ...
147         FOR hold IN SELECT * FROM action.hold_request WHERE target = source_record AND hold_type = 'T' LOOP
148
149                 -- ... and move them to the target record
150                 UPDATE  action.hold_request
151                   SET   target = target_record
152                   WHERE id = hold.id;
153
154                 moved_objects := moved_objects + 1;
155         END LOOP;
156
157         -- Find serial records targeting the source record ...
158         FOR ser_rec IN SELECT * FROM serial.record_entry WHERE record = source_record LOOP
159                 -- ... and move them to the target record
160                 UPDATE  serial.record_entry
161                   SET   record = target_record
162                   WHERE id = ser_rec.id;
163
164                 moved_objects := moved_objects + 1;
165         END LOOP;
166
167         -- Find serial subscriptions targeting the source record ...
168         FOR ser_sub IN SELECT * FROM serial.subscription WHERE record_entry = source_record LOOP
169                 -- ... and move them to the target record
170                 UPDATE  serial.subscription
171                   SET   record_entry = target_record
172                   WHERE id = ser_sub.id;
173
174                 moved_objects := moved_objects + 1;
175         END LOOP;
176
177         -- Find booking resource types targeting the source record ...
178         FOR booking IN SELECT * FROM booking.resource_type WHERE record = source_record LOOP
179                 -- ... and move them to the target record
180                 UPDATE  booking.resource_type
181                   SET   record = target_record
182                   WHERE id = booking.id;
183
184                 moved_objects := moved_objects + 1;
185         END LOOP;
186
187         -- Find acq lineitems targeting the source record ...
188         FOR acq_lineitem IN SELECT * FROM acq.lineitem WHERE eg_bib_id = source_record LOOP
189                 -- ... and move them to the target record
190                 UPDATE  acq.lineitem
191                   SET   eg_bib_id = target_record
192                   WHERE id = acq_lineitem.id;
193
194                 moved_objects := moved_objects + 1;
195         END LOOP;
196
197         -- Find acq user purchase requests targeting the source record ...
198         FOR acq_request IN SELECT * FROM acq.user_request WHERE eg_bib = source_record LOOP
199                 -- ... and move them to the target record
200                 UPDATE  acq.user_request
201                   SET   eg_bib = target_record
202                   WHERE id = acq_request.id;
203
204                 moved_objects := moved_objects + 1;
205         END LOOP;
206
207         -- Find parts attached to the source ...
208         FOR source_part IN SELECT * FROM biblio.monograph_part WHERE record = source_record LOOP
209
210                 SELECT  INTO target_part *
211                   FROM  biblio.monograph_part
212                   WHERE label = source_part.label
213                         AND record = target_record;
214
215                 -- ... and if there's a conflicting one on the target ...
216                 IF FOUND THEN
217
218                         -- ... move the copy-part maps to that, and ...
219                         UPDATE  asset.copy_part_map
220                           SET   part = target_part.id
221                           WHERE part = source_part.id;
222
223                         -- ... move P holds to the move-target part
224                         FOR hold IN SELECT * FROM action.hold_request WHERE target = source_part.id AND hold_type = 'P' LOOP
225                 
226                                 UPDATE  action.hold_request
227                                   SET   target = target_part.id
228                                   WHERE id = hold.id;
229                 
230                                 moved_objects := moved_objects + 1;
231                         END LOOP;
232
233                 -- ... if not ...
234                 ELSE
235                         -- ... just move the part to the target record
236                         UPDATE  biblio.monograph_part
237                           SET   record = target_record
238                           WHERE id = source_part.id;
239                 END IF;
240
241                 moved_objects := moved_objects + 1;
242         END LOOP;
243
244         -- Find multi_home items attached to the source ...
245         FOR multi_home IN SELECT * FROM biblio.peer_bib_copy_map WHERE peer_record = source_record LOOP
246                 -- ... and move them to the target record
247                 UPDATE  biblio.peer_bib_copy_map
248                   SET   peer_record = target_record
249                   WHERE id = multi_home.id;
250
251                 moved_objects := moved_objects + 1;
252         END LOOP;
253
254         -- And delete mappings where the item's home bib was merged with the peer bib
255         DELETE FROM biblio.peer_bib_copy_map WHERE peer_record = (
256                 SELECT (SELECT record FROM asset.call_number WHERE id = call_number)
257                 FROM asset.copy WHERE id = target_copy
258         );
259
260     -- Apply merge tracking
261     UPDATE biblio.record_entry 
262         SET merge_date = NOW() WHERE id = target_record;
263
264     UPDATE biblio.record_entry
265         SET merge_date = NOW(), merged_to = target_record
266         WHERE id = source_record;
267
268     -- Finally, "delete" the source record
269     DELETE FROM biblio.record_entry WHERE id = source_record;
270
271         -- That's all, folks!
272         RETURN moved_objects;
273 END;
274 $func$ LANGUAGE plpgsql;
275
276
277 COMMIT;