Guest User

Untitled

a guest
Feb 23rd, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.87 KB | None | 0 0
  1. CREATE OR REPLACE FUNCTION check_value_in_bounds(v int, min_v int, max_v int) RETURNS void AS $$
  2. -- Checks if v is in bounds, else throws exception
  3. BEGIN
  4. IF v > max_v THEN
  5. RAISE EXCEPTION 'value too high: % > %', v, max_v;
  6. END IF;
  7.  
  8. IF min_v > v THEN
  9. RAISE EXCEPTION 'value too low: % < %', v, min_v;
  10. END IF;
  11. END;
  12. $$ LANGUAGE plpgsql;
  13.  
  14.  
  15. CREATE OR REPLACE FUNCTION parse_cron_part(cron_part text, min_v int, max_v int) RETURNS int[] AS $$
  16. -- parses one part of crontab string and checks values to be in bounds
  17. DECLARE
  18. result int[];
  19. draft_result int[];
  20. parts text[];
  21. part text;
  22. BEGIN
  23. IF cron_part = '*' THEN
  24. RETURN result;
  25. END IF;
  26.  
  27. IF strpos(cron_part, ',') > 0 THEN
  28. FOREACH part IN ARRAY string_to_array(cron_part, ',') LOOP
  29. result := result || parse_cron_part(part, min_v, max_v);
  30. END LOOP;
  31.  
  32. RETURN result;
  33. END IF;
  34.  
  35. IF strpos(cron_part, '-') > 0 THEN
  36. parts := string_to_array(cron_part, '-');
  37. PERFORM check_value_in_bounds(parts[1]::int, min_v, max_v);
  38. PERFORM check_value_in_bounds(parts[2]::int, min_v, max_v);
  39. result := ARRAY(SELECT generate_series(parts[1]::int, parts[2]::int));
  40. RETURN result;
  41. END IF;
  42.  
  43. IF strpos(cron_part, '/') > 0 THEN
  44. parts := string_to_array(cron_part, '/');
  45. IF parts[1] <> '*' THEN
  46. PERFORM check_value_in_bounds(parts[1]::int, min_v, max_v);
  47. END IF;
  48. PERFORM check_value_in_bounds(parts[2]::int, min_v, max_v);
  49.  
  50. draft_result := ARRAY(SELECT generate_series(min_v, max_v));
  51. FOR i IN 1..cardinality(draft_result) LOOP
  52. IF draft_result[i] % parts[2]::int = 0 THEN
  53. IF parts[1] <> '*' THEN
  54. result := result || (draft_result[i] + parts[1]::int);
  55. ELSE
  56. result := result || draft_result[i];
  57. END IF;
  58. END IF;
  59. END LOOP;
  60.  
  61. RETURN result;
  62. END IF;
  63.  
  64. PERFORM check_value_in_bounds(cron_part::int, min_v, max_v);
  65.  
  66. RETURN ARRAY[cron_part::int];
  67. END;
  68. $$ LANGUAGE plpgsql;
  69.  
  70.  
  71. CREATE OR REPLACE FUNCTION date_matches_crontab(crontab text, dt timestamp) RETURNS boolean AS $$
  72. -- matches date to given crontab string
  73. DECLARE
  74. parts text[];
  75. seconds int[];
  76. minutes int[];
  77. hours int[];
  78. days int[];
  79. months int[];
  80. dows int[];
  81. years int[];
  82. i int;
  83. BEGIN
  84. parts := string_to_array(crontab, ' ');
  85.  
  86. IF cardinality(parts) <> 7 THEN
  87. RAISE EXCEPTION 'Crontab string must consist of 7 parts (s, m, h, d, m, dow, year)';
  88. END IF;
  89.  
  90. seconds := parse_cron_part(parts[1], 0, 59);
  91. minutes := parse_cron_part(parts[2], 0, 59);
  92. hours := parse_cron_part(parts[3], 0, 23);
  93. days := parse_cron_part(parts[4], 1, 31);
  94. months := parse_cron_part(parts[5], 1, 12);
  95. dows := parse_cron_part(parts[6], 0, 7);
  96. years := parse_cron_part(parts[7], 0, 9999);
  97.  
  98. IF cardinality(dows) > 0 THEN
  99. FOR i IN 1..cardinality(dows) LOOP
  100. dows[i] := dows[i] % 7;
  101. END LOOP;
  102. END IF;
  103.  
  104. IF not(cardinality(seconds) > 0 AND trunc(EXTRACT(second FROM dt)) = ANY(seconds)) THEN
  105. RETURN false;
  106. END IF;
  107.  
  108. IF not(cardinality(minutes) > 0 AND EXTRACT(minute FROM dt) = ANY(minutes)) THEN
  109. RETURN false;
  110. END IF;
  111.  
  112. IF not(cardinality(hours) > 0 AND EXTRACT(hour FROM dt) = ANY(hours)) THEN
  113. RETURN false;
  114. END IF;
  115.  
  116. IF not(cardinality(days) > 0 AND EXTRACT(day FROM dt) = ANY(days)) THEN
  117. RETURN false;
  118. END IF;
  119.  
  120. IF not(cardinality(months) > 0 AND EXTRACT(month FROM dt) = ANY(months)) THEN
  121. RETURN false;
  122. END IF;
  123.  
  124. IF not(cardinality(dows) > 0 AND EXTRACT(dow FROM dt) = ANY(dows)) THEN
  125. RETURN false;
  126. END IF;
  127.  
  128. IF not(cardinality(years) > 0 AND EXTRACT(year FROM dt) = ANY(years)) THEN
  129. RETURN false;
  130. END IF;
  131.  
  132. RETURN true;
  133. END;
  134. $$ LANGUAGE plpgsql;
Add Comment
Please, Sign In to add comment