Git Product home page Git Product logo

opensourcecobol / open-cobol-esql Goto Github PK

View Code? Open in Web Editor NEW
48.0 10.0 23.0 1.07 MB

Open Cobol ESQL (ocesql) is an open-source Embedded SQL pre-compiler and run-time library designed for COBOL applications which access an open-source database.

Home Page: https://www.osscons.jp/osscobol/

License: GNU Lesser General Public License v3.0

Makefile 0.49% M4 0.29% COBOL 0.37% C 23.13% Shell 71.74% Yacc 1.61% Lex 1.69% Dockerfile 0.18% Python 0.50%
c cobol postgresql

open-cobol-esql's Introduction

                   Open Cobol ESQL (Ocesql)
                       Version 1.3.0

                       March 24, 2022

                 Tokyo System House Co., Ltd.
                  [email protected]

1. Introduction
===============

Open Cobol ESQL (ocesql) is an open-source Embedded SQL pre-compiler
and run-time library designed for COBOL applications which access 
an open-source database.  Ocesql translates each EXEC SQL statements
into the standard COBOL CALL statements to the run-time library.

2. Package overview
===================

This package includes the following subdirectories:

    - copy          Copy books for pre-compiled COBOL programs
    - dblib         DB access library (Run-time library)
    - ocesql        ESQL pre-compiler
    - sample        Sample cobol programs

A build of this package typically installs an ocesql executable and 
run-time library as follows:

    - ocesql        ESQL pre-compiler
    - libocesql.so  Run-time library

3. License
==========

All programs except those in dblib subdirectories are distributed
under the GNU General Public License v3 or later.  See COPYING for details.

Programs in dblib subdirectories are distributed under the GNU
Lesser General Public License v3 or later.  See COPYING.LESSER for details.

See also AUTHORS for the author and contributors.

4. Requirements
===============

  1) Open-source database

    Ocesql currently supports PostgreSQL database only.

    o PostgreSQL C Library (libpq) 8.4 or later
      https://www.postgresql.org/
      https://www.postgresql.jp/

  2) COBOL Development System

    Ocesql is tested with the following COBOL compilers:

    o OpenCOBOL 1.1
      https://sourceforge.net/projects/open-cobol/

    o opensource COBOL 1.5.2J
      https://www.osscons.jp/osscobol/download/

    o Micro Focus Server Express 5.1
      Micro Focus Visual COBOL 2.1 for x64/x86 Linux
      https://www.microfocus.com/
      https://www.microfocus.co.jp/

    o GnuCOBOL 2.2
      https://www.gnu.org/software/gnucobol/

5. Installation
===============

To install Ocesql (PostgreSQL 9.0 or above):  
Before running "configure", you'll need to tell ocesql where your include PostgreSQL include files such as "libpq-fe.h" are, 
and also possibly the library location.  These vary by PostgreSQL version and distribution, but on a recent Ubuntu with PostgreSQL 14 this will be something like:

    export CPPFLAGS="-I/usr/include/postgresql"

An earlier version (PostgreSQL 9) might be:

    export CPPFLAGS="-I/usr/pgsql-9.x/include"
    export LDFLAGS="-L/usr/pgsql-9.x/lib"
    
Then run:

    ./configure
    make
    make install
    
If you want to install Ocesql on PostgreSQL < 9, just:

    ./configure
    make
    make install



The "make install" will default to "/usr/local" as the install path.
You may override this by specifying "--prefix=<your install path>" 
to the "./configure" command.

6. Sample programs
==================

Ocesql comes with two sample programs that demonstrate embedded 
SQL in a COBOL application.  The "sample" directory contains
following programs:

  o INSERTTBL.cbl ---- CONNECT, DROP TABLE, CREATE TABLE, 
                       INSERT, COMMIT, ROLLBACK, DISCONNECT

  o FETCHTBL.cbl ----- CONNECT, SELECT COUNT(*), DECLARE cursor, 
                       FETCH cursor, COMMIT, ROLLBACK, DISCONNECT

* Note that these sample programs includes Japanese Shift-JIS characters.
  If you wish to run on non-Japanese environment, modify them first so that the commented-out lines containing non-Japanese text are used in place of the Japanese ones.

To run the sample programs: 

  1) Create a sample database named "testdb"

     When PostgreSQL (non-Japanese):

       createdb -T template0 testdb

     Or, if working in a Japanese environment, encoding should be UTF-8.

       createdb -E UTF8 -T template0 --lc-collate=ja_JP.UTF-8 --lc-ctype=ja_JP.UTF-8 testdb

  2) Pre-compile the sample programs

       cd <your install path>/Open-COBOL-ESQL/sample
       ocesql INSERTTBL.cbl INSERTTBL.cob
       ocesql FETCHTBL.cbl FETCHTBL.cob

   * Usage: ocesql [--inc=<include path>] SOURCE [DESTFILE] [LOGFILE]

  3) Compile the sample programs with COBOL compiler and 
     generate executable files:

     Working with Micro Focus Server Express or Visual COBOL:

       export COBCPY=<your install path>/Open-COBOL-ESQL/copy
       cob -ze "" /usr/local/lib/libocesql.so -o mfocesql.so
       cob -x INSERTTBL.cob -C"INITCALL(mfocesql)"
       cob -x FETCHTBL.cob -C"INITCALL(mfocesql)"

     Working with OpenCOBOL or opensource COBOL:

       export COBCPY=<your install path>/Open-COBOL-ESQL/copy
       cobc -x -locesql INSERTTBL.cob
       cobc -x -locesql FETCHTBL.cob

  4) Run the sample programs:
  
       ./INSERTTBL
       ./FETCHTBL

   * To create a sample table, run INSERTTBL first.
     Database credentials are hardcoded in each sample program and by default access is as the "postgres" user.

7. Working with PostgreSQL
==========================

7-1. SQL Verbs
--------------
Ocesql accepts most SQL verbs supported by PostgreSQL's libpq.

The pre-compiler translates each embedded SQL statement into a standard
COBOL CALL statement to the run-time library.  When the CALL statement
is executed, the original SQL statement is passed to libpq's functions
like PQexecParams or PQexec, which in turn submits it to the database.

There are some exceptions to this rule.  When the following SQL verbs
are found, the pre-compiler performs syntax checking, parses these verbs
and generates a series of special SQL commands:

  o CONNECT username IDENTIFIED BY passwd USING dbname
  o DISCONNECT
  o SELECT ... INTO :host-variable ...
  o DECLARE CURSOR cursor FOR SELECT ...
  o OPEN cursor
  o CLOSE cursor
  o FETCH cursor INTO :host-variable

The sample programs demonstrate the use of these special verbs.

7-2. Error handling
-------------------
If SQLCODE or SQLSTATE of SQLCA is set to non-zero value, 
this means that a PostgreSQL error has happened internally.  
SQLSTATE is set to one of the PostgreSQL error codes listed in 
the following URL:

  https://www.postgresql.org/docs/8.4/static/errcodes-appendix.html
  https://www.postgresql.jp/document/8.4/html/errcodes-appendix.html

The sample programs demonstrate the use of SQLSTATE.

8. Working with other databases
===============================
Ocesql is currently supports PostgreSQL only, although it is designed 
to work with several open-source databases, 

----------------------------------------------------------------------
Copyright 2019 Tokyo System House Co., Ltd.

open-cobol-esql's People

Contributors

chihhao-su avatar gitmensch avatar n-isaka avatar n-izawa avatar shraddha-2405 avatar someoneelseosm avatar ytr-sakamoto avatar yutaro-sakamoto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

open-cobol-esql's Issues

add "quiet" mode to ocesql (to not output "LIST OF CALLED DB Library API")

precompiling a pco without any EXEC SQL leads to:

precompile start: EMPTY.pco
=======================================================
              LIST OF CALLED DB Library API
=======================================================
=======================================================

Using a "normal" source leads to

precompile start: NORMAL.pco
=======================================================
              LIST OF CALLED DB Library API
=======================================================
Generate:OCESQLPrepare
Generate:OCESQLIDExecPrepare
Generate:OCESQLIDConnect
Generate:OCESQLIDExecSelectIntoOne
Generate:OCESQLIDExecSelectIntoOne
Generate:OCESQLIDExecSelectIntoOne
Generate:OCESQLIDExec
Generate:OCESQLIDExecSelectIntoOne
Generate:COMMITuseDBNAME
Generate:ROLLBACKuseDBNAME
=======================================================

This is very verbose (so I'd actually suggest to only output all of those when running with --verbose, but if you want one could use --quiet instead (which otherwise could be used/reserved for "no display, only exit code").

I would give implementing that a try, but would like to have the "ok" to implement it either way up-front.

Change the license to GPL3

After discussion in our community, we decided to change the license to GPL3.
We will release v1.3 in a few days.

See #49

Compile not working on Fedora 34

Downloaded Ocesql 1.2, I have Postgresql 13, gcc 11.2.

Ran configure, make and got the following:

libtool: link: gcc -O2 -o ocesql errorfile.o ocesql.o ocesqlutil.o parser.o ppout.o scanner.o -lpq
/usr/bin/ld: scanner.o:(.bss+0x540): multiple definition of dbname'; ocesql.o:(.bss+0x220): first defined here /usr/bin/ld: scanner.o:(.bss+0x440): multiple definition of prepname'; ocesql.o:(.bss+0x120): first defined here
/usr/bin/ld: scanner.o:(.bss+0x650): multiple definition of host_reference_list'; ocesql.o:(.bss+0x338): first defined here /usr/bin/ld: scanner.o:(.bss+0x648): multiple definition of res_host_reference_list'; ocesql.o:(.bss+0x330): first defined here
/usr/bin/ld: scanner.o:(.bss+0x240): multiple definition of cursorname'; ocesql.o:(.bss+0x20): first defined here /usr/bin/ld: scanner.o:(.bss+0x640): multiple definition of sql_list'; ocesql.o:(.bss+0x328): first defined here
/usr/bin/ld: scanner.o:(.bss+0x674): multiple definition of hostlineno'; ocesql.o:(.bss+0x344): first defined here /usr/bin/ld: scanner.o:(.bss+0x658): multiple definition of exec_list'; ocesql.o:(.bss+0x320): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:395: ocesql] Error 1
make[2]: Leaving directory '/home/paul/Downloads/Open-COBOL-ESQL-1.2/ocesql'
make[1]: *** [Makefile:393: all-recursive] Error 1
make[1]: Leaving directory '/home/paul/Downloads/Open-COBOL-ESQL-1.2'
make: *** [Makefile:324: all] Error 2

