Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
This repository contains demo presenting capabilities of Oracle Database related to processing external JSON data stored in Object Storage buckets.
It consists of the following files:
* utl_json_cloud.* - this is the definition of PL/SQL package UTL_JSON_CLOUD, which is used in the demo
this package provides
wrappers for credential creation procedures allowing to create a credential object in the same way regardless of the flavour of the database
procedures automatizing creation of JSON collection views pointing to external JSON data
* demo.sql - demo presenting reading, importing, exporting and managing the external JSON data

# License

Copyright (c) 2025 Oracle and/or its affiliates.

Licensed under the Universal Permissive License (UPL), Version 1.0.

See [LICENSE](https://github.com/oracle-devrel/technology-engineering/blob/main/LICENSE) for more details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
-- required credential creation
begin
utl_json_cloud.create_or_replace_credential(p_credential_name => 'JSON_DEMO_CREDENTIAL',
p_username => 'username',
p_password => 'authentication_token');
end;
/


-- "external json collection" i.e. pair of external table pointing to some json data and json collection view on top of this
begin
utl_json_cloud.create_external_json_collection(p_collection_name => 'iot_events_external',
p_credential_name => 'JSON_DEMO_CREDENTIAL',
p_file_list => 'bucket_url/dir*/*.json');
end;
/

select *
from iot_events_external;

select *
from iot_events_external_ext;

select *
from iot_events;

drop table if exists iot_events_part;


-- json collection partitioned table
create json collection table iot_events_part
partition by range (json_value(DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR))
interval (numtodsinterval(1,'DAY'))
(
partition p_before_2025 values less than (DATE '2025-01-01')
);

-- loading data from "external json collection"
insert /*+ append parallel(16) */ into iot_events_part
select *
from iot_events_external;

select * from iot_events_part iot
WHERE json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) >= DATE '2025-01-30'
AND json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) < DATE '2025-01-31';

select partition_name, high_value
from user_tab_partitions where table_name = 'IOT_EVENTS_PART';

declare
part_URL VARCHAR2(4000);
begin
part_URL := 'bucket_url/year=2025/month=01';
dbms_cloud.export_data(
credential_name => 'JSON_DEMO_CREDENTIAL',
file_uri_list => part_URL || '/day=01/2025-01-01_events.json',
query => q'[
select
DATA
FROM iot_events_part c
WHERE json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) >= DATE '2025-01-01'
AND json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) < DATE '2025-01-02'
]',
format => json_object('type' VALUE 'json')
);
end;
/

-- data export

declare
part_URL VARCHAR2(4000);
begin
part_URL := ' part_URL := 'bucket_url/year=2025/month=01';
dbms_cloud.export_data(
credential_name => 'JSON_DEMO_CREDENTIAL',
file_uri_list => part_URL || '/day=02/2025-01-02_events.json',
query => q'[
select
DATA
FROM iot_events_part iot
WHERE json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) >= DATE '2025-01-02'
AND json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) < DATE '2025-01-03'
]',
format => json_object('type' VALUE 'json')
);
end;
/

declare
part_URL VARCHAR2(4000);
begin
part_URL := part_URL := 'bucket_url/year=2025/month=01';
dbms_cloud.export_data(
credential_name => 'JSON_DEMO_CREDENTIAL',
file_uri_list => part_URL || '/day=03/2025-01-03_events.json',
query => q'[
select
DATA
FROM iot_events_part iot
WHERE json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) >= DATE '2025-01-03'
AND json_value(iot.DATA, '$.eventDate' RETURNING DATE ERROR ON ERROR) < DATE '2025-01-04'
]',
format => json_object('type' VALUE 'json')
);
end;
/

-- cold data "external json collection view" creation
begin
utl_json_cloud.create_external_json_collection(p_collection_name => 'iot_events_cold_data',
p_credential_name => 'JSON_DEMO_CREDENTIAL',
p_file_list => 'bucket_url/year*/month*/day*/*.json');
end;
/

select *
from iot_events_cold_data;

-- old data removal
alter table iot_events_part
drop partition for (DATE '2025-01-01')
update indexes;

alter table iot_events_part
drop partition for (DATE '2025-01-02')
update indexes;

alter table iot_events_part
drop partition for (DATE '2025-01-03')
update indexes;

-- create a view on top of "external" and "internal" json collections
create or replace json collection view iot_events
as
select *
from iot_events_part
union all
select *
from iot_events_cold_data;

select *
from iot_events;



Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
create or replace package body utl_json_cloud
is
function is_autonomous return boolean
is
num_of_rows number(1);
begin
select count(*)
into num_of_rows
from dba_pdbs
where cloud_identity like '%AUTONOMOUS%';

if num_of_rows > 0 then
return true;
end if;
return false;
end;

procedure create_credential(p_credential_name varchar2,
p_username varchar2,
p_password varchar2)
is
begin
if is_autonomous then
dbms_cloud.create_credential(credential_name => p_credential_name,
username => p_username,
password => p_password);
else
dbms_credential.create_credential(credential_name => p_credential_name,
username => p_username,
password => p_password);
end if;
end;

procedure drop_credential(p_credential_name varchar2)
is
begin
if is_autonomous then
dbms_cloud.drop_credential(credential_name => p_credential_name);
else
dbms_credential.drop_credential(credential_name => p_credential_name);
end if;
end;

procedure create_or_replace_credential(p_credential_name varchar2,
p_username varchar2,
p_password varchar2)
is
begin
begin
drop_credential(p_credential_name);
exception
when e_non_existing_credential then
null;
end;
create_credential(p_credential_name,p_username,p_password);
end;

procedure create_external_json_collection(p_collection_name varchar2,
p_credential_name varchar2,
p_file_list clob)
is
begin
dbms_cloud.create_external_table(table_name => p_collection_name||'_ext',
credential_name => p_credential_name,
file_uri_list => p_file_list,
format => json_object('type' value 'jsondoc'));
execute immediate 'create or replace json collection view '||p_collection_name||' as select DATA from '||p_collection_name||'_ext';
end;

procedure drop_external_json_collection(p_collection_name varchar2)
is
begin
execute immediate 'drop view '||p_collection_name;
execute immediate 'drop table '||p_collection_name||'_ext';
end;

end;
/
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
create or replace package utl_json_cloud
is
e_non_existing_credential exception;
pragma exception_init(e_non_existing_credential,-20004);

function is_autonomous return boolean;

procedure create_credential(p_credential_name varchar2,
p_username varchar2,
p_password varchar2);

procedure drop_credential(p_credential_name varchar2);

procedure create_or_replace_credential(p_credential_name varchar2,
p_username varchar2,
p_password varchar2);

procedure create_external_json_collection(p_collection_name varchar2,
p_credential_name varchar2,
p_file_list clob);

procedure drop_external_json_collection(p_collection_name varchar2);

end;
/