⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gram.y

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 Y
📖 第 1 页 / 共 4 页
字号:
proc_stmts		: proc_stmts proc_stmt						{							if ($2 == NULL)								$$ = $1;							else								$$ = lappend($1, $2);						}				| proc_stmt						{							if ($1 == NULL)								$$ = NULL;							else								$$ = list_make1($1);						}				;proc_stmt		: pl_block ';'						{ $$ = $1; }				| stmt_assign						{ $$ = $1; }				| stmt_if						{ $$ = $1; }				| stmt_loop						{ $$ = $1; }				| stmt_while						{ $$ = $1; }				| stmt_for						{ $$ = $1; }				| stmt_select						{ $$ = $1; }				| stmt_exit						{ $$ = $1; }				| stmt_return						{ $$ = $1; }				| stmt_return_next						{ $$ = $1; }				| stmt_raise						{ $$ = $1; }				| stmt_execsql						{ $$ = $1; }				| stmt_dynexecute						{ $$ = $1; }				| stmt_perform						{ $$ = $1; }				| stmt_getdiag						{ $$ = $1; }				| stmt_open						{ $$ = $1; }				| stmt_fetch						{ $$ = $1; }				| stmt_close						{ $$ = $1; }				| stmt_null						{ $$ = $1; }				;stmt_perform	: K_PERFORM lno expr_until_semi					{						PLpgSQL_stmt_perform *new;						new = palloc0(sizeof(PLpgSQL_stmt_perform));						new->cmd_type = PLPGSQL_STMT_PERFORM;						new->lineno   = $2;						new->expr  = $3;						$$ = (PLpgSQL_stmt *)new;					}				;stmt_assign		: assign_var lno K_ASSIGN expr_until_semi					{						PLpgSQL_stmt_assign *new;						new = palloc0(sizeof(PLpgSQL_stmt_assign));						new->cmd_type = PLPGSQL_STMT_ASSIGN;						new->lineno   = $2;						new->varno = $1;						new->expr  = $4;						$$ = (PLpgSQL_stmt *)new;					}				;stmt_getdiag	: K_GET K_DIAGNOSTICS lno getdiag_list ';'					{						PLpgSQL_stmt_getdiag	 *new;						new = palloc0(sizeof(PLpgSQL_stmt_getdiag));						new->cmd_type = PLPGSQL_STMT_GETDIAG;						new->lineno   = $3;						new->diag_items  = $4;						$$ = (PLpgSQL_stmt *)new;					}				;getdiag_list : getdiag_list ',' getdiag_list_item					{						$$ = lappend($1, $3);					}				| getdiag_list_item					{						$$ = list_make1($1);					}				;getdiag_list_item : getdiag_target K_ASSIGN getdiag_kind					{						PLpgSQL_diag_item *new;						new = palloc(sizeof(PLpgSQL_diag_item));						new->target = $1;						new->kind = $3;						$$ = new;					}				;getdiag_kind : K_ROW_COUNT					{						$$ = PLPGSQL_GETDIAG_ROW_COUNT;					}				| K_RESULT_OID					{						$$ = PLPGSQL_GETDIAG_RESULT_OID;					}				;getdiag_target	: T_SCALAR					{						check_assignable(yylval.scalar);						$$ = yylval.scalar->dno;					}				;assign_var		: T_SCALAR					{						check_assignable(yylval.scalar);						$$ = yylval.scalar->dno;					}				| T_ROW					{						check_assignable((PLpgSQL_datum *) yylval.row);						$$ = yylval.row->rowno;					}				| T_RECORD					{						check_assignable((PLpgSQL_datum *) yylval.rec);						$$ = yylval.rec->recno;					}				| assign_var '[' expr_until_rightbracket					{						PLpgSQL_arrayelem	*new;						new = palloc0(sizeof(PLpgSQL_arrayelem));						new->dtype		= PLPGSQL_DTYPE_ARRAYELEM;						new->subscript	= $3;						new->arrayparentno = $1;						plpgsql_adddatum((PLpgSQL_datum *)new);						$$ = new->dno;					}				;stmt_if			: K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'					{						PLpgSQL_stmt_if *new;						new = palloc0(sizeof(PLpgSQL_stmt_if));						new->cmd_type	= PLPGSQL_STMT_IF;						new->lineno		= $2;						new->cond		= $3;						new->true_body	= $4;						new->false_body = $5;						$$ = (PLpgSQL_stmt *)new;					}				;stmt_else		:					{						$$ = NIL;					}				| K_ELSIF lno expr_until_then proc_sect stmt_else					{						/*						 * Translate the structure:	   into:						 *						 * IF c1 THEN				   IF c1 THEN						 *	 ...						   ...						 * ELSIF c2 THEN			   ELSE						 *								   IF c2 THEN						 *	 ...							   ...						 * ELSE							   ELSE						 *	 ...							   ...						 * END IF						   END IF						 *							   END IF						 */						PLpgSQL_stmt_if *new_if;						/* first create a new if-statement */						new_if = palloc0(sizeof(PLpgSQL_stmt_if));						new_if->cmd_type	= PLPGSQL_STMT_IF;						new_if->lineno		= $2;						new_if->cond		= $3;						new_if->true_body	= $4;						new_if->false_body	= $5;						/* wrap the if-statement in a "container" list */						$$ = list_make1(new_if);					}				| K_ELSE proc_sect					{						$$ = $2;					}				;stmt_loop		: opt_block_label K_LOOP lno loop_body					{						PLpgSQL_stmt_loop *new;						new = palloc0(sizeof(PLpgSQL_stmt_loop));						new->cmd_type = PLPGSQL_STMT_LOOP;						new->lineno   = $3;						new->label	  = $1;						new->body	  = $4.stmts;						check_labels($1, $4.end_label);						plpgsql_ns_pop();						$$ = (PLpgSQL_stmt *)new;					}				;stmt_while		: opt_block_label K_WHILE lno expr_until_loop loop_body					{						PLpgSQL_stmt_while *new;						new = palloc0(sizeof(PLpgSQL_stmt_while));						new->cmd_type = PLPGSQL_STMT_WHILE;						new->lineno   = $3;						new->label	  = $1;						new->cond	  = $4;						new->body	  = $5.stmts;						check_labels($1, $5.end_label);						plpgsql_ns_pop();						$$ = (PLpgSQL_stmt *)new;					}				;stmt_for		: opt_block_label K_FOR for_control loop_body					{						/* This runs after we've scanned the loop body */						if ($3->cmd_type == PLPGSQL_STMT_FORI)						{							PLpgSQL_stmt_fori		*new;							new = (PLpgSQL_stmt_fori *) $3;							new->label	  = $1;							new->body	  = $4.stmts;							$$ = (PLpgSQL_stmt *) new;						}						else if ($3->cmd_type == PLPGSQL_STMT_FORS)						{							PLpgSQL_stmt_fors		*new;							new = (PLpgSQL_stmt_fors *) $3;							new->label	  = $1;							new->body	  = $4.stmts;							$$ = (PLpgSQL_stmt *) new;						}						else						{							PLpgSQL_stmt_dynfors	*new;							Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);							new = (PLpgSQL_stmt_dynfors *) $3;							new->label	  = $1;							new->body	  = $4.stmts;							$$ = (PLpgSQL_stmt *) new;						}						check_labels($1, $4.end_label);						/* close namespace started in opt_label */						plpgsql_ns_pop();					}				;for_control		:				lno for_variable K_IN					{						int			tok = yylex();						/* Simple case: EXECUTE is a dynamic FOR loop */						if (tok == K_EXECUTE)						{							PLpgSQL_stmt_dynfors	*new;							PLpgSQL_expr			*expr;							expr = plpgsql_read_expression(K_LOOP, "LOOP");							new = palloc0(sizeof(PLpgSQL_stmt_dynfors));							new->cmd_type = PLPGSQL_STMT_DYNFORS;							new->lineno   = $1;							if ($2.rec)								new->rec = $2.rec;							else if ($2.row)								new->row = $2.row;							else							{								plpgsql_error_lineno = $1;								yyerror("loop variable of loop over rows must be a record or row variable");							}							new->query = expr;							$$ = (PLpgSQL_stmt *) new;						}						else						{							PLpgSQL_expr	*expr1;							bool			 reverse = false;							/*							 * We have to distinguish between two							 * alternatives: FOR var IN a .. b and FOR							 * var IN query. Unfortunately this is							 * tricky, since the query in the second							 * form needn't start with a SELECT							 * keyword.  We use the ugly hack of							 * looking for two periods after the first							 * token. We also check for the REVERSE							 * keyword, which means it must be an							 * integer loop.							 */							if (tok == K_REVERSE)								reverse = true;							else								plpgsql_push_back_token(tok);							/*							 * Read tokens until we see either a ".."							 * or a LOOP. The text we read may not							 * necessarily be a well-formed SQL							 * statement, so we need to invoke							 * read_sql_construct directly.							 */							expr1 = read_sql_construct(K_DOTDOT,													   K_LOOP,													   "LOOP",													   "SELECT ",													   true,													   false,													   &tok);							if (tok == K_DOTDOT)							{								/* Saw "..", so it must be an integer loop */								PLpgSQL_expr		*expr2;								PLpgSQL_var			*fvar;								PLpgSQL_stmt_fori	*new;								/* First expression is well-formed */								check_sql_expr(expr1->query);								expr2 = plpgsql_read_expression(K_LOOP, "LOOP");								fvar = (PLpgSQL_var *)									plpgsql_build_variable($2.name,														   $2.lineno,														   plpgsql_build_datatype(INT4OID,																				  -1),														   true);								/* put the for-variable into the local block */								plpgsql_add_initdatums(NULL);								new = palloc0(sizeof(PLpgSQL_stmt_fori));								new->cmd_type = PLPGSQL_STMT_FORI;								new->lineno   = $1;								new->var	  = fvar;								new->reverse  = reverse;								new->lower	  = expr1;								new->upper	  = expr2;								$$ = (PLpgSQL_stmt *) new;							}							else							{								/*								 * No "..", so it must be a query loop. We've prefixed an								 * extra SELECT to the query text, so we need to remove that								 * before performing syntax checking.								 */								char				*tmp_query;								PLpgSQL_stmt_fors	*new;								if (reverse)									yyerror("cannot specify REVERSE in query FOR loop");								Assert(strncmp(expr1->query, "SELECT ", 7) == 0);								tmp_query = pstrdup(expr1->query + 7);								pfree(expr1->query);								expr1->query = tmp_query;								check_sql_expr(expr1->query);								new = palloc0(sizeof(PLpgSQL_stmt_fors));								new->cmd_type = PLPGSQL_STMT_FORS;								new->lineno   = $1;								if ($2.rec)									new->rec = $2.rec;								else if ($2.row)									new->row = $2.row;								else								{									plpgsql_error_lineno = $1;									yyerror("loop variable of loop over rows must be record or row variable");								}								new->query = expr1;								$$ = (PLpgSQL_stmt *) new;							}						}					}				;for_variable	: T_SCALAR					{						char		*name;						plpgsql_convert_ident(yytext, &name, 1);						$$.name = name;						$$.lineno  = plpgsql_scanner_lineno();						$$.rec = NULL;						$$.row = NULL;					}				| T_WORD					{						char		*name;						plpgsql_convert_ident(yytext, &name, 1);						$$.name = name;						$$.lineno  = plpgsql_scanner_lineno();						$$.rec = NULL;						$$.row = NULL;					}				| T_RECORD					{						char		*name;						plpgsql_convert_ident(yytext, &name, 1);						$$.name = name;						$$.lineno  = plpgsql_scanner_lineno();						$$.rec = yylval.rec;						$$.row = NULL;					}				| T_ROW					{						char		*name;						plpgsql_convert_ident(yytext, &name, 1);						$$.name = name;						$$.lineno  = plpgsql_scanner_lineno();						$$.row = yylval.row;						$$.rec = NULL;					}				;stmt_select		: K_SELECT lno					{						$$ = make_select_stmt();						$$->lineno = $2;					}				;stmt_exit		: exit_type lno opt_label opt_exitcond					{						PLpgSQL_stmt_exit *new;						new = palloc0(sizeof(PLpgSQL_stmt_exit));						new->cmd_type = PLPGSQL_STMT_EXIT;						new->is_exit  = $1;						new->lineno	  = $2;						new->label	  = $3;						new->cond	  = $4;						$$ = (PLpgSQL_stmt *)new;					}				;exit_type		: K_EXIT					{						$$ = true;					}				| K_CONTINUE					{						$$ = false;					}				;stmt_return		: K_RETURN lno					{						PLpgSQL_stmt_return *new;						new = palloc0(sizeof(PLpgSQL_stmt_return));						new->cmd_type = PLPGSQL_STMT_RETURN;						new->lineno   = $2;						new->expr	  = NULL;						new->retvarno = -1;						if (plpgsql_curr_compile->fn_retset)						{							if (yylex() != ';')								yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");						}						else if (plpgsql_curr_compile->out_param_varno >= 0)						{							if (yylex() != ';')								yyerror("RETURN cannot have a parameter in function with OUT parameters");							new->retvarno = plpgsql_curr_compile->out_param_varno;						}						else if (plpgsql_curr_compile->fn_rettype == VOIDOID)						{							if (yylex() != ';')								yyerror("RETURN cannot have a parameter in function returning void");						}						else if (plpgsql_curr_compile->fn_retistuple)						{							switch (yylex())							{								case K_NULL:									/* we allow this to support RETURN NULL in triggers */									break;								case T_ROW:									new->retvarno = yylval.row->rowno;									break;								case T_RECORD:									new->retvarno = yylval.rec->recno;									break;								default:									yyerror("RETURN must specify a record or row variable in function returning tuple");									break;							}							if (yylex() != ';')								yyerror("RETURN must specify a record or row variable in function returning tuple");						}						else						{							/*							 * Note that a well-formed expression is							 * _required_ here; anything else is a							 * compile-time error.							 */							new->expr = plpgsql_read_expression(';', ";");						}						$$ = (PLpgSQL_stmt *)new;					}				;stmt_return_next: K_RETURN_NEXT lno					{						PLpgSQL_stmt_return_next *new;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -