searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

词法分析及语法分析(二)

2023-08-16 07:18:21
20
0

延续上文,我们分别有学生表student以及入职表tyy,现有一条查询语句

学生表:

入职表:

查询语句跟上篇一样,这里就不重复展示了

1. 在scan.l的规则段

{identifier}	{
					int			kwnum;
					char	   *ident;

					SET_YYLLOC();

					/* Is it a keyword? */
					/* yyextra->keywordlist中保存了导入kwlist.h中的所有关键字,可以在
					 * src\include\parser\kwlist.h中查阅
					 */
					kwnum = ScanKeywordLookup(yytext,
											  yyextra->keywordlist);
					if (kwnum >= 0)
					{
						yylval->keyword = GetScanKeyword(kwnum,
														 yyextra->keywordlist);  // 二分法查找关键字
						return yyextra->keyword_tokens[kwnum];   // 返回token,这里为SELECT_P
					}

					/*
					 * No.  Convert the identifier to lower case, and truncate
					 * if necessary.
					 */
					ident = downcase_truncate_identifier(yytext, yyleng, true);
					yylval->str = ident;
					return IDENT;
				}

2. 返回SELECT_P后,在gram.y中对该规则进行分析,SelectStmt

---------------------------"select ... order by ..."--------------------------
/* SelectStmt-> select_no_parens-> simple_select && sort_clause */
SelectStmt: select_no_parens			%prec UMINUS
			| select_with_parens		%prec UMINUS
		;
select_no_parens:
			simple_select						{ $$ = $1; }
			| select_clause sort_clause
				{
					insertSelectOptions((SelectStmt *) $1, $2, NIL,
										NULL, NULL,
										yyscanner);
					$$ = $1;
				}
			...

3. select_clause

---------------------------"select ... "--------------------------
/* select_clause-> simple_select-> opt_all_clause && opt_target_list && into_clause &&  from_clause && 
			 where_clause && group_clause && having_clause && window_clause  */
select_clause:
			simple_select							{ $$ = $1; }
			...
simple_select:
			SELECT opt_all_clause opt_target_list
			into_clause from_clause where_clause
			group_clause having_clause window_clause
				{
					SelectStmt *n = makeNode(SelectStmt);

					n->targetList = $3;
					n->intoClause = $4;
					n->fromClause = $5;
					n->whereClause = $6;
					n->groupClause = ($7)->list;
					n->groupDistinct = ($7)->distinct;
					n->havingClause = $8;
					n->windowClause = $9;
					$$ = (Node *) n;
				}
			...

4. opt_target_list

---------------------------"name, score"--------------------------
/* opt_target_list-> target_list->target_el->a_expr AS ColLabel &&
	 a_expr-> c_expr-> columnref-> ColId  */
opt_target_list: target_list						{ $$ = $1; }
			| /* EMPTY */							{ $$ = NIL; }
		;
/* target_list中的的lappend相当于:$1->tail->data.ptr_value = $3
	 其中$1是一个list,$3是一个ListCell */
target_list:
			target_el								{ $$ = list_make1($1); }
			| target_list ',' target_el				{ $$ = lappend($1, $3); }
		;
target_el:	...
			| a_expr      // name, score
				{
					$$ = makeNode(ResTarget);
					$$->name = NULL;
					s$$->indirection = NIL;
					$$->val = (Node *) $1;
					$$->location = @1;
				}
			...
		;
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
			...

相关结构体:

typedef struct ResTarget
{
	NodeTag		type;
	char	   *name;			/* column name or NULL */
	List	   *indirection;	/* subscripts, field names, and '*', or NIL */
	Node	   *val;			/* the value expression to compute or assign */
	int			location;		/* token location, or -1 if unknown */
} ResTarget;
typedef struct ColumnRef
{
	NodeTag		type;
	List	   *fields;			
	int			location;		
} ColumnRef;

5. from_clause

--------"from studnet, (select * from tyy where tyy.gno = '2023') as sub"-----------
/* from_clause-> from_list-> table_ref */
from_clause:
			  from_list							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NIL; }
		;
from_list:
			table_ref								{ $$ = list_make1($1); }
			| from_list ',' table_ref				{ $$ = lappend($1, $3); }
		;
