1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
+
-
-
+
+
-
-
-
-
+
+
+
+
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
+
+
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
CREATE PROCEDURAL LANGUAGE plpgsql;
-- this function adds tag to domain
CREATE FUNCTION mark(domain text, new_tag text) RETURNS void
LANGUAGE plpgsql STRICT
AS $$
LANGUAGE plpgsql STRICT
AS $$
declare
my_site text[];
my_site_id smallint;
my_tag text[];
my_tag_id smallint;
my_site text[];
my_site_id smallint;
my_tag text[];
my_tag_id smallint;
begin
my_site := tripdomain(domain);
my_site := tripdomain(domain);
-- selecting site id from table or adding site to the table
select id_site from site where my_site = site into my_site_id;
if not found then
insert into site (site) values (my_site);
select id_site from site where my_site = site into my_site_id;
end if;
select id_site from site where my_site = site into my_site_id;
if not found then
insert into site (site) values (my_site);
select id_site from site where my_site = site into my_site_id;
end if;
-- selecting tags site already have and adding new tag to them
-- note that tags should be sorted to eliminate permutations
select tag from urls natural join tag where id_site = my_site_id into my_tag;
if not found then
my_tag := array[new_tag];
else
select array_agg(tag) from (select distinct unnest(my_tag || array[new_tag]) as tag order by tag asc) a into
my_tag;
delete from urls where id_site = my_site_id;
end if;
select tag from urls natural join tag where id_site = my_site_id into my_tag;
if not found then
-- no records found - creating new tag
my_tag := array[new_tag];
else
-- joining tags
select array_agg(tag)
from (select distinct unnest(my_tag || array[new_tag]) as tag order by tag asc) a
into my_tag;
-- deleting old site specification
delete from urls where id_site = my_site_id;
end if;
-- selecting new tag id or adding tag to the table
select id_tag from tag where my_tag = tag into my_tag_id;
if not found then
insert into tag (tag) values(my_tag);
select id_tag from tag where my_tag = tag into my_tag_id;
end if;
select id_tag from tag where my_tag = tag into my_tag_id;
if not found then
insert into tag (tag) values(my_tag);
select id_tag from tag where my_tag = tag into my_tag_id;
end if;
-- adding new site specification
insert into urls (id_site, id_tag) values (my_site_id, my_tag_id);
insert into urls (id_site, id_tag) values (my_site_id, my_tag_id);
end;$$;
-- this function adds tag to site by site id
CREATE FUNCTION mark(my_site_id smallint, new_tag text) RETURNS void
LANGUAGE plpgsql STRICT
AS $$
LANGUAGE plpgsql STRICT
AS $$
declare
-- maybe check should be added to make sure supplied site id really exists
my_tag text[];
my_tag_id smallint;
my_tag text[];
my_tag_id smallint;
begin
select tag from urls natural join tag where id_site = my_site_id into my_tag;
if not found then
my_tag := array[new_tag];
else
select array_agg(tag) from (select distinct unnest(my_tag || array[new_tag]) as tag order by tag asc) a into
my_tag;
delete from urls where id_site = my_site_id;
end if;
-- selecting tags site already have and adding new tag to them
-- note that tags should be sorted to eliminate permutations
select tag from urls natural join tag where id_site = my_site_id into my_tag;
if not found then
-- no records found - creating new tag
my_tag := array[new_tag];
else
-- joining tags
select array_agg(tag)
from (select distinct unnest(my_tag || array[new_tag]) as tag order by tag asc) a
into my_tag;
-- deleting old site specification
delete from urls where id_site = my_site_id;
end if;
-- selecting new tag id or adding tag to the table
select id_tag from tag where my_tag = tag into my_tag_id;
if not found then
insert into tag (tag) values(my_tag);
select id_tag from tag where my_tag = tag into my_tag_id;
end if;
select id_tag from tag where my_tag = tag into my_tag_id;
if not found then
insert into tag (tag) values(my_tag);
select id_tag from tag where my_tag = tag into my_tag_id;
end if;
-- adding new site specification
insert into urls (id_site, id_tag) values (my_site_id, my_tag_id);
insert into urls (id_site, id_tag) values (my_site_id, my_tag_id);
end;$$;
-- transforms domain into ordered array for indexing
CREATE FUNCTION tripdomain(url text) RETURNS text[]
LANGUAGE plpgsql IMMUTABLE STRICT
AS $_$
LANGUAGE plpgsql IMMUTABLE STRICT
AS $_$
declare
result varchar[];
splitted varchar[];
result text[];
splitted text[];
reversed varchar[];
x integer;
x integer;
length integer;
begin
x := 1;
splitted := string_to_array($1, '.');
loop
exit when splitted[x] is null;
splitted := string_to_array($1, '.');
length := array_length(splitted, 1);
x := 1;
loop
exit when splitted[x] is null;
if length(splitted[x]) > 0 then
reversed := splitted[x] || reversed;
result[x] := splitted[x] || ':' || length - x;
end if;
x := x + 1;
end loop;
x := 1;
loop
exit when reversed[x] is null;
result[x] := reversed[x] || ':' || x;
x := x + 1;
end loop;
return result;
x := x + 1;
end loop;
return result;
end;$_$;
-- transforms ordered array into domain
create function untrip(site text[]) returns text
language plpgsql immutable strict
as $_$
declare
x integer;
splitted text[];
pair text[];
begin
x := array_length(site, 1);
loop
exit when site[x] is null;
pair := string_to_array(site[x], ':');
splitted[0 - pair[2]::integer] := pair[1];
x := x - 1;
end loop;
return array_to_string(splitted, '.');
end;
$_$;
-- table to hold all rules
CREATE TABLE rules (
netmask cidr NOT NULL,
redirect_url text DEFAULT 'about::blank'::text NOT NULL,
from_weekday smallint DEFAULT 0 NOT NULL,
to_weekday smallint DEFAULT 6 NOT NULL,
from_time time without time zone DEFAULT '00:00:00'::time without time zone NOT NULL,
to_time time without time zone DEFAULT '23:59:59'::time without time zone NOT NULL,
id_tag smallint NOT NULL
netmask cidr NOT NULL,
redirect_url text DEFAULT 'about::blank'::text NOT NULL,
from_weekday smallint DEFAULT 0 NOT NULL,
to_weekday smallint DEFAULT 6 NOT NULL,
from_time time without time zone DEFAULT '00:00:00'::time without time zone NOT NULL,
to_time time without time zone DEFAULT '23:59:59'::time without time zone NOT NULL,
id_tag smallint NOT NULL
);
ALTER TABLE ONLY rules
ADD CONSTRAINT rules_pkey PRIMARY KEY (netmask);
-- table to hold site arrays
-- maybe full original domain should be added with trigger to leave tripdomain function away
CREATE TABLE site (
id_site serial,
site text[] NOT NULL
id_site serial,
site text[] NOT NULL,
);
domain not null
CREATE TABLE tag (
id_tag serial,
tag text[] NOT NULL
);
CREATE TABLE urls (
date_added timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL,
id_site smallint NOT NULL,
id_tag smallint NOT NULL
);
CREATE VIEW site_rule AS
SELECT a.redirect_url, a.netmask, b.site FROM ((SELECT rules.redirect_url, tag.tag AS rule_tag, rules.netmask FROM (rules NATURAL JOIN tag) WHERE ((((('now'::text)::time without time zone >= rules.from_time) AND (('now'::text)::time without time zone <= rules.to_time)) AND (date_part('dow'::text, now()) >= (rules.from_weekday)::double precision)) AND (date_part('dow'::text, now()) <= (rules.to_weekday)::double precision))) a JOIN (SELECT site.site, tag.tag AS url_tag FROM ((urls NATURAL JOIN tag) NATURAL JOIN site)) b ON ((b.url_tag && a.rule_tag)));
ALTER TABLE ONLY rules
ADD CONSTRAINT rules_pkey PRIMARY KEY (netmask);
ALTER TABLE ONLY site
ADD CONSTRAINT site_id PRIMARY KEY (id_site);
ADD CONSTRAINT site_id PRIMARY KEY (id_site);
ALTER TABLE ONLY tag
ADD CONSTRAINT tag_id PRIMARY KEY (id_tag);
ALTER TABLE ONLY urls
ADD CONSTRAINT urls_pkey PRIMARY KEY (date_added);
CREATE UNIQUE INDEX site_s ON site USING btree (site);
CREATE INDEX site_sg ON site USING gin (site);
-- table to hold tag combinations
CREATE TABLE tag (
id_tag serial,
tag text[] NOT NULL
);
ALTER TABLE ONLY tag
ADD CONSTRAINT tag_id PRIMARY KEY (id_tag);
CREATE INDEX tag_g ON tag USING gin (tag);
CREATE UNIQUE INDEX tag_s ON tag USING btree (tag);
-- table to hold tag - site links
CREATE TABLE urls (
date_added timestamp without time zone DEFAULT ('now'::text)::timestamp(0) without time zone NOT NULL,
id_site smallint NOT NULL,
id_tag smallint NOT NULL
);
ALTER TABLE ONLY urls
ADD CONSTRAINT urls_pkey PRIMARY KEY (date_added);
CREATE UNIQUE INDEX urls_id_site ON urls USING btree (id_site);
-- rule to join all tables into one to simplify access
-- automaticall uses current day and time data
CREATE VIEW site_rule AS
SELECT a.redirect_url, a.netmask, b.site
FROM ((
SELECT rules.redirect_url, tag.tag AS rule_tag, rules.netmask
FROM (rules NATURAL JOIN tag)
WHERE ((((('now'::text)::time without time zone >= rules.from_time)
AND (('now'::text)::time without time zone <= rules.to_time))
AND (date_part('dow'::text, now()) >= (rules.from_weekday)::double precision))
AND (date_part('dow'::text, now()) <= (rules.to_weekday)::double precision))
) a JOIN (
SELECT site.site, tag.tag AS url_tag
FROM ((urls NATURAL JOIN tag) NATURAL JOIN site)
) b ON ((b.url_tag && a.rule_tag)));
|