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

📄 gram.y

📁 PostgreSQL7.4.6 for Linux
💻 Y
📖 第 1 页 / 共 4 页
字号:
					}				;execsql_start	: T_WORD					{ $$ = strdup(yytext); }				| T_ERROR					{ $$ = strdup(yytext); }				;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_label		:					{						plpgsql_ns_push(NULL);						$$ = NULL;					}				| '<' '<' opt_lblname '>' '>'					{						plpgsql_ns_push($3);						$$ = $3;					}				;opt_exitlabel	:					{ $$ = NULL; }				| T_LABEL					{ $$ = strdup(yytext); }				;opt_exitcond	: ';'					{ $$ = NULL; }				| K_WHEN expr_until_semi					{ $$ = $2; }				;opt_lblname		: T_WORD					{						char	*name;						plpgsql_convert_ident(yytext, &name, 1);						$$ = strdup(name);						pfree(name);					}				;lno				:					{						$$ = plpgsql_error_lineno = plpgsql_scanner_lineno();					}				;%%PLpgSQL_expr *plpgsql_read_expression(int until, const char *expected){	return read_sql_construct(until, expected, true, "SELECT ");}static PLpgSQL_expr *read_sql_stmt(const char *sqlstart){	return read_sql_construct(';', ";", false, sqlstart);}static PLpgSQL_expr *read_sql_construct(int until,				   const char *expected,				   bool isexpression,				   const char *sqlstart){	int					tok;	int					lno;	PLpgSQL_dstring		ds;	int					parenlevel = 0;	int					nparams = 0;	int					params[1024];	char				buf[32];	PLpgSQL_expr		*expr;	lno = plpgsql_scanner_lineno();	plpgsql_dstring_init(&ds);	plpgsql_dstring_append(&ds, (char *) sqlstart);	for (;;)	{		tok = yylex();		if (tok == until && parenlevel == 0)			break;		if (tok == '(' || tok == '[')			parenlevel++;		else if (tok == ')' || tok == ']')		{			parenlevel--;			if (parenlevel < 0)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("mismatched parentheses")));		}		/*		 * End of function definition is an error, and we don't expect to		 * hit a semicolon either (unless it's the until symbol, in which		 * case we should have fallen out above).		 */		if (tok == 0 || tok == ';')		{			plpgsql_error_lineno = lno;			if (parenlevel != 0)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("mismatched parentheses")));			if (isexpression)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("missing \"%s\" at end of SQL expression",								expected)));			else				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("missing \"%s\" at end of SQL statement",								expected)));			break;		}		if (plpgsql_SpaceScanned)			plpgsql_dstring_append(&ds, " ");		switch (tok)		{			case T_VARIABLE:				params[nparams] = yylval.variable->dno;				snprintf(buf, sizeof(buf), " $%d ", ++nparams);				plpgsql_dstring_append(&ds, buf);				break;			default:				plpgsql_dstring_append(&ds, yytext);				break;		}	}	expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));	expr->dtype			= PLPGSQL_DTYPE_EXPR;	expr->query			= strdup(plpgsql_dstring_get(&ds));	expr->plan			= NULL;	expr->nparams		= nparams;	while(nparams-- > 0)		expr->params[nparams] = params[nparams];	plpgsql_dstring_free(&ds);	return expr;}static PLpgSQL_type *read_datatype(int tok){	int					lno;	PLpgSQL_dstring		ds;	PLpgSQL_type		*result;	bool				needspace = false;	int					parenlevel = 0;	lno = plpgsql_scanner_lineno();	/* Often there will be a lookahead token, but if not, get one */	if (tok == YYEMPTY)		tok = yylex();	if (tok == T_DTYPE)	{		/* lexer found word%TYPE and did its thing already */		return yylval.dtype;	}	plpgsql_dstring_init(&ds);	while (tok != ';')	{		if (tok == 0)		{			plpgsql_error_lineno = lno;			if (parenlevel != 0)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("mismatched parentheses")));			ereport(ERROR,					(errcode(ERRCODE_SYNTAX_ERROR),					 errmsg("incomplete datatype declaration")));		}		/* Possible followers for datatype in a declaration */		if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)			break;		/* Possible followers for datatype in a cursor_arg list */		if ((tok == ',' || tok == ')') && parenlevel == 0)			break;		if (tok == '(')			parenlevel++;		else if (tok == ')')			parenlevel--;		if (needspace)			plpgsql_dstring_append(&ds, " ");		needspace = true;		plpgsql_dstring_append(&ds, yytext);		tok = yylex();	}	plpgsql_push_back_token(tok);	plpgsql_error_lineno = lno;	/* in case of error in parse_datatype */	result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));	plpgsql_dstring_free(&ds);	return result;}static PLpgSQL_stmt *make_select_stmt(void){	PLpgSQL_dstring		ds;	int					nparams = 0;	int					params[1024];	char				buf[32];	PLpgSQL_expr		*expr;	PLpgSQL_row			*row = NULL;	PLpgSQL_rec			*rec = NULL;	int					tok = 0;	int					have_nexttok = 0;	int					have_into = 0;	plpgsql_dstring_init(&ds);	plpgsql_dstring_append(&ds, "SELECT ");	while(1)	{		if (!have_nexttok)			tok = yylex();		have_nexttok = 0;		if (tok == ';')			break;		if (tok == 0)		{			plpgsql_error_lineno = plpgsql_scanner_lineno();			ereport(ERROR,					(errcode(ERRCODE_SYNTAX_ERROR),					 errmsg("unexpected end of function definition")));		}		if (tok == K_INTO)		{			if (have_into)			{				plpgsql_error_lineno = plpgsql_scanner_lineno();				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("INTO specified more than once")));			}			tok = yylex();			switch (tok)			{				case T_ROW:					row = yylval.row;					have_into = 1;					break;				case T_RECORD:					rec = yylval.rec;					have_into = 1;					break;				case T_VARIABLE:				{					int				nfields = 1;					char			*fieldnames[1024];					int				varnos[1024];					check_assignable(yylval.variable);					fieldnames[0] = strdup(yytext);					varnos[0]	  = yylval.variable->dno;					while ((tok = yylex()) == ',')					{						tok = yylex();						switch(tok)						{							case T_VARIABLE:								check_assignable(yylval.variable);								fieldnames[nfields] = strdup(yytext);								varnos[nfields++]	= yylval.variable->dno;								break;							default:								plpgsql_error_lineno = plpgsql_scanner_lineno();								ereport(ERROR,										(errcode(ERRCODE_SYNTAX_ERROR),										 errmsg("\"%s\" is not a variable",												yytext)));						}					}					have_nexttok = 1;					row = malloc(sizeof(PLpgSQL_row));					row->dtype = PLPGSQL_DTYPE_ROW;					row->refname = strdup("*internal*");					row->lineno = plpgsql_scanner_lineno();					row->rowtupdesc = NULL;					row->nfields = nfields;					row->fieldnames = malloc(sizeof(char *) * nfields);					row->varnos = malloc(sizeof(int) * nfields);					while (--nfields >= 0)					{						row->fieldnames[nfields] = fieldnames[nfields];						row->varnos[nfields] = varnos[nfields];					}					plpgsql_adddatum((PLpgSQL_datum *)row);					have_into = 1;				}				break;				default:					/* Treat the INTO as non-special */					plpgsql_dstring_append(&ds, " INTO ");					have_nexttok = 1;					break;			}			continue;		}		if (plpgsql_SpaceScanned)			plpgsql_dstring_append(&ds, " ");		switch (tok)		{			case T_VARIABLE:				params[nparams] = yylval.variable->dno;				snprintf(buf, sizeof(buf), " $%d ", ++nparams);				plpgsql_dstring_append(&ds, buf);				break;			default:				plpgsql_dstring_append(&ds, yytext);				break;		}	}	expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));	expr->dtype			= PLPGSQL_DTYPE_EXPR;	expr->query			= strdup(plpgsql_dstring_get(&ds));	expr->plan			= NULL;	expr->nparams		= nparams;	while(nparams-- > 0)		expr->params[nparams] = params[nparams];	plpgsql_dstring_free(&ds);	if (have_into)	{		PLpgSQL_stmt_select *select;		select = malloc(sizeof(PLpgSQL_stmt_select));		memset(select, 0, sizeof(PLpgSQL_stmt_select));		select->cmd_type = PLPGSQL_STMT_SELECT;		select->rec		 = rec;		select->row		 = row;		select->query	 = expr;		return (PLpgSQL_stmt *)select;	}	else	{		PLpgSQL_stmt_execsql *execsql;		execsql = malloc(sizeof(PLpgSQL_stmt_execsql));		execsql->cmd_type = PLPGSQL_STMT_EXECSQL;		execsql->sqlstmt  = expr;		return (PLpgSQL_stmt *)execsql;	}}static PLpgSQL_stmt *make_fetch_stmt(void){	int					tok;	PLpgSQL_row		   *row = NULL;	PLpgSQL_rec		   *rec = NULL;	PLpgSQL_stmt_fetch *fetch;	int					have_nexttok = 0;	/* We have already parsed everything through the INTO keyword */	tok = yylex();	switch (tok)	{		case T_ROW:			row = yylval.row;			break;		case T_RECORD:			rec = yylval.rec;			break;		case T_VARIABLE:			{				int				nfields = 1;				char			*fieldnames[1024];				int				varnos[1024];				check_assignable(yylval.variable);				fieldnames[0] = strdup(yytext);				varnos[0]	  = yylval.variable->dno;				while ((tok = yylex()) == ',')				{					tok = yylex();					switch(tok)					{						case T_VARIABLE:							check_assignable(yylval.variable);							fieldnames[nfields] = strdup(yytext);							varnos[nfields++]	= yylval.variable->dno;							break;						default:							plpgsql_error_lineno = plpgsql_scanner_lineno();							ereport(ERROR,									(errcode(ERRCODE_SYNTAX_ERROR),									 errmsg("\"%s\" is not a variable",											yytext)));					}				}				have_nexttok = 1;				row = malloc(sizeof(PLpgSQL_row));				row->dtype = PLPGSQL_DTYPE_ROW;				row->refname = strdup("*internal*");				row->lineno = plpgsql_scanner_lineno();				row->rowtupdesc = NULL;				row->nfields = nfields;				row->fieldnames = malloc(sizeof(char *) * nfields);				row->varnos = malloc(sizeof(int) * nfields);				while (--nfields >= 0)				{					row->fieldnames[nfields] = fieldnames[nfields];					row->varnos[nfields] = varnos[nfields];				}				plpgsql_adddatum((PLpgSQL_datum *)row);			}			break;		default:			yyerror("syntax error");	}	if (!have_nexttok)		tok = yylex();	if (tok != ';')		yyerror("syntax error");	fetch = malloc(sizeof(PLpgSQL_stmt_select));	memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));	fetch->cmd_type = PLPGSQL_STMT_FETCH;	fetch->rec		 = rec;	fetch->row		 = row;	return (PLpgSQL_stmt *)fetch;}static voidcheck_assignable(PLpgSQL_datum *datum){	switch (datum->dtype)	{		case PLPGSQL_DTYPE_VAR:			if (((PLpgSQL_var *) datum)->isconst)			{				plpgsql_error_lineno = plpgsql_scanner_lineno();				ereport(ERROR,						(errcode(ERRCODE_ERROR_IN_ASSIGNMENT),						 errmsg("\"%s\" is declared CONSTANT",								((PLpgSQL_var *) datum)->refname)));			}			break;		case PLPGSQL_DTYPE_RECFIELD:			/* always assignable? */			break;		case PLPGSQL_DTYPE_ARRAYELEM:			/* always assignable? */			break;		case PLPGSQL_DTYPE_TRIGARG:			yyerror("cannot assign to tg_argv");			break;		default:			elog(ERROR, "unrecognized dtype: %d", datum->dtype);			break;	}}#include "pl_scan.c"

⌨️ 快捷键说明

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