位可变的PostgreSQL按位运算符;不能使用不同大小的位字符串“;

位可变的PostgreSQL按位运算符;不能使用不同大小的位字符串“;,postgresql,bit-manipulation,Postgresql,Bit Manipulation,我有一个可变位掩码字段,我想对其执行按位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') (要获得此错误,表中需要具有不同长度的位掩码。) 我希望按位计算如下所示: 00010&1000001

我有一个可变位掩码字段,我想对其执行按位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')
(要获得此错误,表中需要具有不同长度的位掩码。)

我希望按位计算如下所示: 00010&10000010=00010

我还尝试将位掩码强制转换为整数,但没有成功

为什么PostgreSQL会在这方面窒息

我应该如何重写此查询才能很好地发挥作用

我能够使用以下方法使按位运算符工作: lpad(读\角色\位掩码::varchar,64,'0')::bigint


然而,这被限制为64位,有更好的方法吗?

PostgreSQL
位和
位变化类型的行为毫无帮助,它拒绝为操作扩展位字段,并为强制转换右扩展位字段,而不是左扩展位字段

Pg在AND或or操作之前用零左扩展较小的操作数是有意义的,而不是失败

您不能使用对
位(n)
的强制转换来获得相同的长度,因为出于某种疯狂的原因,对
位(n)
的强制转换会增加参数的正确性,使得它在几乎所有情况下都是无用的

您可以使用类似于
lpad($1::text,maxist(length($1),length($2)),'0')::bit variabling
的方法将位字段用零向左扩展到两个长度中的较大值。它很笨重,但会有用的。我建议编写包装器函数来包含混乱


另一方面,考虑修改<代码> BIT <代码>支持代码,在代码> SRC/Endo/UTLS/ADT/VARBITE。C/<代码>中添加函数到左扩展和左截断位字段,以及函数做左扩展比较。基于现有的代码,这应该很容易。

我今天也遇到了类似的问题。我想做几乎完全相同的事情:屏蔽位字符串中最低有效的两位,并将结果与文本值进行比较,如下所示:

status & b'11' > b'01'
(status << length(status)-2)::bit(2) > b'01'
(状态是我的专栏)

起初,我尝试使用Craig的解决方案,但很快就变得非常混乱,因为不仅掩码必须保持扩展,而且我比较结果的值也必须保持扩展,因为根据postgresql:

t2=> select b'0010' < b'01';
 ?column?
----------
 t
(1 row)
t2=>选择b'0010'
如其他答案中所述,在应用
1)之前,右侧填充使其尺寸与左侧相同-

postgres has has some inconvenient/counterintuitive behaviors - 
right padding when casting to bit(n), 
bitwise ops only on similar size,
etc.
2) 一个解决办法是-

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

示例:

基本左填充:

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
位屏蔽/转换以获得三个最低有效位:

select B'11010'::int::bit(3)
010
select B'11010'::bit(3)
110
位屏蔽/转换以获得三个最高有效位:

select B'11010'::int::bit(3)
010
select B'11010'::bit(3)
110
更新:
使用int8来容纳更长的位字符串

这是一个奇怪的限制。我希望Pg的
&
会自动用零左扩展较小的操作数。@Craig:“大小必须相同”的行为被记录在案。另外,
B'10'::位(1)
B'1'
,而
B'1'::位(2)
B'10'
,所以位从左到右。我得到的印象是,位顺序在某个地方发生了变化,因此它们可能会迫使您显式地避免版本问题。这是有文档记录的,但坦率地说,右扩展位字段并没有隐式或显式地提供左扩展选项是非常无用的。谁使用从左到右的位字符串?使用
read\u roles\u bitmask&B'10'>B'0'
部分,您只想查看位2(从右到左,基于1的计数)是否为
1
,对吗?如果从左向右转换位,则可以转换到
位(2)
以仅获取最左边的2位。