]> granicus.if.org Git - postgresql/commitdiff
Add Oracle like handling of char arrays.
authorMichael Meskes <meskes@postgresql.org>
Tue, 13 Mar 2018 23:54:13 +0000 (00:54 +0100)
committerMichael Meskes <meskes@postgresql.org>
Tue, 13 Mar 2018 23:54:13 +0000 (00:54 +0100)
In some cases Oracle Pro*C handles char array differently than ECPG. This patch
adds a Oracle compatibility mode to make ECPG behave like Pro*C.

Patch by David Rader <davidr@openscg.com>

12 files changed:
src/interfaces/ecpg/ecpglib/data.c
src/interfaces/ecpg/ecpglib/extern.h
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/test/Makefile
src/interfaces/ecpg/test/compat_oracle/.gitignore [new file with mode: 0644]
src/interfaces/ecpg/test/compat_oracle/Makefile [new file with mode: 0644]
src/interfaces/ecpg/test/compat_oracle/char_array.pgc [new file with mode: 0644]
src/interfaces/ecpg/test/ecpg_schedule
src/interfaces/ecpg/test/expected/compat_oracle-char_array.c [new file with mode: 0644]
src/interfaces/ecpg/test/expected/compat_oracle-char_array.stderr [new file with mode: 0644]
src/interfaces/ecpg/test/expected/compat_oracle-char_array.stdout [new file with mode: 0644]