automate the tests more

The testing framework is what currently stand out when compared to GixSQL. It would be good to include it in the "autotools way":

  • if not done already: add tests/README or similar that specifies in detail what is needed to run the testsuite
  • change tests/Makefile to tests/Makefile.am and the subdirs in root to let the testsuite be updated and build automatically; and also be run with make check in the root dir
  • if not done already: do the setup (= test db creation) via a shell script, allowing the connection details to be specified via environment it is fine to have a default that matches your test environment)
  • if necessary: add check-hook and friends to this Makefile.am to do the necessary setup

I could have a look at doing this, possibly in May 2022.

Update CI actions

@yutaro-sakamoto See warnings in the logs of the workflows:

Open-COBOL-ESQL-tests
Node.js 12 actions are deprecated. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/. Please update the following actions to use Node.js 16: actions/cache@v2, actions/checkout@v2, actions/upload-artifact@v2
The save-state command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/

The second issue is likely going away with handling the first one.

replace "int type" and magic number defines with an enum type

this is related to struct sql_var / its typedef SQLVARLIST and everything this is used for, for example OCESQLSetSQLParams, OCESQLSetResultParams,

static SQLVARLIST * new_sql_var_list(void);
static SQLVARLIST * add_sql_var_list(int, int, int, void *);
static SQLVARLIST * add_sql_res_var_list(int, int, int, void *);
static void clear_sql_var_list(const SQLVARLIST *);
static void show_sql_var_list(const SQLVARLIST *);

Background: an enum with defined values is much more easy to debug and follow than magic numbers, which seem to be defined in ocdb.h:

// 型情報
//#define OCDB_TYPE_FORMATTED_NUMBER 0        // 数字編集
#define OCDB_TYPE_UNSIGNED_NUMBER 1         // 符号無数字
//#define OCDB_TYPE_SIGNED_NUMBER_TS 2        // 符号付数字(trailing separate)
#define OCDB_TYPE_SIGNED_NUMBER_TC 3        // 符号付数字(trailing combined)
#define OCDB_TYPE_SIGNED_NUMBER_LS 4        // 符号付数字(leading separete)
//#define OCDB_TYPE_SIGNED_NUMBER_LC 5        // 符号付数字(leading combined)
//#define OCDB_TYPE_SIGNED_CALC 6             // 符号付計算
//#define OCDB_TYPE_UNSIGNED_CALC 7           // 符号無計算
#define OCDB_TYPE_UNSIGNED_NUMBER_PD 8        // 正のパック10進数
#define OCDB_TYPE_SIGNED_NUMBER_PD 9      // 符号付パック10進数
//#define OCDB_TYPE_COMP6 10                  // COMP-6
//#define OCDB_TYPE_SINGED_BINARY 11          // 符号付2進数
//#define OCDB_TYPE_UNSINGED_BINARY 12        // 符号無2進数
#define OCDB_TYPE_SINGED_BINARY_NATIVE 13   // 符号付2進数(native-order)
#define OCDB_TYPE_UNSINGED_BINARY_NATIVE 14 // 符号無2進数(native-order)
#define OCDB_TYPE_ALPHANUMERIC 16           // 英数字
//#define OCDB_TYPE_ALPHANUMERIC_J 17         // 英数字(桁寄せ)
//#define OCDB_TYPE_ALPHABETICAL 18           // 英字
//#define OCDB_TYPE_ALPHABETICAL_J 19         // 英字(桁寄せ)
//#define OCDB_TYPE_FORMATTED_ALPHANUMERIC 20 // 英数字編集
#define OCDB_TYPE_GROUP 22                  // 集団
//#define OCDB_TYPE_FLOATING_NUMBER 23        // Float or Double
#define OCDB_TYPE_JAPANESE 24               // 日本語
//#define OCDB_TYPE_JAPANESE_J 25             // 日本語(桁寄せ)
//#define OCDB_TYPE_FORMATTED_JAPANESE 26     // 日本語編集
//#define OCDB_TYPE_WIDE 27                   // wide
//#define OCDB_TYPE_WIDE_J 28                 // wide(桁寄せ)
//#define OCDB_TYPE_FORMATTED_WIDE 29         // wide
#define OCDB_TYPE_ALPHANUMERIC_VARYING 30     // VARYING(PIC X)
#define OCDB_TYPE_JAPANESE_VARYING 31         // VARYING(PIC N)
#define OCDB_TYPE_MIN 0                       // 型下限
#define OCDB_TYPE_MAX 32                      // 型上限

So instead use

// 型情報
enum sqlVarType {
//    OCDB_TYPE_FORMATTED_NUMBER = 0,        // 数字編集
    OCDB_TYPE_UNSIGNED_NUMBER = 1,         // 符号無数字
//    OCDB_TYPE_SIGNED_NUMBER_TS = 2,        // 符号付数字(trailing separate)
    OCDB_TYPE_SIGNED_NUMBER_TC = 3,        // 符号付数字(trailing combined)
    OCDB_TYPE_SIGNED_NUMBER_LS = 4,        // 符号付数字(leading separete)
//    OCDB_TYPE_SIGNED_NUMBER_LC = 5,        // 符号付数字(leading combined)
//    OCDB_TYPE_SIGNED_CALC = 6,             // 符号付計算
//    OCDB_TYPE_UNSIGNED_CALC = 7,           // 符号無計算
    OCDB_TYPE_UNSIGNED_NUMBER_PD = 8,        // 正のパック10進数
    OCDB_TYPE_SIGNED_NUMBER_PD = 9,      // 符号付パック10進数
//    OCDB_TYPE_COMP6 = 10,                  // COMP-6
//    OCDB_TYPE_SINGED_BINARY = 11,          // 符号付2進数
//    OCDB_TYPE_UNSINGED_BINARY = 12,        // 符号無2進数
    OCDB_TYPE_SINGED_BINARY_NATIVE = 13,   // 符号付2進数(native-order)
    OCDB_TYPE_UNSINGED_BINARY_NATIVE = 14, // 符号無2進数(native-order)
    OCDB_TYPE_ALPHANUMERIC = 16,           // 英数字
//    OCDB_TYPE_ALPHANUMERIC_J = 17,         // 英数字(桁寄せ)
//    OCDB_TYPE_ALPHABETICAL = 18,           // 英字
//    OCDB_TYPE_ALPHABETICAL_J = 19,         // 英字(桁寄せ)
//    OCDB_TYPE_FORMATTED_ALPHANUMERIC = 20, // 英数字編集
    OCDB_TYPE_GROUP = 22,                  // 集団
//    OCDB_TYPE_FLOATING_NUMBER = 23,        // Float or Double
    OCDB_TYPE_JAPANESE = 24,               // 日本語
//    OCDB_TYPE_JAPANESE_J = 25,             // 日本語(桁寄せ)
//    OCDB_TYPE_FORMATTED_JAPANESE = 26,     // 日本語編集
//    OCDB_TYPE_WIDE = 27,                   // wide
//    OCDB_TYPE_WIDE_J = 28,                 // wide(桁寄せ)
//    OCDB_TYPE_FORMATTED_WIDE = 29,         // wide
    OCDB_TYPE_ALPHANUMERIC_VARYING = 30,     // VARYING(PIC X)
    OCDB_TYPE_JAPANESE_VARYING = 31,         // VARYING(PIC N)
    OCDB_TYPE_MIN = 0,                       // 型下限
    OCDB_TYPE_MAX = 32                      // 型上限
};

and then instead of int type use enum sqlVarType type.

mutli-row fetch (oracle) [generating bad COBOL]

procob targeted sources commonly work with ocesql (apart from the place where the DECLARE statements have to be) but while the following code does pass the preparser, the resulting code isn't valid COBOL.

Given the table

       01 T02-FETCHTAB.
           05 T02-ID           PIC  X(018)              OCCURS 10.
           05 T02-STAMP        PIC  X(026)              OCCURS 10.

and the code

           EXEC SQL AT :CON
              DECLARE CSKEYTAB CURSOR FOR
                 SELECT TABID, STAMP FROM TAB
                 ORDER BY
                       USERID
                 ASC
           END-EXEC.

           EXEC SQL AT :CON
              OPEN CSKEYTAB 
           END-EXEC.
      *
           IF SQLCODE NOT = 0
              MOVE 'BAD SQLOPEN' TO ERROR-SQL
              PERFORM ERROR-SQL
           END-IF
      *
       DO-FETCH. 
      *
           INITIALIZE T02-FETCHTAB
           EXEC SQL AT :CON
               FETCH CSKEYTAB 
               INTO
                 :T02-ID,
                 :T02-STAMP
           END-EXEC.

      * SQLERRD(3) stores number of retrieved rows - with each fetch
      * it will be therefore incremented (if more data is there)
           IF SQLCODE NOT = 0
              MOVE 0 TO CUR-MAX
           ELSE
              MOVE FUNCTION MOD (SQLERRD(3), 10) INTO CUR-MAX
              IF CUR-MAX = 0    MOVE 10 TO CUR-MAX.

           PERFORM VARYING TAB-IDX FROM 1 BY 1 UNTIL TAB-IDX > CUR-MAX
              ....
           END-PERFORM
           IF CUR-MAX  = 10  GO TO DO-FETCH.
      
           EXEC SQL AT :CON
              CLOSE CSKEYTAB
           END-EXEC.

