RPM
DDL scriptPackage source
Legend: 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:
10: END rpm;
Package body source
Legend: string keyword reserved word operator
1: PACKAGE BODY rpm AS
2:
3: FUNCTION isdigit(ch CHAR)
4: RETURN BOOLEAN
5: deterministic
6: IS
7: BEGIN
8: if ascii(ch) between ascii('0') and ascii('9')
9: then
10: return TRUE;
11: end if;
12: return FALSE;
13: END isdigit;
14:
15:
16: FUNCTION isalpha(ch CHAR)
17: RETURN BOOLEAN
18: deterministic
19: IS
20: BEGIN
21: if ascii(ch) between ascii('a') and ascii('z') or
22: ascii(ch) between ascii('A') and ascii('Z')
23: then
24: return TRUE;
25: end if;
26: return FALSE;
27: END isalpha;
28:
29:
30: FUNCTION isalphanum(ch CHAR)
31: RETURN BOOLEAN
32: deterministic
33: IS
34: BEGIN
35: if ascii(ch) between ascii('a') and ascii('z') or
36: ascii(ch) between ascii('A') and ascii('Z') or
37: ascii(ch) between ascii('0') and ascii('9')
38: then
39: return TRUE;
40: end if;
41: return FALSE;
42: END isalphanum;
43:
44:
45: FUNCTION rpmstrcmp (string1 IN VARCHAR2, string2 IN VARCHAR2)
46: RETURN NUMBER
47: deterministic
48: IS
49: digits CHAR(10) := '0123456789';
50: lc_alpha CHAR(27) := 'abcdefghijklmnopqrstuvwxyz';
51: uc_alpha CHAR(27) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
52: alpha CHAR(54) := lc_alpha || uc_alpha;
53: str1 VARCHAR2(32767) := string1;
54: str2 VARCHAR2(32767) := string2;
55: one VARCHAR2(32767);
56: two VARCHAR2(32767);
57: isnum BOOLEAN;
58: BEGIN
59: if str1 is NULL or str2 is NULL
60: then
61: raise VALUE_ERROR;
62: end if;
63:
64: if str1 = str2
65: then
66: return 0;
67: end if;
68:
69: one := str1;
70: two := str2;
71:
72: <<segment_loop>>
73: while one is not null or two is not null
74: loop
75: declare
76: segm1 VARCHAR2(32767);
77: segm2 VARCHAR2(32767);
78: onechar CHAR(1);
79: twochar CHAR(1);
80: begin
81:
82:
83: onechar := substr(one, 1, 1);
84: twochar := substr(two, 1, 1);
85: while one is not null and not isalphanum(one) and onechar != '~' and onechar != '^'
86: loop
87: one := substr(one, 2);
88: end loop;
89: while two is not null and not isalphanum(two) and twochar != '~' and twochar != '^'
90: loop
91: two := substr(two, 2);
92: end loop;
93:
94:
95: onechar := substr(one, 1, 1);
96: twochar := substr(two, 1, 1);
97:
98:
99: if (onechar = '~' or twochar = '~')
100: then
101: if (onechar != '~' or onechar is null) then return 1; end if;
102: if (twochar != '~' or twochar is null) then return -1; end if;
103:
104: one := substr(one, 2);
105: two := substr(two, 2);
106: continue;
107: end if;
108:
109:
114: onechar := substr(one, 1, 1);
115: twochar := substr(two, 1, 1);
116: if (onechar = '^' or twochar = '^')
117: then
118: if (one is null) then return -1; end if;
119: if (two is null) then return 1; end if;
120: if (onechar != '^' or onechar is null) then return 1; end if;
121: if (twochar != '^' or twochar is null) then return -1; end if;
122: one := substr(one, 2);
123: two := substr(two, 2);
124: continue;
125: end if;
126:
127: if (not (one is not null and two is not null)) then exit segment_loop; end if;
128:
129: str1 := one;
130: str2 := two;
131:
132:
133:
134:
135:
136: if str1 is not null and isdigit(str1)
137: then
138: str1 := ltrim(str1, digits);
139: str2 := ltrim(str2, digits);
140: isnum := true;
141: else
142: str1 := ltrim(str1, alpha);
143: str2 := ltrim(str2, alpha);
144: isnum := false;
145: end if;
146:
147:
148:
149: if str1 is not null
150: then segm1 := substr(one, 1, length(one) - length(str1));
151: else segm1 := one;
152: end if;
153:
154: if str2 is not null
155: then segm2 := substr(two, 1, length(two) - length(str2));
156: else segm2 := two;
157: end if;
158:
159:
160:
161:
162:
163: if segm1 is null then return -1; end if;
164: if segm2 is null then
165: if isnum then
166: return 1;
167: else
168: return -1;
169: end if;
170: end if;
171:
172: if isnum
173: then
174:
175:
176:
177:
178:
179: segm1 := ltrim(segm1, '0');
180: segm2 := ltrim(segm2, '0');
181:
182:
183:
184: if segm1 is null and segm2 is not null
185: then
186: return -1;
187: end if;
188: if segm1 is not null and segm2 is null
189: then
190: return 1;
191: end if;
192: if length(segm1) > length(segm2) then return 1; end if;
193: if length(segm2) > length(segm1) then return -1; end if;
194: end if;
195:
196:
197:
198:
199:
200:
201: if segm1 < segm2 then return -1; end if;
202: if segm1 > segm2 then return 1; end if;
203:
204: one := str1;
205: two := str2;
206: end;
207: end loop segment_loop;
208:
209:
210:
211: if one is null and two is null then return 0; end if;
212:
213:
214: if one is null then return -1; end if;
215: return 1;
216: END rpmstrcmp;
217:
218:
219: FUNCTION vercmp(
220: e1 VARCHAR2, v1 VARCHAR2, r1 VARCHAR2,
221: e2 VARCHAR2, v2 VARCHAR2, r2 VARCHAR2)
222: RETURN NUMBER
223: IS
224: rc NUMBER;
225: BEGIN
226: DECLARE
227: ep1 NUMBER;
228: ep2 NUMBER;
229: BEGIN
230: if e1 is null then
231: ep1 := 0;
232: else
233: ep1 := TO_NUMBER(e1);
234: end if;
235: if e2 is null then
236: ep2 := 0;
237: else
238: ep2 := TO_NUMBER(e2);
239: end if;
240:
241: if ep1 < ep2 then return -1; end if;
242: if ep1 > ep2 then return 1; end if;
243: rc := rpmstrcmp(v1, v2);
244: if rc != 0 then return rc; end if;
245: return rpmstrcmp(r1, r2);
246: END;
247:
248: END vercmp;
249:
250: END rpm;