-- ============================================================
-- 自动分区与日志清理（幂等）
-- 1) 分区管理表 log_partition_tracker
-- 2) 存储过程 sp_ensure_partitions
-- 3) 存储过程 sp_check_partitions
-- 4) MariaDB 事件 ev_ensure_partitions
-- 注意：本脚本设计为幂等，重复执行不会重复创建分区
-- ============================================================

USE cnc_log;

-- 1. 分区追踪表
CREATE TABLE IF NOT EXISTS log_partition_tracker (
  table_name VARCHAR(100) NOT NULL,
  partition_name VARCHAR(50) NOT NULL,
  partition_value VARCHAR(30) NOT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (table_name, partition_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='分区管理追踪表';

-- 2. 自动分区存储过程
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_ensure_partitions$$
CREATE PROCEDURE sp_ensure_partitions()
BEGIN
  -- 当前月的第一天
  SET @base := DATE_FORMAT(CURDATE(), '%Y-%m-01');
  SET @d1 := DATE_ADD(@base, INTERVAL 1 MONTH);
  SET @d2 := DATE_ADD(@base, INTERVAL 2 MONTH);
  SET @p1 := CONCAT('p', DATE_FORMAT(@d1, '%Y%m'));
  SET @p2 := CONCAT('p', DATE_FORMAT(@d2, '%Y%m'));

  -- 对 log_collect_analysis 表分区
  IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
                 WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p1) THEN
    SET @dead1 := DATE_FORMAT(@d1, '%Y-%m-01');
    SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_analysis ADD PARTITION (PARTITION ', @p1,
                       ' VALUES LESS THAN (TO_DAYS(', '''', @dead1, '''', '))');
    PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
    INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_analysis', @p1, @dead1);
  END IF;

  IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
                 WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p2) THEN
    SET @dead2 := DATE_FORMAT(@d2, '%Y-%m-01');
    SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_analysis ADD PARTITION (PARTITION ', @p2,
                       ' VALUES LESS THAN (TO_DAYS(', '''', @dead2, '''', '))');
    PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
    INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_analysis', @p2, @dead2);
  END IF;

  -- 对 log_collect_cycle 表分区
  IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
                 WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p1) THEN
    SET @dead1 := DATE_FORMAT(@d1, '%Y-%m-01');
    SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_cycle ADD PARTITION (PARTITION ', @p1,
                       ' VALUES LESS THAN (TO_DAYS(', '''', @dead1, '''', '))');
    PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
    INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_cycle', @p1, @dead1);
  END IF;

  IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
                 WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p2) THEN
    SET @dead2 := DATE_FORMAT(@d2, '%Y-%m-01');
    SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_cycle ADD PARTITION (PARTITION ', @p2,
                       ' VALUES LESS THAN (TO_DAYS(', '''', @dead2, '''', '))');
    PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
    INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_cycle', @p2, @dead2);
  END IF;
END$$
DELIMITER ;

-- 3. 分区检查存储过程
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_check_partitions$$
CREATE PROCEDURE sp_check_partitions()
BEGIN
  -- 计算未来两月分区名是否存在
  SET @base := DATE_FORMAT(CURDATE(), '%Y-%m-01');
  SET @d1 := DATE_ADD(@base, INTERVAL 1 MONTH);
  SET @d2 := DATE_ADD(@base, INTERVAL 2 MONTH);
  SET @p1 := CONCAT('p', DATE_FORMAT(@d1, '%Y%m'));
  SET @p2 := CONCAT('p', DATE_FORMAT(@d2, '%Y%m'));

  SET @need := 0;
  IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p1) = 0 THEN SET @need = 1; END IF;
  IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p1) = 0 THEN SET @need = 1; END IF;
  IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p2) = 0 THEN SET @need = 1; END IF;
  IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p2) = 0 THEN SET @need = 1; END IF;

  IF @need = 1 THEN
    CALL sp_ensure_partitions();
  END IF;

  SELECT @need AS need_partition_creation;
END$$
DELIMITER ;

-- 4. MariaDB 事件：每月1日凌晨2:00执行 sp_check_partitions
SET GLOBAL event_scheduler = ON;
DROP EVENT IF EXISTS ev_ensure_partitions;
CREATE EVENT IF NOT EXISTS ev_ensure_partitions
ON SCHEDULE
  EVERY 1 MONTH
STARTS TIMESTAMP '2026-06-01 02:00:00'
DO
  CALL sp_check_partitions();
