MINI MINI MANI MO
Rem
Rem $Header: javavm/install/jvm_ojds.sql /main/5 2017/07/03 21:56:53 stanaya Exp $
Rem
Rem jvm_ojds.sql
Rem
Rem Copyright (c) 2011, 2017, Oracle and/or its affiliates.
Rem All rights reserved.
Rem
Rem NAME
Rem jvm_ojds.sql - Database support for Orcle Java Directory Service
Rem
Rem DESCRIPTION
Rem Creates tables, sequences and indexes for Ojds tables.
Rem Creates pl/sql procdures and funtions for Ojds support.
Rem
Rem NOTES
Rem Create packages ojds_namespace and ojds_context.
Rem
Rem BEGIN SQL_FILE_METADATA
Rem SQL_SOURCE_FILE: javavm/install/jvm_ojds.sql
Rem SQL_SHIPPED_FILE: javavm/install/jvm_ojds.sql
Rem SQL_PHASE: JVM_OJDS
Rem SQL_STARTUP_MODE: NORMAL
Rem SQL_IGNORABLE_ERRORS: NONE
Rem END SQL_FILE_METADATA
Rem
Rem MODIFIED (MM/DD/YY)
Rem etucker 02/22/17 - qaulify SYSTEM objects
Rem nneeluru 03/13/14 - Longer identifiers
Rem etucker 09/03/12 - add protection agains missing ojds_context
Rem package
Rem etucker 05/31/11 - Created
Rem
Rem
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
-- This is the generator of node ids
create sequence OJVMSYS.ojds$node_number$;
-- This is the generator of node ids
create table OJVMSYS.ojds$bindings$ (parent number(28),child number(28),
id varchar(256),
binding_type number);
-- Set up the primary key for the bindings table
alter table OJVMSYS.ojds$bindings$ add primary key (parent, id);
-- This is the table that stores nodes (directories or leaves)
-- refcount is the number of times the node appears in
-- OJVMSYS.ojds$bindings$.child
create table OJVMSYS.ojds$inode$ (node number(28), type number,
refcount number, creation_ts date,
last_modified date, owner varchar2(128),
is_context number(1),
class_name varchar(4000),
class_factory varchar(4000),
class_factory_location varchar(4000),
shared number(1));
-- Create an index so that nodes may be quickly retrieved
create index OJVMSYS.ojds$node_index on OJVMSYS.ojds$inode$ (node);
-- This is the table that stores the attributes the namespace
create table OJVMSYS.ojds$attributes$ (node number(28), id varchar(256),
data blob);
-- Set up the primary key for the attributes table
alter table OJVMSYS.ojds$attributes$ add primary key (node, id);
-- This is the table that stores the reference address data in the namespace
create table OJVMSYS.ojds$refaddr$ (node number(28),
ref_seq number,
ref_minor_seq number,
ref_kind number,
ref_type varchar(200),
ref_string varchar(4000),
ref_bytes raw(2000));
create index OJVMSYS.ojds$refaddr_index on OJVMSYS.ojds$refaddr$ (node, ref_seq, ref_minor_seq);
-- This is the table that stores permissions on nodes
-- Read = 0
-- Write = 1
-- Execute = 2
create table OJVMSYS.ojds$permissions$ (node number(28),
type number,
schema varchar2(128));
-- Create an index so that permissions may be quickly retrieved
create index OJVMSYS.ojds$perm_index on OJVMSYS.ojds$permissions$ (node, type);
-- This is the generator of shared obj mem ids
create sequence OJVMSYS.ojds$shared$obj$seq$;
-- This is the table that stores the shared obj mem information
create table OJVMSYS.ojds$shared$obj$ (node number(28), timestamp date,
key varchar(30), byte_size number);
-- Create an index so that shared obj mems may be quickly retrieved
create index OJVMSYS.ojds$shared$obj_index on OJVMSYS.ojds$shared$obj$ (node, timestamp);
create or replace synonym ojds$node_number$ for OJVMSYS.ojds$node_number$;
create or replace synonym ojds$bindings$ for OJVMSYS.ojds$bindings$;
create or replace synonym ojds$inode$ for OJVMSYS.ojds$inode$;
create or replace synonym ojds$attributes$ for OJVMSYS.ojds$attributes$;
create or replace synonym ojds$refaddr$ for OJVMSYS.ojds$refaddr$;
create or replace synonym ojds$permissions$ for OJVMSYS.ojds$permissions$;
create or replace synonym ojds$shared$obj$seq$ for OJVMSYS.ojds$shared$obj$seq$;
create or replace synonym ojds$shared$obj$ for OJVMSYS.ojds$shared$obj$;
-- The ojds bindings and node tables should not be inserted,
-- deleted directly.
create or replace package ojds_context authid current_user as
-- make a new context with the identified parent and return its node
function mkcontext (p number, c varchar2) return number;
-- make a new reference and return its node
function mkreference (r varchar2) return number;
-- bind a node to a parent
procedure link (p number, c number, i varchar2, bt number);
-- remove a node from a parent
procedure unlink (p number, i varchar2);
-- remove nodes with zero reference_count
function rmUnrefNodes (junk number) return boolean;
-- remove non-empty context
function rmEmptyCtx (c number) return number;
procedure relink (p number, i varchar2, nc number, nt number);
-- helper for buiding initial context in sql.
procedure addperm (i number, t number, s varchar2);
-- invoked when a user is dropped cascade
procedure user_dropped (the_user varchar2);
procedure role_dropped (the_role varchar2);
procedure drop_inode_s (the_dropped varchar2);
procedure drop_permission_s (the_dropped varchar2);
function drop_inode_slow (the_dropped varchar2) return boolean;
procedure drop_inode_node (inode_number NUMBER);
procedure drop_all_child_links (inode_number NUMBER);
function is_this_a_context (inode_number NUMBER) return boolean;
end ojds_context;
/
create or replace package body ojds_context as
-- make a new context and return its node
function mkcontext (p number, c varchar2) return number is
inode number;
begin
select ojds$node_number$.nextval into inode from SYS.dual;
insert into ojds$inode$ (node, type, refcount, creation_ts,
last_modified, owner, is_context)
values (inode, 1, 0, sysdate, sysdate, c, 1);
-- "." and ".." do not contribute to reference counting
-- that's why the links are inserted and deleted manually
-- bind ".." to the parent
insert into ojds$bindings$ (parent, child, id, binding_type)
values (inode, p, '..', 1);
-- bind "." to the parent
insert into ojds$bindings$ (parent, child, id, binding_type)
values (inode, inode, '.', 1);
return inode;
end;
-- make a new reference and return its node
function mkreference (r varchar2) return number is
inode number;
begin
select ojds$node_number$.nextval into inode from SYS.dual;
insert into ojds$inode$ (node, type, refcount, creation_ts,
last_modified, owner, is_context)
values (inode, 2, 0, sysdate, sysdate, r, 0);
return inode;
end;
-- bind a node to a parent
procedure link (p number, c number, i varchar2 , bt number) is
begin
-- update the refcount first, as we should be idempotent on
-- ref managment.
update ojds$inode$ set refcount = refcount + 1 where node = c;
insert into ojds$bindings$ (parent, child, id, binding_type)
values (p, c, i, bt);
end;
-- remove a node from a parent
procedure unlink (p number, i varchar2) is
c number;
bt number;
begin
-- gets the child and lock the rows in bindings$ and inode$ tables
select b.child, b.binding_type into c, bt
from ojds$bindings$ b, ojds$inode$ n
where b.parent = p and b.id = i and
n.node = b.child for update;
-- delete "." and ".." if it's a context
if bt = 1 then
delete from ojds$bindings$ where parent = c and (id = '.' or id = '..');
end if;
-- delete the parent -> child link
delete from ojds$bindings$
where parent = p and id = i;
-- update the child ref count
update ojds$inode$ set refcount = refcount - 1 where node = c;
-- delete the child if refcount is 0
delete from ojds$inode$ where refcount = 0 and node = c;
-- if child was deleted also delete its entries in $permissions
if sql%rowcount > 0 then -- true if the node was deleted in $inode
delete from ojds$permissions$ where node = c;
delete from ojds$attributes$ where node = c;
delete from ojds$refaddr$ where node = c;
end if;
exception
when others then -- catches the case of deleting an unknown binding
if sql%notfound then
null;
end if;
end;
-- remove unreferenced nodes
function rmUnrefNodes (junk number) return boolean is
cursor unrefNodes_cur is select node from ojds$inode$ where refcount = 0;
notEmpty boolean;
begin
notEmpty := FALSE;
for unrefNodes_rec in unrefNodes_cur
loop
notEmpty := TRUE;
-- delete the inode, permission, and attributes
delete from ojds$inode$ where node = unrefNodes_rec.node;
delete from ojds$permissions$ where node = unrefNodes_rec.node;
delete from ojds$attributes$ where node = unrefNodes_rec.node;
delete from ojds$refaddr$ where node = unrefNodes_rec.node;
-- delete child bindings and children's refcount
update ojds$inode$ set refcount = refcount - 1 where
node in (select i.node from ojds$inode$ i, ojds$bindings$ b
where i.node = b.child and b.parent = unrefNodes_rec.node and b.id <> '..' and b.id <> '.');
delete from ojds$bindings$ where parent = unrefNodes_rec.node;
end loop;
return notEmpty;
end;
-- remove empty context; return 1 if it's NOT EMPTY; returns 0 : success.
function rmEmptyCtx (c number) return number is
cnt number;
begin
select count(*) into cnt from ojds$bindings$ where parent = c and id <> '.' and id <> '..';
if (cnt <> 0)
then
return 1; -- not empty
end if;
-- delete its own "." and ".."
delete from ojds$bindings$ where parent = c;
-- delete all pointers to itself
delete from ojds$bindings$ where child = c;
-- delete the inode, permission, and attributes
delete from ojds$inode$ where node = c;
delete from ojds$permissions$ where node = c;
delete from ojds$attributes$ where node = c;
delete from ojds$refaddr$ where node = c;
return 0;
end;
-- relink an entry
procedure relink (p number, i varchar2, nc number, nt number) is
c number;
begin
-- gets the child and lock the rows in bindings$ and inode$ tables
select b.child into c from ojds$bindings$ b, ojds$inode$ n
where b.parent = p and b.id = i and
n.node = b.child for update;
-- update the child ref count
update ojds$inode$ set refcount = refcount - 1 where node = c;
-- update the binding
update ojds$bindings$ set child = nc, binding_type = nt where parent = p and id = i;
-- ref managment.
update ojds$inode$ set refcount = refcount + 1 where node = nc;
-- delete the child if refcount is 0
delete from ojds$inode$ where refcount = 0 and node = c;
-- if child was deleted also delete its entries in $permissions
if sql%rowcount > 0 then -- true if the node was deleted in $inode
delete from ojds$permissions$ where node = c;
delete from ojds$attributes$ where node = c;
delete from ojds$refaddr$ where node = c;
end if;
exception
when others then -- catches the case of deleting an unknown binding
if sql%notfound then
link(p, nc, i, nt);
end if;
end;
-- since permissions are lists, the java code that
-- manipulates this deletes all the permissions, and
-- adds the new ones since permissions are gc'd with their
-- associated inode, this should really be done with
-- some sort of constraint or procedure, but I don't know
-- how to pass arrays to sql from java.
-- helper function for building initial context
procedure addperm (i number, t number, s varchar2) is
begin
insert into ojds$permissions$ (node, type, schema) values (i, t, s);
end;
-- drop user artifacts when a user is dropped.
procedure user_dropped (the_user varchar2) is
begin
drop_inode_s(the_user);
drop_permission_s(the_user);
end;
procedure role_dropped (the_role varchar2) is
begin
drop_permission_s(the_role);
end;
procedure drop_permission_s (the_dropped varchar2) is
begin
delete from ojds$permissions$ where schema=the_dropped;
end;
procedure drop_inode_s (the_dropped varchar2) is
tmpp boolean;
begin
delete from ojds$permissions$ where schema=the_dropped;
-- check inode owner
loop
tmpp := drop_inode_slow(the_dropped);
exit when tmpp = FALSE;
end loop;
end;
procedure drop_inode_node (inode_number NUMBER) is
begin
delete from ojds$inode$ where node = inode_number;
delete from ojds$permissions$ where node = inode_number;
delete from ojds$attributes$ where node = inode_number;
delete from ojds$refaddr$ where node = inode_number;
-- delete inward pointers.
delete from ojds$bindings$ where child = inode_number;
end;
function is_this_a_context (inode_number NUMBER) return boolean is
tmp1 NUMBER;
begin
select is_context into tmp1 from ojds$inode$ where node = inode_number;
if (tmp1 = 0)
then
return FALSE;
else
return TRUE;
end if;
end;
function drop_inode_slow (the_dropped varchar2) return boolean is
cursor drop_inode_cur is select node from ojds$inode$ where owner=the_dropped;
notEmpty boolean;
inode_number NUMBER;
is_context_ NUMBER;
begin
notEmpty := FALSE;
open drop_inode_cur;
fetch drop_inode_cur into inode_number;
if drop_inode_cur%NOTFOUND then
close drop_inode_cur;
return FALSE;
end if;
close drop_inode_cur;
if (is_this_a_context(inode_number)) then
-- take care of '.' and '..'
delete from ojds$bindings$ where parent=inode_number and ((id = '.') or (id = '..'));
drop_all_child_links(inode_number);
end if;
drop_inode_node(inode_number);
return TRUE;
end;
-- after deleting pointers to children and decrement children's reference count
-- we can use 'rmUnrefNode' to take care of the rest
procedure drop_all_child_links (inode_number NUMBER) is
cursor all_children_cur is select child from ojds$bindings$ where parent = inode_number and id <> '.' and id <> '..';
tmpp boolean;
begin
for children_rec in all_children_cur
loop
update ojds$inode$ set refcount = refcount - 1 where node = children_rec.child;
end loop;
delete from ojds$bindings$ where parent=inode_number and id <> '.' and id <> '..';
-- remove nodes with zero refcount cascadingly
loop
tmpp := rmUnrefNodes(1);
exit when tmpp = FALSE;
end loop;
end;
end ojds_context;
/
grant execute on ojds_context to DBA;
create or replace package ojds_namespace authid current_user as
-- Write the serialized command
procedure write(bytes long raw);
-- Execute the command
function execute return number;
-- Read the serialzed result
function read return long raw;
end ojds_namespace;
/
create or replace package body ojds_namespace as
-- Write the serialized command
procedure write(bytes long raw)
as language java name
'oracle.aurora.jndi.ojds.Server.write(byte[])';
-- Execute the command
function execute return number
as language java name
'oracle.aurora.jndi.ojds.Server.execute() return boolean';
-- Read the serialzed result
function read return long raw
as language java name
'oracle.aurora.jndi.ojds.Server.read() return byte[]';
end ojds_namespace;
/
create or replace public synonym ojds_namespace for ojds_namespace;
grant execute on ojds_namespace to public;
-- Create the initial context
declare
root number;
pubn number;
etc number;
pub varchar2(30) := 'PUBLIC';
sys varchar2(30) := 'SYS';
read number;
write number;
execute number;
object_type number;
context_type number;
begin
read := 0;
write := 1;
execute := 2;
object_type := 0;
context_type := 1;
root := 1;
-- create root
root := ojds_context.mkcontext (root, sys);
ojds_context.addperm (root, read, pub);
ojds_context.addperm (root, write, sys);
ojds_context.addperm (root, execute, pub);
-- devilishly setup the root node refcount
update ojds$inode$ set refcount = 666 where node = root;
-- since no one refers to root, it should never get deleted by gc
-- create public
pubn := ojds_context.mkcontext (root, sys);
ojds_context.addperm (pubn, read, pub);
ojds_context.addperm (pubn, write, pub);
ojds_context.addperm (pubn, execute, pub);
-- pub is in root
ojds_context.link (root, pubn, 'public', context_type);
-- create etc
etc := ojds_context.mkcontext(root, sys);
ojds_context.addperm (etc, read, pub);
ojds_context.addperm (etc, write, sys);
ojds_context.addperm (etc, execute, pub);
-- etc is in root
ojds_context.link (root, etc, 'etc', context_type);
end;
/
-- Commit these changes
commit;
-- remove all artifacts when a drop user cascade occurs
insert into duc$ (OWNER, PACK, PROC, FIELD1, OPERATION#, SEQ) values ('SYS', 'OJDS_CONTEXT', 'USER_DROPPED', 0, 1, 1);
-- remove all artifacts when an owning role is dropped.
create or replace trigger OJDS$ROLE_TRIGGER$ after drop on database when (ora_dict_obj_type='ROLE')
begin
ojds_context.role_dropped(ora_dict_obj_name);
exception -- if not present then ignore
when others then
if sqlcode not in (-00604, -04063, -06508) then raise; end if;
end;
/
commit;
OHA YOOOO