PolarDB-for-PostgreSQL

Форк
0
269 строк · 5.3 Кб
1
%{
2
/* contrib/cube/cubeparse.y */
3

4
/* NdBox = [(lowerleft),(upperright)] */
5
/* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
6

7
#include "postgres.h"
8

9
#include "cubedata.h"
10
#include "utils/builtins.h"
11

12
/* All grammar constructs return strings */
13
#define YYSTYPE char *
14

15
/*
16
 * Bison doesn't allocate anything that needs to live across parser calls,
17
 * so we can easily have it use palloc instead of malloc.  This prevents
18
 * memory leaks if we error out during parsing.  Note this only works with
19
 * bison >= 2.0.  However, in bison 1.875 the default is to use alloca()
20
 * if possible, so there's not really much problem anyhow, at least if
21
 * you're building with gcc.
22
 */
23
#define YYMALLOC palloc
24
#define YYFREE   pfree
25

26
static char *scanbuf;
27
static int	scanbuflen;
28

29
static int item_count(const char *s, char delim);
30
static NDBOX *write_box(int dim, char *str1, char *str2);
31
static NDBOX *write_point_as_box(int dim, char *str);
32

33
%}
34

35
/* BISON Declarations */
36
%parse-param {NDBOX **result}
37
%expect 0
38
%name-prefix="cube_yy"
39

40
%token CUBEFLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
41
%start box
42

43
/* Grammar follows */
44
%%
45

46
box: O_BRACKET paren_list COMMA paren_list C_BRACKET
47
	{
48
		int dim;
49

50
		dim = item_count($2, ',');
51
		if (item_count($4, ',') != dim)
52
		{
53
			ereport(ERROR,
54
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
55
					 errmsg("invalid input syntax for cube"),
56
					 errdetail("Different point dimensions in (%s) and (%s).",
57
							   $2, $4)));
58
			YYABORT;
59
		}
60
		if (dim > CUBE_MAX_DIM)
61
		{
62
			ereport(ERROR,
63
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
64
					 errmsg("invalid input syntax for cube"),
65
					 errdetail("A cube cannot have more than %d dimensions.",
66
							   CUBE_MAX_DIM)));
67
			YYABORT;
68
		}
69

70
		*result = write_box( dim, $2, $4 );
71
	}
72

73
	| paren_list COMMA paren_list
74
	{
75
		int dim;
76

77
		dim = item_count($1, ',');
78
		if (item_count($3, ',') != dim)
79
		{
80
			ereport(ERROR,
81
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
82
					 errmsg("invalid input syntax for cube"),
83
					 errdetail("Different point dimensions in (%s) and (%s).",
84
							   $1, $3)));
85
			YYABORT;
86
		}
87
		if (dim > CUBE_MAX_DIM)
88
		{
89
			ereport(ERROR,
90
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
91
					 errmsg("invalid input syntax for cube"),
92
					 errdetail("A cube cannot have more than %d dimensions.",
93
							   CUBE_MAX_DIM)));
94
			YYABORT;
95
		}
96

97
		*result = write_box( dim, $1, $3 );
98
	}
99

100
	| paren_list
101
	{
102
		int dim;
103

104
		dim = item_count($1, ',');
105
		if (dim > CUBE_MAX_DIM)
106
		{
107
			ereport(ERROR,
108
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
109
					 errmsg("invalid input syntax for cube"),
110
					 errdetail("A cube cannot have more than %d dimensions.",
111
							   CUBE_MAX_DIM)));
112
			YYABORT;
113
		}
114

115
		*result = write_point_as_box(dim, $1);
116
	}
117

118
	| list
119
	{
120
		int dim;
121

122
		dim = item_count($1, ',');
123
		if (dim > CUBE_MAX_DIM)
124
		{
125
			ereport(ERROR,
126
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
127
					 errmsg("invalid input syntax for cube"),
128
					 errdetail("A cube cannot have more than %d dimensions.",
129
							   CUBE_MAX_DIM)));
130
			YYABORT;
131
		}
