]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update28.py
add Config() import
[dak.git] / dak / dakdb / update28.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 """
5 keep contents of binary packages in tables so we can generate contents.gz files from dak
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 from daklib.config import Config
35
36 ################################################################################
37
38 def _suites():
39     """
40     return a list of suites to operate on
41     """
42     if Config().has_key( "%s::%s" %(options_prefix,"Suite")):
43         suites = utils.split_args(Config()[ "%s::%s" %(options_prefix,"Suite")])
44     else:
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         suites = _suites()
146
147         for suite in [i.lower() for i in suites]:
148             suite_id = DBConn().get_suite_id(suite)
149             arch_list = arches(c, suite_id)
150             arch_list = arches(c, suite_id)
151
152             for (arch_id,arch_str) in arch_list:
153                 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) )
154
155             for section, sname in [("debian-installer","main"),
156                                   ("non-free/debian-installer", "nonfree")]:
157                 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) )
158
159
160         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_bin_a() RETURNS trigger AS  $$
161     event = TD["event"]
162     if event == "DELETE" or event == "UPDATE":
163
164         plpy.execute(plpy.prepare("DELETE FROM deb_contents WHERE binary_id=$1 and suite=$2",
165                                   ["int","int"]),
166                                   [TD["old"]["bin"], TD["old"]["suite"]])
167
168     if event == "INSERT" or event == "UPDATE":
169
170        content_data = plpy.execute(plpy.prepare(
171             \"\"\"SELECT s.section, b.package, b.architecture, ot.type
172             FROM override o
173             JOIN override_type ot on o.type=ot.id
174             JOIN binaries b on b.package=o.package
175             JOIN files f on b.file=f.id
176             JOIN location l on l.id=f.location
177             JOIN section s on s.id=o.section
178             WHERE b.id=$1
179             AND o.suite=$2
180             \"\"\",
181             ["int", "int"]),
182             [TD["new"]["bin"], TD["new"]["suite"]])[0]
183
184        tablename="%s_contents" % content_data['type']
185
186        plpy.execute(plpy.prepare(\"\"\"DELETE FROM %s
187                    WHERE package=$1 and arch=$2 and suite=$3\"\"\" % tablename,
188                    ['text','int','int']),
189                    [content_data['package'],
190                    content_data['architecture'],
191                    TD["new"]["suite"]])
192
193        filenames = plpy.execute(plpy.prepare(
194            "SELECT bc.file FROM bin_contents bc where bc.binary_id=$1",
195            ["int"]),
196            [TD["new"]["bin"]])
197
198        for filename in filenames:
199            plpy.execute(plpy.prepare(
200                \"\"\"INSERT INTO %s
201                    (filename,section,package,binary_id,arch,suite)
202                    VALUES($1,$2,$3,$4,$5,$6)\"\"\" % tablename,
203                ["text","text","text","int","int","int"]),
204                [filename["file"],
205                 content_data["section"],
206                 content_data["package"],
207                 TD["new"]["bin"],
208                 content_data["architecture"],
209                 TD["new"]["suite"]] )
210 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
211 """)
212
213
214         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_override() RETURNS trigger AS  $$
215     event = TD["event"]
216     if event == "UPDATE":
217
218         otype = plpy.execute(plpy.prepare("SELECT type from override_type where id=$1",["int"]),[TD["new"]["type"]] )[0];
219         if otype["type"].endswith("deb"):
220             section = plpy.execute(plpy.prepare("SELECT section from section where id=$1",["int"]),[TD["new"]["section"]] )[0];
221
222             table_name = "%s_contents" % otype["type"]
223             plpy.execute(plpy.prepare("UPDATE %s set section=$1 where package=$2 and suite=$3" % table_name,
224                                       ["text","text","int"]),
225                                       [section["section"],
226                                       TD["new"]["package"],
227                                       TD["new"]["suite"]])
228
229 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
230 """)
231
232         c.execute("""CREATE OR REPLACE FUNCTION update_contents_for_override()
233                       RETURNS trigger AS  $$
234     event = TD["event"]
235     if event == "UPDATE" or event == "INSERT":
236         row = TD["new"]
237         r = plpy.execute(plpy.prepare( \"\"\"SELECT 1 from suite_architectures sa
238                   JOIN binaries b ON b.architecture = sa.architecture
239                   WHERE b.id = $1 and sa.suite = $2\"\"\",
240                 ["int", "int"]),
241                 [row["bin"], row["suite"]])
242         if not len(r):
243             plpy.error("Illegal architecture for this suite")
244
245 $$ LANGUAGE plpythonu VOLATILE;""")
246
247         c.execute( """CREATE TRIGGER illegal_suite_arch_bin_associations_trigger
248                       BEFORE INSERT OR UPDATE ON bin_associations
249                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
250
251         c.execute( """CREATE TRIGGER bin_associations_contents_trigger
252                       AFTER INSERT OR UPDATE OR DELETE ON bin_associations
253                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_bin_a();""")
254         c.execute("""CREATE TRIGGER override_contents_trigger
255                       AFTER UPDATE ON override
256                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
257
258
259         c.execute( "CREATE INDEX ind_deb_contents_name ON deb_contents(package);");
260         c.execute( "CREATE INDEX ind_udeb_contents_name ON udeb_contents(package);");
261
262         c.execute("UPDATE config SET value = '28' WHERE name = 'db_revision'")
263
264         self.db.commit()
265
266     except psycopg2.ProgrammingError, msg:
267         self.db.rollback()
268         raise DBUpdateError, "Unable to apply process-new update 28, rollback issued. Error message : %s" % (str(msg))
269