PostgreSQL Source Code git master
Loading...
Searching...
No Matches
filter.c File Reference
#include "postgres_fe.h"
#include "common/logging.h"
#include "common/string.h"
#include "filter.h"
#include "lib/stringinfo.h"
#include "pqexpbuffer.h"
Include dependency graph for filter.c:

Go to the source code of this file.

Macros

#define is_keyword_str(cstr, str, bytes)    ((strlen(cstr) == (bytes)) && (pg_strncasecmp((cstr), (str), (bytes)) == 0))
 

Functions

void filter_init (FilterStateData *fstate, const char *filename, exit_function f_exit)
 
void filter_free (FilterStateData *fstate)
 
const charfilter_object_type_name (FilterObjectType fot)
 
static bool get_object_type (const char *keyword, int size, FilterObjectType *objtype)
 
void pg_log_filter_error (FilterStateData *fstate, const char *fmt,...)
 
static const charfilter_get_keyword (const char **line, int *size)
 
static const charread_quoted_string (FilterStateData *fstate, const char *str, PQExpBuffer pattern)
 
static const charread_pattern (FilterStateData *fstate, const char *str, PQExpBuffer pattern)
 
bool filter_read_item (FilterStateData *fstate, char **objname, FilterCommandType *comtype, FilterObjectType *objtype)
 

Macro Definition Documentation

◆ is_keyword_str

#define is_keyword_str (   cstr,
  str,
  bytes 
)     ((strlen(cstr) == (bytes)) && (pg_strncasecmp((cstr), (str), (bytes)) == 0))

Definition at line 22 of file filter.c.

