Header And Logo

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

btree_numeric.c

Go to the documentation of this file.
00001 /*
00002  * contrib/btree_gist/btree_numeric.c
00003  */
00004 #include "postgres.h"
00005 
00006 #include "btree_gist.h"
00007 
00008 #include <math.h>
00009 #include <float.h>
00010 
00011 #include "btree_utils_var.h"
00012 #include "utils/builtins.h"
00013 #include "utils/numeric.h"
00014 #include "utils/rel.h"
00015 
00016 /*
00017 ** Bytea ops
00018 */
00019 PG_FUNCTION_INFO_V1(gbt_numeric_compress);
00020 PG_FUNCTION_INFO_V1(gbt_numeric_union);
00021 PG_FUNCTION_INFO_V1(gbt_numeric_picksplit);
00022 PG_FUNCTION_INFO_V1(gbt_numeric_consistent);
00023 PG_FUNCTION_INFO_V1(gbt_numeric_penalty);
00024 PG_FUNCTION_INFO_V1(gbt_numeric_same);
00025 
00026 Datum       gbt_numeric_compress(PG_FUNCTION_ARGS);
00027 Datum       gbt_numeric_union(PG_FUNCTION_ARGS);
00028 Datum       gbt_numeric_picksplit(PG_FUNCTION_ARGS);
00029 Datum       gbt_numeric_consistent(PG_FUNCTION_ARGS);
00030 Datum       gbt_numeric_penalty(PG_FUNCTION_ARGS);
00031 Datum       gbt_numeric_same(PG_FUNCTION_ARGS);
00032 
00033 
00034 /* define for comparison */
00035 
00036 static bool
00037 gbt_numeric_gt(const void *a, const void *b, Oid collation)
00038 {
00039     return DatumGetBool(DirectFunctionCall2(numeric_gt,
00040                                             PointerGetDatum(a),
00041                                             PointerGetDatum(b)));
00042 }
00043 
00044 static bool
00045 gbt_numeric_ge(const void *a, const void *b, Oid collation)
00046 {
00047     return DatumGetBool(DirectFunctionCall2(numeric_ge,
00048                                             PointerGetDatum(a),
00049                                             PointerGetDatum(b)));
00050 }
00051 
00052 static bool
00053 gbt_numeric_eq(const void *a, const void *b, Oid collation)
00054 {
00055     return DatumGetBool(DirectFunctionCall2(numeric_eq,
00056                                             PointerGetDatum(a),
00057                                             PointerGetDatum(b)));
00058 }
00059 
00060 static bool
00061 gbt_numeric_le(const void *a, const void *b, Oid collation)
00062 {
00063     return DatumGetBool(DirectFunctionCall2(numeric_le,
00064                                             PointerGetDatum(a),
00065                                             PointerGetDatum(b)));
00066 }
00067 
00068 static bool
00069 gbt_numeric_lt(const void *a, const void *b, Oid collation)
00070 {
00071     return DatumGetBool(DirectFunctionCall2(numeric_lt,
00072                                             PointerGetDatum(a),
00073                                             PointerGetDatum(b)));
00074 }
00075 
00076 static int32
00077 gbt_numeric_cmp(const void *a, const void *b, Oid collation)
00078 {
00079     return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
00080                                              PointerGetDatum(a),
00081                                              PointerGetDatum(b)));
00082 }
00083 
00084 
00085 static const gbtree_vinfo tinfo =
00086 {
00087     gbt_t_numeric,
00088     0,
00089     FALSE,
00090     gbt_numeric_gt,
00091     gbt_numeric_ge,
00092     gbt_numeric_eq,
00093     gbt_numeric_le,
00094     gbt_numeric_lt,
00095     gbt_numeric_cmp,
00096     NULL
00097 };
00098 
00099 
00100 /**************************************************
00101  * Text ops
00102  **************************************************/
00103 
00104 
00105 Datum
00106 gbt_numeric_compress(PG_FUNCTION_ARGS)
00107 {
00108     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00109 
00110     PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
00111 }
00112 
00113 
00114 
00115 Datum
00116 gbt_numeric_consistent(PG_FUNCTION_ARGS)
00117 {
00118     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00119     void       *query = (void *) DatumGetNumeric(PG_GETARG_DATUM(1));
00120     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
00121 
00122     /* Oid      subtype = PG_GETARG_OID(3); */
00123     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
00124     bool        retval;
00125     GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
00126     GBT_VARKEY_R r = gbt_var_key_readable(key);
00127 
00128     /* All cases served by this function are exact */
00129     *recheck = false;
00130 
00131     retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
00132                                 GIST_LEAF(entry), &tinfo);
00133     PG_RETURN_BOOL(retval);
00134 }
00135 
00136 
00137 
00138 Datum
00139 gbt_numeric_union(PG_FUNCTION_ARGS)
00140 {
00141     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
00142     int32      *size = (int *) PG_GETARG_POINTER(1);
00143 
00144     PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
00145                                     &tinfo));
00146 }
00147 
00148 
00149 Datum
00150 gbt_numeric_same(PG_FUNCTION_ARGS)
00151 {
00152     Datum       d1 = PG_GETARG_DATUM(0);
00153     Datum       d2 = PG_GETARG_DATUM(1);
00154     bool       *result = (bool *) PG_GETARG_POINTER(2);
00155 
00156     *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
00157     PG_RETURN_POINTER(result);
00158 }
00159 
00160 
00161 Datum
00162 gbt_numeric_penalty(PG_FUNCTION_ARGS)
00163 {
00164     GISTENTRY  *o = (GISTENTRY *) PG_GETARG_POINTER(0);
00165     GISTENTRY  *n = (GISTENTRY *) PG_GETARG_POINTER(1);
00166     float      *result = (float *) PG_GETARG_POINTER(2);
00167 
00168     Numeric     us,
00169                 os,
00170                 ds;
00171 
00172     GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
00173     GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
00174     Datum       uni;
00175     GBT_VARKEY_R rk,
00176                 ok,
00177                 uk;
00178 
00179     rk = gbt_var_key_readable(org);
00180     uni = PointerGetDatum(gbt_var_key_copy(&rk, TRUE));
00181     gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo);
00182     ok = gbt_var_key_readable(org);
00183     uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
00184 
00185     us = DatumGetNumeric(DirectFunctionCall2(
00186                                              numeric_sub,
00187                                              PointerGetDatum(uk.upper),
00188                                              PointerGetDatum(uk.lower)
00189                                              ));
00190 
00191     os = DatumGetNumeric(DirectFunctionCall2(
00192                                              numeric_sub,
00193                                              PointerGetDatum(ok.upper),
00194                                              PointerGetDatum(ok.lower)
00195                                              ));
00196 
00197     ds = DatumGetNumeric(DirectFunctionCall2(
00198                                              numeric_sub,
00199                                              NumericGetDatum(us),
00200                                              NumericGetDatum(os)
00201                                              ));
00202 
00203     if (numeric_is_nan(us))
00204     {
00205         if (numeric_is_nan(os))
00206             *result = 0.0;
00207         else
00208             *result = 1.0;
00209     }
00210     else
00211     {
00212         Numeric     nul = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(0)));
00213 
00214         *result = 0.0;
00215 
00216         if (DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul)))
00217         {
00218             *result += FLT_MIN;
00219             os = DatumGetNumeric(DirectFunctionCall2(
00220                                                      numeric_div,
00221                                                      NumericGetDatum(ds),
00222                                                      NumericGetDatum(us)
00223                                                      ));
00224             *result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
00225         }
00226     }
00227 
00228     if (*result > 0)
00229         *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
00230 
00231     PG_RETURN_POINTER(result);
00232 }
00233 
00234 
00235 
00236 Datum
00237 gbt_numeric_picksplit(PG_FUNCTION_ARGS)
00238 {
00239     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
00240     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
00241 
00242     gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
00243                       &tinfo);
00244     PG_RETURN_POINTER(v);
00245 }