------------------------------"student"--------------------------
/* table_ref-> relation_expr-> qualified_name-> ColId */
table_ref:	relation_expr opt_alias_clause  // opt_alias_clause可以为EMPTY
				{
					$1->alias = $2;
					$$ = (Node *) $1;
				}
				...
relation_expr:
			qualified_name
				{
					/* inheritance query, implicitly */
					$$ = $1;
					$$->inh = true;
					$$->alias = NULL;
				}
			...
qualified_name:
			ColId
				{
					$$ = makeRangeVar(NULL, $1, @1);
				}
			...
----------------"(select * from tyy where tyy.gno = '2023') as sub"--------------
/* table_ref-> select_with_parens-> select_no_parens-> simple_select
   table_ref->  opt_alias_clause*/
table_ref:	...
			| select_with_parens opt_alias_clause
				{
					RangeSubselect *n = makeNode(RangeSubselect);
             
					n->lateral = false;
					n->subquery = $1;
					n->alias = $2;
					...
					$$ = (Node *) n;
				}
select_with_parens:
			'(' select_no_parens ')'				{ $$ = $2; }
			| '(' select_with_parens ')'			{ $$ = $2; }
		;
select_no_parens:
			simple_select						{ $$ = $1; }
			...
----------------"select * from class where class.gno = '2023"--------------    
simple_select:
			SELECT opt_all_clause opt_target_list
			into_clause from_clause where_clause
			group_clause having_clause window_clause
				{
					SelectStmt *n = makeNode(SelectStmt);

					n->targetList = $3;
					n->intoClause = $4;
					n->fromClause = $5;
					n->whereClause = $6;
					n->groupClause = ($7)->list;
					n->groupDistinct = ($7)->distinct;
					n->havingClause = $8;
					n->windowClause = $9;
					$$ = (Node *) n;
				}
				...
----------------"*"--------------
/* simple_select-> opt_target_list-> target_list-> target_el */
opt_target_list: target_list						{ $$ = $1; }
			| /* EMPTY */							{ $$ = NIL; }
		;
target_list:
			target_el								{ $$ = list_make1($1); }
			| target_list ',' target_el				{ $$ = lappend($1, $3); }
		;
target_el:	...
			| '*'
				{
					ColumnRef  *n = makeNode(ColumnRef);

					n->fields = list_make1(makeNode(A_Star));
					n->location = @1;

					$$ = makeNode(ResTarget);
					$$->name = NULL;
					$$->indirection = NIL;
					$$->val = (Node *) n;
					$$->location = @1;
				}
		;
----------------'class'--------------
/* simple_select-> from_clause-> from_list-> table_ref-> relation_expr-> qualified_name */
from_clause:
			FROM from_list							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NIL; }
		;
from_list:
			table_ref								{ $$ = list_make1($1); }
			| from_list ',' table_ref				{ $$ = lappend($1, $3); }
		;
table_ref:	relation_expr opt_alias_clause
				{
					$1->alias = $2;
					$$ = (Node *) $1;
				}
			...
relation_expr:
			qualified_name
				{
					/* inheritance query, implicitly */
					$$ = $1;
					$$->inh = true;
					$$->alias = NULL;
				}
			...
qualified_name:
			ColId
				{
					$$ = makeRangeVar(NULL, $1, @1);
				}
			...
----------------'tyy.gno = '2023''--------------
/* simple_select-> where_clause-> a_expr-> c_expr-> columnref-> columnref-> indirection-> indirection_el-> attr_name-> ColLabel */
from_clause:
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '=' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	...
			| ColId indirection
				{
					$$ = makeColumnRef($1, $2, @1, yyscanner);
				}
		;
indirection:
			indirection_el							{ $$ = list_make1($1); }
			| indirection indirection_el			{ $$ = lappend($1, $2); }
		;
indirection_el:
			'.' attr_name
				{
					$$ = (Node *) makeString($2);
				}
			...
attr_name:	ColLabel								{ $$ = $1; };
ColLabel:	IDENT									{ $$ = $1; }
			| unreserved_keyword					{ $$ = pstrdup($1); }
			| col_name_keyword						{ $$ = pstrdup($1); }
			| type_func_name_keyword				{ $$ = pstrdup($1); }
			| reserved_keyword						{ $$ = pstrdup($1); }
		;