36{
37 fstate->filename = filename;
38 fstate->lineno = 0;
39 fstate->exit_nicely = f_exit;
40 initStringInfo(&fstate->linebuff);
41
42 if (strcmp(filename, "-") != 0)
43 {
44 fstate->fp = fopen(filename, "r");
45 if (!fstate->fp)
46 {
47 pg_log_error("could not open filter file \"%s\": %m", filename);
48 fstate->exit_nicely(1);
49 }
50 }
51 else
52 fstate->fp = stdin;
53}
54
55/*
56 * Release allocated resources for the given filter.
57 */
58void
60{
61 if (!fstate)
62 return;
63
64 free(fstate->linebuff.data);
65 fstate->linebuff.data = NULL;
66
67 if (fstate->fp && fstate->fp != stdin)
68 {
69 if (fclose(fstate->fp) != 0)
70 pg_log_error("could not close filter file \"%s\": %m", fstate->filename);
71
72 fstate->fp = NULL;
73 }
74}
75
76/*
77 * Translate FilterObjectType enum to string. The main purpose is for error
78 * message formatting.
79 */
80const char *
82{
83 switch (fot)
84 {
86 return "comment or empty line";
88 return "table data";
90 return "table data and children";
92 return "database";
94 return "extension";
96 return "foreign data";
98 return "function";
100 return "index";
102 return "schema";
104 return "table";
106 return "table and children";
108 return "trigger";
109 }
110
111 /* should never get here */
113}
114
115/*
116 * Returns true when keyword is one of supported object types, and
117 * set related objtype. Returns false, when keyword is not assigned
118 * with known object type.
119 */
120static bool
121get_object_type(const char *keyword, int size, FilterObjectType *objtype)
122{
123 if (is_keyword_str("table_data", keyword, size))
125 else if (is_keyword_str("table_data_and_children", keyword, size))
127 else if (is_keyword_str("database", keyword, size))
129 else if (is_keyword_str("extension", keyword, size))
131 else if (is_keyword_str("foreign_data", keyword, size))
133 else if (is_keyword_str("function", keyword, size))
135 else if (is_keyword_str("index", keyword, size))
136 *objtype = FILTER_OBJECT_TYPE_INDEX;
137 else if (is_keyword_str("schema", keyword, size))
138 *objtype = FILTER_OBJECT_TYPE_SCHEMA;
139 else if (is_keyword_str("table", keyword, size))
140 *objtype = FILTER_OBJECT_TYPE_TABLE;
141 else if (is_keyword_str("table_and_children", keyword, size))
143 else if (is_keyword_str("trigger", keyword, size))
145 else
146 return false;
147
148 return true;
149}
150
151
152void
154{
156 char buf[256];
157
158 va_start(argp, fmt);
159 vsnprintf(buf, sizeof(buf), fmt, argp);
160 va_end(argp);
161
162 if (fstate->fp == stdin)
163 pg_log_error("invalid format in filter read from standard input on line %d: %s",
164 fstate->lineno, buf);
165 else
166 pg_log_error("invalid format in filter read from file \"%s\" on line %d: %s",
167 fstate->filename, fstate->lineno, buf);
168}
169
170/*
171 * filter_get_keyword - read the next filter keyword from buffer
172 *
173 * Search for keywords (strings of non-whitespace characters) in the passed
174 * in line buffer. Returns NULL when the buffer is empty or no keyword exists.
175 * The length of the found keyword is returned in the size parameter.
176 */
177static const char *
178filter_get_keyword(const char **line, int *size)
179{
180 const char *ptr = *line;
181 const char *result = NULL;
182
183 /* The passed buffer must not be NULL */
184 Assert(*line != NULL);
185
186 /* Set returned length preemptively in case no keyword is found */
187 *size = 0;
188
189 /* Skip initial whitespace */
190 while (isspace((unsigned char) *ptr))
191 ptr++;
192
193 /* Grab one keyword that's the string of non-whitespace characters */
194 if (*ptr != '\0' && !isspace((unsigned char) *ptr))
195 {
196 result = ptr++;
197
198 while (*ptr != '\0' && !isspace((unsigned char) *ptr))
199 ptr++;
200
201 *size = ptr - result;
202 }
203
204 *line = ptr;
205
206 return result;
207}
208
209/*
210 * read_quoted_string - read quoted possibly multi line string
211 *
212 * Reads a quoted string which can span over multiple lines and returns a
213 * pointer to next char after ending double quotes; it will exit on errors.
214 */
215static const char *
217 const char *str,
218 PQExpBuffer pattern)
219{
220 appendPQExpBufferChar(pattern, '"');
221 str++;
222
223 while (1)
224 {
225 /*
226 * We can ignore \r or \n chars because the string is read by
227 * pg_get_line_buf, so these chars should be just trailing chars.
228 */
229 if (*str == '\r' || *str == '\n')
230 {
231 str++;
232 continue;
233 }
234
235 if (*str == '\0')
236 {
237 Assert(fstate->linebuff.data);
238
239 if (!pg_get_line_buf(fstate->fp, &fstate->linebuff))
240 {
241 if (ferror(fstate->fp))
242 pg_log_error("could not read from filter file \"%s\": %m",
243 fstate->filename);
244 else
245 pg_log_filter_error(fstate, _("unexpected end of file"));
246
247 fstate->exit_nicely(1);
248 }
249
250 str = fstate->linebuff.data;
251
252 appendPQExpBufferChar(pattern, '\n');
253 fstate->lineno++;
254 }
255
256 if (*str == '"')
257 {
258 appendPQExpBufferChar(pattern, '"');
259 str++;
260
261 if (*str == '"')
262 {
263 appendPQExpBufferChar(pattern, '"');
264 str++;
265 }
266 else
267 break;
268 }
269 else if (*str == '\\')
270 {
271 str++;
272 if (*str == 'n')
273 appendPQExpBufferChar(pattern, '\n');
274 else if (*str == '\\')
275 appendPQExpBufferChar(pattern, '\\');
276
277 str++;
278 }
279 else
280 appendPQExpBufferChar(pattern, *str++);
281 }
282
283 return str;
284}
285
286/*
287 * read_pattern - reads on object pattern from input
288 *
289 * This function will parse any valid identifier (quoted or not, qualified or
290 * not), which can also includes the full signature for routines.
291 * Note that this function takes special care to sanitize the detected
292 * identifier (removing extraneous whitespaces or other unnecessary
293 * characters). This is necessary as most backup/restore filtering functions
294 * only recognize identifiers if they are written exactly the same way as
295 * they are output by the server.
296 *
297 * Returns a pointer to next character after the found identifier and exits
298 * on error.
299 */
300static const char *
301read_pattern(FilterStateData *fstate, const char *str, PQExpBuffer pattern)
302{
303 bool skip_space = true;
304 bool found_space = false;
305
306 /* Skip initial whitespace */
307 while (isspace((unsigned char) *str))
308 str++;
309
310 if (*str == '\0')
311 {
312 pg_log_filter_error(fstate, _("missing object name pattern"));
313 fstate->exit_nicely(1);
314 }
315
316 while (*str && *str != '#')
317 {
318 while (*str && !isspace((unsigned char) *str) && !strchr("#,.()\"", *str))
319 {
320 /*
321 * Append space only when it is allowed, and when it was found in
322 * original string.
323 */
324 if (!skip_space && found_space)
325 {
326 appendPQExpBufferChar(pattern, ' ');
327 skip_space = true;
328 }
329
330 appendPQExpBufferChar(pattern, *str++);
331 }
332
333 skip_space = false;
334
335 if (*str == '"')
336 {
337 if (found_space)
338 appendPQExpBufferChar(pattern, ' ');
339
340 str = read_quoted_string(fstate, str, pattern);
341 }
342 else if (*str == ',')
343 {
344 appendPQExpBufferStr(pattern, ", ");
345 skip_space = true;
346 str++;
347 }
348 else if (*str && strchr(".()", *str))
349 {
350 appendPQExpBufferChar(pattern, *str++);
351 skip_space = true;
352 }
353
354 found_space = false;
355
356 /* skip ending whitespaces */
357 while (isspace((unsigned char) *str))
358 {
359 found_space = true;
360 str++;
361 }
362 }
363
364 return str;
365}
366
367/*
368 * filter_read_item - Read command/type/pattern triplet from a filter file
369 *
370 * This will parse one filter item from the filter file, and while it is a
371 * row based format a pattern may span more than one line due to how object
372 * names can be constructed. The expected format of the filter file is:
373 *
374 * <command> <object_type> <pattern>
375 *
376 * command can be "include" or "exclude".
377 *
378 * Supported object types are described by enum FilterObjectType
379 * (see function get_object_type).
380 *
381 * pattern can be any possibly-quoted and possibly-qualified identifier. It
382 * follows the same rules as other object include and exclude functions so it
383 * can also use wildcards.
384 *
385 * Returns true when one filter item was successfully read and parsed. When
386 * object name contains \n chars, then more than one line from input file can
387 * be processed. Returns false when the filter file reaches EOF. In case of
388 * error, the function will emit an appropriate error message and exit.
389 */
390bool
392 char **objname,
394 FilterObjectType *objtype)
395{
396 if (pg_get_line_buf(fstate->fp, &fstate->linebuff))
397 {
398 const char *str = fstate->linebuff.data;
399 const char *keyword;
400 int size;
401 PQExpBufferData pattern;
402
403 fstate->lineno++;
404
405 /* Skip initial white spaces */
406 while (isspace((unsigned char) *str))
407 str++;
408
409 /*
410 * Skip empty lines or lines where the first non-whitespace character
411 * is a hash indicating a comment.
412 */
413 if (*str != '\0' && *str != '#')
414 {
415 /*
416 * First we expect sequence of two keywords, {include|exclude}
417 * followed by the object type to operate on.
418 */
419 keyword = filter_get_keyword(&str, &size);
420 if (!keyword)
421 {
423 _("no filter command found (expected \"include\" or \"exclude\")"));
424 fstate->exit_nicely(1);
425 }
426
427 if (is_keyword_str("include", keyword, size))
429 else if (is_keyword_str("exclude", keyword, size))
431 else
432 {
434 _("invalid filter command (expected \"include\" or \"exclude\")"));
435 fstate->exit_nicely(1);
436 }
437
438 keyword = filter_get_keyword(&str, &size);
439 if (!keyword)
440 {
441 pg_log_filter_error(fstate, _("missing filter object type"));
442 fstate->exit_nicely(1);
443 }
444
445 if (!get_object_type(keyword, size, objtype))
446 {
448 _("unsupported filter object type: \"%.*s\""), size, keyword);
449 fstate->exit_nicely(1);
450 }
451
452 initPQExpBuffer(&pattern);
453
454 str = read_pattern(fstate, str, &pattern);
455 *objname = pattern.data;
456 }
457 else
458 {
459 *objname = NULL;
461 *objtype = FILTER_OBJECT_TYPE_NONE;
462 }
463
464 return true;
465 }
466
467 if (ferror(fstate->fp))
468 {
469 pg_log_error("could not read from filter file \"%s\": %m", fstate->filename);
470 fstate->exit_nicely(1);
471 }
472
473 return false;
474}
#define Assert(condition)
Definition c.h:873
#define pg_unreachable()
Definition c.h:341
#define _(x)
Definition elog.c:91
static bool get_object_type(const char *keyword, int size, FilterObjectType *objtype)
Definition filter.c:122
void filter_free(FilterStateData *fstate)
Definition filter.c:60
#define is_keyword_str(cstr, str, bytes)
Definition filter.c:22
const char * filter_object_type_name(FilterObjectType fot)
Definition filter.c:82
bool filter_read_item(FilterStateData *fstate, char **objname, FilterCommandType *comtype, FilterObjectType *objtype)
Definition filter.c:392
void pg_log_filter_error(FilterStateData *fstate, const char *fmt,...)
Definition filter.c:154
static const char * read_pattern(FilterStateData *fstate, const char *str, PQExpBuffer pattern)
Definition filter.c:302
static const char * filter_get_keyword(const char **line, int *size)
Definition filter.c:179
static const char * read_quoted_string(FilterStateData *fstate, const char *str, PQExpBuffer pattern)
Definition filter.c:217
FilterObjectType
Definition filter.h:48
@ FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN
Definition filter.h:51
@ FILTER_OBJECT_TYPE_SCHEMA
Definition filter.h:57
@ FILTER_OBJECT_TYPE_INDEX
Definition filter.h:56
@ FILTER_OBJECT_TYPE_TRIGGER
Definition filter.h:60
@ FILTER_OBJECT_TYPE_FOREIGN_DATA
Definition filter.h:54
@ FILTER_OBJECT_TYPE_DATABASE
Definition filter.h:52
@ FILTER_OBJECT_TYPE_FUNCTION
Definition filter.h:55
@ FILTER_OBJECT_TYPE_TABLE_DATA
Definition filter.h:50
@ FILTER_OBJECT_TYPE_NONE
Definition filter.h:49
@ FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN
Definition filter.h:59
@ FILTER_OBJECT_TYPE_EXTENSION
Definition filter.h:53
@ FILTER_OBJECT_TYPE_TABLE
Definition filter.h:58
FilterCommandType
Definition filter.h:38
@ FILTER_COMMAND_TYPE_NONE
Definition filter.h:39
@ FILTER_COMMAND_TYPE_EXCLUDE
Definition filter.h:41
@ FILTER_COMMAND_TYPE_INCLUDE
Definition filter.h:40
const char * str
#define pg_log_error(...)
Definition logging.h:106
static char * filename
Definition pg_dumpall.c:120
bool pg_get_line_buf(FILE *stream, StringInfo buf)
Definition pg_get_line.c:95
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define vsnprintf
Definition port.h:259
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
static int fb(int x)
#define free(a)
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

