btree_interval.c 5.43 KB
Newer Older
1 2
#include "btree_gist.h"
#include "btree_utils_num.h"
3
#include "utils/timestamp.h"
4 5 6

typedef struct
{
Bruce Momjian's avatar
Bruce Momjian committed
7 8 9
	Interval	lower,
				upper;
}	intvKEY;
10 11 12 13 14 15


/*
** Interval ops
*/
PG_FUNCTION_INFO_V1(gbt_intv_compress);
16
PG_FUNCTION_INFO_V1(gbt_intv_decompress);
17 18 19 20 21 22
PG_FUNCTION_INFO_V1(gbt_intv_union);
PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
PG_FUNCTION_INFO_V1(gbt_intv_consistent);
PG_FUNCTION_INFO_V1(gbt_intv_penalty);
PG_FUNCTION_INFO_V1(gbt_intv_same);

Bruce Momjian's avatar
Bruce Momjian committed
23 24 25 26 27 28 29
Datum		gbt_intv_compress(PG_FUNCTION_ARGS);
Datum		gbt_intv_decompress(PG_FUNCTION_ARGS);
Datum		gbt_intv_union(PG_FUNCTION_ARGS);
Datum		gbt_intv_picksplit(PG_FUNCTION_ARGS);
Datum		gbt_intv_consistent(PG_FUNCTION_ARGS);
Datum		gbt_intv_penalty(PG_FUNCTION_ARGS);
Datum		gbt_intv_same(PG_FUNCTION_ARGS);
30 31


