PRO
PRO REFERENCED INDEXES (sqlobj$plan)
PRO ~~~~~~~~~~~~~~~~~~
COL sql_id FOR A13;
COL signature FOR 99999999999999999999;
COL sql_handle FOR A20;
COL plan_name FOR A30;
COL plan_id FOR 9999999999;
COL plan_hash FOR 9999999999;
COL plan_hash2 FOR 9999999999;
COL plan_hash_full FOR 9999999999;
COL indexed_columns FOR A200;
COL table_owner FOR A30;
COL table_name FOR A30;
COL index_owner FOR A30;
COL index_name FOR A30;
COL sql_text FOR A100 TRUNC;
COL description FOR A100 HEA 'Description' WOR;
COL created FOR A23;
COL last_modified FOR A23;
COL last_executed FOR A23;
COL timestamp FOR A19;
BREAK ON plan_name SKIP PAGE ON plan_id ON description;
--
-- only works from PDB. do not use CONTAINERS(table_name) since it causes ORA-00600: internal error code, arguments: [kkdolci1], [], [], [], [], [], [],
WITH
FUNCTION compute_sql_id (sql_text IN CLOB)
RETURN VARCHAR2 IS
 BASE_32 CONSTANT VARCHAR2(32) := '0123456789abcdfghjkmnpqrstuvwxyz';
 l_raw_128 RAW(128);
 l_hex_32 VARCHAR2(32);
 l_low_16 VARCHAR(16);
 l_q3 VARCHAR2(8);
 l_q4 VARCHAR2(8);
 l_low_16_m VARCHAR(16);
 l_number NUMBER;
 l_idx INTEGER;
 l_sql_id VARCHAR2(13);
 function_returned_an_error EXCEPTION;
 PRAGMA EXCEPTION_INIT(function_returned_an_error, -28817); -- ORA-28817: PL/SQL function returned an error.
BEGIN
 l_raw_128 := /* use md5 algorithm on sql_text and produce 128 bit hash */
 SYS.DBMS_CRYPTO.hash(TRIM(CHR(0) FROM sql_text)||CHR(0), SYS.DBMS_CRYPTO.hash_md5);
 l_hex_32 := RAWTOHEX(l_raw_128); /* 32 hex characters */
 l_low_16 := SUBSTR(l_hex_32, 17, 16); /* we only need lower 16 */
 l_q3 := SUBSTR(l_low_16, 1, 8); /* 3rd quarter (8 hex characters) */
 l_q4 := SUBSTR(l_low_16, 9, 8); /* 4th quarter (8 hex characters) */
 /* need to reverse order of each of the 4 pairs of hex characters */
 l_q3 := SUBSTR(l_q3, 7, 2)||SUBSTR(l_q3, 5, 2)||SUBSTR(l_q3, 3, 2)||SUBSTR(l_q3, 1, 2);
 l_q4 := SUBSTR(l_q4, 7, 2)||SUBSTR(l_q4, 5, 2)||SUBSTR(l_q4, 3, 2)||SUBSTR(l_q4, 1, 2);
 /* assembly back lower 16 after reversing order on each quarter */
 l_low_16_m := l_q3||l_q4;
 /* convert to number */
 SELECT TO_NUMBER(l_low_16_m, 'xxxxxxxxxxxxxxxx') INTO l_number FROM DUAL;
 /* 13 pieces base-32 (5 bits each) make 65 bits. we do have 64 bits */
 FOR i IN 1 .. 13
 LOOP
 l_idx := TRUNC(l_number / POWER(32, (13 - i))); /* index on BASE_32 */
 l_sql_id := l_sql_id||SUBSTR(BASE_32, (l_idx + 1), 1); /* stitch 13 characters */
 l_number := l_number - (l_idx * POWER(32, (13 - i))); /* for next piece */
 END LOOP;
 RETURN l_sql_id;
EXCEPTION
  WHEN function_returned_an_error THEN
    RETURN 'ORA-28817';