Function Documentation

◆ filter_free()

void filter_free ( FilterStateData fstate)

Definition at line 60 of file filter.c.

61{
62 if (!fstate)
63 return;
64
65 free(fstate->linebuff.data);
66 fstate->linebuff.data = NULL;
67
68 if (fstate->fp && fstate->fp != stdin)
69 {
70 if (fclose(fstate->fp) != 0)
71 pg_log_error("could not close filter file \"%s\": %m", fstate->filename);
72
73 fstate->fp = NULL;
74 }
75}

References fb(), free, and pg_log_error.

Referenced by read_dump_filters(), read_dumpall_filters(), and read_restore_filters().

◆ filter_get_keyword()

static const char * filter_get_keyword ( const char **  line,
int size 
)
static

Definition at line 179 of file filter.c.

180{
181 const char *ptr = *line;
182 const char *result = NULL;
183
184 /* The passed buffer must not be NULL */
185 Assert(*line != NULL);
186
187 /* Set returned length preemptively in case no keyword is found */
188 *size = 0;
189
190 /* Skip initial whitespace */
191 while (isspace((unsigned char) *ptr))
192 ptr++;
193
194 /* Grab one keyword that's the string of non-whitespace characters */
195 if (*ptr != '\0' && !isspace((unsigned char) *ptr))
196 {
197 result = ptr++;
198
199 while (*ptr != '\0' && !isspace((unsigned char) *ptr))
200 ptr++;
201
202 *size = ptr - result;
203 }
204
205 *line = ptr;
206
207 return result;
208}

