How to debug "pipelined parallel enable table function" ?

Dear All,
Normally we can retrieve output from a "pipelined parallel enable table function " by using SQL statement, such as
select output from table(pipelined_function(arg1));
Can anyone alight me how to call this function purely using PL/SQL statement?
Reason for this : We have third party developer develooped a complicate "pipelined parallel enable table function" and this function is currently calling by SQL (select output from table(pipelined_function(arg1));
), I will like to debug this function, but unable to do so, so far I have done :
1) compile function with debug option
2) using Procedure Builder to debug, if I execute the above statement (select output from table(pipelined_function(arg1)); I believe, Procedure Builder will not debug a function from a SQL statement
3) try to build up a PL/SQL block, but don't know how to it.
basically I want to debug this "pipelined parallel enable table function " and don't know how to do it, any example will be greate!

user2302827 wrote:
Using dbms_output is fine but too tedious. I was looking for a PL/SQL procedure builder that can help to debug a statement like this:
select output from table(pipelined_function(arg1));
Any suggestion?I don't know about any procedure builders.
There is a debugger you can use, though I'd have to think about how to invoke it to use with a pipelined function. The debugger is available in GUI tools like SQL*Developer and TOAD and can be used to walk through a program and set values

Similar Messages

  • How to use database look up table function in xsl mapping

    Can anybody tell me how to use database look up table function while mapping xsl between 2 nodes.
    I have an XML file coming in and depending on one of XML elements we need to decide which further path to take. But, using this XML element, we need to query database table, get metadata and accordingly take appropriate path. I have written lookup function which returns metadata value.
    Now, the issue is how do I pass the XML element valu as input to look up function? When I tried to drag it to the input node of lookup function, it throws an error like "Maximum number of parameters exceeded"
    Thanks,

    If the lookup table is always going to remain the same (e.g. a character generator or something similar) you can place the values in a 2D array constant on your diagram, with the input value as one column, the equivalent as the other. When you need to perform the lookup you use an index array to return all the values in the "input column", search it using "search 1D array" and use the resulting index number to index the other column's data. If the values may change, then it would probably be best to load an array control with your equivalent values from a file.
    P.M.
    Putnam
    Certified LabVIEW Developer
    Senior Test Engineer
    Currently using LV 6.1-LabVIEW 2012, RT8.5
    LabVIEW Champion

  • How to Debug During Event Linkage( Reciever Function Module )

    Hi all,
           If anybody knows how to debug a reciever function module in event linkage method then please respond.The scenario is that whenever service order is changed the change event will fire the custom business object which has a supertype BUS2088.

    Hi Nishanth,
    You can debug event linkage using the transaction SWUE.
    Here you can raise an event and specify an object key (using an already created service order). 
    Just flag the trigger receiver FM synchr. checkbox and your break point will be hit.
    Hope that helps.
    Cheers,
    Brad

  • HOW to pass page parameter into table function in  HTMLDB

    I created this object and table function in database.
    create or replace TYPE date_flow_type
    AS OBJECT (
    time           date,
    max_time      number,
    avg_total           NUMBER,
    sum_total      NUMBER,
    max_total      NUMBER,
    change_rate      number
    create or replace TYPE date_flow_table_type AS TABLE OF date_flow_type;
    create or replace function ret_date(p_date date default sysdate) return date_flow_table_type is
    v_tbl1 date_flow_table_type :=date_flow_table_type();
    begin
    v_tbl1.extend;
    v_tbl1(v_tbl1.last):=date_flow_type (p_date,1,1,1,1,1);
    return v_tbl1;
    end;
    and it is correct in htmldb when using in these ways
    SELECT TIME da,
         max_time max_time,
         sum_total total,
         max_total max_total,
    change_rate
    FROM TABLE ( ret_icp_date_flow ) a;
    SELECT TIME da,
         max_time max_time,
         sum_total total,
         max_total max_total,
    change_rate
    FROM TABLE ( ret_icp_date_flow( sysdate-1 )) a;
    but return error
    ORA-00904: "RET_ICP_DATE_FLOW": 无效的标识符
    when pasing page parameter into the table function
    SELECT TIME da,
    max_time max_time,
    sum_total total,
    max_total max_total,
    change_rate
    FROM TABLE ( ret_icp_date_flow( to_date(:p1_date,'yyyy-mm-dd') )) a
    and this sql is correct while running in sqlplus .

    Hi!
    Thanks for your reply!
    I have tried this solution but it doesn't work!
    When I do getInitParameter in the init function, the servlet take the default values...
    Maybe I have wrote something wrong?
    Excuse me for my english,
    Thanks

  • How to find the list of Parallel enabled tables for a User?

    Hi All,
    I created a table with parallel option. Now I want to find out the list of all tables created with that option. I searched in DBA tables but I couldn’t get it. Could some one help in it?
    Thanks,
    Darius

    You'll find this information in user_tables in the column DEGREE.
    degree=1 means noparallel
    degree=default means parallel default
    degree=2 means (parallel, 2)
    etc...

  • How to debug script to know output function ?

    Hi  ,
    How to know the function to output  of this "PPIO_ENTRY"  program? (I want get the structure to show ALV )
    Please advise, your help is greatly appreciated.
    Thanks,
    Karen
    Edited by: abaper1712 on Jul 14, 2010 8:54 AM

    Hi Darshana,
    I'm debugging the  program"PPIO_ENTRY" ( this program I got from  transaction COOISPI ) I want adjust the ALV gird but I did not see where is  the ouput layout in the code? , where is the structure to display on ALV report ? Which function to use in this program to display on ALV? Which  the funtion to get final value to displayed on ALV in this program?
    Thanks in Advance,
    Karen.
    Edited by: Karen on Jul 14, 2010 9:31 AM

  • Need some help with the Table Function Operator

    I'm on OWB 10gR2 for Sun/Solaris 10 going against some 10gR2 DB's...
    I've been searching up and down trying to figure out how to make OWB use a Table Function (TF) which will JOIN with another table; allowing a column of the joined table to be a parameter in to the TF. I can't seem to get it to work. I'm able to get this to work in regular SQL, though. Here's the setup:
    -- Source Table:
    DROP TABLE "ZZZ_ROOM_MASTER_EX";
    CREATE TABLE "ZZZ_ROOM_MASTER_EX"
    ( "ID" NUMBER(8,0),
    "ROOM_NUMBER" VARCHAR2(200),
    "FEATURES" VARCHAR2(4000)
    -- Example Data:
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (1,'Room 1',null);
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (2,'Room 2',null);
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (3,'Room 3','1,1;2,3;');
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (4,'Room 4','5,2;5,4;');
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (5,'Room 5',' ');
    -- Destination Table:
    DROP TABLE "ZZZ_ROOM_FEATURES_EX";
    CREATE TABLE "ZZZ_ROOM_FEATURES_EX"
    ( "ROOM_NUMBER" VARCHAR2(200),
    "FEATUREID" NUMBER(8,0),
    "QUANTITY" NUMBER(8,0)
    -- Types for output table:
    CREATE OR REPLACE TYPE FK_Row_EX AS OBJECT
    ID NUMBER(8,0),
    QUANTITY NUMBER(8,0)
    CREATE OR REPLACE TYPE FK_Table_EX AS TABLE OF FK_Row_EX;
    -- Package Dec:
    CREATE OR REPLACE
    PACKAGE ZZZ_SANDBOX_EX IS
    FUNCTION UNFK(inputString VARCHAR2) RETURN FK_Table_EX;
    END ZZZ_SANDBOX_EX;
    -- Package Body:
    CREATE OR REPLACE
    PACKAGE BODY ZZZ_SANDBOX_EX IS
    FUNCTION UNFK(inputString VARCHAR2) RETURN FK_Table_EX
    AS
    RETURN_VALUE FK_Table_EX := FK_Table_EX();
    i NUMBER(8,0) := 0;
    BEGIN
    -- TODO: Put some real code in here that will actually read the
    -- input string, parse it out, and put data in to RETURN_VALUE
    WHILE(i < 3) LOOP
    RETURN_VALUE.EXTEND;
    RETURN_VALUE(RETURN_VALUE.LAST) := FK_Row_EX(4, 5);
    i := i + 1;
    END LOOP;
    RETURN RETURN_VALUE;
    END UNFK;
    END ZZZ_SANDBOX_EX;
    I've got a source system built by lazy DBA's and app developers who decided to store foreign keys for many-to-many relationships as delimited structures in driving tables. I need to build a generic table function to parse this data and return it as an actual table. In my example code, I don't actually have the parsing part written yet (I need to see how many different formats the source system uses first) so I just threw in some stub code to generate a few rows of 4's and 5's to return.
    I can get the data from my source table to my destination table using the following SQL statement:
    -- from source table joined with table function
    INSERT INTO ZZZ_ROOM_FEATURES_EX(
    ROOM_NUMBER,
    FEATUREID,
    QUANTITY)
    SELECT
    ZZZ_ROOM_MASTER_EX.ROOM_NUMBER,
    UNFK.ID,
    UNFK.QUANTITY
    FROM
    ZZZ_ROOM_MASTER_EX,
    TABLE(ZZZ_SANDBOX_EX.UNFK(ZZZ_ROOM_MASTER_EX.FEATURES)) UNFK
    Now, the big question is--how do I do this from OWB? I've tried several different variations of my function and settings in OWB to see if I can build a single SELECT statement which joins a regular table with a table function--but none of them seem to work, I end up getting SQL generated that won't compile because it doesn't see the source table right:
    INSERT
    /*+ APPEND PARALLEL("ZZZ_ROOM_FEATURES_EX") */
    INTO
    "ZZZ_ROOM_FEATURES_EX"
    ("ROOM_NUMBER",
    "FEATUREID",
    "QUANTITY")
    (SELECT
    "ZZZ_ROOM_MASTER_EX"."ROOM_NUMBER" "ROOM_NUMBER",
    "INGRP2"."ID" "ID_1",
    "INGRP2"."QUANTITY" "QUANTITY"
    FROM
    (SELECT
    "UNFK"."ID" "ID",
    "UNFK"."QUANTITY" "QUANTITY"
    FROM
    TABLE ( "ZZZ_SANDBOX_EX"."UNFK2" ("ZZZ_ROOM_MASTER_EX"."FEATURES")) "UNFK") "INGRP2",
    "ZZZ_ROOM_MASTER_EX" "ZZZ_ROOM_MASTER_EX"
    As you can see, it's trying to create a sub-query in the FROM clause--causing it to just ask for "ZZZ_ROOM_MASTER_EX"."FEATURES" as an input--which isn't available because it's outside of the sub-query!
    Is this some kind of bug with the code generator or am I doing something seriously wrong here? Any help will be greatly appreciated!

    Hello Everybody!
    Thank you for all your response!
    I had changes this work area into Internal table and changed the select query. PLease let me know if this causes any performance issues?
    I had created a Z table with the following fields :
    ZADS :
    MANDT
    VKORG
    ABGRU.
    I had written a select query as below :
    I had removed the select single and insted of using the Structure it_rej, I had changed it into Internal table 
    select vkorg abgru from ZADS into it_rej.
    Earlier :
    IT_REJ is a Work area:
    DATA : BEGIN OF IT_REJ,
    VKORG TYPE VBAK-VKORG,
    ABGRU TYPE VBAP-ABGRU,
    END OF IT_REJ.
    Now :
    DATA : BEGIN OF IT_REJ occurs 0,
    VKORG TYPE VBAK-VKORG,
    ABGRU TYPE VBAP-ABGRU,
    END OF IT_REJ.
    I guess this will fix the issue correct?
    PLease suggest!
    Regards,
    Developer.

  • Usage of TAble Functions in OBIEE

    Hello All,
    I have created a table function in the database.
    Is it possible to use/call table functions in obiee.Please let me know how to use table functions in OBIEE.
    Thanks in advance.

    Hi,
    Thanks for your reply.
    I want to use this table function to generate answers report.
    In the query i am using unions,bind variables.I can not create a database view on this query.The best solution would be creating a table function.
    But,i do not know how to access/use/call this table function to create answers report.
    Thanks in advance.

  • 10g: delay for collecting results from parallel pipelined table functions

    When parallel pipelined table functions are properly started and generate output record, there is a delay for the consuming main thread to gather these records.
    This delay is huge compared with the run-time of the worker threads.
    For my application it goes like this:
    main thread timing efforts to start worker and collect their results:
    [10:50:33-*10:50:49*]:JOMA: create (master): 015.93 sec (#66356 records, #4165/sec)
    worker threads:
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.24 sec (#2449 EDRs, #467/sec, #0 errored / #6430 EBTMs, #1227/sec, #0 errored) - bulk #1 / sid #816
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.56 sec (#2543 EDRs, #457/sec, #0 errored / #6792 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #718
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.69 sec (#2610 EDRs, #459/sec, #0 errored / #6950 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #614
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.55 sec (#2548 EDRs, #459/sec, #0 errored / #6744 EBTMs, #1216/sec, #0 errored) - bulk #1 / sid #590
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.33 sec (#2461 EDRs, #462/sec, #0 errored / #6504 EBTMs, #1220/sec, #0 errored) - bulk #1 / sid #508
    You can see, the worker threads are all started at the same time and terminating at the same time: 10:50:34-10:50:*39*.
    But the main thread just invoking them and saving their results into a collection has finished at 10:50:*49*.
    Why does it need #10 sec more just to save the data?
    Here's a sample sqlplus script to demonstrate this:
    --------------------------- snip -------------------------------------------------------
    set serveroutput on;
    drop table perf_data;
    drop table test_table;
    drop table tmp_test_table;
    drop type ton_t;
    drop type test_list;
    drop type test_obj;
    create table perf_data
         sid number,
         t1 timestamp with time zone,
         t2 timestamp with time zone,
         client varchar2(256)
    create table test_table
         a number(19,0),
         b timestamp with time zone,
         c varchar2(256)
    create global temporary table tmp_test_table
         a number(19,0),
         b timestamp with time zone,
         c varchar2(256)
    create or replace type test_obj as object(
         a number(19,0),
         b timestamp with time zone,
         c varchar2(256)
    create or replace type test_list as table of test_obj;
    create or replace type ton_t as table of number;
    create or replace package test_pkg
    as
         type test_rec is record (
              a number(19,0),
              b timestamp with time zone,
              c varchar2(256)
         type test_tab is table of test_rec;
         type test_cur is ref cursor return test_rec;
         function TZDeltaToMilliseconds(
              t1 in timestamp with time zone,
              t2 in timestamp with time zone)
         return pls_integer;
         function TF(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by hash(a));
    end;
    create or replace package body test_pkg
    as
         * Calculate timestamp with timezone difference
         * in milliseconds
         function TZDeltaToMilliseconds(
              t1 in timestamp with time zone,
              t2 in timestamp with time zone)
         return pls_integer
         is
         begin
              return     (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
              +     (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
              +     (extract(second from t2) - extract(second from t1)) * 1000;
         end TZDeltaToMilliseconds;
         function TF(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by hash(a))
    is
              pragma autonomous_transaction;
              sid number;
              counter number(19,0) := 0;
              myrec test_rec;
              mytab test_tab;
              mytab2 test_list := test_list();
              t1 timestamp with time zone;
              t2 timestamp with time zone;
         begin
              t1 := systimestamp;
              select userenv('SID') into sid from dual;
              dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
              loop
                   fetch mycur into myRec;
                   exit when mycur%NOTFOUND;
                   mytab2.extend;
                   mytab2(mytab2.last) := test_obj(myRec.a, myRec.b, myRec.c);
              end loop;
              for i in mytab2.first..mytab2.last loop
                   -- attention: saves own SID in test_obj.a for indication to caller
                   --     how many sids have been involved
                   pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c));
                   pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate
                   pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate once again
                   counter := counter + 1;
              end loop;
              t2 := systimestamp;
              insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
              commit;
              dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
         end;
    end;
    declare
         myList test_list := test_list();
         myList2 test_list := test_list();
         sids ton_t := ton_t();
         sid number;
         t1 timestamp with time zone;
         t2 timestamp with time zone;
    procedure LogPerfTable
    is
    type ton is table of number;
    type tot is table of timestamp with time zone;
              type clients_t is table of varchar2(256);
    sids ton;
    t1s tot;
    t2s tot;
              clients clients_t;
    deltaTime integer;
    btsPerSecond number(19,0);
    edrsPerSecond number(19,0);
    begin
    select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
    if clients.count > 0 then
    for i in clients.FIRST .. clients.LAST loop
    deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
    if deltaTime = 0 then deltaTime := 1; end if;
    dbms_output.put_line(
    '[' || to_char(t1s(i), 'hh:mi:ss') ||
    '-' || to_char(t2s(i), 'hh:mi:ss') ||
    ']:' ||
    ' client ' || clients(i) || ' / sid #' || sids(i)
    end loop;
    end if;
    end LogPerfTable;
    begin
         select userenv('SID') into sid from dual;
         for i in 1..200000 loop
              myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
         end loop;
         -- save into the real table
         insert into test_table select * from table(cast (myList as test_list));
         -- save into the tmp table
         insert into tmp_test_table select * from table(cast (myList as test_list));
         dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
         delete from perf_data;
         t1 := systimestamp;
         select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
         from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
         t2 := systimestamp;
         insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
         LogPerfTable;
         dbms_output.put_line('... saved #' || myList2.count || ' records');
         select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
         dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
         delete from perf_data;
         t1 := systimestamp;
         select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
         from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
         t2 := systimestamp;
         insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
         LogPerfTable;
         dbms_output.put_line('... saved #' || myList2.count || ' records');
         select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
         dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
         delete from perf_data;
         t1 := systimestamp;
         select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
         from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
         t2 := systimestamp;
         insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
         LogPerfTable;
         dbms_output.put_line('... saved #' || myList2.count || ' records');
         select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    end;
    --------------------------- snap -------------------------------------------------------
    best regards,
    Frank

    Hello
    I think the delay you are seeing is down to choosing the partitioning method as HASH. When you specify anything other than ANY, an additional buffer sort is included in the execution plan...
    create or replace package test_pkg
    as
    type test_rec is record (
    a number(19,0),
    b timestamp with time zone,
    c varchar2(256)
    type test_tab is table of test_rec;
    type test_cur is ref cursor return test_rec;
    function TZDeltaToMilliseconds(
    t1 in timestamp with time zone,
    t2 in timestamp with time zone)
    return pls_integer;
    function TF(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by hash(a));
    function TF_Any(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by ANY);
    end;
    create or replace package body test_pkg
    as
    * Calculate timestamp with timezone difference
    * in milliseconds
    function TZDeltaToMilliseconds(
    t1 in timestamp with time zone,
    t2 in timestamp with time zone)
    return pls_integer
    is
    begin
    return (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
    + (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
    + (extract(second from t2) - extract(second from t1)) * 1000;
    end TZDeltaToMilliseconds;
      function TF(mycur test_cur)
      return test_list pipelined
      parallel_enable(partition mycur by hash(a))
      is
      pragma autonomous_transaction;
        sid number;
        counter number(19,0) := 0;
        myrec test_rec;
        t1 timestamp with time zone;
        t2 timestamp with time zone;
      begin
        t1 := systimestamp;
        select userenv('SID') into sid from dual;
        dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
      loop
        fetch mycur into myRec;
        exit when mycur%NOTFOUND;
        -- attention: saves own SID in test_obj.a for indication to caller
        -- how many sids have been involved
        pipe row(test_obj(sid, myRec.b, myRec.c));
        pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
        pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
        counter := counter + 1;
      end loop;
      t2 := systimestamp;
      insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
      commit;
      dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
      end;
      function TF_any(mycur test_cur)
      return test_list pipelined
      parallel_enable(partition mycur by ANY)
      is
      pragma autonomous_transaction;
        sid number;
        counter number(19,0) := 0;
        myrec test_rec;
        t1 timestamp with time zone;
        t2 timestamp with time zone;
      begin
        t1 := systimestamp;
        select userenv('SID') into sid from dual;
        dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
        loop
          fetch mycur into myRec;
          exit when mycur%NOTFOUND;
          -- attention: saves own SID in test_obj.a for indication to caller
          -- how many sids have been involved
          pipe row(test_obj(sid, myRec.b, myRec.c));
          pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
          pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
          counter := counter + 1;
        end loop;
        t2 := systimestamp;
        insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
        commit;
        dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
      end;
    end;
    explain plan for
    select /*+ first_rows */ test_obj(a, b, c)
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    select * from table(dbms_xplan.display);
    Plan hash value: 1037943675
    | Id  | Operation                             | Name       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
    |   0 | SELECT STATEMENT                      |            |  8168 |  3972K|    20   (0)| 00:00:01 |        |      |            |
    |   1 |  PX COORDINATOR                       |            |       |       |            |          |        |      |            |
    |   2 |   PX SEND QC (RANDOM)                 | :TQ10001   |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
    |   3 |    BUFFER SORT                        |            |  8168 |  3972K|            |          |  Q1,01 | PCWP |            |
    |   4 |     VIEW                              |            |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,01 | PCWP |            |
    |   5 |      COLLECTION ITERATOR PICKLER FETCH| TF         |       |       |            |          |  Q1,01 | PCWP |            |
    |   6 |       PX RECEIVE                      |            |   931K|   140M|   136   (2)| 00:00:02 |  Q1,01 | PCWP |            |
    |   7 |        PX SEND HASH                   | :TQ10000   |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | P->P | HASH       |
    |   8 |         PX BLOCK ITERATOR             |            |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWC |            |
    |   9 |          TABLE ACCESS FULL            | TEST_TABLE |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWP |            |
    Note
       - dynamic sampling used for this statement
    explain plan for
    select /*+ first_rows */ test_obj(a, b, c)
    from table(test_pkg.TF_Any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    select * from table(dbms_xplan.display);
    Plan hash value: 4097140875
    | Id  | Operation                            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
    |   0 | SELECT STATEMENT                     |            |  8168 |  3972K|    20   (0)| 00:00:01 |        |      |            |
    |   1 |  PX COORDINATOR                      |            |       |       |            |          |        |      |            |
    |   2 |   PX SEND QC (RANDOM)                | :TQ10000   |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,00 | P->S | QC (RAND)  |
    |   3 |    VIEW                              |            |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,00 | PCWP |            |
    |   4 |     COLLECTION ITERATOR PICKLER FETCH| TF_ANY     |       |       |            |          |  Q1,00 | PCWP |            |
    |   5 |      PX BLOCK ITERATOR               |            |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWC |            |
    |   6 |       TABLE ACCESS FULL              | TEST_TABLE |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWP |            |
    Note
       - dynamic sampling used for this statementI posted about it here a few years ago and I more recently posted a question on Asktom. Unfortunately Tom was not able to find a technical reason for it to be there so I'm still a little in the dark as to why it is needed. The original question I posted is here:
    Pipelined function partition by hash has extra sort#
    I ran your tests with HASH vs ANY and the results are in line with the observations above....
    declare
    myList test_list := test_list();
    myList2 test_list := test_list();
    sids ton_t := ton_t();
    sid number;
    t1 timestamp with time zone;
    t2 timestamp with time zone;
    procedure LogPerfTable
    is
    type ton is table of number;
    type tot is table of timestamp with time zone;
    type clients_t is table of varchar2(256);
    sids ton;
    t1s tot;
    t2s tot;
    clients clients_t;
    deltaTime integer;
    btsPerSecond number(19,0);
    edrsPerSecond number(19,0);
    begin
    select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
    if clients.count > 0 then
    for i in clients.FIRST .. clients.LAST loop
    deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
    if deltaTime = 0 then deltaTime := 1; end if;
    dbms_output.put_line(
    '[' || to_char(t1s(i), 'hh:mi:ss') ||
    '-' || to_char(t2s(i), 'hh:mi:ss') ||
    ']:' ||
    ' client ' || clients(i) || ' / sid #' || sids(i)
    end loop;
    end if;
    end LogPerfTable;
    begin
    select userenv('SID') into sid from dual;
    for i in 1..200000 loop
    myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
    end loop;
    -- save into the real table
    insert into test_table select * from table(cast (myList as test_list));
    -- save into the tmp table
    insert into tmp_test_table select * from table(cast (myList as test_list));
    dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(4) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function ANY:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(5) copy physical ''test_table'' to ''mylist2'' by streaming via table function using ANY:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    end;
    (1) copy 'mylist' to 'mylist2' by streaming via table function...
    test_pkg.TF( sid => '918' ): enter
    test_pkg.TF( sid => '918' ): exit, piped #200000 records
    [01:40:19-01:40:29]: client master / sid #918
    [01:40:19-01:40:29]: client slave / sid #918
    ... saved #600000 records
    (2) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function:
    [01:40:31-01:40:36]: client master / sid #918
    [01:40:31-01:40:32]: client slave / sid #659
    [01:40:31-01:40:32]: client slave / sid #880
    [01:40:31-01:40:32]: client slave / sid #1045
    [01:40:31-01:40:32]: client slave / sid #963
    [01:40:31-01:40:32]: client slave / sid #712
    ... saved #600000 records
    (3) copy physical 'test_table' to 'mylist2' by streaming via table function:
    [01:40:37-01:41:05]: client master / sid #918
    [01:40:37-01:40:42]: client slave / sid #738
    [01:40:37-01:40:42]: client slave / sid #568
    [01:40:37-01:40:42]: client slave / sid #618
    [01:40:37-01:40:42]: client slave / sid #659
    [01:40:37-01:40:42]: client slave / sid #963
    ... saved #3000000 records
    (4) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function ANY:
    [01:41:12-01:41:16]: client master / sid #918
    [01:41:12-01:41:16]: client slave / sid #712
    [01:41:12-01:41:16]: client slave / sid #1045
    [01:41:12-01:41:16]: client slave / sid #681
    [01:41:12-01:41:16]: client slave / sid #754
    [01:41:12-01:41:16]: client slave / sid #880
    ... saved #600000 records
    (5) copy physical 'test_table' to 'mylist2' by streaming via table function using ANY:
    [01:41:18-01:41:38]: client master / sid #918
    [01:41:18-01:41:38]: client slave / sid #681
    [01:41:18-01:41:38]: client slave / sid #712
    [01:41:18-01:41:38]: client slave / sid #754
    [01:41:18-01:41:37]: client slave / sid #880
    [01:41:18-01:41:38]: client slave / sid #1045
    ... saved #3000000 recordsHTH
    David

  • Parallel pipelined table function, autonomous_transaction to global tmp tab

    Hi,
    i try to speed up my parallel pipelined table function and switch from pl/sql collection to global temporary table inside.
    This requires to use PRAGMA AUTONOMOUS_TRANSACTION (and commit), because inserting into global temporary table (DML)
    within select - for invoking the table function - is not allowed without.
    As a consequence of commit it next requires to have on commit preserve rows for the global temporary table.
    Now:
    Inserts into the global temporary table are done - indicated by sql%rowcount.
    But a select afterwards doesn't show any record anymore.
    Here is a program to demonstrate it:
    set serveroutput on;
    drop type TestTableOfNumber_t;
    create or replace type TestTableOfNumber_t is table of number;
    drop type TestStatusList;
    drop type TestStatusObj;
    create or replace type TestStatusObj as object(
         sid number,
         ctr1 number,
         ctr2 number,
         ctr3 number
    create or replace type TestStatusList is table of TestStatusObj;
    drop table TestTmpTable;
    create global temporary table TestTmpTable (
         value     number
    ) on commit preserve rows;
    create or replace package test_pkg
    as
         type TestStatusRec is record (
              sid number,
              ctr1 number,
              ctr2 number,
              ctr3 number
         type TestStatusTab is table of TestStatusRec;
         function FillTmpTable(id in varchar2)
         return TestStatusRec;
         FUNCTION ptf (p_cursor  IN  sys_refcursor)
         RETURN TestStatusList PIPELINED
         PARALLEL_ENABLE(PARTITION p_cursor BY any);
    end;
    create or replace package body test_pkg
    as
         function FillTmpTable(id in varchar2)
         return TestStatusRec
         is
              PRAGMA AUTONOMOUS_TRANSACTION;
              result TestStatusRec;
              sid number;
              type ton is table of number;
              tids TestTableOfNumber_t := TestTableOfNumber_t();
              records number := 0;
         begin
              select userenv('SID') into sid from dual;
              result.sid := sid;
              delete from TestTmpTable;
              for i in 1..100 loop
                   tids.extend;
                   tids(tids.last) := i;
              end loop;
              forall i in 1..tids.count
                   insert into TestTmpTable (value) values (tids(i));
              -- get number of records inserted
              records := sql%rowcount;
              result.ctr1 := records;
              -- retrieve again before commit
              select count(*) into records from TestTmpTable;
              result.ctr2 := records;
              commit;
              -- retrieve again after commit
              select count(*) into records from TestTmpTable;
              result.ctr3 := records;
              return result;
         end;
           FUNCTION ptf (p_cursor  IN  sys_refcursor)
         RETURN TestStatusList PIPELINED
         PARALLEL_ENABLE(PARTITION p_cursor BY any)
         IS
              rec test_pkg.TestStatusRec;
              value number;
              sid number;
              ctr integer := 0;
         BEGIN
              select userenv('SID') into sid from dual;
              rec := FillTmpTable('IN PTF');
              LOOP
                   FETCH p_cursor into value;
                   EXIT WHEN p_cursor%NOTFOUND;
                   ctr := ctr + 1;     
              END LOOP;
              -- as a result i am only interested in the results of FillTmpTable():
              PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
                  RETURN;
         END;
    end;
    declare
         tons TestTableOfNumber_t;
         counts TestTableOfNumber_t;
         status test_pkg.TestStatusRec;
         statusList test_pkg.TestStatusTab;
    begin
         status := test_pkg.FillTmpTable('MAIN');
         dbms_output.put_line('main thread:'
              || ' sid #' || status.sid
              || ' / #' || status.ctr1 || ' inserted '
              || ' / #' || status.ctr2 || ' before commit'
              || ' / #' || status.ctr3 || ' after commit');     
         select value bulk collect into tons from TestTmpTable;
         select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2) */ value from TestTmpTable tab)));
         for i in 1..StatusList.count loop
              dbms_output.put_line('worker thread #' || i  || ':'
              || ' sid #' || statusList(i).sid
              || ' / #' || statusList(i).ctr1 || ' inserted '
              || ' / #' || statusList(i).ctr2 || ' before commit'
              || ' / #' || statusList(i).ctr3 || ' after commit');
         end loop;
    end;
    /The output is:
    main thread: sid #881 / #100 inserted  / #100 before commit / #100 after commit
    worker thread #1: sid #421 / #100 inserted  / #0 before commit / #0 after commit
    worker thread #2: sid #321 / #100 inserted  / #0 before commit / #0 after commitThe 1st line is for the main thread invoking FillTmpTable().
    The next #2 lines are for the worker threads of the parallel pipelined table function for invoking the same FillTmpTable().
    For the main thread everything is as expected.
    But for the worker threads the logs for before commit and after commit both give #0 for the number of available records in the global temporary table.
    However all indicate #100 for the SQL insert
    regards,
    Frank
    Edited by: user8704911 on Jul 7, 2011 10:13 AM
    Edited by: user8704911 on Jul 7, 2011 10:20 AM
    Edited by: user8704911 on Jul 7, 2011 10:27 AM

    SQL> select * from v$version;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
    PL/SQL Release 11.1.0.7.0 - Production
    CORE    11.1.0.7.0      Production
    TNS for Linux: Version 11.1.0.7.0 - Production
    NLSRTL Version 11.1.0.7.0 - Production
    SQL> set serveroutput on;
    SQL> drop type TestTableOfNumber;
    drop type TestTableOfNumber
    ERROR at line 1:
    ORA-04043: object TESTTABLEOFNUMBER does not exist
    SQL> /
    drop type TestTableOfNumber
    ERROR at line 1:
    ORA-04043: object TESTTABLEOFNUMBER does not exist
    SQL> 
    SQL> create or replace type TestTableOfNumber_t is table of number;
      2  /
    Type created.
    SQL> 
    SQL> drop type TestStatusObj;
    drop type TestStatusObj
    ERROR at line 1:
    ORA-04043: object TESTSTATUSOBJ does not exist
    SQL> /
    drop type TestStatusObj
    ERROR at line 1:
    ORA-04043: object TESTSTATUSOBJ does not exist
    SQL> 
    SQL> create or replace type TestStatusObj as object(
      2   sid number,
      3   ctr1 number,
      4   ctr2 number,
      5   ctr3 number
      6  );
      7  /
    Type created.
    SQL> 
    SQL> drop type TestStatusList;
    drop type TestStatusList
    ERROR at line 1:
    ORA-04043: object TESTSTATUSLIST does not exist
    SQL> /
    drop type TestStatusList
    ERROR at line 1:
    ORA-04043: object TESTSTATUSLIST does not exist
    SQL> 
    SQL> create or replace type TestStatusList is table of TestStatusObj;
      2  /
    Type created.
    SQL> 
    SQL> drop table TestTmpTable;
    drop table TestTmpTable
    ERROR at line 1:
    ORA-00942: table or view does not exist
    SQL> /
    drop table TestTmpTable
    ERROR at line 1:
    ORA-00942: table or view does not exist
    SQL> 
    SQL> create global temporary table TestTmpTable (
      2   value number
      3  ) on commit preserve rows;
    Table created.
    SQL> /
    create global temporary table TestTmpTable (
    ERROR at line 1:
    ORA-00955: name is already used by an existing object
    SQL> 
    SQL> create or replace package test_pkg
      2  as
      3  
      4   type TestStatusRec is record (
      5    sid number,
      6    ctr1 number,
      7    ctr2 number,
      8    ctr3 number
      9   );
    10  
    11   type TestStatusTab is table of TestStatusRec;
    12  
    13   function FillTmpTable(id in varchar2)
    14   return TestStatusRec;
    15  
    16   FUNCTION ptf (p_cursor  IN  sys_refcursor)
    17   RETURN TestStatusList PIPELINED
    18   PARALLEL_ENABLE(PARTITION p_cursor BY any);
    19  
    20  end;
    21  /
    Package created.
    SQL> 
    SQL> create or replace package body test_pkg
      2  as
      3  
      4   function FillTmpTable(id in varchar2)
      5   return TestStatusRec
      6   is
      7    PRAGMA AUTONOMOUS_TRANSACTION;
      8  
      9    result TestStatusRec;
    10  
    11    sid number;
    12  
    13    type ton is table of number;
    14    tids TestTableOfNumber_t := TestTableOfNumber_t();
    15  
    16    records number := 0;
    17   begin
    18    select userenv('SID') into sid from dual;
    19    result.sid := sid;
    20  
    21    delete from TestTmpTable;
    22  
    23    for i in 1..100 loop
    24     tids.extend;
    25     tids(tids.last) := i;
    26    end loop;
    27  
    28    forall i in 1..tids.count
    29     insert into TestTmpTable (value) values (tids(i));
    30  
    31    -- get number of records inserted
    32    records := sql%rowcount;
    33    result.ctr1 := records;
    34  
    35    -- retrieve again before commit
    36    select count(*) into records from TestTmpTable;
    37    result.ctr2 := records;
    38  
    39    commit;
    40  
    41    -- retrieve again after commit
    42    select count(*) into records from TestTmpTable;
    43    result.ctr3 := records;
    44  
    45    return result;
    46   end;
    47  
    48     FUNCTION ptf (p_cursor  IN  sys_refcursor)
    49   RETURN TestStatusList PIPELINED
    50   PARALLEL_ENABLE(PARTITION p_cursor BY any)
    51   IS
    52    rec test_pkg.TestStatusRec;
    53    value number;
    54    sid number;
    55    ctr integer := 0;
    56   BEGIN
    57    select userenv('SID') into sid from dual;
    58    rec := FillTmpTable('IN PTF');
    59    LOOP
    60     FETCH p_cursor into value;
    61     EXIT WHEN p_cursor%NOTFOUND;
    62     ctr := ctr + 1;
    63    END LOOP;
    64  
    65    -- as a result i am only interested in the results of FillTmpTable():
    66    PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
    67  
    68        RETURN;
    69   END;
    70  end;
    71  /
    Package body created.
    SQL> 
    SQL> declare
      2   tons TestTableOfNumber_t;
      3   counts TestTableOfNumber_t;
      4   status test_pkg.TestStatusRec;
      5   statusList test_pkg.TestStatusTab;
      6  begin
      7   status := test_pkg.FillTmpTable('MAIN');
      8   dbms_output.put_line('main thread:'
      9    || ' sid #' || status.sid
    10    || ' / #' || status.ctr1 || ' inserted '
    11    || ' / #' || status.ctr2 || ' before commit'
    12    || ' / #' || status.ctr3 || ' after commit');
    13  
    14   select value bulk collect into tons from TestTmpTable;
    15  
    16   select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2
    ) */ value from TestTmpTable tab)));
    17  
    18   for i in 1..StatusList.count loop
    19    dbms_output.put_line('worker thread #' || i  || ':'
    20    || ' sid #' || statusList(i).sid
    21    || ' / #' || statusList(i).ctr1 || ' inserted '
    22    || ' / #' || statusList(i).ctr2 || ' before commit'
    23    || ' / #' || statusList(i).ctr3 || ' after commit');
    24   end loop;
    25  
    26  end;
    27  /
    main thread: sid #1023 / #100 inserted  / #100 before commit / #100 after commit
    worker thread #1: sid #1045 / #100 inserted  / #100 before commit / #100 after
    commit
    worker thread #2: sid #1019 / #100 inserted  / #100 before commit / #100 after
    commit
    PL/SQL procedure successfully completed.
    SQL> I am getting a different result.
    Regards
    Raj

  • Performance issues with pipelined table functions

    I am testing pipelined table functions to be able to re-use the <font face="courier">base_query</font> function. Contrary to my understanding, the <font face="courier">with_pipeline</font> procedure runs 6 time slower than the legacy <font face="courier">no_pipeline</font> procedure. Am I missing something? The <font face="courier">processor</font> function is from [url http://www.oracle-developer.net/display.php?id=429]improving performance with pipelined table functions .
    Edit: The underlying query returns 500,000 rows in about 3 minutes. So there are are no performance issues with the query itself.
    Many thanks in advance.
    CREATE OR REPLACE PACKAGE pipeline_example
    IS
       TYPE resultset_typ IS REF CURSOR;
       TYPE row_typ IS RECORD (colC VARCHAR2(200), colD VARCHAR2(200), colE VARCHAR2(200));
       TYPE table_typ IS TABLE OF row_typ;
       FUNCTION base_query (argA IN VARCHAR2, argB IN VARCHAR2)
          RETURN resultset_typ;
       c_default_limit   CONSTANT PLS_INTEGER := 100;  
       FUNCTION processor (
          p_source_data   IN resultset_typ,
          p_limit_size    IN PLS_INTEGER DEFAULT c_default_limit)
          RETURN table_typ
          PIPELINED
          PARALLEL_ENABLE(PARTITION p_source_data BY ANY);
       PROCEDURE with_pipeline (argA          IN     VARCHAR2,
                                argB          IN     VARCHAR2,
                                o_resultset      OUT resultset_typ);
       PROCEDURE no_pipeline (argA          IN     VARCHAR2,
                              argB          IN     VARCHAR2,
                              o_resultset      OUT resultset_typ);
    END pipeline_example;
    CREATE OR REPLACE PACKAGE BODY pipeline_example
    IS
       FUNCTION base_query (argA IN VARCHAR2, argB IN VARCHAR2)
          RETURN resultset_typ
       IS
          o_resultset   resultset_typ;
       BEGIN
          OPEN o_resultset FOR
             SELECT colC, colD, colE
               FROM some_table
              WHERE colA = ArgA AND colB = argB;
          RETURN o_resultset;
       END base_query;
       FUNCTION processor (
          p_source_data   IN resultset_typ,
          p_limit_size    IN PLS_INTEGER DEFAULT c_default_limit)
          RETURN table_typ
          PIPELINED
          PARALLEL_ENABLE(PARTITION p_source_data BY ANY)
       IS
          aa_source_data   table_typ;-- := table_typ ();
       BEGIN
          LOOP
             FETCH p_source_data
             BULK COLLECT INTO aa_source_data
             LIMIT p_limit_size;
             EXIT WHEN aa_source_data.COUNT = 0;
             /* Process the batch of (p_limit_size) records... */
             FOR i IN 1 .. aa_source_data.COUNT
             LOOP
                PIPE ROW (aa_source_data (i));
             END LOOP;
          END LOOP;
          CLOSE p_source_data;
          RETURN;
       END processor;
       PROCEDURE with_pipeline (argA          IN     VARCHAR2,
                                argB          IN     VARCHAR2,
                                o_resultset      OUT resultset_typ)
       IS
       BEGIN
          OPEN o_resultset FOR
               SELECT /*+ PARALLEL(t, 5) */ colC,
                      SUM (CASE WHEN colD > colE AND colE != '0' THEN colD / ColE END)de,
                      SUM (CASE WHEN colE > colD AND colD != '0' THEN colE / ColD END)ed,
                      SUM (CASE WHEN colD = colE AND colD != '0' THEN '1' END) de_one,
                      SUM (CASE WHEN colD = '0' OR colE = '0' THEN '0' END) de_zero
                 FROM TABLE (processor (base_query (argA, argB),100)) t
             GROUP BY colC
             ORDER BY colC
       END with_pipeline;
       PROCEDURE no_pipeline (argA          IN     VARCHAR2,
                              argB          IN     VARCHAR2,
                              o_resultset      OUT resultset_typ)
       IS
       BEGIN
          OPEN o_resultset FOR
               SELECT colC,
                      SUM (CASE WHEN colD > colE AND colE  != '0' THEN colD / ColE END)de,
                      SUM (CASE WHEN colE > colD AND colD  != '0' THEN colE / ColD END)ed,
                      SUM (CASE WHEN colD = colE AND colD  != '0' THEN 1 END) de_one,
                      SUM (CASE WHEN colD = '0' OR colE = '0' THEN '0' END) de_zero
                 FROM (SELECT colC, colD, colE
                         FROM some_table
                        WHERE colA = ArgA AND colB = argB)
             GROUP BY colC
             ORDER BY colC;
       END no_pipeline;
    END pipeline_example;
    ALTER PACKAGE pipeline_example COMPILE;Edited by: Earthlink on Nov 14, 2010 9:47 AM
    Edited by: Earthlink on Nov 14, 2010 11:31 AM
    Edited by: Earthlink on Nov 14, 2010 11:32 AM
    Edited by: Earthlink on Nov 20, 2010 12:04 PM
    Edited by: Earthlink on Nov 20, 2010 12:54 PM

    Earthlink wrote:
    Contrary to my understanding, the <font face="courier">with_pipeline</font> procedure runs 6 time slower than the legacy <font face="courier">no_pipeline</font> procedure. Am I missing something? Well, we're missing a lot here.
    Like:
    - a database version
    - how did you test
    - what data do you have, how is it distributed, indexed
    and so on.
    If you want to find out what's going on then use a TRACE with wait events.
    All nessecary steps are explained in these threads:
    HOW TO: Post a SQL statement tuning request - template posting
    http://oracle-randolf.blogspot.com/2009/02/basic-sql-statement-performance.html
    Another nice one is RUNSTATS:
    http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551378329289980701

  • How to Debug RFC Enabled FM ?

    Hello All,
             I want to debug an RFC Enabled FM.
    I've written a small Test program to check this.
    DATA: eenumber           LIKE     bapip2001-pernr,
          subtype           LIKE     bapip2001-subty,
          objectid           LIKE     bapip2001-objps,
          lockindicator     LIKE     bapip2001-sprps,
          validitybegin     LIKE     bapip2001-begda,
          validityend           LIKE     bapip2001-endda,
          recordnumber     LIKE     bapip2001-seqnr.
    CALL FUNCTION 'BAPI_ABSENCE_GETDETAIL
      EXPORTING
        employeenumber          = eenumber
        subtype                 = subtype
        objectid                = objectid
        lockindicator           = lockindicator
        validitybegin           = validitybegin
        validityend             = validityend
        recordnumber            = recordnumber
    * IMPORTING
    *   RETURN                  =
    *   START                   =
    *   END                     =
    *   ABSENCETYPE             =
    *   ABSENCEDAYS             =
    *   ABSENCEHOURS            =
    *   NAMEOFABSENCETYPE       =
    IF sy-subrc <> 0.
      WRITE:/ 'UNsuccessful'.
    ENDIF.
    When a Break Point is kept at the above FM and When I press F5 the cursor is going into the FM .
    But when I specify the Destination in the Call Statement as :
    CALL FUNCTION 'BAPI_ABSENCE_GETDETAIL' DESTINATION 'SID_010'
      EXPORTING
        employeenumber          = eenumber
        subtype                 = subtype
        objectid                = objectid
        lockindicator           = lockindicator
        validitybegin           = validitybegin
        validityend             = validityend
        recordnumber            = recordnumber
    * IMPORTING
    *   RETURN                  =
    *   START                   =
    *   END                     =
    *   ABSENCETYPE             =
    *   ABSENCEDAYS             =
    *   ABSENCEHOURS            =
    *   NAMEOFABSENCETYPE       =
    The control is not going into the FM.
    Can any one tell me how to debug the FM within a different system ?
    Regards,
    Deepu.K

    Hi Deepu,
    Your function module is at other system and you are calling it at some other system.
    I hope you know on which system your function module exists.
    First debug your coding at your system where you are calling this RFC Function Module and go to that point where your function module starts,  now check the export data here
    And
    go to that system where this function module exists and give the same export data there and debug this Function Module at that system.
    Reward points, if helpful,
    Sandeep Kaushik

  • How to define a view on a table function

    I have a defined a pipelined table function in a package and can return data from it using:
    select * from table(mtreport.FN_GET_JOBS_FOR_PROJECT(?));How can I define a view on this so that users can select from it without having to know to use the 'table' syntax?
    select *
    from   vw_jobs_for_project
    where id = ?I've tried this, but it doesn't work
    CREATE OR REPLACE VIEW vw_jobs_for_project (PROJECT_ID, NAME) AS
    SELECT     PROJECT_ID, NAME
    FROM     table(mtreport.FN_GET_JOBS_FOR_PROJECT(PROJECT_ID));
    ERROR at line 3:
    ORA-00904: "PROJECT_ID": invalid identifier

    views do not accept input parameters in the way that you want to use. you can define a CONTEXT parameter, but the users would need to set the context value before selecting from the view, so you'll still need to train them to do something new.
    example:
    create or replace context my_context using pkg_context;
    <br>
    create or replace package pkg_context is
      procedure set_context(p_parameter in varchar2, p_value in varchar2);
      function get_context(p_parameter in varchar2) return varchar2;
    end;
    show errors
    create or replace package body pkg_context is
      CONTEXT_NAME constant all_context.namespace%type := 'MY_CONTEXT';
      procedure set_context(p_parameter in varchar2, p_value in varchar2) is
      begin
        dbms_session.set_context(CONTEXT_NAME, p_parameter, p_value);
      end;
      function get_context(p_parameter in varchar2) return varchar2 is
      begin
        return sys_context(CONTEXT_NAME, p_parameter);
      end;
    end;
    show errors
    create or replace view tree_view as
    select level lvl, chid
    from tree
    connect by prior parid=chid
    start with chid = sys_context('MY_CONTEXT','CHID');
    -- at runtime
    exec pkg_context.set_context('CHID', 14)
    select * from tree_view;

  • How to DEBUG a function module running in background mode? Please help!

    Hi Experts,
       I am calling a function module in my ABAP code in background module using the following syntax:
      CALL FUNCTION 'YBBC2_CREATE_SNAPSHOT' IN BACKGROUND TASK
              TABLES
                itab_std_format_inv = itab_std_format_inv
                itab_snapshot_inv = itab_snapshot_inv.
            COMMIT WORK.
    If I put the breakpoint in the CALL FUNCTION line and execute the program, the debugger does not take me to the valled function module. This may be because I am running the function module as background task.
    I cannot comment this  "IN BACKGROUND TASK" statement as well since i am debugging in Quality system where I don't have change access.
    So how to DEBUG a function module running in background mode? Please help!
    Thanks
    Gopal

    Hi,
    You could try to use the following trick:
    (1) Put an endless loop into the coding of your function module where you want to start debugging, e.g.
      DATA:
        lx_exit_loop(1)     TYPE c.
      lx_exit_loop = ' '.
      DO.
        IF ( lx_exit_loop = 'X' ).
          EXIT.
        ENDIF.
      ENDDO.
    (2) Call your function module in background task
    (3) Call transaction SM50 and search for the background process.
    (3) Choose from menu Program/Mode -> Program -> Debugging
    Now you the debugger should bring you right to your endless loop. Set lx_loop_exit = 'X' in the debugger and continue (F5 or F6).
    <b>Reward points</b>
    Regards

  • Pipeline Table Function returning a fraction of data

    My current project involves migrating an Oracle database to a new structure based on the new client application requirements. I would like to use pipelined table functions as it seems as though that would provide the best performance.
    The first table has about 65 fields, about 75% of which require some type of recoding for the new app. I have written a function for each transformation and have all of these functions stored in a package. If I do:
    create new_table as select (
    pkg_name.function1(old_field1),
    pkg_name.function2(old_field2),
    pkg_name.function3(old_field3),
    it runs with out any errors but takes about 3 1/2 hours. There are a little more than 10 million rows in the table.
    I wrote a function that is passed the old table as a cursor, runs all the functions for the transformations and then pipes the new row back to the insert statement that called the function. It is incredibly fast but only returns .025% of the data (about 50 rows out of my sample table of 200,000). It does not throw any errors.
    So I am trying to determine what is going on. Perhaps one of my functions has a bug. If there was would cause the row to be kicked out? There are 40 or so functions so tracking this down has been a bit of a bear.
    Any advice as to how I might resolve this would be much appreciated.
    Thanks
    Dan

    . I would like to use pipelined table functions as it seems as though that would provide the best performanceUh huh...
    it runs with out any errors but takes about 3 1/2 hours. There are a little more than 10 million rows in the table.Not the first time a lovely theory has been killed by an ugly fact. Did you do any bench marks to see whether the pipelined functions did offer performance benefits over doing it some other way?
    From the context of your comments I think you are trying to a populate a new table from a single old table. Is this the case? If so I would have thought a straightforward CTAS with normal functions would be more appropriate: pipelined functions are really meant for situations in which one input produced more than one output. Anyway, ifr we are to help you I think you need to give us more details about how this process works and post a sample transformation function.
    There are 40 or so functions so tracking this down has been a bit of a bear.The teaching is: we should code one function and get that working before moving on to the next one. Which might not seem like a helpful thing to say, but the best lesson is often "I'll do it differently next time".
    Cheers, APC

Maybe you are looking for

  • How can I fix a nav bar that wraps to a second line?

    I have a single line of text on the navigation bar while I'm working in iweb but when published it wraps to a second line. I tried extending the page width which seemed to help on my home page but the other pages still have 2 lines.

  • OIM Provisioning - Error during OID Create User Task

    Hi, I am getting the following error during OIM Provisioning to OID (Create User Task). I added few more attributes to the OID_USR form and then to the "OID User" Process Definition. Also, I added the Code/Decode Key Values in AttrName.Prov.Map.OID.

  • Table Name or Function Module to find out all the Screens & Subscreens for

    Hello Experts,       Table Name or Function Module to find out all the Screens & Subscreens for all T-Codes Helpful Answer will b rewarded Arif Shaik

  • Viewing DPS folio on Content Viewer on PC

    I am developing a DPS folio on a Mac for publication on iOS devices. I have a co-worker who needs to review my content on a PC. He is not using Adobe apps but has downloaded the Content Viewer on his PC. I have shared my folio with him and he can rea

  • Gray screen of death on startup - Please Help!

    Hey everyone, my mini is 6 days old and is giving me some trouble. I used it just fine last night, shut it down, and this evening it won't boot up. It gets stuck at the gray screen with the spinning progress wheel. I unplugged all the peripherals, in