6

さまざまなビットマスクフィールドがあり、ビット単位のANDを実行したいと思います。

PG::Error: ERROR:  cannot AND bit strings of different sizes
SELECT "groups".* FROM "groups"  WHERE (read_roles_bitmask = B'0' OR read_roles_bitmask & B'10' > B'0')

(このエラーを取得するには、テーブルにさまざまな長さのビットマスクが必要です。)

ビット単位の計算は次のようになると思います:000010&100000010 = 00010

また、ビットマスクを整数にキャストしようとしましたが、運がありませんでした。

なぜPostgreSQLはこれを窒息させるのですか?

うまく再生するには、このクエリをどのように書き直す必要がありますか?

次を使用してビット演算子を機能させることができました:lpad(read_roles_bitmask :: varchar、64、 '0'):: bigint

ただし、これは64ビットに制限されていますが、より良い方法はありますか?

4

3 に答える 3

9

PostgreSQLbitbit varyingタイプの動作は非常に役に立たず、操作のためにビットフィールドを拡張することを拒否し、キャストのためにビットフィールドを左に拡張するのではなく、右に拡張します。

Pgが失敗するのではなく、ANDまたはOR演算の前に、小さい方のオペランドをゼロで左に拡張することは理にかなっています。

キャストを使用して同じ長さを取得することはできませんbit(n)。これは、なんらかの理由で、キャストを使用して引数をbit(n) 右に埋め、ほとんどすべての状況で役に立たないためです。

次のようなものを使用lpad($1::text, greatest(length($1), length($2)),'0')::bit varyingして、ゼロのあるビットフィールドを2つの長さの大きい方に左拡張できます。面倒ですが、うまくいきます。混乱を含むラッパー関数を作成することをお勧めします。

bitまたは、サポートコードを変更して、src/backend/utils/adt/varbit.c左拡張ビットフィールドと左切り捨てビットフィールドに関数を追加し、左拡張比較を実行する関数を追加することを検討してください。既存のコードに基づいて、それはかなり簡単なはずです。

于 2012-12-04T01:02:42.870 に答える
2

今日も同様の問題がありました。ほぼ同じことをしたかったのです。ビット文字列の最下位2ビットをマスクして、結果を次のようにリテラル値と比較します。

status & b'11' > b'01'

(ステータスは私のビット変動列でした)。

最初はCraigのソリューションを使用しようとしましたが、マスクを拡張したままにする必要があるだけでなく、postgresqlによると、結果を比較していた値もかなり乱雑になりました。

t2=> select b'0010' < b'01';
 ?column?
----------
 t
(1 row)

RHSは、操作を適用する前にLHSと同じサイズになるように右にパッドが入ってい<ます。

結局、私はそれを次のように解決しました:

(status << length(status)-2)::bit(2) > b'01'

それの良いところは、比較のためにビットのセットを抽出できることです。たとえば、左から3番目のビットのペアを取得するには:

(status << length(status)-6)::bit(2)

substring比較のために任意のビットセットを抽出するために使用することもできます。

于 2015-08-26T01:33:59.180 に答える
1

1)他の回答で述べたように-

postgres has has some inconvenient/counterintuitive behaviors - 
right padding when casting to bit(n), 
bitwise ops only on similar size,
etc.

2)1つの回避策は-

double-casting every value - to integer and then to bit(XX)

長所:

- left vs right padding works correctly 
- all the bit-strings have same length for correct bitwise operations
- comparisons work correctly
- bit-masking/casting to get least significant bits

例:

基本的な左パディング:

select B'0010'::int::bit(22)
0000000000000000000010

ビット演算:

select B'0010'::int::bit(22) | B'01'::int::bit(22)
0000000000000000000011

比較:

select B'0010'::int::bit(22) > B'01'::int::bit(22)
true

3つの最下位ビットを取得するためのビットマスキング/キャスト:

select B'11010'::int::bit(3)
010

3つの最上位ビットを取得するためのビットマスキング/キャスト:

select B'11010'::bit(3)
110

更新: int8を使用して、より長いビット文字列に対応します

于 2019-11-18T16:00:00.507 に答える