Guest User

Untitled

a guest
Dec 13th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.51 KB | None | 0 0
  1. --
  2. -- Update_partitions - Takes a begin time, schema name, primary (parent) table name,
  3. -- table owner, the name of the date column,
  4. -- and if we want 'week'ly or 'month'ly partitions.
  5. -- The number of created tables is returned.
  6. -- ex: SELECT public.update_partitions('2010-02-01','my_schema','my_data','postgres','create_date','week')
  7. --
  8.  
  9.  
  10. -- Function: public.update_partitions(timestamp without time zone, text, text, text, text, text)
  11.  
  12. -- DROP FUNCTION public.update_partitions(timestamp without time zone, text, text, text, text, text);
  13.  
  14. CREATE OR REPLACE FUNCTION public.update_partitions(begin_time timestamp without time zone, schema_name text, primary_table_name text, table_owner text, date_column text, plan text)
  15. RETURNS integer AS
  16. $BODY$
  17. declare startTime timestamp;
  18. declare endTime timestamp;
  19. declare intervalTime timestamp;
  20. declare createStmts text;
  21. declare createTrigger text;
  22. declare fullTablename text;
  23. declare unknownTablename text;
  24. declare triggerName text;
  25. declare createdTables integer;
  26. declare dateFormat text;
  27. declare planInterval interval;
  28.  
  29. BEGIN
  30. dateFormat:=CASE WHEN plan='month' THEN 'YYYYMM'
  31. WHEN plan='week' THEN 'IYYYIW'
  32. WHEN plan='day' THEN 'YYYYDDD'
  33. WHEN plan='year' THEN 'YYYY'
  34. ELSE 'error'
  35. END;
  36. IF dateFormat='error' THEN
  37. RAISE EXCEPTION 'Non valid plan --> %', plan;
  38. END IF;
  39. -- Store the incoming begin_time, and set the endTime to one month/week/day in the future
  40. -- (this allows use of a cronjob at any time during the month/week/day to generate next month/week/day's table)
  41. startTime:=(date_trunc(plan,begin_time));
  42. planInterval:=('1 '||plan)::interval;
  43. endTime:=(date_trunc(plan,(current_timestamp + planInterval)));
  44. createdTables:=0;
  45.  
  46. -- Begin creating the trigger function, we're going to generate it backwards.
  47. createTrigger:='
  48. ELSE
  49. INSERT INTO '||schema_name||'.'||primary_table_name||'_unknowns VALUES (NEW.*);
  50. END IF;
  51. RETURN NULL;
  52. END;
  53. $$
  54. LANGUAGE plpgsql;';
  55.  
  56. while (startTime <= endTime) loop
  57.  
  58. fullTablename:=primary_table_name||'_'||to_char(startTime,dateFormat);
  59. intervalTime:= startTime + planInterval;
  60.  
  61. -- The table creation sql statement
  62. if not exists(select * from information_schema.tables where table_schema = schema_name AND table_name = fullTablename) then
  63. createStmts:='CREATE TABLE '||schema_name||'.'||fullTablename||' (
  64. CHECK ('||date_column||' >= '''||startTime||''' AND '||date_column||' < '''||intervalTime||''')
  65. ) INHERITS ('||schema_name||'.'||primary_table_name||')';
  66.  
  67. -- Run the table creation
  68. EXECUTE createStmts;
  69.  
  70. -- Set the table owner
  71. createStmts :='ALTER TABLE '||schema_name||'.'||fullTablename||' OWNER TO '||table_owner||';';
  72. EXECUTE createStmts;
  73.  
  74. -- Create an index on the timestamp
  75. createStmts:='CREATE INDEX idx_'||fullTablename||'_'||date_column||' ON '||schema_name||'.'||fullTablename||' ('||date_column||');';
  76. EXECUTE createStmts;
  77.  
  78. -- Track how many tables we are creating (should likely be 1, except for initial run and backfilling efforts).
  79. createdTables:=createdTables+1;
  80. end if;
  81.  
  82. -- Add case for this table to trigger creation sql statement.
  83. createTrigger:='( NEW.'||date_column||' >= TIMESTAMP '''||startTime||''' AND NEW.'||date_column||' < TIMESTAMP '''||intervalTime||''' ) THEN
  84. INSERT INTO '||schema_name||'.'||fullTablename||' VALUES (NEW.*); '||createTrigger;
  85.  
  86. startTime:=intervalTime;
  87.  
  88. if (startTime <= endTime)
  89. then
  90. createTrigger:='
  91. ELSEIF '||createTrigger;
  92. end if;
  93.  
  94. end loop;
  95.  
  96. -- CREATE UNKNOWN HOLDER IF IT DOES NOT EXIST, unknowns table handles possible
  97. -- inserts for which there is not an appropriate table partition
  98. -- This is often more desirable than simply raising an error.
  99. unknownTablename:=primary_table_name||'_unknowns';
  100. IF NOT EXISTS(SELECT * FROM information_schema.tables
  101. WHERE table_schema = schema_name
  102. AND table_name = unknownTablename)
  103. THEN
  104. createStmts :='CREATE TABLE '||schema_name||'.'||primary_table_name||'_unknowns (
  105. ) INHERITS ('||schema_name||'.'||primary_table_name||');';
  106.  
  107. -- Execute the unknown table creation
  108. EXECUTE createStmts;
  109.  
  110. -- Set the table owner
  111. createStmts:='ALTER TABLE '||schema_name||'.'||primary_table_name||'_unknowns OWNER TO '||table_owner||';';
  112. EXECUTE createStmts;
  113.  
  114. END IF;
  115.  
  116. -- Finish creating the trigger function (at the beginning).
  117. createTrigger:='CREATE OR REPLACE FUNCTION '||schema_name||'.'||primary_table_name||'_insert_trigger_function()
  118. RETURNS TRIGGER AS $$
  119. BEGIN
  120. IF '||createTrigger;
  121.  
  122. -- Run the trigger replacement;
  123. EXECUTE createTrigger;
  124.  
  125. -- Create the trigger that uses the trigger function, if it isn't already created
  126. triggerName:=primary_table_name||'_insert_trigger';
  127. if not exists(select * from information_schema.triggers where trigger_name = triggerName) then
  128. createTrigger:='CREATE TRIGGER '||primary_table_name||'_insert_trigger
  129. BEFORE INSERT ON '||schema_name||'.'||primary_table_name||'
  130. FOR EACH ROW EXECUTE PROCEDURE '||schema_name||'.'||primary_table_name||'_insert_trigger_function();';
  131. EXECUTE createTrigger;
  132. END if;
  133. return createdTables;
  134. END;
  135. $BODY$
  136. LANGUAGE 'plpgsql' VOLATILE
  137. COST 100;
  138. ALTER FUNCTION public.update_partitions(timestamp without time zone, text, text, text, text, text) OWNER TO postgres;
Add Comment
Please, Sign In to add comment