Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
5b8ac710
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5b8ac710
编写于
3月 04, 2006
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support include directives in postgresql.conf.
Patch by Joachim Wieland, somewhat reworked for clarity and portability.
上级
60d3c9fd
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
205 addition
and
79 deletion
+205
-79
doc/src/sgml/config.sgml
doc/src/sgml/config.sgml
+19
-2
src/backend/utils/misc/guc-file.l
src/backend/utils/misc/guc-file.l
+186
-77
未找到文件。
doc/src/sgml/config.sgml
浏览文件 @
5b8ac710
<!--
$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.4
8 2006/03/03 22:02:07 momjian
Exp $
$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.4
9 2006/03/04 22:19:31 tgl
Exp $
-->
<chapter Id="runtime-config">
<title>Server Configuration</title>
...
...
@@ -47,7 +47,24 @@ search_path = '"$user", public'
anywhere. Parameter values that are not simple identifiers or
numbers must be single-quoted. To embed a single quote in a parameter
value, write either two quotes (preferred) or backslash-quote.
</para>
</para>
<para>
<indexterm>
<primary><literal>include</></primary>
<secondary>in configuration file</secondary>
</indexterm>
In addition to parameter settings, the <filename>postgresql.conf</>
file can contain <firstterm>include directives</>, which specify
another file to read and process as if it were inserted into the
configuration file at this point. Include directives simply look like
<programlisting>
include 'filename'
</programlisting>
If the filename is not an absolute path, it is taken as relative to
the directory containing the referencing configuration file.
Inclusions can be nested.
</para>
<para>
<indexterm>
...
...
src/backend/utils/misc/guc-file.l
浏览文件 @
5b8ac710
...
...
@@ -4,26 +4,25 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.3
4 2006/01/02 19:55:25
tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.3
5 2006/03/04 22:19:31
tgl Exp $
*/
%{
#include "postgres.h"
#include <unistd.h>
#include <ctype.h>
#include <unistd.h>
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/guc.h"
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
#undef fprintf
#define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg)))
static unsigned ConfigFileLineno;
enum {
GUC_ID = 1,
GUC_STRING = 2,
...
...
@@ -36,9 +35,25 @@ enum {
GUC_ERROR = 100
};
/* prototype, so compiler is happy with our high warnings setting */
struct name_value_pair
{
char *name;
char *value;
struct name_value_pair *next;
};
static unsigned int ConfigFileLineno;
/* flex fails to supply a prototype for yylex, so provide one */
int GUC_yylex(void);
static bool ParseConfigFile(const char *config_file, const char *calling_file,
int depth, GucContext context, int elevel,
struct name_value_pair **head_p,
struct name_value_pair **tail_p);
static void free_name_value_list(struct name_value_pair * list);
static char *GUC_scanstr(const char *s);
%}
%option 8bit
...
...
@@ -85,38 +100,9 @@ STRING \'([^'\\\n]|\\.|\'\')*\'
%%
struct name_value_pair
{
char *name;
char *value;
struct name_value_pair *next;
};
/*
* Free a list of name/value pairs, including the names and the values
*/
static void
free_name_value_list(struct name_value_pair * list)
{
struct name_value_pair *item;
item = list;
while (item)
{
struct name_value_pair *save;
save = item->next;
pfree(item->name);
pfree(item->value);
pfree(item);
item = save;
}
}
/*
*
Official
function to read and process the configuration file. The
*
Exported
function to read and process the configuration file. The
* parameter indicates in what context the file is being read --- either
* postmaster startup (including standalone-backend startup) or SIGHUP.
* All options mentioned in the configuration file are set to new values.
...
...
@@ -126,10 +112,7 @@ void
ProcessConfigFile(GucContext context)
{
int elevel;
int token;
char *opt_name, *opt_value;
struct name_value_pair *item, *head, *tail;
FILE *fp;
Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
...
...
@@ -144,27 +127,124 @@ ProcessConfigFile(GucContext context)
else
elevel = ERROR;
fp = AllocateFile(ConfigFileName, "r");
head = tail = NULL;
if (!ParseConfigFile(ConfigFileName, NULL,
0, context, elevel,
&head, &tail))
goto cleanup_list;
/* Check if all options are valid */
for (item = head; item; item = item->next)
{
if (!set_config_option(item->name, item->value, context,
PGC_S_FILE, false, false))
goto cleanup_list;
}
/* If we got here all the options checked out okay, so apply them. */
for (item = head; item; item = item->next)
{
set_config_option(item->name, item->value, context,
PGC_S_FILE, false, true);
}
cleanup_list:
free_name_value_list(head);
}
/*
* Read and parse a single configuration file. This function recurses
* to handle "include" directives.
*
* Input parameters:
* config_file: absolute or relative path of file to read
* calling_file: absolute path of file containing the "include" directive,
* or NULL at outer level (config_file must be absolute at outer level)
* depth: recursion depth (used only to prevent infinite recursion)
* context: GucContext passed to ProcessConfigFile()
* elevel: error logging level determined by ProcessConfigFile()
* Output parameters:
* head_p, tail_p: head and tail of linked list of name/value pairs
*
* *head_p and *tail_p must be initialized to NULL before calling the outer
* recursion level. On exit, they contain a list of name-value pairs read
* from the input file(s).
*
* Returns TRUE if successful, FALSE if an error occurred. The error has
* already been ereport'd, it is only necessary for the caller to clean up
* its own state and release the name/value pairs list.
*
* Note: if elevel >= ERROR then an error will not return control to the
* caller, and internal state such as open files will not be cleaned up.
* This case occurs only during postmaster or standalone-backend startup,
* where an error will lead to immediate process exit anyway; so there is
* no point in contorting the code so it can clean up nicely.
*/
static bool
ParseConfigFile(const char *config_file, const char *calling_file,
int depth, GucContext context, int elevel,
struct name_value_pair **head_p,
struct name_value_pair **tail_p)
{
bool OK = true;
char abs_path[MAXPGPATH];
FILE *fp;
YY_BUFFER_STATE lex_buffer;
int token;
/*
* Reject too-deep include nesting depth. This is just a safety check
* to avoid dumping core due to stack overflow if an include file loops
* back to itself. The maximum nesting depth is pretty arbitrary.
*/
if (depth > 10)
{
ereport(elevel,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("could not open configuration file \"%s\": maximum nesting depth exceeded",
config_file)));
return false;
}
/*
* If config_file is a relative path, convert to absolute. We consider
* it to be relative to the directory holding the calling file.
*/
if (!is_absolute_path(config_file))
{
Assert(calling_file != NULL);
StrNCpy(abs_path, calling_file, MAXPGPATH);
get_parent_directory(abs_path);
join_path_components(abs_path, abs_path, config_file);
canonicalize_path(abs_path);
config_file = abs_path;
}
fp = AllocateFile(config_file, "r");
if (!fp)
{
ereport(elevel,
(errcode_for_file_access(),
errmsg("could not open configuration file \"%s\": %m",
ConfigFileNam
e)));
return;
config_fil
e)));
return
false
;
}
/*
* Parse
*/
yyrestart(fp
);
head = tail = NULL
;
opt_name = opt_value = NULL;
lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE
);
yy_switch_to_buffer(lex_buffer)
;
ConfigFileLineno = 1;
/* This loop iterates once per logical line */
while ((token = yylex()))
{
char *opt_name, *opt_value;
if (token == GUC_EOL) /* empty or comment line */
continue;
...
...
@@ -195,8 +275,30 @@ ProcessConfigFile(GucContext context)
if (token != GUC_EOL && token != 0)
goto parse_error;
/* OK, save the option name and value */
if (strcmp(opt_name, "custom_variable_classes") == 0)
/* OK, process the option name and value */
if (pg_strcasecmp(opt_name, "include") == 0)
{
/*
* An include directive isn't a variable and should be processed
* immediately.
*/
unsigned int save_ConfigFileLineno = ConfigFileLineno;
if (!ParseConfigFile(opt_value, config_file,
depth + 1, context, elevel,
head_p, tail_p))
{
pfree(opt_name);
pfree(opt_value);
OK = false;
goto cleanup_exit;
}
yy_switch_to_buffer(lex_buffer);
ConfigFileLineno = save_ConfigFileLineno;
pfree(opt_name);
pfree(opt_value);
}
else if (pg_strcasecmp(opt_name, "custom_variable_classes") == 0)
{
/*
* This variable must be processed first as it controls
...
...
@@ -207,7 +309,8 @@ ProcessConfigFile(GucContext context)
{
pfree(opt_name);
pfree(opt_value);
FreeFile(fp);
/* we assume error message was logged already */
OK = false;
goto cleanup_exit;
}
pfree(opt_name);
...
...
@@ -216,15 +319,17 @@ ProcessConfigFile(GucContext context)
else
{
/* append to list */
struct name_value_pair *item;
item = palloc(sizeof *item);
item->name = opt_name;
item->value = opt_value;
item->next = NULL;
if (
!head
)
head
= item;
if (
*head_p == NULL
)
*head_p
= item;
else
tail
->next = item;
tail
= item;
(*tail_p)
->next = item;
*tail_p
= item;
}
/* break out of loop if read EOF, else loop for next line */
...
...
@@ -232,45 +337,49 @@ ProcessConfigFile(GucContext context)
break;
}
FreeFile(fp);
/*
* Check if all options are valid
*/
for(item = head; item; item=item->next)
{
if (!set_config_option(item->name, item->value, context,
PGC_S_FILE, false, false))
goto cleanup_exit;
}
/* If we got here all the options parsed okay, so apply them. */
for(item = head; item; item=item->next)
{
set_config_option(item->name, item->value, context,
PGC_S_FILE, false, true);
}
cleanup_exit:
free_name_value_list(head);
return;
/* successful completion of parsing */
goto cleanup_exit;
parse_error:
FreeFile(fp);
free_name_value_list(head);
if (token == GUC_EOL || token == 0)
ereport(elevel,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error in file \"%s\" line %u, near end of line",
ConfigFileNam
e, ConfigFileLineno - 1)));
config_fil
e, ConfigFileLineno - 1)));
else
ereport(elevel,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error in file \"%s\" line %u, near token \"%s\"",
ConfigFileName, ConfigFileLineno, yytext)));
config_file, ConfigFileLineno, yytext)));
OK = false;
cleanup_exit:
yy_delete_buffer(lex_buffer);
FreeFile(fp);
return OK;
}
/*
* Free a list of name/value pairs, including the names and the values
*/
static void
free_name_value_list(struct name_value_pair *list)
{
struct name_value_pair *item;
item = list;
while (item)
{
struct name_value_pair *next = item->next;
pfree(item->name);
pfree(item->value);
pfree(item);
item = next;
}
}
/*
* scanstr
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录