Non-leaf Polymorphic Table Functions (PTF)

The Essentials

Applies to: Oracle 18c, Tested against: Oracle 18.1

The following package demonstrates the bare minimum components required to implement a PTF. All required components can be defined inside an "implementation package". Below we create an implementation package called "ptf_demo".

create or replace package ptf_demo as

  --
  -- the implementation package must have a function called "describe"
  --

  function describe( p_input_table_metadata in out dbms_tf.table_t )
    return dbms_tf.describe_t ;

  --
  -- this next function can either be defined here or in a standalone function
  -- it can have any valid name, but it must have at least one argument with a
  -- data type of TABLE (a new data type introduced in 18.1)
  --

  function pass_through( p_table table )
    return table pipelined row polymorphic using ptf_demo ;

  --
  -- alternately the function can specify "PIPELINED TABLE" (for a "Table Semantics" PTF)
  -- instead of "PIPELINED ROW" (for a "Row Semantics" PTF)
  --
  -- the differences will be described later in this tutorial
  --

  /*
  function pass_through( p_table table )
    return table PIPELINED TABLE polymorphic using ptf_demo ;
  */

  end ptf_demo ;
/

create or replace package body ptf_demo as

  function describe( p_input_table_metadata in out dbms_tf.table_t )
    return dbms_tf.describe_t as
  begin
    return null;
    end describe ;

  end ptf_demo;
/

The PTF can now be invoked like this ...

select *
from   ptf_demo.pass_through( scott.dept ) ;
    DEPTNO DNAME      LOC
---------- ---------- ----------
        10 ACCOUNTING NEW YORK
        20 RESEARCH   DALLAS
        30 SALES      CHICAGO
        40 OPERATIONS BOSTON

... or this

select deptno, ename
from   ptf_demo.pass_through( scott.emp )
where  deptno = 10 ;
    DEPTNO ENAME
---------- ----------
        10 KING
        10 MILLER
        10 CLARK

... or this

with t1 as (
  select deptno, dname, ename
  from   scott.dept join scott.emp using( deptno )
  where  deptno = 10 )
select
  t2.*
from
  ptf_demo.pass_through( t1 ) t2 ;
    DEPTNO DNAME      ENAME
---------- ---------- ----------
        10 ACCOUNTING KING
        10 ACCOUNTING MILLER
        10 ACCOUNTING CLARK

... but not like this.

declare

  v_table table ;
  v_count pls_integer ;

begin

  v_table := SCOTT.DEPT ;

  select count(*) into v_count from ptf_demo.pass_through( v_table ) ;

  end ;
/
ORA-06550: line 3, column 11:
PLS-00765: COLUMNS or TABLE is not allowed in this context
ORA-06550: line 3, column 11:
PL/SQL: Item ignored
ORA-06550: line 8, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 8, column 3:
PL/SQL: Statement ignored
ORA-06550: line 10, column 60:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 10, column 60:
PL/SQL: ORA-00904: "V_TABLE": invalid identifier
ORA-06550: line 10, column 3:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

Aliasing

Multiple functions can use the same implementation package. This effectively creates function aliases.

create or replace package ptf_demo as

  function describe( p_table_metadata in out dbms_tf.table_t )
    return dbms_tf.describe_t ;

  function pass_through( p_table table )
    return table pipelined row polymorphic using ptf_demo ;

  function identity_transformation( p_table table )
    return table pipelined row polymorphic using ptf_demo ;

  end ptf_demo ;
/

create or replace package body ptf_demo as

  function describe( p_table_metadata in out dbms_tf.table_t )
    return dbms_tf.describe_t as
  begin
    return null;
    end describe ;

  end ptf_demo;
/

Let's test the first PTF in the package.

select *
from   ptf_demo.pass_through( scott.dept ) ;
    DEPTNO DNAME      LOC
---------- ---------- ----------
        10 ACCOUNTING NEW YORK
        20 RESEARCH   DALLAS
        30 SALES      CHICAGO
        40 OPERATIONS BOSTON

Now let's test the second PTF in the package.

select *
from   ptf_demo.identity_transformation( scott.dept ) ;
    DEPTNO DNAME      LOC
---------- ---------- ----------
        10 ACCOUNTING NEW YORK
        20 RESEARCH   DALLAS
        30 SALES      CHICAGO
        40 OPERATIONS BOSTON

They both executed the same logic and returned the same results.




Revision Notes

Date Category Note
2018-06-23 Created Added to site