Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3a624e9

Browse files
committed
Revise plpgsql's scanner to process comments and string literals in a way
more nearly matching the core SQL scanner. The user-visible effects are:* Block comments (slash-star comments) now nest, as per SQL spec.* In standard_conforming_strings mode, backslash as the last character of a non-E string literal is now correctly taken as an ordinary character; formerly it was misinterpreted as escaping the ending quote. (Since the string also had to pass through the core scanner, this invariably led to syntax errors.)* Formerly, backslashes in the format string of RAISE were always treated as quoting the next character, regardless of mode. Now, they are ordinary characters with standard_conforming_strings on, while with it off, they introduce the same set of escapes as in the core SQL scanner. Also, escape_string_warning is now effective for RAISE format strings. These changes make RAISE format strings work just like any other string literal.This is implemented by copying and pasting a lot of logic from the corescanner. It would be a good idea to look into getting rid of plpgsql'sscanner entirely in favor of using the core scanner. However, that involvesmore change than I can justify making during beta --- in particular, the corescanner would have to become re-entrant.In passing, remove the kluge that made the plpgsql scanner emit T_FUNCTION orT_TRIGGER as a made-up first token. That presumably had some value once upona time, but now it's just useless complication for both the scanner and thegrammar.
1 parent7f2f798 commit3a624e9

File tree

8 files changed

+398
-236
lines changed

8 files changed

+398
-236
lines changed

‎doc/src/sgml/plpgsql.sgml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.139 2009/04/02 19:20:45 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.140 2009/04/19 18:52:56 tgl Exp $ -->
22

33
<chapter id="plpgsql">
44
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -220,10 +220,8 @@ END <optional> <replaceable>label</replaceable> </optional>;
220220
There are two types of comments in <application>PL/pgSQL</>. A double
221221
dash (<literal>--</literal>) starts a comment that extends to the end of
222222
the line. A <literal>/*</literal> starts a block comment that extends to
223-
the next occurrence of <literal>*/</literal>. Block comments cannot be
224-
nested, but double dash comments can be enclosed into a block comment and
225-
a double dash can hide the block comment delimiters <literal>/*</literal>
226-
and <literal>*/</literal>.
223+
the next occurrence of <literal>*/</literal>. Block comments nest,
224+
just as in ordinary SQL.
227225
</para>
228226

229227
<para>

‎src/pl/plpgsql/src/gram.y

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.121 2009/02/18 11:33:04 petere Exp $
12+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.122 2009/04/19 18:52:57 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -62,6 +62,8 @@ static PLpgSQL_row*make_scalar_list1(const char *initial_name,
6262
int lineno);
6363
staticvoidcheck_sql_expr(constchar *stmt);
6464
staticvoidplpgsql_sql_error_callback(void *arg);
65+
staticchar*parse_string_token(constchar *token);
66+
staticvoidplpgsql_string_error_callback(void *arg);
6567
staticchar*check_label(constchar *yytxt);
6668
staticvoidcheck_labels(constchar *start_label,
6769
constchar *end_label);
@@ -228,8 +230,6 @@ static List*read_raise_options(void);
228230
/*
229231
* Other tokens
230232
*/
231-
%tokenT_FUNCTION
232-
%tokenT_TRIGGER
233233
%tokenT_STRING
234234
%tokenT_NUMBER
235235
%tokenT_SCALAR/* a VAR, RECFIELD, or TRIGARG*/
@@ -244,13 +244,9 @@ static List*read_raise_options(void);
244244

245245
%%
246246

247-
pl_function:T_FUNCTIONcomp_optsectpl_blockopt_semi
247+
pl_function:comp_optsectpl_blockopt_semi
248248
{
249-
yylval.program = (PLpgSQL_stmt_block *)$3;
250-
}
251-
|T_TRIGGERcomp_optsectpl_blockopt_semi
252-
{
253-
yylval.program = (PLpgSQL_stmt_block *)$3;
249+
yylval.program = (PLpgSQL_stmt_block *)$2;
254250
}
255251
;
256252

