PolarDB-for-PostgreSQL

Форк
0
303 строки · 7.3 Кб
1
/*
2
 * contrib/btree_gist/btree_interval.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/timestamp.h"
10

11
typedef struct
12
{
13
	Interval	lower,
14
				upper;
15
} intvKEY;
16

17

18
/*
19
** Interval ops
20
*/
21
PG_FUNCTION_INFO_V1(gbt_intv_compress);
22
PG_FUNCTION_INFO_V1(gbt_intv_fetch);
23
PG_FUNCTION_INFO_V1(gbt_intv_decompress);
24
PG_FUNCTION_INFO_V1(gbt_intv_union);
25
PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
26
PG_FUNCTION_INFO_V1(gbt_intv_consistent);
27
PG_FUNCTION_INFO_V1(gbt_intv_distance);
28
PG_FUNCTION_INFO_V1(gbt_intv_penalty);
29
PG_FUNCTION_INFO_V1(gbt_intv_same);
30

31

32
static bool
33
gbt_intvgt(const void *a, const void *b, FmgrInfo *flinfo)
34
{
35
	return DatumGetBool(DirectFunctionCall2(interval_gt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
36
}
37

38
static bool
39
gbt_intvge(const void *a, const void *b, FmgrInfo *flinfo)
40
{
41
	return DatumGetBool(DirectFunctionCall2(interval_ge, IntervalPGetDatum(a), IntervalPGetDatum(b)));
42
}
43

44
static bool
45
gbt_intveq(const void *a, const void *b, FmgrInfo *flinfo)
46
{
47
	return DatumGetBool(DirectFunctionCall2(interval_eq, IntervalPGetDatum(a), IntervalPGetDatum(b)));
48
}
49

50
static bool
51
gbt_intvle(const void *a, const void *b, FmgrInfo *flinfo)
52
{
53
	return DatumGetBool(DirectFunctionCall2(interval_le, IntervalPGetDatum(a), IntervalPGetDatum(b)));
54
}
55

56
static bool
57
gbt_intvlt(const void *a, const void *b, FmgrInfo *flinfo)
58
{
59
	return DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
60
}
61

62
static int
63
gbt_intvkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
64
{
65
	intvKEY    *ia = (intvKEY *) (((const Nsrt *) a)->t);
66
	intvKEY    *ib = (intvKEY *) (((const Nsrt *) b)->t);
67
	int			res;
68

69
	res = DatumGetInt32(DirectFunctionCall2(interval_cmp, IntervalPGetDatum(&ia->lower), IntervalPGetDatum(&ib->lower)));
70
	if (res == 0)
71
		return DatumGetInt32(DirectFunctionCall2(interval_cmp, IntervalPGetDatum(&ia->upper), IntervalPGetDatum(&ib->upper)));
72

73
	return res;
74
}
75

76

77
static double
78
intr2num(const Interval *i)
79
{
80
	return INTERVAL_TO_SEC(i);
81
}
82

83
static float8
84
gbt_intv_dist(const void *a, const void *b, FmgrInfo *flinfo)
85
{
86
	return (float8) Abs(intr2num((const Interval *) a) - intr2num((const Interval *) b));
87
}
88

89
/*
90
 * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
91
 * in pg_type.  This might be less than sizeof(Interval) if the compiler
92
 * insists on adding alignment padding at the end of the struct.  (Note:
93
 * this concern is obsolete with the current definition of Interval, but
94
 * was real before a separate "day" field was added to it.)
95
 */
96
#define INTERVALSIZE 16
97

98
static const gbtree_ninfo tinfo =
99
{
100
	gbt_t_intv,
101
	sizeof(Interval),
102
	32,							/* sizeof(gbtreekey32) */
103
	gbt_intvgt,
104
	gbt_intvge,
105
	gbt_intveq,
106
	gbt_intvle,
107
	gbt_intvlt,
108
	gbt_intvkey_cmp,
109
	gbt_intv_dist
110
};
111

112

113
Interval *
114
abs_interval(Interval *a)
115
{
116
	static Interval zero = {0, 0, 0};
117

118
	if (DatumGetBool(DirectFunctionCall2(interval_lt,
119
										 IntervalPGetDatum(a),
120
										 IntervalPGetDatum(&zero))))
121
		a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
122
												  IntervalPGetDatum(a)));
123

124
	return a;
125
}
126

127
PG_FUNCTION_INFO_V1(interval_dist);
128
Datum
129
interval_dist(PG_FUNCTION_ARGS)
130
{
131
	Datum		diff = DirectFunctionCall2(interval_mi,
132
										   PG_GETARG_DATUM(0),
133
										   PG_GETARG_DATUM(1));
134

135
	PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
136
}
137

