-------------------------------------------------------------------------------- -- Author: Alberto Dell'Era -- Copyright: (c) 2008, 2009, 2010, 2012, 2013 Alberto Dell'Era http://www.adellera.it -------------------------------------------------------------------------------- procedure extract_tag_value( p_xml clob, p_tag_name varchar2, p_tag_text out varchar2) is l_start int; l_end int; l_start_marker varchar2(30) := '<' || p_tag_name; l_end_marker varchar2(30) := '' ; l_next_chars varchar2(2 char); begin l_start := dbms_lob.instr (p_xml, l_start_marker, 1); if l_start = 0 or l_start is null then return; end if; l_start := l_start + length(l_start_marker); l_next_chars := dbms_lob.substr (p_xml, 2, l_start); if l_next_chars is null or l_next_chars = '/>' then return; end if; l_start := l_start + 1; l_end := dbms_lob.instr (p_xml, l_end_marker, l_start); if l_end = 0 or l_end is null then print ('error: end marker not found for tag '||p_tag_name); return; end if; if l_end - l_start > 32767 then print ('error: tag too long for tag '||p_tag_name); return; end if; p_tag_text := dbms_lob.substr (p_xml, l_end - l_start, l_start); end extract_tag_value; function extract_tag( p_xml varchar2, p_tag_name varchar2, p_occurrence int, p_attributes out varchar2, p_value out varchar2) return boolean is l_start_section varchar2(30) := '<' || p_tag_name || ' '; l_end_tag varchar2(30) := ''; l_start int; l_end_start_tag int; l_end int; begin l_start := instr (p_xml, l_start_section, 1, p_occurrence); if l_start = 0 or l_start is null then return false; end if; l_start := l_start + length(l_start_section); l_end_start_tag := instr (p_xml, '>', l_start); if l_end_start_tag = 0 or l_end_start_tag is null then print ('xml error: xml misformat for tag ' || p_tag_name); return false; end if; if substr(p_xml, l_end_start_tag-1, 1) = '/' then -- p_attributes := substr (p_xml, l_start, (l_end_start_tag-1) - l_start ); p_value := null; else -- value p_attributes := substr (p_xml, l_start, l_end_start_tag - l_start ); l_end := instr (p_xml, l_end_tag, l_end_start_tag+1); if l_end = 0 or l_end is null then print ('xml error: xml misformat 2 for tag ' || p_tag_name); return false; end if; p_value := substr (p_xml, l_end_start_tag+1, l_end - l_end_start_tag - 1); end if; return true; end extract_tag; function get_attribute( p_attributes_str varchar2, p_name varchar2 ) return varchar2 is l_pos int; l_start int; l_end int; begin l_pos := instr (p_attributes_str, p_name||'="'); if l_pos = 0 then return null; end if; l_start := instr (p_attributes_str, '"', l_pos); if l_start = 0 then return '??'; end if; l_start := l_start + 1; l_end := instr (p_attributes_str, '"', l_start); if l_end = 0 then return '???'; end if; return substr (p_attributes_str, l_start, l_end - l_start); end get_attribute; procedure print_peeked_binds(p_other_xml clob) is l_peeked_binds_values long; l_peeked_binds_types long; l_peeked_str long; l_bind_num int; l_nam varchar2(30 char); l_dty int; l_frm int; l_mxl int; l_value_hex long; l_value_raw long raw; l_value long; l_type varchar2(100); l_value_varchar2 varchar2(32767); l_value_nvarchar2 nvarchar2(32767); l_value_number number; l_value_date date; l_value_timestamp timestamp; &COMM_IF_LT_10G. l_value_binary_float binary_float; &COMM_IF_LT_10G. l_value_binary_double binary_double; l_value_rowid rowid; l_bind_attributes long; l_bind_found boolean; begin if p_other_xml is null then return; end if; extract_tag_value ( p_other_xml, 'peeked_binds', l_peeked_str); if l_peeked_str is null then return; end if; if 1=0 then print ('peeked binds : original peeked bind xml section:"'||l_peeked_str||'"'); --return; end if; -- format: 58 -- or (for nulls) -- max is the MaXLength in bytes l_bind_num := 1; l_peeked_binds_values := 'peeked binds values:'; l_peeked_binds_types := 'peeked binds types :'; loop l_bind_found := extract_tag( l_peeked_str, 'bind', l_bind_num, l_bind_attributes, l_value_hex ); --print('peeked binds : attrs=['||l_bind_attributes||'] val=['||l_value_hex||']'); exit when not l_bind_found; begin l_value_raw := hextoraw (l_value_hex); exception when others then raise_application_error (-20089, 'l_value_hex="'||l_value_hex||'" '||sqlerrm); end; l_nam := get_attribute (l_bind_attributes, 'nam'); l_mxl := to_number (get_attribute (l_bind_attributes, 'mxl')); l_dty := to_number (get_attribute (l_bind_attributes, 'dty')); l_frm := trim(get_attribute (l_bind_attributes, 'frm')); -- For dty codes, see "Call Interface Programmer's Guide", "Datatypes" -- Also, "select text from dba_views where view_name = 'USER_TAB_COLS'" gives -- a decode function to interpret them. charsetform is the "frm" in the xml string. -- Generally frm=2 means NLS charset. if l_dty = 1 and l_frm = '1' then -- varchar2 dbms_stats.convert_raw_value (l_value_raw, l_value_varchar2); l_value := ''''||l_value_varchar2||''''; l_type := 'varchar2('||l_mxl||')'; elsif l_dty = 1 and l_frm = '2' then -- nvarchar2 dbms_stats.convert_raw_value_nvarchar (l_value_raw, l_value_nvarchar2); l_value := ''''||l_value_nvarchar2||''''; l_type := 'nvarchar2('||l_mxl||')'; elsif l_dty = 2 then -- number dbms_stats.convert_raw_value (l_value_raw, l_value_number); l_value := nvl (to_char(l_value_number), 'null'); l_type := 'number('||l_mxl||')'; elsif l_dty = 12 then -- date dbms_stats.convert_raw_value (l_value_raw, l_value_date); l_value := nvl (to_char (l_value_date, 'yyyy/mm/dd hh24:mi:ss'), 'null'); l_type := 'date'; elsif l_dty = 23 then -- raw l_value := nvl (to_char(l_value_hex), 'null'); l_type := 'raw('||l_mxl||')'; elsif l_dty = 69 then -- rowid (not fully tested) dbms_stats.convert_raw_value_rowid (l_value_raw, l_value_rowid); l_value := nvl (rowidtochar (l_value_rowid), 'null'); l_type := 'rowid'; elsif l_dty = 96 and l_frm = '1' then -- char dbms_stats.convert_raw_value (l_value_raw, l_value_varchar2); l_value := ''''||l_value_varchar2||''''; l_type := 'char('||l_mxl||')'; elsif l_dty = 96 and l_frm = '2' then -- nchar dbms_stats.convert_raw_value_nvarchar (l_value_raw, l_value_nvarchar2); l_value := ''''||l_value_nvarchar2||''''; l_type := 'nchar('||l_mxl||')'; &COMM_IF_LT_10G. elsif l_dty = 100 then -- binary_float &COMM_IF_LT_10G. dbms_stats.convert_raw_value (l_value_raw, l_value_binary_float); &COMM_IF_LT_10G. l_value := to_char (l_value_binary_float); &COMM_IF_LT_10G. l_type := 'binary_float'; &COMM_IF_LT_10G. elsif l_dty = 101 then -- binary_double &COMM_IF_LT_10G. dbms_stats.convert_raw_value (l_value_raw, l_value_binary_double); &COMM_IF_LT_10G. l_value := to_char (l_value_binary_double); &COMM_IF_LT_10G. l_type := 'binary_double'; elsif l_dty = 180 then -- timestamp l_value := '(hex)'||l_value_hex; -- found no way to convert in 10.2 l_type := 'timestamp'; elsif l_dty = 181 then -- timestamp with time zone l_value := '(hex)'||l_value_hex; -- found no way to convert in 10.2 l_type := 'timestamp with time zone'; elsif l_dty = 182 then -- interval year to month l_value := '(hex)'||l_value_hex; -- found no way to convert in 10.2 l_type := 'interval year to month'; elsif l_dty = 183 then -- interval day to second l_value := '(hex)'||l_value_hex; -- found no way to convert in 10.2 l_type := 'interval day to second'; elsif l_dty = 231 then -- timestamp with local time zone l_value := '(hex)'||l_value_hex; -- found no way to convert in 10.2 l_type := 'timestamp with local time zone'; else l_value := '(hex)'||l_value_hex; l_type := '[dty='||l_dty||' frm='||l_frm||' mxl='||l_mxl||']'; end if; l_peeked_binds_values := l_peeked_binds_values || ' ' || l_nam || ' = ' || l_value|| ','; l_peeked_binds_types := l_peeked_binds_types || ' ' || l_nam || ' = ' || l_type || ','; l_bind_num := l_bind_num + 1; end loop; l_peeked_binds_values := rtrim (l_peeked_binds_values, ','); l_peeked_binds_types := rtrim (l_peeked_binds_types , ','); print (l_peeked_binds_values); print (l_peeked_binds_types); end print_peeked_binds; procedure print_notes(p_other_xml clob) is l_xml long; l_info_num int; l_info_found boolean; l_notes long; l_info_attributes varchar2(200); l_info_value varchar2(1000); l_info_type varchar2(200); begin if p_other_xml is null then return; end if; if dbms_lob.getlength( p_other_xml) > 32767 then print('print_notes: warning: cannot look for notes, other_xml too long'); return; end if; l_xml := dbms_lob.substr (p_other_xml, 32767, 1); l_info_num := 1; loop l_info_found := extract_tag( l_xml, 'info', l_info_num, l_info_attributes, l_info_value ); --print('print_notes : attrs=['||l_info_attributes||'] val=['||l_info_value||']'); exit when not l_info_found; l_info_type := get_attribute( l_info_attributes, 'type' ); if l_info_type not in ( 'plan_hash', 'db_version', 'parse_schema', 'plan_hash_2' ) then l_notes := l_notes || l_info_type || '=' || l_info_value || ' '; end if; l_info_num := l_info_num + 1; end loop; if l_notes is not null then print('notes : ' || l_notes ); end if; end print_notes; function adapt_projection(p_txt varchar2) return varchar2 is l_buf varchar2(4000) := replace( replace(p_txt, '"', ''), ' ', ''); l_open int := 1; l_clos int; begin loop l_open := instr(l_buf, '[', l_open); exit when l_open = 0 or l_open is null; l_clos := instr(l_buf, ']', l_open+1); exit when l_clos = 0 or l_clos is null; l_buf := substr(l_buf, 1, l_open-1) || substr(l_buf, l_clos+1); end loop; return substr(l_buf, 1, 1000); end adapt_projection; function adapt_predicate(p_txt varchar2) return varchar2 is l_buf varchar2(4000) := replace(p_txt, '"', ''); begin return l_buf; end adapt_predicate; procedure print_plan ( p_inst_id sys.gv_$sql.inst_id%type, p_address sys.gv_$sql.address%type, p_hash_value sys.gv_$sql.hash_value%type, p_child_number sys.gv_$sql.child_number%type, p_executions int, p_first_load_time date, p_last_load_time date, p_last_active_time date default null, -- null if not 10gR2+ p_sql_plan_baseline varchar2 default null -- null if not 11g+ ) is type access_predicates_t is table of sys.gv_$sql_plan.access_predicates%type index by binary_integer; type filter_predicates_t is table of sys.gv_$sql_plan.filter_predicates%type index by binary_integer; type others_t is table of sys.gv_$sql_plan.other %type index by binary_integer; type base_table_object_ids_t is table of varchar2(1) index by varchar2(30); l_access_predicates access_predicates_t; l_filter_predicates filter_predicates_t; l_others others_t; l_base_table_object_ids base_table_object_ids_t; l_base_object_id_char varchar2(30); l_plan scf_state_t; l_plan2 scf_state_t; l_plan3 scf_state_t; l_col_tag varchar2(10 char); l_execs int; l_other_tag sys.gv_$sql_plan.other_tag%type; l_id_min int := 1e6; l_id_max int := -1; l_id_string varchar2(10 char); l_tmp varchar2(1000 char); &COMM_IF_LT_10G. l_sql_id sys.gv_$sql.sql_id%type; l_cursor sys_refcursor; l_dbms_xplan_tag varchar2(10 char); l_dbms_xplan_format varchar2(50 char); begin if '&PLAN_LAST_OR_NULL.' = 'LAST_' then l_col_tag := 'last'; l_execs := 1; l_dbms_xplan_tag := ' LAST'; elsif '&PLAN_AVG_PER_EXEC.' = 'Y' then l_col_tag := '/exec'; l_execs := p_executions; else l_col_tag := 'raw'; l_execs := 1; -- a trick, of course end if; if l_execs <= 0 then l_execs := null; end if; for s in (select /*+ xplan_exec_marker */ -- 10.2.0.3 columns -- p.address, -- p.hash_value, &COMM_IF_LT_10G. p.sql_id, &COMM_IF_LT_10G. p.plan_hash_value, &COMM_IF_LT_10GR2. p.child_address, p.child_number, -- p.timestamp, p.operation, p.options, p.object_node, p.object#, p.object_owner, p.object_name, &COMM_IF_LT_10G. p.object_alias, &COMM_IF_LT_10G. p.object_type, p.optimizer, p.id, p.parent_id, p.depth, p.position, p.search_columns, p.cost, p.cardinality, p.bytes, p.other_tag, p.partition_start, p.partition_stop, p.partition_id, p.other, p.distribution, p.cpu_cost, p.io_cost, p.temp_space, &COMM_IF_NO_PREDS. p.access_predicates, &COMM_IF_NO_PREDS. p.filter_predicates, &COMM_IF_LT_10G. p.projection, --time &COMM_IF_LT_10G. p.qblock_name, &COMM_IF_LT_10G. p.remarks, &COMM_IF_LT_10GR2. p.other_xml, s.executions, s.&PLAN_LAST_OR_NULL.starts as starts, s.&PLAN_LAST_OR_NULL.output_rows as output_rows, s.&PLAN_LAST_OR_NULL.cr_buffer_gets as cr_buffer_gets, s.&PLAN_LAST_OR_NULL.cu_buffer_gets as cu_buffer_gets, s.&PLAN_LAST_OR_NULL.disk_reads as disk_reads, s.&PLAN_LAST_OR_NULL.disk_writes as disk_writes, s.&PLAN_LAST_OR_NULL.elapsed_time as elapsed_time, s.policy, s.estimated_optimal_size, s.estimated_onepass_size, s.last_memory_used, s.last_execution, s.last_degree, s.total_executions, s.optimal_executions, s.onepass_executions, s.multipasses_executions, s.active_time, s.max_tempseg_size, s.last_tempseg_size from sys.gv_$sql_plan p, sys.gv_$sql_plan_statistics_all s where p.inst_id = p_inst_id and s.inst_id(+) = p_inst_id and p.address = p_address and p.hash_value = p_hash_value and p.child_number = p_child_number and s.address(+) = p_address and s.hash_value(+) = p_hash_value and s.child_number(+) = p_child_number and p.id = s.id(+) order by p.id) loop if s.id < l_id_min then l_id_min := s.id; end if; if s.id > l_id_max then l_id_max := s.id; end if; &COMM_IF_LT_10G. l_sql_id := s.sql_id; &COMM_IF_LT_10G. if s.id = 1 then &COMM_IF_LT_10GR2. print_peeked_binds (s.other_xml); &COMM_IF_LT_10GR2. print_notes (s.other_xml); &COMM_IF_LT_10G. if p_sql_plan_baseline is not null then print('sql plan baseline : '||p_sql_plan_baseline); end if; &COMM_IF_LT_10G. end if; l_base_object_id_char := to_char(get_cache_base_table_object_id (s.object#)); if l_base_object_id_char is not null then l_base_table_object_ids (l_base_object_id_char) := 'X'; if :OPT_TABINFOS = 'BOTTOM' then m_all_referenced_object_ids(l_base_object_id_char) := 'X'; end if; end if; scf_add_elem (l_plan, 'CR+CU', (s.cr_buffer_gets + s.cu_buffer_gets) / l_execs, p_sep_mid => l_col_tag); &COMM_IF_NO_SELF scf_add_self (l_plan, 'CR+CU+', p_self_src => 'CR+CU'); scf_add_elem (l_plan, 'Ela', s.elapsed_time / l_execs, p_sep_mid => l_col_tag, p_sep_bot=>'usec'); &COMM_IF_NO_SELF scf_add_self (l_plan, 'Ela+', p_self_src => 'Ela'); scf_add_elem (l_plan, 'Starts', s.starts / l_execs, p_sep_mid => l_col_tag); scf_add_elem (l_plan, 'Id' , s.id , p_is_auxil => 'Y', p_self_is_id => 'Y'); scf_add_elem (l_plan, 'pId', s.parent_id, p_is_auxil => 'Y', p_self_is_pid => 'Y', p_is_hidden => 'Y'); /* scf_add_elem (l_plan, 'pId', s.parent_id); -- TEMP!! scf_add_elem (l_plan, 'remarks', s.remarks); -- TEMP!! scf_add_elem (l_plan, 'depth', s.depth); -- TEMP!! scf_add_elem (l_plan, 'position', s.position); -- TEMP!! scf_add_elem (l_plan, 'qblock', s.qblock_name); -- TEMP!! scf_add_elem (l_plan, 'optim', s.optimizer); -- TEMP!! scf_add_elem (l_plan, 'object#', s.object#); -- TEMP!!*/ scf_add_elem (l_plan, 'Operation', lpad (' ', s.depth) || s.operation||' '||s.options ); scf_add_elem (l_plan, 'Name', s.object_name); scf_add_elem (l_plan, 'Table', get_cache_obj_name (get_cache_base_table_object_id (s.object#))); scf_add_elem (l_plan, 'TQ', s.object_node); scf_add_elem (l_plan, 'Erows', s.cardinality); scf_add_elem (l_plan, 'Arows', s.output_rows / l_execs, p_sep_mid => l_col_tag); scf_add_elem (l_plan, 'Cost', s.cost); scf_add_elem (l_plan, 'IoCost', s.io_cost); scf_add_elem (l_plan, 'Psta', replace (s.partition_start, 'ROW LOCATION', 'ROWID') ); scf_add_elem (l_plan, 'Psto', replace (s.partition_stop , 'ROW LOCATION', 'ROWID') ); scf_add_elem (l_plan, 'IdP', s.partition_id); l_other_tag := s.other_tag; l_other_tag := replace (l_other_tag, 'SERIAL_FROM_REMOTE' , 'S->R'); l_other_tag := replace (l_other_tag, 'PARALLEL_FROM_SERIAL' , 'S->P'); l_other_tag := replace (l_other_tag, 'PARALLEL_TO_SERIAL' , 'P->S'); l_other_tag := replace (l_other_tag, 'PARALLEL_TO_PARALLEL' , 'P->P'); l_other_tag := replace (l_other_tag, 'PARALLEL_COMBINED_WITH_PARENT', 'PCWP'); l_other_tag := replace (l_other_tag, 'PARALLEL_COMBINED_WITH_CHILD' , 'PCWC'); scf_add_elem (l_plan, 'OT', l_other_tag); scf_add_elem (l_plan, 'Distr', replace (replace (s.distribution, ' (RANDOM)', '(RAND)'),' (ORDER)', '(ORDER)')); --scf_add_elem (l_plan, 'obj alias', s.object_alias); --scf_add_elem (l_plan, 'qb_name', s.qblock_name); &COMM_IF_NO_PREDS. if s.access_predicates is not null then l_access_predicates(s.id) := adapt_predicate(s.access_predicates); end if; &COMM_IF_NO_PREDS. if s.filter_predicates is not null then l_filter_predicates(s.id) := adapt_predicate(s.filter_predicates); end if; if s.other is not null then l_others(s.id) := s.other; end if; scf_add_elem (l_plan2, 'Id' , s.id , p_is_auxil => 'Y', p_self_is_id => 'Y'); scf_add_elem (l_plan2, 'pId', s.parent_id, p_is_auxil => 'Y', p_self_is_pid => 'Y', p_is_hidden => 'Y'); scf_add_elem (l_plan2, 'Starts', s.starts / l_execs, p_sep_mid => l_col_tag); scf_add_elem (l_plan2, 'CR', s.cr_buffer_gets / l_execs, p_sep_mid => l_col_tag); &COMM_IF_NO_SELF scf_add_self (l_plan2, 'CR+', p_self_src => 'CR'); scf_add_elem (l_plan2, 'CU', s.cu_buffer_gets / l_execs, p_sep_mid => l_col_tag); &COMM_IF_NO_SELF scf_add_self (l_plan2, 'CU+', p_self_src => 'CU'); scf_add_elem (l_plan2, 'diskR', s.disk_reads / l_execs, p_sep_mid => l_col_tag); &COMM_IF_NO_SELF scf_add_self (l_plan2, 'diskR+', p_self_src => 'diskR'); scf_add_elem (l_plan2, 'diskW', s.disk_writes / l_execs, p_sep_mid => l_col_tag); &COMM_IF_NO_SELF scf_add_self (l_plan2, 'diskW+', p_self_src => 'diskW'); scf_add_elem (l_plan2, 'E0ram', s.estimated_optimal_size, p_sep_bot=>'KB'); scf_add_elem (l_plan2, 'E1ram', s.estimated_optimal_size, p_sep_bot=>'KB'); scf_add_elem (l_plan2, 'Aram', s.last_memory_used, p_sep_mid => 'last', p_sep_bot=>'KB'); scf_add_elem (l_plan2, 'Policy', s.policy); scf_add_elem (l_plan2, 'A01M', s.last_execution, p_sep_mid => 'last'); l_tmp := null; if s.optimal_executions > 0 or s.onepass_executions > 0 or s.multipasses_executions > 0 then l_tmp := s.optimal_executions||'/'||s.onepass_executions||'/'||s.multipasses_executions; end if; scf_add_elem (l_plan2, '0/1/M', l_tmp, p_sep_bot=>'#'); scf_add_elem (l_plan2, 'ActTim', s.active_time*10, p_sep_mid => 'avg', p_sep_bot=>'msec'); scf_add_elem (l_plan2, 'ETmpSpc', s.temp_space/1024, p_sep_bot=>'KB'); scf_add_elem (l_plan2, 'ATmpSpcM', s. max_tempseg_size/1024, p_sep_mid => 'max' , p_sep_bot=>'KB'); scf_add_elem (l_plan2, 'ATmpSpcL', s.last_tempseg_size/1024, p_sep_mid => 'last', p_sep_bot=>'KB'); &COMM_IF_LT_10G. if :OPT_PLAN_DETAILS = 'Y' then &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'Id', s.id, p_is_auxil => 'Y'); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'Qb_name', s.qblock_name); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'ObjAlias', s.object_alias); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'ObjType', s.object_type); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'Obj', get_cache_obj_name(s.object#)); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'BaseObj', get_cache_obj_name(get_cache_base_table_object_id (s.object#))); --&COMM_IF_LT_10G. scf_add_elem (l_plan3, 'Obj#', s.object#); --&COMM_IF_LT_10G. scf_add_elem (l_plan3, 'BaseObj#', get_cache_base_table_object_id (s.object#)); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'Projection', adapt_projection(s.projection)); &COMM_IF_LT_10G. scf_add_elem (l_plan3, 'Remarks', s.remarks); &COMM_IF_LT_10G. end if; end loop; scf_print_output (l_plan, 'no plan found.', 'only aux plan infos found.'); -- filter and access predicates for id in l_id_min .. l_id_max loop l_id_string := '.'|| to_char (id, '990'); if l_access_predicates.exists(id) then print (l_id_string||' - access[ '||l_access_predicates(id)||' ]'); l_id_string := rpad ('.', length (l_id_string)); end if; if l_filter_predicates.exists(id) then print (l_id_string||' - filter[ '||l_filter_predicates(id)||' ]'); l_id_string := rpad ('.', length (l_id_string)); end if; end loop; -- VPD policies for po in ( select object_owner, object_name, predicate, policy_function_owner, policy from sys.gv_$vpd_policy where inst_id = p_inst_id and sql_hash = p_hash_value &COMM_IF_LT_10G. and sql_id = l_sql_id and child_number = p_child_number order by object_owner, object_name) loop print('. --- - VPD POLICY on '||po.object_owner||'.'||po.object_name||' : ['||po.predicate||'] applied by function '||po.policy_function_owner||'.'||po.policy); end loop; -- PX Slave SQL if l_others.count > 0 then print ('---- PX Slave SQL:'); for id in l_id_min .. l_id_max loop l_id_string := '.'|| to_char (id, '990'); if l_others.exists(id) then print (l_id_string||' - ['||l_others(id)||']'); l_id_string := rpad ('.', length (l_id_string)); end if; end loop; end if; &COMM_IF_LT_10G. ash_print_stmt_profile ( &COMM_IF_LT_10G. p_inst_id => p_inst_id , p_sql_id => l_sql_id, &COMM_IF_LT_10G. p_child_number => p_child_number , &COMM_IF_LT_10G. p_first_load_time => p_first_load_time, p_last_load_time => p_last_load_time, p_last_active_time => p_last_active_time); scf_print_output (l_plan2, 'no plan details found.', 'only aux plan details found.', p_note => 'note: stats Aram, A01M, 0/1/M, ActTim do not seem to be always accurate.' ); scf_print_output (l_plan3, '', ''); -- output from dbms_xplan.display_cursor &COMM_IF_NO_DBMS_XPLAN. if l_sql_id is not null then &COMM_IF_NO_DBMS_XPLAN. l_dbms_xplan_format := 'ADVANCED'||l_dbms_xplan_tag; &COMM_IF_NO_DBMS_XPLAN. print ('===== dbms_xplan.display_cursor ('||l_dbms_xplan_format||'):'); &COMM_IF_NO_DBMS_XPLAN. open l_cursor for &COMM_IF_NO_DBMS_XPLAN. select /*+ xplan_exec_marker */ plan_table_output &COMM_IF_NO_DBMS_XPLAN. from table (dbms_xplan.display_cursor (l_sql_id, p_child_number, l_dbms_xplan_format)); &COMM_IF_NO_DBMS_XPLAN. loop &COMM_IF_NO_DBMS_XPLAN. fetch l_cursor into l_tmp; &COMM_IF_NO_DBMS_XPLAN. if l_cursor%notfound then &COMM_IF_NO_DBMS_XPLAN. close l_cursor; &COMM_IF_NO_DBMS_XPLAN. exit; &COMM_IF_NO_DBMS_XPLAN. end if; &COMM_IF_NO_DBMS_XPLAN. print (l_tmp); &COMM_IF_NO_DBMS_XPLAN. end loop; &COMM_IF_NO_DBMS_XPLAN. end if; -- print sql-level optimizer env optim_env_print_sql_pars (p_address => p_address, p_hash_value => p_hash_value, p_child_number => p_child_number); -- table infos from data dictionary if :OPT_TABINFOS = 'Y' then declare l_curr_id varchar2(20); begin l_curr_id := l_base_table_object_ids.first; loop exit when l_curr_id is null; print_cache_table_infos (l_curr_id); l_curr_id := l_base_table_object_ids.next (l_curr_id); end loop; end; end if; end print_plan;