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

📄 gram.y

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 Y
📖 第 1 页 / 共 4 页
字号:
						if (!plpgsql_curr_compile->fn_retset)							yyerror("cannot use RETURN NEXT in a non-SETOF function");						new = palloc0(sizeof(PLpgSQL_stmt_return_next));						new->cmd_type	= PLPGSQL_STMT_RETURN_NEXT;						new->lineno		= $2;						new->expr = NULL;						new->retvarno	= -1;						if (plpgsql_curr_compile->out_param_varno >= 0)						{							if (yylex() != ';')								yyerror("RETURN NEXT cannot have a parameter in function with OUT parameters");							new->retvarno = plpgsql_curr_compile->out_param_varno;						}						else if (plpgsql_curr_compile->fn_retistuple)						{							switch (yylex())							{								case T_ROW:									new->retvarno = yylval.row->rowno;									break;								case T_RECORD:									new->retvarno = yylval.rec->recno;									break;								default:									yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");									break;							}							if (yylex() != ';')								yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");						}						else							new->expr = plpgsql_read_expression(';', ";");						$$ = (PLpgSQL_stmt *)new;					}				;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;					}				;loop_body		: proc_sect K_END K_LOOP opt_label ';'					{						$$.stmts = $1;						$$.end_label = $4;					}				;stmt_execsql	: execsql_start lno					{						PLpgSQL_stmt_execsql	*new;						new = palloc(sizeof(PLpgSQL_stmt_execsql));						new->cmd_type = PLPGSQL_STMT_EXECSQL;						new->lineno   = $2;						new->sqlstmt  = read_sql_stmt($1);						$$ = (PLpgSQL_stmt *)new;					}				;stmt_dynexecute : K_EXECUTE lno					{						PLpgSQL_stmt_dynexecute *new;						PLpgSQL_expr *expr;						int endtoken;						expr = read_sql_construct(K_INTO, ';', "INTO|;", "SELECT ",												  true, true, &endtoken);						new = palloc(sizeof(PLpgSQL_stmt_dynexecute));						new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;						new->lineno   = $2;						new->query    = expr;						new->rec = NULL;						new->row = NULL;						/*						 * If we saw "INTO", look for a following row						 * var, record var, or list of scalars.						 */						if (endtoken == K_INTO)						{							switch (yylex())							{								case T_ROW:									check_assignable((PLpgSQL_datum *) yylval.row);									new->row = yylval.row;									break;								case T_RECORD:									check_assignable((PLpgSQL_datum *) yylval.row);									new->rec = yylval.rec;									break;								case T_SCALAR:									new->row = read_into_scalar_list(yytext, yylval.scalar);									break;								default:									plpgsql_error_lineno = $2;									ereport(ERROR,											(errcode(ERRCODE_SYNTAX_ERROR),											 errmsg("syntax error at \"%s\"", yytext),											 errdetail("Expected record variable, row variable, "													   "or list of scalar variables.")));							}							if (yylex() != ';')								yyerror("syntax error");						}						$$ = (PLpgSQL_stmt *)new;					}				;stmt_open		: K_OPEN lno cursor_varptr					{						PLpgSQL_stmt_open *new;						int				  tok;						new = palloc0(sizeof(PLpgSQL_stmt_open));						new->cmd_type = PLPGSQL_STMT_OPEN;						new->lineno = $2;						new->curvar = $3->varno;						if ($3->cursor_explicit_expr == NULL)						{						    tok = yylex();							if (tok != K_FOR)							{								plpgsql_error_lineno = $2;								ereport(ERROR,										(errcode(ERRCODE_SYNTAX_ERROR),										 errmsg("syntax error at \"%s\"",												yytext),										 errdetail("Expected FOR to open a reference cursor.")));							}							tok = yylex();							if (tok == K_EXECUTE)							{								new->dynquery = read_sql_stmt("SELECT ");							}							else							{								plpgsql_push_back_token(tok);								new->query = read_sql_stmt("");							}						}						else						{							if ($3->cursor_explicit_argrow >= 0)							{								char   *cp;								tok = yylex();								if (tok != '(')								{									plpgsql_error_lineno = plpgsql_scanner_lineno();									ereport(ERROR,											(errcode(ERRCODE_SYNTAX_ERROR),											 errmsg("cursor \"%s\" has arguments",													$3->refname)));								}								/*								 * Push back the '(', else read_sql_stmt								 * will complain about unbalanced parens.								 */								plpgsql_push_back_token(tok);								new->argquery = read_sql_stmt("SELECT ");								/*								 * Now remove the leading and trailing parens,								 * because we want "select 1, 2", not								 * "select (1, 2)".								 */								cp = new->argquery->query;								if (strncmp(cp, "SELECT", 6) != 0)								{									plpgsql_error_lineno = plpgsql_scanner_lineno();									/* internal error */									elog(ERROR, "expected \"SELECT (\", got \"%s\"",										 new->argquery->query);								}								cp += 6;								while (*cp == ' ') /* could be more than 1 space here */									cp++;								if (*cp != '(')								{									plpgsql_error_lineno = plpgsql_scanner_lineno();									/* internal error */									elog(ERROR, "expected \"SELECT (\", got \"%s\"",										 new->argquery->query);								}								*cp = ' ';								cp += strlen(cp) - 1;								if (*cp != ')')									yyerror("expected \")\"");								*cp = '\0';							}							else							{								tok = yylex();								if (tok == '(')								{									plpgsql_error_lineno = plpgsql_scanner_lineno();									ereport(ERROR,											(errcode(ERRCODE_SYNTAX_ERROR),											 errmsg("cursor \"%s\" has no arguments",													$3->refname)));								}								if (tok != ';')								{									plpgsql_error_lineno = plpgsql_scanner_lineno();									ereport(ERROR,											(errcode(ERRCODE_SYNTAX_ERROR),											 errmsg("syntax error at \"%s\"",													yytext)));								}							}						}						$$ = (PLpgSQL_stmt *)new;					}				;stmt_fetch		: K_FETCH lno cursor_variable K_INTO					{						PLpgSQL_stmt_fetch *new;						new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();						new->curvar = $3;						$$ = (PLpgSQL_stmt *)new;						$$->lineno = $2;					}				;stmt_close		: K_CLOSE lno cursor_variable ';'					{						PLpgSQL_stmt_close *new;						new = palloc(sizeof(PLpgSQL_stmt_close));						new->cmd_type = PLPGSQL_STMT_CLOSE;						new->lineno = $2;						new->curvar = $3;						$$ = (PLpgSQL_stmt *)new;					}				;stmt_null		: K_NULL ';'					{						/* We do not bother building a node for NULL */						$$ = NULL;					}				;cursor_varptr	: T_SCALAR					{						if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)							yyerror("cursor variable must be a simple variable");						if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)						{							plpgsql_error_lineno = plpgsql_scanner_lineno();							ereport(ERROR,									(errcode(ERRCODE_DATATYPE_MISMATCH),									 errmsg("\"%s\" must be of type cursor or refcursor",											((PLpgSQL_var *) yylval.scalar)->refname)));						}						$$ = (PLpgSQL_var *) yylval.scalar;					}				;cursor_variable	: T_SCALAR					{						if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)							yyerror("cursor variable must be a simple variable");						if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)						{							plpgsql_error_lineno = plpgsql_scanner_lineno();							ereport(ERROR,									(errcode(ERRCODE_DATATYPE_MISMATCH),									 errmsg("\"%s\" must be of type refcursor",											((PLpgSQL_var *) yylval.scalar)->refname)));						}						$$ = yylval.scalar->dno;					}				;execsql_start	: T_WORD					{ $$ = pstrdup(yytext); }				| T_ERROR					{ $$ = pstrdup(yytext); }				;exception_sect	:					{ $$ = NULL; }				| K_EXCEPTION lno					{						/*						 * We use a mid-rule action to add these						 * special variables to the namespace before						 * parsing the WHEN clauses themselves.						 */						PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));						PLpgSQL_variable *var;						var = plpgsql_build_variable("sqlstate", $2,													 plpgsql_build_datatype(TEXTOID, -1),													 true);						((PLpgSQL_var *) var)->isconst = true;						new->sqlstate_varno = var->dno;						var = plpgsql_build_variable("sqlerrm", $2,													 plpgsql_build_datatype(TEXTOID, -1),													 true);						((PLpgSQL_var *) var)->isconst = true;						new->sqlerrm_varno = var->dno;						$<exception_block>$ = new;					}					proc_exceptions					{						PLpgSQL_exception_block *new = $<exception_block>3;						new->exc_list = $4;						$$ = new;					}				;proc_exceptions	: proc_exceptions proc_exception						{							$$ = lappend($1, $2);						}				| proc_exception						{							$$ = list_make1($1);						}				;proc_exception	: K_WHEN lno proc_conditions K_THEN proc_sect					{						PLpgSQL_exception *new;						new = palloc0(sizeof(PLpgSQL_exception));						new->lineno     = $2;						new->conditions = $3;						new->action	    = $5;						$$ = new;					}				;proc_conditions	: proc_conditions K_OR opt_lblname						{							PLpgSQL_condition	*old;							for (old = $1; old->next != NULL; old = old->next)								/* skip */ ;							old->next = plpgsql_parse_err_condition($3);							$$ = $1;						}				| opt_lblname						{							$$ = plpgsql_parse_err_condition($1);						}				;expr_until_semi :					{ $$ = plpgsql_read_expression(';', ";"); }				;expr_until_rightbracket :					{ $$ = plpgsql_read_expression(']', "]"); }				;expr_until_then :					{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }				;expr_until_loop :					{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }				;opt_block_label	:					{						plpgsql_ns_push(NULL);						$$ = NULL;					}				| '<' '<' opt_lblname '>' '>'					{						plpgsql_ns_push($3);						$$ = $3;					}				;opt_label	:					{						$$ = NULL;					}				| T_LABEL					{						char *label_name;						plpgsql_convert_ident(yytext, &label_name, 1);						$$ = label_name;					}				| T_WORD					{						/* just to give a better error than "syntax error" */						yyerror("no such label");					}				;opt_exitcond	: ';'					{ $$ = NULL; }				| K_WHEN expr_until_semi					{ $$ = $2; }				;opt_lblname		: T_WORD					{						char	*name;						plpgsql_convert_ident(yytext, &name, 1);						$$ = name;					}				;lno				:					{						$$ = plpgsql_error_lineno = plpgsql_scanner_lineno();					}				;%%#define MAX_EXPR_PARAMS  1024/* * determine the expression parameter position to use for a plpgsql datum * * It is important that any given plpgsql datum map to just one parameter. * We used to be sloppy and assign a separate parameter for each occurrence * of a datum reference, but that fails for situations such as "select DATUM * from ... group by DATUM". * * The params[] array must be of size MAX_EXPR_PARAMS. */static intassign_expr_param(int dno, int *params, int *nparams){	int		i;	/* already have an instance of this dno? */	for (i = 0; i < *nparams; i++)	{		if (params[i] == dno)			return i+1;	}	/* check for array overflow */	if (*nparams >= MAX_EXPR_PARAMS)	{		plpgsql_error_lineno = plpgsql_scanner_lineno();		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("too many variables specified in SQL statement")));	}	/* add new parameter dno to array */	params[*nparams] = dno;	(*nparams)++;	return *nparams;}PLpgSQL_expr *plpgsql_read_expression(int until, const char *expected){	return read_sql_construct(until, 0, expected, "SELECT ", true, true, NULL);}static PLpgSQL_expr *read_sql_stmt(const char *sqlstart){	return read_sql_construct(';', 0, ";", sqlstart, false, true, NULL);

⌨️ 快捷键说明

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