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
00010 typedef struct
00011 {
00012 DateADT lower;
00013 DateADT upper;
00014 } dateKEY;
00015
00016
00017
00018
00019 PG_FUNCTION_INFO_V1(gbt_date_compress);
00020 PG_FUNCTION_INFO_V1(gbt_date_union);
00021 PG_FUNCTION_INFO_V1(gbt_date_picksplit);
00022 PG_FUNCTION_INFO_V1(gbt_date_consistent);
00023 PG_FUNCTION_INFO_V1(gbt_date_distance);
00024 PG_FUNCTION_INFO_V1(gbt_date_penalty);
00025 PG_FUNCTION_INFO_V1(gbt_date_same);
00026
00027 Datum gbt_date_compress(PG_FUNCTION_ARGS);
00028 Datum gbt_date_union(PG_FUNCTION_ARGS);
00029 Datum gbt_date_picksplit(PG_FUNCTION_ARGS);
00030 Datum gbt_date_consistent(PG_FUNCTION_ARGS);
00031 Datum gbt_date_distance(PG_FUNCTION_ARGS);
00032 Datum gbt_date_penalty(PG_FUNCTION_ARGS);
00033 Datum gbt_date_same(PG_FUNCTION_ARGS);
00034
00035 static bool
00036 gbt_dategt(const void *a, const void *b)
00037 {
00038 return DatumGetBool(
00039 DirectFunctionCall2(date_gt, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
00040 );
00041 }
00042
00043 static bool
00044 gbt_datege(const void *a, const void *b)
00045 {
00046 return DatumGetBool(
00047 DirectFunctionCall2(date_ge, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
00048 );
00049 }
00050
00051 static bool
00052 gbt_dateeq(const void *a, const void *b)
00053 {
00054 return DatumGetBool(
00055 DirectFunctionCall2(date_eq, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
00056 );
00057 }
00058
00059 static bool
00060 gbt_datele(const void *a, const void *b)
00061 {
00062 return DatumGetBool(
00063 DirectFunctionCall2(date_le, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
00064 );
00065 }
00066
00067 static bool
00068 gbt_datelt(const void *a, const void *b)
00069 {
00070 return DatumGetBool(
00071 DirectFunctionCall2(date_lt, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
00072 );
00073 }
00074
00075
00076
00077 static int
00078 gbt_datekey_cmp(const void *a, const void *b)
00079 {
00080 dateKEY *ia = (dateKEY *) (((const Nsrt *) a)->t);
00081 dateKEY *ib = (dateKEY *) (((const Nsrt *) b)->t);
00082 int res;
00083
00084 res = DatumGetInt32(DirectFunctionCall2(date_cmp, DateADTGetDatum(ia->lower), DateADTGetDatum(ib->lower)));
00085 if (res == 0)
00086 return DatumGetInt32(DirectFunctionCall2(date_cmp, DateADTGetDatum(ia->upper), DateADTGetDatum(ib->upper)));
00087
00088 return res;
00089 }
00090
00091 static float8
00092 gdb_date_dist(const void *a, const void *b)
00093 {
00094
00095 Datum diff = DirectFunctionCall2(date_mi,
00096 DateADTGetDatum(*((const DateADT *) a)),
00097 DateADTGetDatum(*((const DateADT *) b)));
00098
00099 return (float8) Abs(DatumGetInt32(diff));
00100 }
00101
00102
00103 static const gbtree_ninfo tinfo =
00104 {
00105 gbt_t_date,
00106 sizeof(DateADT),
00107 gbt_dategt,
00108 gbt_datege,
00109 gbt_dateeq,
00110 gbt_datele,
00111 gbt_datelt,
00112 gbt_datekey_cmp,
00113 gdb_date_dist
00114 };
00115
00116
00117 PG_FUNCTION_INFO_V1(date_dist);
00118 Datum date_dist(PG_FUNCTION_ARGS);
00119 Datum
00120 date_dist(PG_FUNCTION_ARGS)
00121 {
00122
00123 Datum diff = DirectFunctionCall2(date_mi,
00124 PG_GETARG_DATUM(0),
00125 PG_GETARG_DATUM(1));
00126
00127 PG_RETURN_INT32(Abs(DatumGetInt32(diff)));
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 Datum
00138 gbt_date_compress(PG_FUNCTION_ARGS)
00139 {
00140 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00141 GISTENTRY *retval = NULL;
00142
00143 PG_RETURN_POINTER(gbt_num_compress(retval, entry, &tinfo));
00144 }
00145
00146
00147
00148 Datum
00149 gbt_date_consistent(PG_FUNCTION_ARGS)
00150 {
00151 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00152 DateADT query = PG_GETARG_DATEADT(1);
00153 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
00154
00155
00156 bool *recheck = (bool *) PG_GETARG_POINTER(4);
00157 dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
00158 GBT_NUMKEY_R key;
00159
00160
00161 *recheck = false;
00162
00163 key.lower = (GBT_NUMKEY *) &kkk->lower;
00164 key.upper = (GBT_NUMKEY *) &kkk->upper;
00165
00166 PG_RETURN_BOOL(
00167 gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
00168 );
00169 }
00170
00171
00172 Datum
00173 gbt_date_distance(PG_FUNCTION_ARGS)
00174 {
00175 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00176 DateADT query = PG_GETARG_DATEADT(1);
00177
00178
00179 dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
00180 GBT_NUMKEY_R key;
00181
00182 key.lower = (GBT_NUMKEY *) &kkk->lower;
00183 key.upper = (GBT_NUMKEY *) &kkk->upper;
00184
00185 PG_RETURN_FLOAT8(
00186 gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
00187 );
00188 }
00189
00190
00191 Datum
00192 gbt_date_union(PG_FUNCTION_ARGS)
00193 {
00194 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
00195 void *out = palloc(sizeof(dateKEY));
00196
00197 *(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
00198 PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
00199 }
00200
00201
00202 Datum
00203 gbt_date_penalty(PG_FUNCTION_ARGS)
00204 {
00205 dateKEY *origentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
00206 dateKEY *newentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
00207 float *result = (float *) PG_GETARG_POINTER(2);
00208 int32 diff,
00209 res;
00210
00211 diff = DatumGetInt32(DirectFunctionCall2(
00212 date_mi,
00213 DateADTGetDatum(newentry->upper),
00214 DateADTGetDatum(origentry->upper)));
00215
00216 res = Max(diff, 0);
00217
00218 diff = DatumGetInt32(DirectFunctionCall2(
00219 date_mi,
00220 DateADTGetDatum(origentry->lower),
00221 DateADTGetDatum(newentry->lower)));
00222
00223 res += Max(diff, 0);
00224
00225 *result = 0.0;
00226
00227 if (res > 0)
00228 {
00229 diff = DatumGetInt32(DirectFunctionCall2(
00230 date_mi,
00231 DateADTGetDatum(origentry->upper),
00232 DateADTGetDatum(origentry->lower)));
00233 *result += FLT_MIN;
00234 *result += (float) (res / ((double) (res + diff)));
00235 *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
00236 }
00237
00238 PG_RETURN_POINTER(result);
00239 }
00240
00241
00242 Datum
00243 gbt_date_picksplit(PG_FUNCTION_ARGS)
00244 {
00245 PG_RETURN_POINTER(gbt_num_picksplit(
00246 (GistEntryVector *) PG_GETARG_POINTER(0),
00247 (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
00248 &tinfo
00249 ));
00250 }
00251
00252 Datum
00253 gbt_date_same(PG_FUNCTION_ARGS)
00254 {
00255 dateKEY *b1 = (dateKEY *) PG_GETARG_POINTER(0);
00256 dateKEY *b2 = (dateKEY *) PG_GETARG_POINTER(1);
00257 bool *result = (bool *) PG_GETARG_POINTER(2);
00258
00259 *result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
00260 PG_RETURN_POINTER(result);
00261 }