Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k1sbp-0001nH-Sx for pgsql-interfaces@arkaria.postgresql.org; Sat, 01 Aug 2020 14:35:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1k1sbo-0007As-Rp for pgsql-interfaces@arkaria.postgresql.org; Sat, 01 Aug 2020 14:35:36 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k1sbo-0007Al-J3 for pgsql-interfaces@lists.postgresql.org; Sat, 01 Aug 2020 14:35:36 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k1sbm-0004XP-0N; Sat, 01 Aug 2020 14:35:36 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 071EZVOX1925405; Sat, 1 Aug 2020 10:35:31 -0400 From: Tom Lane To: Ashutosh Sharma cc: pgsql-interfaces@postgresql.org, Michael Meskes Subject: Re: ecpg: issue related to preprocessor directives In-reply-to: <1853327.1596240391@sss.pgh.pa.us> References: <1853327.1596240391@sss.pgh.pa.us> Comments: In-reply-to Tom Lane message dated "Fri, 31 Jul 2020 20:06:31 -0400" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <1925362.1596292470.0@sss.pgh.pa.us> Date: Sat, 01 Aug 2020 10:35:31 -0400 Message-ID: <1925404.1596292531@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1925362.1596292470.1@sss.pgh.pa.us> I wrote: > Looking at pgc.l, it seems that 'elif' is treated as though it were > 'endif' followed by 'ifdef', which of course completely loses the > expected property that a previous successful branch would keep the > elif branch from being expanded. > While this doesn't look terribly hard to fix, I'm a little disturbed > by the fact that the existing semantics seem to date back to 1999 > (b57b0e044). We're probably risking breaking existing app code if > we change it. I think we *should* change it, of course, but I'm kind > of inclined not to back-patch. Here's a proposed patch, which also clarifies the documentation, which seemed a bit confused/misleading to me. As stated, I'm not sure it's wise to back-patch this aggressively ... but maybe it'd be okay to squeeze it into v13? regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="fix-ecpg-elif-1.patch"; charset="us-ascii" Content-ID: <1925362.1596292470.2@sss.pgh.pa.us> Content-Description: fix-ecpg-elif-1.patch Content-Transfer-Encoding: quoted-printable diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 106ae0984e..ecdc417d0b 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -5695,7 +5695,7 @@ EXEC SQL UPDATE Tbl SET col =3D MYNUMBER; = - ifdef, ifndef, else, elif, and endif Directives + ifdef, ifndef, elif, else, and endif Directives You can use the following directives to compile code sections conditio= nally: = @@ -5705,7 +5705,7 @@ EXEC SQL UPDATE Tbl SET col =3D MYNUMBER; Checks a name and processes subsequent l= ines if - name has been created with EXEC= SQL define + name has been defined via EXEC = SQL define name. @@ -5716,30 +5716,40 @@ EXEC SQL UPDATE Tbl SET col =3D MYNUMBER; Checks a name and processes subsequent l= ines if - name has not been c= reated with + name has not been d= efined via EXEC SQL define name. = - EXEC SQL else; + EXEC SQL elif name; - Starts processing an alternative section to a section introduced by - either EXEC SQL ifdef name or - EXEC SQL ifndef name. + Begins an alternative section after an + EXEC SQL ifdef name o= r + EXEC SQL ifndef name + directive. Any number of elif sections can appe= ar. + Lines following an elif will be processed + if name has been + defined and no previous section of the same + ifdef/ifndef...endif= + construct has been processed. = - EXEC SQL elif name; + EXEC SQL else; - Checks name and starts an alternative se= ction if - name has been created with EXEC= SQL define - name. + Begins an optional, final alternative section after an + EXEC SQL ifdef name o= r + EXEC SQL ifndef name + directive. Subsequent lines will be processed if no previous secti= on + of the same + ifdef/ifndef...endif= + construct has been processed. @@ -5748,7 +5758,9 @@ EXEC SQL UPDATE Tbl SET col =3D MYNUMBER; EXEC SQL endif; - Ends an alternative section. + Ends an + ifdef/ifndef...endif= + construct. Subsequent lines are processed normally. @@ -5756,14 +5768,20 @@ EXEC SQL UPDATE Tbl SET col =3D MYNUMBER; = - Example: + ifdef/ifndef...endif + constructs can be nested, up to 127 levels deep. + + + + This example will compile exactly one of the three SET + TIMEZONE commands: -EXEC SQL ifndef TZVAR; -EXEC SQL SET TIMEZONE TO 'GMT'; +EXEC SQL ifdef TZVAR; +EXEC SQL SET TIMEZONE TO TZVAR; EXEC SQL elif TZNAME; EXEC SQL SET TIMEZONE TO TZNAME; EXEC SQL else; -EXEC SQL SET TIMEZONE TO TZVAR; +EXEC SQL SET TIMEZONE TO 'GMT'; EXEC SQL endif; diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/prepr= oc/pgc.l index f6052798fd..514ea27a80 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -79,13 +79,27 @@ struct _yy_buffer = static char *old; = +/* + * Vars for handling ifdef/elif/endif constructs. preproc_tos is the cur= rent + * nesting depth of such constructs, and stacked_if_value[preproc_tos] is= the + * state for the innermost level. (For convenience, stacked_if_value[0] = is + * initialized as though we are in the active branch of some outermost if= .) + * The active field is true if the current branch is active (being expand= ed). + * The saw_active field is true if we have found any successful branch, + * so that all subsequent branches of this level should be skipped. + * The else_branch field is true if we've found an 'else' (so that anothe= r + * 'else' or 'elif' at this level is an error.) + * ifcond is valid only while evaluating an if-condition; it's true if we + * are doing ifdef, false if ifndef. + */ #define MAX_NESTED_IF 128 static short preproc_tos; -static short ifcond; +static bool ifcond; static struct _if_value { - short condition; - short else_branch; + bool active; + bool saw_active; + bool else_branch; } stacked_if_value[MAX_NESTED_IF]; = %} @@ -1165,11 +1179,26 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ return S_ANYTHING; } } -{exec_sql}{ifdef}{space}* { ifcond =3D true; BEGIN(xcond); } +{exec_sql}{ifdef}{space}* { + if (preproc_tos >=3D MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions")= ; + preproc_tos++; + stacked_if_value[preproc_tos].active =3D false; + stacked_if_value[preproc_tos].saw_active =3D false; + stacked_if_value[preproc_tos].else_branch =3D false; + ifcond =3D true; + BEGIN(xcond); + } {informix_special}{ifdef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { + if (preproc_tos >=3D MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"= ); + preproc_tos++; + stacked_if_value[preproc_tos].active =3D false; + stacked_if_value[preproc_tos].saw_active =3D false; + stacked_if_value[preproc_tos].else_branch =3D false; ifcond =3D true; BEGIN(xcond); } @@ -1179,11 +1208,26 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ return S_ANYTHING; } } -{exec_sql}{ifndef}{space}* { ifcond =3D false; BEGIN(xcond); } +{exec_sql}{ifndef}{space}* { + if (preproc_tos >=3D MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions")= ; + preproc_tos++; + stacked_if_value[preproc_tos].active =3D false; + stacked_if_value[preproc_tos].saw_active =3D false; + stacked_if_value[preproc_tos].else_branch =3D false; + ifcond =3D false; + BEGIN(xcond); + } {informix_special}{ifndef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { + if (preproc_tos >=3D MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"= ); + preproc_tos++; + stacked_if_value[preproc_tos].active =3D false; + stacked_if_value[preproc_tos].saw_active =3D false; + stacked_if_value[preproc_tos].else_branch =3D false; ifcond =3D false; BEGIN(xcond); } @@ -1193,16 +1237,13 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ return S_ANYTHING; } } -{exec_sql}{elif}{space}* { /* pop stack */ - if ( preproc_tos =3D=3D 0 ) { +{exec_sql}{elif}{space}* { + if (preproc_tos =3D=3D 0) mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC= SQL IFNDEF\""); - } - else if ( stacked_if_value[preproc_tos].else_branch ) + if (stacked_if_value[preproc_tos].else_branch) mmfatal(PARSE_ERROR, "missing \"EXEC SQL ENDIF;\""); - else - preproc_tos--; - - ifcond =3D true; BEGIN(xcond); + ifcond =3D true; + BEGIN(xcond); } {informix_special}{elif}{space}* { /* are we simulating Informix? */ @@ -1210,11 +1251,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifn= def}|{import})((\/\*[^*/]*\*+ { if (preproc_tos =3D=3D 0) mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC= SQL IFNDEF\""); - else if (stacked_if_value[preproc_tos].else_branch) + if (stacked_if_value[preproc_tos].else_branch) mmfatal(PARSE_ERROR, "missing \"EXEC SQL ENDIF;\""); - else - preproc_tos--; - ifcond =3D true; BEGIN(xcond); } @@ -1226,16 +1264,19 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ } = {exec_sql}{else}{space}*";" { /* only exec sql endif pops the st= ack, so take care of duplicated 'else' */ - if (stacked_if_value[preproc_tos].else_branch) + if ( preproc_tos =3D=3D 0 ) + mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC = SQL IFNDEF\""); + else if (stacked_if_value[preproc_tos].else_branch) mmfatal(PARSE_ERROR, "more than one EXEC SQL ELSE"); else { stacked_if_value[preproc_tos].else_branch =3D true; - stacked_if_value[preproc_tos].condition =3D - (stacked_if_value[preproc_tos-1].condition && - !stacked_if_value[preproc_tos].condition); + stacked_if_value[preproc_tos].active =3D + (stacked_if_value[preproc_tos-1].active && + !stacked_if_value[preproc_tos].saw_active); + stacked_if_value[preproc_tos].saw_active =3D true; = - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1245,16 +1286,19 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ /* are we simulating Informix? */ if (INFORMIX_MODE) { - if (stacked_if_value[preproc_tos].else_branch) + if ( preproc_tos =3D=3D 0 ) + mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC= SQL IFNDEF\""); + else if (stacked_if_value[preproc_tos].else_branch) mmfatal(PARSE_ERROR, "more than one EXEC SQL ELSE"); else { stacked_if_value[preproc_tos].else_branch =3D true; - stacked_if_value[preproc_tos].condition =3D - (stacked_if_value[preproc_tos-1].condition && - !stacked_if_value[preproc_tos].condition); + stacked_if_value[preproc_tos].active =3D + (stacked_if_value[preproc_tos-1].active && + !stacked_if_value[preproc_tos].saw_active); + stacked_if_value[preproc_tos].saw_active =3D true; = - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1272,7 +1316,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifnd= ef}|{import})((\/\*[^*/]*\*+ else preproc_tos--; = - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1286,7 +1330,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifnd= ef}|{import})((\/\*[^*/]*\*+ else preproc_tos--; = - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1301,12 +1345,10 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ {other} { /* ignore */ } = {identifier}{space}*";" { - if (preproc_tos >=3D MAX_NESTED_IF-1) - mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); - else { struct _defines *defptr; unsigned int i; + bool this_active; = /* * Skip the ";" and trailing whitespace. Note that yytext @@ -1324,13 +1366,15 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{if= ndef}|{import})((\/\*[^*/]*\*+ defptr =3D defptr->next) /* skip */ ; = - preproc_tos++; - stacked_if_value[preproc_tos].else_branch =3D false; - stacked_if_value[preproc_tos].condition =3D - (defptr ? ifcond : !ifcond) && stacked_if_value[preproc_tos-1].cond= ition; + this_active =3D (defptr ? ifcond : !ifcond); + stacked_if_value[preproc_tos].active =3D + (stacked_if_value[preproc_tos-1].active && + !stacked_if_value[preproc_tos].saw_active && + this_active); + stacked_if_value[preproc_tos].saw_active |=3D this_active; } = - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1442,10 +1486,12 @@ lex_init(void) parenths_open =3D 0; current_function =3D NULL; = - preproc_tos =3D 0; yylineno =3D 1; - ifcond =3D true; - stacked_if_value[preproc_tos].condition =3D ifcond; + + /* initialize state for if/else/endif */ + preproc_tos =3D 0; + stacked_if_value[preproc_tos].active =3D true; + stacked_if_value[preproc_tos].saw_active =3D true; stacked_if_value[preproc_tos].else_branch =3D false; = /* initialize literal buffer to a reasonable but expansible size */ diff --git a/src/interfaces/ecpg/test/expected/preproc-define.c b/src/inte= rfaces/ecpg/test/expected/preproc-define.c index bde15b74a0..0256609b1f 100644 --- a/src/interfaces/ecpg/test/expected/preproc-define.c +++ b/src/interfaces/ecpg/test/expected/preproc-define.c @@ -40,73 +40,90 @@ main(void) { /* exec sql begin declare section */ = + typedef char string [ 8 ]; = -#line 21 "define.pgc" +#line 22 "define.pgc" = = = - = = -#line 22 "define.pgc" + = + + = + + + + = + + = + = + = + = + + = + + + +#line 23 "define.pgc" intarray amount ; = -#line 23 "define.pgc" +#line 24 "define.pgc" char name [ 6 ] [ 8 ] ; = -#line 24 "define.pgc" +#line 37 "define.pgc" char letter [ 6 ] [ 1 ] ; = #if 0 = -#line 26 "define.pgc" +#line 39 "define.pgc" int not_used ; = #endif /* exec sql end declare section */ -#line 29 "define.pgc" +#line 46 "define.pgc" = int i,j; = ECPGdebug(1, stderr); = { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); = -#line 34 "define.pgc" +#line 51 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 34 "define.pgc" +#line 51 "define.pgc" = = { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test ( na= me char ( 8 ) , amount int , letter char ( 1 ) )", ECPGt_EOIT, ECPGt_EORT)= ; -#line 36 "define.pgc" +#line 53 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 36 "define.pgc" +#line 53 "define.pgc" = { ECPGtrans(__LINE__, NULL, "commit"); -#line 37 "define.pgc" +#line 54 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 37 "define.pgc" +#line 54 "define.pgc" = = { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into Test ( nam= e , amount , letter ) values ( 'false' , 1 , 'f' )", ECPGt_EOIT, ECPGt_EOR= T); -#line 39 "define.pgc" +#line 56 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 39 "define.pgc" +#line 56 "define.pgc" = { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test ( nam= e , amount , letter ) values ( 'true' , 2 , 't' )", ECPGt_EOIT, ECPGt_EORT= ); -#line 40 "define.pgc" +#line 57 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 40 "define.pgc" +#line 57 "define.pgc" = { ECPGtrans(__LINE__, NULL, "commit"); -#line 41 "define.pgc" +#line 58 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 41 "define.pgc" +#line 58 "define.pgc" = = { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select * from test", E= CPGt_EOIT, = @@ -116,10 +133,10 @@ if (sqlca.sqlcode < 0) sqlprint();} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, = ECPGt_char,(letter),(long)1,(long)6,(1)*sizeof(char), = ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 43 "define.pgc" +#line 60 "define.pgc" = if (sqlca.sqlcode < 0) sqlprint();} -#line 43 "define.pgc" +#line 60 "define.pgc" = = for (i=3D0, j=3Dsqlca.sqlerrd[2]; i por= t = [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 36: query: create table test ( name char (= 8 ) , amount int , letter char ( 1 ) ); with 0 parameter(s) on connection= ecpg1_regression +[NO_PID]: ecpg_execute on line 53: query: create table test ( name char (= 8 ) , amount int , letter char ( 1 ) ); with 0 parameter(s) on connection= ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 36: using PQexec +[NO_PID]: ecpg_execute on line 53: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 36: OK: CREATE TABLE +[NO_PID]: ecpg_process_output on line 53: OK: CREATE TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 37: action "commit"; connection "ecpg1_regres= sion" +[NO_PID]: ECPGtrans on line 54: action "commit"; connection "ecpg1_regres= sion" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 39: query: insert into Test ( name , amoun= t , letter ) values ( 'false' , 1 , 'f' ); with 0 parameter(s) on connecti= on ecpg1_regression +[NO_PID]: ecpg_execute on line 56: query: insert into Test ( name , amoun= t , letter ) values ( 'false' , 1 , 'f' ); with 0 parameter(s) on connecti= on ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 39: using PQexec +[NO_PID]: ecpg_execute on line 56: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 39: OK: INSERT 0 1 +[NO_PID]: ecpg_process_output on line 56: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 40: query: insert into test ( name , amoun= t , letter ) values ( 'true' , 2 , 't' ); with 0 parameter(s) on connectio= n ecpg1_regression +[NO_PID]: ecpg_execute on line 57: query: insert into test ( name , amoun= t , letter ) values ( 'true' , 2 , 't' ); with 0 parameter(s) on connectio= n ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 40: using PQexec +[NO_PID]: ecpg_execute on line 57: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 40: OK: INSERT 0 1 +[NO_PID]: ecpg_process_output on line 57: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 41: action "commit"; connection "ecpg1_regres= sion" +[NO_PID]: ECPGtrans on line 58: action "commit"; connection "ecpg1_regres= sion" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 43: query: select * from test; with 0 para= meter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 60: query: select * from test; with 0 para= meter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 43: using PQexec +[NO_PID]: ecpg_execute on line 60: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 43: correctly got 2 tuples with 3 f= ields +[NO_PID]: ecpg_process_output on line 60: correctly got 2 tuples with 3 f= ields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: false offset: -1; array: n= o +[NO_PID]: ecpg_get_data on line 60: RESULT: false offset: -1; array: n= o [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: true offset: -1; array: n= o +[NO_PID]: ecpg_get_data on line 60: RESULT: true offset: -1; array: n= o [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: 1 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 60: RESULT: 1 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: 2 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 60: RESULT: 2 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: f offset: -1; array: no +[NO_PID]: ecpg_get_data on line 60: RESULT: f offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: t offset: -1; array: no +[NO_PID]: ecpg_get_data on line 60: RESULT: t offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 57: query: drop table test; with 0 paramet= er(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 74: query: drop table test; with 0 paramet= er(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 57: using PQexec +[NO_PID]: ecpg_execute on line 74: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 57: OK: DROP TABLE +[NO_PID]: ecpg_process_output on line 74: OK: DROP TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 58: action "commit"; connection "ecpg1_regres= sion" +[NO_PID]: ECPGtrans on line 75: action "commit"; connection "ecpg1_regres= sion" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection ecpg1_regression closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/preproc/define.pgc b/src/interfaces/= ecpg/test/preproc/define.pgc index 0d07ebfe63..d360da7ece 100644 --- a/src/interfaces/ecpg/test/preproc/define.pgc +++ b/src/interfaces/ecpg/test/preproc/define.pgc @@ -17,15 +17,32 @@ int main(void) { exec sql begin declare section; + exec sql ifdef NAMELEN; typedef char string[NAMELEN]; intarray amount; char name[AMOUNT][NAMELEN]; +exec sql elif AMOUNT; + should not get here; +exec sql else; + should not get here either; +exec sql endif; + +exec sql ifndef NAMELEN; + should not get here; +exec sql elif AMOUNT; + exec sql ifdef NOSUCHNAME; + should not get here; + exec sql else; char letter[AMOUNT][1]; #if 0 int not_used; #endif + exec sql endif; +exec sql elif AMOUNT; + should not get here; exec sql endif; + exec sql end declare section; int i,j; = ------- =_aaaaaaaaaa0--