@ -69,7 +69,6 @@ static PLpgSQL_expr *read_sql_construct(int until,
RawParseMode parsemode,
RawParseMode parsemode,
bool isexpression,
bool isexpression,
bool valid_sql,
bool valid_sql,
bool trim,
int *startloc,
int *startloc,
int *endtoken);
int *endtoken);
static PLpgSQL_expr *read_sql_expression(int until,
static PLpgSQL_expr *read_sql_expression(int until,
@ -923,7 +922,7 @@ stmt_perform : K_PERFORM
*/
*/
new->expr = read_sql_construct(';', 0, 0, ";",
new->expr = read_sql_construct(';', 0, 0, ";",
RAW_PARSE_DEFAULT,
RAW_PARSE_DEFAULT,
false, false, true,
false, false,
&startloc, NULL);
&startloc, NULL);
/* overwrite "perform" ... */
/* overwrite "perform" ... */
memcpy(new->expr->query, " SELECT", 7);
memcpy(new->expr->query, " SELECT", 7);
@ -1009,7 +1008,7 @@ stmt_assign : T_DATUM
plpgsql_push_back_token(T_DATUM);
plpgsql_push_back_token(T_DATUM);
new->expr = read_sql_construct(';', 0, 0, ";",
new->expr = read_sql_construct(';', 0, 0, ";",
pmode,
pmode,
false, true, true,
false, true,
NULL, NULL);
NULL, NULL);
$$ = (PLpgSQL_stmt *) new;
$$ = (PLpgSQL_stmt *) new;
@ -1498,7 +1497,6 @@ for_control : for_variable K_IN
RAW_PARSE_DEFAULT,
RAW_PARSE_DEFAULT,
true,
true,
false,
false,
true,
&expr1loc,
&expr1loc,
&tok);
&tok);
@ -1903,7 +1901,7 @@ stmt_raise : K_RAISE
expr = read_sql_construct(',', ';', K_USING,
expr = read_sql_construct(',', ';', K_USING,
", or ; or USING",
", or ; or USING",
RAW_PARSE_PLPGSQL_EXPR,
RAW_PARSE_PLPGSQL_EXPR,
true, true, true,
true, true,
NULL, &tok);
NULL, &tok);
new->params = lappend(new->params, expr);
new->params = lappend(new->params, expr);
}
}
@ -2040,7 +2038,7 @@ stmt_dynexecute : K_EXECUTE
expr = read_sql_construct(K_INTO, K_USING, ';',
expr = read_sql_construct(K_INTO, K_USING, ';',
"INTO or USING or ;",
"INTO or USING or ;",
RAW_PARSE_PLPGSQL_EXPR,
RAW_PARSE_PLPGSQL_EXPR,
true, true, true,
true, true,
NULL, &endtoken);
NULL, &endtoken);
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
@ -2079,7 +2077,7 @@ stmt_dynexecute : K_EXECUTE
expr = read_sql_construct(',', ';', K_INTO,
expr = read_sql_construct(',', ';', K_INTO,
", or ; or INTO",
", or ; or INTO",
RAW_PARSE_PLPGSQL_EXPR,
RAW_PARSE_PLPGSQL_EXPR,
true, true, true,
true, true,
NULL, &endtoken);
NULL, &endtoken);
new->params = lappend(new->params, expr);
new->params = lappend(new->params, expr);
} while (endtoken == ',');
} while (endtoken == ',');
@ -2663,7 +2661,7 @@ read_sql_expression(int until, const char *expected)
{
{
return read_sql_construct(until, 0, 0, expected,
return read_sql_construct(until, 0, 0, expected,
RAW_PARSE_PLPGSQL_EXPR,
RAW_PARSE_PLPGSQL_EXPR,
true, true, true, NULL, NULL);
true, true, NULL, NULL);
}
}
/* Convenience routine to read an expression with two possible terminators */
/* Convenience routine to read an expression with two possible terminators */
@ -2673,7 +2671,7 @@ read_sql_expression2(int until, int until2, const char *expected,
{
{
return read_sql_construct(until, until2, 0, expected,
return read_sql_construct(until, until2, 0, expected,
RAW_PARSE_PLPGSQL_EXPR,
RAW_PARSE_PLPGSQL_EXPR,
true, true, true, NULL, endtoken);
true, true, NULL, endtoken);
}
}
/* Convenience routine to read a SQL statement that must end with ';' */
/* Convenience routine to read a SQL statement that must end with ';' */
@ -2682,7 +2680,7 @@ read_sql_stmt(void)
{
{
return read_sql_construct(';', 0, 0, ";",
return read_sql_construct(';', 0, 0, ";",
RAW_PARSE_DEFAULT,
RAW_PARSE_DEFAULT,
false, true, true, NULL, NULL);
false, true, NULL, NULL);
}
}
/*
/*
@ -2695,7 +2693,6 @@ read_sql_stmt(void)
* parsemode: raw_parser() mode to use
* parsemode: raw_parser() mode to use
* isexpression: whether to say we're reading an "expression" or a "statement"
* isexpression: whether to say we're reading an "expression" or a "statement"
* valid_sql: whether to check the syntax of the expr
* valid_sql: whether to check the syntax of the expr
* trim: trim trailing whitespace
* startloc: if not NULL, location of first token is stored at *startloc
* startloc: if not NULL, location of first token is stored at *startloc
* endtoken: if not NULL, ending token is stored at *endtoken
* endtoken: if not NULL, ending token is stored at *endtoken
* (this is only interesting if until2 or until3 isn't zero)
* (this is only interesting if until2 or until3 isn't zero)
@ -2708,7 +2705,6 @@ read_sql_construct(int until,
RawParseMode parsemode,
RawParseMode parsemode,
bool isexpression,
bool isexpression,
bool valid_sql,
bool valid_sql,
bool trim,
int *startloc,
int *startloc,
int *endtoken)
int *endtoken)
{
{
@ -2716,6 +2712,7 @@ read_sql_construct(int until,
StringInfoData ds;
StringInfoData ds;
IdentifierLookup save_IdentifierLookup;
IdentifierLookup save_IdentifierLookup;
int startlocation = -1;
int startlocation = -1;
int endlocation = -1;
int parenlevel = 0;
int parenlevel = 0;
PLpgSQL_expr *expr;
PLpgSQL_expr *expr;
@ -2766,6 +2763,8 @@ read_sql_construct(int until,
expected),
expected),
parser_errposition(yylloc)));
parser_errposition(yylloc)));
}
}
/* Remember end+1 location of last accepted token */
endlocation = yylloc + plpgsql_token_length();
}
}
plpgsql_IdentifierLookup = save_IdentifierLookup;
plpgsql_IdentifierLookup = save_IdentifierLookup;
@ -2776,7 +2775,7 @@ read_sql_construct(int until,
*endtoken = tok;
*endtoken = tok;
/* give helpful complaint about empty input */
/* give helpful complaint about empty input */
if (startlocation >= yylloc )
if (startlocation >= endlocation )
{
{
if (isexpression)
if (isexpression)
yyerror("missing expression");
yyerror("missing expression");
@ -2784,14 +2783,14 @@ read_sql_construct(int until,
yyerror("missing SQL statement");
yyerror("missing SQL statement");
}
}
plpgsql_append_source_text(&ds, startlocation, yylloc);
/*
* We save only the text from startlocation to endlocation-1. This
/* trim any trailing whitespace, for neatness */
* suppresses the "until" token as well as any whitespace or comments
if (trim)
* following the last accepted token. (We used to strip such trailing
{
* whitespace by hand, but that causes problems if there's a "-- comment"
while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]) )
* in front of said whitespace. )
ds.data[--ds.len] = '\0';
*/
}
plpgsql_append_source_text(&ds, startlocation, endlocation);
expr = palloc0(sizeof(PLpgSQL_expr));
expr = palloc0(sizeof(PLpgSQL_expr));
expr->query = pstrdup(ds.data);
expr->query = pstrdup(ds.data);
@ -3932,16 +3931,12 @@ read_cursor_args(PLpgSQL_var *cursor, int until)
* Read the value expression. To provide the user with meaningful
* Read the value expression. To provide the user with meaningful
* parse error positions, we check the syntax immediately, instead of
* parse error positions, we check the syntax immediately, instead of
* checking the final expression that may have the arguments
* checking the final expression that may have the arguments
* reordered. Trailing whitespace must not be trimmed, because
* reordered.
* otherwise input of the form (param -- comment\n, param) would be
* translated into a form where the second parameter is commented
* out.
*/
*/
item = read_sql_construct(',', ')', 0,
item = read_sql_construct(',', ')', 0,
",\" or \")",
",\" or \")",
RAW_PARSE_PLPGSQL_EXPR,
RAW_PARSE_PLPGSQL_EXPR,
true, true,
true, true,
false, /* do not trim */
NULL, &endtoken);
NULL, &endtoken);
argv[argpos] = item->query;
argv[argpos] = item->query;