]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update23.py
Merge remote branch 'flotow/contents' into contents
[dak.git] / dak / dakdb / update23.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 """
5 Adding a trainee field to the process-new notes
6
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2009  Mike O'Connor <stew@debian.org>
9 @license: GNU General Public License version 2 or later
10 """
11
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
16
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
26 ################################################################################
27
28
29 ################################################################################
30
31 import psycopg2
32 import time
33 from daklib.dak_exceptions import DBUpdateError
34
35 ################################################################################
36
37 def suites():
38     """
39     return a list of suites to operate on
40     """
41     if Config().has_key( "%s::%s" %(options_prefix,"Suite")):
42         suites = utils.split_args(Config()[ "%s::%s" %(options_prefix,"Suite")])
43     else:
44         suites = [ 'unstable', 'testing' ]
45 #            suites = Config().SubTree("Suite").List()
46
47     return suites
48
49 def arches(cursor, suite):
50     """
51     return a list of archs to operate on
52     """
53     arch_list = []
54     cursor.execute("""SELECT s.architecture, a.arch_string
55     FROM suite_architectures s
56     JOIN architecture a ON (s.architecture=a.id)
57     WHERE suite = :suite""", {'suite' : suite })
58
59     while True:
60         r = cursor.fetchone()
61         if not r:
62             break
63
64         if r[1] != "source" and r[1] != "all":
65             arch_list.append((r[0], r[1]))
66
67     return arch_list
68
69 def do_update(self):
70     """
71     Adding contents table as first step to maybe, finally getting rid
72     of apt-ftparchive
73     """
74
75     print __doc__
76
77     try:
78         c = self.db.cursor()
79
80         c.execute("""CREATE TABLE pending_bin_contents (
81         id serial NOT NULL,
82         package text NOT NULL,
83         version debversion NOT NULL,
84         arch int NOT NULL,
85         filename text NOT NULL,
86         type int NOT NULL,
87         PRIMARY KEY(id))""" );
88
89         c.execute("""CREATE TABLE deb_contents (
90         filename text,
91         section text,
92         package text,
93         binary_id integer,
94         arch integer,
95         suite integer)""" )
96
97         c.execute("""CREATE TABLE udeb_contents (
98         filename text,
99         section text,
100         package text,
101         binary_id integer,
102         suite integer,
103         arch integer)""" )
104
105         c.execute("""ALTER TABLE ONLY deb_contents
106         ADD CONSTRAINT deb_contents_arch_fkey
107         FOREIGN KEY (arch) REFERENCES architecture(id)
108         ON DELETE CASCADE;""")
109
110         c.execute("""ALTER TABLE ONLY udeb_contents
111         ADD CONSTRAINT udeb_contents_arch_fkey
112         FOREIGN KEY (arch) REFERENCES architecture(id)
113         ON DELETE CASCADE;""")
114
115         c.execute("""ALTER TABLE ONLY deb_contents
116         ADD CONSTRAINT deb_contents_pkey
117         PRIMARY KEY (filename,package,arch,suite);""")
118
119         c.execute("""ALTER TABLE ONLY udeb_contents
120         ADD CONSTRAINT udeb_contents_pkey
121         PRIMARY KEY (filename,package,arch,suite);""")
122
123         c.execute("""ALTER TABLE ONLY deb_contents
124         ADD CONSTRAINT deb_contents_suite_fkey
125         FOREIGN KEY (suite) REFERENCES suite(id)
126         ON DELETE CASCADE;""")
127
128         c.execute("""ALTER TABLE ONLY udeb_contents
129         ADD CONSTRAINT udeb_contents_suite_fkey
130         FOREIGN KEY (suite) REFERENCES suite(id)
131         ON DELETE CASCADE;""")
132
133         c.execute("""ALTER TABLE ONLY deb_contents
134         ADD CONSTRAINT deb_contents_binary_fkey
135         FOREIGN KEY (binary_id) REFERENCES binaries(id)
136         ON DELETE CASCADE;""")
137
138         c.execute("""ALTER TABLE ONLY udeb_contents
139         ADD CONSTRAINT udeb_contents_binary_fkey
140         FOREIGN KEY (binary_id) REFERENCES binaries(id)
141         ON DELETE CASCADE;""")
142
143         c.execute("""CREATE INDEX ind_deb_contents_binary ON deb_contents(binary_id);""" )
144
145
146         suites = self.suites()
147
148         for suite in [i.lower() for i in suites]:
149             suite_id = DBConn().get_suite_id(suite)
150             arch_list = arches(c, suite_id)
151             arch_list = arches(c, suite_id)
152
153             for (arch_id,arch_str) in arch_list:
154                 c.execute( "CREATE INDEX ind_deb_contents_%s_%s ON deb_contents (arch,suite) WHERE (arch=2 OR arch=%d) AND suite=$d"%(arch_str,suite,arch_id,suite_id) )
155
156             for section, sname in [("debian-installer","main"),
157                                   ("non-free/debian-installer", "nonfree")]:
158                 c.execute( "CREATE INDEX ind_udeb_contents_%s_%s ON udeb_contents (section,suite) WHERE section=%s AND suite=$d"%(sname,suite,section,suite_id) )
159
160
161         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_bin_a() RETURNS trigger AS  $$
162     event = TD["event"]
163     if event == "DELETE" or event == "UPDATE":
164
165         plpy.execute(plpy.prepare("DELETE FROM deb_contents WHERE binary_id=$1 and suite=$2",
166                                   ["int","int"]),
167                                   [TD["old"]["bin"], TD["old"]["suite"]])
168
169     if event == "INSERT" or event == "UPDATE":
170
171        content_data = plpy.execute(plpy.prepare(
172             """SELECT s.section, b.package, b.architecture, ot.type
173             FROM override o
174             JOIN override_type ot on o.type=ot.id
175             JOIN binaries b on b.package=o.package
176             JOIN files f on b.file=f.id
177             JOIN location l on l.id=f.location
178             JOIN section s on s.id=o.section
179             WHERE b.id=$1
180             AND o.suite=$2
181             """,
182             ["int", "int"]),
183             [TD["new"]["bin"], TD["new"]["suite"]])[0]
184
185        tablename="%s_contents" % content_data['type']
186
187        plpy.execute(plpy.prepare("""DELETE FROM %s
188                    WHERE package=$1 and arch=$2 and suite=$3""" % tablename,
189                    ['text','int','int']),
190                    [content_data['package'],
191                    content_data['architecture'],
192                    TD["new"]["suite"]])
193
194        filenames = plpy.execute(plpy.prepare(
195            "SELECT bc.file FROM bin_contents bc where bc.binary_id=$1",
196            ["int"]),
197            [TD["new"]["bin"]])
198
199        for filename in filenames:
200            plpy.execute(plpy.prepare(
201                """INSERT INTO %s
202                    (filename,section,package,binary_id,arch,suite)
203                    VALUES($1,$2,$3,$4,$5,$6)""" % tablename,
204                ["text","text","text","int","int","int"]),
205                [filename["file"],
206                 content_data["section"],
207                 content_data["package"],
208                 TD["new"]["bin"],
209                 content_data["architecture"],
210                 TD["new"]["suite"]] )
211 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
212 """)
213
214
215         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_override() RETURNS trigger AS  $$
216     event = TD["event"]
217     if event == "UPDATE":
218
219         otype = plpy.execute(plpy.prepare("SELECT type from override_type where id=$1",["int"]),[TD["new"]["type"]] )[0];
220         if otype["type"].endswith("deb"):
221             section = plpy.execute(plpy.prepare("SELECT section from section where id=$1",["int"]),[TD["new"]["section"]] )[0];
222
223             table_name = "%s_contents" % otype["type"]
224             plpy.execute(plpy.prepare("UPDATE %s set section=$1 where package=$2 and suite=$3" % table_name,
225                                       ["text","text","int"]),
226                                       [section["section"],
227                                       TD["new"]["package"],
228                                       TD["new"]["suite"]])
229
230 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
231 """)
232
233         c.execute("""CREATE OR REPLACE FUNCTION update_contents_for_override()
234                       RETURNS trigger AS  $$
235     event = TD["event"]
236     if event == "UPDATE" or event == "INSERT":
237         row = TD["new"]
238         r = plpy.execute(plpy.prepare( """SELECT 1 from suite_architectures sa
239                   JOIN binaries b ON b.architecture = sa.architecture
240                   WHERE b.id = $1 and sa.suite = $2""",
241                 ["int", "int"]),
242                 [row["bin"], row["suite"]])
243         if not len(r):
244             plpy.error("Illegal architecture for this suite")
245
246 $$ LANGUAGE plpythonu VOLATILE;""")
247
248         c.execute( """CREATE TRIGGER illegal_suite_arch_bin_associations_trigger
249                       BEFORE INSERT OR UPDATE ON bin_associations
250                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
251
252         c.execute( """CREATE TRIGGER bin_associations_contents_trigger
253                       AFTER INSERT OR UPDATE OR DELETE ON bin_associations
254                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_bin_a();""")
255         c.execute("""CREATE TRIGGER override_contents_trigger
256                       AFTER UPDATE ON override
257                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
258
259
260         c.execute( "CREATE INDEX ind_deb_contents_name ON deb_contents(package);");
261         c.execute( "CREATE INDEX ind_udeb_contents_name ON udeb_contents(package);");
262
263         self.db.commit()
264
265     except psycopg2.ProgrammingError, msg:
266         self.db.rollback()
267         raise DBUpdateError, "Unable to apply process-new update 14, rollback issued. Error message : %s" % (str(msg))
268