From 44cd434ec4a70d2dfbc460492fc0574d08440250 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 3 Aug 2020 09:46:12 -0400 Subject: [PATCH] Fix behavior of ecpg's "EXEC SQL elif name". This ought to work much like C's "#elif defined(name)"; but the code implemented it in a way equivalent to endif followed by ifdef, so that it didn't matter whether any previous branch of the IF construct had succeeded. Fix that; add some test cases covering elif and nested IFs; and improve the documentation, which also seemed a bit confused. AFAICS the code has been like this since the feature was added in 1999 (commit b57b0e044). So while it's surely wrong, there might be code out there relying on the current behavior. Hence, don't back-patch into stable branches. It seems all right to fix it in v13 though. Per report from Ashutosh Sharma. Reviewed by Ashutosh Sharma and Michael Meskes. Discussion: https://postgr.es/m/CAE9k0P=dQk9X0cU2tN49S7a9tv733-e1pVdpB1P-pWJ5PdTktg@mail.gmail.com --- doc/src/sgml/ecpg.sgml | 62 ++++++--- src/interfaces/ecpg/preproc/pgc.l | 128 ++++++++++++------ .../ecpg/test/expected/preproc-define.c | 79 ++++++----- .../ecpg/test/expected/preproc-define.stderr | 70 +++++----- src/interfaces/ecpg/test/preproc/define.pgc | 17 +++ 5 files changed, 228 insertions(+), 128 deletions(-) diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 106ae0984e..1f9d35eeb3 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -5695,7 +5695,7 @@ EXEC SQL UPDATE Tbl SET col = 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 conditionally: @@ -5705,7 +5705,7 @@ EXEC SQL UPDATE Tbl SET col = MYNUMBER; Checks a name and processes subsequent lines 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 = MYNUMBER; Checks a name and processes subsequent lines if - name has not been created with + name has not been defined via EXEC SQL define name. - - EXEC SQL else; - - - Starts processing an alternative section to a section introduced by - either EXEC SQL ifdef name or - EXEC SQL ifndef name. - - - - EXEC SQL elif name; - Checks name and starts an alternative section if - name has been created with EXEC SQL define - name. + Begins an optional alternative section after an + EXEC SQL ifdef name or + EXEC SQL ifndef name + directive. Any number of elif sections can appear. + 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 else; + + + Begins an optional, final alternative section after an + EXEC SQL ifdef name or + EXEC SQL ifndef name + directive. Subsequent lines will be processed if no previous section + of the same + ifdef/ifndef...endif + construct has been processed. @@ -5748,7 +5758,9 @@ EXEC SQL UPDATE Tbl SET col = 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 = 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/preproc/pgc.l index f6052798fd..466bbac6a7 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -79,13 +79,29 @@ struct _yy_buffer static char *old; +/* + * Vars for handling ifdef/elif/endif constructs. preproc_tos is the current + * 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 expanded). + * 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 another + * 'else' or 'elif' at this level is an error.) + * For IFs nested within an inactive branch, all branches always have active + * set to false, but saw_active and else_branch are maintained normally. + * 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 +1181,26 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return S_ANYTHING; } } -{exec_sql}{ifdef}{space}* { ifcond = true; BEGIN(xcond); } +{exec_sql}{ifdef}{space}* { + if (preproc_tos >= MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; + ifcond = true; + BEGIN(xcond); + } {informix_special}{ifdef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { + if (preproc_tos >= MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; ifcond = true; BEGIN(xcond); } @@ -1179,11 +1210,26 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return S_ANYTHING; } } -{exec_sql}{ifndef}{space}* { ifcond = false; BEGIN(xcond); } +{exec_sql}{ifndef}{space}* { + if (preproc_tos >= MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; + ifcond = false; + BEGIN(xcond); + } {informix_special}{ifndef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { + if (preproc_tos >= MAX_NESTED_IF-1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; ifcond = false; BEGIN(xcond); } @@ -1193,16 +1239,13 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return S_ANYTHING; } } -{exec_sql}{elif}{space}* { /* pop stack */ - if ( preproc_tos == 0 ) { +{exec_sql}{elif}{space}* { + if (preproc_tos == 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 = true; BEGIN(xcond); + ifcond = true; + BEGIN(xcond); } {informix_special}{elif}{space}* { /* are we simulating Informix? */ @@ -1210,11 +1253,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { if (preproc_tos == 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 = true; BEGIN(xcond); } @@ -1226,16 +1266,19 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } {exec_sql}{else}{space}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */ - if (stacked_if_value[preproc_tos].else_branch) + if ( preproc_tos == 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 = true; - stacked_if_value[preproc_tos].condition = - (stacked_if_value[preproc_tos-1].condition && - !stacked_if_value[preproc_tos].condition); + stacked_if_value[preproc_tos].active = + (stacked_if_value[preproc_tos-1].active && + !stacked_if_value[preproc_tos].saw_active); + stacked_if_value[preproc_tos].saw_active = true; - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1245,16 +1288,19 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ /* are we simulating Informix? */ if (INFORMIX_MODE) { - if (stacked_if_value[preproc_tos].else_branch) + if ( preproc_tos == 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 = true; - stacked_if_value[preproc_tos].condition = - (stacked_if_value[preproc_tos-1].condition && - !stacked_if_value[preproc_tos].condition); + stacked_if_value[preproc_tos].active = + (stacked_if_value[preproc_tos-1].active && + !stacked_if_value[preproc_tos].saw_active); + stacked_if_value[preproc_tos].saw_active = true; - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1272,7 +1318,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{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 +1332,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{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 +1347,10 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ {other} { /* ignore */ } {identifier}{space}*";" { - if (preproc_tos >= 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 +1368,15 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ defptr = defptr->next) /* skip */ ; - preproc_tos++; - stacked_if_value[preproc_tos].else_branch = false; - stacked_if_value[preproc_tos].condition = - (defptr ? ifcond : !ifcond) && stacked_if_value[preproc_tos-1].condition; + this_active = (defptr ? ifcond : !ifcond); + stacked_if_value[preproc_tos].active = + (stacked_if_value[preproc_tos-1].active && + !stacked_if_value[preproc_tos].saw_active && + this_active); + stacked_if_value[preproc_tos].saw_active |= this_active; } - if (stacked_if_value[preproc_tos].condition) + if (stacked_if_value[preproc_tos].active) BEGIN(C); else BEGIN(xskip); @@ -1442,10 +1488,12 @@ lex_init(void) parenths_open = 0; current_function = NULL; - preproc_tos = 0; yylineno = 1; - ifcond = true; - stacked_if_value[preproc_tos].condition = ifcond; + + /* initialize state for if/else/endif */ + preproc_tos = 0; + stacked_if_value[preproc_tos].active = true; + stacked_if_value[preproc_tos].saw_active = true; stacked_if_value[preproc_tos].else_branch = false; /* initialize literal buffer to a reasonable but expansible size */ diff --git a/src/interfaces/ecpg/test/expected/preproc-define.c b/src/interfaces/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 ( name 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 ( name , amount , letter ) values ( 'false' , 1 , 'f' )", ECPGt_EOIT, ECPGt_EORT); -#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 ( name , 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", ECPGt_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=0, j=sqlca.sqlerrd[2]; i port [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_regression" +[NO_PID]: ECPGtrans on line 54: action "commit"; connection "ecpg1_regression" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 39: query: insert into Test ( name , amount , letter ) values ( 'false' , 1 , 'f' ); with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 56: query: insert into Test ( name , amount , letter ) values ( 'false' , 1 , 'f' ); with 0 parameter(s) on connection 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 , amount , letter ) values ( 'true' , 2 , 't' ); with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 40: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 40: OK: INSERT 0 1 -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 41: action "commit"; connection "ecpg1_regression" -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 43: query: select * from test; with 0 parameter(s) on connection ecpg1_regression -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 43: using PQexec -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 43: correctly got 2 tuples with 3 fields -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: false offset: -1; array: no -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: RESULT: true offset: -1; array: no -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: 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]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 43: 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]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 57: query: drop table test; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 57: query: insert into test ( name , amount , letter ) values ( 'true' , 2 , 't' ); with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 57: 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 57: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGtrans on line 58: action "commit"; connection "ecpg1_regression" [NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 60: query: select * from test; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 60: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 60: correctly got 2 tuples with 3 fields +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 60: RESULT: false offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 60: RESULT: true offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[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 60: RESULT: 2 offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[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 60: RESULT: t offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 74: query: drop table test; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 74: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 74: OK: DROP TABLE +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGtrans on line 75: action "commit"; connection "ecpg1_regression" +[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;