@@ -69,7 +69,7 @@ typedef struct Bloom1MetadataBuilder
6969 Bloom1HasherInternal hasher ;
7070} Bloom1MetadataBuilder ;
7171
72- static void bloom1_hasher_init (Bloom1HasherInternal * hasher , const Oid * type_oids , int num_columns );
72+ static Bloom1HasherInternal bloom1_hasher_init (const Oid * type_oids , int num_columns );
7373
7474/*
7575 * Low-bias invertible hash function from this article:
@@ -544,6 +544,13 @@ bloom1_contains_context_prepare(FunctionCallInfo fcinfo, bool use_element_type)
544544 num_columns )));
545545 }
546546
547+ if (num_columns < 2 )
548+ {
549+ ereport (ERROR ,
550+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
551+ errmsg ("composite bloom filter must have at least two columns" )));
552+ }
553+
547554 for (int i = 0 ; i < num_columns ; i ++ )
548555 {
549556 type_oids [i ] = TupleDescAttr (tupdesc , i )-> atttypid ;
@@ -556,7 +563,7 @@ bloom1_contains_context_prepare(FunctionCallInfo fcinfo, bool use_element_type)
556563 num_columns = 1 ;
557564 }
558565
559- bloom1_hasher_init ( & context -> bloom_hasher , type_oids , num_columns );
566+ context -> bloom_hasher = bloom1_hasher_init ( type_oids , num_columns );
560567
561568 get_typlenbyvalalign (context -> element_type ,
562569 & context -> element_typlen ,
@@ -583,12 +590,6 @@ bloom1_contains_hash_internal(const char *words_buf, uint32 num_bits, uint64 has
583590{
584591 Assert (words_buf != NULL );
585592
586- /* Must be a power of two. */
587- CheckCompressedData (num_bits == (1ULL << pg_leftmost_one_pos32 (num_bits )));
588-
589- /* Must be >= 64 bits. */
590- CheckCompressedData (num_bits >= 64 );
591-
592593 const uint32 num_word_bits = sizeof (* words_buf ) * 8 ;
593594 Assert (num_bits % num_word_bits == 0 );
594595 const uint32 log2_word_bits = pg_leftmost_one_pos32 (num_word_bits );
@@ -767,12 +768,12 @@ bloom1_contains_any(PG_FUNCTION_ARGS)
767768 const char * words_buf = bloom1_words_buf (bloom );
768769 const uint32 num_bits = bloom1_num_bits (bloom );
769770
770- /* Must be a power of two. */
771- CheckCompressedData (num_bits == (1ULL << pg_leftmost_one_pos32 (num_bits )));
772-
773771 /* Must be >= 64 bits. */
774772 CheckCompressedData (num_bits >= 64 );
775773
774+ /* Must be a power of two. */
775+ CheckCompressedData (num_bits == (1ULL << pg_leftmost_one_pos32 (num_bits )));
776+
776777 const uint32 num_word_bits = sizeof (* words_buf ) * 8 ;
777778 Assert (num_bits % num_word_bits == 0 );
778779 const uint32 log2_word_bits = pg_leftmost_one_pos32 (num_word_bits );
@@ -809,7 +810,7 @@ bloom1_contains_any(PG_FUNCTION_ARGS)
809810}
810811
811812/*
812- * Checks whether any hashes of the given array can be present in the given
813+ * Checks whether any hashes in the given array can be present in the given
813814 * bloom filter. This is used for predicate pushdown where the values are
814815 * pre-hashed at planning time.
815816 *
@@ -864,6 +865,12 @@ bloom1_contains_any_hashes(PG_FUNCTION_ARGS)
864865 const char * words_buf = bloom1_words_buf (bloom );
865866 const uint32 num_bits = bloom1_num_bits (bloom );
866867
868+ /* Must be >= 64 bits. */
869+ CheckCompressedData (num_bits >= 64 );
870+
871+ /* Must be a power of two. */
872+ CheckCompressedData (num_bits == (1ULL << pg_leftmost_one_pos32 (num_bits )));
873+
867874 for (int i = 0 ; i < num_hashes ; i ++ )
868875 {
869876 if (hash_nulls [i ])
@@ -912,6 +919,13 @@ bloom1_hash(PG_FUNCTION_ARGS)
912919 num_columns )));
913920 }
914921
922+ if (num_columns < 2 )
923+ {
924+ ereport (ERROR ,
925+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
926+ errmsg ("composite bloom filter must have at least two columns" )));
927+ }
928+
915929 for (int i = 0 ; i < num_columns ; i ++ )
916930 {
917931 type_oids [i ] = TupleDescAttr (tupdesc , i )-> atttypid ;
@@ -938,8 +952,8 @@ bloom1_hash(PG_FUNCTION_ARGS)
938952 num_columns = 1 ;
939953 }
940954
941- Bloom1Hasher * hasher = bloom1_hasher_create (type_oids , num_columns );
942- uint64 hash = hasher -> hash_values (hasher , values );
955+ Bloom1HasherInternal hasher = bloom1_hasher_init (type_oids , num_columns );
956+ uint64 hash = hasher . functions . hash_values (& hasher , values );
943957 PG_RETURN_INT64 ((int64 ) hash );
944958}
945959
@@ -981,36 +995,39 @@ batch_metadata_builder_bloom1_varlena_size(void)
981995 return bloom1_varlena_alloc_size (desired_bits );
982996}
983997
984- static void
985- bloom1_hasher_init (Bloom1HasherInternal * hasher , const Oid * type_oids , int num_columns )
998+ static Bloom1HasherInternal
999+ bloom1_hasher_init (const Oid * type_oids , int num_columns )
9861000{
987- * hasher = (Bloom1HasherInternal ){
1001+ Bloom1HasherInternal hasher = (Bloom1HasherInternal ){
9881002 .functions =
9891003 (Bloom1Hasher ){
9901004 .hash_values = bloom1_hash_values ,
9911005 .num_columns = num_columns ,
9921006 },
9931007 };
9941008
1009+ Assert (num_columns != 0 );
9951010 for (int i = 0 ; i < num_columns ; i ++ )
9961011 {
997- hasher -> hash_functions [i ] =
998- bloom1_get_hash_function (type_oids [i ], & hasher -> hash_function_finfos [i ]);
999- if (hasher -> hash_functions [i ] == NULL )
1012+ hasher . hash_functions [i ] =
1013+ bloom1_get_hash_function (type_oids [i ], & hasher . hash_function_finfos [i ]);
1014+ if (hasher . hash_functions [i ] == NULL )
10001015 {
10011016 ereport (ERROR ,
10021017 (errcode (ERRCODE_UNDEFINED_FUNCTION ),
10031018 errmsg ("the argument type %s lacks an extended hash function" ,
10041019 format_type_be (type_oids [i ]))));
10051020 }
10061021 }
1022+
1023+ return hasher ;
10071024}
10081025
10091026Bloom1Hasher *
10101027bloom1_hasher_create (const Oid * type_oids , int num_columns )
10111028{
10121029 Bloom1HasherInternal * hasher = palloc (sizeof (* hasher ));
1013- bloom1_hasher_init ( hasher , type_oids , num_columns );
1030+ * hasher = bloom1_hasher_init ( type_oids , num_columns );
10141031 return & hasher -> functions ;
10151032}
10161033
@@ -1038,7 +1055,7 @@ batch_metadata_builder_bloom1_create(int num_columns, const Oid *type_oids,
10381055 memcpy (builder -> input_columns , attnums , num_columns * sizeof (AttrNumber ));
10391056
10401057 /* Initialize the embedded hasher */
1041- bloom1_hasher_init ( & builder -> hasher , type_oids , num_columns );
1058+ builder -> hasher = bloom1_hasher_init ( type_oids , num_columns );
10421059
10431060 /*
10441061 * Initialize the bloom filter.
@@ -1197,15 +1214,15 @@ ts_bloom1_composite_debug_hash(PG_FUNCTION_ARGS)
11971214 }
11981215 ReleaseTupleDesc (tupdesc );
11991216
1200- Bloom1Hasher * hasher = bloom1_hasher_create (type_oids , num_fields );
1217+ Bloom1HasherInternal hasher = bloom1_hasher_init (type_oids , num_fields );
12011218
12021219 NullableDatum values [MAX_BLOOM_FILTER_COLUMNS ];
12031220 for (int i = 0 ; i < num_fields ; i ++ )
12041221 {
12051222 values [i ].value = GetAttributeByNum (tuple , i + 1 , & values [i ].isnull );
12061223 }
12071224
1208- uint64 hash = hasher -> hash_values (hasher , values );
1225+ uint64 hash = hasher . functions . hash_values (& hasher , values );
12091226 PG_RETURN_INT64 ((int64 ) hash );
12101227}
12111228
@@ -1228,9 +1245,8 @@ bloom1_contains_hash(Datum bloom_datum, uint64 hash)
12281245 const uint32 num_bits = 8 * VARSIZE_ANY_EXHDR (bloom );
12291246
12301247 /* Validate bloom structure */
1231- CheckCompressedData (num_bits != 0 );
1232- CheckCompressedData (num_bits == (1ULL << pg_leftmost_one_pos32 (num_bits )));
12331248 CheckCompressedData (num_bits >= 64 );
1249+ CheckCompressedData (num_bits == (1ULL << pg_leftmost_one_pos32 (num_bits )));
12341250
12351251 return bloom1_contains_hash_internal (words_buf , num_bits , hash );
12361252}
0 commit comments