index 871e2011f3e828e87cb569350c60c5f8b9c6caee..bb2bef1afffde3c5fb9a0e416943c03f477a4532 100644 (file)
@@ -464,7 +464,45 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 
                                                if (varcharsize == 0 || varcharsize > size)
                                                {
-                                                       strncpy(str, pval, size + 1);
+                                                       /* compatibility mode, blank pad and null terminate char array */
+                                                       if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
+                                                       {
+                                                               memset(str, ' ', varcharsize);
+                                                               memcpy(str, pval, size);
+                                                               str[varcharsize-1] = '\0';
+
+                                                               /* compatiblity mode empty string gets -1 indicator but no warning */
+                                                               if (size == 0) {
+                                                                       /* truncation */
+                                                                       switch (ind_type)
+                                                                       {
+                                                                               case ECPGt_short:
+                                                                               case ECPGt_unsigned_short:
+                                                                                       *((short *) (ind + ind_offset * act_tuple)) = -1;
+                                                                                       break;
+                                                                               case ECPGt_int:
+                                                                               case ECPGt_unsigned_int:
+                                                                                       *((int *) (ind + ind_offset * act_tuple)) = -1;
+                                                                                       break;
+                                                                               case ECPGt_long:
+                                                                               case ECPGt_unsigned_long:
+                                                                                       *((long *) (ind + ind_offset * act_tuple)) = -1;
+                                                                                       break;
+       #ifdef HAVE_LONG_LONG_INT
+                                                                               case ECPGt_long_long:
+                                                                               case ECPGt_unsigned_long_long:
+                                                                                       *((long long int *) (ind + ind_offset * act_tuple)) = -1;
+                                                                                       break;
+       #endif                                                  /* HAVE_LONG_LONG_INT */
+                                                                               default:
+                                                                                       break;
+                                                                       }
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               strncpy(str, pval, size + 1);
+                                                       }
                                                        /* do the rtrim() */
                                                        if (type == ECPGt_string)
                                                        {
@@ -481,7 +519,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
                                                {
                                                        strncpy(str, pval, varcharsize);
 
-                                                       if (varcharsize < size)
+                                                       /* compatibility mode, null terminate char array */
+                                                       if (ORACLE_MODE(compat) && (varcharsize - 1) < size)
+                                                       {
+                                                               if (type == ECPGt_char || type == ECPGt_unsigned_char)
+                                                                       str[varcharsize-1] = '\0';
+                                                       }
+
+                                                       if (varcharsize < size || (ORACLE_MODE(compat) && (varcharsize - 1) < size))
                                                        {
                                                                /* truncation */
                                                                switch (ind_type)
index 91c7367b8b06f8cd888aac4a324b95c856c70143..a88f34106cceec5785b74561f04a3e10a0658f78 100644 (file)
 
 enum COMPAT_MODE
 {
-       ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE
+       ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE, ECPG_COMPAT_ORACLE
 };
 
 extern bool ecpg_internal_regression_mode;
 
 #define INFORMIX_MODE(X) ((X) == ECPG_COMPAT_INFORMIX || (X) == ECPG_COMPAT_INFORMIX_SE)
+#define ORACLE_MODE(X) ((X) == ECPG_COMPAT_ORACLE)
 
 enum ARRAY_TYPE
 {
index 0704837396f7678bb8248d2023e88c4754e379de..8fb731fcfb18e574bfc4795cb3acc84aa6cff3a1 100644 (file)
@@ -41,7 +41,7 @@ help(const char *progname)
        printf(_("  -c             automatically generate C code from embedded SQL code;\n"
                         "                 this affects EXEC SQL TYPE\n"));
        printf(_("  -C MODE        set compatibility mode; MODE can be one of\n"
-                        "                 \"INFORMIX\", \"INFORMIX_SE\"\n"));
+                        "                 \"INFORMIX\", \"INFORMIX_SE\", \"ORACLE\"\n"));
 #ifdef YYDEBUG
        printf(_("  -d             generate parser debug output\n"));
 #endif
@@ -208,6 +208,10 @@ main(int argc, char *const argv[])
                                        snprintf(informix_path, MAXPGPATH, "%s/informix/esql", pkginclude_path);
                                        add_include_path(informix_path);
                                }
+                               else if (strncmp(optarg, "ORACLE", strlen("ORACLE")) == 0)
+                               {
+                                       compat = ECPG_COMPAT_ORACLE;
+                               }
                                else
                                {
                                        fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
index 2c35426b7fb126d6654965244f8b9fe001089f9a..d0c4e4701664f123d68dca7210f90db7929473fe 100644 (file)
@@ -122,10 +122,12 @@ extern int        filtered_base_yylex(void);
 
 enum COMPAT_MODE
 {
-       ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE
+       ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE, ECPG_COMPAT_ORACLE
 };
 extern enum COMPAT_MODE compat;
 
 #define INFORMIX_MODE  (compat == ECPG_COMPAT_INFORMIX || compat == ECPG_COMPAT_INFORMIX_SE)
+#define ORACLE_MODE (compat == ECPG_COMPAT_ORACLE)
+
 
 #endif                                                 /* _ECPG_PREPROC_EXTERN_H */
index 45a4b0783791a6301dd4e7ca0dba1cd47d02e15f..8eedcf39dc813f353045271d548ee803df22eab9 100644 (file)
@@ -30,6 +30,7 @@ all install installdirs uninstall distprep:
        $(MAKE) -C pgtypeslib $@
        $(MAKE) -C preproc $@
        $(MAKE) -C compat_informix $@
+       $(MAKE) -C compat_oracle $@
        $(MAKE) -C thread $@
 
 clean distclean maintainer-clean:
@@ -38,6 +39,7 @@ clean distclean maintainer-clean:
        $(MAKE) -C pgtypeslib $@
        $(MAKE) -C preproc $@
        $(MAKE) -C compat_informix $@
+       $(MAKE) -C compat_oracle $@
        $(MAKE) -C thread $@
        rm -rf tmp_check results log
        rm -f pg_regress regression.diffs regression.out pg_regress_ecpg.o $(WIN32RES)
diff --git a/src/interfaces/ecpg/test/compat_oracle/.gitignore b/src/interfaces/ecpg/test/compat_oracle/.gitignore
new file mode 100644 (file)
index 0000000..63b3766
--- /dev/null
@@ -0,0 +1,2 @@
+/char_array
+/char_array.c
diff --git a/src/interfaces/ecpg/test/compat_oracle/Makefile b/src/interfaces/ecpg/test/compat_oracle/Makefile
new file mode 100644 (file)
index 0000000..cd4e7e8
--- /dev/null
@@ -0,0 +1,11 @@
+subdir = src/interfaces/ecpg/test/compat_oracle
+top_builddir = ../../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/$(subdir)/../Makefile.regress
+
+# Use special oracle compatibility switch for all tests in this directory
+ECPG += -C ORACLE
+
+TESTS = char_array char_array.c
+
+all: $(TESTS)
diff --git a/src/interfaces/ecpg/test/compat_oracle/char_array.pgc b/src/interfaces/ecpg/test/compat_oracle/char_array.pgc
new file mode 100644 (file)
index 0000000..8e16339
--- /dev/null
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+EXEC SQL INCLUDE ../regression;
+
+static void warn();
+
+/* Compatible handling of char array to retrieve varchar field to char array
+   should be fixed-length, blank-padded, then null-terminated.
+   Conforms to the ANSI Fixed Character type. */
+
+int main() {
+
+  ECPGdebug(1, stderr);
+  EXEC SQL CONNECT TO REGRESSDB1;
+
+  EXEC SQL WHENEVER SQLWARNING do warn();
+  EXEC SQL WHENEVER SQLERROR SQLPRINT;
+
+  const char *ppppp = "XXXXX";
+
+  EXEC SQL BEGIN DECLARE SECTION;
+  char shortstr[5];
+  char bigstr[11];
+  short shstr_ind = 0;
+  short bigstr_ind = 0;
+  EXEC SQL END DECLARE SECTION;
+
+  EXEC SQL CREATE TABLE strdbase (strval varchar(10));
+  EXEC SQL INSERT INTO strdbase values ('');
+  EXEC SQL INSERT INTO strdbase values ('AB');
+  EXEC SQL INSERT INTO strdbase values ('ABCD');
+  EXEC SQL INSERT INTO strdbase values ('ABCDE');
+  EXEC SQL INSERT INTO strdbase values ('ABCDEF');
+  EXEC SQL INSERT INTO strdbase values ('ABCDEFGHIJ');
+
+  EXEC SQL declare C cursor for select strval, strval from strdbase;
+  EXEC SQL OPEN C;
+
+  EXEC SQL WHENEVER NOT FOUND DO BREAK;
+
+  printf("Full Str.  :  Short  Ind.\n");
+  while(1) {
+    strncpy(shortstr, ppppp, sizeof shortstr);
+    memset(bigstr, 0, sizeof bigstr);
+    EXEC SQL FETCH C into :bigstr :bigstr_ind, :shortstr :shstr_ind;
+    printf("\"%s\": \"%s\"  %d\n", bigstr, shortstr, shstr_ind);
+  }
+
+  EXEC SQL close cstr;
+  EXEC SQL DROP TABLE strdbase;
+
+  printf("\nGOOD-BYE!!\n\n");
+
+  EXEC SQL COMMIT WORK;
+
+  EXEC SQL DISCONNECT ALL;
+
+  return 0;
+}
+
+static void warn(void)
+{
+  fprintf(stderr, "Warning: At least one column was truncated\n");
+}
index cff4eebfde4ef9859036bdcfef82575cd83a39e0..991b8cb5e24c6976d0c563617fddef56f437bd25 100644 (file)
@@ -7,6 +7,7 @@ test: compat_informix/sqlda
 test: compat_informix/describe
 test: compat_informix/test_informix
 test: compat_informix/test_informix2
+test: compat_oracle/char_array
 test: connect/test2
 test: connect/test3
 test: connect/test4
diff --git a/src/interfaces/ecpg/test/expected/compat_oracle-char_array.c b/src/interfaces/ecpg/test/expected/compat_oracle-char_array.c
new file mode 100644 (file)
index 0000000..21980ca
--- /dev/null
@@ -0,0 +1,219 @@
+/* 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 "char_array.pgc"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#line 1 "regression.h"
+
+
+
+
+
+
+#line 5 "char_array.pgc"
+
+
+static void warn();
+
+/* Compatible handling of char array to retrieve varchar field to char array
+   should be fixed-length, blank-padded, then null-terminated.
+   Conforms to the ANSI Fixed Character type. */
+
+int main() {
+
+  ECPGdebug(1, stderr);
+  { ECPGconnect(__LINE__, 3, "ecpg1_regression" , NULL, NULL , NULL, 0); }
+#line 16 "char_array.pgc"
+
+
+  /* exec sql whenever sql_warning  do warn ( ) ; */
+#line 18 "char_array.pgc"
+
+  /* exec sql whenever sqlerror  sqlprint ; */
+#line 19 "char_array.pgc"
+
+
+  const char *ppppp = "XXXXX";
+
+  /* exec sql begin declare section */
+   
+   
+     
+     
+  
+#line 24 "char_array.pgc"
+ char shortstr [ 5 ] ;
+#line 25 "char_array.pgc"
+ char bigstr [ 11 ] ;
+#line 26 "char_array.pgc"
+ short shstr_ind = 0 ;
+#line 27 "char_array.pgc"
+ short bigstr_ind = 0 ;
+/* exec sql end declare section */
+#line 28 "char_array.pgc"
+
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "create table strdbase ( strval varchar ( 10 ) )", ECPGt_EOIT, ECPGt_EORT);
+#line 30 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 30 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 30 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "insert into strdbase values ( '' )", ECPGt_EOIT, ECPGt_EORT);
+#line 31 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 31 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 31 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "insert into strdbase values ( 'AB' )", ECPGt_EOIT, ECPGt_EORT);
+#line 32 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 32 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 32 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "insert into strdbase values ( 'ABCD' )", ECPGt_EOIT, ECPGt_EORT);
+#line 33 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 33 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 33 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "insert into strdbase values ( 'ABCDE' )", ECPGt_EOIT, ECPGt_EORT);
+#line 34 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 34 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 34 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "insert into strdbase values ( 'ABCDEF' )", ECPGt_EOIT, ECPGt_EORT);
+#line 35 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 35 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 35 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "insert into strdbase values ( 'ABCDEFGHIJ' )", ECPGt_EOIT, ECPGt_EORT);
+#line 36 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 36 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 36 "char_array.pgc"
+
+
+  /* declare C cursor for select strval , strval from strdbase */
+#line 38 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "declare C cursor for select strval , strval from strdbase", ECPGt_EOIT, ECPGt_EORT);
+#line 39 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 39 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 39 "char_array.pgc"
+
+
+  /* exec sql whenever not found  break ; */
+#line 41 "char_array.pgc"
+
+
+  printf("Full Str.  :  Short  Ind.\n");
+  while(1) {
+    strncpy(shortstr, ppppp, sizeof shortstr);
+    memset(bigstr, 0, sizeof bigstr);
+    { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "fetch C", ECPGt_EOIT, 
+       ECPGt_char,(bigstr),(long)11,(long)1,(11)*sizeof(char), 
+       ECPGt_short,&(bigstr_ind),(long)1,(long)1,sizeof(short), 
+       ECPGt_char,(shortstr),(long)5,(long)1,(5)*sizeof(char), 
+       ECPGt_short,&(shstr_ind),(long)1,(long)1,sizeof(short), ECPGt_EORT);
+#line 47 "char_array.pgc"
+
+if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
+#line 47 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 47 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 47 "char_array.pgc"
+
+    printf("\"%s\": \"%s\"  %d\n", bigstr, shortstr, shstr_ind);
+  }
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "close cstr", ECPGt_EOIT, ECPGt_EORT);
+#line 51 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 51 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 51 "char_array.pgc"
+
+  { ECPGdo(__LINE__, 3, 1, NULL, 0, ECPGst_normal, "drop table strdbase", ECPGt_EOIT, ECPGt_EORT);
+#line 52 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 52 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 52 "char_array.pgc"
+
+
+  printf("\nGOOD-BYE!!\n\n");
+
+  { ECPGtrans(__LINE__, NULL, "commit work");
+#line 56 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 56 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 56 "char_array.pgc"
+
+
+  { ECPGdisconnect(__LINE__, "ALL");
+#line 58 "char_array.pgc"
+
+if (sqlca.sqlwarn[0] == 'W') warn ( );
+#line 58 "char_array.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint();}
+#line 58 "char_array.pgc"
+
+
+  return 0;
+}
+
+static void warn(void)
+{
+  fprintf(stderr, "Warning: At least one column was truncated\n");
+}
diff --git a/src/interfaces/ecpg/test/expected/compat_oracle-char_array.stderr b/src/interfaces/ecpg/test/expected/compat_oracle-char_array.stderr
new file mode 100644 (file)
index 0000000..5e3ec20
--- /dev/null
@@ -0,0 +1,145 @@
+[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 30: query: create table strdbase ( strval varchar ( 10 ) ); 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: CREATE TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: insert into strdbase values ( '' ); 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 strdbase values ( 'AB' ); 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 33: query: insert into strdbase values ( 'ABCD' ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 33: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 33: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 34: query: insert into strdbase values ( 'ABCDE' ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 34: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 34: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 35: query: insert into strdbase values ( 'ABCDEF' ); with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 35: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 35: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 36: query: insert into strdbase values ( 'ABCDEFGHIJ' ); 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: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: query: declare C cursor for select strval , strval from strdbase; 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]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 39: OK: DECLARE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT:  offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT:  offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: AB offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: AB offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCD offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCD offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCDE offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCDE offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+Warning: At least one column was truncated
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCDEF offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCDEF offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+Warning: At least one column was truncated
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCDEFGHIJ offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: ABCDEFGHIJ offset: -1; array: no
+[NO_PID]: sqlca: code: 0, state: 00000
+Warning: At least one column was truncated
+[NO_PID]: ecpg_execute on line 47: query: fetch C; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 47: correctly got 0 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode 100 on line 47: no data found on line 47
+[NO_PID]: sqlca: code: 100, state: 02000
+[NO_PID]: ecpg_execute on line 51: query: close cstr; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 51: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_check_PQresult on line 51: bad response - ERROR:  cursor "cstr" does not exist
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlstate 34000 (sqlcode -400): cursor "cstr" does not exist on line 51
+[NO_PID]: sqlca: code: -400, state: 34000
+SQL error: cursor "cstr" does not exist on line 51
+[NO_PID]: ecpg_execute on line 52: query: drop table strdbase; with 0 parameter(s) on connection ecpg1_regression
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 52: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_check_PQresult on line 52: bad response - ERROR:  current transaction is aborted, commands ignored until end of transaction block
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlstate 25P02 (sqlcode -400): current transaction is aborted, commands ignored until end of transaction block on line 52
+[NO_PID]: sqlca: code: -400, state: 25P02
+SQL error: current transaction is aborted, commands ignored until end of transaction block on line 52
+[NO_PID]: ECPGtrans on line 56: action "commit work"; 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/expected/compat_oracle-char_array.stdout b/src/interfaces/ecpg/test/expected/compat_oracle-char_array.stdout
new file mode 100644 (file)
index 0000000..d58b3c7
--- /dev/null
@@ -0,0 +1,10 @@
+Full Str.  :  Short  Ind.
+"          ": "    "  -1
+"AB        ": "AB  "  0
+"ABCD      ": "ABCD"  0
+"ABCDE     ": "ABCD"  5
+"ABCDEF    ": "ABCD"  6
+"ABCDEFGHIJ": "ABCD"  10
+
+GOOD-BYE!!
+