Postgresql 减少伪加密函数ouput的长度
我有一个关于你的问题。 有没有办法把输出量减少到6?我真的很喜欢这个函数,并想使用它,但只需要输出介于1和999999之间 这个问题涉及到。我想用它来创建介于1和999999之间的unqiue数字 谢谢。使用生成的值生成从Postgresql 减少伪加密函数ouput的长度,postgresql,Postgresql,我有一个关于你的问题。 有没有办法把输出量减少到6?我真的很喜欢这个函数,并想使用它,但只需要输出介于1和999999之间 这个问题涉及到。我想用它来创建介于1和999999之间的unqiue数字 谢谢。使用生成的值生成从开始\u值到结束\u值范围内的数字: select start_value + mod(pseudo_encrypt(number), end_value - start_value + 1); 对于您的情况,这将如下所示: select 1 + mod(pseudo_enc
开始\u值
到结束\u值
范围内的数字:
select start_value + mod(pseudo_encrypt(number), end_value - start_value + 1);
对于您的情况,这将如下所示:
select 1 + mod(pseudo_encrypt(23452), 999999);
设定9999999的上限并不十分简单,因为该算法是在比特块上运行的,所以很难摆脱二的幂 您可以通过以下方法解决此问题:只需尝试
encrypt(n)
,encrypt(n))
,encrypt(encrypt(n))
。。。直到结果在[1999999]范围内为止。为了将迭代次数保持在最小,您需要调整块大小,使其尽可能接近此范围
此版本将允许您指定输入/输出的范围:
CREATE OR REPLACE FUNCTION pseudo_encrypt(
value INT8,
min INT8 DEFAULT 0,
max INT8 DEFAULT (2^62::NUMERIC)-1
) RETURNS INT8 AS
$$
DECLARE
rounds CONSTANT INT = 3;
L INT8[];
R INT8[];
i INT;
blocksize INT;
blockmask INT8;
result INT8;
BEGIN
max = max - min;
value = value - min;
IF NOT ((value BETWEEN 0 AND max) AND (max BETWEEN 0 AND 2^62::NUMERIC-1)) THEN
RAISE 'Input out of range';
END IF;
blocksize = ceil(char_length(ltrim(max::BIT(64)::TEXT,'0'))/2.0);
blockmask = (2^blocksize::NUMERIC-1)::INT8;
result = value;
LOOP
L[1] = (result >> blocksize) & blockmask;
R[1] = result & blockmask;
FOR i IN 1..rounds LOOP
L[i+1] = R[i];
R[i+1] = L[i] # ((941083981*R[i] + 768614336404564651) & blockmask);
END LOOP;
result = (L[rounds]::INT8 << blocksize) | R[rounds];
IF result <= max THEN
RETURN result + min;
END IF;
END LOOP;
END;
$$
LANGUAGE plpgsql STRICT IMMUTABLE;
回答很好,但是当我使用这个选择时,我又遇到了一个独特的问题。很难用9999999条目来测试它,但是当我用例如99来测试它时。我又遇到了unqiue验证问题。
SELECT i FROM generate_series(1,999999) s(i)
EXCEPT
SELECT pseudo_encrypt(i,1,999999) FROM generate_series(1,999999) s(i)