Header And Logo

PostgreSQL
| The world's most advanced open source database.

btree_utils_num.c

Go to the documentation of this file.
00001 /*
00002  * contrib/btree_gist/btree_utils_num.c
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 ** The GiST union method for numerical values
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))  /* out->lower > cur->lower */
00123             memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
00124         if ((*tinfo->f_lt) (o.upper, c.upper))  /* out->upper < cur->upper */
00125             memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
00126     }
00127 
00128     return out;
00129 }
00130 
00131 
00132 
00133 /*
00134 ** The GiST same method for numerical values
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  * The GiST consistent method
00191  *
00192  * Note: we currently assume that no datatypes that use this routine are
00193  * collation-aware; so we don't bother passing collation through.
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 ** The GiST distance method (for KNN-Gist)
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     /* Sort entries */
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     /* We do simply create two parts */
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 }