Implement DO CONTINUE action for ECPG WHENEVER statement.
authorMichael Meskes <[email protected]>
Fri, 25 Aug 2017 13:15:03 +0000 (15:15 +0200)
committerMichael Meskes <[email protected]>
Fri, 25 Aug 2017 13:17:29 +0000 (15:17 +0200)
Author: Vinayak Pokale
Reviewed-By: Masahiko Sawada
doc/src/sgml/ecpg.sgml
src/interfaces/ecpg/preproc/ecpg.trailer
src/interfaces/ecpg/preproc/output.c
src/interfaces/ecpg/test/ecpg_schedule
src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.c [new file with mode: 0644]
src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.stderr [new file with mode: 0644]
src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.stdout [new file with mode: 0644]
src/interfaces/ecpg/test/preproc/Makefile
src/interfaces/ecpg/test/preproc/whenever_do_continue.pgc [new file with mode: 0644]

index f13a0e999f259a92853cbd704d9859ac79801b83..3cb4001cc0cf70d2fae48beb31d951ce2c6f93da 100644 (file)
@@ -4762,6 +4762,17 @@ EXEC SQL WHENEVER <replaceable>condition</replaceable> <replaceable>action</repl
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><literal>DO CONTINUE</literal></term>
+      <listitem>
+       <para>
+        Execute the C statement <literal>continue</literal>.  This should
+        only be used in loops statements.  if executed, will cause the flow 
+        of control to return to the top of the loop.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><literal>CALL <replaceable>name</replaceable> (<replaceable>args</replaceable>)</literal></term>
       <term><literal>DO <replaceable>name</replaceable> (<replaceable>args</replaceable>)</literal></term>
@@ -7799,6 +7810,7 @@ WHENEVER { NOT FOUND | SQLERROR | SQLWARNING } <replaceable class="PARAMETER">ac
 <programlisting>
 EXEC SQL WHENEVER NOT FOUND CONTINUE;
 EXEC SQL WHENEVER NOT FOUND DO BREAK;
+EXEC SQL WHENEVER NOT FOUND DO CONTINUE;
 EXEC SQL WHENEVER SQLWARNING SQLPRINT;
 EXEC SQL WHENEVER SQLWARNING DO warn();
 EXEC SQL WHENEVER SQLERROR sqlprint;
index d273070dabff24ca28f4fc77b9a10a2ad25df0ed..f60a62099d4613cfd94619739b2daf162170af73 100644 (file)
@@ -1454,6 +1454,12 @@ action : CONTINUE_P
            $<action>$.command = NULL;
            $<action>$.str = mm_strdup("break");
        }