What currently happens is that the preprarser generates the reference "as it got", so the subscript is missing:

OCESQL*    EXEC SQL AT :CON
OCESQL*        FETCH CSKEYTAB
OCESQL*        INTO
OCESQL*          :T02-ID,
OCESQL*          :T02-STAMP
OCESQL*    END-EXEC.
OCESQL     CALL "OCESQLStartSQL"
OCESQL     END-CALL
OCESQL     CALL "OCESQLSetResultParams" USING
OCESQL         BY VALUE 16
OCESQL         BY VALUE 18
OCESQL         BY VALUE 0
OCESQL         BY REFERENCE T02-ID
OCESQL     END-CALL
OCESQL     CALL "OCESQLSetResultParams" USING
OCESQL         BY VALUE 16
OCESQL         BY VALUE 26
OCESQL         BY VALUE 0
OCESQL         BY REFERENCE T02-STAMP
OCESQL     END-CALL
OCESQL     CALL "OCESQLCursorFetchOne" USING
OCESQL         BY REFERENCE SQLCA
OCESQL         BY REFERENCE "PROG_CSKEYTAB" & x"00"
OCESQL     END-CALL
OCESQL     CALL "OCESQLEndSQL"
OCESQL     END-CALL.

which, of course raises a compiler error on both BY REFERENCE

just for reference - this is what procob does:

      *    EXEC SQL AT :CON
      *        FETCH CSKEY13NG
      *        INTO
      *          :T02-ID,
      *          :T02-STAMP
      *    END-EXEC.
           MOVE 10 TO SQL-ITERS
           MOVE 2429 TO SQL-OFFSET
           MOVE 0 TO SQL-OCCURS
           MOVE 1 TO SQL-SELERR
           MOVE 0 TO SQL-SQPMEM
           CALL "SQLADR" USING
               SQLCUD
               SQL-CUD
           CALL "SQLADR" USING
               SQLCA
               SQL-SQLEST
           MOVE 4352 TO SQL-SQLETY
           MOVE 0 TO SQL-SQFOFF
           MOVE 2 TO SQL-SQFMOD
           CALL "SQLADR" USING
               T02-ID IN
               T02-FETCHTAB(1)
               SQL-SQHSTV(1)
           MOVE 18 TO SQL-SQHSTL(1)
           MOVE 18 TO SQL-SQHSTS(1)
           MOVE 0 TO SQL-SQINDV(1)
           MOVE 0 TO SQL-SQINDS(1)
           MOVE 0 TO SQL-SQHARM(1)
           CALL "SQLADR" USING
               T02-STAMP IN
               T02-FETCHTAB(1)
               SQL-SQHSTV(2)
           MOVE 26 TO SQL-SQHSTL(2)
           MOVE 26 TO SQL-SQHSTS(2)
           MOVE 0 TO SQL-SQINDV(2)
           MOVE 0 TO SQL-SQINDS(2)
           MOVE 0 TO SQL-SQHARM(2)
           CALL "SQLADR" USING
               CON
               SQL-SQHSTV(3)
           MOVE 10 TO SQL-SQHSTL(3)
           MOVE 10 TO SQL-SQHSTS(3)
           MOVE 0 TO SQL-SQINDV(3)
           MOVE 0 TO SQL-SQINDS(3)
           MOVE 0 TO SQL-SQHARM(3)
           CALL "SQLADR" USING
               SQL-SQHSTV(1)
               SQL-SQPHSV
           CALL "SQLADR" USING
               SQL-SQHSTL(1)
               SQL-SQPHSL
           CALL "SQLADR" USING
               SQL-SQHSTS(1)
               SQL-SQPHSS
           CALL "SQLADR" USING
               SQL-SQINDV(1)
               SQL-SQPIND
           CALL "SQLADR" USING
               SQL-SQINDS(1)
               SQL-SQPINS
           CALL "SQLADR" USING
               SQL-SQHARM(1)
               SQL-SQPARM
           CALL "SQLADR" USING
               SQL-SQHARC(1)
               SQL-SQPARC

           CALL "SQLBEX" USING
               SQLCTX
               SQLEXD
               SQLFPN
               .

some checking in the OCESQL code showed that the preparser knows about the OCCURS attribute and there is OCESQLCursorFetchOccurs, but I have no clue if this is the part in the runtime that could handle that.

If there's already support for multi-row access: How does this need to be (re-)coded in COBOL?
If not - can you share any ETA for this feature?

Support for VARCHAR DB data type

I'd like to read and write to data defined as VARCHAR(100).
Ideally the data should always be padded to the COBOL field size on reading via SELECT and have an auto-trim on write / when used in the WHERE clause.

How to achieve that?

Note: using procob this was solved by defining the data asCHAR/VARCHAR in the database and using

           EXEC SQL VAR COBFIXNAME           IS CHARF     END-EXEC.
           EXEC SQL VAR COBVARNAME           IS VARCHAR2  END-EXEC.

in the COBOL program. Ideally this could be used with ocesql, too.

DECLARE CURSOR with `COMP-3` fields read not allocated memory

Seen by valgrind's memcheck. It would be very reasonable to have an extended testsuite #30 and run valgrind against it.
Here's its output of this case:


 Invalid read of size 2
    at 0x4C320E0: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1050)
    by 0x4E41848: add_cursor_list (ocesql.c:3477)
    by 0x4E41848: _ocesqlCursorDeclare (ocesql.c:1105)
    by 0x4E42A45: OCESQLIDCursorDeclareParams (ocesql.c:1073)
    by 0x4155F31A: PROG_ (PROG.cob:3762)
    by 0x4154180C: PROG (PROG.cob:941)
    by 0x4019FF: main (cobcrun.c:421)
  Address 0x43a89850 is 5 bytes after a block of size 11 alloc'd
    at 0x4C2B067: malloc (vg_replace_malloc.c:380)
    by 0x5F23949: strdup (in /usr/lib64/libc-2.17.so)
    by 0x4E3F873: create_realdata (ocesql.c:2757)
    by 0x4E44455: add_sql_var_list (ocesql.c:2425)
    by 0x4E44455: OCESQLSetSQLParams (ocesql.c:2203)
    by 0x4155EED5: PROG_ (PROG.cob:3738)
    by 0x4154180C: PROG (PROG.cob:941)

