如果我们需要修改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)