I have a mysql database where everywhere id (Primary Key) is ulid. The problem is that it is stored as VARCHAR(255). I want to correct it (change to binary) the following way:
The problem is transforming the ulid stored as VARCHAR(255) in utf8mb3 charset to binary. I have tried the following function:
DELIMITER //
-- The input is of type CHAR(26) for simplicity as converting varchar(255) to char(26) does not seem to be a problem, the problem is converting it further to binary
CREATE FUNCTION ConvertULIDToBinary(ulid CHAR(26) CHARACTER SET utf8mb3)
RETURNS BINARY(16)
DETERMINISTIC
BEGIN
DECLARE result BINARY(16);
SET result = UNHEX(CONCAT(
LPAD(CONV(SUBSTRING(ulid, 1, 6), 36, 16), 10, '0'),
LPAD(CONV(SUBSTRING(ulid, 7, 6), 36, 16), 10, '0'),
LPAD(CONV(SUBSTRING(ulid, 13, 6), 36, 16), 10, '0'),
LPAD(CONV(SUBSTRING(ulid, 19, 8), 36, 16), 16, '0')
));
RETURN result;
END //
DELIMITER ;
But if I run it, I get the following error:
SQL Error (1406) in statement #3: Data too long for column 'result' at row 1
Try the following function:
delimiter //
DROP FUNCTION IF EXISTS ULID_DECODE//
CREATE FUNCTION ULID_DECODE (s CHAR(26)) RETURNS BINARY(16) DETERMINISTIC
BEGIN
DECLARE s_base32 CHAR(26);
SET s_base32 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(UPPER(s), 'J', 'I'), 'K', 'J'), 'M', 'K'), 'N', 'L'), 'P', 'M'), 'Q', 'N'), 'R', 'O'), 'S', 'P'), 'T', 'Q'), 'V', 'R'), 'W', 'S'), 'X', 'T'), 'Y', 'U'), 'Z', 'V');
RETURN UNHEX(CONCAT(LPAD(CONV(SUBSTRING(s_base32, 1, 2), 32, 16), 2, '0'), LPAD(CONV(SUBSTRING(s_base32, 3, 12), 32, 16), 15, '0'), LPAD(CONV(SUBSTRING(s_base32, 15, 12), 32, 16), 15, '0')));
END//
delimiter ;