----------------" as sub"--------------
/* opt_alias_clause-> alias_clause-> ColId */
opt_alias_clause: alias_clause						{ $$ = $1; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
alias_clause:
			...
			| AS ColId
				{
					$$ = makeNode(Alias);
					$$->aliasname = $2;
				}

相关结构体:

typedef struct RangeVar
{
	NodeTag		type;
	char	   *catalogname;	/* the catalog (database) name, or NULL */
	char	   *schemaname;		/* the schema name, or NULL */
	char	   *relname;		/* the relation/sequence name */
	bool		inh;			/* expand rel by inheritance? recursively act
								 * on children? */
	char		relpersistence; /* see RELPERSISTENCE_* in pg_class.h */
	Alias	   *alias;			/* table alias & optional column aliases */
	int			location;		/* token location, or -1 if unknown */
} RangeVar;
typedef struct RangeSubselect
{
	NodeTag		type;
	bool		lateral;		/* does it have LATERAL prefix? */
	Node	   *subquery;		/* the untransformed sub-select clause */
	Alias	   *alias;			/* table alias & optional column aliases */
} RangeSubselect;
typedef struct A_Expr
{
	NodeTag		type;
	A_Expr_Kind kind;			/* see above */
	List	   *name;			/* possibly-qualified name of operator */
	Node	   *lexpr;			/* left argument, or NULL if none */
	Node	   *rexpr;			/* right argument, or NULL if none */
	int			location;		/* token location, or -1 if unknown */
} A_Expr;
typedef struct Alias
{
	NodeTag		type;
	char	   *aliasname;		/* aliased rel name (never qualified) */
	List	   *colnames;		/* optional list of column aliases */
} Alias;

6. where_clause

--------"where student.sno = sub.sno and sub.department = '数据库'"-----------
----------------"WHERE ... AND ... "--------------
/* where_clause-> a_expr */
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr AND a_expr
				{ $$ = makeAndExpr($1, $3, @2); }
--------"student.sno = sub.sno"-----------
/* simple_select-> where_clause-> a_expr-> c_expr-> columnref-> 
		 indirection-> indirection_el-> attr_name-> ColLabel */
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '=' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	...
			| ColId indirection
				{
					$$ = makeColumnRef($1, $2, @1, yyscanner);
				}
		;
indirection:
			indirection_el							{ $$ = list_make1($1); }
			| indirection indirection_el			{ $$ = lappend($1, $2); }
		;
indirection_el:
			'.' attr_name
				{
					$$ = (Node *) makeString($2);
				}
			...
attr_name:	ColLabel								{ $$ = $1; };
ColLabel:	IDENT									{ $$ = $1; }
			| unreserved_keyword					{ $$ = pstrdup($1); }
			| col_name_keyword						{ $$ = pstrdup($1); }
			| type_func_name_keyword				{ $$ = pstrdup($1); }
			| reserved_keyword						{ $$ = pstrdup($1); }
		;
--------" sub.department = '数据库' "-----------
/* simple_select-> where_clause-> a_expr-> c_expr-> columnref */
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '=' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
				...

7. group_clause

----------------"group by name, score "--------------
/* group_clause-> group_by_list-> group_by_item-> a_expr-> c_expr-> columnref-> ColId */
group_clause:
			GROUP_P BY set_quantifier group_by_list
				{
					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));

					n->distinct = $3 == SET_QUANTIFIER_DISTINCT;
					n->list = $4;
					$$ = n;
				}
				...
group_by_list:
			group_by_item							{ $$ = list_make1($1); }
			| group_by_list ',' group_by_item		{ $$ = lappend($1,$3); }
		;
group_by_item:
			a_expr									{ $$ = $1; }
			...
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
			...

8. having_clause

----------------"having score > 80 "--------------
/* having_clause-> a_expr*/
having_clause:
			HAVING a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '>' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
/* 后面为重复操作 */

9. sort_clause

----------------"order by score DESC; "--------------
/* sort_clause-> sortby_list-> sortby-> a_expr && opt_asc_desc 
		a_expr-> c_expr-> columnref */
sort_clause:
			ORDER BY sortby_list					{ $$ = $3; }
		;
sortby_list:
			sortby									{ $$ = list_make1($1); }
			| sortby_list ',' sortby				{ $$ = lappend($1, $3); }
		;
