PostgreSQL Source Code  git master
filter.c File Reference
#include "postgres_fe.h"
#include "common/fe_memutils.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 23 of file filter.c.

Function Documentation

◆ filter_free()

void filter_free ( FilterStateData fstate)

Definition at line 61 of file filter.c.

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

182 {
183  const char *ptr = *line;
184  const char *result = 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  if (isalpha((unsigned char) *ptr))
194  {
195  result = ptr++;
196 
197  while (isalpha((unsigned char) *ptr) || *ptr == '_')
198  ptr++;
199 
200  *size = ptr - result;
201  }
202 
203  *line = ptr;
204 
205  return result;
206 }
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 37 of file filter.c.

38 {
39  fstate->filename = filename;
40  fstate->lineno = 0;
41  fstate->exit_nicely = f_exit;
42  initStringInfo(&fstate->linebuff);
43 
44  if (strcmp(filename, "-") != 0)
45  {
46  fstate->fp = fopen(filename, "r");
47  if (!fstate->fp)
48  {
49  pg_log_error("could not open filter file \"%s\": %m", filename);
50  fstate->exit_nicely(1);
51  }
52  }
53  else
54  fstate->fp = stdin;
55 }
static char * filename
Definition: pg_dumpall.c:119
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
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 83 of file filter.c.

84 {
85  switch (fot)
86  {
88  return "comment or empty line";
90  return "table data";
92  return "table data and children";
94  return "database";
96  return "extension";
98  return "foreign data";
100  return "function";
102  return "index";
104  return "schema";
106  return "table";
108  return "table and children";
110  return "trigger";
111  }
112 
113  /* should never get here */
114  pg_unreachable();
115 }
#define pg_unreachable()
Definition: c.h:296
@ 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 390 of file filter.c.

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

124 {
125  if (is_keyword_str("table_data", keyword, size))
127  else if (is_keyword_str("table_data_and_children", keyword, size))
129  else if (is_keyword_str("database", keyword, size))
130  *objtype = FILTER_OBJECT_TYPE_DATABASE;
131  else if (is_keyword_str("extension", keyword, size))
132  *objtype = FILTER_OBJECT_TYPE_EXTENSION;
133  else if (is_keyword_str("foreign_data", keyword, size))
135  else if (is_keyword_str("function", keyword, size))
136  *objtype = FILTER_OBJECT_TYPE_FUNCTION;
137  else if (is_keyword_str("index", keyword, size))
138  *objtype = FILTER_OBJECT_TYPE_INDEX;
139  else if (is_keyword_str("schema", keyword, size))
140  *objtype = FILTER_OBJECT_TYPE_SCHEMA;
141  else if (is_keyword_str("table", keyword, size))
142  *objtype = FILTER_OBJECT_TYPE_TABLE;
143  else if (is_keyword_str("table_and_children", keyword, size))
145  else if (is_keyword_str("trigger", keyword, size))
146  *objtype = FILTER_OBJECT_TYPE_TRIGGER;
147  else
148  return false;
149 
150  return true;
151 }

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

156 {
157  va_list argp;
158  char buf[256];
159 
160  va_start(argp, fmt);
161  vsnprintf(buf, sizeof(buf), fmt, argp);
162  va_end(argp);
163 
164  if (fstate->fp == stdin)
165  pg_log_error("invalid format in filter read from standard input on line %d: %s",
166  fstate->lineno, buf);
167  else
168  pg_log_error("invalid format in filter read from file \"%s\" on line %d: %s",
169  fstate->filename, fstate->lineno, buf);
170 }
static void const char * fmt
va_end(args)
va_start(args, fmt)
static char * buf
Definition: pg_test_fsync.c:73
#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 300 of file filter.c.

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

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

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