PolarDB-for-PostgreSQL

Форк
0
238 строк · 5.6 Кб
1
/*
2
 * contrib/btree_gist/btree_uuid.c
3
 */
4
#include "postgres.h"
5

6
#include "btree_gist.h"
7
#include "btree_utils_num.h"
8
#include "port/pg_bswap.h"
9
#include "utils/uuid.h"
10

11
typedef struct
12
{
13
	pg_uuid_t	lower,
14
				upper;
15
} uuidKEY;
16

17

18
/*
19
 * UUID ops
20
 */
21
PG_FUNCTION_INFO_V1(gbt_uuid_compress);
22
PG_FUNCTION_INFO_V1(gbt_uuid_fetch);
23
PG_FUNCTION_INFO_V1(gbt_uuid_union);
24
PG_FUNCTION_INFO_V1(gbt_uuid_picksplit);
25
PG_FUNCTION_INFO_V1(gbt_uuid_consistent);
26
PG_FUNCTION_INFO_V1(gbt_uuid_penalty);
27
PG_FUNCTION_INFO_V1(gbt_uuid_same);
28

29

30
static int
31
uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2)
32
{
33
	return memcmp(arg1->data, arg2->data, UUID_LEN);
34
}
35

36
static bool
37
gbt_uuidgt(const void *a, const void *b, FmgrInfo *flinfo)
38
{
39
	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) > 0;
40
}
41

42
static bool
43
gbt_uuidge(const void *a, const void *b, FmgrInfo *flinfo)
44
{
45
	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) >= 0;
46
}
47

48
static bool
49
gbt_uuideq(const void *a, const void *b, FmgrInfo *flinfo)
50
{
51
	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) == 0;
52
}
53

54
static bool
55
gbt_uuidle(const void *a, const void *b, FmgrInfo *flinfo)
56
{
57
	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) <= 0;
58
}
59

60
static bool
61
gbt_uuidlt(const void *a, const void *b, FmgrInfo *flinfo)
62
{
63
	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) < 0;
64
}
65

66
static int
67
gbt_uuidkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
68
{
69
	uuidKEY    *ia = (uuidKEY *) (((const Nsrt *) a)->t);
70
	uuidKEY    *ib = (uuidKEY *) (((const Nsrt *) b)->t);
71
	int			res;
72

73
	res = uuid_internal_cmp(&ia->lower, &ib->lower);
74
	if (res == 0)
75
		res = uuid_internal_cmp(&ia->upper, &ib->upper);
76
	return res;
77
}
78

79

80
static const gbtree_ninfo tinfo =
81
{
82
	gbt_t_uuid,
83
	UUID_LEN,
84
	32,							/* sizeof(gbtreekey32) */
85
	gbt_uuidgt,
86
	gbt_uuidge,
87
	gbt_uuideq,
88
	gbt_uuidle,
89
	gbt_uuidlt,
90
	gbt_uuidkey_cmp,
91
	NULL
92
};
93

94

95
/**************************************************
96
 * uuid ops
97
 **************************************************/
98

99

100
Datum
101
gbt_uuid_compress(PG_FUNCTION_ARGS)
102
{
103
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
104
	GISTENTRY  *retval;
105

106
	if (entry->leafkey)
107
	{
108
		char	   *r = (char *) palloc(2 * UUID_LEN);
109
		pg_uuid_t  *key = DatumGetUUIDP(entry->key);
110

111
		retval = palloc(sizeof(GISTENTRY));
112

113
		memcpy((void *) r, (void *) key, UUID_LEN);
114
		memcpy((void *) (r + UUID_LEN), (void *) key, UUID_LEN);
115
		gistentryinit(*retval, PointerGetDatum(r),
116
					  entry->rel, entry->page,
117
					  entry->offset, false);
118
	}
119
	else
120
		retval = entry;
121

122
	PG_RETURN_POINTER(retval);
123
}
124

