]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update66.py
Rewrite trigger functions in plpgsql.
[dak.git] / dak / dakdb / update66.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 """
5 Add audit schema and initial package table and triggers
6
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2011 Mark Hymers <mhy@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 import psycopg2
29 from daklib.dak_exceptions import DBUpdateError
30 from daklib.config import Config
31
32 ################################################################################
33 def do_update(self):
34     """
35     Add audit schema and initial package table and triggers
36     """
37     print __doc__
38     try:
39         c = self.db.cursor()
40
41         c.execute("CREATE SCHEMA audit");
42         c.execute("GRANT USAGE on SCHEMA audit TO public")
43         c.execute("GRANT USAGE on SCHEMA audit TO ftpteam")
44         c.execute("GRANT USAGE on SCHEMA audit TO ftpmaster")
45
46         c.execute("""CREATE TABLE audit.package_changes (
47    changedate TIMESTAMP NOT NULL DEFAULT now(),
48    package TEXT NOT NULL,
49    version DEBVERSION NOT NULL,
50    architecture TEXT NOT NULL,
51    suite TEXT NOT NULL,
52    event TEXT NOT NULL,
53    priority TEXT,
54    component TEXT,
55    section TEXT
56 )""")
57
58         c.execute("GRANT INSERT ON audit.package_changes TO dak")
59         c.execute("GRANT SELECT ON audit.package_changes TO PUBLIC")
60
61         c.execute("""CREATE OR REPLACE FUNCTION trigger_binsrc_assoc_update() RETURNS TRIGGER AS $$
62 DECLARE
63   v_data RECORD;
64
65   v_package audit.package_changes.package%TYPE;
66   v_version audit.package_changes.version%TYPE;
67   v_architecture audit.package_changes.architecture%TYPE;
68   v_suite audit.package_changes.suite%TYPE;
69   v_event audit.package_changes.event%TYPE;
70   v_priority audit.package_changes.priority%TYPE;
71   v_component audit.package_changes.component%TYPE;
72   v_section audit.package_changes.section%TYPE;
73 BEGIN
74   CASE TG_OP
75     WHEN 'INSERT' THEN v_event := 'I'; v_data := NEW;
76     WHEN 'DELETE' THEN v_event := 'D'; v_data := OLD;
77     ELSE RAISE EXCEPTION 'trigger called for invalid operation (%)', TG_OP;
78   END CASE;
79
80   SELECT suite_name INTO STRICT v_suite FROM suite WHERE id = v_data.suite;
81
82   CASE TG_TABLE_NAME
83     WHEN 'bin_associations' THEN
84       SELECT package, version, arch_string
85         INTO STRICT v_package, v_version, v_architecture
86         FROM binaries LEFT JOIN architecture ON (architecture.id = binaries.architecture)
87         WHERE binaries.id = v_data.bin;
88
89       SELECT component.name, priority.priority, section.section
90         INTO v_component, v_priority, v_section
91         FROM override
92              JOIN override_type ON (override.type = override_type.id)
93              JOIN priority ON (priority.id = override.priority)
94              JOIN section ON (section.id = override.section)
95              JOIN component ON (override.component = component.id)
96              JOIN suite ON (suite.id = override.suite)
97         WHERE override_type.type != 'dsc'
98               AND override.package = v_package AND suite.id = v_data.suite;
99
100     WHEN 'src_associations' THEN
101       SELECT source, version
102         INTO STRICT v_package, v_version
103         FROM source WHERE source.id = v_data.source;
104       v_architecture := 'source';
105
106       SELECT component.name, priority.priority, section.section
107         INTO v_component, v_priority, v_section
108         FROM override
109              JOIN override_type ON (override.type = override_type.id)
110              JOIN priority ON (priority.id = override.priority)
111              JOIN section ON (section.id = override.section)
112              JOIN component ON (override.component = component.id)
113              JOIN suite ON (suite.id = override.suite)
114         WHERE override_type.type = 'dsc'
115               AND override.package = v_package AND suite.id = v_data.suite;
116
117     ELSE RAISE EXCEPTION 'trigger called for invalid table (%)', TG_TABLE_NAME;
118   END CASE;
119
120   INSERT INTO audit.package_changes
121     (package, version, architecture, suite, event, priority, component, section)
122     VALUES (v_package, v_version, v_architecture, v_suite, v_event, v_priority, v_component, v_section);
123
124   RETURN NEW;
125 END;
126 $$ LANGUAGE plpgsql VOLATILE SECURITY DEFINER""");
127
128         c.execute("""CREATE OR REPLACE FUNCTION trigger_override_update() RETURNS TRIGGER AS $$
129 DECLARE
130   v_src_override_id override_type.id%TYPE;
131
132   v_priority audit.package_changes.priority%TYPE := NULL;
133   v_component audit.package_changes.component%TYPE := NULL;
134   v_section audit.package_changes.section%TYPE := NULL;
135 BEGIN
136
137   IF TG_TABLE_NAME != 'override' THEN
138     RAISE EXCEPTION 'trigger called for invalid table (%)', TG_TABLE_NAME;
139   END IF;
140   IF TG_OP != 'UPDATE' THEN
141     RAISE EXCEPTION 'trigger called for invalid event (%)', TG_OP;
142   END IF;
143
144   IF OLD.package != NEW.package OR OLD.type != NEW.type OR OLD.suite != NEW.suite THEN
145     RETURN NEW;
146   END IF;
147
148   IF OLD.priority != NEW.priority THEN
149     SELECT priority INTO STRICT v_priority FROM priority WHERE id = NEW.priority;
150   END IF;
151
152   IF OLD.component != NEW.component THEN
153     SELECT name INTO STRICT v_component FROM component WHERE id = NEW.component;
154   END IF;
155
156   IF OLD.section != NEW.section THEN
157     SELECT section INTO STRICT v_section FROM section WHERE id = NEW.section;
158   END IF;
159
160   -- Find out if we're doing src or binary overrides
161   SELECT id INTO STRICT v_src_override_id FROM override_type WHERE type = 'dsc';
162   IF OLD.type = v_src_override_id THEN
163     -- Doing a src_association link
164     INSERT INTO audit.package_changes
165       (package, version, architecture, suite, event, priority, component, section)
166       SELECT NEW.package, source.version, 'source', suite.suite_name, 'U', v_priority, v_component, v_section
167         FROM source
168           JOIN src_associations ON (source.id = src_associations.source)
169           JOIN suite ON (suite.id = src_associations.suite)
170         WHERE source.source = NEW.package AND src_associations.suite = NEW.suite;
171   ELSE
172     -- Doing a bin_association link
173     INSERT INTO audit.package_changes
174       (package, version, architecture, suite, event, priority, component, section)
175       SELECT NEW.package, binaries.version, architecture.arch_string, suite.suite_name, 'U', v_priority, v_component, v_section
176         FROM binaries
177           JOIN bin_associations ON (binaries.id = bin_associations.bin)
178           JOIN architecture ON (architecture.id = binaries.architecture)
179           JOIN suite ON (suite.id = bin_associations.suite)
180         WHERE binaries.package = NEW.package AND bin_associations.suite = NEW.suite;
181   END IF;
182
183   RETURN NEW;
184 END;
185 $$ LANGUAGE plpgsql VOLATILE SECURITY DEFINER""");
186
187         c.execute("CREATE TRIGGER trigger_bin_associations_audit AFTER INSERT OR DELETE ON bin_associations FOR EACH ROW EXECUTE PROCEDURE trigger_binsrc_assoc_update()")
188         c.execute("CREATE TRIGGER trigger_src_associations_audit AFTER INSERT OR DELETE ON src_associations FOR EACH ROW EXECUTE PROCEDURE trigger_binsrc_assoc_update()")
189         c.execute("CREATE TRIGGER trigger_override_audit AFTER UPDATE ON override FOR EACH ROW EXECUTE PROCEDURE trigger_override_update()")
190
191         c.execute("UPDATE config SET value = '66' WHERE name = 'db_revision'")
192         self.db.commit()
193
194     except psycopg2.ProgrammingError, msg:
195         self.db.rollback()
196         raise DBUpdateError, 'Unable to apply sick update 66, rollback issued. Error message : %s' % (str(msg))