@ -61,6 +61,10 @@ static bool tok_is_keyword(int token, union YYSTYPE *lval,
static void word_is_not_variable(PLword *word, int location, yyscan_t yyscanner);
static void word_is_not_variable(PLword *word, int location, yyscan_t yyscanner);
static void cword_is_not_variable(PLcword *cword, int location, yyscan_t yyscanner);
static void cword_is_not_variable(PLcword *cword, int location, yyscan_t yyscanner);
static void current_token_is_not_variable(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner);
static void current_token_is_not_variable(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner);
static PLpgSQL_expr *make_plpgsql_expr(const char *query,
RawParseMode parsemode);
static void mark_expr_as_assignment_source(PLpgSQL_expr *expr,
PLpgSQL_datum *target);
static PLpgSQL_expr *read_sql_construct(int until,
static PLpgSQL_expr *read_sql_construct(int until,
int until2,
int until2,
int until3,
int until3,
@ -536,6 +540,10 @@ decl_statement : decl_varname decl_const decl_datatype decl_collate decl_notnull
errmsg("variable \"%s\" must have a default value, since it's declared NOT NULL",
errmsg("variable \"%s\" must have a default value, since it's declared NOT NULL",
var->refname),
var->refname),
parser_errposition(@5)));
parser_errposition(@5)));
if (var->default_val != NULL)
mark_expr_as_assignment_source(var->default_val,
(PLpgSQL_datum *) var);
}
}
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
{
{
@ -996,6 +1004,7 @@ stmt_assign : T_DATUM
false, true,
false, true,
NULL, NULL,
NULL, NULL,
&yylval, &yylloc, yyscanner);
&yylval, &yylloc, yyscanner);
mark_expr_as_assignment_source(new->expr, $1.datum);
$$ = (PLpgSQL_stmt *) new;
$$ = (PLpgSQL_stmt *) new;
}
}
@ -2651,6 +2660,38 @@ current_token_is_not_variable(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yysca
yyerror(yyllocp, NULL, yyscanner, "syntax error");
yyerror(yyllocp, NULL, yyscanner, "syntax error");
}
}
/* Convenience routine to construct a PLpgSQL_expr struct */
static PLpgSQL_expr *
make_plpgsql_expr(const char *query,
RawParseMode parsemode)
{
PLpgSQL_expr *expr = palloc0(sizeof(PLpgSQL_expr));
expr->query = pstrdup(query);
expr->parseMode = parsemode;
expr->func = plpgsql_curr_compile;
expr->ns = plpgsql_ns_top();
/* might get changed later during parsing: */
expr->target_param = -1;
/* other fields are left as zeroes until first execution */
return expr;
}
/* Mark a PLpgSQL_expr as being the source of an assignment to target */
static void
mark_expr_as_assignment_source(PLpgSQL_expr *expr, PLpgSQL_datum *target)
{
/*
* Mark the expression as being an assignment source, if target is a
* simple variable. We don't currently support optimized assignments to
* other DTYPEs, so no need to mark in other cases.
*/
if (target->dtype == PLPGSQL_DTYPE_VAR)
expr->target_param = target->dno;
else
expr->target_param = -1; /* should be that already */
}
/* Convenience routine to read an expression with one possible terminator */
/* Convenience routine to read an expression with one possible terminator */
static PLpgSQL_expr *
static PLpgSQL_expr *
read_sql_expression(int until, const char *expected, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner)
read_sql_expression(int until, const char *expected, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner)
@ -2794,13 +2835,7 @@ read_sql_construct(int until,
*/
*/
plpgsql_append_source_text(&ds, startlocation, endlocation, yyscanner);
plpgsql_append_source_text(&ds, startlocation, endlocation, yyscanner);
expr = palloc0(sizeof(PLpgSQL_expr));
expr = make_plpgsql_expr(ds.data, parsemode);
expr->query = pstrdup(ds.data);
expr->parseMode = parsemode;
expr->plan = NULL;
expr->paramnos = NULL;
expr->target_param = -1;
expr->ns = plpgsql_ns_top();
pfree(ds.data);
pfree(ds.data);
if (valid_sql)
if (valid_sql)
@ -3122,13 +3157,7 @@ make_execsql_stmt(int firsttoken, int location, PLword *word, YYSTYPE *yylvalp,
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
ds.data[--ds.len] = '\0';
ds.data[--ds.len] = '\0';
expr = palloc0(sizeof(PLpgSQL_expr));
expr = make_plpgsql_expr(ds.data, RAW_PARSE_DEFAULT);
expr->query = pstrdup(ds.data);
expr->parseMode = RAW_PARSE_DEFAULT;
expr->plan = NULL;
expr->paramnos = NULL;
expr->target_param = -1;
expr->ns = plpgsql_ns_top();
pfree(ds.data);
pfree(ds.data);
check_sql_expr(expr->query, expr->parseMode, location, yyscanner);
check_sql_expr(expr->query, expr->parseMode, location, yyscanner);
@ -4006,13 +4035,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyll
appendStringInfoString(&ds, ", ");
appendStringInfoString(&ds, ", ");
}
}
expr = palloc0(sizeof(PLpgSQL_expr));
expr = make_plpgsql_expr(ds.data, RAW_PARSE_PLPGSQL_EXPR);
expr->query = pstrdup(ds.data);
expr->parseMode = RAW_PARSE_PLPGSQL_EXPR;
expr->plan = NULL;
expr->paramnos = NULL;
expr->target_param = -1;
expr->ns = plpgsql_ns_top();
pfree(ds.data);
pfree(ds.data);
/* Next we'd better find the until token */
/* Next we'd better find the until token */