数码资讯
如何修改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 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 > </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,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
| 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", 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)
声明:本文内容用于数码产品信息整理与选购参考,具体价格、库存、售后政策以官方渠道和电商页面实时信息为准。