Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Cleanup and refactoring of annotation cache. #986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions .travis/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ PROMPT Creating $UT3_TESTER - Power-user for testing internal framework code
create user $UT3_TESTER identified by "$UT3_TESTER_PASSWORD" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE;
grant create session, create procedure, create type, create table to $UT3_TESTER;

PROMPT Additional grants for disabling DDL trigger and testing parser without trigger enabled/present

grant alter any trigger to $UT3_TESTER;
grant administer database trigger to $UT3_TESTER;
grant execute on dbms_lock to $UT3_TESTER;

PROMPT Granting $UT3_OWNER code to $UT3_TESTER
Expand All @@ -98,7 +94,7 @@ end;
PROMPT Granting $UT3_OWNER tables to $UT3_TESTER

begin
for i in ( select table_name from all_tables t where owner = 'UT3' and nested = 'NO' and IOT_NAME is NULL)
for i in ( select table_name from all_tables t where owner = 'UT3' and nested = 'NO' and iot_name is null)
loop
execute immediate 'grant select on UT3.'||i.table_name||' to UT3_TESTER';
end loop;
Expand All @@ -124,8 +120,33 @@ grant create public database link to $UT3_TESTER_HELPER;
grant drop public database link to $UT3_TESTER_HELPER;

PROMPT Grants for testing coverage outside of main UT3 schema.
grant create any procedure, drop any procedure, execute any procedure, create any type, drop any type, execute any type, under any type, select any table, update any table, insert any table, delete any table, create any table, drop any table, alter any table, select any dictionary, create any synonym, drop any synonym to $UT3_TESTER_HELPER;
grant create any procedure, drop any procedure, execute any procedure, create any type, drop any type, execute any type, under any type,
select any table, update any table, insert any table, delete any table, create any table, drop any table, alter any table,
select any dictionary, create any synonym, drop any synonym,
grant any object privilege, grant any privilege
to $UT3_TESTER_HELPER;

grant create job to $UT3_TESTER_HELPER;

PROMPT Additional grants for disabling DDL trigger and testing parser without trigger enabled/present

grant alter any trigger to $UT3_TESTER_HELPER;
grant administer database trigger to $UT3_TESTER_HELPER;
grant execute on dbms_lock to $UT3_TESTER_HELPER;

create user ut3_cache_test_owner identified by ut3;
grant create session, create procedure to ut3_cache_test_owner;

create user ut3_no_extra_priv_user identified by ut3;
grant create session, create procedure to ut3_no_extra_priv_user;

create user ut3_select_catalog_user identified by ut3;
grant create session, create procedure, select_catalog_role to ut3_select_catalog_user;

create user ut3_select_any_table_user identified by ut3;
grant create session, create procedure, select any table to ut3_select_any_table_user;

create user ut3_execute_any_proc_user identified by ut3;
grant create session, create procedure, execute any procedure to ut3_execute_any_proc_user;
exit
SQL
5 changes: 5 additions & 0 deletions development/cleanup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ drop user ${UT3_RELEASE_VERSION_SCHEMA} cascade;
drop user ${UT3_TESTER} cascade;
drop user ${UT3_TESTER_HELPER} cascade;
drop user ${UT3_USER} cascade;
drop user ut3_cache_test_owner cascade;
drop user ut3_no_extra_priv_user cascade;
drop user ut3_select_catalog_user cascade;
drop user ut3_select_any_table_user cascade;
drop user ut3_execute_any_proc_user cascade;

