PostgreSQLで次のことをする方法はあるのだろうかと思っていました:
UPDATE cryptotable SET work = work + 'some big hexadecimal number'
ここで、workは符号なし256ビットの数値です。現在、私の列は文字の変化する(64)列(16進表記)ですが、上記の操作を実行できる場合は、別のデータ型に切り替えてもかまいません。
Vanilla PostgreSQLではそれができない場合、私に役立つ拡張機能はありますか?
(私も これをpgsql-hackersに投稿しました ですので、そこにあるスレッドで詳細を確認してください。)
結局、提案されているようにnumeric
型を使用し、アプリケーションコードで16進数/数値の変換を行っただけです。
pg-bignum
_ を使用する_pg-bignum
_ライブラリはあなたが望むことをします。私はただ 16進入力を受け入れるようにパッチを当てました。
ライブラリをダウンロードします。走る
_make
Sudo make install
_
今、実行します
_CREATE EXTENSION bignum;
_
今、あなたはこのような256ビットの数を取ることができます
_59 51 a1 20 2e 65 62 26 ab f3 af e6 93 16 db 1c
3b 37 24 47 75 32 72 95 79 e9 d7 fa 38 12 c0 0e
_
そして、それをbn_hex_in()
にフィードします。
_SELECT bn_in_hex('5951a1202e656226abf3afe69316db1c3b3724477532729579e9d7fa3812c00e');
bn_in_hex
-------------------------------------------------------------------------------
40400070184923956455012790534029088594440775740385060328118871212830923866126
(1 row)
_
数値はかなり大きい ドキュメントから
数値は、余分な先頭または末尾のゼロなしで物理的に保存されます。したがって、列の宣言された精度とスケールは最大であり、固定割り当てではありません。 (この意味で、数値タイプはchar(n)よりもvarchar(n)に似ています。)実際のストレージ要件は、4桁の10進数のグループごとに2バイトと、3〜8バイトのオーバーヘッドです。
上記の数値の例は46バイトです(_::text::numeric
_で確認できます)。bignumは36です。
非常に大きな16進数を数値型に変換するという根本的な質問に対する適切な答えを見つけることができなかったので、それが数年遅れたとしても、これが私の代替的なアプローチです。
CREATE FUNCTION hex2numeric(hex TEXT)
RETURNS NUMERIC AS $$
DECLARE
nibble RECORD;
decimal_digit NUMERIC;
result NUMERIC := 0;
BEGIN
-- Loop through each hexadecimal digit, starting from the right
FOR nibble IN (SELECT (n - 1) AS position, SUBSTRING(REVERSE(hex) FROM n FOR 1) AS digit FROM generate_series(1, length( hex ), 1) n) LOOP
-- get the decimal representation of the hex digit
decimal_digit := ('x' || nibble.digit)::BIT(4)::INT::NUMERIC;
-- multiply the digit by the nth power of 16 and add to the result
result := result + (decimal_digit * (16::NUMERIC^nibble.position::NUMERIC));
END LOOP;
RETURN result;
END
$$ LANGUAGE plpgsql IMMUTABLE;
使用法(例:512ビットの16進数):
psql=# select hex2numeric('87783308B813E3B4FB3271534D844EE8FDBDF302273B3E3D5CB3BF6E0117F45DBAFE1AD7D30FA91CE7F0D33C7E877CA544D1770E7AD4F37691426E89806CB48B')::NUMERIC(156,0);
hex2numeric
------------------------------------------------------------------------------------------------------------------------------------------------------------
7095114927382653019461910892845641210567311772867384729122528908252679853572077146666940749408552370045395041242349820090839313239920717104090735323165835
(1 row)
それが桁ごとに行われていることを考えると、それはおそらくあまりパフォーマンスが高くありませんが、私のユースケースでは仕事を完了します。
これは、16進数を10進数に変換するための here で説明されている方法の拡張であり、- here で説明されている16進数を変換および合計するアルゴリズムです。