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