📄 gram.y
字号:
{ char *name; plpgsql_convert_ident(yytext, &name, 1); /* name should be malloc'd for use as varname */ $$.name = strdup(name); $$.lineno = plpgsql_scanner_lineno(); pfree(name); } | T_WORD { char *name; plpgsql_convert_ident(yytext, &name, 1); /* name should be malloc'd for use as varname */ $$.name = strdup(name); $$.lineno = plpgsql_scanner_lineno(); pfree(name); } ;fori_lower : { int tok; tok = yylex(); if (tok == K_REVERSE) { $$.reverse = 1; } else { $$.reverse = 0; plpgsql_push_back_token(tok); } $$.expr = plpgsql_read_expression(K_DOTDOT, ".."); } ;stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body { PLpgSQL_stmt_fors *new; new = malloc(sizeof(PLpgSQL_stmt_fors)); memset(new, 0, sizeof(PLpgSQL_stmt_fors)); new->cmd_type = PLPGSQL_STMT_FORS; new->lineno = $3; new->label = $1; switch ($4->dtype) { case PLPGSQL_DTYPE_REC: new->rec = $4; break; case PLPGSQL_DTYPE_ROW: new->row = (PLpgSQL_row *)$4; break; default: elog(ERROR, "unrecognized dtype: %d", $4->dtype); } new->query = $7; new->body = $8; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body { PLpgSQL_stmt_dynfors *new; new = malloc(sizeof(PLpgSQL_stmt_dynfors)); memset(new, 0, sizeof(PLpgSQL_stmt_dynfors)); new->cmd_type = PLPGSQL_STMT_DYNFORS; new->lineno = $3; new->label = $1; switch ($4->dtype) { case PLPGSQL_DTYPE_REC: new->rec = $4; break; case PLPGSQL_DTYPE_ROW: new->row = (PLpgSQL_row *)$4; break; default: elog(ERROR, "unrecognized dtype: %d", $4->dtype); } new->query = $7; new->body = $8; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;fors_target : T_RECORD { $$ = yylval.rec; } | T_ROW { $$ = (PLpgSQL_rec *)(yylval.row); } ;stmt_select : K_SELECT lno { $$ = make_select_stmt(); $$->lineno = $2; } ;stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond { PLpgSQL_stmt_exit *new; new = malloc(sizeof(PLpgSQL_stmt_exit)); memset(new, 0, sizeof(PLpgSQL_stmt_exit)); new->cmd_type = PLPGSQL_STMT_EXIT; new->lineno = $2; new->label = $3; new->cond = $4; $$ = (PLpgSQL_stmt *)new; } ;stmt_return : K_RETURN lno { PLpgSQL_stmt_return *new; new = malloc(sizeof(PLpgSQL_stmt_return)); memset(new, 0, sizeof(PLpgSQL_stmt_return)); new->expr = NULL; new->retrecno = -1; new->retrowno = -1; if (plpgsql_curr_compile->fn_retistuple && !plpgsql_curr_compile->fn_retset) { switch (yylex()) { case K_NULL: break; case T_ROW: new->retrowno = yylval.row->rowno; break; case T_RECORD: new->retrecno = yylval.rec->recno; break; default: yyerror("return type mismatch in function returning tuple"); break; } if (yylex() != ';') yyerror("expected \";\""); } else new->expr = plpgsql_read_expression(';', ";"); new->cmd_type = PLPGSQL_STMT_RETURN; new->lineno = $2; $$ = (PLpgSQL_stmt *)new; } ;stmt_return_next: K_RETURN_NEXT lno { PLpgSQL_stmt_return_next *new; new = malloc(sizeof(PLpgSQL_stmt_return_next)); memset(new, 0, sizeof(PLpgSQL_stmt_return_next)); new->cmd_type = PLPGSQL_STMT_RETURN_NEXT; new->lineno = $2; if (plpgsql_curr_compile->fn_retistuple) { int tok = yylex(); if (tok == T_RECORD) new->rec = yylval.rec; else if (tok == T_ROW) new->row = yylval.row; else yyerror("incorrect argument to RETURN NEXT"); if (yylex() != ';') yyerror("expected \";\""); } else new->expr = plpgsql_read_expression(';', ";"); $$ = (PLpgSQL_stmt *)new; } ;stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';' { PLpgSQL_stmt_raise *new; new = malloc(sizeof(PLpgSQL_stmt_raise)); new->cmd_type = PLPGSQL_STMT_RAISE; new->lineno = $2; new->elog_level = $3; new->message = $4; new->nparams = $5.nused; new->params = malloc(sizeof(int) * $5.nused); memcpy(new->params, $5.nums, sizeof(int) * $5.nused); $$ = (PLpgSQL_stmt *)new; } | K_RAISE lno raise_level raise_msg ';' { PLpgSQL_stmt_raise *new; new = malloc(sizeof(PLpgSQL_stmt_raise)); new->cmd_type = PLPGSQL_STMT_RAISE; new->lineno = $2; new->elog_level = $3; new->message = $4; new->nparams = 0; new->params = NULL; $$ = (PLpgSQL_stmt *)new; } ;raise_msg : T_STRING { $$ = strdup(yytext); } ;raise_level : K_EXCEPTION { $$ = ERROR; } | K_WARNING { $$ = WARNING; } | K_NOTICE { $$ = NOTICE; } | K_INFO { $$ = INFO; } | K_LOG { $$ = LOG; } | K_DEBUG { $$ = DEBUG2; } ;raise_params : raise_params raise_param { if ($1.nused == $1.nalloc) { $1.nalloc *= 2; $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc); } $1.nums[$1.nused++] = $2; $$.nalloc = $1.nalloc; $$.nused = $1.nused; $$.nums = $1.nums; } | raise_param { $$.nalloc = 1; $$.nused = 1; $$.nums = palloc(sizeof(int) * $$.nalloc); $$.nums[0] = $1; } ;raise_param : ',' T_VARIABLE { $$ = yylval.variable->dno; } ;loop_body : proc_sect K_END K_LOOP ';' { $$ = $1; } ;stmt_execsql : execsql_start lno { PLpgSQL_stmt_execsql *new; new = malloc(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 expr_until_semi { PLpgSQL_stmt_dynexecute *new; new = malloc(sizeof(PLpgSQL_stmt_dynexecute)); new->cmd_type = PLPGSQL_STMT_DYNEXECUTE; new->lineno = $2; new->query = $3; $$ = (PLpgSQL_stmt *)new; } ;stmt_open : K_OPEN lno cursor_varptr { PLpgSQL_stmt_open *new; int tok; new = malloc(sizeof(PLpgSQL_stmt_open)); memset(new, 0, 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(); switch (tok) { case K_SELECT: case '(': plpgsql_push_back_token(tok); new->query = read_sql_stmt(""); break; case K_EXECUTE: new->dynquery = read_sql_stmt("SELECT "); break; default: plpgsql_error_lineno = $2; ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error at \"%s\"", yytext))); } } 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 = malloc(sizeof(PLpgSQL_stmt_close)); new->cmd_type = PLPGSQL_STMT_CLOSE; new->lineno = $2; new->curvar = $3; $$ = (PLpgSQL_stmt *)new; } ;cursor_varptr : T_VARIABLE { if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR) yyerror("cursor variable must be a simple variable"); if (((PLpgSQL_var *) yylval.variable)->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.variable)->refname))); } $$ = (PLpgSQL_var *) yylval.variable; } ;cursor_variable : T_VARIABLE { if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR) yyerror("cursor variable must be a simple variable"); if (((PLpgSQL_var *) yylval.variable)->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.variable)->refname))); } $$ = yylval.variable->dno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -