-- A5M2で実行時に[SQL] - [スラッシュ(/)のみの行でSQLを区切る]に変えてから実行する
-- $$から始まり$$で終わる文字は後からREPLACEする文字を示す独自ルール
-- crm_historyストアドプロシージャは、同一セッション内での並列処理を実行することができない
-- 実行者の権限でストアドプロシージャを実行するために、「SQL SECURITY INVOKER」を付与している
CREATE PROCEDURE src02.crm_history(target_table VARCHAR(255), target_column VARCHAR(255))
SQL SECURITY INVOKER
BEGIN
	-- 例外処理
	-- エラーが発生した場合に一時テーブルの削除を実施
	DECLARE EXIT HANDLER FOR SQLEXCEPTION 
		BEGIN
			GET DIAGNOSTICS CONDITION 1
				@error_state = RETURNED_SQLSTATE, @error_msg = MESSAGE_TEXT;
			EXECUTE drop_tmp_table_stmt;
			DEALLOCATE PREPARE drop_tmp_table_stmt;
			ROLLBACK;
			SIGNAL SQLSTATE '45000'
				SET MYSQL_ERRNO = @error_state, MESSAGE_TEXT = @error_msg;
		END;

	SET @error_state = NULL, @error_msg = NULL;
	START TRANSACTION;

	-- ②-3で利用する一時テーブル削除のSQLを準備
	-- 例外処理でも利用するため先に記述
	SET @drop_tmp_table = '
		DROP TEMPORARY TABLE IF EXISTS $$target_table$$_make_history_tmp
	';
	SET @drop_tmp_table = REPLACE(@drop_tmp_table, "$$target_table$$", target_table);
	PREPARE drop_tmp_table_stmt from @drop_tmp_table;
	
	-- ①-1 Salesforce側で更新されたデータの適用開始日時と適用終了日時を設定する
	SET @new_history_save = '
		UPDATE $$target_table$$ 
		SET
			start_datetime = $$target_column$$
			, end_datetime = "9999-12-31 00:00:00"
			, upd_user = CURRENT_USER() 
			, upd_date = CURRENT_TIMESTAMP()
		WHERE
			start_datetime IS NULL 
			AND end_datetime IS NULL
	';
	SET @new_history_save = REPLACE(@new_history_save, "$$target_table$$", target_table);
	SET @new_history_save = REPLACE(@new_history_save, "$$target_column$$", target_column);
	PREPARE new_history_save_stmt from @new_history_save;
	EXECUTE new_history_save_stmt;
	DEALLOCATE PREPARE new_history_save_stmt;

	-- ②-1 Salesforce側で更新されたデータを検出用一時テーブルの作成
	SET @make_history_tmp_create = '
		CREATE TEMPORARY TABLE $$target_table$$_make_history_tmp 
		SELECT
			Id
			, MIN($$target_column$$) AS min_start_datetime
			, MAX(start_datetime) AS max_start_datetime 
		FROM
			$$target_table$$ 
		WHERE
			end_datetime = "9999-12-31 00:00:00" 
		GROUP BY
			Id 
		HAVING
			count(Id) = 2
	';
	SET @make_history_tmp_create = REPLACE(@make_history_tmp_create, "$$target_table$$", target_table);
	SET @make_history_tmp_create = REPLACE(@make_history_tmp_create, "$$target_column$$", target_column);
	PREPARE make_history_tmp_create_stmt from @make_history_tmp_create;
	EXECUTE make_history_tmp_create_stmt;
	DEALLOCATE PREPARE make_history_tmp_create_stmt;

	-- ②-2 「②-1」で取得した全件に更新処理を行う
	SET @update_end_datetime = '
		UPDATE $$target_table$$ tt 
			INNER JOIN $$target_table$$_make_history_tmp mht 
				ON tt.Id = mht.Id 
				AND tt.start_datetime = mht.min_start_datetime 
		SET
			end_datetime = mht.max_start_datetime - INTERVAL 1 SECOND 
			, upd_user = CURRENT_USER() 
			, upd_date = CURRENT_TIMESTAMP()
	';
	SET @update_end_datetime = REPLACE(@update_end_datetime, "$$target_table$$", target_table);
	SET @update_end_datetime = REPLACE(@update_end_datetime, "$$target_column$$", target_column);
	PREPARE update_end_datetime_stmt from @update_end_datetime;
	EXECUTE update_end_datetime_stmt;
	DEALLOCATE PREPARE update_end_datetime_stmt;

	-- ②-3 「②-1」で作成した一時テーブルを削除する
	EXECUTE drop_tmp_table_stmt;
	DEALLOCATE PREPARE drop_tmp_table_stmt;

	COMMIT;

END
