RawParseMode parsemode,
bool isexpression,
bool valid_sql,
- bool trim,
int *startloc,
int *endtoken);
static PLpgSQL_expr *read_sql_expression(int until,
*/
new->expr = read_sql_construct(';', 0, 0, ";",
RAW_PARSE_DEFAULT,
- false, false, true,
+ false, false,
&startloc, NULL);
/* overwrite "perform" ... */
memcpy(new->expr->query, " SELECT", 7);
plpgsql_push_back_token(T_DATUM);
new->expr = read_sql_construct(';', 0, 0, ";",
pmode,
- false, true, true,
+ false, true,
NULL, NULL);
$$ = (PLpgSQL_stmt *) new;
RAW_PARSE_DEFAULT,
true,
false,
- true,
&expr1loc,
&tok);
expr = read_sql_construct(',', ';', K_USING,
", or ; or USING",
RAW_PARSE_PLPGSQL_EXPR,
- true, true, true,
+ true, true,
NULL, &tok);
new->params = lappend(new->params, expr);
}
expr = read_sql_construct(K_INTO, K_USING, ';',
"INTO or USING or ;",
RAW_PARSE_PLPGSQL_EXPR,
- true, true, true,
+ true, true,
NULL, &endtoken);
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
expr = read_sql_construct(',', ';', K_INTO,
", or ; or INTO",
RAW_PARSE_PLPGSQL_EXPR,
- true, true, true,
+ true, true,
NULL, &endtoken);
new->params = lappend(new->params, expr);
} while (endtoken == ',');
{
return read_sql_construct(until, 0, 0, expected,
RAW_PARSE_PLPGSQL_EXPR,
- true, true, true, NULL, NULL);
+ true, true, NULL, NULL);
}
/* Convenience routine to read an expression with two possible terminators */
{
return read_sql_construct(until, until2, 0, expected,
RAW_PARSE_PLPGSQL_EXPR,
- true, true, true, NULL, endtoken);
+ true, true, NULL, endtoken);
}
/* Convenience routine to read a SQL statement that must end with ';' */
{
return read_sql_construct(';', 0, 0, ";",
RAW_PARSE_DEFAULT,
- false, true, true, NULL, NULL);
+ false, true, NULL, NULL);
}
/*
* parsemode: raw_parser() mode to use
* isexpression: whether to say we're reading an "expression" or a "statement"
* 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
* endtoken: if not NULL, ending token is stored at *endtoken
* (this is only interesting if until2 or until3 isn't zero)
RawParseMode parsemode,
bool isexpression,
bool valid_sql,
- bool trim,
int *startloc,
int *endtoken)
{
StringInfoData ds;
IdentifierLookup save_IdentifierLookup;
int startlocation = -1;
+ int endlocation = -1;
int parenlevel = 0;
PLpgSQL_expr *expr;
expected),
parser_errposition(yylloc)));
}
+ /* Remember end+1 location of last accepted token */
+ endlocation = yylloc + plpgsql_token_length();
}
plpgsql_IdentifierLookup = save_IdentifierLookup;
*endtoken = tok;
/* give helpful complaint about empty input */
- if (startlocation >= yylloc)
+ if (startlocation >= endlocation)
{
if (isexpression)
yyerror("missing expression");
yyerror("missing SQL statement");
}
- plpgsql_append_source_text(&ds, startlocation, yylloc);
-
- /* trim any trailing whitespace, for neatness */
- if (trim)
- {
- while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
- ds.data[--ds.len] = '\0';
- }
+ /*
+ * We save only the text from startlocation to endlocation-1. This
+ * suppresses the "until" token as well as any whitespace or comments
+ * following the last accepted token. (We used to strip such trailing
+ * whitespace by hand, but that causes problems if there's a "-- comment"
+ * in front of said whitespace.)
+ */
+ plpgsql_append_source_text(&ds, startlocation, endlocation);
expr = palloc0(sizeof(PLpgSQL_expr));
expr->query = pstrdup(ds.data);
* Read the value expression. To provide the user with meaningful
* parse error positions, we check the syntax immediately, instead of
* checking the final expression that may have the arguments
- * reordered. Trailing whitespace must not be trimmed, because
- * otherwise input of the form (param -- comment\n, param) would be
- * translated into a form where the second parameter is commented
- * out.
+ * reordered.
*/
item = read_sql_construct(',', ')', 0,
",\" or \")",
RAW_PARSE_PLPGSQL_EXPR,
true, true,
- false, /* do not trim */
NULL, &endtoken);
argv[argpos] = item->query;