diff --git a/ora/interval_agg.pkb b/ora/interval_agg.pkb new file mode 100644 index 0000000..6833f05 --- /dev/null +++ b/ora/interval_agg.pkb @@ -0,0 +1,209 @@ +/* + +Purpose: Types used by the interval aggregate functions + +Remarks: + +Who Date Description +------ ---------- ------------------------------------- +AJM 14.09.2015 Created + +*/ + +create or replace type body t_sum_dsinterval +as + + static function ODCIAggregateInitialize (actx in out t_sum_dsinterval) return number + as + begin + + if actx is null then + actx := t_sum_dsinterval (interval '0 0:0:0.0' day to second); + else + actx.runningsum := interval '0 0:0:0.0' day to second; + end if; + return ODCIConst.Success; + + end ODCIAggregateInitialize; + + member function ODCIAggregateIterate (self in out t_sum_dsinterval, + val in dsinterval_unconstrained) return number as + begin + + self.runningsum := self.runningsum + val; + return ODCIConst.Success; + + end ODCIAggregateIterate; + + member function ODCIAggregateMerge (self in out t_sum_dsinterval, + ctx2 in t_sum_dsinterval) return number as + begin + + self.runningsum := self.runningsum + ctx2.runningsum; + return ODCIConst.Success; + + end ODCIAggregateMerge; + + member function ODCIAggregateTerminate (self in t_sum_dsinterval, + returnvalue out dsinterval_unconstrained, + flags in number) return number as + begin + + returnvalue := self.runningsum; + return ODCIConst.Success; + + end ODCIAggregateTerminate; +end; +/ + +create or replace type body t_avg_dsinterval +as + + static function ODCIAggregateInitialize (actx in out t_avg_dsinterval) return number + as + begin + + if actx is null then + actx := t_avg_dsinterval (interval '0 0:0:0.0' day to second, 0); + else + actx.runningsum := interval '0 0:0:0.0' day to second; + actx.runningcount := 0; + end if; + return ODCIConst.Success; + + end ODCIAggregateInitialize; + + member function ODCIAggregateIterate (self in out t_avg_dsinterval, + val in dsinterval_unconstrained) return number as + begin + + self.runningsum := self.runningsum + val; + self.runningcount := self.runningcount + 1; + return ODCIConst.Success; + + end ODCIAggregateIterate; + + member function ODCIAggregateMerge (self in out t_avg_dsinterval, + ctx2 in t_avg_dsinterval) return number as + begin + + self.runningsum := self.runningsum + ctx2.runningsum; + self.runningcount := self.runningcount + ctx2.runningcount; + return ODCIConst.Success; + + end ODCIAggregateMerge; + + member function ODCIAggregateTerminate (self in t_avg_dsinterval, + returnvalue out dsinterval_unconstrained, + flags in number) return number as + begin + + if self.runningcount <> 0 then + returnvalue := self.runningsum / self.runningcount; + else + returnvalue := self.runningsum; + end if; + return ODCIConst.Success; + + end ODCIAggregateTerminate; +end; +/ + +create or replace type body t_sum_yminterval +as + + static function ODCIAggregateInitialize (actx in out t_sum_yminterval) return number + as + begin + + if actx is null then + actx := t_sum_yminterval (interval '0-00' year to month); + else + actx.runningsum := interval '0-00' year to month; + end if; + return ODCIConst.Success; + + end ODCIAggregateInitialize; + + member function ODCIAggregateIterate (self in out t_sum_yminterval, + val in yminterval_unconstrained) return number as + begin + + self.runningsum := self.runningsum + val; + return ODCIConst.Success; + + end ODCIAggregateIterate; + + member function ODCIAggregateMerge (self in out t_sum_yminterval, + ctx2 in t_sum_yminterval) return number as + begin + + self.runningsum := self.runningsum + ctx2.runningsum; + return ODCIConst.Success; + + end ODCIAggregateMerge; + + member function ODCIAggregateTerminate (self in t_sum_yminterval, + returnvalue out yminterval_unconstrained, + flags in number) return number as + begin + + returnvalue := self.runningsum; + return ODCIConst.Success; + + end ODCIAggregateTerminate; +end; +/ + +create or replace type body t_avg_yminterval +as + + static function ODCIAggregateInitialize (actx in out t_avg_yminterval) return number + as + begin + + if actx is null then + actx := t_avg_yminterval (interval '0-00' year to month, 0); + else + actx.runningsum := interval '0-00' year to month; + actx.runningcount := 0; + end if; + return ODCIConst.Success; + + end ODCIAggregateInitialize; + + member function ODCIAggregateIterate (self in out t_avg_yminterval, + val in yminterval_unconstrained) return number as + begin + + self.runningsum := self.runningsum + val; + self.runningcount := self.runningcount + 1; + return ODCIConst.Success; + + end ODCIAggregateIterate; + + member function ODCIAggregateMerge (self in out t_avg_yminterval, + ctx2 in t_avg_yminterval) return number as + begin + + self.runningsum := self.runningsum + ctx2.runningsum; + self.runningcount := self.runningcount + ctx2.runningcount; + return ODCIConst.Success; + + end ODCIAggregateMerge; + + member function ODCIAggregateTerminate (self in t_avg_yminterval, + returnvalue out yminterval_unconstrained, + flags in number) return number as + begin + + if self.runningcount <> 0 then + returnvalue := self.runningsum / self.runningcount; + else + returnvalue := self.runningsum; + end if; + return ODCIConst.Success; + + end ODCIAggregateTerminate; +end; +/ diff --git a/ora/interval_agg.pks b/ora/interval_agg.pks new file mode 100644 index 0000000..b6e6b32 --- /dev/null +++ b/ora/interval_agg.pks @@ -0,0 +1,81 @@ +/* + +Purpose: Types used by the interval aggregate functions + +Remarks: + +Who Date Description +------ ---------- ------------------------------------- +AJM 14.09.2015 Created + +*/ + +create or replace type t_sum_dsinterval as object ( + runningsum interval day(9) to second(9), + + static function ODCIAggregateInitialize (actx in out t_sum_dsinterval) return number, + + member function ODCIAggregateIterate (self in out t_sum_dsinterval, + val in dsinterval_unconstrained) return number, + + member function ODCIAggregateMerge (self in out t_sum_dsinterval, + ctx2 in t_sum_dsinterval) return number, + + member function ODCIAggregateTerminate (self in t_sum_dsinterval, + returnvalue out dsinterval_unconstrained, + flags in number) return number +); +/ + +create or replace type t_avg_dsinterval as object ( + runningsum interval day(9) to second(9), + runningcount number, + + static function ODCIAggregateInitialize (actx in out t_avg_dsinterval) return number, + + member function ODCIAggregateIterate (self in out t_avg_dsinterval, + val in dsinterval_unconstrained) return number, + + member function ODCIAggregateMerge (self in out t_avg_dsinterval, + ctx2 in t_avg_dsinterval) return number, + + member function ODCIAggregateTerminate (self in t_avg_dsinterval, + returnvalue out dsinterval_unconstrained, + flags in number) return number +); +/ + +create or replace type t_sum_yminterval as object ( + runningsum interval year(9) to month, + + static function ODCIAggregateInitialize (actx in out t_sum_yminterval) return number, + + member function ODCIAggregateIterate (self in out t_sum_yminterval, + val in yminterval_unconstrained) return number, + + member function ODCIAggregateMerge (self in out t_sum_yminterval, + ctx2 in t_sum_yminterval) return number, + + member function ODCIAggregateTerminate (self in t_sum_yminterval, + returnvalue out yminterval_unconstrained, + flags in number) return number +); +/ + +create or replace type t_avg_yminterval as object ( + runningsum interval year(9) to month, + runningcount number, + + static function ODCIAggregateInitialize (actx in out t_avg_yminterval) return number, + + member function ODCIAggregateIterate (self in out t_avg_yminterval, + val in yminterval_unconstrained) return number, + + member function ODCIAggregateMerge (self in out t_avg_yminterval, + ctx2 in t_avg_yminterval) return number, + + member function ODCIAggregateTerminate (self in t_avg_yminterval, + returnvalue out yminterval_unconstrained, + flags in number) return number +); +/ diff --git a/ora/interval_agg.sql b/ora/interval_agg.sql new file mode 100644 index 0000000..2656bce --- /dev/null +++ b/ora/interval_agg.sql @@ -0,0 +1,35 @@ +/* + +Purpose: Interval aggregate functions + +Remarks: + +Who Date Description +------ ---------- ------------------------------------- +AJM 14.09.2015 Created + +*/ + +-- sum aggregate function for interval day to second +create or replace function sum_dsinterval (x dsinterval_unconstrained) return dsinterval_unconstrained +parallel_enable +aggregate using t_sum_dsinterval; +/ + +-- average aggregate function for interval day to second +create or replace function avg_dsinterval (x dsinterval_unconstrained) return dsinterval_unconstrained +parallel_enable +aggregate using t_avg_dsinterval; +/ + +-- sum aggregate function for interval year to month +create or replace function sum_yminterval (x yminterval_unconstrained) return yminterval_unconstrained +parallel_enable +aggregate using t_sum_yminterval; +/ + +-- average aggregate function for interval year to month +create or replace function avg_yminterval (x yminterval_unconstrained) return yminterval_unconstrained +parallel_enable +aggregate using t_avg_yminterval; +/ diff --git a/ora/interval_util_pkg.pkb b/ora/interval_util_pkg.pkb new file mode 100644 index 0000000..b20ef7e --- /dev/null +++ b/ora/interval_util_pkg.pkb @@ -0,0 +1,112 @@ +CREATE OR REPLACE package body interval_util_pkg +as + + /* + + Purpose: Package handles functionality related to intervals + + Remarks: + + Who Date Description + ------ ---------- ------------------------------------- + AJM 14.09.2015 Created + + */ + + +function dsintervaltonum (p_interval in interval day to second, p_unit in varchar2) return number deterministic is + l_illegal_argument exception; + pragma exception_init (l_illegal_argument, -1760); + l_returnvalue number; +begin + + /* + + Purpose: convert an interval day to second to number + + Remarks: + + Who Date Description + ------ ---------- ------------------------------------- + AJM 14.09.2015 Created + + */ + + case upper (p_unit) + when 'SECOND' + then + l_returnvalue := + extract (day from p_interval) * 86400 + + extract (hour from p_interval) * 3600 + + extract (minute from p_interval) * 60 + + extract (second from p_interval); + when 'MINUTE' + then + l_returnvalue := + extract (day from p_interval) * 1440 + + extract (hour from p_interval) * 60 + + extract (minute from p_interval) + + extract (second from p_interval) / 60; + when 'HOUR' + then + l_returnvalue := + extract (day from p_interval) * 24 + + extract (hour from p_interval) + + extract (minute from p_interval) / 60 + + extract (second from p_interval) / 3600; + when 'DAY' + then + l_returnvalue := + extract (day from p_interval) + + extract (hour from p_interval) / 24 + + extract (minute from p_interval) / 1440 + + extract (second from p_interval) / 86400; + else + raise l_illegal_argument; + end case; + + return l_returnvalue; + +end dsintervaltonum; + + +function ymintervaltonum (p_interval in interval year to month, p_unit in varchar2) return number deterministic is + l_illegal_argument exception; + pragma exception_init (l_illegal_argument, -1760); + l_returnvalue number; +begin + + /* + + Purpose: convert an interval year to month to number + + Remarks: + + Who Date Description + ------ ---------- ------------------------------------- + AJM 14.09.2015 Created + + */ + + case upper (p_unit) + when 'MONTH' + then + l_returnvalue := + extract (month from p_interval) + + extract (year from p_interval) * 12; + when 'YEAR' + then + l_returnvalue := + extract (month from p_interval) / 12 + + extract (year from p_interval); + else + raise l_illegal_argument; + end case; + + return l_returnvalue; + +end ymintervaltonum; + + +end interval_util_pkg; +/ diff --git a/ora/interval_util_pkg.pks b/ora/interval_util_pkg.pks new file mode 100644 index 0000000..30d218a --- /dev/null +++ b/ora/interval_util_pkg.pks @@ -0,0 +1,23 @@ +CREATE OR REPLACE package interval_util_pkg +as + + /* + + Purpose: Package handles functionality related to intervals + + Remarks: + + Who Date Description + ------ ---------- ------------------------------------- + AJM 14.09.2015 Created + + */ + + -- convert an interval day to second to number + function dsintervaltonum (p_interval in interval day to second, p_unit in varchar2) return number deterministic; + + -- convert an interval year to month to number + function ymintervaltonum (p_interval in interval year to month, p_unit in varchar2) return number deterministic; + +end interval_util_pkg; +/ diff --git a/ora/string_util_pkg.pkb b/ora/string_util_pkg.pkb index d2f6229..b3e6ba9 100755 --- a/ora/string_util_pkg.pkb +++ b/ora/string_util_pkg.pkb @@ -236,6 +236,56 @@ begin end get_token_count; +function pad_str_num (p_text in varchar2, + p_pad_size in number := 10, + p_decimal_separator in varchar2 := '.') return varchar2 deterministic +as + l_counter number; + l_returnvalue varchar2(4000) := null; + l_number_length number := 0; + l_current_char varchar2(1); +begin + + /* + + Purpose: pad numbers within a string to the specified length + + Remarks: + + Who Date Description + ------ ---------- ------------------------------------- + AJM 13.07.2016 Created + + */ + + + if p_text is not null then + l_returnvalue := p_text; + + for l_counter in reverse 1..length (p_text) loop + l_current_char := substr (p_text, l_counter, 1); + + if regexp_instr (l_current_char, '[0-9]') <> 0 then + l_number_length := l_number_length + 1; + else + if l_number_length > 0 and l_current_char <> p_decimal_separator then + l_returnvalue := substr (l_returnvalue, 1, l_counter) || lpad ('0', p_pad_size - l_number_length, '0') || substr (l_returnvalue, l_counter + 1, length (l_returnvalue)); + end if; + + l_number_length := 0; + end if; + end loop; + + if l_number_length > 0 then + l_returnvalue := lpad ('0', p_pad_size - l_number_length, '0') || l_returnvalue; + end if; + + end if; + + return l_returnvalue; +end pad_str_num; + + function str_to_num (p_str in varchar2, p_decimal_separator in varchar2 := null, p_thousand_separator in varchar2 := null, diff --git a/ora/string_util_pkg.pks b/ora/string_util_pkg.pks index ab03d2d..4dc57b1 100755 --- a/ora/string_util_pkg.pks +++ b/ora/string_util_pkg.pks @@ -62,6 +62,11 @@ as function get_token_count(p_text in varchar2, p_separator in varchar2 := g_default_separator) return number; + -- pad numbers within a string to the specified length + function pad_str_num (p_text in varchar2, + p_pad_size in number := 10, + p_decimal_separator in varchar2 := '.') return varchar2 deterministic; + -- convert string to number function str_to_num (p_str in varchar2, p_decimal_separator in varchar2 := null,