Artifact
f3002f17d4b0807088c298e6b1b1ccb9587311c3f5b5d76c6a0fc17d3031387d:
0000: 43 52 45 41 54 45 20 54 41 42 4c 45 20 69 66 20 CREATE TABLE if
0010: 6e 6f 74 20 65 78 69 73 74 73 20 63 6f 75 6e 74 not exists count
0020: 65 72 20 28 0a 09 75 69 64 20 74 65 78 74 20 4e er (..uid text N
0030: 4f 54 20 4e 55 4c 4c 2c 0a 09 72 65 66 65 72 65 OT NULL,..refere
0040: 72 20 74 65 78 74 20 44 45 46 41 55 4c 54 20 27 r text DEFAULT '
0050: 2d 27 20 4e 4f 54 20 4e 55 4c 4c 2c 0a 09 69 70 -' NOT NULL,..ip
0060: 20 69 6e 65 74 20 4e 4f 54 20 4e 55 4c 4c 2c 0a inet NOT NULL,.
0070: 09 64 61 79 20 64 61 74 65 20 44 45 46 41 55 4c .day date DEFAUL
0080: 54 20 6e 6f 77 28 29 20 4e 4f 54 20 4e 55 4c 4c T now() NOT NULL
0090: 2c 0a 09 63 6f 75 6e 74 20 69 6e 74 65 67 65 72 ,..count integer
00a0: 20 44 45 46 41 55 4c 54 20 30 20 4e 4f 54 20 4e DEFAULT 0 NOT N
00b0: 55 4c 4c 0a 29 3b 0a 0a 43 52 45 41 54 45 20 54 ULL.);..CREATE T
00c0: 41 42 4c 45 20 69 66 20 6e 6f 74 20 65 78 69 73 ABLE if not exis
00d0: 74 73 20 63 6f 75 6e 74 65 72 5f 73 75 6d 20 28 ts counter_sum (
00e0: 0a 09 72 65 66 65 72 65 72 20 74 65 78 74 20 44 ..referer text D
00f0: 45 46 41 55 4c 54 20 27 2d 27 3a 3a 74 65 78 74 EFAULT '-'::text
0100: 20 4e 4f 54 20 4e 55 4c 4c 2c 0a 09 64 61 79 20 NOT NULL,..day
0110: 64 61 74 65 20 44 45 46 41 55 4c 54 20 6e 6f 77 date DEFAULT now
0120: 28 29 20 4e 4f 54 20 4e 55 4c 4c 2c 0a 09 63 6f () NOT NULL,..co
0130: 75 6e 74 20 69 6e 74 65 67 65 72 20 44 45 46 41 unt integer DEFA
0140: 55 4c 54 20 30 20 4e 4f 54 20 4e 55 4c 4c 0a 29 ULT 0 NOT NULL.)
0150: 3b 0a 0a 43 52 45 41 54 45 20 6f 72 20 72 65 70 ;..CREATE or rep
0160: 6c 61 63 65 20 46 55 4e 43 54 49 4f 4e 20 67 65 lace FUNCTION ge
0170: 74 5f 73 74 61 74 73 28 74 61 72 67 65 74 20 74 t_stats(target t
0180: 65 78 74 29 20 52 45 54 55 52 4e 53 20 72 65 63 ext) RETURNS rec
0190: 6f 72 64 20 4c 41 4e 47 55 41 47 45 20 73 71 6c ord LANGUAGE sql
01a0: 20 41 53 20 24 5f 24 0a 73 65 6c 65 63 74 20 0a AS $_$.select .
01b0: 09 63 6f 61 6c 65 73 63 65 28 28 73 65 6c 65 63 .coalesce((selec
01c0: 74 20 63 6f 75 6e 74 20 66 72 6f 6d 20 6c 69 6d t count from lim
01d0: 62 6f 2e 63 6f 75 6e 74 65 72 5f 73 75 6d 20 77 bo.counter_sum w
01e0: 68 65 72 65 20 64 61 79 20 3d 20 63 75 72 72 65 here day = curre
01f0: 6e 74 5f 64 61 74 65 20 61 6e 64 20 72 65 66 65 nt_date and refe
0200: 72 65 72 20 3d 20 24 31 29 2c 20 30 29 20 61 73 rer = $1), 0) as
0210: 20 74 6f 64 61 79 2c 0a 09 63 6f 61 6c 65 73 63 today,..coalesc
0220: 65 28 28 73 65 6c 65 63 74 20 63 6f 75 6e 74 20 e((select count
0230: 66 72 6f 6d 20 6c 69 6d 62 6f 2e 63 6f 75 6e 74 from limbo.count
0240: 65 72 5f 73 75 6d 20 77 68 65 72 65 20 64 61 79 er_sum where day
0250: 20 3d 20 28 63 75 72 72 65 6e 74 5f 64 61 74 65 = (current_date
0260: 20 2d 20 69 6e 74 65 72 76 61 6c 20 27 31 20 64 - interval '1 d
0270: 61 79 27 29 3a 3a 64 61 74 65 20 61 6e 64 20 72 ay')::date and r
0280: 65 66 65 72 65 72 20 3d 20 24 31 29 2c 20 30 29 eferer = $1), 0)
0290: 20 61 73 20 6c 61 73 74 64 61 79 2c 0a 09 63 6f as lastday,..co
02a0: 61 6c 65 73 63 65 28 28 73 65 6c 65 63 74 20 73 alesce((select s
02b0: 75 6d 28 63 6f 75 6e 74 29 20 66 72 6f 6d 20 6c um(count) from l
02c0: 69 6d 62 6f 2e 63 6f 75 6e 74 65 72 5f 73 75 6d imbo.counter_sum
02d0: 0a 09 09 77 68 65 72 65 20 64 61 74 65 5f 74 72 ...where date_tr
02e0: 75 6e 63 28 27 77 65 65 6b 27 2c 20 63 75 72 72 unc('week', curr
02f0: 65 6e 74 5f 64 61 74 65 29 20 3d 20 64 61 74 65 ent_date) = date
0300: 5f 74 72 75 6e 63 28 27 77 65 65 6b 27 2c 20 64 _trunc('week', d
0310: 61 79 29 20 61 6e 64 20 64 61 79 20 3c 3e 20 63 ay) and day <> c
0320: 75 72 72 65 6e 74 5f 64 61 74 65 20 61 6e 64 20 urrent_date and
0330: 72 65 66 65 72 65 72 20 3d 20 24 31 0a 09 09 67 referer = $1...g
0340: 72 6f 75 70 20 62 79 20 72 65 66 65 72 65 72 29 roup by referer)
0350: 2c 20 30 29 20 61 73 20 77 65 65 6b 2c 0a 09 63 , 0) as week,..c
0360: 6f 61 6c 65 73 63 65 28 28 73 65 6c 65 63 74 20 oalesce((select
0370: 73 75 6d 28 63 6f 75 6e 74 29 20 66 72 6f 6d 20 sum(count) from
0380: 6c 69 6d 62 6f 2e 63 6f 75 6e 74 65 72 5f 73 75 limbo.counter_su
0390: 6d 20 77 68 65 72 65 20 64 61 79 20 3c 3e 20 63 m where day <> c
03a0: 75 72 72 65 6e 74 5f 64 61 74 65 20 61 6e 64 20 urrent_date and
03b0: 72 65 66 65 72 65 72 20 3d 20 24 31 20 67 72 6f referer = $1 gro
03c0: 75 70 20 62 79 20 72 65 66 65 72 65 72 29 2c 20 up by referer),
03d0: 30 29 20 61 73 20 77 68 6f 6c 65 0a 24 5f 24 3b 0) as whole.$_$;
03e0: 0a 0a 43 52 45 41 54 45 20 6f 72 20 72 65 70 6c ..CREATE or repl
03f0: 61 63 65 20 46 55 4e 43 54 49 4f 4e 20 63 6f 75 ace FUNCTION cou
0400: 6e 74 65 72 5f 73 75 6d 5f 5f 63 68 61 6e 67 65 nter_sum__change
0410: 5f 74 72 69 67 67 65 72 28 29 20 52 45 54 55 52 _trigger() RETUR
0420: 4e 53 20 74 72 69 67 67 65 72 20 4c 41 4e 47 55 NS trigger LANGU
0430: 41 47 45 20 70 6c 70 67 73 71 6c 20 41 53 20 24 AGE plpgsql AS $
0440: 24 0a 64 65 63 6c 61 72 65 0a 09 64 65 6c 74 61 $.declare..delta
0450: 5f 63 6f 75 6e 74 20 73 6d 61 6c 6c 69 6e 74 3b _count smallint;
0460: 0a 62 65 67 69 6e 0a 09 69 66 20 28 54 47 5f 4f .begin..if (TG_O
0470: 50 20 3d 20 27 55 50 44 41 54 45 27 29 20 74 68 P = 'UPDATE') th
0480: 65 6e 0a 09 09 69 66 20 28 6f 6c 64 2e 72 65 66 en...if (old.ref
0490: 65 72 65 72 20 3c 3e 20 6e 65 77 2e 72 65 66 65 erer <> new.refe
04a0: 72 65 72 20 6f 72 20 6f 6c 64 2e 64 61 79 20 3c rer or old.day <
04b0: 3e 20 6e 65 77 2e 64 61 79 29 20 74 68 65 6e 0a > new.day) then.
04c0: 09 09 09 72 61 69 73 65 20 65 78 63 65 70 74 69 ...raise excepti
04d0: 6f 6e 20 27 43 68 61 6e 67 69 6e 67 20 72 65 66 on 'Changing ref
04e0: 65 72 65 72 20 6f 72 20 64 61 79 20 69 73 20 70 erer or day is p
04f0: 72 6f 68 69 62 69 74 65 64 27 3b 0a 09 09 65 6e rohibited';...en
0500: 64 20 69 66 3b 0a 09 09 64 65 6c 74 61 5f 63 6f d if;...delta_co
0510: 75 6e 74 20 3d 20 6e 65 77 2e 63 6f 75 6e 74 20 unt = new.count
0520: 2d 20 6f 6c 64 2e 63 6f 75 6e 74 3b 0a 09 65 6c - old.count;..el
0530: 73 69 66 20 28 54 47 5f 4f 50 20 3d 20 27 49 4e sif (TG_OP = 'IN
0540: 53 45 52 54 27 29 20 74 68 65 6e 0a 09 09 64 65 SERT') then...de
0550: 6c 74 61 5f 63 6f 75 6e 74 20 3d 20 6e 65 77 2e lta_count = new.
0560: 63 6f 75 6e 74 3b 0a 09 65 6c 73 69 66 20 28 54 count;..elsif (T
0570: 47 5f 4f 50 20 3d 20 27 44 45 4c 45 54 45 27 29 G_OP = 'DELETE')
0580: 20 74 68 65 6e 0a 09 09 72 61 69 73 65 20 65 78 then...raise ex
0590: 63 65 70 74 69 6f 6e 20 27 44 65 6c 65 74 69 6e ception 'Deletin
05a0: 67 20 63 6f 75 6e 74 65 72 73 20 70 72 6f 68 69 g counters prohi
05b0: 62 69 74 65 64 27 3b 0a 09 65 6e 64 20 69 66 3b bited';..end if;
05c0: 0a 09 3c 3c 69 6e 73 65 72 74 5f 75 70 64 61 74 ..<<insert_updat
05d0: 65 3e 3e 20 6c 6f 6f 70 0a 09 09 75 70 64 61 74 e>> loop...updat
05e0: 65 20 6c 69 6d 62 6f 2e 63 6f 75 6e 74 65 72 5f e limbo.counter_
05f0: 73 75 6d 20 73 65 74 20 63 6f 75 6e 74 20 3d 20 sum set count =
0600: 63 6f 75 6e 74 20 2b 20 64 65 6c 74 61 5f 63 6f count + delta_co
0610: 75 6e 74 0a 09 09 09 77 68 65 72 65 20 72 65 66 unt....where ref
0620: 65 72 65 72 20 3d 20 6e 65 77 2e 72 65 66 65 72 erer = new.refer
0630: 65 72 20 61 6e 64 20 64 61 79 20 3d 20 6e 65 77 er and day = new
0640: 2e 64 61 79 3b 0a 09 09 65 78 69 74 20 69 6e 73 .day;...exit ins
0650: 65 72 74 5f 75 70 64 61 74 65 20 77 68 65 6e 20 ert_update when
0660: 66 6f 75 6e 64 3b 0a 09 09 62 65 67 69 6e 0a 09 found;...begin..
0670: 09 09 69 6e 73 65 72 74 20 69 6e 74 6f 20 6c 69 ..insert into li
0680: 6d 62 6f 2e 63 6f 75 6e 74 65 72 5f 73 75 6d 20 mbo.counter_sum
0690: 28 72 65 66 65 72 65 72 2c 20 64 61 79 2c 20 63 (referer, day, c
06a0: 6f 75 6e 74 29 20 76 61 6c 75 65 73 20 28 6e 65 ount) values (ne
06b0: 77 2e 72 65 66 65 72 65 72 2c 20 6e 65 77 2e 64 w.referer, new.d
06c0: 61 79 2c 20 64 65 6c 74 61 5f 63 6f 75 6e 74 29 ay, delta_count)
06d0: 3b 0a 09 09 09 65 78 69 74 20 69 6e 73 65 72 74 ;....exit insert
06e0: 5f 75 70 64 61 74 65 3b 0a 09 09 09 65 78 63 65 _update;....exce
06f0: 70 74 69 6f 6e 20 77 68 65 6e 20 75 6e 69 71 75 ption when uniqu
0700: 65 5f 76 69 6f 6c 61 74 69 6f 6e 20 74 68 65 6e e_violation then
0710: 0a 09 09 65 6e 64 3b 0a 09 65 6e 64 20 6c 6f 6f ...end;..end loo
0720: 70 20 69 6e 73 65 72 74 5f 75 70 64 61 74 65 3b p insert_update;
0730: 0a 09 72 65 74 75 72 6e 20 6e 65 77 3b 0a 65 6e ..return new;.en
0740: 64 3b 20 24 24 3b 0a 0a 43 52 45 41 54 45 20 6f d; $$;..CREATE o
0750: 72 20 72 65 70 6c 61 63 65 20 46 55 4e 43 54 49 r replace FUNCTI
0760: 4f 4e 20 6d 65 72 67 65 5f 63 6f 75 6e 74 65 72 ON merge_counter
0770: 28 6d 65 72 67 65 5f 75 69 64 20 74 65 78 74 2c (merge_uid text,
0780: 20 6d 65 72 67 65 5f 72 65 66 65 72 65 72 20 74 merge_referer t
0790: 65 78 74 2c 20 6d 65 72 67 65 5f 69 70 20 69 6e ext, merge_ip in
07a0: 65 74 2c 20 6d 65 72 67 65 5f 63 6f 75 6e 74 20 et, merge_count
07b0: 73 6d 61 6c 6c 69 6e 74 29 20 52 45 54 55 52 4e smallint) RETURN
07c0: 53 20 62 6f 6f 6c 65 61 6e 20 4c 41 4e 47 55 41 S boolean LANGUA
07d0: 47 45 20 70 6c 70 67 73 71 6c 20 41 53 20 24 24 GE plpgsql AS $$
07e0: 0a 42 45 47 49 4e 0a 09 3c 3c 69 6e 73 65 72 74 .BEGIN..<<insert
07f0: 5f 75 70 64 61 74 65 3e 3e 20 4c 4f 4f 50 0a 09 _update>> LOOP..
0800: 09 55 50 44 41 54 45 20 6c 69 6d 62 6f 2e 63 6f .UPDATE limbo.co
0810: 75 6e 74 65 72 20 53 45 54 20 63 6f 75 6e 74 20 unter SET count
0820: 3d 20 63 6f 75 6e 74 20 2b 20 6d 65 72 67 65 5f = count + merge_
0830: 63 6f 75 6e 74 0a 09 09 09 57 48 45 52 45 20 75 count....WHERE u
0840: 69 64 20 3d 20 6d 65 72 67 65 5f 75 69 64 20 61 id = merge_uid a
0850: 6e 64 20 69 70 20 3d 20 6d 65 72 67 65 5f 69 70 nd ip = merge_ip
0860: 20 61 6e 64 20 72 65 66 65 72 65 72 20 3d 20 6d and referer = m
0870: 65 72 67 65 5f 72 65 66 65 72 65 72 20 61 6e 64 erge_referer and
0880: 20 64 61 79 20 3d 20 63 75 72 72 65 6e 74 5f 64 day = current_d
0890: 61 74 65 3b 0a 09 09 65 78 69 74 20 69 6e 73 65 ate;...exit inse
08a0: 72 74 5f 75 70 64 61 74 65 20 77 68 65 6e 20 66 rt_update when f
08b0: 6f 75 6e 64 3b 0a 09 09 42 45 47 49 4e 0a 09 09 ound;...BEGIN...
08c0: 09 49 4e 53 45 52 54 20 49 4e 54 4f 20 6c 69 6d .INSERT INTO lim
08d0: 62 6f 2e 63 6f 75 6e 74 65 72 20 28 75 69 64 2c bo.counter (uid,
08e0: 20 72 65 66 65 72 65 72 2c 20 69 70 2c 20 63 6f referer, ip, co
08f0: 75 6e 74 29 20 56 41 4c 55 45 53 20 28 6d 65 72 unt) VALUES (mer
0900: 67 65 5f 75 69 64 2c 20 6d 65 72 67 65 5f 72 65 ge_uid, merge_re
0910: 66 65 72 65 72 2c 20 6d 65 72 67 65 5f 69 70 2c ferer, merge_ip,
0920: 20 6d 65 72 67 65 5f 63 6f 75 6e 74 29 3b 0a 09 merge_count);..
0930: 09 09 45 58 49 54 20 69 6e 73 65 72 74 5f 75 70 ..EXIT insert_up
0940: 64 61 74 65 3b 0a 09 09 09 45 58 43 45 50 54 49 date;....EXCEPTI
0950: 4f 4e 20 57 48 45 4e 20 75 6e 69 71 75 65 5f 76 ON WHEN unique_v
0960: 69 6f 6c 61 74 69 6f 6e 20 54 48 45 4e 0a 09 09 iolation THEN...
0970: 45 4e 44 3b 0a 09 45 4e 44 20 4c 4f 4f 50 20 69 END;..END LOOP i
0980: 6e 73 65 72 74 5f 75 70 64 61 74 65 3b 0a 09 72 nsert_update;..r
0990: 65 74 75 72 6e 20 74 72 75 65 3b 0a 45 4e 44 3b eturn true;.END;
09a0: 0a 24 24 3b 0a 0a 43 52 45 41 54 45 20 49 4e 44 .$$;..CREATE IND
09b0: 45 58 20 69 66 20 6e 6f 74 20 65 78 69 73 74 73 EX if not exists
09c0: 20 63 6f 75 6e 74 65 72 5f 5f 64 61 74 65 20 4f counter__date O
09d0: 4e 20 63 6f 75 6e 74 65 72 20 55 53 49 4e 47 20 N counter USING
09e0: 62 74 72 65 65 20 28 64 61 79 29 3b 0a 43 52 45 btree (day);.CRE
09f0: 41 54 45 20 55 4e 49 51 55 45 20 49 4e 44 45 58 ATE UNIQUE INDEX
0a00: 20 69 66 20 6e 6f 74 20 65 78 69 73 74 73 20 63 if not exists c
0a10: 6f 75 6e 74 65 72 5f 5f 75 69 64 5f 6e 72 65 66 ounter__uid_nref
0a20: 65 72 65 72 5f 69 70 5f 64 61 74 65 20 4f 4e 20 erer_ip_date ON
0a30: 63 6f 75 6e 74 65 72 20 28 75 69 64 2c 20 69 70 counter (uid, ip
0a40: 2c 20 64 61 79 29 20 57 48 45 52 45 20 28 72 65 , day) WHERE (re
0a50: 66 65 72 65 72 20 49 53 20 4e 55 4c 4c 29 3b 0a ferer IS NULL);.
0a60: 43 52 45 41 54 45 20 55 4e 49 51 55 45 20 49 4e CREATE UNIQUE IN
0a70: 44 45 58 20 69 66 20 6e 6f 74 20 65 78 69 73 74 DEX if not exist
0a80: 73 20 63 6f 75 6e 74 65 72 5f 5f 75 69 64 5f 72 s counter__uid_r
0a90: 65 66 65 72 65 72 5f 69 70 5f 64 61 74 65 20 4f eferer_ip_date O
0aa0: 4e 20 63 6f 75 6e 74 65 72 20 28 75 69 64 2c 20 N counter (uid,
0ab0: 72 65 66 65 72 65 72 2c 20 69 70 2c 20 64 61 79 referer, ip, day
0ac0: 29 3b 0a 63 72 65 61 74 65 20 75 6e 69 71 75 65 );.create unique
0ad0: 20 69 6e 64 65 78 20 69 66 20 6e 6f 74 20 65 78 index if not ex
0ae0: 69 73 74 73 20 63 6f 75 6e 74 65 72 5f 73 75 6d ists counter_sum
0af0: 5f 5f 72 65 66 65 72 65 72 5f 64 61 79 20 4f 4e __referer_day ON
0b00: 20 63 6f 75 6e 74 65 72 5f 73 75 6d 20 28 72 65 counter_sum (re
0b10: 66 65 72 65 72 2c 20 64 61 79 29 3b 0a 0a 64 72 ferer, day);..dr
0b20: 6f 70 20 74 72 69 67 67 65 72 20 69 66 20 65 78 op trigger if ex
0b30: 69 73 74 73 20 63 6f 75 6e 74 65 72 5f 5f 63 68 ists counter__ch
0b40: 61 6e 67 65 20 6f 6e 20 63 6f 75 6e 74 65 72 3b ange on counter;
0b50: 0a 43 52 45 41 54 45 20 54 52 49 47 47 45 52 20 .CREATE TRIGGER
0b60: 63 6f 75 6e 74 65 72 5f 5f 63 68 61 6e 67 65 20 counter__change
0b70: 41 46 54 45 52 20 49 4e 53 45 52 54 20 4f 52 20 AFTER INSERT OR
0b80: 44 45 4c 45 54 45 20 4f 52 20 55 50 44 41 54 45 DELETE OR UPDATE
0b90: 20 4f 4e 20 63 6f 75 6e 74 65 72 20 46 4f 52 20 ON counter FOR
0ba0: 45 41 43 48 20 52 4f 57 20 45 58 45 43 55 54 45 EACH ROW EXECUTE
0bb0: 20 50 52 4f 43 45 44 55 52 45 20 63 6f 75 6e 74 PROCEDURE count
0bc0: 65 72 5f 73 75 6d 5f 5f 63 68 61 6e 67 65 5f 74 er_sum__change_t
0bd0: 72 69 67 67 65 72 28 29 3b 0a rigger();.