00001
00002
00003
00004 #include "postgres.h"
00005
00006 #include "btree_gist.h"
00007 #include "btree_utils_num.h"
00008 #include "utils/cash.h"
00009 #include "utils/date.h"
00010 #include "utils/timestamp.h"
00011
00012
00013 GISTENTRY *
00014 gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo *tinfo)
00015 {
00016 if (entry->leafkey)
00017 {
00018 union
00019 {
00020 int16 i2;
00021 int32 i4;
00022 int64 i8;
00023 float4 f4;
00024 float8 f8;
00025 DateADT dt;
00026 TimeADT tm;
00027 Timestamp ts;
00028 Cash ch;
00029 } v;
00030
00031 GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(2 * tinfo->size);
00032 void *leaf = NULL;
00033
00034 switch (tinfo->t)
00035 {
00036 case gbt_t_int2:
00037 v.i2 = DatumGetInt16(entry->key);
00038 leaf = &v.i2;
00039 break;
00040 case gbt_t_int4:
00041 v.i4 = DatumGetInt32(entry->key);
00042 leaf = &v.i4;
00043 break;
00044 case gbt_t_int8:
00045 v.i8 = DatumGetInt64(entry->key);
00046 leaf = &v.i8;
00047 break;
00048 case gbt_t_oid:
00049 v.i4 = DatumGetObjectId(entry->key);
00050 leaf = &v.i4;
00051 break;
00052 case gbt_t_float4:
00053 v.f4 = DatumGetFloat4(entry->key);
00054 leaf = &v.f4;
00055 break;
00056 case gbt_t_float8:
00057 v.f8 = DatumGetFloat8(entry->key);
00058 leaf = &v.f8;
00059 break;
00060 case gbt_t_date:
00061 v.dt = DatumGetDateADT(entry->key);
00062 leaf = &v.dt;
00063 break;
00064 case gbt_t_time:
00065 v.tm = DatumGetTimeADT(entry->key);
00066 leaf = &v.tm;
00067 break;
00068 case gbt_t_ts:
00069 v.ts = DatumGetTimestamp(entry->key);
00070 leaf = &v.ts;
00071 break;
00072 case gbt_t_cash:
00073 v.ch = DatumGetCash(entry->key);
00074 leaf = &v.ch;
00075 break;
00076 default:
00077 leaf = DatumGetPointer(entry->key);
00078 }
00079
00080 memcpy((void *) &r[0], leaf, tinfo->size);
00081 memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
00082 retval = palloc(sizeof(GISTENTRY));
00083 gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
00084 entry->offset, FALSE);
00085 }
00086 else
00087 retval = entry;
00088
00089 return retval;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099 void *
00100 gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo)
00101 {
00102 int i,
00103 numranges;
00104 GBT_NUMKEY *cur;
00105 GBT_NUMKEY_R o,
00106 c;
00107
00108 numranges = entryvec->n;
00109 cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
00110
00111
00112 o.lower = &((GBT_NUMKEY *) out)[0];
00113 o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
00114
00115 memcpy((void *) out, (void *) cur, 2 * tinfo->size);
00116
00117 for (i = 1; i < numranges; i++)
00118 {
00119 cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
00120 c.lower = &cur[0];
00121 c.upper = &cur[tinfo->size];
00122 if ((*tinfo->f_gt) (o.lower, c.lower))
00123 memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
00124 if ((*tinfo->f_lt) (o.upper, c.upper))
00125 memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
00126 }
00127
00128 return out;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 bool
00138 gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo)
00139 {
00140
00141 GBT_NUMKEY_R b1,
00142 b2;
00143
00144 b1.lower = &(((GBT_NUMKEY *) a)[0]);
00145 b1.upper = &(((GBT_NUMKEY *) a)[tinfo->size]);
00146 b2.lower = &(((GBT_NUMKEY *) b)[0]);
00147 b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
00148
00149 if (
00150 (*tinfo->f_eq) (b1.lower, b2.lower) &&
00151 (*tinfo->f_eq) (b1.upper, b2.upper)
00152 )
00153 return TRUE;
00154 return FALSE;
00155
00156 }
00157
00158
00159 void
00160 gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
00161 {
00162
00163 GBT_NUMKEY_R rd;
00164
00165 rd.lower = &e[0];
00166 rd.upper = &e[tinfo->size];
00167
00168 if (!DatumGetPointer(*u))
00169 {
00170 *u = PointerGetDatum(palloc(2 * tinfo->size));
00171 memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), (void *) rd.lower, tinfo->size);
00172 memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), (void *) rd.upper, tinfo->size);
00173 }
00174 else
00175 {
00176 GBT_NUMKEY_R ur;
00177
00178 ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
00179 ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
00180 if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower))
00181 memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
00182 if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper))
00183 memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
00184 }
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 bool
00196 gbt_num_consistent(const GBT_NUMKEY_R *key,
00197 const void *query,
00198 const StrategyNumber *strategy,
00199 bool is_leaf,
00200 const gbtree_ninfo *tinfo)
00201 {
00202 bool retval;
00203
00204 switch (*strategy)
00205 {
00206 case BTLessEqualStrategyNumber:
00207 retval = (*tinfo->f_ge) (query, key->lower);
00208 break;
00209 case BTLessStrategyNumber:
00210 if (is_leaf)
00211 retval = (*tinfo->f_gt) (query, key->lower);
00212 else
00213 retval = (*tinfo->f_ge) (query, key->lower);
00214 break;
00215 case BTEqualStrategyNumber:
00216 if (is_leaf)
00217 retval = (*tinfo->f_eq) (query, key->lower);
00218 else
00219 retval = ((*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper)) ? true : false;
00220 break;
00221 case BTGreaterStrategyNumber:
00222 if (is_leaf)
00223 retval = (*tinfo->f_lt) (query, key->upper);
00224 else
00225 retval = (*tinfo->f_le) (query, key->upper);
00226 break;
00227 case BTGreaterEqualStrategyNumber:
00228 retval = (*tinfo->f_le) (query, key->upper);
00229 break;
00230 case BtreeGistNotEqualStrategyNumber:
00231 retval = (!((*tinfo->f_eq) (query, key->lower) &&
00232 (*tinfo->f_eq) (query, key->upper))) ? true : false;
00233 break;
00234 default:
00235 retval = false;
00236 }
00237
00238 return (retval);
00239 }
00240
00241
00242
00243
00244
00245
00246 float8
00247 gbt_num_distance(const GBT_NUMKEY_R *key,
00248 const void *query,
00249 bool is_leaf,
00250 const gbtree_ninfo *tinfo)
00251 {
00252 float8 retval;
00253
00254 if (tinfo->f_dist == NULL)
00255 elog(ERROR, "KNN search is not supported for btree_gist type %d",
00256 (int) tinfo->t);
00257 if (tinfo->f_le(query, key->lower))
00258 retval = tinfo->f_dist(query, key->lower);
00259 else if (tinfo->f_ge(query, key->upper))
00260 retval = tinfo->f_dist(query, key->upper);
00261 else
00262 retval = 0.0;
00263
00264 return retval;
00265 }
00266
00267
00268 GIST_SPLITVEC *
00269 gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
00270 const gbtree_ninfo *tinfo)
00271 {
00272 OffsetNumber i,
00273 maxoff = entryvec->n - 1;
00274 Nsrt *arr;
00275 int nbytes;
00276
00277 arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
00278 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
00279 v->spl_left = (OffsetNumber *) palloc(nbytes);
00280 v->spl_right = (OffsetNumber *) palloc(nbytes);
00281 v->spl_ldatum = PointerGetDatum(0);
00282 v->spl_rdatum = PointerGetDatum(0);
00283 v->spl_nleft = 0;
00284 v->spl_nright = 0;
00285
00286
00287
00288 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
00289 {
00290 arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
00291 arr[i].i = i;
00292 }
00293 qsort((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), tinfo->f_cmp);
00294
00295
00296
00297 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
00298 {
00299 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
00300 {
00301 gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
00302 v->spl_left[v->spl_nleft] = arr[i].i;
00303 v->spl_nleft++;
00304 }
00305 else
00306 {
00307 gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
00308 v->spl_right[v->spl_nright] = arr[i].i;
00309 v->spl_nright++;
00310 }
00311 }
00312
00313 return v;
00314 }