sortby:		...
			| a_expr opt_asc_desc opt_nulls_order  // "opt_asc_desc" 对应ASC、DESC
				{
					$$ = makeNode(SortBy);
					$$->node = $1;
					$$->sortby_dir = $2;
					$$->sortby_nulls = $3;
					$$->useOp = NIL;
					$$->location = -1;		/* no operator */
				}
		;
a_expr:		c_expr								 	{ $$ = $1; }
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
			...
opt_asc_desc: ASC							{ $$ = SORTBY_ASC; }
			| DESC							{ $$ = SORTBY_DESC; }
			| /*EMPTY*/						{ $$ = SORTBY_DEFAULT; }

10. stmtmulti

/* stmtmulit-> toplevel_stmt-> stmt-> SelectStmt */
stmtmulti:	stmtmulti ';' toplevel_stmt
				{
					if ($1 != NIL)
					{
						/* update length of previous stmt */
						updateRawStmtEnd(llast_node(RawStmt, $1), @2);
					}
					if ($3 != NULL)
						$$ = lappend($1, makeRawStmt($3, @2 + 1));
					else
						$$ = $1;
				}
			| toplevel_stmt
				{
					if ($1 != NULL)
						$$ = list_make1(makeRawStmt($1, 0));
					else
						$$ = NIL;
				}
		;
toplevel_stmt:
			stmt
			| TransactionStmtLegacy
		;
stmt:
			AlterEventTrigStmt
			| AlterCollationStmt
			| AlterDatabaseStmt
			| AlterDatabaseSetStmt
			...
			| DeleteStmt
			...
			| SelectStmt
			...
			| /*EMPTY*/
				{ $$ = NULL; }
		;

*******完成对查询语句的语法解析*******

0条评论
0 / 1000
l****n
3文章数
0粉丝数
l****n
3 文章 | 0 粉丝
l****n
3文章数
0粉丝数
l****n
3 文章 | 0 粉丝
原创

词法分析及语法分析(二)

2023-08-16 07:18:21
20
0

延续上文,我们分别有学生表student以及入职表tyy,现有一条查询语句

学生表:

入职表:

查询语句跟上篇一样,这里就不重复展示了

1. 在scan.l的规则段

{identifier}	{
					int			kwnum;
					char	   *ident;

					SET_YYLLOC();

					/* Is it a keyword? */
					/* yyextra->keywordlist中保存了导入kwlist.h中的所有关键字,可以在
					 * src\include\parser\kwlist.h中查阅
					 */
					kwnum = ScanKeywordLookup(yytext,
											  yyextra->keywordlist);
					if (kwnum >= 0)
					{
						yylval->keyword = GetScanKeyword(kwnum,
														 yyextra->keywordlist);  // 二分法查找关键字
						return yyextra->keyword_tokens[kwnum];   // 返回token,这里为SELECT_P
					}

					/*
					 * No.  Convert the identifier to lower case, and truncate
					 * if necessary.
					 */
					ident = downcase_truncate_identifier(yytext, yyleng, true);
					yylval->str = ident;
					return IDENT;
				}

2. 返回SELECT_P后,在gram.y中对该规则进行分析,SelectStmt

---------------------------"select ... order by ..."--------------------------
/* SelectStmt-> select_no_parens-> simple_select && sort_clause */
SelectStmt: select_no_parens			%prec UMINUS
			| select_with_parens		%prec UMINUS
		;
select_no_parens:
			simple_select						{ $$ = $1; }
			| select_clause sort_clause
				{
					insertSelectOptions((SelectStmt *) $1, $2, NIL,
										NULL, NULL,
										yyscanner);
					$$ = $1;
				}
			...

3. select_clause

---------------------------"select ... "--------------------------
/* select_clause-> simple_select-> opt_all_clause && opt_target_list && into_clause &&  from_clause && 
			 where_clause && group_clause && having_clause && window_clause  */
select_clause:
			simple_select							{ $$ = $1; }
			...
simple_select:
			SELECT opt_all_clause opt_target_list
			into_clause from_clause where_clause
			group_clause having_clause window_clause
				{
					SelectStmt *n = makeNode(SelectStmt);

					n->targetList = $3;
					n->intoClause = $4;
					n->fromClause = $5;
					n->whereClause = $6;
					n->groupClause = ($7)->list;
					n->groupDistinct = ($7)->distinct;
					n->havingClause = $8;
					n->windowClause = $9;
					$$ = (Node *) n;
				}
			...

