如果我们需要修改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 AFTER AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT BOOLEAN_P BOTH BY BYTE_P CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLLATION COLUMN COMMENT COMMENTS COMMIT COMMITTED 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 style="white-space:pre"> </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.y index 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,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",$5); + if (($6 != NULL) && (strcmp($6,"sql_text") != 0)) + $1 = psprintf("%s_%s",$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 | CASCADE diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 6e1e820..792520a 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -61,6 +61,7 @@ PG_KEYWORD("bit",COL_NAME_KEYWORD) PG_KEYWORD("boolean",COL_NAME_KEYWORD) PG_KEYWORD("both",RESERVED_KEYWORD) PG_KEYWORD("by",UNRESERVED_KEYWORD) +PG_KEYWORD("byte",UNRESERVED_KEYWORD) PG_KEYWORD("cache",UNRESERVED_KEYWORD) PG_KEYWORD("called",UNRESERVED_KEYWORD) PG_KEYWORD("cascade",UNRESERVED_KEYWORD)原文链接:https://www.f2er.com/postgresql/194652.html