Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
SonarSource dashboard
Olivier Gaudin – SonarSource SA
Toad for Oracle’s Code Xpert utility (part of the Toad Professional Edition) is
one of the best PL/SQL code analyzers available on the market, embedding
the know-how of leading PL/SQL experts such as Steven Feuerstein.
However, although there is the option to store data in the Code Xpert
repository for point-in-time reporting, it is still primarily a static reporting
tool and therefore cannot report dynamically on code quality trends as part
of an overall quality strategy in a company, without manually querying the
repository tables.
Originally built for Java, Sonar has been extended to include the PL/SQL
language through a commercial plugin. In this article, I am going to explain
how Sonar leverages Toad’s Code Xpert unlocking its full potential in order
to provide a full code quality management product.
Running code analysis with Toad’s Code Xpert covers several axes of code
quality management However, this is not sufficient if you are required to
have a global approach. What do I mean by that? If you want to manage
your projects portfolio globally, follow the evolution throughout time, get
alerts and then maybe delegate some remediation work, you are left with a
lot of manual work to consolidate data, compare projects or versions... That
is where Sonar comes into play with the following features:
2. Central reporting
Sonar centralizes reporting at two levels.
Firstly at the project level where it enables its user to get a comprehensive
dashboard (that extends to any directory) enabling to view all metrics at a
glance to evaluate axes that need to be worked on. On top of the metrics
covered by Code Xpert, Sonar also reports on duplicated code and
comments.
Secondly, at the projects portfolio level to be able to be able to get the big
picture projects portfolio. The configurable dashboard enables to compare
projects and quickly understand where risk lies. This dashboard is cross
language (Java and PL/SQL in this case).
3. Metric evolution
At every analysis, measures are recorded into the Sonar database and add
to historical data. Sonar has a TimeMachine that enables to go back in time,
compare versions and monitor evolution.
4. Chasing tools
The resource viewer enables to display the source code “tainted” with a
specific type of defect. All defects of the selected type are highlighted within
the code.
Moreover, the plugin embarks a PL/SQL code extractor that enables the
analysis of any Oracle Forms application.
The Sonar PL/SQL plugin is now at version 1.5 and currently covers 4 quality
axes out of 6 possible. Here is the list of planned short-term evolutions:
• Integration of SQLScan
• Integration of File complexity (McCabe)
• Integration of Unit tests
Here are a few links to help you find out more about Sonar and the PL/SQL
plugin:
• Sonar web site: http://sonar.codehaus.org
• Sonar in action: http://nemo.sonar.codehaus.org
• Sample PL/SQL project :
http://nemo.sonarsource.org/project/index/nl.oracledeveloper:utpl
sql
• To download a limited version of the plugin :
http://www.sonarsource.com/plugins
He has a strong background in SQL and has been involved in CMMI and ITIL
implementations and have an acute awareness of quality and reliability of
processes.
Many tools for PL/SQL development like TOAD and PL/SQL Developer or even JDeveloper, do not
readily integrate with such tools for PL/SQL code. Besides, most of these tools are used by developers
directly on the PL/SQL source as it is held in the database. Developers do not write the code to file all
the time and they certainly do not check in their code after each change they make. They compile any
changes, sending the latest version of their code to be held in the database – overwriting the previous
state of their PL/SQL object – and that is that. Perhaps after a number of compilations they may save to
a file and at the end of the day or some large task they may check in to the Source Code Control system.
The potential issues with this way of working – and believe me, I have run into them on many occasions
– is that developers often lose stages of their code that later on they want to retrieve.
For example: you start working in the morning on a source that you retrieve from the filesystem or
source code control environment. You make changes, compiling them as you go along. At some point,
you have a pretty good intermediate result. You
then continue with some intricate changes and you make some additional modifications and all of a
sudden, you have messed up your code. And you would really like to return to that intermediate result.
But: where is it? No longer in the database – overwritten by the next compilation. Not on the file system,
as you forgot to save. And certainly not in the Source Code Control repository, as you did not check in.
Then there is the everpresent risk of two developers working on the same package at about the same
time. Compilation by the second developer will immediately override and therefore discard any changes
made by the first.
In this article I would like to outline a very simple mechanism for using the database itself as archive for
all these intermediate versions. The essential pieces for this ‘working archive’ or operational repository:
a table, a package and a trigger. The machinery is put into motion by a Oracle 9i and higher DDL Event
trigger, fired on the CREATE (or compile) event.
The table PLSQL_ARCHIVE will hold earlier versions of the PL/SQL objects in the schema you are
working on. For each previous version, it will
The table is set up to hold a number of values for each Version of PL/SQL Objects: the PL/SQL source,
the timestamp for the compilation/creation, the status, size and errors and when provided by the
developer through annotations in the PL/SQL source also the Author, the Version, a Branch, the Priority
and possibly additional Comments. We define the table like this:
Whenever we compile – create or replace – a PL/SQL object, the CREATE DDL event is fired and we
can intercept that event with our own trigger. At that point we have various pieces of information that
we can use to insert a new record into the PLSQL_ARCHIVE table.
We will bother with the actual implementation of this package later on. Let’s first see how we can make
use of what we have created thusfar:
• Get an overview of all compilations in our schema, including timestamp and resulting status
• Get the errors for a particular "version" of a PL/SQL object
• Get the source at a particular moment in time, for example to compare with the current version
• Revert to a specifc stage in the development of a PL/SQL object
• Create a Stripe or Label, associating specific versions of all or at least many PL/SQL program
units with what could be a release, a patch or whatever the stripe is to signify
• Gather some analytical data on the PL/SQL development process: frequency of compilations,
evolution of number of errors and size of the source
• When the developer uses annotations to provide comments, priority, version label and branch we
can even retrieve version graphs
Some of the information stored in the PLSQL_ARCHIVE table is inherently available at AFTER
CREATE trigger time, such as the source, the errors, the object name, size and type and the compilation
time. Others will have to be provided as annotations or meta-data in the source code, specified by the
developer him or herself.
In the implementation of the PLSQL_ARCHIVER presented below, we make use of the following
annotations, largely following the style used in JavaDoc and also adopted in PLDoc – an open source
project for generation of technical documentation for PL/SQL code:
• @author – for the author or developer of the (current version of the) PL/SQL unit
• @version – the version label for the current instance of the PL/SQL object
• @label – the label or stripe that this current instance of the PL/SQL object is associated with;
examples of Labels are Releases, Patches, Versions of (reusable) Components etc.
• @branch – an indication of the particular branch or subproject the PL/SQL unit is currently
being reworked for; when not explicitly set, the MAIN branch is assumed. Examples of other
branches are ADD_SECURITY (a subproject), 1.0PTCH2 (Patch 2 on Release 1.0) and
10gR2_PORT (the collection instances that make use of new Oracle 10gR2 PL/SQL features.
• @priority – an indication of the extent of changes in this version compared to the previous
version; typicaly values are Pico, Minor, Normal, Major
• @comments – any additional description of this version of the object, for example the changes
with respect to the previous version
The developer would include these keywords or annotations somewhere in a comment section in the
PL/SQL object. For example:
It is probably wise to start with somewhat less information. Let’s say just the Version Label, the
Sequence, Status and the Creation Date Time. The result for our TEST_ARCHIVER object looks
something like:
Note: the asterisk (*) indicates that the object version is INVALID or its PL/SQL code cannot be
compiled!
Next Steps
Things I can envision for next steps with this revolutionary technology framework:
• Include a Compare facility that can report the differences between two versions. If I feel really
incredibly brave, I will do Merge as well. Actually, I think there must be Java based Compare
and perhaps Merge components for Text; we could probably upload them as Java Stored
Procedures and wrap them within PL/SQL wrappers
• Provide a GUI for this database backend or repository
• Provide a migration from CVS to my source code control system (or perhaps the other way
round)
• Ensure that a call to REVERT_TO_VERSION does not itself create a new version upon
compilation (as it currently probably does).
• Provide automatic version labeling: if I check in the next version after 1.4 the tool will call it 1.5
for me. It could even look at the priority level – major, minor, pico, normal – and decide to go
from 1.4 to 1.4.1, 1.5, 2.0 or 1.4.0.1.
• Add support for other database objects such as Tables and Views
Resources
end revert_to_previous_version;
l_branch_columns(l_branches_tbl(i).branch).delete(l_branch_columns(l_branches_tbl(i
).branch).first); else l_line:=l_line|| rpad('
',l_branches_tbl(i).width,' ');