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

Last change on this file since 1907 was 1907, checked in by nanardon, 7 years ago

Add cache for object alias, then allow search trought them

File size: 41.3 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$labase->unexported(1);
50
51my $dbi = $labase->db;
52
53my $rev = $labase->get_global_value('schema_version') || 1;
54
55my @updates = (
56    {
57        ver => 3,
58        sql => [
59            q{ALTER TABLE nethost_attributes_ips DROP CONSTRAINT
60            nethost_is_single_ip},
61            q{DROP TRIGGER IF EXISTS check_zone_name_unity_tg ON nethost},
62            q{DROP TRIGGER IF EXISTS check_zone_name_unity_tg ON netzone},
63            q{DROP FUNCTION IF EXISTS check_zone_name_unity()},
64            q{ALTER TABLE nethost_attributes_ips DROP CONSTRAINT
65            nethost_is_single_ip},
66            q{INSERT INTO settings(varname, val) VALUES ('schema_version', 3)},
67        ],
68    },
69    {
70        ver => 4,
71        sql => [
72            q{
73            CREATE OR REPLACE FUNCTION nethost_sort_fields()
74            RETURNS trigger AS
75            $BODY$BEGIN
76
77            IF (TG_OP='INSERT') then
78            IF (new.attr='ip') THEN
79            insert into nethost_attributes_ips VALUES (new.*);
80            RETURN NULL;
81            END IF;
82
83            IF (new.attr='macaddr') THEN
84            insert into nethost_attributes_macs VALUES (new.*);
85            RETURN NULL;
86            END IF;
87
88            IF (new.attr='owner') THEN
89            insert into nethost_attributes_users VALUES (new.*);
90            RETURN NULL;
91            END IF;
92
93            IF (new.attr='user') THEN
94            insert into nethost_attributes_users VALUES (new.*);
95            RETURN NULL;
96            END IF;
97            end if;
98
99
100            if (TG_OP='DELETE') THEN
101            RETURN old;
102            else
103            RETURN new;
104            end if;
105            END;$BODY$
106            LANGUAGE plpgsql VOLATILE
107            COST 100;
108            },
109        ],
110    },
111    {
112        ver => 5,
113        sql => [
114            q{
115            CREATE OR REPLACE VIEW address_attributes AS
116            ( ( SELECT address."user" AS value, 'user' AS attr, address.rev AS attr_key, address.ikey AS okey
117            FROM address
118            UNION ALL
119            SELECT address.name AS value, 'name' AS attr, address.rev AS attr_key, address.ikey AS okey
120            FROM address )
121            UNION ALL
122            SELECT address_attributes.value, address_attributes.attr, address_attributes.attr_key, address_attributes.okey
123            FROM address_attributes_base address_attributes )
124            UNION ALL
125            SELECT '1' AS value, 'active' AS attr, address.rev AS attr_key, address.ikey AS okey
126            FROM "user" JOIN address ON "user".name = address."user"
127            WHERE "user".exported AND address.exported and
128            ("user".expire IS NULL or "user".expire > now())
129            }
130        ],
131    },
132    {
133        ver => 6,
134        sql => [
135            q{
136            CREATE TABLE request
137            (
138                id serial NOT NULL,
139                "create" timestamp with time zone NOT NULL DEFAULT now(),
140                name text NOT NULL,
141                object text,
142                apply timestamp with time zone NOT NULL DEFAULT now(),
143                done timestamp with time zone,
144                "user" text,
145                CONSTRAINT request_pkey PRIMARY KEY (id ),
146                CONSTRAINT request_name_fkey FOREIGN KEY (name)
147                REFERENCES accreq (name) MATCH SIMPLE
148                ON UPDATE CASCADE ON DELETE CASCADE,
149                CONSTRAINT request_user_fkey FOREIGN KEY ("user")
150                REFERENCES "user" (name) MATCH SIMPLE
151                ON UPDATE CASCADE ON DELETE SET NULL
152            )
153            },
154            q{
155            CREATE INDEX fki_request_name_fkey ON request
156            USING btree (name )
157            },
158            q{
159            CREATE INDEX fki_request_user_fkey ON request
160            USING btree ("user" )
161            },
162            q{
163            CREATE TABLE request_attributes
164            (
165                reqid bigint,
166                attribute text NOT NULL,
167                value text,
168                CONSTRAINT request_id_fkey FOREIGN KEY (reqid)
169                REFERENCES request (id) MATCH SIMPLE
170                ON UPDATE CASCADE ON DELETE CASCADE
171            )
172            },
173            q{
174            CREATE INDEX fki_request_id_fkey ON request_attributes
175            USING btree (reqid )
176            },
177            q{
178            delete from accreq_attributes_list
179            }
180        ],
181    },
182    {
183        ver => 7,
184        sql => [
185            q{
186            ALTER TABLE request ADD COLUMN automated boolean NOT NULL DEFAULT false;
187            },
188            q{
189            ALTER TABLE request ADD COLUMN objrev bigint;
190            },
191            q{
192            ALTER TABLE aliases ADD COLUMN description text;
193            },
194            q{
195            ALTER TABLE revaliases ADD COLUMN description text;
196            },
197            q{
198            CREATE OR REPLACE FUNCTION group_sort_fields()
199              RETURNS trigger AS
200              $BODY$BEGIN
201
202              IF (TG_OP='INSERT') then
203              IF (new.attr='managedBy'
204                  OR  new.attr='managedAlsoBy'
205                  OR  new.attr='member'
206                  OR  new.attr='memberUID') THEN
207              insert into group_attributes_users VALUES (new.*);
208              RETURN NULL;
209              END IF;
210
211              IF (new.attr='sutype') THEN
212              insert into group_attributes_sutypes VALUES (new.*);
213              RETURN NULL;
214              END IF;
215              end if;
216
217
218              IF (TG_OP = 'UPDATE') THEN
219              IF (new.attr='gidNumber') then
220              update "group" set gidnumber = new.value::integer where
221              "group".ikey = new.okey;
222              RETURN NULL;
223              END IF;
224              END IF;
225
226              IF (TG_OP = 'DELETE') THEN
227              IF (old.attr='exported') then
228              update "group" set exported = false where "group".ikey = old.okey;
229              return null;
230              end if;
231              else
232              IF (new.attr='exported') then
233              update "group" set exported = true where "group".ikey = new.okey;
234              RETURN NULL;
235              end if;
236              END IF;
237
238              if (TG_OP='DELETE') THEN
239              RETURN old;
240              else
241              RETURN new;
242              end if;
243              END;$BODY$
244                LANGUAGE plpgsql VOLATILE
245                  COST 100;
246            },
247        ],
248    },
249    {
250        ver => 8,
251        sql => [
252            q{
253            CREATE TABLE objectslogs
254            (
255              logkey SERIAL NOT NULL,
256              ikey bigint NOT NULL,
257              irev bigint,
258              otype text NOT NULL,
259              name text NOT NULL,
260              changetype text NOT NULL,
261              username text NOT NULL,
262              message text NOT NULL,
263              logdate timestamp with time zone NOT NULL DEFAULT now(),
264              CONSTRAINT objectlogs_pkey PRIMARY KEY (logkey)
265            );},
266            q{
267            CREATE INDEX objectlogs_name_idx
268              ON objectslogs
269              USING btree
270              (name);
271            },
272            q{
273            CREATE INDEX objectslogs_ikey_idx
274              ON objectslogs
275              USING btree
276              (ikey);
277            },
278            q{
279            CREATE INDEX objectslogs_otype_idx
280              ON objectslogs
281              USING btree
282              (otype);
283            }
284        ],
285    },
286    {
287        ver => 9,
288        sql => [
289            q{
290            CREATE TABLE nethost_attributes_nethosts
291            (
292            CONSTRAINT nethost_attributes_nethosts_pkey PRIMARY KEY (attr_key),
293            CONSTRAINT nethost_attr_nethosts_fkey FOREIGN KEY (okey)
294            REFERENCES nethost (ikey) MATCH SIMPLE
295            ON UPDATE CASCADE ON DELETE CASCADE,
296            CONSTRAINT nethost_attr_nethosts_nethosts FOREIGN KEY ("value")
297            REFERENCES nethost (name) MATCH SIMPLE
298            ON UPDATE CASCADE ON DELETE CASCADE
299            )
300            INHERITS (nethost_attributes);
301
302            CREATE INDEX fki_nethost_attr_nethosts_fkey
303            ON nethost_attributes_nethosts
304            USING btree
305            (okey);
306
307            CREATE TRIGGER nethost_attr_nethosts_update
308            AFTER INSERT OR UPDATE OR DELETE
309            ON nethost_attributes_nethosts
310            FOR EACH ROW
311            EXECUTE PROCEDURE nethost_attr_update_ref();
312
313
314            CREATE OR REPLACE FUNCTION nethost_sort_fields()
315              RETURNS trigger AS
316              $BODY$BEGIN
317
318              IF (TG_OP='INSERT') then
319              IF (new.attr='ip') THEN
320              insert into nethost_attributes_ips VALUES (new.*);
321              RETURN NULL;
322              END IF;
323
324              IF (new.attr='macaddr') THEN
325              insert into nethost_attributes_macs VALUES (new.*);
326              RETURN NULL;
327              END IF;
328
329              IF (new.attr='owner') THEN
330              insert into nethost_attributes_users VALUES (new.*);
331              RETURN NULL;
332              END IF;
333
334              IF (new.attr='user') THEN
335              insert into nethost_attributes_users VALUES (new.*);
336              RETURN NULL;
337              END IF;
338
339              IF (new.attr='related') THEN
340              insert into nethost_attributes_nethosts VALUES (new.*);
341              RETURN NULL;
342              END IF;
343              end if;
344
345              if (TG_OP='DELETE') THEN
346              RETURN old;
347              else
348              RETURN new;
349              end if;
350              END;$BODY$
351              LANGUAGE plpgsql VOLATILE
352              COST 100;
353
354            }
355        ],
356    },
357    {
358        ver => 10,
359        sql => [
360            q{
361            CREATE OR REPLACE FUNCTION service_attr_update_ref()
362            RETURNS trigger AS
363            $BODY$begin
364
365            IF (TG_OP != 'INSERT') then
366            update "service" set date = now() where "service".ikey = old.okey;
367            end if;
368            IF (TG_OP != 'DELETE') then
369            update "service"  set date = now() where "service".ikey = new.okey;
370            end if;
371
372            IF (TG_OP = 'DELETE') then
373            return old;
374            ELSE
375            return new;
376            END IF;
377
378            END;$BODY$
379            LANGUAGE plpgsql VOLATILE
380            COST 100;
381            },
382            q{
383
384            CREATE TABLE service
385            (
386            "start" date,
387            "end" date,
388            CONSTRAINT service_pkey PRIMARY KEY (name),
389            CONSTRAINT service_ikey_uniq UNIQUE (ikey)
390            )
391            INHERITS (objects);
392            },
393            q{
394            CREATE TABLE service_attributes_list
395            (
396            ikey integer NOT NULL DEFAULT nextval('ikey_seq'::regclass),
397            canonical text NOT NULL,
398            description text,
399            CONSTRAINT service_attributes_list_pkey PRIMARY KEY (ikey),
400            CONSTRAINT g_attr_l_service_uniq UNIQUE (canonical)
401            )
402            INHERITS (revisions, attributes_list)
403            WITH (
404            OIDS=FALSE
405            );
406            ALTER TABLE service_attributes_list
407            OWNER TO latmos;
408
409            CREATE TABLE service_attributes
410            (
411            CONSTRAINT service_attributes_pkey PRIMARY KEY (attr_key),
412            CONSTRAINT service_attr_users_okey_fkey FOREIGN KEY (okey)
413            REFERENCES service (ikey) MATCH SIMPLE
414            ON UPDATE CASCADE ON DELETE CASCADE,
415            CONSTRAINT service_attributes_attr_fkey FOREIGN KEY (attr)
416            REFERENCES service_attributes_list (canonical) MATCH SIMPLE
417            ON UPDATE CASCADE ON DELETE NO ACTION
418            )
419            INHERITS (attributes)
420            WITH (
421            OIDS=FALSE
422            );
423            ALTER TABLE service_attributes
424            OWNER TO latmos;
425
426            CREATE INDEX fki_service_attributes_attr_fkey
427            ON nethost_attributes
428            USING btree
429            (attr);
430
431            CREATE INDEX service_attr_value_idx
432            ON nethost_attributes
433            USING btree
434            (value);
435
436            CREATE TRIGGER serivce_attr_update
437            AFTER INSERT OR UPDATE OR DELETE
438            ON service_attributes
439            FOR EACH ROW
440            EXECUTE PROCEDURE service_attr_update_ref();
441            },
442            q{
443            CREATE TABLE service_attributes_users
444            (
445            CONSTRAINT service_attributes_user_pkey PRIMARY KEY (attr_key),
446            CONSTRAINT service_attr_users_okey_fkey FOREIGN KEY (okey)
447            REFERENCES service (ikey) MATCH SIMPLE
448            ON UPDATE CASCADE ON DELETE CASCADE,
449            CONSTRAINT service_attributes_users_attr_fkey FOREIGN KEY (attr)
450            REFERENCES service_attributes_list (canonical) MATCH SIMPLE
451            ON UPDATE CASCADE ON DELETE NO ACTION,
452            CONSTRAINT service_attributes_users_user_fkey FOREIGN KEY (value)
453            REFERENCES "user" (name) MATCH SIMPLE
454            ON UPDATE CASCADE ON DELETE CASCADE,
455            CONSTRAINT service_attributes_users_uniq UNIQUE (okey, attr, value)
456            )
457            INHERITS (service_attributes);
458
459            CREATE INDEX fki_service_attr_users_okey_fkey
460            ON service_attributes_users
461            USING btree
462            (okey);
463
464            CREATE INDEX fki_service_attributes_users_attr_fkey
465            ON service_attributes_users
466            USING btree
467            (attr);
468
469            CREATE INDEX fki_service_attributes_users_user_fkey
470            ON service_attributes_users
471            USING btree
472            (value);
473
474            CREATE TRIGGER service_attributes_users_update_ref
475            AFTER INSERT OR UPDATE OR DELETE
476            ON service_attributes_users
477            FOR EACH ROW
478            EXECUTE PROCEDURE service_attr_update_ref();
479
480            CREATE OR REPLACE FUNCTION service_sort_fields()
481              RETURNS trigger AS
482              $BODY$BEGIN
483
484              if (TG_OP='INSERT' or TG_OP='UPDATE') THEN
485              IF (new.attr='manager') THEN
486              insert into service_attributes_users VALUES (new.*);
487              RETURN NULL;
488              END IF;
489              END IF;
490
491              if (TG_OP='DELETE') THEN
492              RETURN old;
493              else
494              RETURN new;
495              end if;
496              END;$BODY$
497              LANGUAGE plpgsql VOLATILE
498              COST 100;
499
500              CREATE TRIGGER service_sort_field_tg
501              BEFORE INSERT OR UPDATE OR DELETE
502              ON service_attributes
503              FOR EACH ROW
504              EXECUTE PROCEDURE service_sort_fields();
505
506            CREATE TRIGGER service_rev_tg
507            BEFORE INSERT OR UPDATE OR DELETE
508            ON service
509            FOR EACH ROW
510            EXECUTE PROCEDURE rev_tg_f();
511            },
512        ],
513    },
514    {
515        ver => 11,
516        sql => [
517            q{
518            ALTER TABLE "user" ADD COLUMN endcircuit timestamp with time zone
519            }
520        ],
521    },
522    {
523        ver => 12,
524        sql => [
525            q{
526            CREATE OR REPLACE VIEW user_attributes AS
527            (        (        (        (        (        (        (        (        (        (        (
528            SELECT "user".uidnumber::text AS value, 'uidnumber' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user"
529            UNION ALL
530            SELECT "user".gidnumber::text AS value, 'gidnumber' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user")
531            UNION ALL
532            SELECT "user".name AS value, 'name' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user")
533            UNION ALL
534            SELECT "user".expire::text AS value, 'expire' AS attr, "user".rev AS attr_key, "user".ikey AS okey FROM "user"
535            WHERE "user".expire IS NOT NULL)
536            UNION ALL
537            SELECT '1'::text AS value, 'exported' AS attr, "user".rev AS attr_key, "user".ikey AS okey
538            FROM "user"
539            WHERE "user".exported = true)
540            UNION ALL
541            SELECT address_attributes_site.value, 'allsite' AS attr, "user".rev AS attr_key, "user".ikey AS okey
542            FROM "user"
543            JOIN address ON address."user" = "user".name
544            JOIN address_attributes_site ON address_attributes_site.okey = address.ikey
545            WHERE address_attributes_site.attr = 'site'::text AND address.exported = true)
546            UNION ALL
547            SELECT "group".name AS value, 'memberOf' AS attr, "user".rev AS attr_key, "user".ikey AS okey
548            FROM "user"
549            JOIN group_attributes ON group_attributes.value = "user".name
550            JOIN "group" ON group_attributes.okey = "group".ikey
551            WHERE group_attributes.attr = 'memberUID'::text)
552            UNION ALL
553            SELECT user_attributes.value, user_attributes.attr, user_attributes.attr_key, user_attributes.okey
554            FROM user_attributes_base user_attributes)
555            UNION ALL
556            SELECT "group".name AS value, 'departments' AS attr, "user".rev AS attr_key, "user".ikey AS okey
557            FROM "group"
558            JOIN group_attributes_sutypes ON "group".ikey = group_attributes_sutypes.okey
559            JOIN group_attributes_users ON "group".ikey = group_attributes_users.okey AND group_attributes_users.attr = 'memberUID'::text
560            JOIN "user" ON "user".name = group_attributes_users.value
561            WHERE group_attributes_sutypes.value = 'dpmt'::text AND group_attributes_sutypes.attr = 'sutype'::text)
562            UNION ALL
563            SELECT "group".name AS value, 'cells' AS attr, "user".rev AS attr_key, "user".ikey AS okey
564            FROM "group"
565            JOIN group_attributes_sutypes ON "group".ikey = group_attributes_sutypes.okey
566            JOIN group_attributes_users ON "group".ikey = group_attributes_users.okey AND group_attributes_users.attr = 'memberUID'::text
567            JOIN "user" ON "user".name = group_attributes_users.value
568            WHERE group_attributes_sutypes.value = 'cell'::text AND group_attributes_sutypes.attr = 'sutype'::text)
569            UNION ALL
570            SELECT "group".name AS value, 'managedObjects' AS attr, "user".rev AS attr_key, "user".ikey AS okey
571            FROM "user"
572            JOIN group_attributes ON group_attributes.value = "user".name
573            JOIN "group" ON group_attributes.okey = "group".ikey
574            WHERE group_attributes.attr = 'managedBy'::text)
575            UNION ALL
576            SELECT justify_interval(now() - "user".expire)::text AS value, 'expired' AS attr, "user".rev AS attr_key, "user".ikey AS okey
577            FROM "user"
578            WHERE "user".expire <= now())
579            UNION ALL
580            SELECT 1::text AS value, 'active' AS attr, "user".rev AS attr_key, "user".ikey AS okey
581            FROM "user"
582            WHERE ("user".expire IS NULL OR "user".expire >= now()) AND "user".exported = true
583            UNION ALL
584            SELECT 0::text AS value, 'active' AS attr, "user".rev AS attr_key, "user".ikey AS okey
585            FROM "user"
586            WHERE ("user".expire IS NOT NULL and "user".expire <= now()) or "user".exported = false;
587            },
588            q{
589            CREATE OR REPLACE FUNCTION rev_tg_aliases_f()
590            RETURNS trigger AS
591            $BODY$begin
592
593            IF (TG_OP = 'DELETE') THEN
594            update "user" set rev = nextval('revisions_rev_seq'::regclass), "date" = now() where "name" = ANY (old.forward);
595            return old;
596            ELSE
597                IF (TG_OP = 'UPDATE') THEN
598                update "user" set rev = nextval('revisions_rev_seq'::regclass), "date" = now() where "name" = ANY (old.forward);
599                END IF;
600            update "user" set rev = nextval('revisions_rev_seq'::regclass), "date" = now() where "name" = ANY (new.forward);
601            return new;
602            END IF;
603
604            end;$BODY$
605            LANGUAGE plpgsql VOLATILE
606            COST 100;
607
608            CREATE TRIGGER aliases_user_tg
609            AFTER INSERT OR UPDATE OR DELETE
610            ON aliases
611            FOR EACH ROW
612            EXECUTE PROCEDURE rev_tg_aliases_f();
613            },
614        ],
615    },
616    {
617        ver => 13,
618        sql => [
619            q{
620            CREATE TABLE "stat"
621            (
622            name text NOT NULL,
623            CONSTRAINT stat_pkey PRIMARY KEY (name),
624            CONSTRAINT stat_okey_uniq UNIQUE (ikey)
625            )
626            INHERITS (objects);
627            CREATE INDEX stat_exported_idx
628            ON stat USING btree (exported);
629            CREATE UNIQUE INDEX stat_rev_idx
630            ON stat USING btree (rev);
631
632            CREATE OR REPLACE FUNCTION stat_attr_update_ref()
633            RETURNS trigger AS
634            $BODY$begin
635
636            IF (TG_OP != 'INSERT') then
637            update "stat" set date = now() where "stat".ikey = old.okey;
638            end if;
639            IF (TG_OP != 'DELETE') then
640            update "stat"  set date = now() where "stat".ikey = new.okey;
641            end if;
642
643            IF (TG_OP = 'DELETE') then
644            return old;
645            ELSE
646            return new;
647            END IF;
648
649            END;$BODY$
650            LANGUAGE plpgsql VOLATILE
651            COST 100;
652            },
653            q{
654            CREATE TABLE stat_attributes
655            (
656            CONSTRAINT stat_attributes_pkey PRIMARY KEY (attr_key),
657            CONSTRAINT stat FOREIGN KEY (okey)
658            REFERENCES stat (ikey) MATCH SIMPLE
659            ON UPDATE CASCADE ON DELETE CASCADE
660            )
661            INHERITS (attributes);
662            CREATE INDEX stat_attributes_attr_fkey
663            ON stat_attributes
664            USING btree
665            (attr);
666            CREATE INDEX stat_attr_value_idx
667            ON stat_attributes
668            USING btree
669            (value);
670            CREATE TRIGGER stat_attr_update
671            AFTER INSERT OR UPDATE OR DELETE
672            ON stat_attributes
673            FOR EACH ROW
674            EXECUTE PROCEDURE stat_attr_update_ref();
675            },
676            q{
677            CREATE TABLE stat_attributes_list
678            (
679            CONSTRAINT stat_attr_list_pkey PRIMARY KEY (ikey),
680            CONSTRAINT stat_attr_l_c_uniq UNIQUE (canonical)
681            )
682            INHERITS (revisions, attributes_list);
683            },
684            q{
685            CREATE TABLE statsentry
686            (
687            okey integer NOT NULL,
688            id bigint NOT NULL DEFAULT nextval('revisions_rev_seq'::regclass),
689            tstamp timestamp with time zone NOT NULL DEFAULT now(),
690            CONSTRAINT stat FOREIGN KEY (okey)
691            REFERENCES stat (ikey) MATCH SIMPLE
692            ON UPDATE CASCADE ON DELETE CASCADE,
693            CONSTRAINT statsentry_pkey PRIMARY KEY (id)
694            );
695            CREATE TABLE statvalues
696            (
697            sid bigint NOT NULL,
698            value text NOT NULL,
699            count bigint NOT NULL,
700            CONSTRAINT statvalues_pkey PRIMARY KEY (sid, value),
701            CONSTRAINT statvalues_fkey FOREIGN KEY (sid)
702            REFERENCES statsentry (id) MATCH SIMPLE
703            ON UPDATE CASCADE ON DELETE CASCADE
704            )
705            },
706        ],
707    },
708    {
709        ver => 14,
710        sql => [
711            q{
712            ALTER TABLE objects ADD COLUMN createdby text;
713            },
714            q{
715            ALTER TABLE objects ADD COLUMN modifiedby text;
716            },
717        ],
718    },
719    {
720        ver => 15,
721        sql => [
722            q{
723            CREATE TABLE "employment"
724            (
725            name text NOT NULL,
726            "user" text NOT NULL,
727            firstday date NOT NULL default now(),
728            lastday  date,
729            CONSTRAINT employment_pkey PRIMARY KEY (name),
730            CONSTRAINT employment_okey_uniq UNIQUE (ikey),
731            CONSTRAINT employment_user_fkey FOREIGN KEY ("user")
732                REFERENCES "user" (name) MATCH SIMPLE
733                ON UPDATE CASCADE ON DELETE CASCADE
734            )
735            INHERITS (objects);
736            CREATE INDEX employment_exported_idx
737            ON employment USING btree (exported);
738            CREATE UNIQUE INDEX employment_rev_idx
739            ON employment USING btree (rev);
740
741            CREATE OR REPLACE FUNCTION employment_attr_update_ref()
742            RETURNS trigger AS
743            $BODY$begin
744
745            IF (TG_OP != 'INSERT') then
746            update "employment" set date = now() where "employment".ikey = old.okey;
747            end if;
748            IF (TG_OP != 'DELETE') then
749            update "employment"  set date = now() where "employment".ikey = new.okey;
750            end if;
751
752            IF (TG_OP = 'DELETE') then
753            return old;
754            ELSE
755            return new;
756            END IF;
757
758            END;$BODY$
759            LANGUAGE plpgsql VOLATILE
760            COST 100;
761            },
762            q{
763            CREATE TABLE employment_attributes
764            (
765            CONSTRAINT employment_attributes_pkey PRIMARY KEY (attr_key),
766            CONSTRAINT employment FOREIGN KEY (okey)
767            REFERENCES employment (ikey) MATCH SIMPLE
768            ON UPDATE CASCADE ON DELETE CASCADE
769            )
770            INHERITS (attributes);
771            CREATE INDEX employment_attributes_attr_fkey
772            ON employment_attributes
773            USING btree
774            (attr);
775            CREATE INDEX employment_attr_value_idx
776            ON employment_attributes
777            USING btree
778            (value);
779            CREATE TRIGGER employment_attr_update
780            AFTER INSERT OR UPDATE OR DELETE
781            ON employment_attributes
782            FOR EACH ROW
783            EXECUTE PROCEDURE employment_attr_update_ref();
784            },
785            q{
786            CREATE TABLE employment_attributes_list
787            (
788            CONSTRAINT employment_attr_list_pkey PRIMARY KEY (ikey),
789            CONSTRAINT employment_attr_l_c_uniq UNIQUE (canonical)
790            )
791            INHERITS (revisions, attributes_list);
792            },
793            q{
794            CREATE INDEX employment_firstday_idx
795              ON employment
796                USING btree
797                  (firstday NULLS FIRST);
798            CREATE INDEX employment_lastday_idx
799              ON employment
800                USING btree
801                  (lastday NULLS LAST);
802            },
803        ],
804    },
805    {
806        ver => 16,
807        sql => [
808            q{
809            ALTER TABLE aliases
810              ADD CONSTRAINT aliases_ikey_uniq UNIQUE(ikey);
811            CREATE OR REPLACE FUNCTION aliases_attr_update_ref()
812            RETURNS trigger AS
813            $BODY$begin
814
815            IF (TG_OP != 'INSERT') then
816            update "aliases" set date = now() where "aliases".ikey = old.okey;
817            end if;
818            IF (TG_OP != 'DELETE') then
819            update "aliases"  set date = now() where "aliases".ikey = new.okey;
820            end if;
821
822            IF (TG_OP = 'DELETE') then
823            return old;
824            ELSE
825            return new;
826            END IF;
827
828            END;$BODY$
829            LANGUAGE plpgsql VOLATILE
830            COST 100;
831            },
832            q{
833            CREATE TABLE aliases_attributes_base
834            (
835            CONSTRAINT aliases_attributes_base_pkey PRIMARY KEY (attr_key),
836            CONSTRAINT aliases_fkey FOREIGN KEY (okey)
837            REFERENCES aliases (ikey) MATCH SIMPLE
838            ON UPDATE CASCADE ON DELETE CASCADE
839            )
840            INHERITS (attributes);
841            CREATE INDEX aliases_attributes_base_attr_fkey
842            ON aliases_attributes_base
843            USING btree
844            (attr);
845            CREATE INDEX aliases_attr_value_idx
846            ON aliases_attributes_base
847            USING btree
848            (value);
849            CREATE TRIGGER aliases_attr_update
850            AFTER INSERT OR UPDATE OR DELETE
851            ON aliases_attributes_base
852            FOR EACH ROW
853            EXECUTE PROCEDURE aliases_attr_update_ref();
854            },
855            q{
856            CREATE OR REPLACE VIEW aliases_attributes AS
857            SELECT "user".name AS value,
858            'user'::text AS attr,
859            aliases.rev AS attr_key,
860            aliases.ikey AS okey
861            FROM aliases
862            JOIN "user" ON aliases.name = "user".name OR aliases.forward = ARRAY["user".name]
863            union all
864               select value, attr, attr_key, okey from aliases_attributes_base
865            UNION ALL
866                SELECT "aliases".name AS value,
867                'name'::text AS attr,
868                "aliases".rev AS attr_key,
869                "aliases".ikey AS okey
870                FROM "aliases";
871
872           CREATE OR REPLACE RULE aliases_attributes_insert AS
873           ON INSERT TO aliases_attributes DO INSTEAD  INSERT INTO aliases_attributes_base (value, attr, okey)
874           VALUES (new.value, new.attr, new.okey);
875
876           CREATE OR REPLACE RULE aliases_attributes_update AS
877           ON UPDATE TO aliases_attributes DO INSTEAD  UPDATE aliases_attributes_base SET value = new.value, attr = new.attr, okey = new.okey
878           WHERE aliases_attributes_base.attr_key = old.attr_key AND aliases_attributes_base.attr = old.attr;
879
880           CREATE OR REPLACE RULE aliases_atttributes_delete AS
881           ON DELETE TO aliases_attributes DO INSTEAD  DELETE FROM aliases_attributes_base
882           WHERE aliases_attributes_base.attr_key = old.attr_key AND aliases_attributes_base.attr = old.attr;
883            }
884
885        ],
886    },
887    {
888        ver => 17,
889        sql => [
890            q{
891            CREATE TABLE passwordreset
892            (
893            -- Hérité(e) from table revisions:  rev integer NOT NULL DEFAULT nextval('revisions_rev_seq'::regclass),
894            -- Hérité(e) from table revisions:  date timestamp with time zone NOT NULL DEFAULT now(),
895            -- Hérité(e) from table revisions:  "create" timestamp with time zone NOT NULL DEFAULT now(),
896            -- Hérité(e) from table revisions:  ikey integer NOT NULL DEFAULT nextval('ikey_seq'::regclass),
897            "user" text NOT NULL,
898            id text NOT NULL,
899            CONSTRAINT passwordreset_pkey PRIMARY KEY (id),
900            CONSTRAINT password_reset_user_fkey FOREIGN KEY ("user")
901            REFERENCES "user" (name) MATCH SIMPLE
902            ON UPDATE CASCADE ON DELETE CASCADE
903            )
904            INHERITS (revisions)
905            WITH (
906            OIDS=FALSE
907            );
908            },
909        ],
910    },
911    {
912        ver => 18,
913        sql => [
914            q{
915            ALTER TABLE employment
916            ADD CHECK (lastday is null or firstday <= lastday);
917            }
918        ],
919    },
920    {
921        ver => 19,
922        sql => [
923            q{
924            ALTER TABLE "nethost" ADD COLUMN expire timestamp with time zone;
925            }
926        ],
927    },
928    {
929        ver => 20,
930        sql => [
931            q{
932            CREATE OR REPLACE VIEW user_attributes AS
933                SELECT "user".uidnumber::text AS value, 'uidnumber' AS attr, "user".rev AS attr_key, "user".ikey AS okey
934                FROM "user"
935            UNION ALL
936                SELECT "user".gidnumber::text AS value, 'gidnumber' AS attr, "user".rev AS attr_key, "user".ikey AS okey
937                FROM "user"
938            UNION ALL
939                SELECT "user".name AS value, 'name' AS attr, "user".rev AS attr_key, "user".ikey AS okey
940                FROM "user"
941            UNION ALL
942                SELECT "user".expire::text AS value, 'expire' AS attr, "user".rev AS attr_key, "user".ikey AS okey
943                FROM "user"
944                WHERE "user".expire IS NOT NULL
945            UNION ALL
946                SELECT '1'::text AS value, 'exported' AS attr, "user".rev AS attr_key, "user".ikey AS okey
947                FROM "user"
948                WHERE "user".exported = true
949            UNION ALL
950                SELECT address_attributes_site.value, 'allsite' AS attr, "user".rev AS attr_key, "user".ikey AS okey
951                FROM "user"
952                JOIN address ON address."user" = "user".name
953                JOIN address_attributes_site ON address_attributes_site.okey = address.ikey
954                WHERE address_attributes_site.attr = 'site'::text AND address.exported = true
955            UNION ALL
956                SELECT "group".name AS value, 'memberOf' AS attr, "user".rev AS attr_key, "user".ikey AS okey
957                FROM "user"
958                JOIN group_attributes ON group_attributes.value = "user".name
959                JOIN "group" ON group_attributes.okey = "group".ikey
960                WHERE group_attributes.attr = 'memberUID'::text
961            UNION ALL
962                SELECT user_attributes.value, user_attributes.attr, user_attributes.attr_key, user_attributes.okey
963                FROM user_attributes_base user_attributes
964            UNION ALL
965                SELECT "group".name AS value, 'departments' AS attr, "user".rev AS attr_key, "user".ikey AS okey
966                FROM "group"
967                JOIN group_attributes_sutypes ON "group".ikey = group_attributes_sutypes.okey
968                JOIN group_attributes_users ON "group".ikey = group_attributes_users.okey AND group_attributes_users.attr = 'memberUID'::text
969                JOIN "user" ON "user".name = group_attributes_users.value
970                WHERE group_attributes_sutypes.value = 'dpmt'::text AND group_attributes_sutypes.attr = 'sutype'::text
971            UNION ALL
972                SELECT "group".name AS value, 'cells' AS attr, "user".rev AS attr_key, "user".ikey AS okey
973                FROM "group"
974                JOIN group_attributes_sutypes ON "group".ikey = group_attributes_sutypes.okey
975                JOIN group_attributes_users ON "group".ikey = group_attributes_users.okey AND group_attributes_users.attr = 'memberUID'::text
976                JOIN "user" ON "user".name = group_attributes_users.value
977                WHERE group_attributes_sutypes.value = 'cell'::text AND group_attributes_sutypes.attr = 'sutype'::text
978            UNION ALL
979                SELECT "group".name AS value, 'managedObjects' AS attr, "user".rev AS attr_key, "user".ikey AS okey
980                FROM "user"
981                JOIN group_attributes ON group_attributes.value = "user".name
982                JOIN "group" ON group_attributes.okey = "group".ikey
983                WHERE group_attributes.attr = 'managedBy'::text
984            UNION ALL
985                SELECT justify_interval(now() - "user".expire)::text AS value, 'expired' AS attr, "user".rev AS attr_key, "user".ikey AS okey
986                FROM "user"
987                WHERE "user".expire <= now()
988            UNION ALL
989                SELECT 1::text AS value, 'active' AS attr, "user".rev AS attr_key, "user".ikey AS okey
990                FROM "user"
991                WHERE ("user".expire IS NULL OR "user".expire >= now()) AND "user".exported = true
992            UNION ALL
993                SELECT 0::text AS value, 'active' AS attr, "user".rev AS attr_key, "user".ikey AS okey
994                FROM "user"
995                WHERE "user".expire IS NOT NULL AND "user".expire <= now() OR "user".exported = false
996            UNION ALL
997                SELECT CASE WHEN "user".exported = false THEN 'unexported'
998                WHEN "user".expire IS NOT NULL AND "user".expire <= now() THEN 'expired'
999                ELSE 'active' END AS value, 'status' AS attr, "user".rev AS attr_key, "user".ikey AS okey
1000                FROM "user"
1001            ;
1002
1003            }
1004        ],
1005    },
1006    {
1007        ver => 21,
1008        sql => [
1009            'ALTER TABLE objects ADD COLUMN oalias text',
1010            'ALTER TABLE objects
1011               ADD COLUMN nodelete boolean NOT NULL DEFAULT false',
1012            'ALTER TABLE objects
1013               ADD COLUMN internobject boolean NOT NULL DEFAULT false',
1014        ],
1015    },
1016    {
1017        ver => 22,
1018        sql => [
1019            'CREATE INDEX fki_employment
1020            ON employment_attributes
1021            USING btree (okey);'
1022        ],
1023    },
1024    {
1025        ver => 23,
1026        sql => [
1027            'ALTER TABLE address ADD COLUMN expire timestamp with time zone'
1028        ],
1029    },
1030    {
1031        ver => 24,
1032        sql => [
1033            q{
1034            CREATE OR REPLACE FUNCTION user_sort_fields()
1035            RETURNS trigger AS
1036            $BODY$DECLARE
1037            rec RECORD;
1038            BEGIN
1039
1040            IF (TG_OP='UPDATE' or TG_OP='INSERT') THEN
1041
1042            IF (new.attr='locked') THEN
1043            IF (TG_OP = 'INSERT') THEN
1044            new.value = now()::text;
1045            ELSIF (TG_OP='UPDATE') THEN
1046            new.value = old.value;
1047            END IF;
1048            END IF;
1049
1050            IF (new.attr='nickname') THEN
1051            PERFORM 1 from "user" where "user".ikey = new.okey
1052                and new.value = "user".name;
1053            IF NOT FOUND THEN
1054            select aliases.name into rec from aliases join "user"
1055            on array["user".name] = aliases.forward
1056            where "user".ikey = new.okey and aliases.name = new.value;
1057            IF NOT FOUND THEN
1058            insert into aliases ("name", "forward", "description", exported)
1059            select new.value, array["user".name], 'Forward for ' || "user".name || ' nickname', "user".exported from "user" where "user".ikey = new.okey;
1060            END IF;
1061            END IF;
1062            END IF;
1063
1064            IF (new.attr='uidNumber') THEN
1065            update "user" set uidnumber = new.value::integer where ikey = new.okey;
1066            RETURN NULL;
1067            END IF;
1068
1069            IF (new.attr='gidNumber') THEN
1070            update "user" set gidnumber = new.value::integer where ikey = new.okey;
1071            RETURN null;
1072            END IF;
1073
1074            IF (new.attr='expire') THEN
1075            update "user" set expire = new.value::timestamp where ikey = new.okey;
1076            RETURN NULL;
1077            END IF;
1078
1079            IF (new.attr='exported') THEN
1080            update "user" set exported = true where ikey = new.okey;
1081            RETURN NULL;
1082            END IF;
1083
1084            END IF;
1085
1086            IF (TG_OP = 'DELETE') THEN
1087
1088            IF (old.attr='expire') THEN
1089            update "user" set expire = NULL where ikey = old.okey;
1090            RETURN NULL;
1091            END IF;
1092
1093            IF (old.attr='exported') THEN
1094            update "user" set exported = false where ikey = old.okey;
1095            RETURN NULL;
1096            END IF;
1097
1098            END IF;
1099
1100
1101            IF (TG_OP='INSERT') THEN
1102            IF (new.attr='manager') THEN
1103            insert into user_attributes_users VALUES (new.*);
1104            RETURN NULL;
1105            END IF;
1106
1107            IF (new.attr='site') THEN
1108            insert into user_attributes_site VALUES (new.*);
1109            RETURN NULL;
1110            END IF;
1111
1112            IF (new.attr='department') THEN
1113            insert into user_attributes_groups VALUES (new.*);
1114            RETURN NULL;
1115            END IF;
1116
1117            IF (new.attr='contratType') THEN
1118            insert into user_attributes_groups VALUES (new.*);
1119            RETURN NULL;
1120            END IF;
1121
1122            IF (new.attr='jobType') THEN
1123            insert into user_attributes_groups VALUES (new.*);
1124            RETURN NULL;
1125            END IF;
1126
1127            END IF;
1128
1129            IF (TG_OP='DELETE') then
1130            RETURN old;
1131            ELSE
1132            RETURN new;
1133            end if;
1134            END;$BODY$
1135            LANGUAGE plpgsql VOLATILE
1136            COST 100;
1137            },
1138        ],
1139    },
1140    {
1141        ver => 25,
1142        sql => [
1143            'ALTER TABLE objects ADD COLUMN oaliascache text',
1144        ],
1145    },
1146);
1147
1148my @objects = (
1149    {
1150        name => 'dpmt',
1151        otype => 'sutype',
1152        attrs => {
1153            description => 'Department',
1154        },
1155    },
1156    {
1157        name => 'contrattype',
1158        otype => 'sutype',
1159        attrs => {
1160            description => 'Contract',
1161        },
1162    },
1163    {
1164        name => '-useralias',
1165        otype => 'group',
1166        attrs => {
1167            description => 'Internal group for user alias object',
1168            gidnumber => -1,
1169            unexported => 1,
1170        },
1171        intern => 1,
1172    },
1173);
1174
1175$dbi->rollback;
1176
1177foreach my $maj (@updates) {
1178    if ($rev >= $maj->{ver}) {
1179        next;
1180    }
1181    print "\n";
1182    print 'Switching to schema revision: ' . $maj->{ver} . "\n";
1183    foreach my $sql (@{ $maj->{sql} }) {
1184        {
1185            my $sqlv = $sql;
1186            $sqlv =~ s/^/  /mg;
1187            if ($verbose) {
1188                warn '  >' . $sqlv . "\n";
1189            } else {
1190                print 'x';
1191            }
1192        }
1193        my $err = $dbi->do($sql);
1194        defined($err) or die "Erreur :\\" . $dbi->errstr . "\n";
1195    }
1196
1197    print "\n";
1198
1199    print 'Updating schema_version to ' . $maj->{ver} . "\n";
1200
1201    $dbi->do(
1202        'UPDATE settings SET val = ? where varname = ?',
1203        undef,
1204        $maj->{ver}, 'schema_version'
1205    );
1206    print "Done\n\n";
1207
1208}
1209
1210my $setnodel  = $dbi->prepare('UPDATE objects SET nodelete     = true where name = ?');
1211my $setintern = $dbi->prepare('UPDATE objects SET internobject = true where name = ?');
1212
1213foreach (@objects) {
1214    if (!$labase->GetRawObject($_->{otype}, $_->{name})) {
1215        printf("Creating object %s/%s\n", $_->{otype}, $_->{name});
1216        $labase->create_object($_->{otype}, $_->{name}, %{$_->{attrs} || {}})
1217            or die sprintf("cannot create %s/%s\n", $_->{otype}, $_->{name});
1218
1219    }
1220
1221    $setnodel->execute($_->{name});
1222    $setintern->execute($_->{name}) if ($_->{intern});
1223}
1224
1225if ($nocommit) {
1226    $dbi->rollback;
1227} else {
1228    $dbi->commit;
1229}
1230print "Process terminated successfully\n";
Note: See TracBrowser for help on using the repository browser.