Search code examples
mysqluuidstored-functions

"Incorrect string value" in MySQL user function


I need this function to work in MySQL; I've been trying for a few hours but without results.

DELIMITER //
CREATE FUNCTION `generateGUID`(
    `playerid` BIGINT
) RETURNS text CHARSET utf8
    READS SQL DATA
BEGIN

DECLARE temp text;
DECLARE i int UNSIGNED;

SET temp = '';
SET i = 0;

WHILE i < 8 DO
    SET temp = CONCAT(temp, CHAR(playerid & 0xFF));
    SET playerid = playerid >> 8;
    SET i = i + 1;
END WHILE;

SET temp = MD5(CONCAT("BE", temp));

RETURN temp;

END//
DELIMITER ;

It's a function that gets a number (a Steam ID) and returns a converted string.

The function is from a github repo, but it's old and it seems that the author is not updating it.

I get:

Error de SQL (1366): Incorrect string value: '\x97' for column 'temp' at row 1

Solution

  • What does this function do? It apparently calculates the BattlEye ID:

    md5("BE" (2 bytes) + 64-bit SteamID (8 bytes))
    

    Where...

    WHILE i < 8 DO
        SET temp = CONCAT(temp, CHAR(playerid & 0xFF));
        SET playerid = playerid >> 8;
        SET i = i + 1;
    END WHILE;
    

    ...the first piece taken is the least significant byte, and it ends up at the beginning of the string. So the number is "little endian".

    And this becomes the GUID.

    We can rebuild him. We have the technology.

    A function that generates binary data is UNHEX, and we must feed to it a 16-character sequence padded with zeroes. LPAD is our friend. Then the number is little endian, and we must then employ REVERSE. The rest follows.

    Note that you don't need the function at all, just the core (the object returned).

    DROP FUNCTION generateGUID;
    
    DELIMITER //
    CREATE FUNCTION `generateGUID`(
        `playerid` BIGINT
    ) RETURNS text CHARSET utf8
        READS SQL DATA
    BEGIN
    
    RETURN  MD5(
      CONCAT(
        'BE',
        REVERSE(
          UNHEX(
            LPAD(
              HEX(playerid),
              16,
              '0'
            )
          )
        )
      )
    );
    
    END//
    DELIMITER ;
    

    And the test:

    select generateGUID(76532298015716211) -- found on an online generator
    

    returns f276e058bbaaff85d23070c9bd43e2aa as expected.