Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to chain calls in a pl/sql object type of functions returning SELF

I want to make an oracle object return itself and be able to chain these calls. How do I do that?

I have tried returning the same type, but it doesnt work, I also tried adding a procedure that is invoqued by the funcition but it doesn't work either. Always complains about modifying the value of the width member. Looks like functions wont admit side effects?, are they modelled after a more mathematical function principle? Is this achievable?. I guess I could write the function so it builds a new rectangle with SELF, but that is so much work.

My goal is to be able to chain calls like jQuery or some java classes (a singleton?). Something like:

r := r.setWidth(0).setWidth(1).setWidth(2);

Of course, it would have more methods and it wouldn't be a rectangle. This is the error:

Error: PLS-00363: expression 'SELF' cannot be used as an assignment target
Line: 18
Text: stWidth(w);

-

CREATE OR REPLACE TYPE rectangle AS OBJECT
(
-- The type has 3 attributes.
  length NUMBER,
  width NUMBER,
  area NUMBER,
-- Define a constructor that has only 2 parameters.
  CONSTRUCTOR FUNCTION rectangle(length NUMBER, width NUMBER)
    RETURN SELF AS RESULT,
  MEMBER FUNCTION setWidth(w NUMBER) RETURN rectangle,
  MEMBER PROCEDURE stWidth(w NUMBER)
)

-

CREATE OR REPLACE TYPE BODY rectangle AS
  CONSTRUCTOR FUNCTION rectangle(length NUMBER, width NUMBER)
    RETURN SELF AS RESULT
  AS
  BEGIN
    SELF.length := length;
    SELF.width := width;
-- We compute the area rather than accepting it as a parameter.
    SELF.area := length * width;
    RETURN;
  END;
  MEMBER PROCEDURE stWidth(w NUMBER) IS
  BEGIN
    self.width := w;
  END;
  MEMBER FUNCTION setWidth(w NUMBER) RETURN rectangle IS
    BEGIN
        stWidth(w);

        RETURN SELF;
  END;
END;

Thanks in advance.

like image 343
Roger Avatar asked Feb 16 '23 15:02

Roger


1 Answers

You cannot both change the object and assign to it at the same time. You already know the solution, "build a new rectangle with SELF". But it won't be a lot of work.

Replace this:

  MEMBER FUNCTION setWidth(w NUMBER) RETURN rectangle IS
    BEGIN
        stWidth(w);
        RETURN SELF;
  END;

with this:

  MEMBER FUNCTION setWidth(w NUMBER) RETURN rectangle IS
      v_rectangle rectangle := self;
    BEGIN
        v_rectangle.width := w;
        RETURN v_rectangle;
  END;

You were actually getting a compilation error. By default, SELF is an IN parameter. The call to stWidth failed because it was modifying an IN parameter with self.width := w;.

See: http://docs.oracle.com/cd/B28359_01/appdev.111/b28371/adobjbas.htm#CHDCFEEE

SELF is always the first parameter passed to the method.

  • In member functions, if SELF is not declared, its parameter mode defaults to IN.

  • In member procedures, if SELF is not declared, its parameter mode defaults to IN OUT. The default behavior does not include the NOCOPY compiler hint.

like image 136
Jon Heller Avatar answered Feb 18 '23 09:02

Jon Heller