diff --git a/sqldev/pom.xml b/sqldev/pom.xml index 4be8a609..41261000 100644 --- a/sqldev/pom.xml +++ b/sqldev/pom.xml @@ -5,7 +5,7 @@ org.utplsql org.utplsql.sqldev - 0.7.0-SNAPSHOT + 0.7.0 bundle UTF-8 diff --git a/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend b/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend index 87e7c5e6..e7a12a50 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend +++ b/sqldev/src/main/java/org/utplsql/sqldev/dal/UtplsqlDao.xtend @@ -20,6 +20,7 @@ import java.sql.Connection import java.sql.SQLException import java.sql.Types import java.util.List +import java.util.regex.Pattern import org.oddgen.sqldev.generators.model.Node import org.springframework.dao.DataAccessException import org.springframework.dao.EmptyResultDataAccessException @@ -31,19 +32,81 @@ import org.utplsql.sqldev.model.ut.Annotation import org.utplsql.sqldev.model.ut.OutputLines class UtplsqlDao { - public static val UTPLSQL_PACKAGE_NAME = "UT" + public static val UTPLSQL_PACKAGE_NAME = "UT" + public static val FIRST_VERSION_WITH_INTERNAL_ANNOTATION_API = 3000004 + public static val FIRST_VERSION_WITH_ANNOTATION_API = 3001003 var Connection conn var JdbcTemplate jdbcTemplate // cache fields Boolean cachedDbaViewAccessible String cachedUtplsqlSchema - Boolean cachedUtAnnotationManagerInstalled + String cachedUtPlsqlVersion new(Connection connection) { conn = connection jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true)) } + /** + * used for testing purposes only + */ + def setUtPlsqlVersion(String utPlsqlVersion) { + cachedUtPlsqlVersion = utPlsqlVersion + } + + /** + * returns a normalized utPLSQL version in format 9.9.9 + */ + def String normalizedUtPlsqlVersion() { + val p = Pattern.compile("(\\d+\\.\\d+\\.\\d+)") + val version = getUtPlsqlVersion() + val m = p.matcher(version) + if (m.find) { + return m.group(0) + } else { + return "0.0.0" + } + } + + /** + * get version as number, e.g. 3001004 + */ + def int normalizedUtPlsqlVersionNumber() { + val p = Pattern.compile("(\\d+)") + val version = normalizedUtPlsqlVersion() + val m = p.matcher(version) + m.find + val major = m.group + m.find + val minor = m.group + m.find + val bugfix = m.group + val versionNumber = Integer.valueOf(major)*1000000 + Integer.valueOf(minor)*1000 + Integer.valueOf(bugfix) + return versionNumber + } + + /** + * gets version of installed utPLSQL + */ + def String getUtPlsqlVersion() { + if (cachedUtPlsqlVersion === null) { + val sql = ''' + BEGIN + ? := ut.version; + END; + ''' + cachedUtPlsqlVersion = jdbcTemplate.execute(sql, new CallableStatementCallback() { + override String doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException { + cs.registerOutParameter(1, Types.VARCHAR); + cs.execute + val version = cs.getString(1) + return version + } + }) + } + return cachedUtPlsqlVersion + } + def boolean isDbaViewAccessible() { if (cachedDbaViewAccessible === null) { try { @@ -96,21 +159,7 @@ class UtplsqlDao { * @throws DataAccessException if there is a problem */ def boolean isUtAnnotationManagerInstalled() { - if (cachedUtAnnotationManagerInstalled === null) { - cachedUtAnnotationManagerInstalled = false - if (utplsqlSchema !== null) { - val sql = ''' - SELECT count(*) - FROM «IF dbaViewAccessible»dba«ELSE»all«ENDIF»_objects - WHERE owner = '«utplsqlSchema»' - AND object_type = 'PACKAGE' - AND object_name = 'UT_ANNOTATION_MANAGER' - ''' - val found = jdbcTemplate.queryForObject(sql, Integer) - cachedUtAnnotationManagerInstalled = found == 1 - } - } - return cachedUtAnnotationManagerInstalled + return normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_INTERNAL_ANNOTATION_API } /** @@ -124,31 +173,44 @@ class UtplsqlDao { */ def boolean containsUtplsqlTest(String owner, String objectName, String subobjectName) { try { - val sql = ''' - SELECT count( - CASE - WHEN a.name = 'test' - AND (upper(a.subobject_name) = upper(?) OR ? IS NULL) - THEN - 1 - ELSE - NULL - END - ) - FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o - CROSS JOIN TABLE(o.annotations) a - WHERE (o.object_name = upper(?) OR ? IS NULL) - AND a.name IN ('test', 'suite') - HAVING count( - CASE - WHEN a.name = 'suite' THEN - 1 - ELSE - NULL - END - ) > 0 - ''' - val found = jdbcTemplate.queryForObject(sql, Integer, #[subobjectName, subobjectName, owner, objectName, objectName]) + var Integer found + if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) { + // using API available since 3.1.3 + val sql = ''' + SELECT count(*) + FROM TABLE(ut_runner.get_suites_info(upper(?), upper(?))) + WHERE item_type = 'UT_TEST' + AND (item_name = upper(?) or ? IS NULL) + ''' + found = jdbcTemplate.queryForObject(sql, Integer, #[owner, objectName, subobjectName, subobjectName]) + } else { + // using internal API (deprecated) + val sql = ''' + SELECT count( + CASE + WHEN a.name = 'test' + AND (upper(a.subobject_name) = upper(?) OR ? IS NULL) + THEN + 1 + ELSE + NULL + END + ) + FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o + CROSS JOIN TABLE(o.annotations) a + WHERE (o.object_name = upper(?) OR ? IS NULL) + AND a.name IN ('test', 'suite') + HAVING count( + CASE + WHEN a.name = 'suite' THEN + 1 + ELSE + NULL + END + ) > 0 + ''' + found = jdbcTemplate.queryForObject(sql, Integer, #[subobjectName, subobjectName, owner, objectName, objectName]) + } return found > 0 } catch (EmptyResultDataAccessException e) { return false @@ -172,12 +234,30 @@ class UtplsqlDao { * @throws DataAccessException if a utPLSQL version less than 3.0.4 is installed or if there are other problems */ def List annotations(String owner, String objectName) { - val sql = ''' - SELECT o.object_owner, o.object_type, o.object_name, a.name, a.text, a.subobject_name - FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o - CROSS JOIN TABLE(o.annotations) a - WHERE o.object_name = upper(?) - ''' + var String sql + if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) { + // using API available since 3.1.3 + sql = ''' + SELECT object_owner, + object_name, + lower(substr(item_type, 4)) AS name, + item_name as subobject_name + FROM TABLE(ut_runner.get_suites_info(upper(?), upper(?))) + ''' + + } else { + // using internal API (deprecated) + sql = ''' + SELECT o.object_owner, + o.object_name, + a.name, + a.text, + coalesce(upper(a.subobject_name), o.object_name) AS subobject_name + FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(upper(?), 'PACKAGE')) o + CROSS JOIN TABLE(o.annotations) a + WHERE o.object_name = upper(?) + ''' + } val result = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Annotation), #[owner, objectName]) return result } @@ -222,21 +302,42 @@ class UtplsqlDao { def List testables(String objectType) { var String sql; if (objectType == "PACKAGE") { - sql = ''' - SELECT DISTINCT - object_type || '.' || object_name AS id, - object_type AS parent_id, - 1 AS leaf, - 1 AS generatable, - 1 AS multiselectable - FROM user_procedures - WHERE object_type = ? - AND procedure_name IS NOT NULL - AND object_name NOT IN ( - SELECT object_name - FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(USER, 'PACKAGE')) - ) - ''' + if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) { + // using API available since 3.1.3 + sql = ''' + SELECT DISTINCT + object_type || '.' || object_name AS id, + object_type AS parent_id, + 1 AS leaf, + 1 AS generatable, + 1 AS multiselectable + FROM user_procedures + WHERE object_type = ? + AND procedure_name IS NOT NULL + AND object_name NOT IN ( + SELECT object_name + FROM TABLE(ut_runner.get_suites_info(USER)) + WHERE item_type = 'UT_SUITE' + ) + ''' + } else { + // using internal API (deprecated) + sql = ''' + SELECT DISTINCT + object_type || '.' || object_name AS id, + object_type AS parent_id, + 1 AS leaf, + 1 AS generatable, + 1 AS multiselectable + FROM user_procedures + WHERE object_type = ? + AND procedure_name IS NOT NULL + AND object_name NOT IN ( + SELECT object_name + FROM TABLE(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(USER, 'PACKAGE')) + ) + ''' + } } else if (objectType == "TYPE") { sql = ''' @@ -278,202 +379,306 @@ class UtplsqlDao { * @throws DataAccessException if there is a problem */ def List runnables() { - var sql = ''' - WITH - base AS ( - SELECT rownum AS an_id, - o.object_owner, - o.object_type, - o.object_name, - lower(a.name) AS name, - a.text, - a.subobject_name - FROM table(«utplsqlSchema».ut_annotation_manager.get_annotated_objects(user, 'PACKAGE')) o - CROSS JOIN table(o.annotations) a - WHERE lower(a.name) in ('suite', 'suitepath', 'endcontext', 'test') - OR lower(a.name) = 'context' AND regexp_like(text, '(\w+)(\.\w+)*') - ), - suite AS ( - SELECT object_owner, object_type, object_name, text AS suite_description - FROM base - WHERE name = 'suite' - ), - suitepath as ( - SELECT object_owner, object_type, object_name, lower(text) AS suitepath - FROM base - WHERE name = 'suitepath' - ), - context_base AS ( - SELECT an_id, - lead(an_id) over (partition by object_owner, object_type, object_name order by an_id) AS an_id_end, - object_owner, - object_type, - object_name, - name, - lead(name) over (partition by object_owner, object_type, object_name order by an_id) AS name_end, - text as context - FROM base - WHERE name IN ('context', 'endcontext') - ), - context as ( - SELECT an_id, an_id_end, object_owner, object_type, object_name, context - FROM context_base - WHERE name = 'context' - AND name_end = 'endcontext' - ), - test AS ( - SELECT b.an_id, - b.object_owner, - b.object_type, - b.object_name, - p.suitepath, - c.context, - b.subobject_name, - b.text AS test_description - FROM base b - LEFT JOIN suitepath p - ON p.object_owner = b.object_owner - AND p.object_type = b.object_type - AND p.object_name = b.object_name - LEFT JOIN context c - ON c.object_owner = b.object_owner - AND c.object_type = b.object_type - AND c.object_name = b.object_name - AND b.an_id BETWEEN c.an_id AND c.an_id_end - WHERE name = 'test' - AND (b.object_owner, b.object_type, b.object_name) IN ( - SELECT object_owner, object_type, object_name - FROM suite - ) - ), - suite_tree AS ( - SELECT null AS parent_id, - 'SUITE' AS id, - 'All Suites' AS name, - 'All utPLSQL test suites' AS description, - 'PACKAGE_FOLDER_ICON' AS iconName, - 'No' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM dual - UNION ALL - SELECT DISTINCT - 'SUITE' AS parent_id, - object_owner || '.' || object_name AS id, - object_name AS name, - null AS description, - 'PACKAGE_ICON' AS iconName, - 'No' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM test - UNION ALL - SELECT object_owner || '.' || object_name AS parent_id, - object_owner || '.' || object_name || '.' || subobject_name AS id, - subobject_name AS name, - null AS description, - 'PROCEDURE_ICON' AS iconName, - 'Yes' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM test - ), - suitepath_base AS ( - SELECT DISTINCT - suitepath - FROM suitepath - ), - gen AS ( - SELECT rownum AS pos - FROM xmltable('1 to 100') - ), - suitepath_part AS ( - SELECT DISTINCT - substr(suitepath, 1, instr(suitepath || '.', '.', 1, g.pos) -1) AS suitepath - FROM suitepath_base b - JOIN gen g - ON g.pos <= regexp_count(suitepath, '\w+') - ), - suitepath_tree AS ( - SELECT NULL AS parent_id, - 'SUITEPATH' AS id, - 'All Suitepaths' AS name, - 'All utPLSQL test suitepathes' AS description, - 'FOLDER_ICON' AS iconName, - 'No' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM dual - UNION ALL - SELECT CASE - WHEN regexp_replace(suitepath,'\.?\w+$','') IS NULL THEN - 'SUITEPATH' - ELSE - USER || ':' || regexp_replace(suitepath,'\.?\w+$','') - END AS parent_id, - USER || ':' || suitepath AS id, - regexp_substr(suitepath, '\.?(\w+$)', 1, 1, NULL, 1) AS name, - null AS description, - 'FOLDER_ICON' AS iconName, - 'No' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM suitepath_part - UNION ALL - SELECT DISTINCT - object_owner || ':' || suitepath AS parent_id, - object_owner || ':' || suitepath || '.' || object_name AS id, - object_name AS name, - null AS description, - 'PACKAGE_ICON' AS iconName, - 'No' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM test - WHERE suitepath IS NOT NULL - UNION ALL - SELECT DISTINCT - object_owner || ':' || suitepath || '.' || object_name AS parent_id, - object_owner || ':' || suitepath || '.' || object_name || '.' || context AS id, - context AS name, - null AS description, - 'FOLDER_ICON' AS iconName, - 'No' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM test - WHERE suitepath IS NOT NULL - AND context IS NOT NULL - UNION ALL - SELECT object_owner || ':' || suitepath || '.' || object_name || CASE WHEN context IS NOT NULL THEN '.' || context END AS parent_id, - object_owner || ':' || suitepath || '.' || object_name || CASE WHEN context IS NOT NULL THEN '.' || context END || '.' || subobject_name AS id, - subobject_name AS name, - null AS description, - 'PROCEDURE_ICON' AS iconName, - 'Yes' AS leaf, - 'Yes' AS generatable, - 'Yes' AS multiselectable, - 'Yes' AS relevant - FROM test - WHERE suitepath IS NOT NULL - ), - tree AS ( - SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant - FROM suite_tree - UNION ALL - SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant - FROM suitepath_tree - ) - SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant - FROM tree - ''' + var String sql + if (normalizedUtPlsqlVersionNumber >= FIRST_VERSION_WITH_ANNOTATION_API) { + // using API available since 3.1.3 + sql = ''' + WITH + test AS ( + SELECT object_owner, + object_name, + path AS suitepath, + item_type, + item_name, + item_description + FROM TABLE(ut_runner.get_suites_info(user)) + ), + suite_tree AS ( + SELECT null AS parent_id, + 'SUITE' AS id, + 'All Suites' AS name, + 'All utPLSQL test suites' AS description, + 'PACKAGE_FOLDER_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM dual + UNION ALL + SELECT DISTINCT + 'SUITE' AS parent_id, + object_owner || '.' || object_name AS id, + object_name AS name, + null AS description, + 'PACKAGE_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + WHERE item_type = 'UT_TEST' + UNION ALL + SELECT object_owner || '.' || object_name AS parent_id, + object_owner || '.' || object_name || '.' || item_name AS id, + item_name AS name, + item_description AS description, + 'PROCEDURE_ICON' AS iconName, + 'Yes' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + WHERE item_type = 'UT_TEST' + ), + suitepath_tree AS ( + SELECT NULL AS parent_id, + 'SUITEPATH' AS id, + 'All Suitepaths' AS name, + 'All utPLSQL test suitepathes' AS description, + 'FOLDER_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM dual + UNION ALL + SELECT CASE + WHEN regexp_replace(suitepath,'\.?\w+$','') IS NULL THEN + 'SUITEPATH' + ELSE + object_owner || ':' || regexp_replace(suitepath,'\.?\w+$','') + END AS parent_id, + object_owner || ':' || suitepath AS id, + item_name AS name, + item_description AS description, + CASE item_type + WHEN 'UT_SUITE' THEN + 'PACKAGE_ICON' + WHEN 'UT_TEST' THEN + 'PROCEDURE_ICON' + ELSE + 'FOLDER_ICON' + END AS iconName, + CASE item_type + WHEN 'UT_TEST' THEN + 'Yes' + ELSE + 'No' + END AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + ), + tree AS ( + SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant + FROM suite_tree + UNION ALL + SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant + FROM suitepath_tree + ) + SELECT parent_id, id, initcap(name) AS name, description, iconName, leaf, generatable, multiselectable, relevant + FROM tree + ''' + } else { + // using internal API (deprecated) + sql = ''' + WITH + base AS ( + SELECT rownum AS an_id, + o.object_owner, + o.object_type, + o.object_name, + lower(a.name) AS name, + a.text, + a.subobject_name + FROM table(ut3.ut_annotation_manager.get_annotated_objects(user, 'PACKAGE')) o + CROSS JOIN table(o.annotations) a + WHERE lower(a.name) in ('suite', 'suitepath', 'endcontext', 'test') + OR lower(a.name) = 'context' AND regexp_like(text, '(\w+)(\.\w+)*') + ), + suite AS ( + SELECT object_owner, object_type, object_name, text AS suite_description + FROM base + WHERE name = 'suite' + ), + suitepath as ( + SELECT object_owner, object_type, object_name, lower(text) AS suitepath + FROM base + WHERE name = 'suitepath' + ), + context_base AS ( + SELECT an_id, + lead(an_id) over (partition by object_owner, object_type, object_name order by an_id) AS an_id_end, + object_owner, + object_type, + object_name, + name, + lead(name) over (partition by object_owner, object_type, object_name order by an_id) AS name_end, + text as context + FROM base + WHERE name IN ('context', 'endcontext') + ), + context as ( + SELECT an_id, an_id_end, object_owner, object_type, object_name, context + FROM context_base + WHERE name = 'context' + AND name_end = 'endcontext' + ), + test AS ( + SELECT b.an_id, + b.object_owner, + b.object_type, + b.object_name, + p.suitepath, + c.context, + b.subobject_name, + b.text AS test_description + FROM base b + LEFT JOIN suitepath p + ON p.object_owner = b.object_owner + AND p.object_type = b.object_type + AND p.object_name = b.object_name + LEFT JOIN context c + ON c.object_owner = b.object_owner + AND c.object_type = b.object_type + AND c.object_name = b.object_name + AND b.an_id BETWEEN c.an_id AND c.an_id_end + WHERE name = 'test' + AND (b.object_owner, b.object_type, b.object_name) IN ( + SELECT object_owner, object_type, object_name + FROM suite + ) + ), + suite_tree AS ( + SELECT null AS parent_id, + 'SUITE' AS id, + 'All Suites' AS name, + 'All utPLSQL test suites' AS description, + 'PACKAGE_FOLDER_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM dual + UNION ALL + SELECT DISTINCT + 'SUITE' AS parent_id, + object_owner || '.' || object_name AS id, + object_name AS name, + null AS description, + 'PACKAGE_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + UNION ALL + SELECT object_owner || '.' || object_name AS parent_id, + object_owner || '.' || object_name || '.' || upper(subobject_name) AS id, + subobject_name AS name, + null AS description, + 'PROCEDURE_ICON' AS iconName, + 'Yes' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + ), + suitepath_base AS ( + SELECT DISTINCT + suitepath + FROM suitepath + ), + gen AS ( + SELECT rownum AS pos + FROM xmltable('1 to 100') + ), + suitepath_part AS ( + SELECT DISTINCT + lower(substr(suitepath, 1, instr(suitepath || '.', '.', 1, g.pos) -1)) AS suitepath + FROM suitepath_base b + JOIN gen g + ON g.pos <= regexp_count(suitepath, '\w+') + ), + suitepath_tree AS ( + SELECT NULL AS parent_id, + 'SUITEPATH' AS id, + 'All Suitepaths' AS name, + 'All utPLSQL test suitepathes' AS description, + 'FOLDER_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM dual + UNION ALL + SELECT CASE + WHEN regexp_replace(suitepath,'\.?\w+$','') IS NULL THEN + 'SUITEPATH' + ELSE + USER || ':' || regexp_replace(suitepath,'\.?\w+$','') + END AS parent_id, + USER || ':' || suitepath AS id, + regexp_substr(suitepath, '\.?(\w+$)', 1, 1, NULL, 1) AS name, + null AS description, + 'FOLDER_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM suitepath_part + UNION ALL + SELECT DISTINCT + object_owner || ':' || suitepath AS parent_id, + object_owner || ':' || suitepath || '.' || lower(object_name) AS id, + object_name AS name, + null AS description, + 'PACKAGE_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + WHERE suitepath IS NOT NULL + UNION ALL + SELECT DISTINCT + object_owner || ':' || suitepath || '.' || lower(object_name) AS parent_id, + object_owner || ':' || suitepath || '.' || lower(object_name) || '.' || context AS id, + context AS name, + null AS description, + 'FOLDER_ICON' AS iconName, + 'No' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + WHERE suitepath IS NOT NULL + AND context IS NOT NULL + UNION ALL + SELECT object_owner || ':' || suitepath || '.' || lower(object_name) || CASE WHEN context IS NOT NULL THEN '.' || context END AS parent_id, + object_owner || ':' || suitepath || '.' || lower(object_name) || CASE WHEN context IS NOT NULL THEN '.' || context END || '.' || lower(subobject_name) AS id, + subobject_name AS name, + null AS description, + 'PROCEDURE_ICON' AS iconName, + 'Yes' AS leaf, + 'Yes' AS generatable, + 'Yes' AS multiselectable, + 'Yes' AS relevant + FROM test + WHERE suitepath IS NOT NULL + ), + tree AS ( + SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant + FROM suite_tree + UNION ALL + SELECT parent_id, id, name, description, iconName, leaf, generatable, multiselectable, relevant + FROM suitepath_tree + ) + SELECT parent_id, id, initcap(name) AS name, description, iconName, leaf, generatable, multiselectable, relevant + FROM tree + ''' + } val jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true)) val nodes = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Node)) return nodes @@ -638,8 +843,9 @@ class UtplsqlDao { 'MDSYS', 'OLAPSYS', 'ORDDATA', 'XDB', 'WMSYS', 'ORDSYS', 'GSMCATUSER', 'MDDATA', 'REMOTE_SCHEDULER_AGENT', 'SYSBACKUP', 'GSMUSER', 'APEX_PUBLIC_USER', 'SYSRAC', 'AUDSYS', 'DIP', 'SYSKM', 'ORACLE_OCM', 'APEX_INSTANCE_ADMIN_USER', - 'SYSDG', 'FLOWS_FILES', 'ORDS_METADATA', 'ORDS_PUBLIC_USER', 'APEX_180100' + 'SYSDG', 'FLOWS_FILES', 'ORDS_METADATA', 'ORDS_PUBLIC_USER' ) + AND referenced_owner NOT LIKE 'APEX\_______' AND referenced_type IN ('PACKAGE', 'TYPE', 'PROCEDURE', 'FUNCTION', 'TRIGGER') ''' val jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true)) diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend b/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend index 087f2330..ee658e91 100644 --- a/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend +++ b/sqldev/src/main/java/org/utplsql/sqldev/model/ut/Annotation.xtend @@ -21,7 +21,6 @@ import org.utplsql.sqldev.model.AbstractModel @Accessors class Annotation extends AbstractModel { String objectOwner - String objectType String objectName String name String text diff --git a/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend b/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend index 6ceb7544..9dbad90b 100644 --- a/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend +++ b/sqldev/src/test/java/org/utplsql/sqldev/tests/DalTest.xtend @@ -86,9 +86,9 @@ class DalTest extends AbstractJdbcTest { Assert.assertTrue(dao.utAnnotationManagerInstalled) } - @Test - def void containsUtplsqlTest() { + def void containsUtplsqlTest(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS -- %suite @@ -125,10 +125,20 @@ class DalTest extends AbstractJdbcTest { Assert.assertFalse(dao.containsUtplsqlTest("scott", "junit_utplsql_test_pkg", "t3")) jdbcTemplate.execute("DROP PACKAGE junit_utplsql_test_pkg") } - + + @Test + def void containsUtplsqlTest304() { + containsUtplsqlTest("3.0.4") + } + @Test - def void annotations() { + def void containsUtplsqlTest313() { + containsUtplsqlTest("3.1.3") + } + + def void annotations(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS -- %suite @@ -146,31 +156,39 @@ class DalTest extends AbstractJdbcTest { val expected = new ArrayList val suite = new Annotation suite.objectOwner = "SCOTT" - suite.objectType = "PACKAGE" suite.objectName = "JUNIT_UTPLSQL_TEST_PKG" suite.name = 'suite' + suite.subobjectName = suite.objectName expected.add(suite) val t1 = new Annotation t1.objectOwner = "SCOTT" - t1.objectType = "PACKAGE" t1.objectName = "JUNIT_UTPLSQL_TEST_PKG" t1.name = 'test' - t1.subobjectName = 't1' + t1.subobjectName = 'T1' expected.add(t1) val t2 = new Annotation t2.objectOwner = "SCOTT" - t2.objectType = "PACKAGE" t2.objectName = "JUNIT_UTPLSQL_TEST_PKG" t2.name = 'test' - t2.subobjectName = 't2' + t2.subobjectName = 'T2' expected.add(t2) Assert.assertEquals(expected.toString, actual.toString) jdbcTemplate.execute("DROP PACKAGE junit_utplsql_test_pkg") } - + + @Test + def void annotations304() { + annotations("3.0.4") + } + @Test - def void testablesPackages() { + def void annotations313() { + annotations("3.1.3") + } + + def void testablesPackages(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS -- %suite @@ -197,8 +215,18 @@ class DalTest extends AbstractJdbcTest { } @Test - def void testablesTypes() { + def void testablesPackages304() { + testablesPackages("3.0.4") + } + + @Test + def void testablesPackages313() { + testablesPackages("3.1.3") + } + + def void testablesTypes(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE TYPE junit_tab1_ot IS object (a integer, b integer); ''') @@ -218,8 +246,18 @@ class DalTest extends AbstractJdbcTest { } @Test - def void testablesFunctions() { + def void testablesTypes304() { + testablesTypes("3.0.4") + } + + @Test + def void testablesTypes313() { + testablesTypes("3.1.3") + } + + def void testablesFunctions(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE FUNCTION junit_f RETURN INTEGER IS BEGIN @@ -232,8 +270,18 @@ class DalTest extends AbstractJdbcTest { } @Test - def void testablesProcedures() { + def void testablesFunctions304() { + testablesFunctions("3.0.4") + } + + @Test + def void testablesFunctions313() { + testablesFunctions("3.1.3") + } + + def void testablesProcedures(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE PROCEDURE junit_p RETURN INTEGER IS BEGIN @@ -246,22 +294,32 @@ class DalTest extends AbstractJdbcTest { } @Test - def void runnables() { + def void testablesProcedures304() { + testablesProcedures("3.0.4") + } + + @Test + def void testablesProcedures313() { + testablesProcedures("3.1.3") + } + + def void runnables(String utPlsqlVersion) { val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = utPlsqlVersion jdbcTemplate.execute(''' CREATE OR REPLACE PACKAGE junit_utplsql_test_pkg IS -- %suite -- %suitepath(a.B.c) -- %test - PROCEDURE t0; + PROCEDURE T0; - -- %context(mycontext) + -- %context(myContext) - -- %test + -- %test(t1: test One) PROCEDURE t1; - -- %test + -- %test(t2: test Two) PROCEDURE t2; -- %endcontext @@ -278,20 +336,30 @@ class DalTest extends AbstractJdbcTest { } Assert.assertEquals(null, actual.get("SUITE")) Assert.assertEquals("SUITE", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG")) - Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t0")) - Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t1")) - Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t2")) - Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.t3")) + Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T0")) + Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T1")) + Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T2")) + Assert.assertEquals("SCOTT.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT.JUNIT_UTPLSQL_TEST_PKG.T3")) Assert.assertEquals(null, actual.get("SUITEPATH")) Assert.assertEquals("SUITEPATH", actual.get("SCOTT:a")) Assert.assertEquals("SCOTT:a", actual.get("SCOTT:a.b")) Assert.assertEquals("SCOTT:a.b", actual.get("SCOTT:a.b.c")) - Assert.assertEquals("SCOTT:a.b.c", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG")) - Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext")) - Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.t0")) - Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.t3")) - Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext.t1")) - Assert.assertEquals("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext", actual.get("SCOTT:a.b.c.JUNIT_UTPLSQL_TEST_PKG.mycontext.t2")) + Assert.assertEquals("SCOTT:a.b.c", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg")) + Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext")) + Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.t0")) + Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.t3")) + Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext.t1")) + Assert.assertEquals("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext", actual.get("SCOTT:a.b.c.junit_utplsql_test_pkg.myContext.t2")) + } + + @Test + def void runnables304() { + runnables("3.0.4") + } + + @Test + def void runnables313() { + runnables("3.1.3") } @Test @@ -361,5 +429,47 @@ class DalTest extends AbstractJdbcTest { val actual = dao.includes('junit_utplsql_test_pkg') Assert.assertEquals(#['JUNIT_UTPLSQL_TEST_PKG','JUNIT_F','UT_EXPECTATION'].sort, actual.sort) } + + @Test + def void normalizedPlsqlVersionOkRelease() { + val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = "v3.1.10.1234" + val actual = dao.normalizedUtPlsqlVersion() + Assert.assertEquals("3.1.10", actual) + } + + @Test + def void normalizedPlsqlVersionOkDevelop() { + val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = "v3.1.10.1234-develop" + val actual = dao.normalizedUtPlsqlVersion() + Assert.assertEquals("3.1.10", actual) + } + + @Test + def void normalizedPlsqlVersionNok() { + val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = "bla bla 1.2" + val actual = dao.normalizedUtPlsqlVersion() + Assert.assertEquals("0.0.0", actual) + } + + @Test + def void normaliedPlsqlVersionNumber() { + val dao = new UtplsqlDao(dataSource.connection) + dao.utPlsqlVersion = "3.14.37" + val actual = dao.normalizedUtPlsqlVersionNumber() + Assert.assertEquals(3014037, actual) + } + + @Test + def void utPlsqlVersion() { + val dao = new UtplsqlDao(dataSource.connection) + val actual = dao.utPlsqlVersion + val sql = "SELECT ut.version FROM DUAL" + val expected = jdbcTemplate.queryForObject(sql, String) + Assert.assertEquals(expected, actual) + + } } \ No newline at end of file diff --git a/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend b/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend index 131a9d4e..93be55f4 100644 --- a/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend +++ b/sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend @@ -35,6 +35,7 @@ class UtplsqlParserTest extends AbstractJdbcTest { CREATE OR REPLACE PACKAGE pkg IS -- %suite -- %rollback(manual) + -- %test PROCEDURE p (in_p1 INTEGER); FUNCTION f (in_p1 INTEGER) RETURN INTEGER; @@ -90,7 +91,7 @@ class UtplsqlParserTest extends AbstractJdbcTest { Assert.assertEquals("pkg", parser.getPathAt(parser.toPosition(4,1))) Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(10,33))) Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(13,1))) - Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(19,1))) + Assert.assertEquals("SCOTT.PKG.p", parser.getPathAt(parser.toPosition(19,1))) Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(22,9))) Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(22,10))) Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(29,1))) @@ -125,7 +126,7 @@ class UtplsqlParserTest extends AbstractJdbcTest { Assert.assertEquals(2, parser.getObjects.size) Assert.assertEquals(2, parser.getUnits.size) Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(13,1))) - Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(19,1))) + Assert.assertEquals("SCOTT.PKG.p", parser.getPathAt(parser.toPosition(19,1))) setupAndTeardown }