If I run this stored procedure as is, it gives incorrect return value, and when I examine my log, it never logs the else condition:
CREATE DEFINER=`root`@`localhost` PROCEDURE `rpt_PlayerOnlineTime`(IN ucid VARCHAR(128), INOUT totaltime INT)
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_event varchar(20) DEFAULT "";
DECLARE v_time BIGINT DEFAULT 0;
DECLARE v_server_id INT DEFAULT 0;
DECLARE v_session_id INT DEFAULT 0;
DECLARE v_start BIGINT DEFAULT 0;
DECLARE v_end BIGINT;
DEClARE con_cursor CURSOR FOR
SELECT type, real_time, server_id, session_id FROM ki.raw_connection_log WHERE player_ucid = ucid;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime: ", totaltime));
OPEN con_cursor;
online_time: LOOP
CALL ki.log("rpt_PlayerOnlineTime", "In Loop");
FETCH con_cursor INTO v_event, v_time, v_server_id, v_session_id;
IF v_finished = 1 THEN
CALL ki.log("rpt_PlayerOnlineTime", "Finished Loop");
LEAVE online_time;
END IF;
IF v_event = "CONNECTED" THEN
IF v_start != 0 then
CALL ki.log("rpt_PlayerOnlineTime", "CONNECTED EVENT TWICE IN A ROW");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_server_id - ", v_server_id));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_session_id - ", v_session_id));
-- If the next event is not a disconnect event, assume that the player or server crashed, and get the time from the session
SELECT session.real_time_end INTO v_end FROM ki.session WHERE server_id = v_server_id AND session_id = v_session_id;
IF v_end IS NOT NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end TO SESSION END TIME");
ELSE
SELECT session.last_heartbeat INTO v_end FROM ki.session WHERE session.server_id = v_server_id AND session.session_id = v_session_id;
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end To Last HeartBeat Received from session");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime : ", totaltime));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_start : ", v_start));
IF v_end IS NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "Last Heartbeat is NULL - defaulting to start");
SET v_end = v_start; -- if the last_heartbeat is null, then assume there was no end date
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_end : ", v_end));
END IF;
SET totaltime = totaltime + (v_end - v_start);
END IF;
SET v_start = v_time;
ELSEIF v_event = "DISCONNECTED" THEN
CALL ki.log("rpt_PlayerOnlineTime", "DISCONNECTED EVENT - CALCULATING END TIME");
SET totaltime = totaltime + (v_time - v_start);
SET v_start = 0;
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("IN LOOP: Total Time: ", totaltime));
END LOOP online_time;
CLOSE con_cursor;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("Total Time: ", totaltime));
END
The problem is here in this section of code - v_end may be NULL, but using the current if statement it never is true (I never see the else information logged)
-- If the next event is not a disconnect event, assume that the player or server crashed, and get the time from the session
SELECT session.real_time_end INTO v_end FROM ki.session WHERE server_id = v_server_id AND session_id = v_session_id;
IF v_end IS NOT NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end TO SESSION END TIME");
ELSE
SELECT session.last_heartbeat INTO v_end FROM ki.session WHERE session.server_id = v_server_id AND session.session_id = v_session_id;
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end To Last HeartBeat Received from session");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime : ", totaltime));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_start : ", v_start));
IF v_end IS NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "Last Heartbeat is NULL - defaulting to start");
SET v_end = v_start; -- if the last_heartbeat is null, then assume there was no end date
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_end : ", v_end));
END IF;
However, if I modify the if statement to use != NULL, it works.
-- If the next event is not a disconnect event, assume that the player or server crashed, and get the time from the session
SELECT session.real_time_end INTO v_end FROM ki.session WHERE server_id = v_server_id AND session_id = v_session_id;
IF v_end != NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end TO SESSION END TIME");
ELSE
SELECT session.last_heartbeat INTO v_end FROM ki.session WHERE session.server_id = v_server_id AND session.session_id = v_session_id;
CALL ki.log("rpt_PlayerOnlineTime", "SETTING v_end To Last HeartBeat Received from session");
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("totaltime : ", totaltime));
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_start : ", v_start));
IF v_end IS NULL THEN
CALL ki.log("rpt_PlayerOnlineTime", "Last Heartbeat is NULL - defaulting to start");
SET v_end = v_start; -- if the last_heartbeat is null, then assume there was no end date
END IF;
CALL ki.log("rpt_PlayerOnlineTime", CONCAT("v_end : ", v_end));
END IF;
Why does MySQL work this way? I was looking at other stackoverflow posts about the proper way to check if a variable is null, and they recommend using IS NOT NULL instead of != NULL.
How to check if a variable is NULL, then set it with a MySQL stored procedure?
I'm using MySql 5.7.20 - is this a bug in MySql?