source: trunk/LATMOS-Accounts/bin/la-sql-upgrade.in @ 1634

Last change on this file since 1634 was 1490, checked in by nanardon, 9 years ago

Add filter based aliases (dynamics)

File size: 31.6 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5use LATMOS::Accounts;
6use Getopt::Long;
7use Pod::Usage;
8
9my $DATADIR = '@DATADIR@';
10
11=head1 NAME
12
13    la-sql-upgrade - Update SQL base schema
14
15=head1 SYNOPSIS
16
17    la-sql-upgrade [options] [name]
18
19=cut
20
21GetOptions(
22    'c|config=s'     => \my $config,
23    'b|base=s'       => \my $base,
24    'no-commit'      => \my $nocommit,
25    'v|verbose'      => \my $verbose,
26    'h|help'         => sub { pod2usage(1); },
27) or pod2usage();
28
29=head1 OPTIONS
30
31=over 4
32
33=item -c|--config configdir
34
35Use this configuration directory instead of the default one.
36
37=item -b|--base basename
38
39Query this specific base instead of the default one.
40
41=back
42
43=cut
44
45$| = 1; # autoflush
46
47my $LA = LATMOS::Accounts->new($config, noacl => 1);
48my $labase = $LA->base($base);
49
50my $dbi = $labase->db;
51
52my $rev = $labase->get_global_value('schema_version') || 1;
53
54my @updates = (
55    {
56        ver => 3,
57        sql => [
58            q{ALTER TABLE nethost_attributes_ips DROP CONSTRAINT
59            nethost_is_single_ip},
60            q{DROP TRIGGER IF EXISTS check_zone_name_unity_tg ON nethost},
61            q{DROP TRIGGER IF EXISTS check_zone_name_unity_tg ON netzone},
62            q{DROP FUNCTION IF EXISTS check_zone_name_unity()},
63            q{ALTER TABLE nethost_attributes_ips DROP CONSTRAINT
64            nethost_is_single_ip},
65            q{INSERT INTO settings(varname, val) VALUES ('schema_version', 3)},
66        ],
67    },
68    {
69        ver => 4,
70        sql => [
71            q{
72            CREATE OR REPLACE FUNCTION nethost_sort_fields()
73            RETURNS trigger AS
74            $BODY$BEGIN
75
76            IF (TG_OP='INSERT') then
77            IF (new.attr='ip') THEN
78            insert into nethost_attributes_ips VALUES (new.*);
79            RETURN NULL;
80            END IF;
81
82            IF (new.attr='macaddr') THEN
83            insert into nethost_attributes_macs VALUES (new.*);
84            RETURN NULL;
85            END IF;
86
87            IF (new.attr='owner') THEN
88            insert into nethost_attributes_users VALUES (new.*);
89            RETURN NULL;
90            END IF;
91
92            IF (new.attr='user') THEN
93            insert into nethost_attributes_users VALUES (new.*);
94            RETURN NULL;
95            END IF;
96            end if;
97
98
99            if (TG_OP='DELETE') THEN
100            RETURN old;
101            else
102            RETURN new;
103            end if;
104            END;$BODY$
105            LANGUAGE plpgsql VOLATILE
106            COST 100;
107            },
108        ],
109    },
110    {
111        ver => 5,
112        sql => [
113            q{
114            CREATE OR REPLACE VIEW address_attributes AS
115            ( ( SELECT address."user" AS value, 'user' AS attr, address.rev AS attr_key, address.ikey AS okey
116            FROM address
117            UNION ALL
118            SELECT address.name AS value, 'name' AS attr, address.rev AS attr_key, address.ikey AS okey
119            FROM address )
120            UNION ALL
121            SELECT address_attributes.value, address_attributes.attr, address_attributes.attr_key, address_attributes.okey
122            FROM address_attributes_base address_attributes )
123            UNION ALL
124            SELECT '1' AS value, 'active' AS attr, address.rev AS attr_key, address.ikey AS okey
125            FROM "user" JOIN address ON "user".name = address."user"
126            WHERE "user".exported AND address.exported and
127            ("user".expire IS NULL or "user".expire > now())
128            }
129        ],
130    },
131    {
132        ver => 6,
133        sql => [
134            q{
135            CREATE TABLE request
136            (
137                id serial NOT NULL,
138                "create" timestamp with time zone NOT NULL DEFAULT now(),
139                name text NOT NULL,
140                object text,
141                apply timestamp with time zone NOT NULL DEFAULT now(),
142                done timestamp with time zone,
143                "user" text,
144                CONSTRAINT request_pkey PRIMARY KEY (id ),
145                CONSTRAINT request_name_fkey FOREIGN KEY (name)
146                REFERENCES accreq (name) MATCH SIMPLE
147                ON UPDATE CASCADE ON DELETE CASCADE,
148                CONSTRAINT request_user_fkey FOREIGN KEY ("user")
149                REFERENCES "user" (name) MATCH SIMPLE
150                ON UPDATE CASCADE ON DELETE SET NULL
151            )
152            },
153            q{
154            CREATE INDEX fki_request_name_fkey ON request
155            USING btree (name )
156            },
157            q{
158            CREATE INDEX fki_request_user_fkey ON request
159            USING btree ("user" )
160            },
161            q{
162            CREATE TABLE request_attributes
163            (
164                reqid bigint,
165                attribute text NOT NULL,
166                value text,
167                CONSTRAINT request_id_fkey FOREIGN KEY (reqid)
168                REFERENCES request (id) MATCH SIMPLE
169                ON UPDATE CASCADE ON DELETE CASCADE
170            )
171            },
172            q{
173            CREATE INDEX fki_request_id_fkey ON request_attributes
174            USING btree (reqid )
175            },
176            q{
177            delete from accreq_attributes_list
178            }
179        ],
180    },
181    {
182        ver => 7,
183        sql => [
184            q{
185            ALTER TABLE request ADD COLUMN automated boolean NOT NULL DEFAULT false;
186            },
187            q{
188            ALTER TABLE request ADD COLUMN objrev bigint;
189            },
190            q{
191            ALTER TABLE aliases ADD COLUMN description text;
192            },
193            q{
194            ALTER TABLE revaliases ADD COLUMN description text;
195            },
196            q{
197            CREATE OR REPLACE FUNCTION group_sort_fields()
198              RETURNS trigger AS
199              $BODY$BEGIN
200
201              IF (TG_OP='INSERT') then
202              IF (new.attr='managedBy'
203                  OR  new.attr='managedAlsoBy'
204                  OR  new.attr='member'
205                  OR  new.attr='memberUID') THEN
206              insert into group_attributes_users VALUES (new.*);
207              RETURN NULL;
208              END IF;
209
210              IF (new.attr='sutype') THEN
211              insert into group_attributes_sutypes VALUES (new.*);
212              RETURN NULL;
213              END IF;
214              end if;
215
216
217              IF (TG_OP = 'UPDATE') THEN
218              IF (new.attr='gidNumber') then
219              update "group" set gidnumber = new.value::integer where
220              "group".ikey = new.okey;
221              RETURN NULL;
222              END IF;
223              END IF;
224
225              IF (TG_OP = 'DELETE') THEN
226              IF (old.attr='exported') then
227              update "group" set exported = false where "group".ikey = old.okey;
228              return null;
229              end if;
230              else
231              IF (new.attr='exported') then
232              update "group" set exported = true where "group".ikey = new.okey;
233              RETURN NULL;
234              end if;
235              END IF;
236
237              if (TG_OP='DELETE') THEN
238              RETURN old;
239              else
240              RETURN new;
241              end if;
242              END;$BODY$
243                LANGUAGE plpgsql VOLATILE
244                  COST 100;
245            },
246        ],
247    },
248    {
249        ver => 8,
250        sql => [
251            q{
252            CREATE TABLE objectslogs
253            (
254              logkey SERIAL NOT NULL,
255              ikey bigint NOT NULL,
256              irev bigint,
257              otype text NOT NULL,
258              name text NOT NULL,
259              changetype text NOT NULL,
260              username text NOT NULL,
261              message text NOT NULL,
262              logdate timestamp with time zone NOT NULL DEFAULT now(),
263              CONSTRAINT objectlogs_pkey PRIMARY KEY (logkey)
264            );},
265            q{
266            CREATE INDEX objectlogs_name_idx
267              ON objectslogs
268              USING btree
269              (name);
270            },
271            q{
272            CREATE INDEX objectslogs_ikey_idx
273              ON objectslogs
274              USING btree
275              (ikey);
276            },
277            q{
278            CREATE INDEX objectslogs_otype_idx
279              ON objectslogs
280              USING btree
281              (otype);
282            }
283        ],
284    },
285    {
286        ver => 9,
287        sql => [
288            q{
289            CREATE TABLE nethost_attributes_nethosts
290            (
291            CONSTRAINT nethost_attributes_nethosts_pkey PRIMARY KEY (attr_key),
292            CONSTRAINT nethost_attr_nethosts_fkey FOREIGN KEY (okey)
293            REFERENCES nethost (ikey) MATCH SIMPLE
294            ON UPDATE CASCADE ON DELETE CASCADE,
295            CONSTRAINT nethost_attr_nethosts_nethosts FOREIGN KEY ("value")
296            REFERENCES nethost (name) MATCH SIMPLE
297            ON UPDATE CASCADE ON DELETE CASCADE
298            )
299            INHERITS (nethost_attributes);
300
301            CREATE INDEX fki_nethost_attr_nethosts_fkey
302            ON nethost_attributes_nethosts
303            USING btree
304            (okey);
305
306            CREATE TRIGGER nethost_attr_nethosts_update
307            AFTER INSERT OR UPDATE OR DELETE
308            ON nethost_attributes_nethosts
309            FOR EACH ROW
310            EXECUTE PROCEDURE nethost_attr_update_ref();
311
312
313            CREATE OR REPLACE FUNCTION nethost_sort_fields()
314              RETURNS trigger AS
315              $BODY$BEGIN
316
317              IF (TG_OP='INSERT') then
318              IF (new.attr='ip') THEN
319              insert into nethost_attributes_ips VALUES (new.*);
320              RETURN NULL;
321              END IF;
322
323              IF (new.attr='macaddr') THEN
324              insert into nethost_attributes_macs VALUES (new.*);
325              RETURN NULL;
326              END IF;
327
328              IF (new.attr='owner') THEN
329              insert into nethost_attributes_users VALUES (new.*);
330              RETURN NULL;
331              END IF;
332
333              IF (new.attr='user') THEN
334              insert into nethost_attributes_users VALUES (new.*);
335              RETURN NULL;
336              END IF;
337
338              IF (new.attr='related') THEN
339              insert into nethost_attributes_nethosts VALUES (new.*);
340              RETURN NULL;
341              END IF;
342              end if;
343
344              if (TG_OP='DELETE') THEN
345              RETURN old;
346              else
347              RETURN new;
348              end if;
349              END;$BODY$
350              LANGUAGE plpgsql VOLATILE
351              COST 100;
352
353            }
354        ],
355    },
356    {
357        ver => 10,
358        sql => [
359            q{
360            CREATE OR REPLACE FUNCTION service_attr_update_ref()
361            RETURNS trigger AS
362            $BODY$begin
363
364            IF (TG_OP != 'INSERT') then
365            update "service" set date = now() where "service".ikey = old.okey;
366            end if;
367            IF (TG_OP != 'DELETE') then
368            update "service"  set date = now() where "service".ikey = new.okey;
369            end if;
370
371            IF (TG_OP = 'DELETE') then
372            return old;
373            ELSE
374            return new;
375            END IF;
376
377            END;$BODY$
378            LANGUAGE plpgsql VOLATILE
379            COST 100;
380            },
381            q{
382
383            CREATE TABLE service
384            (
385            "start" date,
386            "end" date,
387            CONSTRAINT service_pkey PRIMARY KEY (name),
388            CONSTRAINT service_ikey_uniq UNIQUE (ikey)
389            )
390            INHERITS (objects);
391            },
392            q{
393            CREATE TABLE service_attributes_list
394            (
395            ikey integer NOT NULL DEFAULT nextval('ikey_seq'::regclass),
396            canonical text NOT NULL,
397            description text,
398            CONSTRAINT service_attributes_list_pkey PRIMARY KEY (ikey),
399            CONSTRAINT g_attr_l_service_uniq UNIQUE (canonical)
400            )
401            INHERITS (revisions, attributes_list)
402            WITH (
403            OIDS=FALSE
404            );
405            ALTER TABLE service_attributes_list
406            OWNER TO latmos;
407
408            CREATE TABLE service_attributes
409            (
410            CONSTRAINT service_attributes_pkey PRIMARY KEY (attr_key),
411            CONSTRAINT service_attr_users_okey_fkey FOREIGN KEY (okey)
412            REFERENCES service (ikey) MATCH SIMPLE
413            ON UPDATE CASCADE ON DELETE CASCADE,
414            CONSTRAINT service_attributes_attr_fkey FOREIGN KEY (attr)
415            REFERENCES service_attributes_list (canonical) MATCH SIMPLE
416            ON UPDATE CASCADE ON DELETE NO ACTION
417            )
418            INHERITS (attributes)
419            WITH (
420            OIDS=FALSE
421            );
422            ALTER TABLE service_attributes
423            OWNER TO latmos;
424
425            CREATE INDEX fki_service_attributes_attr_fkey
426            ON nethost_attributes
427            USING btree
428            (attr);
429
430            CREATE INDEX service_attr_value_idx
431            ON nethost_attributes
432            USING btree
433            (value);
434
435            CREATE TRIGGER serivce_attr_update
436            AFTER INSERT OR UPDATE OR DELETE
437            ON service_attributes
438            FOR EACH ROW
439            EXECUTE PROCEDURE service_attr_update_ref();
440            },
441            q{
442            CREATE TABLE service_attributes_users
443            (
444            CONSTRAINT service_attributes_user_pkey PRIMARY KEY (attr_key),
445            CONSTRAINT service_attr_users_okey_fkey FOREIGN KEY (okey)
446            REFERENCES service (ikey) MATCH SIMPLE
447            ON UPDATE CASCADE ON DELETE CASCADE,
448            CONSTRAINT service_attributes_users_attr_fkey FOREIGN KEY (attr)
449            REFERENCES service_attributes_list (canonical) MATCH SIMPLE
450            ON UPDATE CASCADE ON DELETE NO ACTION,
451            CONSTRAINT service_attributes_users_user_fkey FOREIGN KEY (value)
452            REFERENCES "user" (name) MATCH SIMPLE
453            ON UPDATE CASCADE ON DELETE CASCADE,
454            CONSTRAINT service_attributes_users_uniq UNIQUE (okey, attr, value)
455            )
456            INHERITS (service_attributes);
457
458            CREATE INDEX fki_service_attr_users_okey_fkey
459            ON service_attributes_users
460            USING btree
461            (okey);
462
463            CREATE INDEX fki_service_attributes_users_attr_fkey
464            ON service_attributes_users
465            USING btree
466            (attr);
467
468            CREATE INDEX fki_service_attributes_users_user_fkey
469            ON service_attributes_users
470            USING btree
471            (value);
472
473            CREATE TRIGGER service_attributes_users_update_ref
474            AFTER INSERT OR UPDATE OR DELETE
475            ON service_attributes_users
476            FOR EACH ROW
477            EXECUTE PROCEDURE service_attr_update_ref();
478
479            CREATE OR REPLACE FUNCTION service_sort_fields()
480              RETURNS trigger AS
481              $BODY$BEGIN
482
483              if (TG_OP='INSERT' or TG_OP='UPDATE') THEN
484              IF (new.attr='manager') THEN
485              insert into service_attributes_users VALUES (new.*);
486              RETURN NULL;
487              END IF;
488              END IF;
489
490              if (TG_OP='DELETE') THEN
491              RETURN old;
492              else
493              RETURN new;
494              end if;
495              END;$BODY$
496              LANGUAGE plpgsql VOLATILE
497              COST 100;
498
499              CREATE TRIGGER service_sort_field_tg
500              BEFORE INSERT OR UPDATE OR DELETE
501              ON service_attributes
502              FOR EACH ROW
503              EXECUTE PROCEDURE service_sort_fields();
504
505            CREATE TRIGGER service_rev_tg
506            BEFORE INSERT OR UPDATE OR DELETE
507            ON service
508            FOR EACH ROW
509            EXECUTE PROCEDURE rev_tg_f();
510            },
511        ],
512    },
513    {
514        ver => 11,
515        sql => [
516            q{
517            ALTER TABLE "user" ADD COLUMN endcircuit timestamp with time zone
518            }
519        ],
520    },
521    {
522        ver => 12,
523        sql => [
524            q{
525            CREATE OR REPLACE VIEW user_attributes AS
526            (        (        (        (        (        (        (        (        (        (        (
527            SELECT "user".uidnumber::text AS value, 'uidnumber' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user"
528            UNION ALL
529            SELECT "user".gidnumber::text AS value, 'gidnumber' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user")
530            UNION ALL
531            SELECT "user".name AS value, 'name' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user")
532            UNION ALL
533            SELECT "user".expire::text AS value, 'expire' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user"
534            WHERE "user".expire IS NOT NULL)
535            UNION ALL
536            SELECT '1'::text AS value, 'exported' AS attr, "user".rev AS attr_key, "user".ikey AS okey
537            FROM "user"
538            WHERE "user".exported = true)
539            UNION ALL
540            SELECT address_attributes_site.value, 'allsite' AS attr, "user".rev AS attr_key, "user".ikey AS okey
541            FROM "user"
542            JOIN address ON address."user" = "user".name
543            JOIN address_attributes_site ON address_attributes_site.okey = address.ikey
544            WHERE address_attributes_site.attr = 'site'::text AND address.exported = true)
545            UNION ALL
546            SELECT "group".name AS value, 'memberOf' AS attr, "user".rev AS attr_key, "user".ikey AS okey
547            FROM "user"
548            JOIN group_attributes ON group_attributes.value = "user".name
549            JOIN "group" ON group_attributes.okey = "group".ikey
550            WHERE group_attributes.attr = 'memberUID'::text)
551            UNION ALL
552            SELECT user_attributes.value, user_attributes.attr, user_attributes.attr_key, user_attributes.okey
553            FROM user_attributes_base user_attributes)
554            UNION ALL
555            SELECT "group".name AS value, 'departments' AS attr, "user".rev AS attr_key, "user".ikey AS okey
556            FROM "group"
557            JOIN group_attributes_sutypes ON "group".ikey = group_attributes_sutypes.okey
558            JOIN group_attributes_users ON "group".ikey = group_attributes_users.okey AND group_attributes_users.attr = 'memberUID'::text
559            JOIN "user" ON "user".name = group_attributes_users.value
560            WHERE group_attributes_sutypes.value = 'dpmt'::text AND group_attributes_sutypes.attr = 'sutype'::text)
561            UNION ALL
562            SELECT "group".name AS value, 'cells' AS attr, "user".rev AS attr_key, "user".ikey AS okey
563            FROM "group"
564            JOIN group_attributes_sutypes ON "group".ikey = group_attributes_sutypes.okey
565            JOIN group_attributes_users ON "group".ikey = group_attributes_users.okey AND group_attributes_users.attr = 'memberUID'::text
566            JOIN "user" ON "user".name = group_attributes_users.value
567            WHERE group_attributes_sutypes.value = 'cell'::text AND group_attributes_sutypes.attr = 'sutype'::text)
568            UNION ALL
569            SELECT "group".name AS value, 'managedObjects' AS attr, "user".rev AS attr_key, "user".ikey AS okey
570            FROM "user"
571            JOIN group_attributes ON group_attributes.value = "user".name
572            JOIN "group" ON group_attributes.okey = "group".ikey
573            WHERE group_attributes.attr = 'managedBy'::text)
574            UNION ALL
575            SELECT justify_interval(now() - "user".expire)::text AS value, 'expired' AS attr, "user".rev AS attr_key, "user".ikey AS okey
576            FROM "user"
577            WHERE "user".expire <= now())
578            UNION ALL
579            SELECT 1::text AS value, 'active' AS attr, "user".rev AS attr_key, "user".ikey AS okey
580            FROM "user"
581            WHERE ("user".expire IS NULL OR "user".expire >= now()) AND "user".exported = true
582            UNION ALL
583            SELECT 0::text AS value, 'active' AS attr, "user".rev AS attr_key, "user".ikey AS okey
584            FROM "user"
585            WHERE ("user".expire IS NOT NULL and "user".expire <= now()) or "user".exported = false;
586            },
587            q{
588            CREATE OR REPLACE FUNCTION rev_tg_aliases_f()
589            RETURNS trigger AS
590            $BODY$begin
591
592            IF (TG_OP = 'DELETE') THEN
593            update "user" set rev = nextval('revisions_rev_seq'::regclass), "date" = now() where "name" = ANY (old.forward);
594            return old;
595            ELSE
596                IF (TG_OP = 'UPDATE') THEN
597                update "user" set rev = nextval('revisions_rev_seq'::regclass), "date" = now() where "name" = ANY (old.forward);
598                END IF;
599            update "user" set rev = nextval('revisions_rev_seq'::regclass), "date" = now() where "name" = ANY (new.forward);
600            return new;
601            END IF;
602
603            end;$BODY$
604            LANGUAGE plpgsql VOLATILE
605            COST 100;
606
607            CREATE TRIGGER aliases_user_tg
608            AFTER INSERT OR UPDATE OR DELETE
609            ON aliases
610            FOR EACH ROW
611            EXECUTE PROCEDURE rev_tg_aliases_f();
612            },
613        ],
614    },
615    {
616        ver => 13,
617        sql => [
618            q{
619            CREATE TABLE "stat"
620            (
621            name text NOT NULL,
622            CONSTRAINT stat_pkey PRIMARY KEY (name),
623            CONSTRAINT stat_okey_uniq UNIQUE (ikey)
624            )
625            INHERITS (objects);
626            CREATE INDEX stat_exported_idx
627            ON stat USING btree (exported);
628            CREATE UNIQUE INDEX stat_rev_idx
629            ON stat USING btree (rev);
630
631            CREATE OR REPLACE FUNCTION stat_attr_update_ref()
632            RETURNS trigger AS
633            $BODY$begin
634
635            IF (TG_OP != 'INSERT') then
636            update "stat" set date = now() where "stat".ikey = old.okey;
637            end if;
638            IF (TG_OP != 'DELETE') then
639            update "stat"  set date = now() where "stat".ikey = new.okey;
640            end if;
641
642            IF (TG_OP = 'DELETE') then
643            return old;
644            ELSE
645            return new;
646            END IF;
647
648            END;$BODY$
649            LANGUAGE plpgsql VOLATILE
650            COST 100;
651            },
652            q{
653            CREATE TABLE stat_attributes
654            (
655            CONSTRAINT stat_attributes_pkey PRIMARY KEY (attr_key),
656            CONSTRAINT stat FOREIGN KEY (okey)
657            REFERENCES stat (ikey) MATCH SIMPLE
658            ON UPDATE CASCADE ON DELETE CASCADE
659            )
660            INHERITS (attributes);
661            CREATE INDEX stat_attributes_attr_fkey
662            ON stat_attributes
663            USING btree
664            (attr);
665            CREATE INDEX stat_attr_value_idx
666            ON stat_attributes
667            USING btree
668            (value);
669            CREATE TRIGGER stat_attr_update
670            AFTER INSERT OR UPDATE OR DELETE
671            ON stat_attributes
672            FOR EACH ROW
673            EXECUTE PROCEDURE stat_attr_update_ref();
674            },
675            q{
676            CREATE TABLE stat_attributes_list
677            (
678            CONSTRAINT stat_attr_list_pkey PRIMARY KEY (ikey),
679            CONSTRAINT stat_attr_l_c_uniq UNIQUE (canonical)
680            )
681            INHERITS (revisions, attributes_list);
682            },
683            q{
684            CREATE TABLE statsentry
685            (
686            okey integer NOT NULL,
687            id bigint NOT NULL DEFAULT nextval('revisions_rev_seq'::regclass),
688            tstamp timestamp with time zone NOT NULL DEFAULT now(),
689            CONSTRAINT stat FOREIGN KEY (okey)
690            REFERENCES stat (ikey) MATCH SIMPLE
691            ON UPDATE CASCADE ON DELETE CASCADE,
692            CONSTRAINT statsentry_pkey PRIMARY KEY (id)
693            );
694            CREATE TABLE statvalues
695            (
696            sid bigint NOT NULL,
697            value text NOT NULL,
698            count bigint NOT NULL,
699            CONSTRAINT statvalues_pkey PRIMARY KEY (sid, value),
700            CONSTRAINT statvalues_fkey FOREIGN KEY (sid)
701            REFERENCES statsentry (id) MATCH SIMPLE
702            ON UPDATE CASCADE ON DELETE CASCADE
703            )
704            },
705        ],
706    },
707    {
708        ver => 14,
709        sql => [
710            q{
711            ALTER TABLE objects ADD COLUMN createdby text;
712            },
713            q{
714            ALTER TABLE objects ADD COLUMN modifiedby text;
715            },
716        ],
717    },
718    {
719        ver => 15,
720        sql => [
721            q{
722            CREATE TABLE "employment"
723            (
724            name text NOT NULL,
725            "user" text NOT NULL,
726            firstday date NOT NULL default now(),
727            lastday  date,
728            CONSTRAINT employment_pkey PRIMARY KEY (name),
729            CONSTRAINT employment_okey_uniq UNIQUE (ikey),
730            CONSTRAINT employment_user_fkey FOREIGN KEY ("user")
731                REFERENCES "user" (name) MATCH SIMPLE
732                ON UPDATE CASCADE ON DELETE CASCADE
733            )
734            INHERITS (objects);
735            CREATE INDEX employment_exported_idx
736            ON employment USING btree (exported);
737            CREATE UNIQUE INDEX employment_rev_idx
738            ON employment USING btree (rev);
739
740            CREATE OR REPLACE FUNCTION employment_attr_update_ref()
741            RETURNS trigger AS
742            $BODY$begin
743
744            IF (TG_OP != 'INSERT') then
745            update "employment" set date = now() where "employment".ikey = old.okey;
746            end if;
747            IF (TG_OP != 'DELETE') then
748            update "employment"  set date = now() where "employment".ikey = new.okey;
749            end if;
750
751            IF (TG_OP = 'DELETE') then
752            return old;
753            ELSE
754            return new;
755            END IF;
756
757            END;$BODY$
758            LANGUAGE plpgsql VOLATILE
759            COST 100;
760            },
761            q{
762            CREATE TABLE employment_attributes
763            (
764            CONSTRAINT employment_attributes_pkey PRIMARY KEY (attr_key),
765            CONSTRAINT employment FOREIGN KEY (okey)
766            REFERENCES employment (ikey) MATCH SIMPLE
767            ON UPDATE CASCADE ON DELETE CASCADE
768            )
769            INHERITS (attributes);
770            CREATE INDEX employment_attributes_attr_fkey
771            ON employment_attributes
772            USING btree
773            (attr);
774            CREATE INDEX employment_attr_value_idx
775            ON employment_attributes
776            USING btree
777            (value);
778            CREATE TRIGGER employment_attr_update
779            AFTER INSERT OR UPDATE OR DELETE
780            ON employment_attributes
781            FOR EACH ROW
782            EXECUTE PROCEDURE employment_attr_update_ref();
783            },
784            q{
785            CREATE TABLE employment_attributes_list
786            (
787            CONSTRAINT employment_attr_list_pkey PRIMARY KEY (ikey),
788            CONSTRAINT employment_attr_l_c_uniq UNIQUE (canonical)
789            )
790            INHERITS (revisions, attributes_list);
791            },
792            q{
793            CREATE INDEX employment_firstday_idx
794              ON employment
795                USING btree
796                  (firstday NULLS FIRST);
797            CREATE INDEX employment_lastday_idx
798              ON employment
799                USING btree
800                  (lastday NULLS LAST);
801            },
802        ],
803    },
804    {
805        ver => 16,
806        sql => [
807            q{
808            ALTER TABLE aliases
809              ADD CONSTRAINT aliases_ikey_uniq UNIQUE(ikey);
810            CREATE OR REPLACE FUNCTION aliases_attr_update_ref()
811            RETURNS trigger AS
812            $BODY$begin
813
814            IF (TG_OP != 'INSERT') then
815            update "aliases" set date = now() where "aliases".ikey = old.okey;
816            end if;
817            IF (TG_OP != 'DELETE') then
818            update "aliases"  set date = now() where "aliases".ikey = new.okey;
819            end if;
820
821            IF (TG_OP = 'DELETE') then
822            return old;
823            ELSE
824            return new;
825            END IF;
826
827            END;$BODY$
828            LANGUAGE plpgsql VOLATILE
829            COST 100;
830            },
831            q{
832            CREATE TABLE aliases_attributes_base
833            (
834            CONSTRAINT aliases_attributes_base_pkey PRIMARY KEY (attr_key),
835            CONSTRAINT aliases_fkey FOREIGN KEY (okey)
836            REFERENCES aliases (ikey) MATCH SIMPLE
837            ON UPDATE CASCADE ON DELETE CASCADE
838            )
839            INHERITS (attributes);
840            CREATE INDEX aliases_attributes_base_attr_fkey
841            ON aliases_attributes_base
842            USING btree
843            (attr);
844            CREATE INDEX aliases_attr_value_idx
845            ON aliases_attributes_base
846            USING btree
847            (value);
848            CREATE TRIGGER aliases_attr_update
849            AFTER INSERT OR UPDATE OR DELETE
850            ON aliases_attributes_base
851            FOR EACH ROW
852            EXECUTE PROCEDURE aliases_attr_update_ref();
853            },
854            q{
855            CREATE OR REPLACE VIEW aliases_attributes AS
856            SELECT "user".name AS value,
857            'user'::text AS attr,
858            aliases.rev AS attr_key,
859            aliases.ikey AS okey
860            FROM aliases
861            JOIN "user" ON aliases.name = "user".name OR aliases.forward = ARRAY["user".name]
862            union all
863               select value, attr, attr_key, okey from aliases_attributes_base
864            UNION ALL
865                SELECT "aliases".name AS value,
866                'name'::text AS attr,
867                "aliases".rev AS attr_key,
868                "aliases".ikey AS okey
869                FROM "aliases";
870
871           CREATE OR REPLACE RULE aliases_attributes_insert AS
872           ON INSERT TO aliases_attributes DO INSTEAD  INSERT INTO aliases_attributes_base (value, attr, okey)
873           VALUES (new.value, new.attr, new.okey);
874
875           CREATE OR REPLACE RULE aliases_attributes_update AS
876           ON UPDATE TO aliases_attributes DO INSTEAD  UPDATE aliases_attributes_base SET value = new.value, attr = new.attr, okey = new.okey
877           WHERE aliases_attributes_base.attr_key = old.attr_key AND aliases_attributes_base.attr = old.attr;
878
879           CREATE OR REPLACE RULE aliases_atttributes_delete AS
880           ON DELETE TO aliases_attributes DO INSTEAD  DELETE FROM aliases_attributes_base
881           WHERE aliases_attributes_base.attr_key = old.attr_key AND aliases_attributes_base.attr = old.attr;
882            }
883
884        ],
885    }
886);
887
888my @objects = (
889    {
890        name => 'dpmt',
891        otype => 'sutype',
892        attrs => {
893            description => 'Department',
894        },
895    },
896    {
897        name => 'contrattype',
898        otype => 'sutype',
899        attrs => {
900            description => 'Contract',
901        },
902    },
903);
904
905$dbi->rollback;
906
907foreach my $maj (@updates) {
908    if ($rev >= $maj->{ver}) {
909        next;
910    }
911    print "\n";
912    print 'Switching to schema revision: ' . $maj->{ver} . "\n";
913    foreach my $sql (@{ $maj->{sql} }) {
914        {
915            my $sqlv = $sql;
916            $sqlv =~ s/^/  /mg;
917            if ($verbose) {
918                warn '  >' . $sqlv . "\n";
919            } else {
920                print 'x';
921            }
922        }
923        my $err = $dbi->do($sql);
924        defined($err) or die "Erreur :\\" . $dbi->errstr . "\n";
925    }
926
927    print "\n";
928
929    print 'Updating schema_version to ' . $maj->{ver} . "\n";
930
931    $dbi->do(
932        'UPDATE settings SET val = ? where varname = ?',
933        undef,
934        $maj->{ver}, 'schema_version'
935    );
936    print "Done\n\n";
937
938}
939
940foreach my $otype ($labase->list_supported_objects) {
941    foreach my $attribute ($labase->list_canonical_fields($otype, 'r')) {
942        my $attr = $labase->attribute($otype, $attribute);
943        $attr->{inline} and next;
944        $attr->{managed} and next;
945
946        if ($labase->is_registered_attribute($otype, $attribute)) {
947        } else {
948            $labase->register_attribute($otype, $attribute, $attr->{comment})
949                or die "Error, aborting\n";
950            print "Attr. $attribute for object type $otype registred\n";
951        }
952    }
953}
954 
955foreach (@objects) {
956    if (!$labase->get_object($_->{otype}, $_->{name})) {
957        printf("Creatting object %s/%s\n", $_->{otype}, $_->{name});
958        $labase->create_object($_->{otype}, $_->{name}, %{$_->{attrs} || {}})
959            or die sprintf("cannot create %s/%s\n", $_->{otype}, $_->{name});
960
961    }
962}
963
964if ($nocommit) {
965    $dbi->rollback;
966} else {
967    $dbi->commit;
968}
969print "Process terminated successfully\n";
Note: See TracBrowser for help on using the repository browser.