SELECT ... INTO variable results in NULL or idk
So, the ultimate answer to my own question is, as follows.

The stored procedures on MySQL version 5.6.13 don't like, when you use local variables and procedure parameters named exactly as the column names returned by queries used in the procedure's body - even though I used backticks in the queries. Documentation on the use of backticks in MySQL queries.

I have made some changes in the logic of the procedure, as it was not working as I expected. But after renaming the following variables the code did not throw any exceptions, at all.


user_id -> usr_id
points -> to_spend
to_spend -> cur_pts


The edited code:


DELIMITER $$

DROP PROCEDURE IF EXISTS `user_spends_points`$$
CREATE DEFINER=`a30267_palivo`@`%` PROCEDURE `user_spends_points`(IN `usr_id` INT UNSIGNED, IN `to_spend` MEDIUMINT UNSIGNED)
BEGIN
    DECLARE done BOOLEAN DEFAULT FALSE;
    DECLARE cur_pts MEDIUMINT UNSIGNED DEFAULT 0;
    DECLARE v_id INT UNSIGNED;
    DECLARE loc_points MEDIUMINT UNSIGNED;
    DECLARE loc_spent MEDIUMINT UNSIGNED;
    DECLARE cur CURSOR FOR SELECT `id`, `points`, `spent` FROM `smartfuel_activities` WHERE `user_id` = usr_id AND `expired` = 0 AND `points` &lt;&gt; `spent` ORDER BY `created_at` ASC;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;
        CALL `log`("handler", "SQLEXCEPTION");
        CALL `log`("to_spend", CAST(cur_pts as CHAR(5)));
        RESIGNAL;
    END;
    DECLARE EXIT HANDLER FOR SQLSTATE '45000'
    BEGIN
        ROLLBACK;
        CALL `log`("handler", "SQLSTATE");
        CALL `log`("to_spend", CAST(cur_pts as CHAR(5)));
        CALL `log`("user_id", CAST(usr_id as CHAR(5)));
        CALL `log`("points", CAST(to_spend as CHAR(5)));
        RESIGNAL;
    END;
    DECLARE CONTINUE HANDLER FOR NOT FOUND
    BEGIN
        SET done:= TRUE;
        CALL `log`("handler", "NOT FOUND");
        CALL `log`("to_spend", CAST(cur_pts as CHAR(5)));
        CALL `log`("user_id", CAST(usr_id as CHAR(5)));
        CALL `log`("points", CAST(to_spend as CHAR(5)));
    END;

    START TRANSACTION;
    SELECT `current_points` INTO cur_pts FROM `smartfuel_users` WHERE `id` = usr_id;

    IF cur_pts &gt; to_spend THEN    
        OPEN cur;

        userPointsLoop: LOOP
            FETCH cur INTO v_id, loc_points, loc_spent;
            IF done THEN
                LEAVE userPointsLoop;
            END IF;

            IF to_spend &gt; 0 THEN
                IF (loc_points - loc_spent) &gt; to_spend THEN
                    UPDATE `smartfuel_activities` SET `spent` = loc_spent + to_spend WHERE `id` = v_id;
                    SET to_spend = 0;
                    LEAVE userPointsLoop;
                ELSE
                    UPDATE `smartfuel_activities` SET `spent` = loc_points WHERE `id` = v_id;
                    SET to_spend = to_spend - (loc_points - loc_spent);
                END IF;
            ELSE
                LEAVE userPointsLoop;
            END IF;
        END LOOP userPointsLoop;

        CLOSE cur;
    ELSE
        SIGNAL SQLSTATE '45000'
            SET MESSAGE_TEXT = 'Not enough points to complete expenditure', MYSQL_ERRNO = 1000;
    END IF;

    COMMIT;
END$$

DELIMITER ;