1 /* 2 * contrib/btree_gist/btree_date.c 3 */ 4 #include "postgres.h" 5 6 #include "btree_gist.h" 7 #include "btree_utils_num.h" 8 #include "utils/builtins.h" 9 #include "utils/date.h" 10 11 typedef struct 12 { 13 DateADT lower; 14 DateADT upper; 15 } dateKEY; 16 17 /* 18 ** date ops 19 */ 20 PG_FUNCTION_INFO_V1(gbt_date_compress); 21 PG_FUNCTION_INFO_V1(gbt_date_fetch); 22 PG_FUNCTION_INFO_V1(gbt_date_union); 23 PG_FUNCTION_INFO_V1(gbt_date_picksplit); 24 PG_FUNCTION_INFO_V1(gbt_date_consistent); 25 PG_FUNCTION_INFO_V1(gbt_date_distance); 26 PG_FUNCTION_INFO_V1(gbt_date_penalty); 27 PG_FUNCTION_INFO_V1(gbt_date_same); 28 29 static bool 30 gbt_dategt(const void *a, const void *b, FmgrInfo *flinfo) 31 { 32 return DatumGetBool( 33 DirectFunctionCall2(date_gt, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b))) 34 ); 35 } 36 37 static bool 38 gbt_datege(const void *a, const void *b, FmgrInfo *flinfo) 39 { 40 return DatumGetBool( 41 DirectFunctionCall2(date_ge, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b))) 42 ); 43 } 44 45 static bool 46 gbt_dateeq(const void *a, const void *b, FmgrInfo *flinfo) 47 { 48 return DatumGetBool( 49 DirectFunctionCall2(date_eq, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b))) 50 ); 51 } 52 53 static bool 54 gbt_datele(const void *a, const void *b, FmgrInfo *flinfo) 55 { 56 return DatumGetBool( 57 DirectFunctionCall2(date_le, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b))) 58 ); 59 } 60 61 static bool 62 gbt_datelt(const void *a, const void *b, FmgrInfo *flinfo) 63 { 64 return DatumGetBool( 65 DirectFunctionCall2(date_lt, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b))) 66 ); 67 } 68 69 70 71 static int 72 gbt_datekey_cmp(const void *a, const void *b, FmgrInfo *flinfo) 73 { 74 dateKEY *ia = (dateKEY *) (((const Nsrt *) a)->t); 75 dateKEY *ib = (dateKEY *) (((const Nsrt *) b)->t); 76 int res; 77 78 res = DatumGetInt32(DirectFunctionCall2(date_cmp, DateADTGetDatum(ia->lower), DateADTGetDatum(ib->lower))); 79 if (res == 0) 80 return DatumGetInt32(DirectFunctionCall2(date_cmp, DateADTGetDatum(ia->upper), DateADTGetDatum(ib->upper))); 81 82 return res; 83 } 84 85 static float8 86 gdb_date_dist(const void *a, const void *b, FmgrInfo *flinfo) 87 { 88 /* we assume the difference can't overflow */ 89 Datum diff = DirectFunctionCall2(date_mi, 90 DateADTGetDatum(*((const DateADT *) a)), 91 DateADTGetDatum(*((const DateADT *) b))); 92 93 return (float8) Abs(DatumGetInt32(diff)); 94 } 95 96 97 static const gbtree_ninfo tinfo = 98 { 99 gbt_t_date, 100 sizeof(DateADT), 101 8, /* sizeof(gbtreekey8) */ 102 gbt_dategt, 103 gbt_datege, 104 gbt_dateeq, 105 gbt_datele, 106 gbt_datelt, 107 gbt_datekey_cmp, 108 gdb_date_dist 109 }; 110 111 112 PG_FUNCTION_INFO_V1(date_dist); 113 Datum 114 date_dist(PG_FUNCTION_ARGS) 115 { 116 /* we assume the difference can't overflow */ 117 Datum diff = DirectFunctionCall2(date_mi, 118 PG_GETARG_DATUM(0), 119 PG_GETARG_DATUM(1)); 120 121 PG_RETURN_INT32(Abs(DatumGetInt32(diff))); 122 } 123 124 125 /************************************************** 126 * date ops 127 **************************************************/ 128 129 130 131 Datum 132 gbt_date_compress(PG_FUNCTION_ARGS) 133 { 134 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); 135 136 PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo)); 137 } 138 139 Datum 140 gbt_date_fetch(PG_FUNCTION_ARGS) 141 { 142 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); 143 144 PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo)); 145 } 146 147 Datum 148 gbt_date_consistent(PG_FUNCTION_ARGS) 149 { 150 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); 151 DateADT query = PG_GETARG_DATEADT(1); 152 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); 153 154 /* Oid subtype = PG_GETARG_OID(3); */ 155 bool *recheck = (bool *) PG_GETARG_POINTER(4); 156 dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key); 157 GBT_NUMKEY_R key; 158 159 /* All cases served by this function are exact */ 160 *recheck = false; 161 162 key.lower = (GBT_NUMKEY *) &kkk->lower; 163 key.upper = (GBT_NUMKEY *) &kkk->upper; 164 165 PG_RETURN_BOOL( 166 gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo) 167 ); 168 } 169 170 171 Datum 172 gbt_date_distance(PG_FUNCTION_ARGS) 173 { 174 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); 175 DateADT query = PG_GETARG_DATEADT(1); 176 177 /* Oid subtype = PG_GETARG_OID(3); */ 178 dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key); 179 GBT_NUMKEY_R key; 180 181 key.lower = (GBT_NUMKEY *) &kkk->lower; 182 key.upper = (GBT_NUMKEY *) &kkk->upper; 183 184 PG_RETURN_FLOAT8( 185 gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo) 186 ); 187 } 188 189 190 Datum 191 gbt_date_union(PG_FUNCTION_ARGS) 192 { 193 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); 194 void *out = palloc(sizeof(dateKEY)); 195 196 *(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY); 197 PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); 198 } 199 200 201 Datum 202 gbt_date_penalty(PG_FUNCTION_ARGS) 203 { 204 dateKEY *origentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); 205 dateKEY *newentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); 206 float *result = (float *) PG_GETARG_POINTER(2); 207 int32 diff, 208 res; 209 210 diff = DatumGetInt32(DirectFunctionCall2( 211 date_mi, 212 DateADTGetDatum(newentry->upper), 213 DateADTGetDatum(origentry->upper))); 214 215 res = Max(diff, 0); 216 217 diff = DatumGetInt32(DirectFunctionCall2( 218 date_mi, 219 DateADTGetDatum(origentry->lower), 220 DateADTGetDatum(newentry->lower))); 221 222 res += Max(diff, 0); 223 224 *result = 0.0; 225 226 if (res > 0) 227 { 228 diff = DatumGetInt32(DirectFunctionCall2( 229 date_mi, 230 DateADTGetDatum(origentry->upper), 231 DateADTGetDatum(origentry->lower))); 232 *result += FLT_MIN; 233 *result += (float) (res / ((double) (res + diff))); 234 *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); 235 } 236 237 PG_RETURN_POINTER(result); 238 } 239 240 241 Datum 242 gbt_date_picksplit(PG_FUNCTION_ARGS) 243 { 244 PG_RETURN_POINTER(gbt_num_picksplit( 245 (GistEntryVector *) PG_GETARG_POINTER(0), 246 (GIST_SPLITVEC *) PG_GETARG_POINTER(1), 247 &tinfo, fcinfo->flinfo 248 )); 249 } 250 251 Datum 252 gbt_date_same(PG_FUNCTION_ARGS) 253 { 254 dateKEY *b1 = (dateKEY *) PG_GETARG_POINTER(0); 255 dateKEY *b2 = (dateKEY *) PG_GETARG_POINTER(1); 256 bool *result = (bool *) PG_GETARG_POINTER(2); 257 258 *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); 259 PG_RETURN_POINTER(result); 260 } 261