00001
00002
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
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
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
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
00215 bool *recheck = (bool *) PG_GETARG_POINTER(4);
00216 timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
00217 GBT_NUMKEY_R key;
00218
00219
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
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
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
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 }