9
9
10
10
#include "access/htup_details.h"
11
11
#include "catalog/pg_statistic.h"
12
+ #include "common/hashfn.h"
12
13
#include "ltree.h"
13
14
#include "utils/builtins.h"
14
15
#include "utils/lsyscache.h"
@@ -24,6 +25,8 @@ PG_FUNCTION_INFO_V1(ltree_eq);
24
25
PG_FUNCTION_INFO_V1 (ltree_ne );
25
26
PG_FUNCTION_INFO_V1 (ltree_ge );
26
27
PG_FUNCTION_INFO_V1 (ltree_gt );
28
+ PG_FUNCTION_INFO_V1 (hash_ltree );
29
+ PG_FUNCTION_INFO_V1 (hash_ltree_extended );
27
30
PG_FUNCTION_INFO_V1 (nlevel );
28
31
PG_FUNCTION_INFO_V1 (ltree_isparent );
29
32
PG_FUNCTION_INFO_V1 (ltree_risparent );
@@ -129,6 +132,72 @@ ltree_ne(PG_FUNCTION_ARGS)
129
132
PG_RETURN_BOOL (res != 0 );
130
133
}
131
134
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
+
132
201
Datum
133
202
nlevel (PG_FUNCTION_ARGS )
134
203
{
0 commit comments