10

私たちのソフトウェア プロジェクトの 1 つは、バイトタイプの列「guid」を持つ PostgreSQL テーブルを使用します。

これは、PostgreSQL 8.4 の hibernate 3.3.2.GA で使用されます。これは、 Java オブジェクトのシリアライゼーションを使用して Java UUID タイプをシリアライズします。結果は、次のescape形式の bytea リテラルのような値になります。

'\254\355\000\005sr\000\016java.util.UUID\274\231\003\367\230m\205/\002\000\002‌​J\000\014leastSigBitsJ\000\013mostSigBitsxp\273\222)\360*r\322\262u\274\310\020\3‌​42\004M '

...関連する行を取得するための選択または条件としてクエリで簡単に使用することはできません。

hibernate-queryを設定せずに、クエリのselect-またはwhere-partでbytea-columnを読み取ったり使用したりする方法はありますか(たとえば、psqlまたはpgadmin3を介して)?

4

3 に答える 3

7

更新: 質問の編集を参照してください。この回答は、uuid の一般的な 16 バイトのシリアル化に適用されます。Javaのシリアル化を反映するように質問が修正されました。


興味深い問題です。私はそれを効率的に行うために単純な C 拡張機能を作成することになりましたが、以下の PL/Python バージョンを使用する方がおそらく賢明です。

uuidは固定サイズの型であり、可変長フィールド ヘッダーが邪魔になるため、単純にバイナリ強制することbyteavarlenaできません。create cast ... as implicit

bytea 入力が uuid を返す組み込み関数はありません。あると便利ですが、まだ誰もやっていないと思います。

最も簡単な方法

更新:実際にはこれを行う簡単な方法があります。in 16 形式は、 orなしのプレーンな装飾されていない 16 進数を受け入れるためbytea、 が取り除かれると実際には有効な uuid リテラルです。これだけ:\xuuid_in-{}

regress=> SET bytea_output = 'hex';
SET
regress=> SELECT CAST( substring(CAST (BYTEA '\x0FCC6350118D11E4A5597DE5338EB025' AS text) from 3) AS uuid);
              substring               
--------------------------------------
 0fcc6350-118d-11e4-a559-7de5338eb025
(1 row)

これには、いくつかの文字列のコピーと 16 進のエンコード/デコード サイクルが含まれますが、以前に提案した PL の回答よりもはるかに高速ですが、C よりは遅くなります。

その他のオプション

個人的には、PL/Perl または pl/pythonu を使用することをお勧めします。私は例をフォローアップします。

uuid が 16 進形式のバイトリテラルであると仮定します。

'\x0FCC6350118D11E4A5597DE5338EB025'

uuid次のタイプに変換できます。

PL/パール

create language plperlu;

create or replace function to_uuid(bytea) returns uuid language plperlu immutable as $$
use Data::UUID;
my $ug = new Data::UUID;
my $uuid = $ug->from_hexstring(substr($_[0],2));
return $ug->to_string($uuid);
$$
SET bytea_output = hex;

SELECT to_uuid(BYTEA '\x0FCC6350118D11E4A5597DE5338EB025');

PL/パイソン

PL/Python インターフェイスはbytea16 進文字列ではなく生のバイトとして渡すため、Python の方がおそらく高速でクリーンです。

CREATE LANGUAGE plpythonu;

CREATE or replace function to_uuid(uuidbytes bytea) 
RETURNS uuid LANGUAGE plpythonu IMMUTABLE 
AS $$
import uuid
return uuid.UUID(bytes=uuidbytes)
$$;

SELECT to_uuid(BYTEA '\x0FCC6350118D11E4A5597DE5338EB025');

C では、キック用です。醜いハック。

C 拡張モジュールはこちらで確認できます。

しかし、本当に、私はそれが醜いということを意味します. C で適切に実行する場合は、拡張機能を使用するのではなく、実際に PostgreSQL にパッチを適用することをお勧めします。

于 2014-07-22T10:40:37.230 に答える
0

いくつかの試行錯誤の後、postgresql-UUID 値を抽出する次の関数を作成しました。

CREATE OR REPLACE FUNCTION bytea2uuid (x bytea) RETURNS uuid as $$ SELECT encode(substring(x, 73, 8) || substring(x, 65, 8), 'hex')::uuid $$ language sql;

これは、16 進数にエンコードして「uuid」型にキャストするのではなく、leastSigBits と mostSigBits の Java long-values (逆の順序で格納されている) で使用されるバイトを抽出することによって機能します。

次のように使用します。 select bytea2uuid(guid) as guid from documents limit 1;

"75bcc810-e204-4d20-bb92-29f02a72d2b2"

于 2014-07-23T12:05:51.293 に答える
0

これは私のために働く:

ALTER TABLE myTable ALTER COLUMN id TYPE uuid USING CAST(ENCODE(id, 'hex') AS uuid);
于 2015-01-13T09:50:44.793 に答える