Main Tables Views Materialized Views Indexes Constraints Triggers Procedures Functions Packages Sequences Java Sources Sanity Check Index DDL scrips
Package source Package body source

RPM

DDL script

Package source

Legend: comment string keyword reserved word operator
     1: PACKAGE rpm AS
     2:     FUNCTION vercmp(
     3:         e1 VARCHAR2, v1 VARCHAR2, r1 VARCHAR2,
     4:         e2 VARCHAR2, v2 VARCHAR2, r2 VARCHAR2)
     5:     RETURN NUMBER
     6:         DETERMINISTIC
     7:         PARALLEL_ENABLE;
     8:     PRAGMA RESTRICT_REFERENCES(vercmp, WNDS, RNDS);
     9:     FUNCTION vercmpCounter
    10:     return NUMBER
    11:         DETERMINISTIC
    12:         PARALLEL_ENABLE;
    13:     PRAGMA RESTRICT_REFERENCES(vercmpCounter, WNDS, RNDS);
    14:     FUNCTION vercmpResetCounter
    15:     return NUMBER
    16:         DETERMINISTIC
    17:         PARALLEL_ENABLE;
    18:     PRAGMA RESTRICT_REFERENCES(vercmpResetCounter, WNDS, RNDS);
    19: END rpm;

Package body source

