3

Using PL/SQL, how does one chain two method calls in the same statement without assigning an output to some variable in the calling scope?

I first saw this technique in utPLSQL framework.

begin
  ut.expect(6/2).to_equal(3);
end;
/

This db<>fiddle shows my various failed attempts, but the primary statements are copied below.

create or replace type obj as object 
  ( var number
  , member function fn(self in out obj, val number) return obj
  , member procedure proc(val number)
  )
;
/
create or replace type body obj
as
  member function fn(self in out obj, val number)
    return obj
    as
    begin
      self.var := val;
      return self;
    end
  ;
  
  member procedure proc(self in out obj, val number)
    as
    begin
      self.var := self.var * val;
    end
  ;
end;
/
declare
  o obj;
begin
  o := obj(4);
  o.fn(5).proc(2); --PLS-00363: expression 'FIDDLE_ZCGFGJIACZWGMWNQLREX.OBJ.FN(O, 5)' cannot be used as an assignment target
  dbms_output.put_line(o.var);
end;
/

I am expecting 10 to display (the result of 5 * 2) instead of the PLS-00363.

Using Oracle 19c Enterprise Edition (though the db<>fiddle is 21c).

Thank you in advance.

Alex Bartsmon
  • 471
  • 4
  • 9
  • 2
    Although I can't figure this out, based on the utPLSQL code but I would guess that one of the key issues is that [UT](https://github.com/utPLSQL/utPLSQL/blob/75c7b35c234371146cee40bd4d6d0c26133565b9/source/api/ut.pks) is a package with functions that return objects, not an object itself. – Jon Heller Jan 14 '22 at 06:06
  • 2
    Apparently an implicit object argument cannot be passed as an ``out`` parameter. ```lang-sql begin obj(4).proc(2); --PLS-00363: expression 'OBJ(, 4)' cannot be used as an assignment target end; / ``` Changing the ``in out`` to be just ``in`` and overloading the first method to be both a procedure and function seems to be the trick. The end of this updated [db<>fiddle](https://dbfiddle.uk/?rdbms=oracle_21&fiddle=82cc1cbaf3ecd326bbc48625cc7ea4ae) shows an example. Yes, if wrapped it in a package then i wouldn't need the silly obj(4) to get the statement started. – Alex Bartsmon Jan 14 '22 at 12:00

0 Answers0