@@ -1403,7 +1399,7 @@ stmt_raise: K_RAISE lno
14031399
if (tok == T_STRING)
14041400
{
14051401
/* old style message and parameters*/
1406-
new->message =plpgsql_get_string_value();
1402+
new->message =parse_string_token(yytext);
14071403
/*
14081404
* We expect either a semi-colon, which
14091405
* indicates no parameters, or a comma that
@@ -1435,7 +1431,7 @@ stmt_raise: K_RAISE lno
14351431

14361432
if (yylex() != T_STRING)
14371433
yyerror("syntax error");
1438-
sqlstatestr =plpgsql_get_string_value();
1434+
sqlstatestr =parse_string_token(yytext);
14391435

14401436
if (strlen(sqlstatestr) !=5)
14411437
yyerror("invalid SQLSTATE code");
@@ -1778,7 +1774,7 @@ proc_condition: opt_lblname
17781774
/* next token should be a string literal*/
17791775
if (yylex() != T_STRING)
17801776
yyerror("syntax error");
1781-
sqlstatestr =plpgsql_get_string_value();
1777+
sqlstatestr =parse_string_token(yytext);
17821778

17831779
if (strlen(sqlstatestr) !=5)
17841780
yyerror("invalid SQLSTATE code");
@@ -2738,6 +2734,49 @@ plpgsql_sql_error_callback(void *arg)
27382734
errposition(0);
27392735
}
27402736

