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
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
