99
1010#include "access/htup_details.h"
1111#include "catalog/pg_statistic.h"
12+ #include "common/hashfn.h"
1213#include "ltree.h"
1314#include "utils/builtins.h"
1415#include "utils/lsyscache.h"
@@ -24,6 +25,8 @@ PG_FUNCTION_INFO_V1(ltree_eq);
2425PG_FUNCTION_INFO_V1 (ltree_ne );
2526PG_FUNCTION_INFO_V1 (ltree_ge );
2627PG_FUNCTION_INFO_V1 (ltree_gt );
28+ PG_FUNCTION_INFO_V1 (hash_ltree );
29+ PG_FUNCTION_INFO_V1 (hash_ltree_extended );
2730PG_FUNCTION_INFO_V1 (nlevel );
2831PG_FUNCTION_INFO_V1 (ltree_isparent );
2932PG_FUNCTION_INFO_V1 (ltree_risparent );
@@ -129,6 +132,72 @@ ltree_ne(PG_FUNCTION_ARGS)
129132 PG_RETURN_BOOL (res != 0 );
130133}
131134
135+ /* Compute a hash for the ltree */
136+ Datum
137+ hash_ltree (PG_FUNCTION_ARGS )
138+ {
139+ ltree * a = PG_GETARG_LTREE_P (0 );
140+ uint32 result = 1 ;
141+ int an = a -> numlevel ;
142+ ltree_level * al = LTREE_FIRST (a );
143+
144+ while (an > 0 )
145+ {
146+ uint32 levelHash = DatumGetUInt32 (hash_any ((unsigned char * ) al -> name , al -> len ));
147+
148+ /*
149+ * Combine hash values of successive elements by multiplying the
150+ * current value by 31 and adding on the new element's hash value.
151+ *
152+ * This method is borrowed from hash_array(), which see for further
153+ * commentary.
154+ */
155+ result = (result << 5 ) - result + levelHash ;
156+
157+ an -- ;
158+ al = LEVEL_NEXT (al );
159+ }
160+
161+ PG_FREE_IF_COPY (a , 0 );
162+ PG_RETURN_UINT32 (result );
163+ }
164+
165+ /* Compute an extended hash for the ltree */
166+ Datum
167+ hash_ltree_extended (PG_FUNCTION_ARGS )
168+ {
169+ ltree * a = PG_GETARG_LTREE_P (0 );
170+ const uint64 seed = PG_GETARG_INT64 (1 );
171+ uint64 result = 1 ;
172+ int an = a -> numlevel ;
173+ ltree_level * al = LTREE_FIRST (a );
174+
175+ /*
176+ * If the path has length zero, return 1 + seed to ensure that the low 32
177+ * bits of the result match hash_ltree when the seed is 0, as required by
178+ * the hash index support functions, but to also return a different value
179+ * when there is a seed.
180+ */
181+ if (an == 0 )
182+ {
183+ PG_FREE_IF_COPY (a , 0 );
184+ PG_RETURN_UINT64 (result + seed );
185+ }
186+
187+ while (an > 0 )
188+ {
189+ uint64 levelHash = DatumGetUInt64 (hash_any_extended ((unsigned char * ) al -> name , al -> len , seed ));
190+
191+ result = (result << 5 ) - result + levelHash ;
192+
193+ an -- ;
194+ al = LEVEL_NEXT (al );
195+ }
196+
197+ PG_FREE_IF_COPY (a , 0 );
198+ PG_RETURN_UINT64 (result );
199+ }
200+
132201Datum
133202nlevel (PG_FUNCTION_ARGS )
134203{
0 commit comments