END compute_sql_id;
i AS (
SELECT ic.table_owner, ic.table_name, ic.index_owner, ic.index_name, 
       LISTAGG('"'||ic.table_name||'"."'||ic.column_name||'"', ' ' ON OVERFLOW TRUNCATE) WITHIN GROUP (ORDER BY ic.column_position) AS indexed_columns
  FROM dba_ind_columns ic
 GROUP BY
       ic.table_owner, ic.table_name, ic.index_owner, ic.index_name
), 
b AS (
SELECT p.signature,
       t.sql_handle,
       o.name AS plan_name,
       p.plan_id,
       TO_NUMBER(EXTRACTVALUE(XMLTYPE(p.other_xml),'/*/info[@type = "plan_hash"]')) AS plan_hash, -- normal plan_hash_value
       TO_NUMBER(EXTRACTVALUE(XMLTYPE(p.other_xml),'/*/info[@type = "plan_hash_2"]')) AS plan_hash_2, -- plan_hash_value ignoring transient object names (must be same than plan_id for a baseline to be used) 
       TO_NUMBER(EXTRACTVALUE(XMLTYPE(p.other_xml),'/*/info[@type = "plan_hash_full"]')) AS plan_hash_full, -- adaptive plan (must be different than plan_hash_2 on loaded plans) 
       DECODE(BITAND(o.flags, 1),   0, 'NO', 'YES') AS enabled,
       DECODE(BITAND(o.flags, 2),   0, 'NO', 'YES') AS accepted,
       DECODE(BITAND(o.flags, 4),   0, 'NO', 'YES') AS fixed,
       DECODE(BITAND(o.flags, 64),  0, 'YES', 'NO') AS reproduced,
       DECODE(BITAND(o.flags, 128), 0, 'NO', 'YES') AS autopurge,
       DECODE(BITAND(o.flags, 256), 0, 'NO', 'YES') AS adaptive, 
       SUBSTR(x.outline_hint, INSTR(x.outline_hint, '(', 1, 2) + 1, INSTR(x.outline_hint, '))') - INSTR(x.outline_hint, '(', 1, 2) - 1) AS indexed_columns,
       t.sql_text,
       a.description,
       a.origin,
       a.created,
       a.last_modified,
       o.last_executed,
       p.timestamp
  FROM sys.sqlobj$plan p,
       XMLTABLE('other_xml/outline_data/hint' PASSING XMLTYPE(p.other_xml) COLUMNS outline_hint VARCHAR2(500) PATH '.') x,
       sys.sqlobj$ o,
       sys.sqlobj$auxdata a,
       sys.sql$text t
 WHERE p.signature = :cs_signature
   AND p.category = 'DEFAULT'
   AND p.obj_type = &&cs_obj_type. /* 1:profile, 2:baseline, 3:patch */
   AND p.other_xml IS NOT NULL
   AND x.outline_hint LIKE 'INDEX%(%(%))'
   AND o.signature = p.signature
   AND o.category = p.category
   AND o.obj_type = p.obj_type
   AND o.plan_id = p.plan_id
   AND a.signature = o.signature
   AND a.category = o.category
   AND a.obj_type = o.obj_type
   AND a.plan_id = o.plan_id
   AND t.signature = a.signature
),
x AS (
SELECT DISTINCT
       compute_sql_id(b.sql_text) AS sql_id,
       b.sql_handle,
       b.plan_name,
       b.plan_id,
       b.plan_hash,
       b.plan_hash_2,
       b.plan_hash_full,
       b.enabled,
       b.accepted,
       b.fixed,
       b.reproduced,
       b.autopurge,
       b.adaptive,
       b.indexed_columns,
       NVL(i.table_owner, '"missing"') AS table_owner,
       NVL(i.table_name, '"missing"') AS table_name,
       NVL(i.index_owner, '"missing"') AS index_owner,
       NVL(i.index_name, '"missing"') AS index_name,
       DBMS_LOB.SUBSTR(b.sql_text, 1000) AS sql_text,
       b.description,
       b.created,
       b.last_modified,
       b.last_executed,
       b.timestamp
  FROM b, i
 WHERE i.indexed_columns(+) = b.indexed_columns
)
SELECT /* comment out unwanted columns */
      --  x.sql_id,
      --  x.sql_text,
      --  x.sql_handle,
       x.plan_name,
       x.plan_id,
      --  x.plan_hash,
      --  x.plan_hash_2,
      --  x.plan_hash_full,
       x.enabled,
       x.accepted,
      --  x.fixed,
      --  x.reproduced,
      --  x.autopurge,
      --  x.adaptive,
       x.indexed_columns,
      --  x.table_owner, 
      --  x.table_name, 
       x.index_owner, 
       x.index_name,
      --  x.created,
      --  x.last_modified,
      --  x.last_executed,
      --  x.timestamp,
       x.description
  FROM x
 ORDER BY
      --  x.sql_id,
       x.plan_name,
       x.indexed_columns,
       x.table_owner, 
       x.table_name, 
       x.index_owner, 
       x.index_name
/
CLEAR BREAK;
PRO
PRO CBO_HINTS (sqlobj$plan)
PRO ~~~~~~~~~
COL plan_id  FOR 99999999990;
COL category FOR A10;
COL outline_hint FOR A300;
-- only works from PDB. do not use CONTAINERS(table_name) since it causes ORA-00600: internal error code, arguments: [kkdolci1], [], [], [], [], [], [],
BREAK ON plan_id SKIP PAGE ON category;
SELECT d.plan_id, d.category, x.outline_hint
  FROM sys.sqlobj$plan d, XMLTABLE('other_xml/outline_data/hint' PASSING XMLTYPE(d.other_xml) COLUMNS outline_hint VARCHAR2(500) PATH '.') x
 WHERE d.obj_type = &&cs_obj_type. /* 1:profile, 2:baseline, 3:patch */ 
   AND d.other_xml IS NOT NULL
   AND d.signature = :cs_signature
/
CLEAR BREAK;