Postgres:如何通过每 4 个字节进行异或运算将 16 个字节转换为 4 个字节

Postgres: How to convert 16 bytes into 4 bytes by XOR-ing every 4 bytes

我有一个 16 字节的 md5 散列,我需要使用 XOR "fold" 将其转换为 4 字节数据:{1st 4 bytes} XOR {2nd 4 bytes} XOR {3rd 4 bytes} XOR {4th 4 字节}。然后我需要将结果转换为十六进制形式(8 字符字符串)。

我正在这样生成我的散列(解码为十六进制,因为它看起来更容易处理):

SELECT decode(md5('test'), 'hex');

但这就是我得到的。我不知道将 16 字节哈希拆分为 4 个 4 字节值,然后对这些 4 字节值进行异或运算的最佳方法。

不幸的是 docs are a bit vague about what you could do with a bit string value, but mentions the substring function (sytax is on the string functions page),可用于从中提取部分:

select i1 # i2 # i3 # i4
from   cast('x' || md5('test') as bit(128)) bits,
       cast(substring(bits from 97 for 32) as int4) i1,
       cast(substring(bits from 65 for 32) as int4) i2,
       cast(substring(bits from 33 for 32) as int4) i3,
       cast(substring(bits from  1 for 32) as int4) i4

注意:较低的位在其位串表示中具有较高的索引,f.ex。

select 3::bit(32)
-- will yield '00000000000000000000000000000011'

在花了一些时间了解 this 答案后,我得出了这个结论:

CREATE OR REPLACE FUNCTION compressed_md5(var_txt TEXT) RETURNS TEXT
AS $$
DECLARE
  var_hash BYTEA;
  var_compressedHash BYTEA;
  var_offset INTEGER;
BEGIN
  var_hash := decode(md5(var_txt), 'hex');
  var_compressedHash := decode('00000000', 'hex'); -- prepopulate with some 4-byte data
  FOR var_offset IN 0..3 LOOP
    var_compressedHash := set_byte(var_compressedHash, var_offset,
                                   get_byte(var_hash, var_offset) #
                                   get_byte(var_hash, var_offset + 4) #
                                   get_byte(var_hash, var_offset + 8) #
                                   get_byte(var_hash, var_offset + 12));
  END LOOP;
  RETURN encode(var_compressedHash, 'hex');
END;
$$ LANGUAGE plpgsql;

SELECT compressed_md5('test');

结果:

"a35742cb"