@@ -936,9 +936,19 @@ def size(self) -> int:
936936 """Number of live values in the column."""
937937 return len (self )
938938
939+ def _ensure_queryable (self ) -> None :
940+ if self .is_varlen_scalar :
941+ raise NotImplementedError (
942+ f"Column { self ._col_name !r} is a vlstring/vlbytes column; "
943+ "lazy expressions and vectorized comparisons are not supported yet."
944+ )
945+
939946 @staticmethod
940947 def _unwrap_operand (other ):
941- return other ._raw_col if isinstance (other , Column ) else other
948+ if isinstance (other , Column ):
949+ other ._ensure_queryable ()
950+ return other ._raw_col
951+ return other
942952
943953 @property
944954 def _is_nullable_bool (self ) -> bool :
@@ -950,99 +960,129 @@ def _is_nullable_bool(self) -> bool:
950960 )
951961
952962 def __neg__ (self ):
963+ self ._ensure_queryable ()
953964 return - self ._raw_col
954965
955966 def __pos__ (self ):
967+ self ._ensure_queryable ()
956968 return + self ._raw_col
957969
958970 def __abs__ (self ):
971+ self ._ensure_queryable ()
959972 return abs (self ._raw_col )
960973
961974 def __add__ (self , other ):
975+ self ._ensure_queryable ()
962976 return self ._raw_col + self ._unwrap_operand (other )
963977
964978 def __radd__ (self , other ):
979+ self ._ensure_queryable ()
965980 return self ._unwrap_operand (other ) + self ._raw_col
966981
967982 def __sub__ (self , other ):
983+ self ._ensure_queryable ()
968984 return self ._raw_col - self ._unwrap_operand (other )
969985
970986 def __rsub__ (self , other ):
987+ self ._ensure_queryable ()
971988 return self ._unwrap_operand (other ) - self ._raw_col
972989
973990 def __mul__ (self , other ):
991+ self ._ensure_queryable ()
974992 return self ._raw_col * self ._unwrap_operand (other )
975993
976994 def __rmul__ (self , other ):
995+ self ._ensure_queryable ()
977996 return self ._unwrap_operand (other ) * self ._raw_col
978997
979998 def __truediv__ (self , other ):
999+ self ._ensure_queryable ()
9801000 return self ._raw_col / self ._unwrap_operand (other )
9811001
9821002 def __rtruediv__ (self , other ):
1003+ self ._ensure_queryable ()
9831004 return self ._unwrap_operand (other ) / self ._raw_col
9841005
9851006 def __floordiv__ (self , other ):
1007+ self ._ensure_queryable ()
9861008 return self ._raw_col // self ._unwrap_operand (other )
9871009
9881010 def __rfloordiv__ (self , other ):
1011+ self ._ensure_queryable ()
9891012 return self ._unwrap_operand (other ) // self ._raw_col
9901013
9911014 def __mod__ (self , other ):
1015+ self ._ensure_queryable ()
9921016 return self ._raw_col % self ._unwrap_operand (other )
9931017
9941018 def __rmod__ (self , other ):
1019+ self ._ensure_queryable ()
9951020 return self ._unwrap_operand (other ) % self ._raw_col
9961021
9971022 def __pow__ (self , other ):
1023+ self ._ensure_queryable ()
9981024 return self ._raw_col ** self ._unwrap_operand (other )
9991025
10001026 def __rpow__ (self , other ):
1027+ self ._ensure_queryable ()
10011028 return self ._unwrap_operand (other ) ** self ._raw_col
10021029
10031030 def __and__ (self , other ):
1031+ self ._ensure_queryable ()
10041032 return self ._raw_col & self ._unwrap_operand (other )
10051033
10061034 def __rand__ (self , other ):
1035+ self ._ensure_queryable ()
10071036 return self ._unwrap_operand (other ) & self ._raw_col
10081037
10091038 def __or__ (self , other ):
1039+ self ._ensure_queryable ()
10101040 return self ._raw_col | self ._unwrap_operand (other )
10111041
10121042 def __ror__ (self , other ):
1043+ self ._ensure_queryable ()
10131044 return self ._unwrap_operand (other ) | self ._raw_col
10141045
10151046 def __xor__ (self , other ):
1047+ self ._ensure_queryable ()
10161048 return self ._raw_col ^ self ._unwrap_operand (other )
10171049
10181050 def __rxor__ (self , other ):
1051+ self ._ensure_queryable ()
10191052 return self ._unwrap_operand (other ) ^ self ._raw_col
10201053
10211054 def __invert__ (self ):
1055+ self ._ensure_queryable ()
10221056 if self ._is_nullable_bool :
10231057 return self ._raw_col == 0
10241058 return ~ self ._raw_col
10251059
10261060 def __lt__ (self , other ):
1061+ self ._ensure_queryable ()
10271062 return self ._raw_col < self ._unwrap_operand (other )
10281063
10291064 def __le__ (self , other ):
1065+ self ._ensure_queryable ()
10301066 return self ._raw_col <= self ._unwrap_operand (other )
10311067
10321068 def __eq__ (self , other ):
1069+ self ._ensure_queryable ()
10331070 if self ._is_nullable_bool and isinstance (other , (bool , np .bool_ )):
10341071 return self ._raw_col == int (other )
10351072 return self ._raw_col == self ._unwrap_operand (other )
10361073
10371074 def __ne__ (self , other ):
1075+ self ._ensure_queryable ()
10381076 if self ._is_nullable_bool and isinstance (other , (bool , np .bool_ )):
10391077 return self ._raw_col == int (not other )
10401078 return self ._raw_col != self ._unwrap_operand (other )
10411079
10421080 def __gt__ (self , other ):
1081+ self ._ensure_queryable ()
10431082 return self ._raw_col > self ._unwrap_operand (other )
10441083
10451084 def __ge__ (self , other ):
1085+ self ._ensure_queryable ()
10461086 return self ._raw_col >= self ._unwrap_operand (other )
10471087
10481088 @property
@@ -1598,6 +1638,8 @@ def __init__(
15981638 cc = self ._schema .columns_by_name [name ]
15991639 if self ._is_list_column (cc ):
16001640 col = storage .open_list_column (name )
1641+ elif self ._is_varlen_scalar_column (cc ):
1642+ col = storage .open_varlen_scalar_column (name , cc .spec )
16011643 else :
16021644 col = storage .open_column (name )
16031645 self ._cols [name ] = col
@@ -5656,6 +5698,16 @@ def _where_expression_operands(self) -> dict[str, blosc2.NDArray | blosc2.LazyEx
56565698 operands .update ({name : cc ["lazy" ] for name , cc in self ._computed_cols .items ()})
56575699 return operands
56585700
5701+ def _guard_varlen_scalar_expression (self , expr : str ) -> None :
5702+ for col in self ._schema .columns :
5703+ if self ._is_varlen_scalar_column (col ) and re .search (
5704+ rf"(?<!\w){ re .escape (col .name )} (?!\w)" , expr
5705+ ):
5706+ raise NotImplementedError (
5707+ f"Column { col .name !r} is a vlstring/vlbytes column; "
5708+ "lazy expressions are not supported yet."
5709+ )
5710+
56595711 def where (
56605712 self ,
56615713 expr_result : str | np .ndarray | blosc2 .NDArray | blosc2 .LazyExpr | Column ,
@@ -5735,6 +5787,7 @@ def where(
57355787 t.where(not t.returned)
57365788 """
57375789 if isinstance (expr_result , str ):
5790+ self ._guard_varlen_scalar_expression (expr_result )
57385791 expr_result = blosc2 .lazyexpr (expr_result , self ._where_expression_operands ())
57395792 if isinstance (expr_result , np .ndarray ) and expr_result .dtype == np .bool_ :
57405793 expr_result = blosc2 .asarray (expr_result )
0 commit comments