+       | DO CONTINUE_P
+       {
+           $<action>$.code = W_CONTINUE;
+           $<action>$.command = NULL;
+           $<action>$.str = mm_strdup("continue");
+       }
        | SQL_CALL name '(' c_args ')'
        {
            $<action>$.code = W_DO;
index 0479c93c99149baceb6bb5cd6e08f3de9408def4..a55bf2b06a781286098e6f42c2f98650033d6e11 100644 (file)
@@ -51,6 +51,9 @@ print_action(struct when *w)
        case W_BREAK:
            fprintf(base_yyout, "break;");
            break;
+       case W_CONTINUE:
+           fprintf(base_yyout, "continue;");
+           break;
        default:
            fprintf(base_yyout, "{/* %d not implemented yet */}", w->code);
            break;
index c3ec125c36fdc0298c4b23efe4de884cab98d406..cff4eebfde4ef9859036bdcfef82575cd83a39e0 100644 (file)
@@ -28,6 +28,7 @@ test: preproc/type
 test: preproc/variable
 test: preproc/outofscope
 test: preproc/whenever
+test: preproc/whenever_do_continue
 test: sql/array
 test: sql/binary
 test: sql/code100
diff --git a/src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.c b/src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.c
new file mode 100644 (file)
index 0000000..2e95581
--- /dev/null
@@ -0,0 +1,161 @@
+/* Processed by ecpg (regression mode) */
+/* These include files are added by the preprocessor */
+#include <ecpglib.h>
+#include <ecpgerrno.h>
+#include <sqlca.h>
+/* End of automatic include section */
+#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+#line 1 "whenever_do_continue.pgc"
+#include <stdlib.h>
+
+
+#line 1 "regression.h"
+
+
+
+
+
+
+#line 3 "whenever_do_continue.pgc"
+
+
+/* exec sql whenever sqlerror  sqlprint ; */
+#line 5 "whenever_do_continue.pgc"
+
+
+int main(void)
+{
+   /* exec sql begin declare section */
+   
+   
+        
+        
+        
+    
+
+    
+   
+#line 15 "whenever_do_continue.pgc"
+ struct { 
+#line 12 "whenever_do_continue.pgc"
+ char ename [ 12 ] ;
+#line 13 "whenever_do_continue.pgc"
+ float sal ;
+#line 14 "whenever_do_continue.pgc"
+ float comm ;
+ } emp ;
+#line 17 "whenever_do_continue.pgc"
+ char msg [ 128 ] ;
+/* exec sql end declare section */
+#line 18 "whenever_do_continue.pgc"
+
+
+   ECPGdebug(1, stderr);
+
+   strcpy(msg, "connect");
+   { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); 
+#line 23 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 23 "whenever_do_continue.pgc"
+
+
+   strcpy(msg, "create");
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table emp ( ename varchar , sal double precision , comm double precision )", ECPGt_EOIT, ECPGt_EORT);
+#line 26 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 26 "whenever_do_continue.pgc"
+
+
+   strcpy(msg, "insert");
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into emp values ( 'Ram' , 111100 , 21 )", ECPGt_EOIT, ECPGt_EORT);
+#line 29 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 29 "whenever_do_continue.pgc"
+
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into emp values ( 'aryan' , 11110 , null )", ECPGt_EOIT, ECPGt_EORT);
+#line 30 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 30 "whenever_do_continue.pgc"
+
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into emp values ( 'josh' , 10000 , 10 )", ECPGt_EOIT, ECPGt_EORT);
+#line 31 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 31 "whenever_do_continue.pgc"
+
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into emp values ( 'tom' , 20000 , null )", ECPGt_EOIT, ECPGt_EORT);
+#line 32 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 32 "whenever_do_continue.pgc"
+
+
+   /* declare c cursor for select ename , sal , comm from emp order by ename asc */
+#line 34 "whenever_do_continue.pgc"
+
+
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare c cursor for select ename , sal , comm from emp order by ename asc", ECPGt_EOIT, ECPGt_EORT);
+#line 36 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 36 "whenever_do_continue.pgc"
+
+
+   /* The 'BREAK' condition to exit the loop. */
+   /* exec sql whenever not found  break ; */
+#line 39 "whenever_do_continue.pgc"
+
+
+   /* The DO CONTINUE makes the loop start at the next iteration when an error occurs.*/
+   /* exec sql whenever sqlerror  continue ; */
+#line 42 "whenever_do_continue.pgc"
+
+
+   while (1)
+   {
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch c", ECPGt_EOIT, 
+   ECPGt_char,&(emp.ename),(long)12,(long)1,(12)*sizeof(char), 
+   ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+   ECPGt_float,&(emp.sal),(long)1,(long)1,sizeof(float), 
+   ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+   ECPGt_float,&(emp.comm),(long)1,(long)1,sizeof(float), 
+   ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 46 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
+#line 46 "whenever_do_continue.pgc"
+
+if (sqlca.sqlcode < 0) continue;}
+#line 46 "whenever_do_continue.pgc"
+
+       /* The employees with non-NULL commissions will be displayed. */
+       printf("%s %7.2f %9.2f\n", emp.ename, emp.sal, emp.comm);
+   }
+
+   /*
+    * This 'CONTINUE' shuts off the 'DO CONTINUE' and allow the program to
+    * proceed if any further errors do occur.
+    */
+   /* exec sql whenever sqlerror  continue ; */
+#line 55 "whenever_do_continue.pgc"
+
+
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close c", ECPGt_EOIT, ECPGt_EORT);}
+#line 57 "whenever_do_continue.pgc"
+
+
+   strcpy(msg, "drop");
+   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table emp", ECPGt_EOIT, ECPGt_EORT);}
+#line 60 "whenever_do_continue.pgc"
+
+
+   exit(0);
+}
diff --git a/src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.stderr b/src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.stderr
new file mode 100644 (file)
index 0000000..b33329b
--- /dev/null
@@ -0,0 +1,112 @@
+[NO_PID]: ECPGdebug: set to 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>  
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 26: query: create table emp ( ename varchar , sal double precision , comm double precision ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 26: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 26: OK: CREATE TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 29: query: insert into emp values ( 'Ram' , 111100 , 21 ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 29: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 29: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 30: query: insert into emp values ( 'aryan' , 11110 , null ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 30: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 30: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: insert into emp values ( 'josh' , 10000 , 10 ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 31: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 32: query: insert into emp values ( 'tom' , 20000 , null ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 32: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 32: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: query: declare c cursor for select ename , sal , comm from emp order by ename asc; 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]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 36: OK: DECLARE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: query: fetch c; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 46: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: aryan offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: 11110 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT:  offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode -213 on line 46: null value without indicator on line 46
+[NO_PID]: sqlca: code: -213, state: 22002
+[NO_PID]: ecpg_execute on line 46: query: fetch c; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 46: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: josh offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: 10000 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: 10 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: query: fetch c; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 46: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: Ram offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: 111100 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: 21 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: query: fetch c; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 46: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: tom offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT: 20000 offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 46: RESULT:  offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode -213 on line 46: null value without indicator on line 46
+[NO_PID]: sqlca: code: -213, state: 22002
+[NO_PID]: ecpg_execute on line 46: query: fetch c; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 46: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 46: correctly got 0 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode 100 on line 46: no data found on line 46
+[NO_PID]: sqlca: code: 100, state: 02000
+[NO_PID]: ecpg_execute on line 57: query: close c; 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: CLOSE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 60: query: drop table emp; 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: OK: DROP TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
diff --git a/src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.stdout b/src/interfaces/ecpg/test/expected/preproc-whenever_do_continue.stdout
new file mode 100644 (file)
index 0000000..75fb6ce
--- /dev/null
@@ -0,0 +1,2 @@
+josh 10000.00     10.00
+Ram 111100.00     21.00
index d658a4d6b2c323ed035895cc83ce93bc8dd5d8e2..39b1974f5fbdaf557440b2ce025623bff53a8383 100644 (file)
@@ -15,6 +15,7 @@ TESTS = array_of_struct array_of_struct.c \
    type type.c \
    variable variable.c \
    whenever whenever.c \
+   whenever_do_continue whenever_do_continue.c \
    pointer_to_struct pointer_to_struct.c
 
 all: $(TESTS)
diff --git a/src/interfaces/ecpg/test/preproc/whenever_do_continue.pgc b/src/interfaces/ecpg/test/preproc/whenever_do_continue.pgc
new file mode 100644 (file)
index 0000000..8ceda69
--- /dev/null
@@ -0,0 +1,63 @@
+#include <stdlib.h>
+
+exec sql include ../regression;
+
+exec sql whenever sqlerror sqlprint;
+
+int main(void)
+{
+   exec sql begin declare section;
+   struct
+   {
+       char ename[12];
+       float sal;
+       float comm;
+   } emp;
+
+   char msg[128];
+   exec sql end declare section;
+
+   ECPGdebug(1, stderr);
+
+   strcpy(msg, "connect");
+   exec sql connect to REGRESSDB1;
+
+   strcpy(msg, "create");
+   exec sql  create table emp(ename varchar,sal double precision, comm double precision);
+
+   strcpy(msg, "insert");
+   exec sql insert into emp values ('Ram',111100,21);
+   exec sql insert into emp values ('aryan',11110,null);
+   exec sql insert into emp values ('josh',10000,10);
+   exec sql insert into emp values ('tom',20000,null);
+
+   exec sql declare c cursor for select ename, sal, comm from emp order by ename asc;
+
+   exec sql open c;
+
+   /* The 'BREAK' condition to exit the loop. */
+   exec sql whenever not found do break;
+
+   /* The DO CONTINUE makes the loop start at the next iteration when an error occurs.*/
+   exec sql whenever sqlerror do continue;
+
+   while (1)
+   {
+       exec sql fetch c into :emp;
+       /* The employees with non-NULL commissions will be displayed. */
+       printf("%s %7.2f %9.2f\n", emp.ename, emp.sal, emp.comm);
+   }
+
+   /*
+    * This 'CONTINUE' shuts off the 'DO CONTINUE' and allow the program to
+    * proceed if any further errors do occur.
+    */
+   exec sql whenever sqlerror continue;
+
+   exec sql close c;
+
+   strcpy(msg, "drop");
+   exec sql drop table emp;
+
+   exit(0);
+}