For a project that I’m working on I had to create MAC generator. Initially I decided that I will do it in BASH.
function gen_mac() {
mac_vars=(0 1 2 3 4 5 6 7 8 9 a b c d e f)
mac_base='52:53:54:'
ret=''
for i in {1..6}; do
n=$RANDOM
let 'n %= 16'
ret="${ret}${mac_vars[$n]}"
if [ $i -eq 2 ] || [ $i -eq 4 ]; then
ret="${ret}:"
fi
done
echo "${mac_base}${ret}"
}
But unfortunately I had to rewrite it in plpgsql in order to prevent a stupid race condition that can appear.
CREATE OR REPLACE FUNCTION generate_mac() RETURNS text
LANGUAGE plpgsql
AS $$DECLARE
mac TEXT;
a CHAR;
count INTEGER;
BEGIN
mac='52:53:54:';
FOR count IN 1..6 LOOP
SELECT substring('0123456789abcdef' FROM (random()*16)::int + 1 FOR 1) INTO a;
-- This fixes un issue, wehre the above SELECT returns NULL or empty string
-- If for some reason we concatenate with a NULL string, the result will be NULL string
WHILE a IS NULL OR a = '' LOOP
SELECT substring('0123456789abcdef' FROM (random()*16)::int + 1 FOR 1) INTO a;
END LOOP;
mac = mac || a;
IF count = 2 OR count = 4 THEN
mac = mac || ':';
END IF;
END LOOP;
RETURN mac;
END;$$;