]> granicus.if.org Git - postgresql/blob - contrib/btree_gist/btree_utils_num.c
Convert contrib modules to use the extension facility.
[postgresql] / contrib / btree_gist / btree_utils_num.c
1 /*
2  * contrib/btree_gist/btree_utils_num.c
3  */
4 #include "btree_gist.h"
5 #include "btree_utils_num.h"
6 #include "utils/cash.h"
7 #include "utils/date.h"
8
9
10 GISTENTRY *
11 gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo *tinfo)
12 {
13         if (entry->leafkey)
14         {
15                 union
16                 {
17                         int16           i2;
18                         int32           i4;
19                         int64           i8;
20                         float4          f4;
21                         float8          f8;
22                         DateADT         dt;
23                         TimeADT         tm;
24                         Timestamp       ts;
25                         Cash            ch;
26                 }                       v;
27
28                 GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(2 * tinfo->size);
29                 void       *leaf = NULL;
30
31                 switch (tinfo->t)
32                 {
33                         case gbt_t_int2:
34                                 v.i2 = DatumGetInt16(entry->key);
35                                 leaf = &v.i2;
36                                 break;
37                         case gbt_t_int4:
38                                 v.i4 = DatumGetInt32(entry->key);
39                                 leaf = &v.i4;
40                                 break;
41                         case gbt_t_int8:
42                                 v.i8 = DatumGetInt64(entry->key);
43                                 leaf = &v.i8;
44                                 break;
45                         case gbt_t_oid:
46                                 v.i4 = DatumGetObjectId(entry->key);
47                                 leaf = &v.i4;
48                                 break;
49                         case gbt_t_float4:
50                                 v.f4 = DatumGetFloat4(entry->key);
51                                 leaf = &v.f4;
52                                 break;
53                         case gbt_t_float8:
54                                 v.f8 = DatumGetFloat8(entry->key);
55                                 leaf = &v.f8;
56                                 break;
57                         case gbt_t_date:
58                                 v.dt = DatumGetDateADT(entry->key);
59                                 leaf = &v.dt;
60                                 break;
61                         case gbt_t_time:
62                                 v.tm = DatumGetTimeADT(entry->key);
63                                 leaf = &v.tm;
64                                 break;
65                         case gbt_t_ts:
66                                 v.ts = DatumGetTimestamp(entry->key);
67                                 leaf = &v.ts;
68                                 break;
69                         case gbt_t_cash:
70                                 v.ch = DatumGetCash(entry->key);
71                                 leaf = &v.ch;
72                                 break;
73                         default:
74                                 leaf = DatumGetPointer(entry->key);
75                 }
76
77                 memcpy((void *) &r[0], leaf, tinfo->size);
78                 memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
79                 retval = palloc(sizeof(GISTENTRY));
80                 gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
81                                           entry->offset, FALSE);
82         }
83         else
84                 retval = entry;
85
86         return retval;
87 }
88
89
90
91
92 /*
93 ** The GiST union method for numerical values
94 */
95
96 void *
97 gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo)
98 {
99         int                     i,
100                                 numranges;
101         GBT_NUMKEY *cur;
102         GBT_NUMKEY_R o,
103                                 c;
104
105         numranges = entryvec->n;
106         cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
107
108
109         o.lower = &((GBT_NUMKEY *) out)[0];
110         o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
111
112         memcpy((void *) out, (void *) cur, 2 * tinfo->size);
113
114         for (i = 1; i < numranges; i++)
115         {
116                 cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
117                 c.lower = &cur[0];
118                 c.upper = &cur[tinfo->size];
119                 if ((*tinfo->f_gt) (o.lower, c.lower))  /* out->lower > cur->lower */
120                         memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
121                 if ((*tinfo->f_lt) (o.upper, c.upper))  /* out->upper < cur->upper */
122                         memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
123         }
124
125         return out;
126 }
127
128
129
130 /*
131 ** The GiST same method for numerical values
132 */
133
134 bool
135 gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo)
136 {
137
138         GBT_NUMKEY_R b1,
139                                 b2;
140
141         b1.lower = &(((GBT_NUMKEY *) a)[0]);
142         b1.upper = &(((GBT_NUMKEY *) a)[tinfo->size]);
143         b2.lower = &(((GBT_NUMKEY *) b)[0]);
144         b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
145
146         if (
147                 (*tinfo->f_eq) (b1.lower, b2.lower) &&
148                 (*tinfo->f_eq) (b1.upper, b2.upper)
149                 )
150                 return TRUE;
151         return FALSE;
152
153 }
154
155
156 void
157 gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
158 {
159
160         GBT_NUMKEY_R rd;
161
162         rd.lower = &e[0];
163         rd.upper = &e[tinfo->size];
164
165         if (!DatumGetPointer(*u))
166         {
167                 *u = PointerGetDatum(palloc(2 * tinfo->size));
168                 memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), (void *) rd.lower, tinfo->size);
169                 memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), (void *) rd.upper, tinfo->size);
170         }
171         else
172         {
173                 GBT_NUMKEY_R ur;
174
175                 ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
176                 ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
177                 if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower))
178                         memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
179                 if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper))
180                         memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
181         }
182 }
183
184
185
186 /*
187 ** The GiST consistent method
188 */
189
190 bool
191 gbt_num_consistent(
192                                    const GBT_NUMKEY_R *key,
193                                    const void *query,
194                                    const StrategyNumber *strategy,
195                                    bool is_leaf,
196                                    const gbtree_ninfo *tinfo
197 )
198 {
199
200         bool            retval = FALSE;
201
202         switch (*strategy)
203         {
204                 case BTLessEqualStrategyNumber:
205                         retval = (*tinfo->f_ge) (query, key->lower);
206                         break;
207                 case BTLessStrategyNumber:
208                         if (is_leaf)
209                                 retval = (*tinfo->f_gt) (query, key->lower);
210                         else
211                                 retval = (*tinfo->f_ge) (query, key->lower);
212                         break;
213                 case BTEqualStrategyNumber:
214                         if (is_leaf)
215                                 retval = (*tinfo->f_eq) (query, key->lower);
216                         else
217                                 retval = (*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper);
218                         break;
219                 case BTGreaterStrategyNumber:
220                         if (is_leaf)
221                                 retval = (*tinfo->f_lt) (query, key->upper);
222                         else
223                                 retval = (*tinfo->f_le) (query, key->upper);
224                         break;
225                 case BTGreaterEqualStrategyNumber:
226                         retval = (*tinfo->f_le) (query, key->upper);
227                         break;
228                 case BtreeGistNotEqualStrategyNumber:
229                         retval = ! ((*tinfo->f_eq) (query, key->lower) &&
230                                 (*tinfo->f_eq) (query, key->upper));
231                         break;
232                 default:
233                         retval = FALSE;
234         }
235
236         return (retval);
237 }
238
239
240 GIST_SPLITVEC *
241 gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
242                                   const gbtree_ninfo *tinfo)
243 {
244         OffsetNumber i,
245                                 maxoff = entryvec->n - 1;
246         Nsrt       *arr;
247         int                     nbytes;
248
249         arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
250         nbytes = (maxoff + 2) * sizeof(OffsetNumber);
251         v->spl_left = (OffsetNumber *) palloc(nbytes);
252         v->spl_right = (OffsetNumber *) palloc(nbytes);
253         v->spl_ldatum = PointerGetDatum(0);
254         v->spl_rdatum = PointerGetDatum(0);
255         v->spl_nleft = 0;
256         v->spl_nright = 0;
257
258         /* Sort entries */
259
260         for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
261         {
262                 arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
263                 arr[i].i = i;
264         }
265         qsort((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), tinfo->f_cmp);
266
267         /* We do simply create two parts */
268
269         for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
270         {
271                 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
272                 {
273                         gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
274                         v->spl_left[v->spl_nleft] = arr[i].i;
275                         v->spl_nleft++;
276                 }
277                 else
278                 {
279                         gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
280                         v->spl_right[v->spl_nright] = arr[i].i;
281                         v->spl_nright++;
282                 }
283         }
284
285         return v;
286 }