Mapepire-IBMi / mapepire-server

Server-side support for Code for IBM i
GNU General Public License v3.0
23 stars 10 forks source link

Problem Calling External Stored Procedures w/Long CLOB Input #82

Open DavidRusso opened 1 month ago

DavidRusso commented 1 month ago

Hi,

Not sure if this is a client or server issue, but I thought I would start here.

Using client version 0.3.0 (also happens in current master) and server version 2.1.2-1, I'm unable to call stored procedures that are implemented as ILE C++ service programs and pass long CLOB input data.

Example service program source code:

/*
  CRTCPPMOD MODULE(YOURLIB/TESTPROC) SRCSTMF('/home/bob/testproc.cpp') DBGVIEW(*ALL)
  CRTSRVPGM SRVPGM(YOURLIB/TESTPROC) EXPORT(*ALL)
  RUNSQLSTM SRCSTMF('/home/bob/testproc.sql')
*/
#include <sqludf.h>
#include <string.h>

extern "C" void testproc(const SQLUDF_CLOB * in,
                         SQLUDF_CLOB * out,
                         const SQLUDF_NULLIND * null_in,
                         SQLUDF_NULLIND * null_out,
                         SQLUDF_CHAR * sqlState,
                         const SQLUDF_VARCHAR * qualProcName,
                         const SQLUDF_VARCHAR * specProcName,
                         SQLUDF_VARCHAR * message) {

  out->length = 1;
  if (in->length == 1 && *in->data == '1') {
    *out->data = '2';
  }
  else {
    *out->data = '3';
  }

}

And SQL script:

create or replace procedure YOURLIB/testproc
(
  in in_json clob(128K),
  out out_json clob(128K)
)
language c++
specific YOURLIB/testproc
parameter style sql
not deterministic
dynamic result sets 0
program type sub
no dbinfo
not fenced
external name '"YOURLIB"/TESTPROC(testproc)';

Calling procedure like this in TS code works correctly:

  const job = new SQLJob();
  await job.connect(creds);

  const queryA = job.query<any[]>(`call qsys2.qcmdexc('chglibl libl(YOURLIB)')`);
  await queryA.execute();
  await queryA.close();

  const param = "1";
  const queryB = job.query<any[]>(
    `call drusso.testproc(?, ?)`,
    { parameters: [param, ""] }
  );
  const result = await queryB.execute();
  await queryB.close();

But, if I change the length of the input parameter data like this:

const param = "1".repeat(65535);

Then the queryB.execute() method "hangs up". By this, I mean that the returned Promise never resolves nor rejects.

On the server side, there are no messages in the connection's QZDASOINIT job. The job appears to be reset and ready for new connection -- for example the job log is cleared out, even the "library list changed'" message produced by the above CHGLIBL call disappears. Also no messages in the MAPEPIRE server job logs or in the log stream file specified by sc.

Interestingly, this problem does NOT occur when calling procedures with same parameter types/lengths when the stored procedure is defined purely with SQL. It seems to relate to procs defined by external ILE service programs.

I also tried parameter style general with same result.

worksofliam commented 1 month ago

Appreciate the detailed issue. This is a server bug, so I am transferring to the correct repository. Nonetheless, I have scheduled sometime to look at this. Thanks!