Skip to content
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

Add copy_object procedure and bugfix for get_object_list #49

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
93 changes: 85 additions & 8 deletions ora/amazon_aws_s3_pkg.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ as
l_xml xmltype;
l_xml_is_truncated xmltype;
l_xml_next_continuation xmltype;

l_date_str varchar2(255);
l_auth_str varchar2(255);

Expand All @@ -559,9 +559,9 @@ begin
Purpose: get objects

Remarks: see http://docs.aws.amazon.com/AmazonS3/latest/API/v2-RESTBucketGET.html

see http://code.google.com/p/plsql-utils/issues/detail?id=16

"I've rewritten get_object_list as an internal procedure that uses the "marker" parameter,
so that get_object_tab can now call the Amazon API multiple times to return the complete set of objects.
The get_object_list function remains functionally unchanged in this version - it just returns one set of objects -
Expand All @@ -577,7 +577,7 @@ begin
KJS 06.10.2016 Modified to use newest S3 API which performs much better on large buckets. Changed for-loop to bulk operation.

*/

l_date_str := amazon_aws_auth_pkg.get_date_string;
l_auth_str := amazon_aws_auth_pkg.get_auth_string ('GET' || chr(10) || chr(10) || chr(10) || l_date_str || chr(10) || '/' || p_bucket_name || '/');

Expand All @@ -597,7 +597,7 @@ begin
l_header_values(3) := l_auth_str;

if p_next_continuation_token is not null then
l_clob := make_request (get_url(p_bucket_name) || '?list-type=2&continuation-token=' || utl_url.escape(p_next_continuation_token) || '&max-keys=' || p_max_keys || '&prefix=' || utl_url.escape(p_prefix), 'GET', l_header_names, l_header_values, null);
l_clob := make_request (get_url(p_bucket_name) || '?list-type=2&max-keys=' || p_max_keys || '&prefix=' || utl_url.escape(p_prefix) || '&continuation-token=' || utl_url.escape(p_next_continuation_token, true), 'GET', l_header_names, l_header_values, null);
else
l_clob := make_request (get_url(p_bucket_name) || '?list-type=2&max-keys=' || p_max_keys || '&prefix=' || utl_url.escape(p_prefix), 'GET', l_header_names, l_header_values, null);
end if;
Expand All @@ -612,10 +612,10 @@ begin
to_date(extractValue(value(t), '*/LastModified', g_aws_namespace_s3_full), g_date_format_xml)
bulk collect into l_returnvalue
from table(xmlsequence(l_xml.extract('//ListBucketResult/Contents', g_aws_namespace_s3_full))) t;

-- check if this is the last set of data or not, and set the in/out p_next_continuation_token as expected
l_xml_is_truncated := l_xml.extract('//ListBucketResult/IsTruncated/text()', g_aws_namespace_s3_full);

if l_xml_is_truncated is not null and l_xml_is_truncated.getStringVal = 'true' then
l_xml_next_continuation := l_xml.extract('//ListBucketResult/NextContinuationToken/text()', g_aws_namespace_s3_full);
if l_xml_next_continuation is not null then
Expand Down Expand Up @@ -876,6 +876,84 @@ begin

end delete_object;

procedure copy_object (p_src_bucket_name in varchar2,
p_src_key in varchar2,
p_dest_bucket_name in varchar2,
p_dest_key in varchar2,
p_acl in varchar2 := null) is
l_src_key varchar2(4000) := utl_url.escape (p_src_key);
l_dest_key varchar2(4000) := utl_url.escape (p_dest_key);

l_clob clob;

l_date_str varchar2(255);
l_auth_str varchar2(255);

l_header_names t_str_array := t_str_array();
l_header_values t_str_array := t_str_array();

begin

/*

Purpose: copy existing object to new destination

Remarks: see http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html

Who Date Description
------ ---------- -------------------------------------
KJS 24.01.2017 Created

*/

l_date_str := amazon_aws_auth_pkg.get_date_string;

if p_acl is not null then
l_auth_str := amazon_aws_auth_pkg.get_auth_string ('PUT' || chr(10) || chr(10) || chr(10) ||
l_date_str || chr(10) ||
'x-amz-acl:' || p_acl || chr(10) ||
'x-amz-copy-source:' || '/' || p_src_bucket_name || '/' || l_src_key || chr(10) ||
'/' || p_dest_bucket_name || '/' || l_dest_key);
else
l_auth_str := amazon_aws_auth_pkg.get_auth_string ('PUT' || chr(10) || chr(10) || chr(10) ||
l_date_str || chr(10) ||
'x-amz-copy-source:' || '/' || p_src_bucket_name || '/' || l_src_key || chr(10) ||
'/' || p_dest_bucket_name || '/' || l_dest_key);
end if;

l_header_names.extend;
l_header_names(1) := 'Host';
l_header_values.extend;
l_header_values(1) := get_host(p_dest_bucket_name);

l_header_names.extend;
l_header_names(2) := 'Date';
l_header_values.extend;
l_header_values(2) := l_date_str;

l_header_names.extend;
l_header_names(3) := 'Authorization';
l_header_values.extend;
l_header_values(3) := l_auth_str;

l_header_names.extend;
l_header_names(4) := 'x-amz-copy-source';
l_header_values.extend;
l_header_values(4) := '/' || p_src_bucket_name || '/' || l_src_key;

-- Per documentation, default ACL is always private to the authorized user, that is, this API does not copy the existing object ACL
if p_acl is not null then
l_header_names.extend;
l_header_names(5) := 'x-amz-acl';
l_header_values.extend;
l_header_values(5) := p_acl;
end if;

l_clob := make_request (get_url (p_src_bucket_name, l_dest_key), 'PUT', l_header_names, l_header_values);

check_for_errors (l_clob);
end copy_object;


function get_object (p_bucket_name in varchar2,
p_key in varchar2) return blob
Expand Down Expand Up @@ -1203,4 +1281,3 @@ end set_object_acl;

end amazon_aws_s3_pkg;
/