begin
for i in (
Expand Down
7 changes: 0 additions & 7 deletions docs/userguide/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,6 @@ cd source
sqlplus sys/sys_pass@db as sysdba @install_headless_with_trigger.sql utp3 my_verySecret_password utp3_tablespace
```

**Note:**
>When installing utPLSQL into database with existing unit test packages, utPLSQL will not be able to already-existing unit test packages. When utPSLQL was installed with DDL trigger, you have to do one of:
>- Recompile existing Unit Test packages to make utPLSQL aware of their existence
>- Invoke `exec ut_runner.rebuild_annotation_cache(a_object_owner=> ... );` for every schema containing unit tests in your database
>
> Steps above are required to assure annotation cache is populated properly from existing objects. Rebuilding annotation cache might be faster than code recompilation.

# Recommended Schema
It is highly recommended to install utPLSQL in it's own schema. You are free to choose any name for this schema.
Installing uPLSQL into shared schema is really not recommended as you loose isolation of framework.
Expand Down
5 changes: 3 additions & 2 deletions source/core/annotations/ut_annotation_cache_info.sql
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ create table ut_annotation_cache_info (
object_name varchar2(250) not null,
object_type varchar2(250) not null,
parse_time timestamp not null,
constraint ut_annotation_cache_info_pk primary key(cache_id),
constraint ut_annotation_cache_info_uk unique (object_owner, object_type, object_name)
constraint ut_annotation_cache_info_pk primary key(cache_id) using index,
constraint ut_annotation_cache_info_uk unique (object_owner, object_type, object_name) using index,
constraint ut_annotation_cache_info_fk foreign key(object_owner, object_type) references ut_annotation_cache_schema(object_owner, object_type) on delete cascade
) organization index;

124 changes: 72 additions & 52 deletions source/core/annotations/ut_annotation_cache_manager.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@ create or replace package body ut_annotation_cache_manager as
*/

procedure update_cache(a_object ut_annotated_object) is
l_cache_id integer;
l_new_objects_count integer := 0;
l_cache_id integer;
l_timestamp timestamp := systimestamp;
pragma autonomous_transaction;
begin
update ut_annotation_cache_schema s
set s.max_parse_time = l_timestamp
where s.object_type = a_object.object_type and s.object_owner = a_object.object_owner;

if sql%rowcount = 0 then
insert into ut_annotation_cache_schema s
(object_owner, object_type, max_parse_time)
values (a_object.object_owner, a_object.object_type, l_timestamp);
end if;

-- if not in trigger, or object has annotations
if ora_sysevent is null or a_object.annotations is not null and a_object.annotations.count > 0 then

update ut_annotation_cache_info i
set i.parse_time = systimestamp
set i.parse_time = l_timestamp
where (i.object_owner, i.object_name, i.object_type)
in ((a_object.object_owner, a_object.object_name, a_object.object_type))
returning cache_id into l_cache_id;
Expand All @@ -34,23 +44,12 @@ create or replace package body ut_annotation_cache_manager as

insert into ut_annotation_cache_info
(cache_id, object_owner, object_name, object_type, parse_time)
values (ut_annotation_cache_seq.nextval, a_object.object_owner, a_object.object_name, a_object.object_type, systimestamp)
values (ut_annotation_cache_seq.nextval, a_object.object_owner, a_object.object_name, a_object.object_type, l_timestamp)
returning cache_id into l_cache_id;
l_new_objects_count := 1;
end if;

end if;

update ut_annotation_cache_schema s
set s.object_count = s.object_count + l_new_objects_count, s.max_parse_time = systimestamp
where s.object_type = a_object.object_type and s.object_owner = a_object.object_owner;

if sql%rowcount = 0 then
insert into ut_annotation_cache_schema s
(object_owner, object_type, object_count, max_parse_time)
values (a_object.object_owner, a_object.object_type, l_new_objects_count, systimestamp);
end if;

delete from ut_annotation_cache c where cache_id = l_cache_id;

if a_object.annotations is not null and a_object.annotations.count > 0 then
Expand All @@ -63,7 +62,8 @@ create or replace package body ut_annotation_cache_manager as
end;


procedure cleanup_cache(a_objects ut_annotation_objs_cache_info) is
procedure reset_objects_cache(a_objects ut_annotation_objs_cache_info) is
l_timestamp timestamp := systimestamp;
pragma autonomous_transaction;
begin

Expand All @@ -75,23 +75,45 @@ create or replace package body ut_annotation_cache_manager as
on o.object_name = i.object_name
and o.object_type = i.object_type
and o.object_owner = i.object_owner
and o.needs_refresh = 'Y'
);

update ut_annotation_cache_schema s
set s.max_parse_time = l_timestamp
where (s.object_owner, s.object_type)
in (
select o.object_owner, o.object_type
from table(a_objects) o
where o.needs_refresh = 'Y'
);

if sql%rowcount = 0 then
insert into ut_annotation_cache_schema s
(object_owner, object_type, max_parse_time)
select distinct o.object_owner, o.object_type, l_timestamp
from table(a_objects) o
where o.needs_refresh = 'Y';
end if;

merge into ut_annotation_cache_info i
using (select o.object_name, o.object_type, o.object_owner
from table(a_objects) o ) o
from table(a_objects) o
where o.needs_refresh = 'Y'
) o
on (o.object_name = i.object_name
and o.object_type = i.object_type
and o.object_owner = i.object_owner)
when matched then update set parse_time = systimestamp
when matched then
update
set parse_time = l_timestamp
when not matched then insert
(cache_id, object_owner, object_name, object_type, parse_time)
values (ut_annotation_cache_seq.nextval, o.object_owner, o.object_name, o.object_type, systimestamp);
(cache_id, object_owner, object_name, object_type, parse_time)
values (ut_annotation_cache_seq.nextval, o.object_owner, o.object_name, o.object_type, l_timestamp);

commit;
end;

function get_annotations_objects_info(a_object_owner varchar2, a_object_type varchar2) return ut_annotation_objs_cache_info is
function get_cached_objects_list(a_object_owner varchar2, a_object_type varchar2, a_parsed_after timestamp := null) return ut_annotation_objs_cache_info is
l_result ut_annotation_objs_cache_info;
begin
select ut_annotation_obj_cache_info(
Expand All @@ -104,7 +126,8 @@ create or replace package body ut_annotation_cache_manager as
bulk collect into l_result
from ut_annotation_cache_info i
where i.object_owner = a_object_owner
and i.object_type = a_object_type;
and i.object_type = a_object_type
and (i.parse_time > a_parsed_after or a_parsed_after is null);
return l_result;
end;

Expand All @@ -123,6 +146,16 @@ create or replace package body ut_annotation_cache_manager as
return l_result;
end;

procedure set_fully_refreshed(a_object_owner varchar2, a_object_type varchar2) is
pragma autonomous_transaction;
begin
update ut_annotation_cache_schema s
set s.full_refresh_time = s.max_parse_time
where s.object_owner = a_object_owner
and s.object_type = a_object_type;
commit;
end;

procedure remove_from_cache(a_objects ut_annotation_objs_cache_info) is
pragma autonomous_transaction;
begin
Expand All @@ -138,10 +171,10 @@ create or replace package body ut_annotation_cache_manager as
commit;
end;

function get_annotations_for_objects(a_cached_objects ut_annotation_objs_cache_info, a_parse_time timestamp) return sys_refcursor is
l_results sys_refcursor;
function get_annotations_parsed_since(a_object_owner varchar2, a_object_type varchar2, a_parsed_after timestamp) return sys_refcursor is
l_results sys_refcursor;
begin
open l_results for q'[
open l_results for
select ut_annotated_object(
i.object_owner, i.object_name, i.object_type, i.parse_time,
cast(
Expand All @@ -151,14 +184,12 @@ create or replace package body ut_annotation_cache_manager as
) order by c.annotation_position
) as ut_annotations
)
)
from table(:a_cached_objects) o
join ut_annotation_cache_info i
on o.object_owner = i.object_owner and o.object_name = i.object_name and o.object_type = i.object_type
) as annotated_object
from ut_annotation_cache_info i
join ut_annotation_cache c on i.cache_id = c.cache_id
where ]'|| case when a_parse_time is null then ':a_parse_date is null' else 'i.parse_time > :a_parse_time' end ||q'[
group by i.object_owner, i.object_name, i.object_type, i.parse_time]'
using a_cached_objects, a_parse_time;
where i.object_owner = a_object_owner and i.object_type = a_object_type
and (i.parse_time > a_parsed_after or a_parsed_after is null)
group by i.object_owner, i.object_type, i.object_name, i.parse_time;
return l_results;
end;

Expand All @@ -168,35 +199,24 @@ create or replace package body ut_annotation_cache_manager as
pragma autonomous_transaction;
begin
if a_object_owner is null and a_object_type is null then
l_cache_filter := ':a_object_owner is null and :a_object_type is null';
l_filter := l_cache_filter;
l_filter := ':a_object_owner is null and :a_object_type is null';
l_cache_filter := l_filter;
else
l_filter :=
case when a_object_owner is null then ':a_object_owner is null' else 'object_owner = :a_object_owner' end || '
and '||case when a_object_type is null then ':a_object_type is null' else 'object_type = :a_object_type' end;
l_cache_filter := ' c.cache_id
in (select i.cache_id
from ut_annotation_cache_info i
where '|| l_filter || '
)';
l_filter := case when a_object_owner is null then ':a_object_owner is null' else 'object_owner = :a_object_owner' end;
l_filter := l_filter || ' and ' || case when a_object_type is null then ':a_object_type is null' else 'object_type = :a_object_type' end;
l_cache_filter := ' c.cache_id in (select i.cache_id from ut_annotation_cache_info i where ' || l_filter || ' )';
end if;
execute immediate '
delete from ut_annotation_cache c
where '||l_cache_filter
execute immediate 'delete from ut_annotation_cache c where ' || l_cache_filter
using a_object_owner, a_object_type;

execute immediate '
delete from ut_annotation_cache_info i
where ' || l_filter
execute immediate ' delete from ut_annotation_cache_info i where ' || l_filter
using a_object_owner, a_object_type;

execute immediate '
delete from ut_annotation_cache_schema s
where ' || l_filter
execute immediate ' delete from ut_annotation_cache_schema s where ' || l_filter
using a_object_owner, a_object_type;

commit;
end;

end ut_annotation_cache_manager;
end;
/
19 changes: 13 additions & 6 deletions source/core/annotations/ut_annotation_cache_manager.pks
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ create or replace package ut_annotation_cache_manager authid definer as
limitations under the License.
*/
subtype t_cache_schema_info is ut_annotation_cache_schema%rowtype;

/**
* Populates cache with information about object and it's annotations
* Cache information for individual object is modified by this code
Expand All @@ -30,21 +31,27 @@ create or replace package ut_annotation_cache_manager authid definer as
* Returns a ref_cursor containing `ut_annotated_object` as result
* Range of data returned is limited by the input collection o cache object info
*
* @param a_cached_objects a `ut_annotation_objs_cache_info` list with information about objects to get from cache
* @param a_cached_objects - list of `ut_annotation_objs_cache_info` containing objects to get from cache
* @param a_min_parse_time - limit results to annotations parsed after specified time only,
* if null - all cached annotations for given objects are returned
*/
function get_annotations_for_objects(a_cached_objects ut_annotation_objs_cache_info, a_parse_time timestamp) return sys_refcursor;

function get_annotations_parsed_since(a_object_owner varchar2, a_object_type varchar2, a_parsed_after timestamp) return sys_refcursor;

function get_annotations_objects_info(a_object_owner varchar2, a_object_type varchar2) return ut_annotation_objs_cache_info;
procedure set_fully_refreshed(a_object_owner varchar2, a_object_type varchar2);

function get_cache_schema_info(a_object_owner varchar2, a_object_type varchar2) return t_cache_schema_info;

/**
* Removes cached information about annotations for objects on the list and updates parse_time in cache info table.
* Returns information about all objects stored in annotation cache
*/
function get_cached_objects_list(a_object_owner varchar2, a_object_type varchar2, a_parsed_after timestamp := null) return ut_annotation_objs_cache_info;

/**
* Resets cached information about annotations for objects on the list and updates parse_time in cache info table.
*
* @param a_objects a `ut_annotation_objs_cache_info` list with information about objects to remove annotations for
*/
procedure cleanup_cache(a_objects ut_annotation_objs_cache_info);
procedure reset_objects_cache(a_objects ut_annotation_objs_cache_info);

/**
* Removes information about objects on the list
Expand Down
8 changes: 4 additions & 4 deletions source/core/annotations/ut_annotation_cache_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ create table ut_annotation_cache_schema (
See the License for the specific language governing permissions and
limitations under the License.
*/
object_owner varchar2(250) not null,
object_type varchar2(250) not null,
object_count integer not null,
max_parse_time date not null,
object_owner varchar2(250) not null,
object_type varchar2(250) not null,
max_parse_time date not null,
full_refresh_time timestamp,
constraint ut_annotation_cache_schema_pk primary key(object_owner, object_type)
) organization index;

Loading