Header And Logo

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

btree_date.c

Go to the documentation of this file.
00001 /*
00002  * contrib/btree_gist/btree_date.c
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 ** date ops
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     /* we assume the difference can't overflow */
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     /* we assume the difference can't overflow */
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  * date ops
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     /* Oid      subtype = PG_GETARG_OID(3); */
00156     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
00157     dateKEY    *kkk = (dateKEY *) DatumGetPointer(entry->key);
00158     GBT_NUMKEY_R key;
00159 
00160     /* All cases served by this function are exact */
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     /* Oid      subtype = PG_GETARG_OID(3); */
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 }