References Assert, and fb().

Referenced by filter_read_item().

◆ filter_init()

void filter_init ( FilterStateData fstate,
const char filename,
exit_function  f_exit 
)

Definition at line 36 of file filter.c.

37{
38 fstate->filename = filename;
39 fstate->lineno = 0;
40 fstate->exit_nicely = f_exit;
41 initStringInfo(&fstate->linebuff);
42
43 if (strcmp(filename, "-") != 0)
44 {
45 fstate->fp = fopen(filename, "r");
46 if (!fstate->fp)
47 {
48 pg_log_error("could not open filter file \"%s\": %m", filename);
49 fstate->exit_nicely(1);
50 }
51 }
52 else
53 fstate->fp = stdin;
54}

References fb(), filename, initStringInfo(), and pg_log_error.

Referenced by read_dump_filters(), read_dumpall_filters(), and read_restore_filters().

◆ filter_object_type_name()

const char * filter_object_type_name ( FilterObjectType  fot)

Definition at line 82 of file filter.c.

83{
84 switch (fot)
85 {
87 return "comment or empty line";
89 return "table data";
91 return "table data and children";
93 return "database";
95 return "extension";
97 return "foreign data";
99 return "function";
101 return "index";
103 return "schema";
105 return "table";
107 return "table and children";
109 return "trigger";
110 }
111
112 /* should never get here */
114}

