Merge branch '8784-dir-listings'
[arvados.git] / services / api / db / migrate / 20140117231056_normalize_collection_uuid.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 class NormalizeCollectionUuid < ActiveRecord::Migration
6   def count_orphans
7     %w(head tail).each do |ht|
8       results = ActiveRecord::Base.connection.execute(<<-EOS)
9 SELECT COUNT(links.*)
10  FROM links
11  LEFT JOIN collections c
12    ON links.#{ht}_uuid = c.uuid
13  WHERE (#{ht}_kind='arvados#collection' or #{ht}_uuid ~ '^[0-9a-f]{32,}')
14    AND #{ht}_uuid IS NOT NULL
15    AND #{ht}_uuid NOT IN (SELECT uuid FROM collections)
16 EOS
17       puts "#{results.first['count'].to_i} links with #{ht}_uuid pointing nowhere."
18     end
19   end
20
21   def up
22     # Normalize uuids in the collections table to
23     # {hash}+{size}. Existing uuids might be {hash},
24     # {hash}+{size}+K@{instance-name}, {hash}+K@{instance-name}, etc.
25
26     count_orphans
27     puts "Normalizing collection UUIDs."
28
29     update_sql <<-EOS
30 UPDATE collections
31  SET uuid = regexp_replace(uuid,'\\+.*','') || '+' || length(manifest_text)
32  WHERE uuid !~ '^[0-9a-f]{32,}\\+[0-9]+$'
33    AND (regexp_replace(uuid,'\\+.*','') || '+' || length(manifest_text))
34      NOT IN (SELECT uuid FROM collections)
35 EOS
36
37     count_orphans
38     puts "Updating links by stripping +K@.* from *_uuid attributes."
39
40     update_sql <<-EOS
41 UPDATE links
42  SET head_uuid = regexp_replace(head_uuid,'\\+K@.*','')
43  WHERE head_uuid like '%+K@%'
44 EOS
45     update_sql <<-EOS
46 UPDATE links
47  SET tail_uuid = regexp_replace(tail_uuid,'\\+K@.*','')
48  WHERE tail_uuid like '%+K@%'
49 EOS
50
51     count_orphans
52     puts "Updating links by searching bare collection hashes using regexp."
53
54     # Next, update {hash} (and any other non-normalized forms) to
55     # {hash}+{size}. This can only work where the corresponding
56     # collection is found in the collections table (otherwise we can't
57     # know the size).
58     %w(head tail).each do |ht|
59       update_sql <<-EOS
60 UPDATE links
61  SET #{ht}_uuid = c.uuid
62  FROM collections c
63  WHERE #{ht}_uuid IS NOT NULL
64    AND (#{ht}_kind='arvados#collection' or #{ht}_uuid ~ '^[0-9a-f]{32,}')
65    AND #{ht}_uuid NOT IN (SELECT uuid FROM collections)
66    AND regexp_replace(#{ht}_uuid,'\\+.*','') = regexp_replace(c.uuid,'\\+.*','')
67    AND c.uuid ~ '^[0-9a-f]{32,}\\+[0-9]+$'
68 EOS
69     end
70
71     count_orphans
72     puts "Stripping \"+K@.*\" from jobs.output, jobs.log, job_tasks.output."
73
74     update_sql <<-EOS
75 UPDATE jobs
76  SET output = regexp_replace(output,'\\+K@.*','')
77  WHERE output ~ '^[0-9a-f]{32,}\\+[0-9]+\\+K@\\w+$'
78 EOS
79     update_sql <<-EOS
80 UPDATE jobs
81  SET log = regexp_replace(log,'\\+K@.*','')
82  WHERE log ~ '^[0-9a-f]{32,}\\+[0-9]+\\+K@\\w+$'
83 EOS
84     update_sql <<-EOS
85 UPDATE job_tasks
86  SET output = regexp_replace(output,'\\+K@.*','')
87  WHERE output ~ '^[0-9a-f]{32,}\\+[0-9]+\\+K@\\w+$'
88 EOS
89
90     puts "Done."
91   end
92
93   def down
94   end
95 end