Re: [BUGS] BUG #2171: Differences compiling plpgsql in ecpg and psql - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: [BUGS] BUG #2171: Differences compiling plpgsql in ecpg and psql |
Date | |
Msg-id | 200602030558.k135w2Q25207@candle.pha.pa.us Whole thread Raw |
Responses |
Re: [BUGS] BUG #2171: Differences compiling plpgsql in ecpg
Re: [BUGS] BUG #2171: Differences compiling plpgsql in ecpg and psql |
List | pgsql-patches |
Here is an updated patch. It fixes things in the places it should be fixed by handling \n at the time we double-quote, and double single quotes at the place we are building the $$ string. I am going to apply this to HEAD. It is a fix, but I am worried it might affect ecpg users who might have worked-around these problems and this might break their work-around. I am looking for opinions on applying this to back releases. --------------------------------------------------------------------------- Andrew Klosterman wrote: > On Wed, 1 Feb 2006, Bruce Momjian wrote: > > > > > I have researched your report, and you are right, there are two ecpg > > bugs here. First, dollar quoting uses single-quotes internally to do > > the quoting, but it does not double any single-quotes in the > > dollar-quoted string. > > > > Second, when a dollar quoted string or single-quoted string spans > > multiple lines, ecpg does not escape the newline that is part of the > > string. Some compilers will accept an unescaped newline in a string, > > while others will not: > > > > $ gcc -pedantic -c -g -Wall tst1.c > > tst1.c:5: warning: string constant runs past end of line > > > > It isn't standard so I think we need to replace newline in a string with > > "\n\". > > > > Attached is a patch which fixes both of these issues. This changes ecpg > > behavior so I am thinking this patch would only appear in 8.2. > > > > I am unclear if I fixed the \r case properly. > > > > --------------------------------------------------------------------------- > > > > andrew5@ece.cmu.edu wrote: > > > > > > The following bug has been logged online: > > > > > > Bug reference: 2171 > > > Logged by: > > > Email address: andrew5@ece.cmu.edu > > > PostgreSQL version: 8.1.2 > > > Operating system: Linux (Debian) > > > Description: Differences compiling plpgsql in ecpg and psql > > > Details: > > > > > > There appear to be parsing problems with ecpg. The following example > > > program shows code snippets that allow for the successful creation of a > > > function (CREATE FUNCTION) only using two different syntaxes: one when > > > entered through psql, and another when compiling with ecpg. > > > > > > The expectation (and hints from the documentation) indicate that the exact > > > same method of defining a function should succeed in both cases, but such is > > > not the case. > > > > > > Different quoting and line-wrap behavior is observed between psql and ecpg. > > > > > > (Thanks for the attention, I hope this is useful!) > > > > > > BEGIN CODE--------------- > > > /* This file is bug.pgc. */ > > > /* Compile as shown: > > > ecpg bug.pgc -o bug.c > > > gcc -c -g -std=c99 -I/usr/local/pgsql/include -L/usr/local/pgsql/lib > > > bug.c -o bug.o > > > gcc -I/usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg bug.o -o bug > > > */ > > > /* Run as: ./bug */ > > > #include <stdio.h> > > > #include <stdlib.h> > > > #include <string.h> > > > > > > int main(int argc, char* argv[]) { > > > > > > EXEC SQL CONNECT TO DEFAULT; > > > > > > EXEC SQL SET AUTOCOMMIT TO ON; > > > EXEC SQL WHENEVER SQLWARNING SQLPRINT; > > > EXEC SQL WHENEVER SQLERROR SQLPRINT; > > > > > > EXEC SQL CREATE TABLE My_Table ( Item1 int, Item2 text ); > > > > > > /* Documentation appears to indicate that only single quotes (') are > > > needed, but this will not ecpg-compile without double-single ('') > > > quotes. When entered through psql, only the single quotes (') > > > are needed. */ > > > /* doc/html/sql-syntax.html#SQL-SYNTAX-DOLLAR-QUOTING: "It is > > > particularly useful when representing string constants inside > > > other constants, as is often needed in procedural function > > > definitions." */ > > > /* doc/html/sql-createfunction.html: "Without dollar quoting, any > > > single quotes or backslashes in the function definition must be > > > escaped by doubling them." */ > > > > > > /* Documentation appears to indicate that the body of the funtion > > > can be extended across multiple lines in the input file (this > > > file) but it will not compile (ecpg) without keeping the function > > > body on one line. Multiple line input works through psql, but > > > not here.*/ > > > //bad ecpg,good psql: EXEC SQL CREATE FUNCTION My_Table_Check() RETURNS > > > trigger > > > //bad ecpg,good psql: AS $My_Table_Check$ > > > //bad ecpg,good psql: BEGIN RAISE NOTICE 'TG_NAME=%, TG WHEN=%', TG_NAME, > > > TG_WHEN; > > > //bad ecpg,good psql: RETURN NEW; > > > //bad ecpg,good psql: END; > > > //bad ecpg,good psql: $My_Table_Check$ > > > //bad ecpg,good psql: LANGUAGE 'plpgsql'; > > > EXEC SQL CREATE FUNCTION My_Table_Check() RETURNS trigger > > > AS $My_Table_Check$ BEGIN RAISE NOTICE ''TG_NAME=%, TG WHEN=%'', > > > TG_NAME, TG_WHEN; RETURN NEW; END; $My_Table_Check$ > > > LANGUAGE 'plpgsql'; > > > > > > EXEC SQL CREATE TRIGGER My_Table_Check_Trigger > > > BEFORE INSERT > > > ON My_Table > > > FOR EACH ROW > > > EXECUTE PROCEDURE My_Table_Check(); > > > > > > EXEC SQL INSERT INTO My_Table VALUES (1234, 'Some random text'); > > > EXEC SQL INSERT INTO My_Table VALUES (5678, 'The Quick Brown'); > > > > > > EXEC SQL DROP TRIGGER My_Table_Check_Trigger ON My_Table; > > > EXEC SQL DROP FUNCTION My_Table_Check(); > > > EXEC SQL DROP TABLE My_Table; > > > > > > EXEC SQL DISCONNECT ALL; > > > > > > return 0; > > > } > > > > > > END CODE------------------ > > > > > > ---------------------------(end of broadcast)--------------------------- > > > TIP 9: In versions below 8.0, the planner will ignore your desire to > > > choose an index scan if your joining column's datatypes do not > > > match > > > > > > > -- > > Bruce Momjian | http://candle.pha.pa.us > > pgman@candle.pha.pa.us | (610) 359-1001 > > + If your life is a hard drive, | 13 Roberts Road > > + Christ can be your backup. | Newtown Square, Pennsylvania 19073 > > > > > --Andrew J. Klosterman > andrew5@ece.cmu.edu > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: src/interfaces/ecpg/preproc/output.c =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/ecpg/preproc/output.c,v retrieving revision 1.12 diff -c -c -r1.12 output.c *** src/interfaces/ecpg/preproc/output.c 13 Oct 2004 01:25:13 -0000 1.12 --- src/interfaces/ecpg/preproc/output.c 3 Feb 2006 05:33:38 -0000 *************** *** 2,7 **** --- 2,9 ---- #include "extern.h" + static void ouput_escaped_str(char *cmd); + void output_line_number(void) { *************** *** 10,30 **** } void ! output_simple_statement(char *cmd) { ! int i, ! j = strlen(cmd);; ! ! /* output this char by char as we have to filter '\"' */ ! for (i = 0; i < j; i++) ! { ! if (cmd[i] != '"') ! fputc(cmd[i], yyout); ! else ! fputs("\\\"", yyout); ! } output_line_number(); ! free(cmd); } /* --- 12,22 ---- } void ! output_simple_statement(char *stmt) { ! ouput_escaped_str(stmt); output_line_number(); ! free(stmt); } /* *************** *** 106,125 **** void output_statement(char *stmt, int mode, char *con) { - int i, - j = strlen(stmt); - fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, \"", compat, force_indicator, con ? con : "NULL"); ! ! /* output this char by char as we have to filter '\"' */ ! for (i = 0; i < j; i++) ! { ! if (stmt[i] != '"') ! fputc(stmt[i], yyout); ! else ! fputs("\\\"", yyout); ! } ! fputs("\", ", yyout); /* dump variables to C file */ --- 98,105 ---- void output_statement(char *stmt, int mode, char *con) { fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, \"", compat, force_indicator, con ? con : "NULL"); ! ouput_escaped_str(stmt); fputs("\", ", yyout); /* dump variables to C file */ *************** *** 135,137 **** --- 115,135 ---- if (connection != NULL) free(connection); } + + + static void + ouput_escaped_str(char *str) + { + int i, len = strlen(str); + + /* output this char by char as we have to filter " and \n */ + for (i = 0; i < len; i++) + { + if (str[i] == '"') + fputs("\\\"", yyout); + else if (str[i] == '\n') + fputs("\\n\\\n", yyout); + else + fputc(str[i], yyout); + } + } Index: src/interfaces/ecpg/preproc/pgc.l =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v retrieving revision 1.140 diff -c -c -r1.140 pgc.l *** src/interfaces/ecpg/preproc/pgc.l 2 Feb 2006 03:51:41 -0000 1.140 --- src/interfaces/ecpg/preproc/pgc.l 3 Feb 2006 05:33:38 -0000 *************** *** 152,158 **** dolq_cont [A-Za-z\200-\377_0-9] dolqdelim \$({dolq_start}{dolq_cont}*)?\$ dolqfailed \${dolq_start}{dolq_cont}* ! dolqinside [^$]+ /* Double quote * Allows embedded spaces and other special characters into identifiers. --- 152,158 ---- dolq_cont [A-Za-z\200-\377_0-9] dolqdelim \$({dolq_start}{dolq_cont}*)?\$ dolqfailed \${dolq_start}{dolq_cont}* ! dolqinside [^$']+ /* Double quote * Allows embedded spaces and other special characters into identifiers. *************** *** 476,482 **** <xdolq>{dolqinside} { addlit(yytext, yyleng); } <xdolq>{dolqfailed} { addlit(yytext, yyleng); } <xdolq>. { ! /* This is only needed for $ inside the quoted text */ addlitchar(yytext[0]); } <xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); } --- 476,485 ---- <xdolq>{dolqinside} { addlit(yytext, yyleng); } <xdolq>{dolqfailed} { addlit(yytext, yyleng); } <xdolq>. { ! /* $$ is implemented as a single-quoted string, so double it? */ ! if (yytext[0] == '\'') ! addlitchar(yytext[0]); ! /* single quote or dollar sign */ addlitchar(yytext[0]); } <xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); }
pgsql-patches by date: