Log Message:
-----------
Updated pgAgent schema with cron-style scheduling.
Modified Files:
--------------
pgagent:
pgagent.sql (r1.4 -> r1.5)
Index: pgagent.sql
===================================================================
RCS file: /projects/pgagent/pgagent.sql,v
retrieving revision 1.4
retrieving revision 1.5
diff -Lpgagent.sql -Lpgagent.sql -u -w -r1.4 -r1.5
--- pgagent.sql
+++ pgagent.sql
@@ -11,12 +11,15 @@
CREATE SCHEMA pgagent;
COMMENT ON SCHEMA pgagent IS 'pgAgent system tables';
+
+
CREATE TABLE pgagent.pga_jobagent (
jagpid int4 NOT NULL PRIMARY KEY,
logintime timestamptz NOT NULL DEFAULT current_timestamp,
station text NOT NULL
) WITHOUT OIDS;
-COMMENT ON TABLE pgagent.pga_jobagent IS 'active job agents';
+COMMENT ON TABLE pgagent.pga_jobagent IS 'Active job agents';
+
CREATE TABLE pgagent.pga_jobclass (
@@ -26,6 +29,12 @@
CREATE UNIQUE INDEX pga_jobclass_name ON pgagent.pga_jobclass(jclname);
COMMENT ON TABLE pgagent.pga_jobclass IS 'Job classification';
+INSERT INTO pgagent.pga_jobclass (jclname) VALUES ('Routine Maintenance');
+INSERT INTO pgagent.pga_jobclass (jclname) VALUES ('Data Import');
+INSERT INTO pgagent.pga_jobclass (jclname) VALUES ('Data Export');
+INSERT INTO pgagent.pga_jobclass (jclname) VALUES ('Data Summarisation');
+INSERT INTO pgagent.pga_jobclass (jclname) VALUES ('Miscellaneous');
+
CREATE TABLE pgagent.pga_job (
@@ -44,6 +53,7 @@
COMMENT ON COLUMN pgagent.pga_job.jobagentid IS 'Agent that currently executes
this job.';
+
CREATE TABLE pgagent.pga_jobstep (
jstid serial NOT NULL PRIMARY KEY,
jstjobid int4 NOT NULL REFERENCES pgagent.pga_job
(jobid) ON DELETE CASCADE ON UPDATE RESTRICT,
@@ -71,16 +81,33 @@
jscenabled bool NOT NULL DEFAULT true,
jscstart timestamptz NOT NULL DEFAULT current_timestamp,
jscend timestamptz NULL,
-jsckind char NOT NULL CHECK (jsckind IN ('n',
's', 'd', 'w', 'm', 'y')) DEFAULT 'n', -- normal, single, daily, weekly,
monthly, yearly
-jscsched timestamptz NULL,
-jsclist interval[] NOT NULL
+jscminutes bool[60] NOT NULL DEFAULT
'{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}',
+jschours bool[24] NOT NULL DEFAULT
'{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}',
+jscweekdays bool[7] NOT NULL DEFAULT '{f,f,f,f,f,f,f}',
+jscmonthdays bool[32] NOT NULL DEFAULT
'{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}',
+jscmonths bool[12] NOT NULL DEFAULT
'{f,f,f,f,f,f,f,f,f,f,f,f}',
+CONSTRAINT pga_schedule_jscminutes_size CHECK (array_upper(jscminutess, 1) =
60),
+CONSTRAINT pga_schedule_jschours_size CHECK (array_upper(jschours, 1) = 24),
+CONSTRAINT pga_schedule_jscweekdays_size CHECK (array_upper(jscweekdays, 1) =
7),
+CONSTRAINT pga_schedule_jscmonthdays_size CHECK (array_upper(jscmonthdays, 1)
= 32),
+CONSTRAINT pga_schedule_jscmonths_size CHECK (array_upper(jscmonths, 1) = 12),
) WITHOUT OIDS;
CREATE INDEX pga_jobschedule_jobid ON pgagent.pga_schedule(jscjobid);
COMMENT ON TABLE pgagent.pga_schedule IS 'Schedule for a job';
-COMMENT ON COLUMN pgagent.pga_schedule.jsckind IS 'Kind of schedule: normal
periodical (jsclist has one entry), single, daily, weekly, monthly, yearly
(jsclist contains list of intervals in period)';
+CREATE TABLE pgagent.pga_exception (
+jexid serial NOT NULL PRIMARY KEY,
+jexscid int4 NOT NULL REFERENCES
pgagent.pga_schedule (jscid) ON DELETE CASCADE ON UPDATE RESTRICT,
+jexdate date NULL,
+jextime time NULL
+)
+WITHOUT OIDS;
+CREATE INDEX pga_exception_jexscid ON pgagent.pga_exception (jexscid);
+CREATE UNIQUE INDEX pga_exception_datetime ON pgagent.pga_exception (jexdate,
jextime);
+COMMENT ON TABLE pgagent.pga_schedule IS 'Job schedule exceptions';
+
CREATE TABLE pgagent.pga_jobprotocol (
@@ -113,83 +140,403 @@
-CREATE OR REPLACE FUNCTION pgagent.pga_next_schedule(timestamptz, timestamptz,
timestamptz, char, interval[]) returns timestamptz as
-'
+CREATE OR REPLACE FUNCTION pgagent.pga_next_schedule(int4, timestamptz,
timestamptz, _bool, _bool, _bool, _bool, _bool) RETURNS timestamptz AS '
DECLARE
- jscstart ALIAS FOR $1;
- jscend ALIAS FOR $2;
- jscsched ALIAS FOR $3;
- jsckind ALIAS FOR $4;
- jsclist ALIAS FOR $5;
-
- nextrun timestamptz;
- period interval;
- i int4;
+ jscid ALIAS FOR $1;
+ jscstart ALIAS FOR $2;
+ jscend ALIAS FOR $3;
+ jscminutes ALIAS FOR $4;
+ jschours ALIAS FOR $5;
+ jscweekdays ALIAS FOR $6;
+ jscmonthdays ALIAS FOR $7;
+ jscmonths ALIAS FOR $8;
+
+ nextrun timestamptz := ''1970-01-01 00:00:00-00'';
+ runafter timestamptz := ''1970-01-01 00:00:00-00'';
+
+ bingo bool := FALSE;
+ gotit bool := FALSE;
+ foundval bool := FALSE;
+ daytweak bool := FALSE;
+
+ i int2 := 0;
+ d int2 := 0;
+
+ nextminute int2 := 0;
+ nexthour int2 := 0;
+ nextday int2 := 0;
+ nextmonth int2 := 0;
+ nextyear int2 := 0;
BEGIN
- -- check for validity range of schedule
- IF jscstart IS NULL OR jscstart > now() THEN RETURN NULL; END IF;
+ -- No valid start date has been specified
+ IF jscstart IS NULL THEN RETURN NULL; END IF;
+
+ -- The schedule is past its end date
IF jscend IS NOT NULL AND jscend < now() THEN RETURN NULL; END IF;
- IF jsckind = ''n'' THEN
- -- schedule type n: every <jsclist[1]> after <jscsched>
- IF jscsched IS NULL OR jscsched > now() THEN RETURN NULL; END IF;
- nextrun := jscsched
- + ( 1 + floor(
- (extract(EPOCH FROM now()) - extract(EPOCH FROM
jscsched))
- / extract(EPOCH FROM jsclist[1]))
- ) * jsclist[1];
-
- ELSIF jsckind = ''s'' THEN
- nextrun := jscsched;
- ELSIF jsckind IN (''y'', ''m'', ''w'', ''d'') THEN
- -- other schedule types:
- IF jsckind = ''y'' THEN nextrun := date_trunc(''year'', now());
period := ''1 year''::interval;
- ELSIF jsckind = ''m'' THEN nextrun := date_trunc(''month'', now());
period := ''1 month''::interval;
- ELSIF jsckind = ''d'' THEN nextrun := date_trunc(''day'', now());
period := ''1 day''::interval;
- ELSE
- -- calculate monday of this week; period starts with monday
00:00:00
- nextrun := date_trunc(''day'', now()) - ((extract(DOW FROM
now())-1)::text || '' days''::text)::interval ;
- period := ''7 days''::interval;
- END IF;
- i := 1;
- WHILE jsclist[i] IS NOT NULL LOOP
- IF nextrun + jsclist[i] > now() THEN
- nextrun := nextrun + jsclist[i];
- EXIT;
- END IF;
- i := i + 1;
- END LOOP;
- IF nextrun < now() THEN
- -- one complete period further
- nextrun := nextrun + jsclist[1] + period;
+ -- Get the time to find the next run after. It will just be the later of
+ -- now() and the start date for the time being, however, we might want to
+ -- do more complex things using this value in the future.
+ IF date_trunc(''MINUTE'', jscstart) > date_trunc(''MINUTE'', now()) THEN
+ runafter := date_trunc(''MINUTE'', jscstart);
+ ELSE
+ runafter := date_trunc(''MINUTE'', now());
+ END IF;
+
+
+ --
+ -- Enter a loop, generating next run timestamps until we find one
+ -- that falls on the required weekday, and is not matched by an exception
+ --
+
+ WHILE bingo = FALSE LOOP
+
+ --
+ -- Get the next run year
+ --
+ nextyear := date_part(''YEAR'', runafter);
+
+ --
+ -- Get the next run month
+ --
+ nextmonth := date_part(''MONTH'', runafter);
+ gotit := FALSE;
+ FOR i IN (nextmonth) .. 12 LOOP
+ IF jscmonths[i] = TRUE THEN
+ nextmonth := i;
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ IF gotit = FALSE THEN
+ FOR i IN 1 .. (nextmonth - 1) LOOP
+ IF jscmonths[i] = TRUE THEN
+ nextmonth := i;
+
+ -- Wrap into next year
+ nextyear := nextyear + 1;
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ END IF;
+
+ --
+ -- Get the next run day
+ --
+ -- If the year, or month have incremented, get the lowest day,
+ -- otherwise look for the next day matching or after today.
+ IF (nextyear > date_part(''YEAR'', runafter) OR nextmonth >
date_part(''MONTH'', runafter)) THEN
+ nextday := 1;
+ FOR i IN 1 .. 32 LOOP
+ IF jscmonthdays[i] = TRUE THEN
+ nextday := i;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ ELSE
+ nextday := date_part(''DAY'', runafter);
+ gotit := FALSE;
+ FOR i IN nextday .. 32 LOOP
+ IF jscmonthdays[i] = TRUE THEN
+ nextday := i;
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ IF gotit = FALSE THEN
+ FOR i IN 1 .. (nextday - 1) LOOP
+ IF jscmonthdays[i] = TRUE THEN
+ nextday := i;
+
+ -- Wrap into next month
+ IF nextmonth = 12 THEN
+ nextyear := nextyear + 1;
+ nextmonth := 1;
+ ELSE
+ nextmonth := nextmonth + 1;
+ END IF;
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ END IF;
+ END IF;
+
+ -- Was the last day flag selected?
+ IF nextday = 32 THEN
+ IF nextmonth = 1 THEN
+ nextday := 31;
+ ELSEIF nextmonth = 2 THEN
+ IF pgagent.pga_is_leap_year(nextyear) = TRUE THEN
+ nextday := 29;
+ ELSE
+ nextday := 28;
+ END IF;
+ ELSEIF nextmonth = 3 THEN
+ nextday := 31;
+ ELSEIF nextmonth = 4 THEN
+ nextday := 30;
+ ELSEIF nextmonth = 5 THEN
+ nextday := 31;
+ ELSEIF nextmonth = 6 THEN
+ nextday := 30;
+ ELSEIF nextmonth = 7 THEN
+ nextday := 31;
+ ELSEIF nextmonth = 8 THEN
+ nextday := 31;
+ ELSEIF nextmonth = 9 THEN
+ nextday := 30;
+ ELSEIF nextmonth = 10 THEN
+ nextday := 31;
+ ELSEIF nextmonth = 11 THEN
+ nextday := 30;
+ ELSEIF nextmonth = 12 THEN
+ nextday := 31;
+ END IF;
+ END IF;
+
+ --
+ -- Get the next run hour
+ --
+ -- If the year, month or day have incremented, get the lowest hour,
+ -- otherwise look for the next hour matching or after the current one.
+ IF (nextyear > date_part(''YEAR'', runafter) OR nextmonth >
date_part(''MONTH'', runafter) OR nextday > date_part(''DAY'', runafter) OR
daytweak = TRUE) THEN
+ nexthour := 0;
+ FOR i IN 1 .. 24 LOOP
+ IF jschours[i] = TRUE THEN
+ nexthour := i - 1;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ ELSE
+ nexthour := date_part(''HOUR'', runafter);
+ gotit := FALSE;
+ FOR i IN (nexthour + 1) .. 24 LOOP
+ IF jschours[i] = TRUE THEN
+ nexthour := i - 1;
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ IF gotit = FALSE THEN
+ FOR i IN 1 .. nexthour LOOP
+ IF jschours[i] = TRUE THEN
+ nexthour := i - 1;
+
+ -- Wrap into next month
+ IF (nextmonth = 1 OR nextmonth = 3 OR nextmonth = 5 OR
nextmonth = 7 OR nextmonth = 8 OR nextmonth = 10 OR nextmonth = 12) THEN
+ d = 31;
+ ELSEIF (nextmonth = 4 OR nextmonth = 6 OR nextmonth =
9 OR nextmonth = 11) THEN
+ d = 30;
+ ELSE
+ IF pgagent.pga_is_leap_year(nextyear) = TRUE THEN
+ d := 29;
+ ELSE
+ d := 28;
+ END IF;
+ END IF;
+
+ IF nextday = d THEN
+ nextday := 1;
+ IF nextmonth = 12 THEN
+ nextyear := nextyear + 1;
+ nextmonth := 1;
+ ELSE
+ nextmonth := nextmonth + 1;
+ END IF;
+ ELSE
+ nextday := nextday + 1;
+ END IF;
+
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ END IF;
+ END IF;
+
+ --
+ -- Get the next run minute
+ --
+ -- If the year, month day or hour have incremented, get the lowest
minute,
+ -- otherwise look for the next minute matching or after the current
one.
+ IF (nextyear > date_part(''YEAR'', runafter) OR nextmonth >
date_part(''MONTH'', runafter) OR nextday > date_part(''DAY'', runafter) OR
nexthour > date_part(''HOUR'', runafter) OR daytweak = TRUE) THEN
+ nextminute := 0;
+ FOR i IN 1 .. 60 LOOP
+ IF jscminutes[i] = TRUE THEN
+ nextminute := i - 1;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ ELSE
+ nextminute := date_part(''MINUTE'', runafter);
+ gotit := FALSE;
+ FOR i IN (nextminute + 1) .. 60 LOOP
+ IF jscminutes[i] = TRUE THEN
+ nextminute := i - 1;
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+ IF gotit = FALSE THEN
+ FOR i IN 1 .. nextminute LOOP
+ IF jscminutes[i] = TRUE THEN
+ nextminute := i - 1;
+
+ -- Wrap into next hour
+ IF (nextmonth = 1 OR nextmonth = 3 OR nextmonth = 5 OR
nextmonth = 7 OR nextmonth = 8 OR nextmonth = 10 OR nextmonth = 12) THEN
+ d = 31;
+ ELSEIF (nextmonth = 4 OR nextmonth = 6 OR nextmonth =
9 OR nextmonth = 11) THEN
+ d = 30;
+ ELSE
+ IF pgagent.pga_is_leap_year(nextyear) = TRUE THEN
+ d := 29;
+ ELSE
+ d := 28;
+ END IF;
+ END IF;
+
+ IF nexthour = 23 THEN
+ nexthour = 0;
+ IF nextday = d THEN
+ nextday := 1;
+ IF nextmonth = 12 THEN
+ nextyear := nextyear + 1;
+ nextmonth := 1;
+ ELSE
+ nextmonth := nextmonth + 1;
+ END IF;
+ ELSE
+ nextday := nextday + 1;
END IF;
ELSE
- RAISE EXCEPTION ''pgagent.pga_next_schedule: unknown schedule kind'';
+ nexthour := nexthour + 1;
+ END IF;
+
+ gotit := TRUE;
+ foundval := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
END IF;
+ END IF;
+
+ -- Build the result, and check it is not the same as runafter - this
may
+ -- happen if all array entries are set to false. In this case, add a
minute.
+
+ nextrun := (nextyear::varchar || ''-''::varchar || nextmonth::varchar
|| ''-'' || nextday::varchar || '' '' || nexthour::varchar || '':'' ||
nextminute::varchar)::timestamptz;
+
+ IF nextrun = runafter AND foundval = FALSE THEN
+ nextrun := nextrun + INTERVAL ''1 Minute'';
+ END IF;
+
+ -- If the result is past the end date, exit.
+ IF nextrun > jscend THEN
+ RETURN NULL;
+ END IF;
+
+ -- Check to ensure that the nextrun time is actually still valid. Its
+ -- possible that wrapped values may have carried the nextrun onto an
+ -- invalid time or date.
+ IF ((jscminutes =
''{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}''
OR jscminutes[date_part(''MINUTE'', nextrun) + 1] = TRUE) AND
+ (jschours = ''{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}''
OR jschours[date_part(''HOUR'', nextrun) + 1] = TRUE) AND
+ (jscmonthdays =
''{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}'' OR
jscmonthdays[date_part(''DAY'', nextrun)] = TRUE OR
+ (jscmonthdays =
''{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,t}'' AND
+ ((date_part(''MONTH'', nextrun) IN (1,3,5,7,8,10,12) AND
date_part(''DAY'', nextrun) = 31) OR
+ (date_part(''MONTH'', nextrun) IN (4,6,9,11) AND
date_part(''DAY'', nextrun) = 30) OR
+ (date_part(''MONTH'', nextrun) = 2 AND
((pgagent.pga_is_leap_year(date_part(''DAY'', nextrun)::int2) AND
date_part(''DAY'', nextrun) = 29) OR date_part(''DAY'', nextrun) = 28))))) AND
+ (jscmonths = ''{f,f,f,f,f,f,f,f,f,f,f,f}'' OR
jscmonths[date_part(''MONTH'', nextrun)] = TRUE)) THEN
+
+
+ -- Now, check to see if the nextrun time found is a) on an
acceptable
+ -- weekday, and b) not matched by an exception. If not, set
+ -- runafter = nextrun and try again.
+
+ -- Check for a wildcard weekday
+ gotit := FALSE;
+ FOR i IN 1 .. 7 LOOP
+ IF jscweekdays[i] = TRUE THEN
+ gotit := TRUE;
+ EXIT;
+ END IF;
+ END LOOP;
+
+ -- OK, is the correct weekday selected, or a wildcard?
+ IF (jscweekdays[date_part(''DOW'', nextrun)] = TRUE OR gotit =
FALSE) THEN
+
+ -- Check for exceptions
+ SELECT INTO d jexid FROM pgagent.pga_exception WHERE jexscid =
jscid AND ((jexdate = nextrun::date AND jextime = nextrun::time) OR (jexdate =
nextrun::date AND jextime IS NULL) OR (jexdate IS NULL AND jextime =
nextrun::time));
+ IF FOUND THEN
+ -- Nuts - found an exception. Increment the time and try
again
+ runafter := nextrun + INTERVAL ''1 Minute'';
+ bingo := FALSE;
+ ELSE
+ bingo := TRUE;
+ END IF;
+ ELSE
+ -- We''re on the wrong week day - increment a day and try
again.
+ runafter := nextrun + INTERVAL ''1 Day'';
+ bingo := FALSE;
+ daytweak := TRUE;
+ END IF;
+
+ ELSE
+ runafter := nextrun + INTERVAL ''1 Minute'';
+ bingo := FALSE;
+ END IF;
+
+ END LOOP;
+
RETURN nextrun;
END;
-'
-language 'plpgsql';
+' LANGUAGE 'plpgsql' VOLATILE;
+COMMENT ON FUNCTION pgagent.pga_next_schedule(int4, timestamptz, timestamptz,
_bool, _bool, _bool, _bool, _bool) IS 'Calculates the next runtime for a given
schedule';
+
+--
+-- Test code
+--
+-- SELECT pgagent.pga_next_schedule(
+-- 2, -- Schedule ID
+-- '2005-01-01 00:00:00', -- Start date
+-- '2006-10-01 00:00:00', -- End date
+--
'{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}',
-- Minutes
+-- '{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}', -- Hours
+-- '{f,f,f,f,f,f,f}', -- Weekdays
+-- '{f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f}', --
Monthdays
+-- '{f,f,f,f,f,f,f,f,f,f,f,f}' -- Months
+-- );
-CREATE OR REPLACE FUNCTION pgagent.pga_job_trigger() RETURNS trigger AS '
+
+
+CREATE OR REPLACE FUNCTION pgagent.pga_is_leap_year(int2) RETURNS bool AS '
BEGIN
- IF NEW.jobenabled THEN
- IF NEW.jobnextrun IS NULL THEN
- SELECT INTO NEW.jobnextrun
- MIN(pgagent.pga_next_schedule(jscstart, jscend, jscsched,
jsckind, jsclist))
- FROM pgagent.pga_schedule
- WHERE jscenabled AND jscjobid=OLD.jobid;
+ IF $1 % 4 != 0 THEN
+ RETURN FALSE;
END IF;
- ELSE
- NEW.jobnextrun := NULL;
+
+ IF $1 % 100 != 0 THEN
+ RETURN TRUE;
END IF;
- RETURN NEW;
+
+ RETURN $1 % 400 = 0;
END;
-' LANGUAGE 'plpgsql';
+' LANGUAGE 'plpgsql' IMMUTABLE;
+COMMENT ON FUNCTION pgagent.pga_is_leap_year(int2) IS 'Returns TRUE is $1 is a
leap year';
CREATE TRIGGER pga_job_trigger BEFORE UPDATE
@@ -197,43 +544,67 @@
EXECUTE PROCEDURE pgagent.pga_job_trigger();
+
CREATE OR REPLACE FUNCTION pgagent.pga_schedule_trigger() RETURNS trigger AS '
BEGIN
IF TG_OP = ''DELETE'' THEN
-- update pga_job from remaining schedules
-- the actual calculation of jobnextrun will be performed in the
trigger
- UPDATE pgadmin.pga_job
+ UPDATE pgagent.pga_job
SET jobnextrun = NULL
WHERE jobenabled AND jobid=OLD.jscjobid;
RETURN OLD;
ELSE
- UPDATE pgadmin.pga_job
+ UPDATE pgagent.pga_job
SET jobnextrun = NULL
WHERE jobenabled AND jobid=NEW.jscjobid;
RETURN NEW;
END IF;
END;
' LANGUAGE 'plpgsql';
+COMMENT ON FUNCTION pgagent.pga_schedule_trigger() IS 'Update the job\'s next
run time whenever a schedule changes';
CREATE TRIGGER pga_schedule_trigger AFTER INSERT OR UPDATE OR DELETE
ON pgagent.pga_schedule FOR EACH ROW
EXECUTE PROCEDURE pgagent.pga_schedule_trigger();
+COMMENT ON TRIGGER pga_schedule_trigger ON pgagent.pga_schedule IS 'Update the
job\'s next run time whenever a schedule changes';
-/*
-delete from pgagent.pga_jobclass;
+CREATE OR REPLACE FUNCTION pgagent.pga_exception_trigger() RETURNS "trigger"
AS '
+DECLARE
+
+ jobid int4 := 0;
+
+BEGIN
-insert into pgagent.pga_jobclass (jclname) values ('misc');
+ IF TG_OP = ''DELETE'' THEN
+
+ SELECT INTO jobid jscjobid FROM pgagent.pga_schedule WHERE jscid =
OLD.jexscid;
+
+ -- update pga_job from remaining schedules
+ -- the actual calculation of jobnextrun will be performed in the
trigger
+ UPDATE pgagent.pga_job
+ SET jobnextrun = NULL
+ WHERE jobenabled AND jobid=jobid;
+ RETURN OLD;
+ ELSE
- delete from pgagent.pga_schedule;
- select * from pgagent.pga_Schedule;
+ SELECT INTO jobid jscjobid FROM pgagent.pga_schedule WHERE jscid =
NEW.jexscid;
- insert into pgagent.pga_schedule(jscjoboid,jscname, jscdesc, jscenabled,
jscstart, jscsched, jsclist)
- values (xxxxx, '10min', 'arbitrary 10min cycle', true, '2002-01-01',
'2002-01-01', ARRAY['10 min'::interval] );
+ UPDATE pgagent.pga_job
+ SET jobnextrun = NULL
+ WHERE jobenabled AND jobid=jobid;
+ RETURN NEW;
+ END IF;
+END;
+' LANGUAGE 'plpgsql' VOLATILE;
+COMMENT ON FUNCTION pgagent.pga_schedule_trigger() IS 'Update the job\'s next
run time whenever an exception changes';
--- update pgagent.pga_schedule set jscenabled=jscenabled
-*/
+CREATE TRIGGER pga_exception_trigger AFTER INSERT OR UPDATE OR DELETE
+ ON pgagent.pga_exception FOR EACH ROW
+ EXECUTE PROCEDURE pgagent.pga_exception_trigger();
+COMMENT ON TRIGGER pga_exception_trigger ON pgagent.pga_exception IS 'Update
the job\'s next run time whenever an exception changes';
\ No newline at end of file
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match