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

📄 gram.y

📁 postgresql8.3.4源码,开源数据库
💻 Y
📖 第 1 页 / 共 4 页
字号:
						{ $$ = $1; }				| stmt_open						{ $$ = $1; }				| stmt_fetch						{ $$ = $1; }				| stmt_move						{ $$ = $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_block_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;								check_assignable((PLpgSQL_datum *) new->rec);							}							else if ($2.row)							{								new->row = $2.row;								check_assignable((PLpgSQL_datum *) new->row);							}							else if ($2.scalar)							{								/* convert single scalar to list */								new->row = make_scalar_list1($2.name, $2.scalar, $2.lineno);								/* no need for check_assignable */							}							else							{								plpgsql_error_lineno = $2.lineno;								yyerror("loop variable of loop over rows must be a record or row variable or list of scalar variables");							}							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_expr		*expr_by;								PLpgSQL_var			*fvar;								PLpgSQL_stmt_fori	*new;								char				*varname;								/* Check first expression is well-formed */								check_sql_expr(expr1->query);								/* Read and check the second one */								expr2 = read_sql_construct(K_LOOP,														   K_BY,														   "LOOP",														   "SELECT ",														   true,														   true,														   &tok);								/* Get the BY clause if any */								if (tok == K_BY)									expr_by = plpgsql_read_expression(K_LOOP, "LOOP");								else									expr_by = NULL;								/* Should have had a single variable name */								plpgsql_error_lineno = $2.lineno;								if ($2.scalar && $2.row)									ereport(ERROR,											(errcode(ERRCODE_SYNTAX_ERROR),											 errmsg("integer FOR loop must have just one target variable")));								/* create loop's private variable */								plpgsql_convert_ident($2.name, &varname, 1);								fvar = (PLpgSQL_var *)									plpgsql_build_variable(varname,														   $2.lineno,														   plpgsql_build_datatype(INT4OID,																				  -1),														   true);								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;								new->step	  = expr_by;								$$ = (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;									check_assignable((PLpgSQL_datum *) new->rec);								}								else if ($2.row)								{									new->row = $2.row;									check_assignable((PLpgSQL_datum *) new->row);								}								else if ($2.scalar)								{									/* convert single scalar to list */									new->row = make_scalar_list1($2.name, $2.scalar, $2.lineno);									/* no need for check_assignable */								}								else								{									plpgsql_error_lineno = $2.lineno;									yyerror("loop variable of loop over rows must be a record or row variable or list of scalar variables");								}								new->query = expr1;								$$ = (PLpgSQL_stmt *) new;							}						}					}				;/* * Processing the for_variable is tricky because we don't yet know if the * FOR is an integer FOR loop or a loop over query results.  In the former * case, the variable is just a name that we must instantiate as a loop * local variable, regardless of any other definition it might have. * Therefore, we always save the actual identifier into $$.name where it * can be used for that case.  We also save the outer-variable definition, * if any, because that's what we need for the loop-over-query case.  Note * that we must NOT apply check_assignable() or any other semantic check * until we know what's what. * * However, if we see a comma-separated list of names, we know that it * can't be an integer FOR loop and so it's OK to check the variables * immediately.  In particular, for T_WORD followed by comma, we should * complain that the name is not known rather than say it's a syntax error. * Note that the non-error result of this case sets *both* $$.scalar and * $$.row; see the for_control production. */for_variable	: T_SCALAR					{						int			tok;						$$.name = pstrdup(yytext);						$$.lineno  = plpgsql_scanner_lineno();						$$.scalar = yylval.scalar;						$$.rec = NULL;						$$.row = NULL;						/* check for comma-separated list */						tok = yylex();						plpgsql_push_back_token(tok);						if (tok == ',')							$$.row = read_into_scalar_list($$.name, $$.scalar);					}				| T_WORD					{						int			tok;						$$.name = pstrdup(yytext);						$$.lineno  = plpgsql_scanner_lineno();						$$.scalar = NULL;						$$.rec = NULL;						$$.row = NULL;						/* check for comma-separated list */						tok = yylex();						plpgsql_push_back_token(tok);						if (tok == ',')						{							plpgsql_error_lineno = $$.lineno;							ereport(ERROR,									(errcode(ERRCODE_SYNTAX_ERROR),									 errmsg("\"%s\" is not a scalar variable",											$$.name)));						}					}				| T_RECORD					{						$$.name = pstrdup(yytext);						$$.lineno  = plpgsql_scanner_lineno();						$$.scalar = NULL;						$$.rec = yylval.rec;						$$.row = NULL;					}				| T_ROW					{						$$.name = pstrdup(yytext);						$$.lineno  = plpgsql_scanner_lineno();						$$.scalar = NULL;						$$.row = yylval.row;						$$.rec = NULL;					}				;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					{						int	tok;						tok = yylex();						if (tok == 0)							yyerror("unexpected end of function definition");						/*						 * To avoid making NEXT and QUERY effectively be						 * reserved words within plpgsql, recognize them						 * via yytext.						 */						if (pg_strcasecmp(yytext, "next") == 0)						{							$$ = make_return_next_stmt($2);						}						else if (pg_strcasecmp(yytext, "query") == 0)						{							$$ = make_return_query_stmt($2);						}						else						{							plpgsql_push_back_token(tok);							$$ = make_return_stmt($2);						}					}				;stmt_raise		: K_RAISE lno raise_level raise_msg					{						PLpgSQL_stmt_raise		*new;						int	tok;						new = palloc(sizeof(PLpgSQL_stmt_raise));						new->cmd_type	= PLPGSQL_STMT_RAISE;						new->lineno		= $2;						new->elog_level = $3;						new->message	= $4;						new->params		= NIL;						tok = yylex();						/*						 * We expect either a semi-colon, which						 * indicates no parameters, or a comma that						 * begins the list of parameter expressions						 */						if (tok != ',' && tok != ';')							yyerror("syntax error");						if (tok == ',')						{							PLpgSQL_expr *expr;							int term;							for (;;)							{								expr = read_sql_construct(',', ';', ", or ;",														  "SELECT ",														  true, true, &term);								new->params = lappend(new->params, expr);								if (term == ';')									break;							}						}						$$ = (PLpgSQL_stmt *)new;					}				;raise_msg		: T_STRING					{						$$ = plpgsql_get_string_value();					}				;raise_level		: K_EXCEPTION					{						$$ = ERROR;					}				| K_WARNING					{						$$ = WARNING;					}				| K_NOTICE					{						$$ = NOTICE;					}				| K_INFO					{						$$ = INFO;					}				| K_LOG					{						$$ = LOG;					}				| K_DEBUG					{						$$ = DEBUG1;					}				;

⌨️ 快捷键说明

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