2737+
/*
2738+
* Convert a string-literal token to the represented string value.
2739+
*
2740+
* To do this, we need to invoke the core lexer. To avoid confusion between
2741+
* the core bison/flex definitions and our own, the actual invocation is in
2742+
* pl_funcs.c. Here we are only concerned with setting up the right errcontext
2743+
* state, which is handled the same as in check_sql_expr().
2744+
*/
2745+
staticchar *
2746+
parse_string_token(constchar *token)
2747+
{
2748+
char *result;
2749+
ErrorContextCallback syntax_errcontext;
2750+
ErrorContextCallback *previous_errcontext;
2751+
2752+
/* See comments in check_sql_expr()*/
2753+
Assert(error_context_stack->callback == plpgsql_compile_error_callback);
2754+
2755+
previous_errcontext = error_context_stack;
2756+
syntax_errcontext.callback = plpgsql_string_error_callback;
2757+
syntax_errcontext.arg = (char *) token;
2758+
syntax_errcontext.previous = error_context_stack->previous;
2759+
error_context_stack = &syntax_errcontext;
2760+
2761+
result =plpgsql_parse_string_token(token);
2762+
2763+
/* Restore former ereport callback*/
2764+
error_context_stack = previous_errcontext;
2765+
2766+
return result;
2767+
}
2768+
2769+
staticvoid
2770+
plpgsql_string_error_callback(void *arg)
2771+
{
2772+
Assert(plpgsql_error_funcname);
2773+
2774+
errcontext("string literal in PL/PgSQL function\"%s\" near line %d",
2775+
plpgsql_error_funcname, plpgsql_error_lineno);
2776+
/* representing the string literal as internalquery seems overkill*/
2777+
errposition(0);
2778+
}
2779+
27412780
staticchar *
27422781
check_label(constchar *yytxt)
27432782
{

‎src/pl/plpgsql/src/pl_comp.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.134 2009/02/18 11:33:04 petere Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.135 2009/04/19 18:52:57 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -261,7 +261,7 @@ do_compile(FunctionCallInfo fcinfo,
261261
boolforValidator)
262262
{
263263
Form_pg_procprocStruct= (Form_pg_proc)GETSTRUCT(procTup);
264-
intfunctype=CALLED_AS_TRIGGER(fcinfo) ?T_TRIGGER :T_FUNCTION;
264+
boolis_trigger=CALLED_AS_TRIGGER(fcinfo);
265265
Datumprosrcdatum;
266266
boolisnull;
267267
char*proc_source;
@@ -293,7 +293,7 @@ do_compile(FunctionCallInfo fcinfo,
293293
if (isnull)
294294
elog(ERROR,"null prosrc");
295295
proc_source=TextDatumGetCString(prosrcdatum);
296-
plpgsql_scanner_init(proc_source,functype);
296+
plpgsql_scanner_init(proc_source);
297297

298298
plpgsql_error_funcname=pstrdup(NameStr(procStruct->proname));
299299
plpgsql_error_lineno=0;
@@ -359,13 +359,13 @@ do_compile(FunctionCallInfo fcinfo,
359359
function->fn_oid=fcinfo->flinfo->fn_oid;
360360
function->fn_xmin=HeapTupleHeaderGetXmin(procTup->t_data);
361361
function->fn_tid=procTup->t_self;
362-
function->fn_functype=functype;
362+
function->fn_is_trigger=is_trigger;
363363
function->fn_cxt=func_cxt;
364364
function->out_param_varno=-1;/* set up for no OUT param */
365365

366-
switch (functype)
366+
switch (is_trigger)
367367
{
368-
caseT_FUNCTION:
368+
casefalse:
369369

370370
/*
371371
* Fetch info about the procedure's parameters. Allocations aren't
@@ -564,7 +564,7 @@ do_compile(FunctionCallInfo fcinfo,
564564
ReleaseSysCache(typeTup);
565565
break;
566566

567-
caseT_TRIGGER:
567+
casetrue:
568568
/* Trigger procedure's return type is unknown yet */
569569
function->fn_rettype=InvalidOid;
570570
function->fn_retbyval= false;
@@ -645,7 +645,7 @@ do_compile(FunctionCallInfo fcinfo,
645645
break;
646646

647647
default:
648-
elog(ERROR,"unrecognized function typecode: %u",functype);
648+
elog(ERROR,"unrecognized function typecode: %d",(int)is_trigger);
649649
break;
650650
}
651651

@@ -790,7 +790,7 @@ plpgsql_parse_word(const char *word)
790790
* Recognize tg_argv when compiling triggers
791791
* (XXX this sucks, it should be a regular variable in the namestack)
792792
*/
793-
if (plpgsql_curr_compile->fn_functype==T_TRIGGER)
793+
if (plpgsql_curr_compile->fn_is_trigger)
794794
{
795795
if (strcmp(cp[0],"tg_argv")==0)
796796
{

‎src/pl/plpgsql/src/pl_funcs.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.76 2009/02/18 11:33:04 petere Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.77 2009/04/19 18:52:57 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -17,6 +17,8 @@
1717

1818
#include<ctype.h>
1919

20+
#include"parser/gramparse.h"
21+
#include"parser/gram.h"
2022
#include"parser/scansup.h"
2123

2224

@@ -459,6 +461,41 @@ plpgsql_convert_ident(const char *s, char **output, int numidents)
459461
}
460462

461463

464+
/*
465+
* plpgsql_parse_string_token - get the value represented by a string literal
466+
*
467+
* We do not make plpgsql's lexer produce the represented value, because
468+
* in many cases we don't need it. Instead this function is invoked when
469+
* we do need it. The input is the T_STRING token as identified by the lexer.
470+
*
471+
* The result is a palloc'd string.
472+
*
473+
* Note: this is called only from plpgsql's gram.y, but we can't just put it
474+
* there because including parser/gram.h there would cause confusion.
475+
*/
476+
char*
477+
plpgsql_parse_string_token(constchar*token)
478+
{
479+
intctoken;
480+
481+
/*
482+
* We use the core lexer to do the dirty work. Aside from getting the
483+
* right results for escape sequences and so on, this helps us produce
484+
* appropriate warnings for escape_string_warning etc.
485+
*/
486+
scanner_init(token);
487+
488+
ctoken=base_yylex();
489+
490+
if (ctoken!=SCONST)
491+
elog(ERROR,"unexpected result from base lexer: %d",ctoken);
492+
493+
scanner_finish();
494+
495+
returnbase_yylval.str;
496+
}
497+
498+
462499
/*
463500
* Statement type as a string, for use in error messages etc.
464501
*/

‎src/pl/plpgsql/src/plpgsql.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.110 2009/04/09 02:57:53 tgl Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.111 2009/04/19 18:52:57 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -650,7 +650,7 @@ typedef struct PLpgSQL_function
650650
Oidfn_oid;
651651
TransactionIdfn_xmin;
652652
ItemPointerDatafn_tid;
653-
intfn_functype;
653+
boolfn_is_trigger;
654654
PLpgSQL_func_hashkey*fn_hashkey;/* back-link to hashtable key */
655655
MemoryContextfn_cxt;
656656

@@ -880,6 +880,7 @@ extern void plpgsql_ns_rename(char *oldname, char *newname);
880880
* ----------
881881
*/
882882
externvoidplpgsql_convert_ident(constchar*s,char**output,intnumidents);
883+
externchar*plpgsql_parse_string_token(constchar*token);
883884
externconstchar*plpgsql_stmt_typename(PLpgSQL_stmt*stmt);
884885
externvoidplpgsql_dumptree(PLpgSQL_function*func);
885886

@@ -894,8 +895,7 @@ extern intplpgsql_yylex(void);
894895
externvoidplpgsql_push_back_token(inttoken);
895896
externvoidplpgsql_yyerror(constchar*message);
896897
externintplpgsql_scanner_lineno(void);
897-
externvoidplpgsql_scanner_init(constchar*str,intfunctype);
898+
externvoidplpgsql_scanner_init(constchar*str);
898899
externvoidplpgsql_scanner_finish(void);
899-
externchar*plpgsql_get_string_value(void);
900900

901901
#endif/* PLPGSQL_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp