source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/upgrade.pm @ 2095

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

Typo

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