4. opt_target_list

---------------------------"name, score"--------------------------
/* opt_target_list-> target_list->target_el->a_expr AS ColLabel &&
	 a_expr-> c_expr-> columnref-> ColId  */
opt_target_list: target_list						{ $$ = $1; }
			| /* EMPTY */							{ $$ = NIL; }
		;
/* target_list中的的lappend相当于:$1->tail->data.ptr_value = $3
	 其中$1是一个list,$3是一个ListCell */
target_list:
			target_el								{ $$ = list_make1($1); }
			| target_list ',' target_el				{ $$ = lappend($1, $3); }
		;
target_el:	...
			| a_expr      // name, score
				{
					$$ = makeNode(ResTarget);
					$$->name = NULL;
					s$$->indirection = NIL;
					$$->val = (Node *) $1;
					$$->location = @1;
				}
			...
		;
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
			...

相关结构体:

typedef struct ResTarget
{
	NodeTag		type;
	char	   *name;			/* column name or NULL */
	List	   *indirection;	/* subscripts, field names, and '*', or NIL */
	Node	   *val;			/* the value expression to compute or assign */
	int			location;		/* token location, or -1 if unknown */
} ResTarget;
typedef struct ColumnRef
{
	NodeTag		type;
	List	   *fields;			
	int			location;		
} ColumnRef;

5. from_clause

--------"from studnet, (select * from tyy where tyy.gno = '2023') as sub"-----------
/* from_clause-> from_list-> table_ref */
from_clause:
			  from_list							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NIL; }
		;
from_list:
			table_ref								{ $$ = list_make1($1); }
			| from_list ',' table_ref				{ $$ = lappend($1, $3); }
		;
------------------------------"student"--------------------------
/* table_ref-> relation_expr-> qualified_name-> ColId */
table_ref:	relation_expr opt_alias_clause  // opt_alias_clause可以为EMPTY
				{
					$1->alias = $2;
					$$ = (Node *) $1;
				}
				...
relation_expr:
			qualified_name
				{
					/* inheritance query, implicitly */
					$$ = $1;
					$$->inh = true;
					$$->alias = NULL;
				}
			...
qualified_name:
			ColId
				{
					$$ = makeRangeVar(NULL, $1, @1);
				}
			...
----------------"(select * from tyy where tyy.gno = '2023') as sub"--------------
/* table_ref-> select_with_parens-> select_no_parens-> simple_select
   table_ref->  opt_alias_clause*/
table_ref:	...
			| select_with_parens opt_alias_clause
				{
					RangeSubselect *n = makeNode(RangeSubselect);
             
					n->lateral = false;
					n->subquery = $1;
					n->alias = $2;
					...
					$$ = (Node *) n;
				}
select_with_parens:
			'(' select_no_parens ')'				{ $$ = $2; }
			| '(' select_with_parens ')'			{ $$ = $2; }
		;
select_no_parens:
			simple_select						{ $$ = $1; }
			...
----------------"select * from class where class.gno = '2023"--------------    
simple_select:
			SELECT opt_all_clause opt_target_list
			into_clause from_clause where_clause
			group_clause having_clause window_clause
				{
					SelectStmt *n = makeNode(SelectStmt);

					n->targetList = $3;
					n->intoClause = $4;
					n->fromClause = $5;
					n->whereClause = $6;
					n->groupClause = ($7)->list;
					n->groupDistinct = ($7)->distinct;
					n->havingClause = $8;
					n->windowClause = $9;
					$$ = (Node *) n;
				}
				...
----------------"*"--------------
/* simple_select-> opt_target_list-> target_list-> target_el */
opt_target_list: target_list						{ $$ = $1; }
			| /* EMPTY */							{ $$ = NIL; }
		;
target_list:
			target_el								{ $$ = list_make1($1); }
			| target_list ',' target_el				{ $$ = lappend($1, $3); }
		;
target_el:	...
			| '*'
				{
					ColumnRef  *n = makeNode(ColumnRef);

					n->fields = list_make1(makeNode(A_Star));
					n->location = @1;

					$$ = makeNode(ResTarget);
					$$->name = NULL;
					$$->indirection = NIL;
					$$->val = (Node *) n;
					$$->location = @1;
				}
		;
