如何修改Postgres的语法规则文件---gram.y

如何修改Postgres的语法规则文件---gram.y

如果我们需要修改postgresql数据库的语法时主要涉及两个文件“gram.y”和“kwlist.h”,下面你一个简单的例子介绍如何修改,最好的例子就是gram.y本身,我们可以参考gram.y的其他关键来添加自己的关键字,比如我们要添加一个TYPE_P的关键字并按照字母顺序添加到kwlist.h中,可以参考BY关键字都在哪定义了?

1、定义一个自动工具要使用的关键字BYTE_P,在kwlist.h文件中增加一行

PG_KEYWORD("asc", ASC, RESERVED_KEYWORD)PG_KEYWORD("assertion", ASSERTION, UNRESERVED_KEYWORD)PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD)PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD)PG_KEYWORD("at", AT, UNRESERVED_KEYWORD)PG_KEYWORD("attribute", ATTRIBUTE, UNRESERVED_KEYWORD)PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD)PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD)PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD)PG_KEYWORD("begin", BEGIN_P, UNRESERVED_KEYWORD)PG_KEYWORD("between", BETWEEN, COL_NAME_KEYWORD)PG_KEYWORD("bigint", BIGINT, COL_NAME_KEYWORD)PG_KEYWORD("binary", BINARY, TYPE_FUNC_NAME_KEYWORD)PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD)PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD)PG_KEYWORD("both", BOTH, RESERVED_KEYWORD)PG_KEYWORD("by", BY, UNRESERVED_KEYWORD)PG_KEYWORD("byte", BYTE_P, UNRESERVED_KEYWORD)PG_KEYWORD("cache", CACHE, UNRESERVED_KEYWORD)PG_KEYWORD("called", CALLED, UNRESERVED_KEYWORD)PG_KEYWORD("cascade", CASCADE, UNRESERVED_KEYWORD)
这里要注意:我们添加的关键字要按照字母的顺序添加到kwlist.h文件中

2、在gram.y中添加关键字的说明和文法规则

%token 声明新的终结符

%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTERAGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASCASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATIONBACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BITBOOLEAN_P BOTH BY BYTE_PCACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_PCHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSECLUSTER COALESCE COLLATE COLLATION COLUMN COMMENT COMMENTS COMMITCOMMITTED CONCURRENTLY CONFIGURATION CONFLICT CONNECTION CONSTRAINT


%type 声明我们使用的新非终结符

%type <str>opt_existing_window_name unit_opt%type <boolean> opt_if_not_exists

添加新语法规则
CharacterWithLength:  character '(' Iconst unit_opt ')' opt_charset{if (($6 != NULL) && (strcmp($6, "sql_text") != 0))$1 = psprintf("%s_%s", $1, $6);$$ = SystemTypeName($1);$$->typmods = list_make1(makeIntConst($3, @3));$$->location = @1;};unit_opt:CHAR_P{ $$ = $1 }|BYTE_P<span ></span>{ $$ = $1 }| /*EMPTY*/{ $$ = “byte” }


添加到非保留字(kwlist.h中的每一个关键字,这都要有对应,防止移进归约冲突)

/* "Unreserved" keywords --- available for use as any kind of name. */unreserved_keyword:  ABORT_P| ABSOLUTE_P| ACCESS| ACTION| ADD_P| ADMIN| AFTER| AGGREGATE| ALSO| ALTER| ALWAYS| ASSERTION| ASSIGNMENT| AT| ATTRIBUTE| BACKWARD| BEFORE| BEGIN_P| BY| BYTE_P| CACHE| CALLED| CASCADE| CASCADED| CATALOG_P| CHAIN| CHARACTERISTICS| CHECKPOINT| CLASS| CLOSE| CLUSTER| COMMENT| COMMENTS| COMMIT| COMMITTED| CONFIGURATION| CONFLICT| CONNECTION| CONSTRAINTS| CONTENT_P| CONTINUE_P| CONVERSION_P| COPY| COST| CSV| CUBE| CURRENT_P| CURSOR

3、重新编译即可

gram.c gram.h是gram.y生成C文件,里面会有新关键字的宏定义,你也可以在src/backend/parser 目录指定 bison gram.y 来命令生成gram.c gram.h ,以验证我们的gram.y是否修改ok 。


4、git diff 结果

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.yindex b307b48..e316171 100644--- a/src/backend/parser/gram.y+++ b/src/backend/parser/gram.y@@ -535,7 +535,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <list>window_clause window_definition_list opt_partition_clause %type <windef>window_definition over_clause window_specification opt_frame_clause frame_extent frame_bound-%type <str>opt_existing_window_name+%type <str>opt_existing_window_name unit_opt %type <boolean> opt_if_not_exists  /*@@ -565,7 +565,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION  BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT-BOOLEAN_P BOTH BY+BOOLEAN_P BOTH BY BYTE_P  CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE@@ -11285,10 +11285,10 @@ ConstCharacter:  CharacterWithLength } ; -CharacterWithLength:  character '(' Iconst ')' opt_charset+CharacterWithLength:  character '(' Iconst unit_opt ')' opt_charset {-if (($5 != NULL) && (strcmp($5, "sql_text") != 0))-$1 = psprintf("%s_%s", $1, $5);+if (($6 != NULL) && (strcmp($6, "sql_text") != 0))+$1 = psprintf("%s_%s", $1, $6);  $$ = SystemTypeName($1); $$->typmods = list_make1(makeIntConst($3, @3));@@ -11296,6 +11296,12 @@ CharacterWithLength:  character '(' Iconst ')' opt_charset } ; +unit_opt:+CHAR_P{ $$ = $1 }+| BYTE_P{ $$ = $1 }+| /*EMPTY*/{ $$ = "byte" }++ CharacterWithoutLength: character opt_charset { if (($2 != NULL) && (strcmp($2, "sql_text") != 0))@@ -13666,6 +13672,7 @@ unreserved_keyword: | BEFORE | BEGIN_P | BY+| BYTE_P | CACHE | CALLED | CASCADEdiff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.hindex 6e1e820..792520a 100644--- a/src/include/parser/kwlist.h+++ b/src/include/parser/kwlist.h@@ -61,6 +61,7 @@ PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD) PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD) PG_KEYWORD("both", BOTH, RESERVED_KEYWORD) PG_KEYWORD("by", BY, UNRESERVED_KEYWORD)+PG_KEYWORD("byte", BYTE_P, UNRESERVED_KEYWORD) PG_KEYWORD("cache", CACHE, UNRESERVED_KEYWORD) PG_KEYWORD("called", CALLED, UNRESERVED_KEYWORD) PG_KEYWORD("cascade", CASCADE, UNRESERVED_KEYWORD)

推荐阅读