References fb(), FILTER_OBJECT_TYPE_DATABASE, FILTER_OBJECT_TYPE_EXTENSION, FILTER_OBJECT_TYPE_FOREIGN_DATA, FILTER_OBJECT_TYPE_FUNCTION, FILTER_OBJECT_TYPE_INDEX, FILTER_OBJECT_TYPE_NONE, FILTER_OBJECT_TYPE_SCHEMA, FILTER_OBJECT_TYPE_TABLE, FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN, FILTER_OBJECT_TYPE_TABLE_DATA, FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN, FILTER_OBJECT_TYPE_TRIGGER, and pg_unreachable.

Referenced by read_dump_filters(), read_dumpall_filters(), and read_restore_filters().

◆ filter_read_item()

bool filter_read_item ( FilterStateData fstate,
char **  objname,
FilterCommandType comtype,
FilterObjectType objtype 
)

Definition at line 392 of file filter.c.

396{
397 if (pg_get_line_buf(fstate->fp, &fstate->linebuff))
398 {
399 const char *str = fstate->linebuff.data;
400 const char *keyword;
401 int size;
402 PQExpBufferData pattern;
403
404 fstate->lineno++;
405
406 /* Skip initial white spaces */
407 while (isspace((unsigned char) *str))
408 str++;
409
410 /*
411 * Skip empty lines or lines where the first non-whitespace character
412 * is a hash indicating a comment.
413 */
414 if (*str != '\0' && *str != '#')
415 {
416 /*
417 * First we expect sequence of two keywords, {include|exclude}
418 * followed by the object type to operate on.
419 */
420 keyword = filter_get_keyword(&str, &size);
421 if (!keyword)
422 {
424 _("no filter command found (expected \"include\" or \"exclude\")"));
425 fstate->exit_nicely(1);
426 }
427
428 if (is_keyword_str("include", keyword, size))
430 else if (is_keyword_str("exclude", keyword, size))
432 else
433 {
435 _("invalid filter command (expected \"include\" or \"exclude\")"));
436 fstate->exit_nicely(1);
437 }
438
439 keyword = filter_get_keyword(&str, &size);
440 if (!keyword)
441 {
442 pg_log_filter_error(fstate, _("missing filter object type"));
443 fstate->exit_nicely(1);
444 }
445
446 if (!get_object_type(keyword, size, objtype))
447 {
449 _("unsupported filter object type: \"%.*s\""), size, keyword);
450 fstate->exit_nicely(1);
451 }
452
453 initPQExpBuffer(&pattern);
454
455 str = read_pattern(fstate, str, &pattern);
456 *objname = pattern.data;
457 }
458 else
459 {
460 *objname = NULL;
462 *objtype = FILTER_OBJECT_TYPE_NONE;
463 }
464
465 return true;
466 }
467
468 if (ferror(fstate->fp))
469 {
470 pg_log_error("could not read from filter file \"%s\": %m", fstate->filename);
471 fstate->exit_nicely(1);
472 }
473
474 return false;
475}

References _, PQExpBufferData::data, fb(), FILTER_COMMAND_TYPE_EXCLUDE, FILTER_COMMAND_TYPE_INCLUDE, FILTER_COMMAND_TYPE_NONE, filter_get_keyword(), FILTER_OBJECT_TYPE_NONE, get_object_type(), initPQExpBuffer(), is_keyword_str, pg_get_line_buf(), pg_log_error, pg_log_filter_error(), read_pattern(), and str.

Referenced by read_dump_filters(), read_dumpall_filters(), and read_restore_filters().

◆ get_object_type()

static bool get_object_type ( const char keyword,
int  size,
FilterObjectType objtype 
)
static

Definition at line 122 of file filter.c.

123{
124 if (is_keyword_str("table_data", keyword, size))
126 else if (is_keyword_str("table_data_and_children", keyword, size))
128 else if (is_keyword_str("database", keyword, size))
130 else if (is_keyword_str("extension", keyword, size))
132 else if (is_keyword_str("foreign_data", keyword, size))
134 else if (is_keyword_str("function", keyword, size))
136 else if (is_keyword_str("index", keyword, size))
137 *objtype = FILTER_OBJECT_TYPE_INDEX;
138 else if (is_keyword_str("schema", keyword, size))
139 *objtype = FILTER_OBJECT_TYPE_SCHEMA;
140 else if (is_keyword_str("table", keyword, size))
141 *objtype = FILTER_OBJECT_TYPE_TABLE;
142 else if (is_keyword_str("table_and_children", keyword, size))
144 else if (is_keyword_str("trigger", keyword, size))
146 else
147 return false;
148
149 return true;
150}

References FILTER_OBJECT_TYPE_DATABASE, FILTER_OBJECT_TYPE_EXTENSION, FILTER_OBJECT_TYPE_FOREIGN_DATA, FILTER_OBJECT_TYPE_FUNCTION, FILTER_OBJECT_TYPE_INDEX, FILTER_OBJECT_TYPE_SCHEMA, FILTER_OBJECT_TYPE_TABLE, FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN, FILTER_OBJECT_TYPE_TABLE_DATA, FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN, FILTER_OBJECT_TYPE_TRIGGER, and is_keyword_str.

Referenced by filter_read_item().

◆ pg_log_filter_error()

void pg_log_filter_error ( FilterStateData fstate,
const char fmt,
  ... 
)

Definition at line 154 of file filter.c.

155{
157 char buf[256];
158
159 va_start(argp, fmt);
160 vsnprintf(buf, sizeof(buf), fmt, argp);
161 va_end(argp);
162
163 if (fstate->fp == stdin)
164 pg_log_error("invalid format in filter read from standard input on line %d: %s",
165 fstate->lineno, buf);
166 else
167 pg_log_error("invalid format in filter read from file \"%s\" on line %d: %s",
168 fstate->filename, fstate->lineno, buf);
169}

References buf, fb(), pg_log_error, and vsnprintf.

Referenced by filter_read_item(), read_dump_filters(), read_dumpall_filters(), read_pattern(), read_quoted_string(), and read_restore_filters().

◆ read_pattern()

static const char * read_pattern ( FilterStateData fstate,
const char str,
PQExpBuffer  pattern 
)
static

Definition at line 302 of file filter.c.

303{
304 bool skip_space = true;
305 bool found_space = false;
306
307 /* Skip initial whitespace */
308 while (isspace((unsigned char) *str))
309 str++;
310
311 if (*str == '\0')
312 {
313 pg_log_filter_error(fstate, _("missing object name pattern"));
314 fstate->exit_nicely(1);
315 }
316
317 while (*str && *str != '#')
318 {
319 while (*str && !isspace((unsigned char) *str) && !strchr("#,.()\"", *str))
320 {
321 /*
322 * Append space only when it is allowed, and when it was found in
323 * original string.
324 */
325 if (!skip_space && found_space)
326 {
327 appendPQExpBufferChar(pattern, ' ');
328 skip_space = true;
329 }
330
331 appendPQExpBufferChar(pattern, *str++);
332 }
333
334 skip_space = false;
335
336 if (*str == '"')
337 {
338 if (found_space)
339 appendPQExpBufferChar(pattern, ' ');
340
341 str = read_quoted_string(fstate, str, pattern);
342 }
343 else if (*str == ',')
344 {
345 appendPQExpBufferStr(pattern, ", ");
346 skip_space = true;
347 str++;
348 }
349 else if (*str && strchr(".()", *str))
350 {
351 appendPQExpBufferChar(pattern, *str++);
352 skip_space = true;
353 }
354
355 found_space = false;
356
357 /* skip ending whitespaces */
358 while (isspace((unsigned char) *str))
359 {
360 found_space = true;
361 str++;
362 }
363 }
364
365 return str;
366}

References _, appendPQExpBufferChar(), appendPQExpBufferStr(), fb(), pg_log_filter_error(), read_quoted_string(), and str.

Referenced by filter_read_item().

◆ read_quoted_string()

static const char * read_quoted_string ( FilterStateData fstate,
const char str,
PQExpBuffer  pattern 
)
static

Definition at line 217 of file filter.c.

220{
221 appendPQExpBufferChar(pattern, '"');
222 str++;
223
224 while (1)
225 {
226 /*
227 * We can ignore \r or \n chars because the string is read by
228 * pg_get_line_buf, so these chars should be just trailing chars.
229 */
230 if (*str == '\r' || *str == '\n')
231 {
232 str++;
233 continue;
234 }
235
236 if (*str == '\0')
237 {
238 Assert(fstate->linebuff.data);
239
240 if (!pg_get_line_buf(fstate->fp, &fstate->linebuff))
241 {
242 if (ferror(fstate->fp))
243 pg_log_error("could not read from filter file \"%s\": %m",
244 fstate->filename);
245 else
246 pg_log_filter_error(fstate, _("unexpected end of file"));
247
248 fstate->exit_nicely(1);
249 }
250
251 str = fstate->linebuff.data;
252
253 appendPQExpBufferChar(pattern, '\n');
254 fstate->lineno++;
255 }
256
257 if (*str == '"')
258 {
259 appendPQExpBufferChar(pattern, '"');
260 str++;
261
262 if (*str == '"')
263 {
264 appendPQExpBufferChar(pattern, '"');
265 str++;
266 }
267 else
268 break;
269 }
270 else if (*str == '\\')
271 {
272 str++;
273 if (*str == 'n')
274 appendPQExpBufferChar(pattern, '\n');
275 else if (*str == '\\')
276 appendPQExpBufferChar(pattern, '\\');
277
278 str++;
279 }
280 else
281 appendPQExpBufferChar(pattern, *str++);
282 }
283
284 return str;
285}

References _, appendPQExpBufferChar(), Assert, fb(), pg_get_line_buf(), pg_log_error, pg_log_filter_error(), and str.

Referenced by read_pattern().