|
| 1 | +# PL/SQL Analyzer |
| 2 | + |
| 3 | +## Introduction |
| 4 | + |
| 5 | +Trivadis PL/SQL Analyzer is a command line utility to parse PL/SQL and SQL source code within an Oracle database and store the resulting XML parse-trees in dedicated relational tables – as an extension to the Oracle Data Dictionary – for further analysis. |
| 6 | + |
| 7 | +Analysis is supported for static and dynamic code. |
| 8 | + |
| 9 | +Sample analyses are provided as views and pipelined table functions, e.g.: |
| 10 | + |
| 11 | +- `TVD_OBJECT_HINT_USAGE_V`: Used hints in static code. |
| 12 | +- `TVD_OBJECT_USAGE_V`: Used tables/views in static code. |
| 13 | +- `TVD_OBJECT_COL_USAGE_V`: Used columns in static code. |
| 14 | +- `TVD_COLDEP_PKG`: View column dependencies. |
| 15 | +- `TVD_SQL_HINT_USAGE_V`: Used hints in captures SQL statements. |
| 16 | +- `TVD_SQL_USAGE_V`: Used tables/views in captured SQL statements. |
| 17 | +- `TVD_SQL_COL_USAGE_V`: Used columns in captured SQL statements. |
| 18 | + |
| 19 | +## Concepts |
| 20 | + |
| 21 | +### Scope |
| 22 | + |
| 23 | +The primary scope of PL/SQL Analyzer is the analysis of SQL and PL/SQL code within an Oracle database instance as shown in the following picture: |
| 24 | + |
| 25 | +<img alt="Scope" src="images/tvdca_scope.png" width="400"> |
| 26 | + |
| 27 | +Please consider using standard tooling from Oracle before using PL/SQL Analyzer. Oracle provides in that area the following support: |
| 28 | + |
| 29 | +- Oracle data dictionary views such as `DBA_DEPENDENCIES`, `DBA_SOURCE`, `DBA_PROCEDURES`, `DBA_ARGUMENTS`, `DBA_TYPES`, `DBA_TYPE_METHODS`, `DBA_TRIGGERS`, `DBA_VIEWS`, `DBA_TABLES` |
| 30 | +- PL/Scope and its data dictionary views `DBA_IDENTIFIERS` and `DBA_STATEMENTS` (see also the free [plscope-utils for SQL Developer](https://www.salvis.com/blog/plscope-utils-for-sql-developer/)) |
| 31 | +- Oracle parser such as UTL_XML.PARSEQUERY (which is a good choice for SELECT statements without plsql_declarations in the [with_clause](http://docs.oracle.com/database/122/SQLRF/SELECT.htm#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__BABFAFID)) |
| 32 | + |
| 33 | +As soon as you need deeper information about SQL statements in your code, e.g. column usage in general or in certain clauses (e.g. in the select_list), PL/SQL Analyzer becomes appealing. |
| 34 | + |
| 35 | +### Oracle Dictionary Extension for Static Code Analysis |
| 36 | + |
| 37 | +PL/SQL Analyzer populates the following structure as an extension to the Oracle data dictionary for static analysis: |
| 38 | + |
| 39 | +``` |
| 40 | +SQL> desc tvd_parsed_objects_v |
| 41 | + Name Null? Type |
| 42 | + ------------------------------- -------- ---------------------------- |
| 43 | + OBJECT_ID NOT NULL NUMBER |
| 44 | + OWNER NOT NULL VARCHAR2(30 CHAR) |
| 45 | + OBJECT_NAME NOT NULL VARCHAR2(128 CHAR) |
| 46 | + OBJECT_TYPE NOT NULL VARCHAR2(30 CHAR) |
| 47 | + LAST_DDL_TIME NOT NULL DATE |
| 48 | + DDL_SOURCE NOT NULL CLOB |
| 49 | + PARSE_TREE SYS.XMLTYPE |
| 50 | + PARSE_ERRORS CLOB |
| 51 | +``` |
| 52 | + |
| 53 | +The columns `OBJECT_ID`, `OWNER`, `OBJECT_NAME`, `OBJECT_TYPE` and `LAST_DDL_TIME` have the same semantic as the columns in the Oracle data dictionary view `DBA_OBJECTS`. The column `DDL_SOURCE` contains the result of a `DBMS_METADATA.GET_DDL` function call. The column `PARSE_TREE` contains the parse tree in XML format. The column `PARSE_ERRORS` contains error messages that occurred during parse or XML serialization. Errors may occur if the DDL contains invalid code; or the DDL contains control characters which may not be serialized in XML; or the Trivadis PL/SQL parser is not able to fully parse the code. However, a partial parse tree is created even if the Trivadis PL/SQL parser throws an error. In that case typically just the failing SQL statement is missing. |
| 54 | + |
| 55 | +The following picture visualizes the population process of the view `tvd_parsed_objects_v`: |
| 56 | + |
| 57 | +<img alt="Parsed Objects" src="images/tvdca_parsed_objects.png" width="400"> |
| 58 | + |
| 59 | +Just outdated rows in `DBA_OBJECTS` are processed (identified via column `LAST_DDL_TIME`). |
| 60 | + |
| 61 | +### Oracle Dictionary Extension for Dynamic Code Analysis |
| 62 | + |
| 63 | +As explained in chapter [Scope](#scope) PL/SQL Analyzer is primarily designed for static code analysis. However, it’s possible to analyze dynamic PL/SQL and SQL if the code is captured in the following structure: |
| 64 | + |
| 65 | +``` |
| 66 | +SQL> desc tvd_captured_sql_t |
| 67 | + Name Null? Type |
| 68 | + ------------------------------- -------- ---------------------------- |
| 69 | + CAP_ID NOT NULL NUMBER |
| 70 | + CAP_SOURCE NOT NULL CLOB |
| 71 | + SQL_ID VARCHAR2(13 CHAR) |
| 72 | + USER_NAME VARCHAR2(30 CHAR) |
| 73 | + SCHEMA_NAME VARCHAR2(30 CHAR) |
| 74 | + MODULE VARCHAR2(64 CHAR) |
| 75 | + ACTION VARCHAR2(64 CHAR) |
| 76 | + LAST_DDL_TIME DATE |
| 77 | + PARSE_TREE SYS.XMLTYPE |
| 78 | + PARSE_TREE_CLOB CLOB |
| 79 | + PARSE_ERRORS CLOB |
| 80 | +``` |
| 81 | + |
| 82 | +The column `CAP_ID` is the primary key of the table and should be populated with a sequence value from `TVD_CAPTURED_SQL_SEQ` to avoid duplicated entries. The column `CAP_SOURCE` contains the captured SQL or PL/SQL statement. It does not matter how this structure is populated, it simply updates the columns `PARSE_TREE` and `PARSE_ERRORS` if the `PARSE_TREE` column `IS NULL` (`PARSE_TREE_CLOB` is a workaround for `XMLTYPE` bugs). All other columns are optional and may give the SQL a context. |
| 83 | + |
| 84 | +The structure above could be populated on an Oracle instance as follows: |
| 85 | + |
| 86 | +```sql |
| 87 | +MERGE INTO tvd_captured_sql_t t |
| 88 | +USING (SELECT a.sql_id, |
| 89 | + a.sql_fulltext AS cap_source, |
| 90 | + u.username AS user_name, |
| 91 | + a.parsing_schema_name AS schema_name, |
| 92 | + a.module, |
| 93 | + a.action, |
| 94 | + a.last_load_time |
| 95 | + FROM v$sqlarea a |
| 96 | + INNER JOIN all_users u |
| 97 | + ON a.parsing_user_id = u.user_id |
| 98 | + WHERE a.parsing_schema_name NOT IN |
| 99 | + ('ANONYMOUS', |
| 100 | + 'APEX_PUBLIC_USER', |
| 101 | + 'CTXSYS', |
| 102 | + 'DBSNMP', |
| 103 | + 'DIP', |
| 104 | + 'EXFSYS', |
| 105 | + 'FLOWS_FILES', |
| 106 | + 'GSMADMIN_INTERNAL', |
| 107 | + 'LBACSYS', |
| 108 | + 'MDDATA', |
| 109 | + 'MDSYS', |
| 110 | + 'MGMT_VIEW', |
| 111 | + 'OLAPSYS', |
| 112 | + 'ORACLE_OCM', |
| 113 | + 'ORDDATA', |
| 114 | + 'ORDPLUGINS', |
| 115 | + 'ORDSYS', |
| 116 | + 'OUTLN', |
| 117 | + 'OWBSYS', |
| 118 | + 'SI_INFORMTN_SCHEMA', |
| 119 | + 'SPATIAL_CSW_ADMIN_USR', |
| 120 | + 'SPATIAL_WFS_ADMIN_USR', |
| 121 | + 'SYS', |
| 122 | + 'SYSMAN', |
| 123 | + 'SYSTEM', |
| 124 | + 'WKPROXY', |
| 125 | + 'WKSYS', |
| 126 | + 'WK_TEST', |
| 127 | + 'WMSYS', |
| 128 | + 'XDB', |
| 129 | + 'XS$NULL')) s |
| 130 | +ON (s.sql_id = t.sql_id) |
| 131 | +WHEN MATCHED THEN |
| 132 | + UPDATE |
| 133 | + SET t.last_load_time = s.last_load_time |
| 134 | + WHERE t.last_load_time < s.last_load_time |
| 135 | +WHEN NOT MATCHED THEN |
| 136 | + INSERT |
| 137 | + (t.cap_id, |
| 138 | + t.cap_source, |
| 139 | + t.sql_id, |
| 140 | + t.user_name, |
| 141 | + t.schema_name, |
| 142 | + t.module, |
| 143 | + t.action, |
| 144 | + t.last_load_time) |
| 145 | + VALUES |
| 146 | + (tvd_captured_sql_seq.nextval, |
| 147 | + s.cap_source, |
| 148 | + s.sql_id, |
| 149 | + s.user_name, |
| 150 | + s.schema_name, |
| 151 | + s.module, |
| 152 | + s.action, |
| 153 | + s.last_load_time) |
| 154 | +``` |
| 155 | +Please note that the column `sql_fulltext` is not available in `v$sql_area` before version 11g Release 1 and that the SQL statement gathering process is not part of PL/SQL Analyzer. |
| 156 | + |
| 157 | +## Custom Analysis |
| 158 | + |
| 159 | +The sample analysis views and PL/SQL packages show you how the analysis based on the views tvd_parsed_objects_v and tvd_captured_sql_v could be done. |
| 160 | + |
| 161 | +The idea is to query the relevant information from the XML parse tree using XQuery and present the result in a relational structure using the Oracle function XMLTABLE and do all further analysis in classic SQL based way. |
| 162 | + |
| 163 | +It’s recommended to develop the XQuery using an XML editor supporting XQuery. |
| 164 | + |
| 165 | +See XML schema documentation in the xsd directory. The complex type PLSQLFile is a good starting point in the HTML documentation. |
| 166 | + |
| 167 | +## Releases |
| 168 | + |
| 169 | +You find all releases and release information [here](https://github.com/Trivadis/plsql-analyzer/releases). |
| 170 | + |
| 171 | +## Issues |
| 172 | +Please file your bug reports, enhancement requests, questions and other support requests within [Github's issue tracker](https://help.github.com/articles/about-issues/). |
| 173 | + |
| 174 | +* [Questions](https://github.com/trivadis/plsql-analyzer/issues?q=is%3Aissue+label%3Aquestion) |
| 175 | +* [Open enhancements](https://github.com/trivadis/plsql-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) |
| 176 | +* [Open bugs](https://github.com/trivadis/plsql-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3Abug) |
| 177 | +* [Submit new issue](https://github.com/trivadis/plsql-analyzer/issues/new) |
| 178 | + |
| 179 | +## Frequently Asked Questions |
| 180 | + |
| 181 | +see [Frequently Ased Questions](FAQ.md). |
| 182 | + |
| 183 | +## License |
| 184 | + |
| 185 | +The preview/trial version of PL/SQL Analyzer is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License. You may obtain a copy of the License at https://creativecommons.org/licenses/by-nc-nd/3.0/. |
| 186 | + |
| 187 | + |
| 188 | + |
| 189 | +The trial/preview version provides full functionality but is limited in time and volume. |
| 190 | + |
| 191 | +For production use a separate software license agreement is required. |
0 commit comments