CREATE OR REPLACE PACKAGE tab2keyval_pkg AS
FUNCTION describe(tab IN OUT DBMS_TF.TABLE_T,
id_cols IN DBMS_TF.COLUMNS_T)
RETURN DBMS_TF.DESCRIBE_T;
PROCEDURE fetch_rows;
END tab2keyval_pkg;
Package created.
CREATE OR REPLACE PACKAGE BODY tab2keyval_pkg AS
FUNCTION describe(tab IN OUT DBMS_TF.TABLE_T,
id_cols IN DBMS_TF.COLUMNS_T)
RETURN DBMS_TF.DESCRIBE_T
AS
new_cols DBMS_TF.COLUMNS_NEW_T;
col_id PLS_INTEGER := 1;
BEGIN
FOR I IN 1 .. tab.COLUMN.COUNT LOOP
tab.column(i).pass_through := FALSE;
TAB.COLUMN(i).for_read := TRUE;
-- Unless this is one of ID-columns
FOR J IN 1 .. id_cols.COUNT LOOP
IF ( tab.COLUMN(i).description.name = id_cols(j) ) THEN
tab.column(i).pass_through := TRUE;
TAB.COLUMN(i).for_read := FALSE;
END IF;
END LOOP;
END LOOP;
-- new columns: key_name, key_val_char, key_val_num, key_val_date
NEW_COLS(col_id) := dbms_tf.column_metadata_t(name => 'KEY_NAME',
TYPE => dbms_tf.type_varchar2);
NEW_COLS(col_id + 1) := dbms_tf.column_metadata_t(name => 'KEY_VAL_CHAR',
TYPE => dbms_tf.type_varchar2);
NEW_COLS(col_id + 2) := dbms_tf.column_metadata_t(name => 'KEY_VAL_NUMBER',
TYPE => dbms_tf.type_number);
NEW_COLS(col_id + 3) := dbms_tf.column_metadata_t(name => 'KEY_VAL_DATE',
TYPE => dbms_tf.type_date);
RETURN DBMS_TF.DESCRIBE_T(new_columns => new_cols, row_replication=>true);
END;
PROCEDURE fetch_rows IS
inp_rs DBMS_TF.row_set_t;
env dbms_tf.env_t := dbms_tf.get_env();
colcnt PLS_INTEGER;
rowcnt PLS_INTEGER;
repfac dbms_tf.tab_naturaln_t;
namecol dbms_tf.tab_varchar2_t;
valnumcol dbms_tf.tab_number_t;
valcharcol dbms_tf.tab_varchar2_t;
valdatecol dbms_tf.tab_date_t;
BEGIN
DBMS_TF.get_row_set(inp_rs, rowcnt, colcnt);
FOR i IN 1 .. rowcnt LOOP
repfac(i) := 0;
END LOOP;
FOR r IN 1 .. rowcnt LOOP
FOR c IN 1 .. colcnt LOOP
IF env.get_columns(c).type = dbms_tf.type_number then
repfac(r) := repfac(r) + 1;
namecol(nvl(namecol.last+1,1)) := replace(env.get_columns(c).name,'"');
valnumcol(NVL(valnumcol.last+1,1)) := inp_rs(c).tab_number(r);
valcharcol(NVL(valcharcol.last+1,1)) := NULL;
valdatecol(NVL(valdatecol.last+1,1)) := NULL;
ELSIF env.get_columns(c).type = dbms_tf.type_varchar2 then
repfac(r) := repfac(r) + 1;
namecol(nvl(namecol.last+1,1)) := replace(env.get_columns(c).name,'"');
valcharcol(NVL(valcharcol.last+1,1)) := inp_rs(c).tab_varchar2(r);
valnumcol(NVL(valnumcol.last+1,1)) := NULL;
valdatecol(NVL(valdatecol.last+1,1)) := NULL;
ELSIF env.get_columns(c).type = dbms_tf.type_date then
repfac(r) := repfac(r) + 1;
namecol(nvl(namecol.last+1,1)) := replace(env.get_columns(c).name,'"');
valdatecol(NVL(valdatecol.last+1,1)) := inp_rs(c).tab_date(r);
valcharcol(NVL(valcharcol.last+1,1)) := NULL;
valnumcol(NVL(valnumcol.last+1,1)) := NULL;
END IF;
END LOOP;
END LOOP;
dbms_tf.row_replication(replication_factor => repfac);
dbms_tf.put_col(1, namecol);
dbms_tf.put_col(2, valcharcol);
dbms_tf.put_col(3, valnumcol);
dbms_tf.put_col(4, valdatecol);
END;
END tab2keyval_pkg;
Package Body created.
CREATE OR REPLACE FUNCTION tab2keyval(tab TABLE, id_cols COLUMNS) RETURN TABLE
PIPELINED ROW POLYMORPHIC USING tab2keyval_pkg;
Function created.
SELECT *
FROM tab2keyval(scott.emp, COLUMNS(empno))
EMPNO | KEY_NAME | KEY_VAL_CHAR | KEY_VAL_NUMBER | KEY_NAME_DATE | 7839 | ENAME | KING | - | - | 7839 | JOB | PRESIDENT | - | - | 7839 | MGR | - | - | - | 7839 | HIREDATE | - | - | 17-NOV-81 | 7839 | SAL | - | 5000 | - | 7839 | COMM | - | - | - | 7839 | DEPTNO | - | 10 | - | 7698 | ENAME | BLAKE | - | - | 7698 | JOB | MANAGER | - | - | 7698 | MGR | - | 7839 | - | 7698 | HIREDATE | - | - | 01-MAY-81 | 7698 | SAL | - | 2850 | - | 7698 | COMM | - | - | - | 7698 | DEPTNO | - | 30 | - | 7782 | ENAME | CLARK | - | - | 7782 | JOB | MANAGER | - | - | 7782 | MGR | - | 7839 | - | 7782 | HIREDATE | - | - | 09-JUN-81 | 7782 | SAL | - | 2450 | - | 7782 | COMM | - | - | - | 7782 | DEPTNO | - | 10 | - | 7566 | ENAME | JONES | - | - | 7566 | JOB | MANAGER | - | - | 7566 | MGR | - | 7839 | - | 7566 | HIREDATE | - | - | 02-APR-81 | 7566 | SAL | - | 2975 | - | 7566 | COMM | - | - | - | 7566 | DEPTNO | - | 20 | - | 7788 | ENAME | SCOTT | - | - | 7788 | JOB | ANALYST | - | - | 7788 | MGR | - | 7566 | - | 7788 | HIREDATE | - | - | 19-APR-87 | 7788 | SAL | - | 3000 | - | 7788 | COMM | - | - | - | 7788 | DEPTNO | - | 20 | - | 7902 | ENAME | FORD | - | - | 7902 | JOB | ANALYST | - | - | 7902 | MGR | - | 7566 | - | 7902 | HIREDATE | - | - | 03-DEC-81 | 7902 | SAL | - | 3000 | - | 7902 | COMM | - | - | - | 7902 | DEPTNO | - | 20 | - | 7369 | ENAME | SMITH | - | - | 7369 | JOB | CLERK | - | - | 7369 | MGR | - | 7902 | - | 7369 | HIREDATE | - | - | 17-DEC-80 | 7369 | SAL | - | 800 | - | 7369 | COMM | - | - | - | 7369 | DEPTNO | - | 20 | - | 7499 | ENAME | ALLEN | - | - | 7499 | JOB | SALESMAN | - | - | 7499 | MGR | - | 7698 | - | 7499 | HIREDATE | - | - | 20-FEB-81 | 7499 | SAL | - | 1600 | - | 7499 | COMM | - | 300 | - | 7499 | DEPTNO | - | 30 | - | 7521 | ENAME | WARD | - | - | 7521 | JOB | SALESMAN | - | - | 7521 | MGR | - | 7698 | - | 7521 | HIREDATE | - | - | 22-FEB-81 | 7521 | SAL | - | 1250 | - | 7521 | COMM | - | 500 | - | 7521 | DEPTNO | - | 30 | - | 7654 | ENAME | MARTIN | - | - | 7654 | JOB | SALESMAN | - | - | 7654 | MGR | - | 7698 | - | 7654 | HIREDATE | - | - | 28-SEP-81 | 7654 | SAL | - | 1250 | - | 7654 | COMM | - | 1400 | - | 7654 | DEPTNO | - | 30 | - | 7844 | ENAME | TURNER | - | - | 7844 | JOB | SALESMAN | - | - | 7844 | MGR | - | 7698 | - | 7844 | HIREDATE | - | - | 08-SEP-81 | 7844 | SAL | - | 1500 | - | 7844 | COMM | - | 0 | - | 7844 | DEPTNO | - | 30 | - | 7876 | ENAME | ADAMS | - | - | 7876 | JOB | CLERK | - | - | 7876 | MGR | - | 7788 | - | 7876 | HIREDATE | - | - | 23-MAY-87 | 7876 | SAL | - | 1100 | - | 7876 | COMM | - | - | - | 7876 | DEPTNO | - | 20 | - | 7900 | ENAME | JAMES | - | - | 7900 | JOB | CLERK | - | - | 7900 | MGR | - | 7698 | - | 7900 | HIREDATE | - | - | 03-DEC-81 | 7900 | SAL | - | 950 | - | 7900 | COMM | - | - | - | 7900 | DEPTNO | - | 30 | - | 7934 | ENAME | MILLER | - | - | 7934 | JOB | CLERK | - | - | 7934 | MGR | - | 7782 | - | 7934 | HIREDATE | - | - | 23-JAN-82 | 7934 | SAL | - | 1300 | - | 7934 | COMM | - | - | - | 7934 | DEPTNO | - | 10 | - |
---|