Header And Logo

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

btree_time.c

Go to the documentation of this file.
00001 /*
00002  * contrib/btree_gist/btree_time.c
00003  */
00004 #include "postgres.h"
00005 
00006 #include "btree_gist.h"
00007 #include "btree_utils_num.h"
00008 #include "utils/date.h"
00009 #include "utils/timestamp.h"
00010 
00011 typedef struct
00012 {
00013     TimeADT     lower;
00014     TimeADT     upper;
00015 } timeKEY;
00016 
00017 /*
00018 ** time ops
00019 */
00020 PG_FUNCTION_INFO_V1(gbt_time_compress);
00021 PG_FUNCTION_INFO_V1(gbt_timetz_compress);
00022 PG_FUNCTION_INFO_V1(gbt_time_union);
00023 PG_FUNCTION_INFO_V1(gbt_time_picksplit);
00024 PG_FUNCTION_INFO_V1(gbt_time_consistent);
00025 PG_FUNCTION_INFO_V1(gbt_time_distance);
00026 PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
00027 PG_FUNCTION_INFO_V1(gbt_time_penalty);
00028 PG_FUNCTION_INFO_V1(gbt_time_same);
00029 
00030 Datum       gbt_time_compress(PG_FUNCTION_ARGS);
00031 Datum       gbt_timetz_compress(PG_FUNCTION_ARGS);
00032 Datum       gbt_time_union(PG_FUNCTION_ARGS);
00033 Datum       gbt_time_picksplit(PG_FUNCTION_ARGS);
00034 Datum       gbt_time_consistent(PG_FUNCTION_ARGS);
00035 Datum       gbt_time_distance(PG_FUNCTION_ARGS);
00036 Datum       gbt_timetz_consistent(PG_FUNCTION_ARGS);
00037 Datum       gbt_time_penalty(PG_FUNCTION_ARGS);
00038 Datum       gbt_time_same(PG_FUNCTION_ARGS);
00039 
00040 
00041 #ifdef USE_FLOAT8_BYVAL
00042 #define TimeADTGetDatumFast(X) TimeADTGetDatum(X)
00043 #else
00044 #define TimeADTGetDatumFast(X) PointerGetDatum(&(X))
00045 #endif
00046 
00047 
00048 static bool
00049 gbt_timegt(const void *a, const void *b)
00050 {
00051     const TimeADT *aa = (const TimeADT *) a;
00052     const TimeADT *bb = (const TimeADT *) b;
00053 
00054     return DatumGetBool(DirectFunctionCall2(time_gt,
00055                                             TimeADTGetDatumFast(*aa),
00056                                             TimeADTGetDatumFast(*bb)));
00057 }
00058 
00059 static bool
00060 gbt_timege(const void *a, const void *b)
00061 {
00062     const TimeADT *aa = (const TimeADT *) a;
00063     const TimeADT *bb = (const TimeADT *) b;
00064 
00065     return DatumGetBool(DirectFunctionCall2(time_ge,
00066                                             TimeADTGetDatumFast(*aa),
00067                                             TimeADTGetDatumFast(*bb)));
00068 }
00069 
00070 static bool
00071 gbt_timeeq(const void *a, const void *b)
00072 {
00073     const TimeADT *aa = (const TimeADT *) a;
00074     const TimeADT *bb = (const TimeADT *) b;
00075 
00076     return DatumGetBool(DirectFunctionCall2(time_eq,
00077                                             TimeADTGetDatumFast(*aa),
00078                                             TimeADTGetDatumFast(*bb)));
00079 }
00080 
00081 static bool
00082 gbt_timele(const void *a, const void *b)
00083 {
00084     const TimeADT *aa = (const TimeADT *) a;
00085     const TimeADT *bb = (const TimeADT *) b;
00086 
00087     return DatumGetBool(DirectFunctionCall2(time_le,
00088                                             TimeADTGetDatumFast(*aa),
00089                                             TimeADTGetDatumFast(*bb)));
00090 }
00091 
00092 static bool
00093 gbt_timelt(const void *a, const void *b)
00094 {
00095     const TimeADT *aa = (const TimeADT *) a;
00096     const TimeADT *bb = (const TimeADT *) b;
00097 
00098     return DatumGetBool(DirectFunctionCall2(time_lt,
00099                                             TimeADTGetDatumFast(*aa),
00100                                             TimeADTGetDatumFast(*bb)));
00101 }
00102 
00103 
00104 
00105 static int
00106 gbt_timekey_cmp(const void *a, const void *b)
00107 {
00108     timeKEY    *ia = (timeKEY *) (((const Nsrt *) a)->t);
00109     timeKEY    *ib = (timeKEY *) (((const Nsrt *) b)->t);
00110     int         res;
00111 
00112     res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->lower), TimeADTGetDatumFast(ib->lower)));
00113     if (res == 0)
00114         return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->upper), TimeADTGetDatumFast(ib->upper)));
00115 
00116     return res;
00117 }
00118 
00119 static float8
00120 gbt_time_dist(const void *a, const void *b)
00121 {
00122     const TimeADT *aa = (const TimeADT *) a;
00123     const TimeADT *bb = (const TimeADT *) b;
00124     Interval   *i;
00125 
00126     i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
00127                                               TimeADTGetDatumFast(*aa),
00128                                               TimeADTGetDatumFast(*bb)));
00129     return (float8) Abs(INTERVAL_TO_SEC(i));
00130 }
00131 
00132 
00133 static const gbtree_ninfo tinfo =
00134 {
00135     gbt_t_time,
00136     sizeof(TimeADT),
00137     gbt_timegt,
00138     gbt_timege,
00139     gbt_timeeq,
00140     gbt_timele,
00141     gbt_timelt,
00142     gbt_timekey_cmp,
00143     gbt_time_dist
00144 };
00145 
00146 
00147 PG_FUNCTION_INFO_V1(time_dist);
00148 Datum       time_dist(PG_FUNCTION_ARGS);
00149 Datum
00150 time_dist(PG_FUNCTION_ARGS)
00151 {
00152     Datum       diff = DirectFunctionCall2(time_mi_time,
00153                                            PG_GETARG_DATUM(0),
00154                                            PG_GETARG_DATUM(1));
00155 
00156     PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
00157 }
00158 
00159 
00160 /**************************************************
00161  * time ops
00162  **************************************************/
00163 
00164 
00165 
00166 Datum
00167 gbt_time_compress(PG_FUNCTION_ARGS)
00168 {
00169     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00170     GISTENTRY  *retval = NULL;
00171 
00172     PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
00173 }
00174 
00175 
00176 Datum
00177 gbt_timetz_compress(PG_FUNCTION_ARGS)
00178 {
00179     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00180     GISTENTRY  *retval;
00181 
00182     if (entry->leafkey)
00183     {
00184         timeKEY    *r = (timeKEY *) palloc(sizeof(timeKEY));
00185         TimeTzADT  *tz = DatumGetTimeTzADTP(entry->key);
00186         TimeADT     tmp;
00187 
00188         retval = palloc(sizeof(GISTENTRY));
00189 
00190         /* We are using the time + zone only to compress */
00191 #ifdef HAVE_INT64_TIMESTAMP
00192         tmp = tz->time + (tz->zone * INT64CONST(1000000));
00193 #else
00194         tmp = (tz->time + tz->zone);
00195 #endif
00196         r->lower = r->upper = tmp;
00197         gistentryinit(*retval, PointerGetDatum(r),
00198                       entry->rel, entry->page,
00199                       entry->offset, FALSE);
00200     }
00201     else
00202         retval = entry;
00203     PG_RETURN_POINTER(retval);
00204 }
00205 
00206 
00207 Datum
00208 gbt_time_consistent(PG_FUNCTION_ARGS)
00209 {
00210     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00211     TimeADT     query = PG_GETARG_TIMEADT(1);
00212     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
00213 
00214     /* Oid      subtype = PG_GETARG_OID(3); */
00215     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
00216     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
00217     GBT_NUMKEY_R key;
00218 
00219     /* All cases served by this function are exact */
00220     *recheck = false;
00221 
00222     key.lower = (GBT_NUMKEY *) &kkk->lower;
00223     key.upper = (GBT_NUMKEY *) &kkk->upper;
00224 
00225     PG_RETURN_BOOL(
00226                    gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
00227         );
00228 }
00229 
00230 Datum
00231 gbt_time_distance(PG_FUNCTION_ARGS)
00232 {
00233     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00234     TimeADT     query = PG_GETARG_TIMEADT(1);
00235 
00236     /* Oid      subtype = PG_GETARG_OID(3); */
00237     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
00238     GBT_NUMKEY_R key;
00239 
00240     key.lower = (GBT_NUMKEY *) &kkk->lower;
00241     key.upper = (GBT_NUMKEY *) &kkk->upper;
00242 
00243     PG_RETURN_FLOAT8(
00244             gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
00245         );
00246 }
00247 
00248 Datum
00249 gbt_timetz_consistent(PG_FUNCTION_ARGS)
00250 {
00251     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00252     TimeTzADT  *query = PG_GETARG_TIMETZADT_P(1);
00253     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
00254 
00255     /* Oid      subtype = PG_GETARG_OID(3); */
00256     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
00257     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
00258     TimeADT     qqq;
00259     GBT_NUMKEY_R key;
00260 
00261     /* All cases served by this function are inexact */
00262     *recheck = true;
00263 
00264 #ifdef HAVE_INT64_TIMESTAMP
00265     qqq = query->time + (query->zone * INT64CONST(1000000));
00266 #else
00267     qqq = (query->time + query->zone);
00268 #endif
00269 
00270     key.lower = (GBT_NUMKEY *) &kkk->lower;
00271     key.upper = (GBT_NUMKEY *) &kkk->upper;
00272 
00273     PG_RETURN_BOOL(
00274                    gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo)
00275         );
00276 }
00277 
00278 
00279 Datum
00280 gbt_time_union(PG_FUNCTION_ARGS)
00281 {
00282     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
00283     void       *out = palloc(sizeof(timeKEY));
00284 
00285     *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
00286     PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
00287 }
00288 
00289 
00290 Datum
00291 gbt_time_penalty(PG_FUNCTION_ARGS)
00292 {
00293     timeKEY    *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
00294     timeKEY    *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
00295     float      *result = (float *) PG_GETARG_POINTER(2);
00296     Interval   *intr;
00297     double      res;
00298     double      res2;
00299 
00300     intr = DatumGetIntervalP(DirectFunctionCall2(
00301                                                  time_mi_time,
00302                                         TimeADTGetDatumFast(newentry->upper),
00303                                      TimeADTGetDatumFast(origentry->upper)));
00304     res = INTERVAL_TO_SEC(intr);
00305     res = Max(res, 0);
00306 
00307     intr = DatumGetIntervalP(DirectFunctionCall2(
00308                                                  time_mi_time,
00309                                        TimeADTGetDatumFast(origentry->lower),
00310                                       TimeADTGetDatumFast(newentry->lower)));
00311     res2 = INTERVAL_TO_SEC(intr);
00312     res2 = Max(res2, 0);
00313 
00314     res += res2;
00315 
00316     *result = 0.0;
00317 
00318     if (res > 0)
00319     {
00320         intr = DatumGetIntervalP(DirectFunctionCall2(
00321                                                      time_mi_time,
00322                                        TimeADTGetDatumFast(origentry->upper),
00323                                      TimeADTGetDatumFast(origentry->lower)));
00324         *result += FLT_MIN;
00325         *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
00326         *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
00327     }
00328 
00329     PG_RETURN_POINTER(result);
00330 }
00331 
00332 
00333 Datum
00334 gbt_time_picksplit(PG_FUNCTION_ARGS)
00335 {
00336     PG_RETURN_POINTER(gbt_num_picksplit(
00337                                     (GistEntryVector *) PG_GETARG_POINTER(0),
00338                                       (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
00339                                         &tinfo
00340                                         ));
00341 }
00342 
00343 Datum
00344 gbt_time_same(PG_FUNCTION_ARGS)
00345 {
00346     timeKEY    *b1 = (timeKEY *) PG_GETARG_POINTER(0);
00347     timeKEY    *b2 = (timeKEY *) PG_GETARG_POINTER(1);
00348     bool       *result = (bool *) PG_GETARG_POINTER(2);
00349 
00350     *result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
00351     PG_RETURN_POINTER(result);
00352 }