Search code examples
sqloraclesql-insertuser-defined-typesoracle18c

Reference a user-defined type in a db<>fiddle session (when inserting a row)


In db<>fiddle for Oracle 18c:

I've created a user-defined type (UDT) and a table that uses the type:

create or replace TYPE "MY_ST_GEOMETRY" Authid current_user  AS object
  (entity integer,numpts integer,minx float(64),
  miny float(64),maxx float(64),maxy float(64),
  minz float (64),maxz float(64),minm float(64),
  maxm float(64),area float(64),len float(64),
  srid integer,points blob,
  constructor Function my_st_geometry(geom_str clob,srid number) Return self AS result deterministic,
  constructor Function my_st_geometry(x     number,
                                   y     number,
                                   z     number,
                                   m     number,
                                   srid  integer) Return self AS result deterministic) NOT final

create table polygons (
    id int,
    shape my_st_geometry
)

I want to insert a row into the table.

insert into polygons (id, shape ) VALUES (
 1,
 my_st_geometry('polygon ((52 28,58 28,58 23,52 23,52 28))', 4326)
);

But I get an error:

ORA-04067: not executed, type body "FIDDLE_KVDCLIHQNZSONDPDJHLS.MY_ST_GEOMETRY" does not exist
ORA-06508: PL/SQL: could not find program unit being called: "FIDDLE_KVDCLIHQNZSONDPDJHLS.MY_ST_GEOMETRY"
ORA-06512: at line 1

db<>fiddle

I suspect I need to prefix the UDT with the user name. Since db<>fiddle generates a different user name each time I hit run, I believe I need to get the user name dynamically using a function.

Is there a function I can use to get the user -- so that I can prefix the UDT when inserting a row?


Solution

  • You need to pass the type into the constructor:

    create or replace TYPE "MY_ST_GEOMETRY" Authid current_user  AS object(
      entity integer,
      numpts integer,
      minx float(64),
      miny float(64),
      maxx float(64),
      maxy float(64),
      minz float(64),
      maxz float(64),
      minm float(64),
      maxm float(64),
      area float(64),
      len float(64),
      srid integer,
      points blob,
    
      constructor Function my_st_geometry(
        SELF IN OUT NOCOPY my_st_geometry,
        geom_str clob,
        srid number
      ) Return self AS result deterministic,
      
      constructor Function my_st_geometry(
        SELF IN OUT NOCOPY my_st_geometry,
        x     number,
        y     number,
        z     number,
        m     number,
        srid  integer
      ) Return self AS result deterministic
    ) NOT final;
    

    Then you need to create a body for the type that defines how you want to construct the type:

    create or replace TYPE BODY "MY_ST_GEOMETRY" IS
      constructor Function my_st_geometry(
        SELF IN OUT NOCOPY my_st_geometry,
        geom_str clob,
        srid number
      ) Return self AS result deterministic
      IS
      BEGIN
        -- Add constructor logic here.
        RETURN;
      END;
      
      constructor Function my_st_geometry(
        SELF IN OUT NOCOPY my_st_geometry,
        x     number,
        y     number,
        z     number,
        m     number,
        srid  integer
      ) Return self AS result deterministic
      IS
      BEGIN
        -- Add constructor logic here.
        SELF.minx := x;
        SELF.maxx := x;
        SELF.miny := y;
        SELF.maxy := y;
        SELF.minz := z;
        SELF.maxz := z;
        SELF.minm := m;
        SELF.maxm := m;
        SELF.srid := srid;
        RETURN;
      END;
    END;
    /
    

    Then it "works" (note: you need to complete the constructors and define the logic that constructs the type).

    fiddle