Attached is a proof-of-concept diff that makes the main SQL parser accept quoted strings in the style recently discussed ($Q$ ... $Q$). To complete the feature, we'd need to make the plpgsql parser do the same, update psql to understand this, update pg_dump to use this style of quoting for function bodies (and perhaps other things?), and update the documentation. The last is a nontrivial project all by itself. Anybody want to run with this football?
regards, tom lane *** src/backend/parser/scan.l.orig Sun Aug 3 23:00:44 2003 --- src/backend/parser/scan.l Sun Sep 14 01:38:55 2003 *************** *** 39,44 **** --- 39,46 ---- static int xcdepth = 0; /* depth of nesting in slash-star comments */ + static char *hqstart; /* current here-document start string */ + /* * literalbuf is used to accumulate literal values when multiple rules * are needed to parse a single literal. Call startlit to reset buffer *************** *** 95,100 **** --- 97,103 ---- * <xd> delimited identifiers (double-quoted identifiers) * <xh> hexadecimal numeric string * <xq> quoted strings + * <hq> here-document-style quoted strings */ %x xb *************** *** 102,107 **** --- 105,111 ---- %x xd %x xh %x xq + %x hq /* Bit string * It is tempting to scan the string for only those characters *************** *** 141,146 **** --- 145,157 ---- xqoctesc [\\][0-7]{1,3} xqcat {quote}{whitespace_with_newline}{quote} + /* Here-document-style quotes + * The quoted string starts with $letters$ and extends to the first occurrence + * of an identical string. There is *no* processing of the quoted text. + */ + hqdelim \$[A-Za-z]*\$ + hqinside [^$]+ + /* Double quote * Allows embedded spaces and other special characters into identifiers. */ *************** *** 387,392 **** --- 398,432 ---- } <xq><<EOF>> { yyerror("unterminated quoted string"); } + {hqdelim} { + token_start = yytext; + hqstart = pstrdup(yytext); + BEGIN(hq); + startlit(); + } + <hq>{hqdelim} { + if (strcmp(yytext, hqstart) == 0) + { + pfree(hqstart); + BEGIN(INITIAL); + yylval.str = litbufdup(); + return SCONST; + } + /* + * When we fail to match $...$ to hqstart, transfer + * the $... part to the output, but put back the final + * $ for rescanning. Consider $delim$...$junk$delim$ + */ + addlit(yytext, yyleng-1); + yyless(yyleng-1); + } + <hq>{hqinside} { + addlit(yytext, yyleng); + } + <hq>. { + addlitchar(yytext[0]); + } + <hq><<EOF>> { yyerror("unterminated special-quoted string"); } {xdstart} { token_start = yytext; ---------------------------(end of broadcast)--------------------------- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html