00001
00002
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
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
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
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
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
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 }