Вы находитесь на странице: 1из 3

--- Update_partitions - Takes a begin time, schema name, primary (parent) table n ame, -table owner, the name

of the date column, -and if we want 'week'ly or 'month'ly partitions. -The number of created tables is returned. -ex: SELECT public.update_partitions('2010-02-01','my_sche ma','my_data','postgres','create_date','week') --- Function: public.update_partitions(timestamp without time zone, text, text, t ext, text, text) -- DROP FUNCTION public.update_partitions(timestamp without time zone, text, tex t, text, text, text); CREATE OR REPLACE FUNCTION public.update_partitions(begin_time timestamp without time zone, schema_name text, primary_table_name text, table_owner text, date_co lumn text, plan text) RETURNS integer AS $BODY$ declare startTime timestamp; declare endTime timestamp; declare intervalTime timestamp; declare createStmts text; declare createTrigger text; declare fullTablename text; declare unknownTablename text; declare triggerName text; declare createdTables integer; declare dateFormat text; declare planInterval interval; BEGIN dateFormat:=CASE WHEN plan='month' THEN 'YYYYMM' WHEN plan='week' THEN 'IYYYIW' WHEN plan='day' THEN 'YYYYDDD' WHEN plan='year' THEN 'YYYY' ELSE 'error' END; IF dateFormat='error' THEN RAISE EXCEPTION 'Non valid plan --> %', plan; END IF; -- Store the incoming begin_time, and set the endTime to one month/week/day in t he future -(this allows use of a cronjob at any time during the month/week/day to ge nerate next month/week/day's table) startTime:=(date_trunc(plan,begin_time)); planInterval:=('1 '||plan)::interval; endTime:=(date_trunc(plan,(current_timestamp + planInterval))); createdTables:=0; -- Begin creating the trigger function, we're going to generate it backwards. createTrigger:=' ELSE INSERT INTO '||schema_name||'.'||primary_table_name||'_unknowns VALU ES (NEW.*); END IF; RETURN NULL;

END; $$ LANGUAGE plpgsql;'; while (startTime <= endTime) loop fullTablename:=primary_table_name||'_'||to_char(startTime,dateFormat); intervalTime:= startTime + planInterval; -- The table creation sql statement if not exists(select * from information_schema.tables where table_schema = sc hema_name AND table_name = fullTablename) then createStmts:='CREATE TABLE '||schema_name||'.'||fullTablename||' ( CHECK ('||date_column||' >= '''||startTime||''' AND '||date_column ||' < '''||intervalTime||''') ) INHERITS ('||schema_name||'.'||primary_table_name||')'; -- Run the table creation EXECUTE createStmts; -- Set the table owner createStmts :='ALTER TABLE '||schema_name||'.'||fullTablename||' OWNER TO ' ||table_owner||';'; EXECUTE createStmts; -- Create an index on the timestamp createStmts:='CREATE INDEX idx_'||fullTablename||'_'||date_column||' ON '|| schema_name||'.'||fullTablename||' ('||date_column||');'; EXECUTE createStmts; -- Track how many tables we are creating (should likely be 1, except for in itial run and backfilling efforts). createdTables:=createdTables+1; end if; -- Add case for this table to trigger creation sql statement. createTrigger:='( NEW.'||date_column||' >= TIMESTAMP '''||startTime||''' AND NEW.'||date_column||' < TIMESTAMP '''||intervalTime||''' ) THEN INSERT INTO '||schema_name||'.'||fullTablename||' VALUES (NEW.*); '||createTrigger; startTime:=intervalTime; if (startTime <= endTime) then createTrigger:=' ELSEIF '||createTrigger; end if; end loop; -- CREATE UNKNOWN HOLDER IF IT DOES NOT EXIST, unknowns table handles possible -inserts for which there is not an appropriate table partition -This is often more desirable than simply raising an error. unknownTablename:=primary_table_name||'_unknowns'; IF NOT EXISTS(SELECT * FROM information_schema.tables WHERE table_schema = schema_name AND table_name = unknownTablename) THEN createStmts :='CREATE TABLE '||schema_name||'.'||primary_table_name||'_unkno

wns ( ) INHERITS ('||schema_name||'.'||primary_table_name||');'; -- Execute the unknown table creation EXECUTE createStmts; -- Set the table owner createStmts:='ALTER TABLE '||schema_name||'.'||primary_table_name||'_unknown s OWNER TO '||table_owner||';'; EXECUTE createStmts; END IF; -- Finish creating the trigger function (at the beginning). createTrigger:='CREATE OR REPLACE FUNCTION '||schema_name||'.'||primary_table_na me||'_insert_trigger_function() RETURNS TRIGGER AS $$ BEGIN IF '||createTrigger; -- Run the trigger replacement; EXECUTE createTrigger; -- Create the trigger that uses the trigger function, if it isn't already create d triggerName:=primary_table_name||'_insert_trigger'; if not exists(select * from information_schema.triggers where trigger_name = tri ggerName) then createTrigger:='CREATE TRIGGER '||primary_table_name||'_insert_trigger BEFORE INSERT ON '||schema_name||'.'||primary_table_name||' FOR EACH ROW EXECUTE PROCEDURE '||schema_name||'.'||primary_ta ble_name||'_insert_trigger_function();'; EXECUTE createTrigger; END if; return createdTables; END; $BODY$ LANGUAGE 'plpgsql' VOLATILE COST 100; ALTER FUNCTION public.update_partitions(timestamp without time zone, text, text, text, text, text) OWNER TO postgres;

Вам также может понравиться