----------------'class'--------------
/* simple_select-> from_clause-> from_list-> table_ref-> relation_expr-> qualified_name */
from_clause:
			FROM from_list							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NIL; }
		;
from_list:
			table_ref								{ $$ = list_make1($1); }
			| from_list ',' table_ref				{ $$ = lappend($1, $3); }
		;
table_ref:	relation_expr opt_alias_clause
				{
					$1->alias = $2;
					$$ = (Node *) $1;
				}
			...
relation_expr:
			qualified_name
				{
					/* inheritance query, implicitly */
					$$ = $1;
					$$->inh = true;
					$$->alias = NULL;
				}
			...
qualified_name:
			ColId
				{
					$$ = makeRangeVar(NULL, $1, @1);
				}
			...
----------------'tyy.gno = '2023''--------------
/* simple_select-> where_clause-> a_expr-> c_expr-> columnref-> columnref-> indirection-> indirection_el-> attr_name-> ColLabel */
from_clause:
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '=' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	...
			| ColId indirection
				{
					$$ = makeColumnRef($1, $2, @1, yyscanner);
				}
		;
indirection:
			indirection_el							{ $$ = list_make1($1); }
			| indirection indirection_el			{ $$ = lappend($1, $2); }
		;
indirection_el:
			'.' attr_name
				{
					$$ = (Node *) makeString($2);
				}
			...
attr_name:	ColLabel								{ $$ = $1; };
ColLabel:	IDENT									{ $$ = $1; }
			| unreserved_keyword					{ $$ = pstrdup($1); }
			| col_name_keyword						{ $$ = pstrdup($1); }
			| type_func_name_keyword				{ $$ = pstrdup($1); }
			| reserved_keyword						{ $$ = pstrdup($1); }
		;
----------------" as sub"--------------
/* opt_alias_clause-> alias_clause-> ColId */
opt_alias_clause: alias_clause						{ $$ = $1; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
alias_clause:
			...
			| AS ColId
				{
					$$ = makeNode(Alias);
					$$->aliasname = $2;
				}

相关结构体:

typedef struct RangeVar
{
	NodeTag		type;
	char	   *catalogname;	/* the catalog (database) name, or NULL */
	char	   *schemaname;		/* the schema name, or NULL */
	char	   *relname;		/* the relation/sequence name */
	bool		inh;			/* expand rel by inheritance? recursively act
								 * on children? */
	char		relpersistence; /* see RELPERSISTENCE_* in pg_class.h */
	Alias	   *alias;			/* table alias & optional column aliases */
	int			location;		/* token location, or -1 if unknown */
} RangeVar;
typedef struct RangeSubselect
{
	NodeTag		type;
	bool		lateral;		/* does it have LATERAL prefix? */
	Node	   *subquery;		/* the untransformed sub-select clause */
	Alias	   *alias;			/* table alias & optional column aliases */
} RangeSubselect;
typedef struct A_Expr
{
	NodeTag		type;
	A_Expr_Kind kind;			/* see above */
	List	   *name;			/* possibly-qualified name of operator */
	Node	   *lexpr;			/* left argument, or NULL if none */
	Node	   *rexpr;			/* right argument, or NULL if none */
	int			location;		/* token location, or -1 if unknown */
} A_Expr;
typedef struct Alias
{
	NodeTag		type;
	char	   *aliasname;		/* aliased rel name (never qualified) */
	List	   *colnames;		/* optional list of column aliases */
} Alias;

6. where_clause

--------"where student.sno = sub.sno and sub.department = '数据库'"-----------
----------------"WHERE ... AND ... "--------------
/* where_clause-> a_expr */
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr AND a_expr
				{ $$ = makeAndExpr($1, $3, @2); }
--------"student.sno = sub.sno"-----------
/* simple_select-> where_clause-> a_expr-> c_expr-> columnref-> 
		 indirection-> indirection_el-> attr_name-> ColLabel */
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '=' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	...
			| ColId indirection
				{
					$$ = makeColumnRef($1, $2, @1, yyscanner);
				}
		;
indirection:
			indirection_el							{ $$ = list_make1($1); }
			| indirection indirection_el			{ $$ = lappend($1, $2); }
		;
indirection_el:
			'.' attr_name
				{
					$$ = (Node *) makeString($2);
				}
			...
attr_name:	ColLabel								{ $$ = $1; };
ColLabel:	IDENT									{ $$ = $1; }
			| unreserved_keyword					{ $$ = pstrdup($1); }
			| col_name_keyword						{ $$ = pstrdup($1); }
			| type_func_name_keyword				{ $$ = pstrdup($1); }
			| reserved_keyword						{ $$ = pstrdup($1); }
		;
--------" sub.department = '数据库' "-----------
/* simple_select-> where_clause-> a_expr-> c_expr-> columnref */
where_clause:
			WHERE a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '=' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", $1, $3, @2); }
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
				...

7. group_clause

----------------"group by name, score "--------------
/* group_clause-> group_by_list-> group_by_item-> a_expr-> c_expr-> columnref-> ColId */
group_clause:
			GROUP_P BY set_quantifier group_by_list
				{
					GroupClause *n = (GroupClause *) palloc(sizeof(GroupClause));

					n->distinct = $3 == SET_QUANTIFIER_DISTINCT;
					n->list = $4;
					$$ = n;
				}
				...
group_by_list:
			group_by_item							{ $$ = list_make1($1); }
			| group_by_list ',' group_by_item		{ $$ = lappend($1,$3); }
		;
group_by_item:
			a_expr									{ $$ = $1; }
			...
a_expr:		c_expr									{ $$ = $1; }
			...
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
			...

8. having_clause

----------------"having score > 80 "--------------
/* having_clause-> a_expr*/
having_clause:
			HAVING a_expr							{ $$ = $2; }
			| /*EMPTY*/								{ $$ = NULL; }
		;
a_expr:		...
			| a_expr '>' a_expr
				{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $3, @2); }
