035_usage_logs_partitioning.sql 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. -- usage_logs monthly partition bootstrap.
  2. -- Only creates partitions when usage_logs is already partitioned.
  3. -- Converting usage_logs to a partitioned table requires a manual migration plan.
  4. DO $$
  5. DECLARE
  6. is_partitioned BOOLEAN := FALSE;
  7. has_data BOOLEAN := FALSE;
  8. month_start DATE;
  9. prev_month DATE;
  10. next_month DATE;
  11. BEGIN
  12. SELECT EXISTS(
  13. SELECT 1
  14. FROM pg_partitioned_table pt
  15. JOIN pg_class c ON c.oid = pt.partrelid
  16. WHERE c.relname = 'usage_logs'
  17. ) INTO is_partitioned;
  18. IF NOT is_partitioned THEN
  19. SELECT EXISTS(SELECT 1 FROM usage_logs LIMIT 1) INTO has_data;
  20. IF NOT has_data THEN
  21. -- Automatic conversion is intentionally skipped; see manual migration plan.
  22. RAISE NOTICE 'usage_logs is not partitioned; skip automatic partitioning';
  23. END IF;
  24. END IF;
  25. IF is_partitioned THEN
  26. month_start := date_trunc('month', now() AT TIME ZONE 'UTC')::date;
  27. prev_month := (month_start - INTERVAL '1 month')::date;
  28. next_month := (month_start + INTERVAL '1 month')::date;
  29. EXECUTE format(
  30. 'CREATE TABLE IF NOT EXISTS usage_logs_%s PARTITION OF usage_logs FOR VALUES FROM (%L) TO (%L)',
  31. to_char(prev_month, 'YYYYMM'),
  32. prev_month,
  33. month_start
  34. );
  35. EXECUTE format(
  36. 'CREATE TABLE IF NOT EXISTS usage_logs_%s PARTITION OF usage_logs FOR VALUES FROM (%L) TO (%L)',
  37. to_char(month_start, 'YYYYMM'),
  38. month_start,
  39. next_month
  40. );
  41. EXECUTE format(
  42. 'CREATE TABLE IF NOT EXISTS usage_logs_%s PARTITION OF usage_logs FOR VALUES FROM (%L) TO (%L)',
  43. to_char(next_month, 'YYYYMM'),
  44. next_month,
  45. (next_month + INTERVAL '1 month')::date
  46. );
  47. END IF;
  48. END $$;