2013-07-26 41 views
9

我使用DBMS_PROFILER来对我的PL/SQL包进行基本分析。我也用它使用下面的查询来获取代码覆盖率的统计数据:使用DBMS Profiler构建PL/SQL覆盖报告

SELECT EXEC.unit_name unitname,ROUND (EXEC.cnt/total.cnt * 100, 1) Code_coverage FROM 
    (SELECT u.unit_name, COUNT(1) cnt FROM plsql_profiler_data d, plsql_profiler_units u WHERE u.unit_number = d.unit_number GROUP BY u.unit_name) total, 
    (SELECT u.unit_name, COUNT(1) cnt FROM plsql_profiler_data d, plsql_profiler_units u WHERE u.unit_number = d.unit_number AND d.total_occur > 0 GROUP BY u.unit_name) EXEC 
    WHERE EXEC.unit_name = total.unit_name 

我清除plsql_profiler_data,plsql_profiler_units,plsql_profiler_runs表的每个探查器运行之前,这样我不知道运行ID各一次。

这将为我提供关于分析过程中所涉及的代码百分比的明智信息。现在我试图看看这是否可以构建为一个正常的覆盖报告,我可以知道哪一行代码被覆盖,哪一个不是(说选择lineOfCode,iscovered from ...),以便我可以用html构建报告格式化以指示是否覆盖某行。

我不是太精通Oracle表结构上,其中的功能和程序得到保存等。(接到了一个博客上面的查询,并略作修改,除去运行的ID)

这可能吗?

如果是的话我该如何做到这一点?

+0

看看是否有帮助:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:458240723799 – Slartibartfast

回答

0

实际上有一些PL/SQL工具可以做代码覆盖。有关更多信息,请参阅此question的答案。

说这一点,可以在以下的表找到关于用户创建的数据结构和代码信息:

  • user_source:这里可以找到在TEXT字段通过函数,过程,包等为代表的源
  • User_tables
  • user_indexes
  • user_types:如果你使用某种类型的面向对象的代码。
  • 其他以您可能需要的user_开头的表。

基本上你需要检查你的查询结果与user_source并从其他表中获得额外的信息。

+0

该链接中的大多数答案指向DBMS_PROFILER,给出的查询与我在问题中显示的查询几乎相同。其他两个链接看起来不太有希望。因此,这个问题。将检查user_source,看看它是否可以帮助 – rajesh

1

我觉得这接近你以后:

-- View lines of code profiled, along with run times, next to the complete, ordered source.. 
-- Provides an annotated view of profiled packages, procs, etc. 
-- Only the first line of a multiline SQL statement will register with timings. 
SELECT u.UNIT_OWNER || '.' || u.UNIT_NAME AS "Unit" 
    , s.line 
    , CASE WHEN d.TOTAL_OCCUR >= 0 THEN 'C' 
    ELSE ' ' END AS Covered 
    , s.TEXT 
    , TO_CHAR(d.TOTAL_TIME/(1000*1000*1000), 'fm990.000009') AS "Total Time (sec)" 
    , CASE WHEN NVL(d.TOTAL_OCCUR, 1) > 0 THEN d.TOTAL_OCCUR ELSE 1 END AS "# Iterations" 
    , TO_CHAR(CASE WHEN d.TOTAL_OCCUR > 0 THEN d.TOTAL_TIME/(d.TOTAL_OCCUR * (1000*1000*1000)) 
    ELSE NULL END, 'fm990.000009') AS "Avg Time (sec)" 
FROM all_source s 
    LEFT JOIN plsql_profiler_units u ON s.OWNER = u.UNIT_OWNER 
    AND s.NAME = u.UNIT_NAME 
    AND s.TYPE = u.UNIT_TYPE 
    LEFT JOIN plsql_profiler_data d ON u.UNIT_NUMBER = d.UNIT_NUMBER 
    AND s.LINE = d.LINE# 
    AND d.RUNID = u.RUNID 
WHERE u.RUNID = ? -- Add RUNID of profiler run to investigate here 
ORDER BY u.UNIT_NAME 
    , s.LINE 

有几个问题需要注意。

1)在plsql_profiler_data表中的多行会,因为他们执行比计时器的分辨率更快NOT在他们TOTAL_TIME列准确的数值。

Ask Tom re: timings

的定时被使用的时间单位一些,典型地仅 粒状到HSECS收集。

这意味着很多离散事件的时间少于1/1200秒,似乎需要等待0秒。

许多小于1/100秒的离散事件可能会花费1/100秒。

2)只有多行语句中的FIRST行会显示为被覆盖。因此,如果你在多行中拆分INSERT或其他内容,我不知道是否有任何简单的方法让每条行显示为在注释源报告样式中进行概要分析。

此外,请查看Oracle的dbms_profiler文档和this有用的软件包参考,以帮助您针对收集的配置文件数据进行查询。

+0

谢谢汤姆。将检查这一点,但需要几天的时间,因为我在一些截止日期举行。将更新你 – rajesh

+0

我应该在查询中有WHERE u.RUNID = 2吗?没有结果,如果我有这个where子句,但是当我删除它和u.RUNID = d.RUNID,我得到了IO错误'ORA-01114:写入块到文件(块#)的IO错误'。 – rajesh

+0

当我尝试这样'SELECT * FROM ALL_SOURCEš LEFT JOIN plsql_profiler_units U ON s.OWNER = u.UNIT_OWNER AND s.NAME = u.UNIT_NAME AND s.TYPE = u.UNIT_TYPE LEFT JOIN plsql_profiler_data d U上。 UNIT_NUMBER = d.UNIT_NUMBER AND s.LINE = d.LINE#AND d.RUNID = u.RUNID where total_occur is not null我确实得到了结果。我没有空检查,因为我看到一些条目为空,但空检查我也得到0.可能我需要> 0任何其他优化可能?我只需要知道一行是否已被覆盖 – rajesh