/* 后面为重复操作 */

9. sort_clause

----------------"order by score DESC; "--------------
/* sort_clause-> sortby_list-> sortby-> a_expr && opt_asc_desc 
		a_expr-> c_expr-> columnref */
sort_clause:
			ORDER BY sortby_list					{ $$ = $3; }
		;
sortby_list:
			sortby									{ $$ = list_make1($1); }
			| sortby_list ',' sortby				{ $$ = lappend($1, $3); }
		;
sortby:		...
			| a_expr opt_asc_desc opt_nulls_order  // "opt_asc_desc" 对应ASC、DESC
				{
					$$ = makeNode(SortBy);
					$$->node = $1;
					$$->sortby_dir = $2;
					$$->sortby_nulls = $3;
					$$->useOp = NIL;
					$$->location = -1;		/* no operator */
				}
		;
a_expr:		c_expr								 	{ $$ = $1; }
c_expr:		columnref								{ $$ = $1; }
			...
columnref:	ColId
				{
					$$ = makeColumnRef($1, NIL, @1, yyscanner);
				}
			...
opt_asc_desc: ASC							{ $$ = SORTBY_ASC; }
			| DESC							{ $$ = SORTBY_DESC; }
			| /*EMPTY*/						{ $$ = SORTBY_DEFAULT; }

10. stmtmulti

/* stmtmulit-> toplevel_stmt-> stmt-> SelectStmt */
stmtmulti:	stmtmulti ';' toplevel_stmt
				{
					if ($1 != NIL)
					{
						/* update length of previous stmt */
						updateRawStmtEnd(llast_node(RawStmt, $1), @2);
					}
					if ($3 != NULL)
						$$ = lappend($1, makeRawStmt($3, @2 + 1));
					else
						$$ = $1;
				}
			| toplevel_stmt
				{
					if ($1 != NULL)
						$$ = list_make1(makeRawStmt($1, 0));
					else
						$$ = NIL;
				}
		;
toplevel_stmt:
			stmt
			| TransactionStmtLegacy
		;
stmt:
			AlterEventTrigStmt
			| AlterCollationStmt
			| AlterDatabaseStmt
			| AlterDatabaseSetStmt
			...
			| DeleteStmt
			...
			| SelectStmt
			...
			| /*EMPTY*/
				{ $$ = NULL; }
		;

*******完成对查询语句的语法解析*******

文章来自个人专栏
PostgreSQL数据库
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
1
1