如何修改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 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

猜你在找的Postgre SQL相关文章