The issue is that add_sql_var_list() uses the correct data length to allocate the data, then using strdup() to get the data over (when it actually should use memcpy() for "data" as 00012.34 COMP-3 is x'0001234' and strdup() wouldn't copy anything at all), but add_cursor_list() uses memcpy to copy from this temporary field that has the correct data length (and up to correct data) with the real data length - so copies too much for anything that isn't USAGE DISPLAY.

scanning of variables does not end after `EXEC SQL END DECLARE`, leading to "Syntax error"

ocesql does not understand - and does not need to - all different variable types that exist and also does not know about REPLACE statements. It therefore does not (need to) know what to do with stuff like USAGE POINTER, ==ID==-VAR or even a simple OCCURS ... INDEXED BY; but currently the scanner does start at EXEC SQL BEGIN DECLARE and does not stop after EXEC SQL END DECLARE, therefore the parsing state get everything until WORKING STORAGE ends - and has to fail.

Intallation fails on Ubuntu

A sample program INSERTTBL in sample/ directory does not work on Ubuntu.

$ ocesql INSERTTBL.cbl INSERTTBL.cob
$ cobc -m -locesql INSERTTBL.cob
$ cobcrun INSERTTBL
*** INSERTTBL STARTED ***
libcob: Cannot find module 'OCESQLConnect'

In order to execute INSERTTBL, it is necessary to set the environment variable LD_PRELOAD to /usr/local/lib/libocesql.so

$ ocesql INSERTTBL.cbl INSERTTBL.cob
$ cobc -m -locesql INSERTTBL.cob
$ LD_PRELOAD=/usr/local/lib/libocesql.so cobcrun INSERTTBL

This problem is probably caused by an incorrect configuration of libocesql.so
The following Dockerfile describes the full installation process on Ubuntu.

FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update

RUN apt-get install -y build-essential libncurses5 libncurses5-dev libgmp-dev bison flex gettext automake autoconf git
RUN apt-get install -y libpq-dev

RUN cd /root && git clone https://github.com/opensourcecobol/opensource-cobol.git

RUN cd /root/opensource-cobol/vbisam &&\
    ./configure --prefix=/usr/ &&\
    make &&\
    make install &&\
    cd ../ &&\
    ./configure --prefix=/usr/ --with-vbisam &&\
    make &&\
    make install

ADD https://github.com/opensourcecobol/Open-COBOL-ESQL/archive/refs/tags/v1.2.tar.gz /root/Open-COBOL-ESQL-1.2.tar.gz
RUN cd /root &&\
    tar zxvf Open-COBOL-ESQL-1.2.tar.gz &&\
    cd Open-COBOL-ESQL-1.2 &&\
    ./configure &&\
    C_INCLUDE_PATH=/usr/include/postgresql/ make &&\
    make install

RUN cd /root/Open-COBOL-ESQL-1.2/sample &&\
    cp ../copy/* . &&\
    ocesql INSERTTBL.cbl INSERTTBL.cob &&\
    cobc -m -locesql INSERTTBL.cob  &&\
    LD_PRELOAD=/usr/local/lib/libocesql.so cobcrun INSERTTBL

ENTRYPOINT ["/bin/bash"]

configure script fails when source code is obtained with git clone command

configure script succeeds when source code is extract from a .tar.gz file in Release page.
Refer to https://github.com/yutaro-sakamoto/Open-COBOL-ESQL/actions/runs/1931459589

configure script fails when source code is obtained with git clone command.
Refer to https://github.com/yutaro-sakamoto/Open-COBOL-ESQL/actions/runs/1931485674

After executing 'touch *' command, configure script succeeds.

The cause may be related to time stamps of files.

Translation error with a source code containing a variable initialized to empty string.

Open-COBOL-ESQL cannot convert the following source code.
Open-COBOL-ESQL does not accept source code containing a variable initialized to an empty string.

       IDENTIFICATION              DIVISION.
       PROGRAM-ID.                 a.
       DATA                        DIVISION.
       WORKING-STORAGE             SECTION.
       01 VAL PIC X(5) VALUE "".
       PROCEDURE                   DIVISION.
           DISPLAY "Hello".
           STOP RUN.

If opensource COBOL compiles the source code, compiling succeeds while cobc displays warning messages.

a.cbl:5: Warning: Alphanumeric literal has zero length
a.cbl:5: Warning: A SPACE will be assumed

Issue with scanner.c

Hello,
While running the command 'make' I got this error:
/bin/sh ../ylwrap scanner.l .c scanner.c -- : make[2]: *** [scanner.c] Erreur 1

Before I had this one /bin/sh ../ylwrap parser.y y.tab.c parser.c y.tab.h parser.h y.output parser.output -- byacc byacc: e - line 20 of "/nfs/home/nelamrao/workspace/Labs/cobol/Open-COBOL-ESQL/ocesql/parser.y", syntax error %defines ^

Can you help please!

debug message (with wrong format) in parser.y

This one is in since the first version, the last refactoring change 211f15d#diff-b0bcf66ecc6091f6946729c4c217e7d3R907 did not adjust the original issue.

Things to check:

  • Why is that code in at all? Looks like something only a developer of ocesql wants to see.
  • What was the intend? If it was "has children" the correct code would be something like the following (currently it casts a pointer to an int value)
 printmsg("CHILDR:sname=%s, level=%d, occurs=%d, children=%d",
-	       field->sname, field->level, field->occurs, field->children);
+	       field->sname, field->level, field->occurs, field->children != NULL);

`COMP-3` variables lead to buffer overflow on assignment

Reason is in dblib/ocesql.c create_coboldata()'s handling for OCDB_TYPE_UNSIGNED_NUMBER_PD + OCDB_TYPE_SIGNED_NUMBER_PD- The size of the buffer is calculated as "packed data length", calloc()d, and afterwards the zero-padding and following code uses this as "real length". The fix is to use the "real data length" for allocation.

The best fix and more performance is provided by replacing the calloc/free parts for those buffers by a buffer with the maximum digit size (should likely be 38), either "local" or global via static array.

PostgreSQL Cursor Re-open error in GnuCOBOL

I am trying to move from Oracle to PostgreSQL on GnuCOBOL. I have a piece of code which uses cursors and need opening a cursor multiple times. However when trying to open the cursor again I get the error ERROR: cursor "fetchtbl_c1" already exists

    IDENTIFICATION              DIVISION.
    PROGRAM-ID.                 FETCHTBL.

    DATA                        DIVISION.
    WORKING-STORAGE             SECTION.
    01  D-SOC-REC.
        05  D-SOC-NO-1          PIC  X(3).
        05  FILLER              PIC  X.
        05  D-SOC-NO-2          PIC  X(3).

    EXEC SQL BEGIN DECLARE SECTION END-EXEC.
    01  USERNAME                PIC  X(30) VALUE SPACE.
    01  SOC-REC-VARS.
        05  SOC-NO-1            PIC X(3).
        05  SOC-NO-2            PIC X(3).
    EXEC SQL END DECLARE SECTION END-EXEC.

    EXEC SQL INCLUDE SQLCA END-EXEC.
    PROCEDURE                   DIVISION.
    MAIN-RTN.
        MOVE  SPACE             TO   USERNAME.
        EXEC SQL
            CONNECT :USERNAME
        END-EXEC.
        IF  SQLCODE NOT = ZERO DISPLAY "ERROR CONNECTING".

   *    DECLARE CURSOR
        EXEC SQL
            DECLARE C1 CURSOR FOR
            SELECT SOC_NO_1, SOC_NO_2
                   FROM INSP
                   ORDER BY SOC_NO_1
        END-EXEC.
        EXEC SQL
            OPEN C1
        END-EXEC.
        IF SQLCODE = ZERO DISPLAY "OPEN SUCCESSFUL"
        ELSE DISPLAY "OPEN FAILED".

   *    FETCH
        EXEC SQL
            FETCH C1 INTO :SOC-NO-1,:SOC-NO-2
        END-EXEC.
        IF SQLCODE = ZERO DISPLAY "FETCH SUCCESSFUL"
        ELSE DISPLAY "FETCH FAILED".
        PERFORM UNTIL SQLCODE NOT = ZERO
           MOVE  SOC-NO-1      TO    D-SOC-NO-1
           MOVE  SOC-NO-2      TO    D-SOC-NO-2
           DISPLAY D-SOC-REC
           EXEC SQL
               FETCH C1 INTO :SOC-NO-1,:SOC-NO-2
           END-EXEC
        END-PERFORM.

   *    CLOSE CURSOR
        EXEC SQL
            CLOSE C1
        END-EXEC.
        IF SQLCODE = ZERO DISPLAY "CLOSE SUCCESSFUL"
        ELSE DISPLAY "CLOSE FAILED".

   *    OPEN AGAIN
        EXEC SQL
            OPEN C1
        END-EXEC.
        IF SQLCODE = ZERO DISPLAY "REOPEN SUCCESSFUL"
        ELSE DISPLAY "REOPEN FAILED " SQLERRMC.
   *    COMMIT
        EXEC SQL
            COMMIT WORK
        END-EXEC.

   *    DISCONNECT
        EXEC SQL
            DISCONNECT ALL
        END-EXEC.

   *    END
        STOP RUN.

Pre-compiled the code using ocesql and compiled using cobc -x

Postgres Output

OPEN SUCCESSFUL
FETCH SUCCESSFUL
003 001
005 001
CLOSE SUCCESSFUL
REOPEN FAILED ERROR: cursor "fetchtbl_c1" already exists
The above code works perfectly fine (except for connection part) in Oracle.

Oracle output

OPEN SUCCESSFUL
FETCH SUCCESSFUL
003 001
CLOSE SUCCESSFUL
REOPEN SUCCESSFUL
I have tried searching on the internet but without any luck. Anybody can help me with this? I am using PostgreSQL version 10.3 and GnuCOBOL version 2.2.0.


I made the below fix and it works, please suggest if I can raise a PR for this?

I have put a fix in ocdb.c in function OCDBSetResultStatus to return a successful code in case there is not result resource (which happens for open cursor case).

This might not be entirely correct but after spending a few hours testing I see this working fine.

Code changes:

int
OCDBSetResultStatus(int id, struct sqlca_t *st){
struct s_conn *p_conn;
int retval;

p_conn = look_up_conn_lists(id);
if(p_conn == NULL){
  //return OCDB_RES_FATAL_ERROR;
    return RESULT_ERROR;
}
if(p_conn->resaddr == OCDB_RES_DEFAULT_ADDRESS){
    // 結果リソースが無いため成功で返す
    // Ankit: uncommented since there is no result resource,
    //        (true in case of open cursor)
    return OCDB_RES_COMMAND_OK;
    //return RESULT_ERROR;
}

#ifdef PGSQL_MODE_ON
retval = OCDB_PGSetResultStatus(p_conn->resaddr,st);
#endif
return retval;
}
Let me know if anybody faces any issues because of this change.

Original stackoverflow question that I had raised.

Parser brings an error on Ascending Clause

Hi,

on this statement the parser reports an error:

   01 T98-TAB.
     05 T98-ROWID-LAST        PIC  9(009) COMP-5 VALUE ZERO.
     05 T98-ROWID-NEW         PIC  9(009) COMP-5 VALUE ZERO.
     05 T98-TAB-CACHE  OCCURS 100
        DEPENDING ON Z-T98-EINTRAEGE
        ASCENDING KEY IS T98-ROWID
        INDEXED BY I-TAB.

I can only precompile the source, when I put this statements in an extry Cobol-Library.

Any suggestions?

Kind regards

Hans

Add ODBC support

The README says

Ocesql is currently supports PostgreSQL only

What do you think about adding support for unixODBC, allowing Ocesql to be used with a wide set of DBs?

`DECLARE CURSOR` cannot be used in `WORKING STORAGE` - and sets `SQLCODE`

This is a huge difference to every other EXEC SQL preprocessor I'm aware of and is likely to create issues when porting from an existing one.
Note: The GixSQL fork has a sample, so I assume it's scanner and parser handle those (warning: those are licensed GPLv3+ so the only way to include changes would be a license update; and the files are heavily changed because they use C++/QT instead of plain C).

I volunteer to work on identifying and integrating the relevant changes (under GPLv3+).

please provide release tarballs

issues like #10, #11 could be prevented by publishing release tarballs.
Please run make dist with a clean checkout and build of ocesql-1.2 and attach the result to https://github.com/opensourcecobol/Open-COBOL-ESQL/releases/tag/v1.2 - the current "assets" are only source snaphots and don't have the correct timestamps, which is the reason that bison, flex, automake and others are run - which should not be the case (both to prevent missing/mismatched toolset of those maintainer tools [= removing unnecessary dependencies] to break the build and to actually provide a tested release version).

Prepared statements: switch to use PQprepare / PQexecPrepared

Currently prepared statements are done manually. This seems to at least has the benefit of directly supporting cursor access to those (not sure if this would be possible "directly" otherwise), but has the downside of re-creating something libpg and the the DB has put in man-years of effort, not being able to see the prepared statements on the db side, ...

Doing this change would also fix #67 "for free".

add support to directly execute statements - EXECUTE IMMEDIATE

Feature Request

https://docs.oracle.com/cd/A97630_01/appdev.920/a96109/pco09dyn.htm#774
https://www.postgresql.org/docs/14/ecpg-dynamic.html

EXEC SQL
    EXECUTE IMMEDIATE 'some hard-coded sql here'
END-EXEC
EXEC SQL AT :dbs
    EXECUTE IMMEDIATE :stmt
END-EXEC

As a wide-supported way to execute something that has no bind parameters (only the statement if not given by literal) and no result set (The SQLCA structure would still be set, so checkingSQLCODE and friends still would be possible).
:stmt should be a "plain" pic x item, but it would be nice to optional be able to use a varlength group, too.


Workaround

use prepared statements, as this currently works only correct with varlength groups (tracked under #64) you need to change the statement definition first:

-       77 SQL-COMMAND  PIC X(50)
-            VALUE "DELETE FROM TESTTABLE WHERE I > ?".
+       01 SQL-COMMAND.
+         03 SQL-COMMAND-LEN PIC 9(9) VALUE 50.
+         03 SQL-COMMAND-ARR PIC X(50)
+            VALUE "DELETE FROM TESTTABLE WHERE I > ?".

and then use that in COBOL

      *  place statement to execute into SQL-COMMAND-ARR, then
           MOVE FUNCTION LENGTH(FUNCTION TRIM(SQL-COMMAND-ARR))
             TO SQL-COMMAND-LEN.
           EXEC SQL AT :DBS
               PREPARE P1 FROM :SQL-COMMAND
           END-EXEC.
      *
           IF SQLCODE NOT = 0
              DISPLAY "PREPARE ERROR"
              STOP RUN
           END-IF.
      *
           EXEC SQL AT :DBS
              EXECUTE P1
           END-EXEC.

consider to drop Open-COBOL-ESQL in favor of its fork/rewrite GixSQL

Reaching out to @opensourcecobol @n-isaka @ytr-sakamoto / @yutaro-sakamoto.
I know that this is a strange issue to post and please: don't be offended by it.

As Open-COBOL-ESQL was staled for years people have looked for alternatives and there is also one reasonable fork (heavy rewriting) that I'd consider to use instead: GixSQL ( see https://github.com/mridoni/gixsql with release tarballs and binaries at https://github.com/mridoni/gixsql/releases/latest / https://github.com/mridoni/gix/releases/latest ).

Other than "actively developed" and "provides release tarballs, provides release binaries" it also has nearly all issues open here fixed and also provides the optional binding to MySQL/MariaDB or ODBC and is verified to work on both GNU/Linux using GCC and also on Windows using either GCC or MSVC.

You could also "fork the fork", possibly naming it Open-COBOL-ESQL2 (if for some strange reason this is necessary) and/or actively work together.

There's only one single downside: it has a different (higher) dependency - a "reasonable new C++ compiler" (in case of GCC this would be GCC8, I think [this one works]); but if you just install the binaries that is no issue at all.

include error message in CONNECT errors

currently OCDB_PGConnect gets the error message - but only set it into the error log:

conn = PQconnectdb(conninfo);
if(conn == NULL){
return OCDB_CONN_FAIL_CONNECT;
} else if(PQstatus(conn) != CONNECTION_OK){
ERRLOG("%s\n",PQerrorMessage(conn));
PQfinish(conn);
return OCDB_CONN_FAIL_CONNECT;
}

It should either store the message somewhere for later lookup or the error message should be get later again to set it into SQLERRM.

The easiest way to reproduce: just specify a user that doesn't exist...

missing check for truncation of numeric data lead to "double free" or other memory errors

This is related to the "in progress" issue #31 and should ideally be solved together with that.

Given the code in

Open-COBOL-ESQL/dblib/ocesql.c

Lines 2789 to 3172 in 1b272b8

case OCDB_TYPE_UNSIGNED_NUMBER:
{
char *ptr;
int fillzero;
int zcount;
char *final;
int finalbuflen;
// fill zero
finalbuflen = sv->length + TERMINAL_LENGTH;
final = (char *)calloc(finalbuflen, sizeof(char));
// before decimal point
int beforedp = 0;
for(ptr = retstr; *ptr != '\0'; ptr++){
if(*ptr == '.'){
break;
} else {
beforedp++;
}
}
fillzero = sv->length - beforedp + sv->power;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
memcpy(final + fillzero, retstr, beforedp);
if(sv->power < 0){
int afterdp = 0;
if(*ptr != '\0'){
ptr++;
// after decimal point
for(; *ptr != '\0'; ptr++){
afterdp++;
}
// fill zero
memcpy(final + fillzero + beforedp,
retstr + beforedp + DECIMAL_LENGTH, afterdp);
}
fillzero = - sv->power - afterdp;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
}
memcpy(addr, final, sv->length);
free(final);
break;
}
case OCDB_TYPE_SIGNED_NUMBER_TC:
{
char *value;
char *ptr;
int is_negative = false;
int fillzero;
int zcount;
char *final;
int finalbuflen;
int final_length;
// fill zero
finalbuflen = sv->length;
final = (char *)calloc(finalbuflen, sizeof(char));
if(retstr[0] == '-'){
is_negative = true;
value = retstr + 1;
} else {
value = retstr;
}
// before decimal point
int beforedp = 0;
for(ptr = value; *ptr != '\0'; ptr++){
if(*ptr == '.'){
break;
} else {
beforedp++;
}
}
fillzero = sv->length - beforedp + sv->power;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
memcpy(final + fillzero, value, beforedp);
if(sv->power < 0){
int afterdp = 0;
if(*ptr != '\0'){
ptr++;
// after decimal point
for(; *ptr != '\0'; ptr++){
afterdp++;
}
memcpy(final + fillzero + beforedp, value +
beforedp + DECIMAL_LENGTH, afterdp);
}
// fill zero
fillzero = - sv->power - afterdp;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
}
final_length = strlen(final);
if(is_negative){
int index = *(final + (final_length - 1)) - '0';
final[final_length - 1] = type_tc_negative_final_number[index];
}
memcpy(addr, final, sv->length);
free(final);
break;
}
case OCDB_TYPE_SIGNED_NUMBER_LS:
{
char *value;
char *ptr;
int fillzero;
int zcount;
char *final;
int finalbuflen;
// fill zero
finalbuflen = SIGN_LENGTH + sv->length + TERMINAL_LENGTH;
final = (char *)calloc(finalbuflen, sizeof(char));
if(retstr[0] == '-'){
final[0] = '-';
value = retstr + 1;
} else {
final[0] = '+';
value = retstr;
}
// before decimal point
int beforedp = 0;
for(ptr = value; *ptr != '\0'; ptr++){
if(*ptr == '.'){
break;
} else {
beforedp++;
}
}
fillzero = sv->length - beforedp + sv->power;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
memcpy(final + SIGN_LENGTH + fillzero, value, beforedp);
if(sv->power < 0){
int afterdp = 0;
if(*ptr != '\0'){
ptr++;
// after decimal point
for(; *ptr != '\0'; ptr++){
afterdp++;
}
// fill zero
memcpy(final + SIGN_LENGTH + fillzero + beforedp,
value + beforedp + DECIMAL_LENGTH, afterdp);
}
fillzero = - sv->power - afterdp;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
}
memcpy(addr, final, sv->length + SIGN_LENGTH);
free(final);
break;
}
case OCDB_TYPE_UNSIGNED_NUMBER_PD:
{
char *value = retstr;
char *ptr;
int is_negative = false;
int fillzero;
int zcount;
char *pre_final;
int pre_final_len;
char *final;
double dlength;
int skip_first;
int i;
unsigned char ubit = 0xF0;
unsigned char lbit = 0x0F;
dlength = ceil(((double)sv->length + 1)/2);
skip_first = (sv->length + 1) % 2; // 1 -> skip first 4 bits
pre_final_len = sv->length + TERMINAL_LENGTH;
pre_final = (char *)calloc(pre_final_len, sizeof(char));
// before decimal point
int beforedp = 0;
for(ptr = value; *ptr != '\0'; ptr++){
if(*ptr == '.'){
break;
} else {
beforedp++;
}
}
fillzero = sv->length - beforedp + sv->power;
for(zcount = 0; zcount < fillzero; zcount++){
pre_final[zcount] = '0';
}
memcpy(pre_final + fillzero, value, beforedp);
if(sv->power < 0){
int afterdp = 0;
if(*ptr != '\0'){
ptr++;
// after decimal point
for(; *ptr != '\0'; ptr++){
afterdp++;
}
memcpy(pre_final + fillzero + beforedp,
value + beforedp + DECIMAL_LENGTH, afterdp);
}
// fill zero
fillzero = - sv->power - afterdp;
for(zcount = 0; zcount < fillzero; zcount++){
pre_final[zcount] = '0';
}
}
// format setting
final = (char *)calloc((int)dlength + TERMINAL_LENGTH, sizeof(char));
ptr = pre_final;
for(i=0; i<dlength; i++){
unsigned char vubit = 0x00;
unsigned char vlbit = 0x00;
if(i == 0 && skip_first){
vubit = 0x00;
} else {
vubit = (*ptr) << 4;
vubit = vubit & ubit;
ptr++;
}
if(i != dlength - 1){
vlbit = *ptr;
vlbit = vlbit & lbit;
ptr++;
} else {
vlbit = 0x0F;
}
final[i] = vubit | vlbit;
}
memcpy(addr, final, (int)dlength);
free(pre_final);
free(final);
break;
}
case OCDB_TYPE_SIGNED_NUMBER_PD:
{
char *value;
char *ptr;
int is_negative = false;
int fillzero;
int zcount;
char *pre_final;
int pre_final_len;
char *final;
double dlength;
int skip_first;
int i;
unsigned char ubit = 0xF0;
unsigned char lbit = 0x0F;
dlength = ceil((double)(sv->length + 1)/2);
skip_first = (sv->length + 1) % 2; // 1 -> skip first 4 bits
if(retstr[0] == '-'){
is_negative = true;
value = retstr + 1;
} else {
value = retstr;
}
pre_final_len = (int)dlength + TERMINAL_LENGTH;
pre_final = (char *)calloc(pre_final_len, sizeof(char));
// before decimal point
int beforedp = 0;
for(ptr = value; *ptr != '\0'; ptr++){
if(*ptr == '.'){
break;
} else {
beforedp++;
}
}
fillzero = sv->length - beforedp + sv->power;
for(zcount = 0; zcount < fillzero; zcount++){
pre_final[zcount] = '0';
}
memcpy(pre_final + fillzero, value, beforedp);
if(sv->power < 0){
int afterdp = 0;
if(*ptr != '\0'){
ptr++;
// after decimal point
for(; *ptr != '\0'; ptr++){
afterdp++;
}
memcpy(pre_final + fillzero + beforedp,
value + beforedp + DECIMAL_LENGTH, afterdp);
}
// fill zero
fillzero = - sv->power - afterdp;
for(zcount = 0; zcount < fillzero; zcount++){
pre_final[zcount] = '0';
}
}
// format setting
final = (char *)calloc((int)dlength + TERMINAL_LENGTH, sizeof(char));
ptr = pre_final;
for(i=0; i<dlength; i++){
unsigned char vubit = 0x00;
unsigned char vlbit = 0x00;
if(i == 0 && skip_first){
vubit = 0x00;
} else {
vubit = (*ptr) << 4;
vubit = vubit & ubit;
ptr++;
}
if(i != dlength - 1){
vlbit = *ptr;
vlbit = vlbit & lbit;
ptr++;
} else {
if(is_negative){
vlbit = 0x0D;
} else {
vlbit = 0x0C;
}
}
final[i] = vubit | vlbit;
}
memcpy(addr, final, (int)dlength);
free(pre_final);
free(final);
break;
}

  • the driver queries the data, for example with an integer type in the DB you may get 2147483647
  • it translates the data to its string value, so for our example "2147483647"
  • the library frontend takes this value and sets the COBOL data

... so far: totally correct.

The issue is that in all those places the local allocated buffer that is used to write the data to is allocated based on dlength - the length of the COBOL field, but the memcpy is based on the strlen(data), which can be bigger.

In the example above, given a COBOL definition of S9(8) we allocate 8 (+1 for strlen) bytes, but create_coboldata copies the 10 bytes from the data size (*ptr != '\0' / strlen()). In the case of OCDB_TYPE_SIGNED_NUMBER_TC:

Open-COBOL-ESQL/dblib/ocesql.c

Lines 2867 to 2881 in 1b272b8

// before decimal point
int beforedp = 0;
for(ptr = value; *ptr != '\0'; ptr++){
if(*ptr == '.'){
break;
} else {
beforedp++;
}
}
fillzero = sv->length - beforedp + sv->power;
for(zcount = 0; zcount < fillzero; zcount++){
final[zcount] = '0';
}
memcpy(final + fillzero, value, beforedp);

we compute fillzero which will end up with -2 and then copy the data "two bytes before the allocated buffer".

If this does not crash the memory layout, then the end result looks correct (left-truncation).

As seen above the truncation must be explicit checked, both to return the correct values and even more important to don't trash the memory.

And very likely after the data is stored with COBOL correct truncation an sqlcode for "field truncated" should be set.

Test ocesql's output

Testsuite checks program executions results, but not output of ocesql command.
Testsuite should check both.

"configure" fails on Ubuntu 22.04 LTS (WSL2)

https://gnucobol.sourceforge.io/faq/index.html#does-gnucobol-support-any-sql-databases
suggests "Coded for ./configure; make; make check && sudo make install"

https://github.com/opensourcecobol/Open-COBOL-ESQL/blob/master/README#L77
suggests the same thing

Postgres is installed:

libpq5/jammy-updates,jammy-security,now 14.7-0ubuntu0.22.04.1 amd64 [installed,automatic]
postgis/jammy,now 3.2.0+dfsg-1ubuntu1 amd64 [installed]
postgis-doc/jammy,now 3.2.0+dfsg-1ubuntu1 all [installed,automatic]
postgresql/jammy,now 14+238 all [installed]
postgresql-14/jammy-updates,jammy-security,now 14.7-0ubuntu0.22.04.1 amd64 [installed,automatic]
postgresql-14-postgis-3/jammy,now 3.2.0+dfsg-1ubuntu1 amd64 [installed]
postgresql-14-postgis-3-scripts/jammy,now 3.2.0+dfsg-1ubuntu1 all [installed]
postgresql-client-14/jammy-updates,jammy-security,now 14.7-0ubuntu0.22.04.1 amd64 [installed,automatic]
postgresql-client-common/jammy,now 238 all [installed,automatic]
postgresql-common/jammy,now 238 all [installed,automatic]
postgresql-contrib/jammy,now 14+238 all [installed]

I've also done:

sudo apt install postgresql-server-dev-14
sudo apt install g++

"postgresql-server-dev-14" brought in "libpq-dev" among other things, and:

$ find /usr/include -name libpq-fe.h -print
/usr/include/postgresql/libpq-fe.h

I configure and make:
./configure
(snip)

$ make
make  all-recursive
make[1]: Entering directory '/home/ajtown/src/Open-COBOL-ESQL'
Making all in dblib
make[2]: Entering directory '/home/ajtown/src/Open-COBOL-ESQL/dblib'
/bin/bash ../libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I..    -lpq -O2 -MT ocesql.lo -MD -MP -MF .deps/ocesql.Tpo -c -o ocesql.lo ocesql.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -lpq -O2 -MT ocesql.lo -MD -MP -MF .deps/ocesql.Tpo -c ocesql.c  -fPIC -DPIC -o .libs/ocesql.o
In file included from ocdb.h:33,
             from ocesql.h:22,
             from ocesql.c:29:
ocpgsql.h:21:10: fatal error: libpq-fe.h: No such file or directory
   21 | #include <libpq-fe.h>
      |          ^~~~~~~~~~~~
compilation terminated.
make[2]: *** [Makefile:418: ocesql.lo] Error 1
make[2]: Leaving directory '/home/ajtown/src/Open-COBOL-ESQL/dblib'
make[1]: *** [Makefile:393: all-recursive] Error 1
make[1]: Leaving directory '/home/ajtown/src/Open-COBOL-ESQL'
make: *** [Makefile:324: all] Error 2

Any suggestions?

OpenCobol IDE

Can somebody provide us pls. how to include ESQL into the OpenCobol IDE?

Thanks/regards
Gabor

How to work with bytea / lob

Is it possible to work on these with PIC_VARYING?

For people that don't know about the internal types: to handle VARCHAR without explicit space trim/pad it is already possible to declare a host variable as "PIC X VARYING" the following way:

01 BINARY-DB-FIELD     PIC X(50000) VARYING.

and the preparser then converts that to

01 BINARY-DB-FIELD.
    03 BINARY-DB-FIELD-LEN   PIC S9(8) COMP-5.
    03 BINARY-DB-FIELD-ARR   PIC X(50000).

Within the COBOL program, before/after using the host variable :BINARY-DB-FIELD the length is then set/read.

The question is: Can that be handled the same way with the PostgreSQL data types bytea (think "as blobs") and /or with lob?

... second check: before this is done specification of variable types seems to be necessary to be added first, in this case:

EXEC SQL    VAR BINARY-DB-FIELD IS VARBINARY END-EXEC

... or the DB2 variant:

01 BINARY-DB-FIELD     SQLTYPE IS VARBINARY(50000).

missing COPYING.LIB

The README file says to refer to COPYING.LIB for license details of programs in the dblib subdirectory, but that file does not actually exist.

bug: missing error (return code) for unknown fields

given

           EXEC SQL  FETCH SOMETHING INTO :FIELD END-EXEC.
      *
           IF SQLCODE = 0

resulted in

OCESQL*    EXEC SQL  FETCH SOMETHING INTO :FIELD END-EXEC.
OCESQL     CALL "OCESQLStartSQL"
OCESQL     END-CALL
      *
           IF SQLCODE = 0

The reason in this case was that FIELD was not contained in the variables visible to the parser (copybook instead of SQL INCLUDE, possibly because of missing support for #91).
The code generation should raise a clear error here "unknown bind variable :FIELD".

... rechecking the code - this happens here:

com_sprintf(buff,sizeof(buff), "OCESQL%5sCALL \"OCESQLStartSQL\"\nOCESQL%5sEND-CALL\n"," "," ");
fputs(buff, outfile);
host_list = list->host_list;
int count = 0;
if(host_list){
iret = gethostvarianttype(host_list->hostreference, &type, &digits, &scale);
if(iret != 0){
printmsg("%s:%d\n", host_list->hostreference,iret);
memset(buff, 0, sizeof(buff));
com_sprintf(buff,sizeof(buff), "E%03d",iret);
printerrormsg(host_list->hostreference, host_list->lineno,
buff);
return;

and there is indeed an output:

00234:E001:FIELD is not defined in the working-storage !

... but as ocesql still returns 0 and the message is placed to stdout this is easy to miss

FR: Support for ANSI Dynamic SQL

See full test program https://redirect.cs.umbc.edu/portal/help/oracle8/server.815/a68023/sqlansi.htm#1005697

            EXEC SQL ALLOCATE DESCRIPTOR 'in' END-EXEC.
            EXEC SQL ALLOCATE DESCRIPTOR 'out' END-EXEC.
            EXEC SQL PREPARE s FROM :DYN-STATEMENT END-EXEC.
            EXEC SQL DESCRIBE INPUT s USING DESCRIPTOR 'in' END-EXEC.
            EXEC SQL SET DESCRIPTOR 'in' VALUE 1 TYPE=:DEPTNO-TYP,
               LENGTH=:DEPTNO-LEN, DATA=:DEPTNO-DAT END-EXEC.
            EXEC SQL DECLARE c CURSOR FOR s END-EXEC.
            EXEC SQL OPEN c USING DESCRIPTOR 'in' END-EXEC.   -- syntax error, unexpected TOKEN, expecting host-variable
            EXEC SQL DESCRIBE OUTPUT s USING DESCRIPTOR 'out' END-EXEC.
            EXEC SQL SET DESCRIPTOR 'out' VALUE 1 TYPE=:ENAME-TYP, 
               LENGTH=:ENAME-LEN, DATA=:ENAME-DAT END-EXEC.
            EXEC SQL SET DESCRIPTOR 'out' VALUE 2 TYPE=:EMPNO-TYP, 
               LENGTH=:EMPNO-LEN, DATA=:EMPNO-DAT END-EXEC.

As this is an optional clause and not "directly" included as a sample in this doc - the following also raises a syntax error:

           EXEC SQL
                     DESCRIBE BIND VARIABLES FOR S1 INTO BNDDSC
           END-EXEC.
      *
           IF SQLDFND IN BNDDSC < 0
              DISPLAY "ERROR BIND VARIABLES!"
              EXIT PROGRAM
           ELSE
              MOVE SQLDFND IN BNDDSC TO SQLDNUM IN BNDDSC
              MOVE SQLDFND IN BNDDSC TO VAR-COUNT
              DISPLAY "NUMBER OF BIND VARIABLES: " VAR-COUNT
           END-IF.
      *
           EXEC SQL  DESCRIBE SELECT LIST FOR S1 INTO SELDSC  END-EXEC.
      *

Also see the PostgreSQL documentation about using descriptors with epcg.

When ocesql converts queries it repeats variable names, so then the cobol compiler will not compile

Hi

May be this bug is a bit hard to explein but I will try
It happens when in a query you use structured variables like this

01 TRANSACTION
. . 03 ID
. . 03 AMOUNT

01 CUSTUMER
. . 03 ID
. . 03 NAME

PROBLEM:
Both structured variables has a subfield ID. Same name for both. This is valid in cobol but ocesql tis not aware of it

Example:
When you use the TRANSACTION.ID on a query:

SELECT T.AMOUNT
FROM TRANSACTIONS T
INTO :TRANSACTION-AMOUNT
WHERE T.ID = :TRANSACTION.ID

This last variable :TRANSACTION.ID will casuse the problem since ID varrable has the same name on TRANSACTION as in CUSTOMER structured varables

When this is translated by ocesql it does this
OCESQL CALL "OCESQLSetSQLParams" USING
OCESQL BY VALUE 9
OCESQL BY VALUE 9
OCESQL BY VALUE 0
OCESQL BY REFERENCE ID <---- PROBLEM this is wrong since the compiler wont realize whose ID is it (Transaction´s or Cusromers´s ?)

The correct way to do this would have been to consider the structured variable name for level 01. This means to be done like this

OCESQL BY REFERENCE ID OF TRANSACTION

Of course if you name all variables with different names you wont have this problem, but this is not the way the COBOL variables works since sctrucured variables with rerpeated names are used a lot in cobol. Theres lots of programs already written like this, so changing them its not the best option. I think it should be better to fix it on ocesql

I hope mi explanation was clear enough, but feel free to ask for further information
Could yoiy please fix this issue because its very important, specially for already written probrams that will change only the queries from oracle to porstrgres

Thanks
Regards

signed `DISPLAY` lead to buffer overflow by 1

dblib/ocesql; create_coboldata()'s code for OCDB_TYPE_SIGNED_NUMBER_TC writes one byte too much (including the trailing sign - which does not apply here); similar to #31, but in this case into the program's storage.

Can't compile ESQL on Ubuntu

There is a problem in ./configure that I can't figure out. (I have fixed quite a lot of missing tools).

This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by Open COBOL ESQL configure 1.2, which was
generated by GNU Autoconf 2.69. Invocation command line was

$ ./configure

---------

Platform.

---------

hostname = Chicago
uname -m = x86_64
uname -r = 4.15.0-101-generic
uname -s = Linux
uname -v = #102-Ubuntu SMP Mon May 11 10:07:26 UTC 2020

/usr/bin/uname -p = unknown
/bin/uname -X = unknown

/bin/arch = unknown
/usr/bin/arch -k = unknown
/usr/convex/getsysinfo = unknown
/usr/bin/hostinfo = unknown
/bin/machine = unknown
/usr/bin/oslevel = unknown
/bin/universe = unknown

PATH: /home/andrew/bin
PATH: /home/andrew/.local/bin
PATH: /home/andrew/Computing/android-studio/bin
PATH: /usr/local/sbin
PATH: /usr/local/bin
PATH: /usr/sbin
PATH: /usr/bin
PATH: /sbin
PATH: /bin
PATH: /usr/games
PATH: /usr/local/games
PATH: /snap/bin

-----------

Core tests.

-----------

configure:2612: checking for a BSD-compatible install
configure:2680: result: /usr/bin/install -c
configure:2691: checking whether build environment is sane
configure:2746: result: yes
configure:2897: checking for a thread-safe mkdir -p
configure:2936: result: /bin/mkdir -p
configure:2943: checking for gawk
configure:2959: found /usr/bin/gawk
configure:2970: result: gawk
configure:2981: checking whether make sets $(MAKE)
configure:3003: result: yes
configure:3032: checking whether make supports nested variables
configure:3049: result: yes
configure:3290: checking for C++ compiler version
configure:3299: /usr/bin/cpp --version >&5
cpp (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

configure:3310: $? = 0
configure:3299: /usr/bin/cpp -v >&5

1 ""

1 ""

1 ""

31 ""

1 "/usr/include/stdc-predef.h" 1 3 4

32 "" 2

1 ""

Using built-in specs.
COLLECT_GCC=/usr/bin/cpp
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu118.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1
18.04)
COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/7/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu - -mtune=generic -march=x86-64 -fstack-protector-strong -Wformat -Wformat-security
... rest of stderr output deleted ...
configure:3310: $? = 0
configure:3299: /usr/bin/cpp -V >&5
cpp: error: unrecognized command line option '-V'
configure:3310: $? = 1
configure:3299: /usr/bin/cpp -qversion >&5
cpp: error: unrecognized command line option '-qversion'; did you mean '--version'?
configure:3310: $? = 1
configure:3330: checking whether the C++ compiler works
configure:3352: /usr/bin/cpp conftest.cpp >&5

1 "conftest.cpp"

1 ""

1 ""

1 "/usr/include/stdc-predef.h" 1 3 4

1 "" 2

1 "conftest.cpp"

12 "conftest.cpp"

int
main ()
{

;
return 0;
}
configure:3356: $? = 0
configure:3394: result: no
configure: failed program was:
| /* confdefs.h /
| #define PACKAGE_NAME "Open COBOL ESQL"
| #define PACKAGE_TARNAME "open-cobol-esql"
| #define PACKAGE_VERSION "1.2"
| #define PACKAGE_STRING "Open COBOL ESQL 1.2"
| #define PACKAGE_BUGREPORT "[email protected]"
| #define PACKAGE_URL ""
| #define PACKAGE "open-cobol-esql"
| #define VERSION "1.2"
| /
end confdefs.h. */
|
| int
| main ()
| {
|
| ;
| return 0;
| }
configure:3399: error: in /home/andrew/Software/COBOL/ESQL': configure:3401: error: C++ compiler cannot create executables See config.log' for more details

----------------

Cache variables.

----------------

ac_cv_env_CCC_set=
ac_cv_env_CCC_value=
ac_cv_env_CC_set=
ac_cv_env_CC_value=
ac_cv_env_CFLAGS_set=
ac_cv_env_CFLAGS_value=
ac_cv_env_CPPFLAGS_set=
ac_cv_env_CPPFLAGS_value=
ac_cv_env_CPP_set=
ac_cv_env_CPP_value=
ac_cv_env_CXXCPP_set=
ac_cv_env_CXXCPP_value=
ac_cv_env_CXXFLAGS_set=
ac_cv_env_CXXFLAGS_value=
ac_cv_env_CXX_set=set
ac_cv_env_CXX_value=/usr/bin/cpp
ac_cv_env_LDFLAGS_set=
ac_cv_env_LDFLAGS_value=
ac_cv_env_LIBS_set=
ac_cv_env_LIBS_value=
ac_cv_env_LT_SYS_LIBRARY_PATH_set=
ac_cv_env_LT_SYS_LIBRARY_PATH_value=
ac_cv_env_YACC_set=
ac_cv_env_YACC_value=
ac_cv_env_YFLAGS_set=
ac_cv_env_YFLAGS_value=
ac_cv_env_build_alias_set=
ac_cv_env_build_alias_value=
ac_cv_env_host_alias_set=
ac_cv_env_host_alias_value=
ac_cv_env_target_alias_set=
ac_cv_env_target_alias_value=
ac_cv_path_install='/usr/bin/install -c'
ac_cv_path_mkdir=/bin/mkdir
ac_cv_prog_AWK=gawk
ac_cv_prog_make_make_set=yes
am_cv_make_support_nested_variables=yes

-----------------

Output variables.

-----------------

ACLOCAL='${SHELL} /home/andrew/Software/COBOL/ESQL/missing aclocal-1.15'
ALLOCA=''
AMDEPBACKSLASH=''
AMDEP_FALSE=''
AMDEP_TRUE=''
AMTAR='$${TAR-tar}'
AM_BACKSLASH=''
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
AM_DEFAULT_VERBOSITY='1'
AM_V='$(V)'
AR=''
AUTOCONF='${SHELL} /home/andrew/Software/COBOL/ESQL/missing autoconf'
AUTOHEADER='${SHELL} /home/andrew/Software/COBOL/ESQL/missing autoheader'
AUTOMAKE='${SHELL} /home/andrew/Software/COBOL/ESQL/missing automake-1.15'
AWK='gawk'
CC=''
CCDEPMODE=''
CFLAGS=''
CPP=''
CPPFLAGS=''
CXX='/usr/bin/cpp'
CXXCPP=''
CXXDEPMODE=''
CXXFLAGS=''
CYGPATH_W='echo'
DEFS=''
DEPDIR=''
DISABLE_OCESQL_FALSE=''
DISABLE_OCESQL_TRUE=''
DLLTOOL=''
DSYMUTIL=''
DUMPBIN=''
ECHO_C=''
ECHO_N='-n'
ECHO_T=''
EGREP=''
EXEEXT=''
FGREP=''
GREP=''
INSTALL_DATA='${INSTALL} -m 644'
INSTALL_PROGRAM='${INSTALL}'
INSTALL_SCRIPT='${INSTALL}'
INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
LD=''
LDFLAGS=''
LEX=''
LEXLIB=''
LEX_OUTPUT_ROOT=''
LIBOBJS=''
LIBS=''
LIBTOOL=''
LIPO=''
LN_S=''
LTLIBOBJS=''
LT_SYS_LIBRARY_PATH=''
MAKEINFO='${SHELL} /home/andrew/Software/COBOL/ESQL/missing makeinfo'
MANIFEST_TOOL=''
MKDIR_P='/bin/mkdir -p'
NM=''
NMEDIT=''
OBJDUMP=''
OBJEXT=''
OTOOL64=''
OTOOL=''
PACKAGE='open-cobol-esql'
PACKAGE_BUGREPORT='[email protected]'
PACKAGE_NAME='Open COBOL ESQL'
PACKAGE_STRING='Open COBOL ESQL 1.2'
PACKAGE_TARNAME='open-cobol-esql'
PACKAGE_URL=''
PACKAGE_VERSION='1.2'
PATH_SEPARATOR=':'
RANLIB=''
SED=''
SET_MAKE=''
SHELL='/bin/bash'
STRIP=''
VERSION='1.2'
YACC=''
YFLAGS=''
ac_ct_AR=''
ac_ct_CC=''
ac_ct_CXX=''
ac_ct_DUMPBIN=''
am__EXEEXT_FALSE=''
am__EXEEXT_TRUE=''
am__fastdepCC_FALSE=''
am__fastdepCC_TRUE=''
am__fastdepCXX_FALSE=''
am__fastdepCXX_TRUE=''
am__include=''
am__isrc=''
am__leading_dot='.'
am__nodep=''
am__quote=''
am__tar='$${TAR-tar} chof - "$$tardir"'
am__untar='$${TAR-tar} xf -'
bindir='${exec_prefix}/bin'
build=''
build_alias=''
build_cpu=''
build_os=''
build_vendor=''
datadir='${datarootdir}'
datarootdir='${prefix}/share'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
dvidir='${docdir}'
exec_prefix='NONE'
host=''
host_alias=''
host_cpu=''
host_os=''
host_vendor=''
htmldir='${docdir}'
includedir='${prefix}/include'
infodir='${datarootdir}/info'
install_sh='${SHELL} /home/andrew/Software/COBOL/ESQL/install-sh'
libdir='${exec_prefix}/lib'
libexecdir='${exec_prefix}/libexec'
localedir='${datarootdir}/locale'
localstatedir='${prefix}/var'
mandir='${datarootdir}/man'
mkdir_p='$(MKDIR_P)'
oldincludedir='/usr/include'
pdfdir='${docdir}'
prefix='NONE'
program_transform_name='s,x,x,'
psdir='${docdir}'
runstatedir='${localstatedir}/run'
sbindir='${exec_prefix}/sbin'
sharedstatedir='${prefix}/com'
sysconfdir='${prefix}/etc'
target_alias=''

-----------

confdefs.h.

-----------

/* confdefs.h */
#define PACKAGE_NAME "Open COBOL ESQL"
#define PACKAGE_TARNAME "open-cobol-esql"
#define PACKAGE_VERSION "1.2"
#define PACKAGE_STRING "Open COBOL ESQL 1.2"
#define PACKAGE_BUGREPORT "[email protected]"
#define PACKAGE_URL ""
#define PACKAGE "open-cobol-esql"
#define VERSION "1.2"

configure: exit 77

Warning messages when building Open-COBOL-ESQL

The following warning messages appear when building with make command.

ocpgsql.c: In function 'OCDB_PGCursorFetchOccurs':
ocpgsql.c:292:29: warning: implicit declaration of function 'log10' [-Wimplicit-function-declaration]
  292 |  str_fetchcount_size = (int)log10(fetchcount) + 1 + 1;
      |                             ^~~~~
ocpgsql.c:292:29: warning: incompatible implicit declaration of built-in function 'log10'
ocpgsql.c:26:1: note: include '<math.h>' or provide a declaration of 'log10'
   25 | #include "ocdbutil.h"
  +++ |+#include <math.h>
   26 |
ocpgsql.c: In function 'OCDB_PGcmdtuples':
ocpgsql.c:359:11: warning: implicit declaration of function 'atoi'; did you mean 'atooid'? [-Wimplicit-function-declaration]
  359 |   return  atoi(result);
      |           ^~~~
      |           atooid
ocesqlutil.c: In function 'com_readline':
ocesqlutil.c:152:3: warning: implicit declaration of function 'printmsg'; did you mean 'printf'? [-Wimplicit-function-declaration]
  152 |   printmsg("com_readline: although EOF wasn't detected, fgets() returned NULL ");
      |   ^~~~~~~~
      |   printf
ppout.c: In function 'ppbuff_incfile':
ppout.c:1976:37: warning: '%s' directive writing up to 511 bytes into a region of size 169 [-Wformat-overflow=]
 1976 |   sprintf(incmsg, "%s incfile start:%s", INC_START_MARK, filename);
      |                                     ^~                   ~~~~~~~~
ppout.c:1976:3: note: 'sprintf' output between 88 and 599 bytes into a destination of size 256
 1976 |   sprintf(incmsg, "%s incfile start:%s", INC_START_MARK, filename);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ppout.c:2002:35: warning: '%s' directive writing up to 511 bytes into a region of size 171 [-Wformat-overflow=]
 2002 |   sprintf(incmsg, "%s incfile end:%s",INC__END__MARK , filename);
      |                                   ^~                   ~~~~~~~~
ppout.c:2002:3: note: 'sprintf' output between 86 and 597 bytes into a destination of size 256
 2002 |   sprintf(incmsg, "%s incfile end:%s",INC__END__MARK , filename);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

performance issue - and easy fix

OCESQLSetResultParams take ~ 20% in some tested batch programs - and nearly all of this time is spend in add_sql_res_var_list. And ~15% of the cpu time is only spend in the following loop (here: line 2407)

Open-COBOL-ESQL/dblib/ocesql.c

Lines 2407 to 2409 in eec3a23

while(p->next != NULL){
p = p->next;
}

The simple solution: add another var next to _sql_var_lists that contains the last current entry, set it likely only in the same function, use it instead of the loop. Result: 14% cpu time saved.

Unexpected value

While building CI pipeline am getting error like unexpected value 'on'

FR: allow multple include paths and `-I` short option

currently there is only "none" or "exactly one":

Open-COBOL-ESQL/ocesql/ppout.c

Lines 1967 to 1973 in eec3a23

if(include_path){
com_sprintf(filename,sizeof(filename), "%s/", include_path);
}
com_strcat(filename,sizeof(filename), l->incfileName);
incf = fopen_or_die(filename, "r");

if(strcmp("inc", opthead) == 0){
if(optval != NULL){
include_path = com_strdup(optval);
} else {
printf("invalid option: --inc is get directory path parameter.\n");
}

(side note: if specified multiple times then each tie there is memory allocated, but it is never freed, nor an error displayed that --inc may be only used once)

FR: allow to use -I as alias for --inc and allow to specify multiple ones.

last input line is included multiple times in the output file

if that is a copybook with a section you get a "redefinition error" from the compiler
workaround: add a line below the copybook with just a comment, gets translated from

      *

(line with line separator)

to

      *      *      *      *

(line without line separator)

but the only result is a compile warning "line not terminated by a newline", so I don't mind

prepared statements: explicit support for `EXEC SQL DEALLOCATE PREPARE name`

The PG documentation and others always specify "When you don't need the prepared statement anymore, you should deallocate it".

Trying it wiuth ocesql raises an error about unknown prepared statements - the reason behind this is that all prepared statements in ocesql are not handled by the DB, but in the DB lib (for whatever historic reason).

Still the prepared statements need memory, at least the prepare_list entry.

So to both circumvent strange errors from the DB about prepared statements not being known and to prevent resource leak I suggest to add EXEC SQL DEALLOCATE PREPARE to the parser and create a matching OCESQLPrepareDeallocate which will be called and free resources + drop the entry out of the internal list.

trouble compiling

Hi-

I tried to compile ocesql, but I got told that my version is too new. I use cygwin. I think I remember that libtool is the wrong version when i tried to run ./configure. The way I read it is that maybe ocesql might be so old that new cygwin files for building won't work with it.

Hi again- I edited this so you can see the error msg. THX!

$ make
make all-recursive
make[1]: Entering directory '/home/mtdew3q/ocesql'
Making all in dblib
make[2]: Entering directory '/home/mtdew/ocesql/dblib'
/bin/sh ../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -g -lpq -MT ocesql.lo -MD -MP -MF .deps/ocesql.Tpo -c -o ocesql.lo ocesql.c
../libtool: line 1314: func_opt_split: command not found
libtool: Version mismatch error. This is libtool 2.2.6b, but the
libtool: definition of this LT_INIT comes from libtool 2.4.6.
libtool: You should recreate aclocal.m4 with macros from libtool 2.2.6b
libtool: and run autoconf again.
make[2]: *** [Makefile:343: ocesql.lo] Error 63
make[2]: Leaving directory '/home/mtdew/ocesql/dblib'
make[1]: *** [Makefile:327: all-recursive] Error 1
make[1]: Leaving directory '/home/mtdew/ocesql'
make: *** [Makefile:258: all] Error 2

I also wanted to mention that I am actively trying to learn cobol. I am not a guru. I figured out how to use direct postgresql sample from gnucobol thx. to brian tiffin, but it is nowhere near as cool as ocesql!

thx- 3rdshiftcoder

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.