125
Datum
126
gbt_uuid_fetch(PG_FUNCTION_ARGS)
127
{
128
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
129

130
	PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
131
}
132

133
Datum
134
gbt_uuid_consistent(PG_FUNCTION_ARGS)
135
{
136
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
137
	pg_uuid_t  *query = PG_GETARG_UUID_P(1);
138
	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
139

140
	/* Oid		subtype = PG_GETARG_OID(3); */
141
	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
142
	uuidKEY    *kkk = (uuidKEY *) DatumGetPointer(entry->key);
143
	GBT_NUMKEY_R key;
144

145
	/* All cases served by this function are exact */
146
	*recheck = false;
147

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

151
	PG_RETURN_BOOL(
152
				   gbt_num_consistent(&key, (void *) query, &strategy,
153
									  GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
154
		);
155
}
156

157
Datum
158
gbt_uuid_union(PG_FUNCTION_ARGS)
159
{
160
	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
161
	void	   *out = palloc(sizeof(uuidKEY));
162

163
	*(int *) PG_GETARG_POINTER(1) = sizeof(uuidKEY);
164
	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
165
}
166

167
/*
168
 * Convert a uuid to a "double" value for estimating sizes of ranges.
169
 */
170
static double
171
uuid_2_double(const pg_uuid_t *u)
172
{
173
	uint64		uu[2];
174
	const double two64 = 18446744073709551616.0;	/* 2^64 */
175

176
	/* Source data may not be suitably aligned, so copy */
177
	memcpy(uu, u->data, UUID_LEN);
178

179
	/*
180
	 * uuid values should be considered as big-endian numbers, since that
181
	 * corresponds to how memcmp will compare them.  On a little-endian
182
	 * machine, byte-swap each half so we can use native uint64 arithmetic.
183
	 */
184
#ifndef WORDS_BIGENDIAN
185
	uu[0] = pg_bswap64(uu[0]);
186
	uu[1] = pg_bswap64(uu[1]);
187
#endif
188

189
	/*
190
	 * 2^128 is about 3.4e38, which in theory could exceed the range of
191
	 * "double" (POSIX only requires 1e37).  To avoid any risk of overflow,
192
	 * put the decimal point between the two halves rather than treating the
193
	 * uuid value as a 128-bit integer.
194
	 */
195
	return (double) uu[0] + (double) uu[1] / two64;
196
}
197

198
Datum
199
gbt_uuid_penalty(PG_FUNCTION_ARGS)
200
{
201
	uuidKEY    *origentry = (uuidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
202
	uuidKEY    *newentry = (uuidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
203
	float	   *result = (float *) PG_GETARG_POINTER(2);
204
	double		olower,
205
				oupper,
206
				nlower,
207
				nupper;
208

209
	olower = uuid_2_double(&origentry->lower);
210
	oupper = uuid_2_double(&origentry->upper);
211
	nlower = uuid_2_double(&newentry->lower);
212
	nupper = uuid_2_double(&newentry->upper);
213

214
	penalty_num(result, olower, oupper, nlower, nupper);
215

216
	PG_RETURN_POINTER(result);
217
}
218

219
Datum
220
gbt_uuid_picksplit(PG_FUNCTION_ARGS)
221
{
222
	PG_RETURN_POINTER(gbt_num_picksplit(
223
										(GistEntryVector *) PG_GETARG_POINTER(0),
224
										(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
225
										&tinfo, fcinfo->flinfo
226
										));
227
}
228

229
Datum
230
gbt_uuid_same(PG_FUNCTION_ARGS)
231
{
232
	uuidKEY    *b1 = (uuidKEY *) PG_GETARG_POINTER(0);
233
	uuidKEY    *b2 = (uuidKEY *) PG_GETARG_POINTER(1);
234
	bool	   *result = (bool *) PG_GETARG_POINTER(2);
235

236
	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
237
	PG_RETURN_POINTER(result);
238
}
239

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

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

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

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