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 }
static pg_noinline void Size size
Definition: slab.c:607

References size.

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:119
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
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 */
113  pg_unreachable();
114 }
#define pg_unreachable()
Definition: c.h:311
@ 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))
426  *comtype = FILTER_COMMAND_TYPE_INCLUDE;
427  else if (is_keyword_str("exclude", keyword, size))
428  *comtype = FILTER_COMMAND_TYPE_EXCLUDE;
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 * filter_get_keyword(const char **line, int *size)
Definition: filter.c:180
static const char * read_pattern(FilterStateData *fstate, const char *str, PQExpBuffer pattern)
Definition: filter.c:299
@ 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(), size, 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))
129  *objtype = FILTER_OBJECT_TYPE_DATABASE;
130  else if (is_keyword_str("extension", keyword, size))
131  *objtype = FILTER_OBJECT_TYPE_EXTENSION;
132  else if (is_keyword_str("foreign_data", keyword, size))
134  else if (is_keyword_str("function", keyword, size))
135  *objtype = FILTER_OBJECT_TYPE_FUNCTION;
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))
145  *objtype = FILTER_OBJECT_TYPE_TRIGGER;
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, is_keyword_str, and size.

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 void const char * fmt
va_end(args)
va_start(args, fmt)
static char * buf
Definition: pg_test_fsync.c:72
#define vsnprintf
Definition: port.h:237

References buf, FilterStateData::filename, fmt, FilterStateData::fp, FilterStateData::lineno, pg_log_error, va_end(), va_start(), 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 }
#define Assert(condition)
Definition: c.h:837

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().