Legend: comment string keyword reserved word operator
     1: PACKAGE BODY rpm AS
     2:     vercmp_counter NUMBER := 0;
     3:     FUNCTION isdigit(ch CHAR)
     4:     RETURN BOOLEAN
     5:     IS
     6:     BEGIN
     7:         if ascii(ch) between ascii('0') and ascii('9')
     8:         then
     9:             return TRUE;
    10:         end if;
    11:         return FALSE;
    12:     END isdigit;
    13:     FUNCTION isalpha(ch CHAR)
    14:     RETURN BOOLEAN
    15:     IS
    16:     BEGIN
    17:         if ascii(ch) between ascii('a') and ascii('z') or
    18:             ascii(ch) between ascii('A') and ascii('Z')
    19:         then
    20:             return TRUE;
    21:         end if;
    22:         return FALSE;
    23:     END isalpha;
    24:     FUNCTION isalphanum(ch CHAR)
    25:     RETURN BOOLEAN
    26:     IS
    27:     BEGIN
    28:         if ascii(ch) between ascii('a') and ascii('z') or
    29:             ascii(ch) between ascii('A') and ascii('Z') or
    30:             ascii(ch) between ascii('0') and ascii('9')
    31:         then
    32:             return TRUE;
    33:         end if;
    34:         return FALSE;
    35:     END isalphanum;
    36:     FUNCTION rpmstrcmp (string1 IN VARCHAR2, string2 IN VARCHAR2)
    37:     RETURN NUMBER
    38:     IS
    39:         digits CHAR(10) := '0123456789';
    40:         lc_alpha CHAR(27) := 'abcdefghijklmnopqrstuvwxyz';
    41:         uc_alpha CHAR(27) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    42:         alpha CHAR(54) := lc_alpha || uc_alpha;
    43:         str1 VARCHAR2(32767) := string1;
    44:         str2 VARCHAR2(32767) := string2;
    45:         one VARCHAR2(32767);
    46:         two VARCHAR2(32767);
    47:         isnum BOOLEAN;
    48:     BEGIN
    49:         if str1 is NULL or str2 is NULL
    50:         then
    51:             raise VALUE_ERROR;
    52:         end if;
    53:         if str1 = str2
    54:         then
    55:             return 0;
    56:         end if;
    57:         one := str1;
    58:         two := str2;
    59:         <<segment_loop>>
    60:         while one is not null and two is not null
    61:         loop
    62:             declare
    63:                 segm1 VARCHAR2(32767);
    64:                 segm2 VARCHAR2(32767);
    65:             begin
    66:                 while one is not null and not isalphanum(one)
    67:                 loop
    68:                     one := substr(one, 2);
    69:                 end loop;
    70:                 while two is not null and not isalphanum(two)
    71:                 loop
    72:                     two := substr(two, 2);
    73:                 end loop;
    74:                 str1 := one;
    75:                 str2 := two;
    76:                 /* grab first completely alpha or completely numeric segment */
    77:                 /* leave one and two pointing to the start of the alpha or numeric */
    78:                 /* segment and walk str1 and str2 to end of segment */
    79:                 if str1 is not null and isdigit(str1)
    80:                 then
    81:                     str1 := ltrim(str1, digits);
    82:                     str2 := ltrim(str2, digits);
    83:                     isnum := true;
    84:                 else
    85:                     str1 := ltrim(str1, alpha);
    86:                     str2 := ltrim(str2, alpha);
    87:                     isnum := false;
    88:                 end if;
    89:                 if str1 is not null
    90:                 then segm1 := substr(one, 1, length(one) - length(str1));
    91:                 else segm1 := one;
    92:                 end if;
    93:                 if str2 is not null
    94:                 then segm2 := substr(two, 1, length(two) - length(str2));
    95:                 else segm2 := two;
    96:                 end if;
    97:                 /* take care of the case where the two version segments are */
    98:                 /* different types: one numeric and one alpha */
    99:                 if segm1 is null then return -1; end if; /* arbitrary */
   100:                 if segm2 is null then
   101: 					if isnum then
   102: 						return 1;
   103: 					else
   104: 						return -1;
   105: 					end if;
   106: 				end if;
   107:                 if isnum
   108:                 then
   109:                     /* this used to be done by converting the digit segments */
   110:                     /* to ints using atoi() - it's changed because long */
   111:                     /* digit segments can overflow an int - this should fix that. */
   112:                     /* throw away any leading zeros - it's a number, right? */
   113:                     segm1 := ltrim(segm1, '0');
   114:                     segm2 := ltrim(segm2, '0');
   115:                     /* whichever number has more digits wins */
   116:                     if segm1 is null and segm2 is not null
   117:                     then
   118:                         return -1;
   119:                     end if;
   120:                     if segm1 is not null and segm2 is null
   121:                     then
   122:                         return 1;
   123:                     end if;
   124:                     if length(segm1) > length(segm2) then return 1; end if;
   125:                     if length(segm2) > length(segm1) then return -1; end if;
   126:                 end if;
   127:                 /* strcmp will return which one is greater - even if the two */
   128:                 /* segments are alpha or if they are numeric.  don't return  */
   129:                 /* if they are equal because there might be more segments to */
   130:                 /* compare */
   131:                 if segm1 < segm2 then return -1; end if;
   132:                 if segm1 > segm2 then return 1; end if;
   133:                 one := str1;
   134:                 two := str2;
   135:             end;
   136:         end loop segment_loop;
   137:         /* this catches the case where all numeric and alpha segments have */
   138:         /* compared identically but the segment sepparating characters were */
   139:         /* different */
   140:         if one is null and two is null then return 0; end if;
   141:         /* whichever version still has characters left over wins */
   142:         if one is null then return -1; end if;
   143:         return 1;
   144:     END rpmstrcmp;
   145:     FUNCTION vercmp(
   146:         e1 VARCHAR2, v1 VARCHAR2, r1 VARCHAR2,
   147:         e2 VARCHAR2, v2 VARCHAR2, r2 VARCHAR2)
   148:     RETURN NUMBER
   149:     IS
   150:         rc NUMBER;
   151:     BEGIN
   152:         DECLARE
   153:           ep1 NUMBER;
   154:           ep2 NUMBER;
   155:           BEGIN
   156:             vercmp_counter := vercmp_counter + 1;
   157:             if e1 is null then
   158:               ep1 := 0;
   159:             else
   160:               ep1 := TO_NUMBER(e1);
   161:             end if;
   162:             if e2 is null then
   163:               ep2 := 0;
   164:             else
   165:               ep2 := TO_NUMBER(e2);
   166:             end if;
   167:             if ep1 < ep2 then return -1; end if;
   168:             if ep1 > ep2 then return 1; end if;
   169:             rc := rpmstrcmp(v1, v2);
   170:             if rc != 0 then return rc; end if;
   171:            return rpmstrcmp(r1, r2);
   172:          END;
   173:     END vercmp;
   174:     FUNCTION vercmpCounter
   175:     RETURN NUMBER
   176:     IS
   177:     BEGIN
   178:         return vercmp_counter;
   179:     END vercmpCounter;
   180:     FUNCTION vercmpResetCounter
   181:     RETURN NUMBER
   182:     IS
   183:         result NUMBER;
   184:     BEGIN
   185:         result := vercmp_counter;
   186:         vercmp_counter := 0;
   187:         return result;
   188:     END vercmpResetCounter;
   189: END rpm;