dollar quoting for plpgsql - Mailing list pgsql-patches

From Andrew Dunstan
Subject dollar quoting for plpgsql
Date
Msg-id 403CCF67.5080107@dunslane.net
Whole thread Raw
In response to Re: dollar quoting with flex  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: dollar quoting for plpgsql  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
Tom Lane wrote:

>
>
>I think plpgsql's lexer also needs to be taught about dollar-quoting.
>
>
>
>

The attached patch appears to do the trick:


floobl=# create or replace function testme() returns text language
plpgsql as $$
floobl$# begin return $foo$a'\b$bar$foo$; end;
floobl$# $$;
CREATE FUNCTION
floobl=# select testme();
  testme
----------
 a'\b$bar
(1 row)

floobl=#



cheers

andrew
Index: src/pl/plpgsql/src/scan.l
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/pl/plpgsql/src/scan.l,v
retrieving revision 1.31
diff -c -r1.31 scan.l
*** src/pl/plpgsql/src/scan.l    24 Feb 2004 22:06:32 -0000    1.31
--- src/pl/plpgsql/src/scan.l    25 Feb 2004 16:32:28 -0000
***************
*** 57,62 ****
--- 57,63 ----
  static bool have_lookahead_token;
  static const char *cur_line_start;
  static int    cur_line_num;
+ static char    *dolqstart;      /* current $foo$ quote start string */

  int    plpgsql_SpaceScanned = 0;
  %}
***************
*** 70,76 ****
  %option case-insensitive


! %x    IN_STRING IN_COMMENT

  digit            [0-9]
  ident_start        [A-Za-z\200-\377_]
--- 71,77 ----
  %option case-insensitive


! %x    IN_STRING IN_COMMENT IN_DOLLARQUOTE

  digit            [0-9]
  ident_start        [A-Za-z\200-\377_]
***************
*** 84,89 ****
--- 85,98 ----

  space            [ \t\n\r\f]

+ /* $foo$ style quotes ("dollar quoting")
+  * copied stright from the backend SQL parser
+  */
+ dolq_start        [A-Za-z\200-\377_]
+ dolq_cont        [A-Za-z\200-\377_0-9]
+ dolqdelim        \$({dolq_start}{dolq_cont}*)?\$
+ dolqinside        [^$]+
+
  %%
      /* ----------
       * Local variables in scanner to remember where
***************
*** 288,293 ****
--- 297,336 ----
                          (errcode(ERRCODE_DATATYPE_MISMATCH),
                           errmsg("unterminated string")));
              }
+
+ {dolqdelim}        {
+               start_lineno = plpgsql_scanner_lineno();
+               start_charpos = yytext;
+               dolqstart = pstrdup(yytext);
+               BEGIN(IN_DOLLARQUOTE);
+                 }
+ <IN_DOLLARQUOTE>{dolqdelim} {
+                     if (strcmp(yytext, dolqstart) == 0)
+                     {
+                         pfree(dolqstart);
+                         yyleng -= (yytext - start_charpos);
+                         yytext = start_charpos;
+                         BEGIN INITIAL;
+                         return T_STRING;
+                     }
+                     else
+                     {
+                         /*
+                          * When we fail to match $...$ to dolqstart, transfer
+                          * the $... part to the output, but put back the final
+                          * $ for rescanning.  Consider $delim$...$junk$delim$
+                          */
+                         yyless(yyleng-1);
+                     }
+                 }
+ <IN_DOLLARQUOTE>{dolqinside} { }
+ <IN_DOLLARQUOTE>.    { /* needed for $ inside the quoted text */ }
+ <IN_DOLLARQUOTE><<EOF>>    {
+                 plpgsql_error_lineno = start_lineno;
+                 ereport(ERROR,
+                         (errcode(ERRCODE_DATATYPE_MISMATCH),
+                          errmsg("unterminated dollar quoted string")));
+                   }

      /* ----------
       * Any unmatched character is returned as is

pgsql-patches by date:

Previous
From: L J Bayuk
Date:
Subject: 1-line fix to port/thread.c for compiling libpq with Borland C
Next
From: Tom Lane
Date:
Subject: Re: dollar quoting for plpgsql