PostgreSQL Source Code git master
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 char * filter_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 char * filter_get_keyword (const char **line, int *size)
 
static const char * read_quoted_string (FilterStateData *fstate, const char *str, PQExpBuffer pattern)
 
static const char * read_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.

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}
#define free(a)
Definition: header.h:65
#define pg_log_error(...)
Definition: logging.h:106
StringInfoData linebuff
Definition: filter.h:31
const char * filename
Definition: filter.h:28
FILE * fp
Definition: filter.h:27

References StringInfoData::data, FilterStateData::filename, FilterStateData::fp, free, FilterStateData::linebuff, 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 180 of file filter.c.

181{
182 const char *ptr = *line;
183 const char *result = NULL;
184
185 /* Set returned length preemptively in case no keyword is found */
186 *size = 0;
187
188 /* Skip initial whitespace */
189 while (isspace((unsigned char) *ptr))
190 ptr++;
191
192 if (isalpha((unsigned char) *ptr))
193 {
194 result = ptr++;
195
196 while (isalpha((unsigned char) *ptr) || *ptr == '_')
197 ptr++;
198
199 *size = ptr - result;
200 }
201
202 *line = ptr;
203
204 return result;
205}

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}
static char * filename
Definition: pg_dumpall.c:124
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
exit_function exit_nicely
Definition: filter.h:29

References FilterStateData::exit_nicely, FilterStateData::filename, filename, FilterStateData::fp, initStringInfo(), FilterStateData::linebuff, FilterStateData::lineno, 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}
#define pg_unreachable()
Definition: c.h:332
@ 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

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_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 389 of file filter.c.

393{
394 if (pg_get_line_buf(fstate->fp, &fstate->linebuff))
395 {
396 const char *str = fstate->linebuff.data;
397 const char *keyword;
398 int size;
399 PQExpBufferData pattern;
400
401 fstate->lineno++;
402
403 /* Skip initial white spaces */
404 while (isspace((unsigned char) *str))
405 str++;
406
407 /*
408 * Skip empty lines or lines where the first non-whitespace character
409 * is a hash indicating a comment.
410 */
411 if (*str != '\0' && *str != '#')
412 {
413 /*
414 * First we expect sequence of two keywords, {include|exclude}
415 * followed by the object type to operate on.
416 */
417 keyword = filter_get_keyword(&str, &size);
418 if (!keyword)
419 {
420 pg_log_filter_error(fstate,
421 _("no filter command found (expected \"include\" or \"exclude\")"));
422 fstate->exit_nicely(1);
423 }
424
425 if (is_keyword_str("include", keyword, size))
427 else if (is_keyword_str("exclude", keyword, size))
429 else
430 {
431 pg_log_filter_error(fstate,
432 _("invalid filter command (expected \"include\" or \"exclude\")"));
433 fstate->exit_nicely(1);
434 }
435
436 keyword = filter_get_keyword(&str, &size);
437 if (!keyword)
438 {
439 pg_log_filter_error(fstate, _("missing filter object type"));
440 fstate->exit_nicely(1);
441 }
442
443 if (!get_object_type(keyword, size, objtype))
444 {
445 pg_log_filter_error(fstate,
446 _("unsupported filter object type: \"%.*s\""), size, keyword);
447 fstate->exit_nicely(1);
448 }
449
450 initPQExpBuffer(&pattern);
451
452 str = read_pattern(fstate, str, &pattern);
453 *objname = pattern.data;
454 }
455 else
456 {
457 *objname = NULL;
458 *comtype = FILTER_COMMAND_TYPE_NONE;
459 *objtype = FILTER_OBJECT_TYPE_NONE;
460 }
461
462 return true;
463 }
464
465 if (ferror(fstate->fp))
466 {
467 pg_log_error("could not read from filter file \"%s\": %m", fstate->filename);
468 fstate->exit_nicely(1);
469 }
470
471 return false;
472}
#define _(x)
Definition: elog.c:90
static bool get_object_type(const char *keyword, int size, FilterObjectType *objtype)
Definition: filter.c:122
#define is_keyword_str(cstr, str, bytes)
Definition: filter.c:22
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:299
static const char * filter_get_keyword(const char **line, int *size)
Definition: filter.c:180
@ 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
bool pg_get_line_buf(FILE *stream, StringInfo buf)
Definition: pg_get_line.c:95
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90

References _, StringInfoData::data, PQExpBufferData::data, FilterStateData::exit_nicely, FilterStateData::filename, FILTER_COMMAND_TYPE_EXCLUDE, FILTER_COMMAND_TYPE_INCLUDE, FILTER_COMMAND_TYPE_NONE, filter_get_keyword(), FILTER_OBJECT_TYPE_NONE, FilterStateData::fp, get_object_type(), initPQExpBuffer(), is_keyword_str, FilterStateData::linebuff, FilterStateData::lineno, 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{
156 va_list argp;
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}
static char * buf
Definition: pg_test_fsync.c:72
#define vsnprintf
Definition: port.h:238

References buf, FilterStateData::filename, FilterStateData::fp, FilterStateData::lineno, 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 299 of file filter.c.

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

References _, appendPQExpBufferChar(), appendPQExpBufferStr(), FilterStateData::exit_nicely, 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 214 of file filter.c.

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

References _, appendPQExpBufferChar(), Assert(), StringInfoData::data, FilterStateData::exit_nicely, FilterStateData::filename, FilterStateData::fp, FilterStateData::linebuff, FilterStateData::lineno, pg_get_line_buf(), pg_log_error, pg_log_filter_error(), and str.

Referenced by read_pattern().