@@ -533,22 +533,23 @@ begin
533533end get_bucket_region;
534534
535535
536- procedure get_object_list (p_bucket_name in varchar2,
537- p_prefix in varchar2,
538- p_max_keys in number,
539- p_list out t_object_list,
540- p_more_marker in out varchar2)
536+ procedure get_object_list (p_bucket_name in varchar2,
537+ p_prefix in varchar2,
538+ p_max_keys in number,
539+ p_list out t_object_list,
540+ p_next_continuation_token in out varchar2)
541541as
542542 l_clob clob;
543543 l_xml xmltype;
544+ l_xml_is_truncated xmltype;
545+ l_xml_next_continuation xmltype;
544546
545547 l_date_str varchar2(255);
546548 l_auth_str varchar2(255);
547549
548550 l_header_names t_str_array := t_str_array();
549551 l_header_values t_str_array := t_str_array();
550552
551- l_count pls_integer := 0;
552553 l_returnvalue t_object_list;
553554
554555begin
@@ -557,7 +558,7 @@ begin
557558
558559 Purpose: get objects
559560
560- Remarks: see http://docs.amazonwebservices. com/AmazonS3/latest/API/index.html?RESTObjectGET .html
561+ Remarks: see http://docs.aws.amazon. com/AmazonS3/latest/API/v2-RESTBucketGET .html
561562
562563 see http://code.google.com/p/plsql-utils/issues/detail?id=16
563564
@@ -573,6 +574,7 @@ begin
573574 ------ ---------- -------------------------------------
574575 MBR 15.01.2011 Created
575576 JKEMP 14.08.2012 Rewritten as private procedure, see remarks above
577+ KJS 06.10.2016 Modified to use newest S3 API which performs much better on large buckets. Changed for-loop to bulk operation.
576578
577579 */
578580
@@ -594,38 +596,36 @@ begin
594596 l_header_values.extend;
595597 l_header_values(3) := l_auth_str;
596598
597- if p_more_marker is not null then
598- l_clob := make_request (get_url(p_bucket_name) || '?marker= ' || p_more_marker || '&max-keys=' || p_max_keys || '&prefix=' || utl_url.escape(p_prefix), 'GET', l_header_names, l_header_values, null);
599+ if p_next_continuation_token is not null then
600+ 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);
599601 else
600- l_clob := make_request (get_url(p_bucket_name) || '?max-keys=' || p_max_keys || '&prefix=' || utl_url.escape(p_prefix), 'GET', l_header_names, l_header_values, null);
602+ 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);
601603 end if;
602-
603604 if (l_clob is not null) and (length(l_clob) > 0) then
604605
605606 l_xml := xmltype (l_clob);
606607
607608 check_for_errors (l_xml);
608609
609- for l_rec in (
610- select extractValue(value(t), '*/Key', g_aws_namespace_s3_full) as key,
611- extractValue(value(t), '*/Size', g_aws_namespace_s3_full) as size_bytes,
612- extractValue(value(t), '*/LastModified', g_aws_namespace_s3_full) as last_modified
613- from table(xmlsequence(l_xml.extract('//ListBucketResult/Contents', g_aws_namespace_s3_full))) t
614- ) loop
615- l_count := l_count + 1;
616- l_returnvalue(l_count).key := l_rec.key;
617- l_returnvalue(l_count).size_bytes := l_rec.size_bytes;
618- l_returnvalue(l_count).last_modified := to_date(l_rec.last_modified, g_date_format_xml);
619- end loop;
620-
621- -- check if this is the last set of data or not
622-
623- l_xml := l_xml.extract('//ListBucketResult/IsTruncated/text()', g_aws_namespace_s3_full);
610+ select extractValue(value(t), '*/Key', g_aws_namespace_s3_full),
611+ extractValue(value(t), '*/Size', g_aws_namespace_s3_full),
612+ to_date(extractValue(value(t), '*/LastModified', g_aws_namespace_s3_full), g_date_format_xml)
613+ bulk collect into l_returnvalue
614+ from table(xmlsequence(l_xml.extract('//ListBucketResult/Contents', g_aws_namespace_s3_full))) t;
615+
616+ -- check if this is the last set of data or not, and set the in/out p_next_continuation_token as expected
617+ l_xml_is_truncated := l_xml.extract('//ListBucketResult/IsTruncated/text()', g_aws_namespace_s3_full);
624618
625- if l_xml is not null and l_xml.getStringVal = 'true' then
626- p_more_marker := l_returnvalue(l_returnvalue.last).key;
619+ if l_xml_is_truncated is not null and l_xml_is_truncated.getStringVal = 'true' then
620+ l_xml_next_continuation := l_xml.extract('//ListBucketResult/NextContinuationToken/text()', g_aws_namespace_s3_full);
621+ if l_xml_next_continuation is not null then
622+ p_next_continuation_token := l_xml_next_continuation.getStringVal;
623+ else
624+ p_next_continuation_token := null;
625+ end if;
626+ else
627+ p_next_continuation_token := null;
627628 end if;
628-
629629 end if;
630630
631631 p_list := l_returnvalue;
@@ -638,7 +638,7 @@ function get_object_list (p_bucket_name in varchar2,
638638 p_max_keys in number := null) return t_object_list
639639as
640640 l_object_list t_object_list;
641- l_more_marker varchar2(4000);
641+ l_next_continuation_token varchar2(4000);
642642begin
643643
644644 /*
@@ -654,11 +654,11 @@ begin
654654 */
655655
656656 get_object_list (
657- p_bucket_name => p_bucket_name,
658- p_prefix => p_prefix,
659- p_max_keys => p_max_keys,
660- p_list => l_object_list,
661- p_more_marker => l_more_marker --ignored by this function
657+ p_bucket_name => p_bucket_name,
658+ p_prefix => p_prefix,
659+ p_max_keys => p_max_keys,
660+ p_list => l_object_list,
661+ p_next_continuation_token => l_next_continuation_token --ignored by this function
662662 );
663663
664664 return l_object_list;
@@ -671,7 +671,7 @@ function get_object_tab (p_bucket_name in varchar2,
671671 p_max_keys in number := null) return t_object_tab pipelined
672672as
673673 l_object_list t_object_list;
674- l_more_marker varchar2(4000);
674+ l_next_continuation_token varchar2(4000);
675675begin
676676
677677 /*
@@ -689,18 +689,18 @@ begin
689689 loop
690690
691691 get_object_list (
692- p_bucket_name => p_bucket_name,
693- p_prefix => p_prefix,
694- p_max_keys => p_max_keys,
695- p_list => l_object_list,
696- p_more_marker => l_more_marker
692+ p_bucket_name => p_bucket_name,
693+ p_prefix => p_prefix,
694+ p_max_keys => p_max_keys,
695+ p_list => l_object_list,
696+ p_next_continuation_token => l_next_continuation_token
697697 );
698698
699699 for i in 1 .. l_object_list.count loop
700700 pipe row (l_object_list(i));
701701 end loop;
702702
703- exit when l_more_marker is null;
703+ exit when l_next_continuation_token is null;
704704
705705 end loop;
706706
0 commit comments