138

139
/**************************************************
140
 * interval ops
141
 **************************************************/
142

143

144
Datum
145
gbt_intv_compress(PG_FUNCTION_ARGS)
146
{
147
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
148
	GISTENTRY  *retval = entry;
149

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

154
		retval = palloc(sizeof(GISTENTRY));
155

156
		if (entry->leafkey)
157
		{
158
			Interval   *key = DatumGetIntervalP(entry->key);
159

160
			memcpy((void *) r, (void *) key, INTERVALSIZE);
161
			memcpy((void *) (r + INTERVALSIZE), (void *) key, INTERVALSIZE);
162
		}
163
		else
164
		{
165
			intvKEY    *key = (intvKEY *) DatumGetPointer(entry->key);
166

167
			memcpy(r, &key->lower, INTERVALSIZE);
168
			memcpy(r + INTERVALSIZE, &key->upper, INTERVALSIZE);
169
		}
170
		gistentryinit(*retval, PointerGetDatum(r),
171
					  entry->rel, entry->page,
172
					  entry->offset, false);
173
	}
174

175
	PG_RETURN_POINTER(retval);
176

177
}
178

179
Datum
180
gbt_intv_fetch(PG_FUNCTION_ARGS)
181
{
182
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
183

184
	PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
185
}
186

187
Datum
188
gbt_intv_decompress(PG_FUNCTION_ARGS)
189
{
190
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
191
	GISTENTRY  *retval = entry;
192

193
	if (INTERVALSIZE != sizeof(Interval))
194
	{
195
		intvKEY    *r = palloc(sizeof(intvKEY));
196
		char	   *key = DatumGetPointer(entry->key);
197

198
		retval = palloc(sizeof(GISTENTRY));
199
		memcpy(&r->lower, key, INTERVALSIZE);
200
		memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
201

202
		gistentryinit(*retval, PointerGetDatum(r),
203
					  entry->rel, entry->page,
204
					  entry->offset, false);
205
	}
206
	PG_RETURN_POINTER(retval);
207
}
208

209

210
Datum
211
gbt_intv_consistent(PG_FUNCTION_ARGS)
212
{
213
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
214
	Interval   *query = PG_GETARG_INTERVAL_P(1);
215
	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
216

217
	/* Oid		subtype = PG_GETARG_OID(3); */
218
	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
219
	intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
220
	GBT_NUMKEY_R key;
221

222
	/* All cases served by this function are exact */
223
	*recheck = false;
224

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

228
	PG_RETURN_BOOL(
229
				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
230
		);
231
}
232

233

234
Datum
235
gbt_intv_distance(PG_FUNCTION_ARGS)
236
{
237
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
238
	Interval   *query = PG_GETARG_INTERVAL_P(1);
239

240
	/* Oid		subtype = PG_GETARG_OID(3); */
241
	intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
242
	GBT_NUMKEY_R key;
243

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

247
	PG_RETURN_FLOAT8(
248
					 gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
249
		);
250
}
251

252

253
Datum
254
gbt_intv_union(PG_FUNCTION_ARGS)
255
{
256
	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
257
	void	   *out = palloc(sizeof(intvKEY));
258

259
	*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
260
	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
261
}
262

263

264
Datum
265
gbt_intv_penalty(PG_FUNCTION_ARGS)
266
{
267
	intvKEY    *origentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
268
	intvKEY    *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
269
	float	   *result = (float *) PG_GETARG_POINTER(2);
270
	double		iorg[2],
271
				inew[2];
272

273
	iorg[0] = intr2num(&origentry->lower);
274
	iorg[1] = intr2num(&origentry->upper);
275
	inew[0] = intr2num(&newentry->lower);
276
	inew[1] = intr2num(&newentry->upper);
277

278
	penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]);
279

280
	PG_RETURN_POINTER(result);
281

282
}
283

284
Datum
285
gbt_intv_picksplit(PG_FUNCTION_ARGS)
286
{
287
	PG_RETURN_POINTER(gbt_num_picksplit(
288
										(GistEntryVector *) PG_GETARG_POINTER(0),
289
										(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
290
										&tinfo, fcinfo->flinfo
291
										));
292
}
293

294
Datum
295
gbt_intv_same(PG_FUNCTION_ARGS)
296
{
297
	intvKEY    *b1 = (intvKEY *) PG_GETARG_POINTER(0);
298
	intvKEY    *b2 = (intvKEY *) PG_GETARG_POINTER(1);
299
	bool	   *result = (bool *) PG_GETARG_POINTER(2);
300

301
	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
302
	PG_RETURN_POINTER(result);
303
}
304

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.