lua-counter example

Hex Artifact Content
anonymous

Hex Artifact Content

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();.