Bruce Momjian's avatar
Bruce Momjian committed
32 33
static bool
gbt_intvgt(const void *a, const void *b)
34
{
Bruce Momjian's avatar
Bruce Momjian committed
35
	return DatumGetBool(DirectFunctionCall2(interval_gt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
36 37
}

Bruce Momjian's avatar
Bruce Momjian committed
38 39
static bool
gbt_intvge(const void *a, const void *b)
40
{
Bruce Momjian's avatar
Bruce Momjian committed
41
	return DatumGetBool(DirectFunctionCall2(interval_ge, IntervalPGetDatum(a), IntervalPGetDatum(b)));
42 43
}

Bruce Momjian's avatar
Bruce Momjian committed
44 45
static bool
gbt_intveq(const void *a, const void *b)
46
{
Bruce Momjian's avatar
Bruce Momjian committed
47
	return DatumGetBool(DirectFunctionCall2(interval_eq, IntervalPGetDatum(a), IntervalPGetDatum(b)));
48 49
}

Bruce Momjian's avatar
Bruce Momjian committed
50 51
static bool
gbt_intvle(const void *a, const void *b)
52
{
Bruce Momjian's avatar
Bruce Momjian committed
53
	return DatumGetBool(DirectFunctionCall2(interval_le, IntervalPGetDatum(a), IntervalPGetDatum(b)));
54 55
}

Bruce Momjian's avatar
Bruce Momjian committed
56 57
static bool
gbt_intvlt(const void *a, const void *b)
58
{
Bruce Momjian's avatar
Bruce Momjian committed
59
	return DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
60 61 62 63 64
}

static int
gbt_intvkey_cmp(const void *a, const void *b)
{
Bruce Momjian's avatar
Bruce Momjian committed
65 66
	return DatumGetInt32(
						 DirectFunctionCall2(interval_cmp,
67 68
										  IntervalPGetDatum(((Nsrt *) a)->t),
										   IntervalPGetDatum(((Nsrt *) b)->t)
Bruce Momjian's avatar
Bruce Momjian committed
69 70
											 )
		);
71 72
}

73

Bruce Momjian's avatar
Bruce Momjian committed
74 75
static double
intr2num(const Interval *i)
76
{
77
	return INTERVAL_TO_SEC(i);
78 79
}

80 81
/*
 * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
82
 * in pg_type.	This might be less than sizeof(Interval) if the compiler
83 84
 * insists on adding alignment padding at the end of the struct.
 */
85
#define INTERVALSIZE 16
86

Bruce Momjian's avatar
Bruce Momjian committed
87
static const gbtree_ninfo tinfo =
88
{
Bruce Momjian's avatar
Bruce Momjian committed
89 90 91 92 93 94 95 96
	gbt_t_intv,
	sizeof(Interval),
	gbt_intvgt,
	gbt_intvge,
	gbt_intveq,
	gbt_intvle,
	gbt_intvlt,
	gbt_intvkey_cmp
97 98 99 100 101 102 103 104 105 106 107
};


/**************************************************
 * interval ops
 **************************************************/


Datum
gbt_intv_compress(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
	GISTENTRY  *retval = entry;

	if (entry->leafkey || INTERVALSIZE != sizeof(Interval))
	{
		char	   *r = (char *) palloc(2 * INTERVALSIZE);

		retval = palloc(sizeof(GISTENTRY));

		if (entry->leafkey)
		{
			Interval   *key = DatumGetIntervalP(entry->key);

			memcpy((void *) r, (void *) key, INTERVALSIZE);
			memcpy((void *) (r + INTERVALSIZE), (void *) key, INTERVALSIZE);
		}
		else
		{
			intvKEY    *key = (intvKEY *) DatumGetPointer(entry->key);

			memcpy(r, &key->lower, INTERVALSIZE);
			memcpy(r + INTERVALSIZE, &key->upper, INTERVALSIZE);
		}
		gistentryinit(*retval, PointerGetDatum(r),
					  entry->rel, entry->page,
Teodor Sigaev's avatar
Teodor Sigaev committed
133
					  entry->offset, FALSE);
Bruce Momjian's avatar
Bruce Momjian committed
134 135 136
	}

	PG_RETURN_POINTER(retval);
137

138
}
139 140 141 142

Datum
gbt_intv_decompress(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
143 144
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
	GISTENTRY  *retval = entry;
145

Bruce Momjian's avatar
Bruce Momjian committed
146 147 148 149
	if (INTERVALSIZE != sizeof(Interval))
	{
		intvKEY    *r = palloc(sizeof(intvKEY));
		char	   *key = DatumGetPointer(entry->key);
150

Bruce Momjian's avatar
Bruce Momjian committed
151 152 153
		retval = palloc(sizeof(GISTENTRY));
		memcpy(&r->lower, key, INTERVALSIZE);
		memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
154

Bruce Momjian's avatar
Bruce Momjian committed
155 156
		gistentryinit(*retval, PointerGetDatum(r),
					  entry->rel, entry->page,
Teodor Sigaev's avatar
Teodor Sigaev committed
157
					  entry->offset, FALSE);
Bruce Momjian's avatar
Bruce Momjian committed
158 159
	}
	PG_RETURN_POINTER(retval);
160 161
}

162 163 164 165

Datum
gbt_intv_consistent(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
166 167 168 169 170 171 172 173 174 175 176 177
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
	Interval   *query = PG_GETARG_INTERVAL_P(1);
	intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
	GBT_NUMKEY_R key;
	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);

	key.lower = (GBT_NUMKEY *) & kkk->lower;
	key.upper = (GBT_NUMKEY *) & kkk->upper;

	PG_RETURN_BOOL(
				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
		);
178 179 180 181 182 183
}


Datum
gbt_intv_union(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
184 185 186 187 188
	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
	void	   *out = palloc(sizeof(intvKEY));

	*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
189 190 191 192 193 194
}


Datum
gbt_intv_penalty(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
195 196 197 198
	intvKEY    *origentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
	intvKEY    *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
	float	   *result = (float *) PG_GETARG_POINTER(2);
	double		iorg[2],
199
				inew[2];
200

Bruce Momjian's avatar
Bruce Momjian committed
201 202 203 204
	iorg[0] = intr2num(&origentry->lower);
	iorg[1] = intr2num(&origentry->upper);
	inew[0] = intr2num(&newentry->lower);
	inew[1] = intr2num(&newentry->upper);
205

206
	penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]);
207

Bruce Momjian's avatar
Bruce Momjian committed
208
	PG_RETURN_POINTER(result);
209 210 211 212 213 214

}

Datum
gbt_intv_picksplit(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
215
	PG_RETURN_POINTER(gbt_num_picksplit(
216 217
									(GistEntryVector *) PG_GETARG_POINTER(0),
									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
Bruce Momjian's avatar
Bruce Momjian committed
218 219
										&tinfo
										));
220 221 222 223 224
}

Datum
gbt_intv_same(PG_FUNCTION_ARGS)
{
Bruce Momjian's avatar
Bruce Momjian committed
225 226 227
	intvKEY    *b1 = (intvKEY *) PG_GETARG_POINTER(0);
	intvKEY    *b2 = (intvKEY *) PG_GETARG_POINTER(1);
	bool	   *result = (bool *) PG_GETARG_POINTER(2);
228

Bruce Momjian's avatar
Bruce Momjian committed
229 230
	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
	PG_RETURN_POINTER(result);
231
}