call invoke - output longchar

Posted by Marian Edu on 20-Oct-2015 01:49

maybe a known issue or never meant to work that way, should I stop banging my head on the wall?

when using call interface one can use a buffer field handle (well it's buffer-value, odd enough) for input-output/output parameters so just went ahead and created a temp-table with one field for each io/o parameters and pass those fields to set-parameter method.

it works like a charm for any primitive data-type, not so much for longchar and most probably neither for memptr... was mapping the longchar to clob and memptr to blob fields, calling invoke doesn't raise any error (like mismatch parameters) but the field value remains null (?).

def var hc as handle.

def temp-table tt no-undo
  field flchar as clob
  field fint   as integer.

create tt.
tt.fint = 10.
/* tt.flchar = 'help'. */


create call hc.
hc:call-name('test.p'). 
hc:num-parameters = 2.
hc:set-parameter(1, 'longchar', 'output', 
   temp-table tt:default-buffer-handle::flchar).
hc:set-parameter(2, 'integer', 'output', 
   temp-table tt:default-buffer-handle::flchar).
hc:invoke().

delete object hc.
message tt:fint skip string(tt.flchar) view-as alert-box.

the test look like this:

def output param plchar as longchar.
def output param pint   as integer.

plchar = 'hello'.
pint = 1234.

the result I get back is OK for integer (or any other primitive data-type), nothing set in clob field, no error thrown.

funny thing is if I set some value in the field before invoke it does throw an error:
bfx: Field too large for a data item. Try to increase -s. (42)


OE 11.5, windows 32/linux 64 all the same :(

something else I can try beside falling back to a longchar array and set a maximum for longchar output parameters?

All Replies

Posted by pliscki on 20-Oct-2015 07:23

Hi Marian,

If you try to run the same procedure with static code it will raise the following error:

Cannot pass large objects as runtime parameters. (14449)

Check what the documentation says about CLOB fields:

CLOB (Character Large OBject) specifies a database table or temp-table field that contains a CLOB locator, which points to the associated CLOB data stored in the database. You must use a LONGCHAR to manipulate the character contents of a CLOB field in ABL.

So you never manipulate a CLOB datatype directly in your ABL code, instead you must use a longchar variable. That is to say that you must assign the temp-table field to a longchar variable and then use this variable as a parameter.

The same thing happens to BLOB fields, where you need memptr variable to manipulate it.

Use the COPY-LOB statement to copy data between large objects.

Posted by Marian Edu on 20-Oct-2015 07:32

Thanks, guess was expecting some sort of error to be thrown by the invoke or set-parameter methods. Did moved to variable length arrays for longchar/memptr and that way it does work.

Posted by Fernando Souza on 20-Oct-2015 08:55

This is a bug. You should have gotten an error. Please, report this as a bug through Technical Support.

Posted by pliscki on 20-Oct-2015 12:44

Hi Marian,

If you try to run the same procedure with static code it will raise the following error:

Cannot pass large objects as runtime parameters. (14449)

Check what the documentation says about CLOB fields:
CLOB (Character Large OBject) specifies a database table or temp-table field that contains a CLOB locator, which points to the associated CLOB data stored in the database. You must use a LONGCHAR to manipulate the character contents of a CLOB field in ABL.

So you never manipulate a CLOB datatype directly in your ABL code, instead you must use a longchar variable. That is to say that you must assign the temp-table field to a longchar variable and then use this variable as a parameter.

The same thing happens to BLOB fields, where you need memptr variable to manipulate it.

Use the COPY-LOB statement to copy data between large objects.

Posted by Marian Edu on 21-Oct-2015 01:09

Done sir, case 00327623 opened :)

I still think this is something that should work with a buffer field handle to make it consistent, I do not pass a CLOB variable there (that does not exist anyway) but a handle to a CLOB field which it seemed appropriate for the LONGCHAR variable I expect as output.

Posted by Lieven De Foor on 21-Oct-2015 03:42

I think this is related to a bug I logged a few month ago: progress.my.salesforce.com/kA0a0000000dqov

I was writing unit tests for our own serializer (pre OE11.4 which has built-in support for this), and found out my tests were failing for LONGCHAR variables only...

Will be fixed in 11.6

Posted by Fernando Souza on 21-Oct-2015 08:28

The longchar issue is a separate issue.

As mentioned in one of the previous posts, we do not support the CLOB datatype as parameter in a procedure/function/method call, whether you use an actual field or a buffer-field.

Posted by Marian Edu on 22-Oct-2015 01:24

Hey Fernando, the fact that you don't support it is understandable as long as there is no way to have a CLOB variable... for me a buffer field handle is well, a HANDLE :)

Anyway, just said will make it for a nice feature and doubt it's that hard to have it added... as long as you guys figure it out how to set the value for primitive data types in a buffer field handle I have all the faith in the world you could do the same for longchar(clob)/memptr(blob).

Meanwhile will be nice to have a note in documentation to clear things out.


parameter-value
An expression whose type is compatible with data-type.

If iomode is "OUTPUT" or "INPUT-OUTPUT", each of the following must be true:
parameter-value must represent a program variable or a NO-UNDO TEMP-TABLE field (perhaps with an array reference).

parameter-value must still be in scope and must still be valid when the dynamic invoke is executed.

If the output value from the called procedure does not have a data type that matches the data type passed, the output value will be converted to the data type passed.

Posted by Fernando Souza on 22-Oct-2015 09:13

Yes, the documentation should have a note about the unsupported data types.

But just to clarify something you said -  "for me a buffer field handle is well, a HANDLE :)"

But when you write something like this:

   temp-table tt:default-buffer-handle::flchar

That is not a handle. it is the equivalent of BUFFER-VALUE. That syntax is a short-hand for:

  temp-table tt:default-buffer-handle:buffer-field("flchar"):buffer-value

So the actual field value is what is being passed in.

This thread is closed