132

133
		*result = write_point_as_box(dim, $1);
134
	}
135
	;
136

137
paren_list: O_PAREN list C_PAREN
138
	{
139
		$$ = $2;
140
	}
141
	| O_PAREN C_PAREN
142
	{
143
		$$ = pstrdup("");
144
	}
145
	;
146

147
list: CUBEFLOAT
148
	{
149
		/* alloc enough space to be sure whole list will fit */
150
		$$ = palloc(scanbuflen + 1);
151
		strcpy($$, $1);
152
	}
153
	| list COMMA CUBEFLOAT
154
	{
155
		$$ = $1;
156
		strcat($$, ",");
157
		strcat($$, $3);
158
	}
159
	;
160

161
%%
162

163
/* This assumes the string has been normalized by productions above */
164
static int
165
item_count(const char *s, char delim)
166
{
167
	int			nitems = 0;
168

169
	if (s[0] != '\0')
170
	{
171
		nitems++;
172
		while ((s = strchr(s, delim)) != NULL)
173
		{
174
			nitems++;
175
			s++;
176
		}
177
	}
178
	return nitems;
179
}
180

181
static NDBOX *
182
write_box(int dim, char *str1, char *str2)
183
{
184
	NDBOX	   *bp;
185
	char	   *s;
186
	char	   *endptr;
187
	int			i;
188
	int			size = CUBE_SIZE(dim);
189
	bool		point = true;
190

191
	bp = palloc0(size);
192
	SET_VARSIZE(bp, size);
193
	SET_DIM(bp, dim);
194

195
	s = str1;
196
	i = 0;
197
	if (dim > 0)
198
		bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
199
	while ((s = strchr(s, ',')) != NULL)
200
	{
201
		s++;
202
		bp->x[i++] = float8in_internal(s, &endptr, "cube", str1);
203
	}
204
	Assert(i == dim);
205

206
	s = str2;
207
	if (dim > 0)
208
	{
209
		bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
210
		/* code this way to do right thing with NaN */
211
		point &= (bp->x[i] == bp->x[0]);
212
		i++;
213
	}
214
	while ((s = strchr(s, ',')) != NULL)
215
	{
216
		s++;
217
		bp->x[i] = float8in_internal(s, &endptr, "cube", str2);
218
		point &= (bp->x[i] == bp->x[i - dim]);
219
		i++;
220
	}
221
	Assert(i == dim * 2);
222

223
	if (point)
224
	{
225
		/*
226
		 * The value turned out to be a point, ie. all the upper-right
227
		 * coordinates were equal to the lower-left coordinates. Resize the
228
		 * cube we constructed.  Note: we don't bother to repalloc() it
229
		 * smaller, as it's unlikely that the tiny amount of memory freed
230
		 * that way would be useful, and the output is always short-lived.
231
		 */
232
		size = POINT_SIZE(dim);
233
		SET_VARSIZE(bp, size);
234
		SET_POINT_BIT(bp);
235
	}
236

237
	return bp;
238
}
239

240
static NDBOX *
241
write_point_as_box(int dim, char *str)
242
{
243
	NDBOX		*bp;
244
	int			i,
245
				size;
246
	char	   *s;
247
	char	   *endptr;
248

249
	size = POINT_SIZE(dim);
250
	bp = palloc0(size);
251
	SET_VARSIZE(bp, size);
252
	SET_DIM(bp, dim);
253
	SET_POINT_BIT(bp);
254

255
	s = str;
256
	i = 0;
257
	if (dim > 0)
258
		bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
259
	while ((s = strchr(s, ',')) != NULL)
260
	{
261
		s++;
262
		bp->x[i++] = float8in_internal(s, &endptr, "cube", str);
263
	}
264
	Assert(i == dim);
265

266
	return bp;
267
}
268

269
#include "cubescan.c"
270

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

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

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

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