DBA Data[Home] [Help]

PACKAGE BODY: APPS.AD_VERSION_UTIL

Source


1 package body ad_version_util as
2 -- $Header: aduverb.pls 120.2 2006/08/25 18:33:12 vlim noship $
3 
4   --
5   -- constant values used when comparing two patchset names
6   --
7 
8   PATCH_LEVEL_SAME    CONSTANT integer := 0;
9   PATCH_LEVEL1_HIGHER CONSTANT integer := -1;
10   PATCH_LEVEL2_HIGHER CONSTANT integer := 1;
11 
12   VERCOMP_SEPARATOR   CONSTANT varchar2(1) := '.';
13 
14   --
15   -- Function to get base release name. This name will be used when
16   -- contructing patch level name for a product.
17   --
18 
19 function get_base_release
20  return varchar2
21 is
22   begin
23      return('R12');
24   end;
25 
26   --
27   -- Return product abbreviation given a product shortname
28   --
29   -- Raises an exception if the product shortname is not found in
30   -- FND_APPLICATION table
31   --
32 
33 function get_appl_abbr
34           (p_appl_shortname in varchar2)
35  return varchar2
36 is
37     l_dummy varchar2(1);
38   begin
39 
40       --
41       -- first check if this is a valid application
42       --
43 
44       begin
45          select null
46          into   l_dummy
47          from   fnd_application
48          where  application_short_name = upper(p_appl_shortname);
49       exception
50          when NO_DATA_FOUND then
51            raise_application_error(-20001,
52              'Invalid application shortname : '||p_appl_shortname);
53       end;
54 
55       if    (p_appl_shortname = 'SQLAP') then
56          return('AP');
57       elsif (p_appl_shortname = 'SQLGL') then
58          return('GL');
59       elsif (p_appl_shortname = 'OFA') then
60          return('FA');
61       else
62          return(p_appl_shortname);
63       end if;
64   end;
65 
66   function get_appl_id
67             (p_appl_sn in varchar2) return number
68   is
69    l_appl_id number;
70   begin
71     select application_id
72     into   l_appl_id
73     from   fnd_application
74     where  application_short_name = upper(p_appl_sn);
75 
76     return(l_appl_id);
77   end;
78 
79   --
80   -- function to check the validity of a patch level
81   --
82   -- The patch level is of the form
83   --    [<BASE RELEASE>.<PRODUCT>.<PATCHSET NAME>]{.<REVISION>}
84   --
85 
86   function validate_patch_level
87             (p_patch_level       in         varchar2,
88              p_product_shortname in         varchar2,
89              p_error_msg         out nocopy varchar2)
90    return boolean
91   is
92     l_patch_base              varchar2(30);
93     l_patch_appl_shortname    varchar2(30);
94     l_patch_patchset_name     varchar2(30);
95     l_patch_patchset_revision varchar2(30);
96     l_patchset_revision       number;
97 
98     l_base_release         varchar2(30);
99     l_appl_shortname       varchar2(30);
100   begin
101     get_patch_level_details(p_patch_level,
102                             l_patch_base,
103                             l_patch_appl_shortname,
104                             l_patch_patchset_name,
105                             l_patch_patchset_revision);
106 
107     l_base_release := get_base_release;
108 
109     if (nvl(l_patch_base, 'UNKNOWN') <> l_base_release) then
110        p_error_msg := 'Incorrect base release "'||l_patch_base||'" found '||
111                       'when expecting "'||l_base_release||'"';
112        return(FALSE);
113     end if;
114 
115     l_appl_shortname := get_appl_abbr(p_product_shortname);
116 
117     if (l_appl_shortname <> nvl(l_patch_appl_shortname, 'UNKNOWN')) then
118        p_error_msg := 'Incorrect product abbreviation "'||
119                       l_patch_appl_shortname||'" found '||
120                       'when expecting "'||l_appl_shortname||'"';
121        return(FALSE);
122     end if;
123 
124     if (length(l_patch_patchset_name) <> 1
125         or
126         l_patch_patchset_name not between 'A' and 'Z') then
127        p_error_msg := 'Incorrect patchset name "'||l_patch_patchset_name||
128                       '". A patchset name must be a character between A to Z.';
129        return(FALSE);
130     end if;
131 
132     if (l_patch_patchset_revision is not null)
133     then
134        if (replace(translate(l_patch_patchset_revision,
135                              '0123456789', ' '),
136                    ' ', '') is not null)
137        then
138           p_error_msg := 'Incorrect patchset revision format "'||
139                             l_patch_patchset_revision||
140                       '". A patchset revision must be a number from 1 to 99.';
141           return(FALSE);
142        end if;
143 
144        if (not(to_number(l_patch_patchset_revision) between 1 and 99)) then
145           p_error_msg := 'Incorrect patchset revision "'||
146                             l_patch_patchset_revision||
147                       '". A patchset revision must be a number from 1 to 99.';
148           return(FALSE);
149        end if;
150     end if;
151 
152     return(TRUE);
153   end;
154 
155 
156   --
157   -- Compares two patch levels
158   --    returns 0 : patch levels are same
159   --            1 : patch level 2 is higher than patch level 1
160   --                or
161   --                patch level 2 is not null and patch level 1 is null
162   --           -1 : patch level 1 is higher than patch level 2
163   --                or
164   --                patch level 1 is not null and patch level 2 is null
165   --
166 
167   function compare_patch_levels
168             (p_level1 in varchar2,
169              p_level2 in varchar2) return number
170   is
171 
172     l_base1           varchar2(30);
173     l_appl_shortname1 varchar2(30);
174     l_patchset_name1  varchar2(30);
175     l_patchset_rev1   varchar2(30);
176     l_base2           varchar2(30);
177     l_appl_shortname2 varchar2(30);
178     l_patchset_name2  varchar2(30);
179     l_patchset_rev2   varchar2(30);
180 
181   begin
182 
183     if    (upper(p_level1) = upper(p_level2)) then
184        return(PATCH_LEVEL_SAME);
185     end if;
186 
187     if (p_level1 is not null and p_level2 is null) then
188        return(PATCH_LEVEL1_HIGHER);
189     end if;
190 
191     if (p_level1 is null and p_level2 is not null) then
192        return(PATCH_LEVEL2_HIGHER);
193     end if;
194 
195     get_patch_level_details(p_level1,
196                             l_base1, l_appl_shortname1, l_patchset_name1,
197                             l_patchset_rev1);
198     get_patch_level_details(p_level2,
199                             l_base2, l_appl_shortname2, l_patchset_name2,
200                             l_patchset_rev2);
201 
202     if (l_base1 <> l_base2) then
203        raise_application_error(-20001,
204            'The base release should be same when comparing patchset versions '||
205            l_base1||' vs '||l_base2);
206     end if;
207 
208     if (l_appl_shortname1 <> l_appl_shortname2) then
209        raise_application_error(-20001,
210            'The product should be same when comparing patchset versions '||
211            l_appl_shortname1||' vs '||l_appl_shortname2);
212     end if;
213 
214     if (l_patchset_name1 <> l_patchset_name2) then
215        if (l_patchset_name1 > l_patchset_name2) then
216                 return(PATCH_LEVEL1_HIGHER);
217        else
218                 return(PATCH_LEVEL2_HIGHER);
219        end if;
220     end if;
221 
222     if (nvl(l_patchset_rev1, -1) = nvl(l_patchset_rev2, -1)) then
223        return(PATCH_LEVEL_SAME);
224     end if;
225 
226     if (nvl(to_number(l_patchset_rev1), -1) >
227           nvl(to_number(l_patchset_rev2), -1)) then
228        return(PATCH_LEVEL1_HIGHER);
229     else
230        return(PATCH_LEVEL2_HIGHER);
231     end if;
232 
233   end;
234 
235   --
236   -- get current patch level from the database
237   --
238   -- this procedure returns NULL for patch levels
239   -- that do not belong to the current base release;
240   -- this procedure is only called within this package.
241   -- (created to fix bugs 5376688 and 5484176)
242   --
243 
244 procedure get_product_patch_level_priv
245            (p_appl_id      in         number,
246             p_patch_level  out nocopy varchar2)
247 is
248     l_patch_level varchar2(30);
249   begin
250     select patch_level
251     into   l_patch_level
252     from   fnd_product_installations
253     where  application_id = p_appl_id
254     and    install_group_num in (0, 1)
255     and    rownum = 1;
256 
257     p_patch_level := l_patch_level;
258 
259     --
260     -- return NULL if earlier releases
261     --
262     if (l_patch_level like '10.7%'
263         or
264         l_patch_level like '11.0%'
265         or
266         l_patch_level like '11i%')
267     then
268        p_patch_level := null;
269     end if;
270   end;
271 
272   --
273   -- get current patch level from the database
274   --
275   -- this procedure returns NULL for patch levels
276   -- that do not belong to the current base release;
277   -- this procedure is only called within this package.
278   -- (created to fix bugs 5376688 and 5484176)
279   --
280 
281 procedure get_product_patch_level_priv
282            (p_appl_shortname in         varchar2,
283             p_patch_level    out nocopy varchar2)
284 is
285     l_appl_id     number;
286     l_patch_level varchar2(30);
287   begin
288 
289     l_appl_id := get_appl_id(p_appl_shortname);
290 
291     get_product_patch_level_priv(p_appl_id=>l_appl_id,
292                                  p_patch_level=>p_patch_level);
293   end;
294 
295 
296   --
297   -- get current patch level from the database
298   --
299 
300 procedure get_product_patch_level
301            (p_appl_id      in         number,
302             p_patch_level  out nocopy varchar2)
303 is
304     l_patch_level varchar2(30);
305   begin
306     select patch_level
307     into   l_patch_level
308     from   fnd_product_installations
309     where  application_id = p_appl_id
310     and    install_group_num in (0, 1)
311     and    rownum = 1;
312 
313     p_patch_level := l_patch_level;
314 
315     --
316     -- return NULL if earlier releases
317     --
318     if (l_patch_level like '10.7%'
319         or
320         l_patch_level like '11.0%')
321     then
322        p_patch_level := null;
323     end if;
324   end;
325 
326   --
327   -- get current patch level from the database
328   --
329 
330 procedure get_product_patch_level
331            (p_appl_shortname in         varchar2,
332             p_patch_level    out nocopy varchar2)
333 is
334     l_appl_id     number;
335     l_patch_level varchar2(30);
336   begin
337 
338     l_appl_id := get_appl_id(p_appl_shortname);
339 
340     get_product_patch_level(p_appl_id=>l_appl_id,
341                             p_patch_level=>p_patch_level);
342   end;
343 
344   --
345   -- construct patch level for a product
346   --
347 
348 procedure build_patch_level
349            (p_appl_shortname    in         varchar2,
350             p_patchset_name     in         varchar2,
351             p_patchset_revision in         varchar2,
352             p_patch_level       out nocopy varchar2)
353 is
354   begin
355      p_patch_level := get_base_release||VERCOMP_SEPARATOR||
356                     get_appl_abbr(upper(p_appl_shortname))||VERCOMP_SEPARATOR||
357                     upper(p_patchset_name);
358 
359      if (p_patchset_revision is not null) then
360        p_patch_level := p_patch_level||VERCOMP_SEPARATOR||p_patchset_revision;
361      end if;
362   end;
363 
364   --
365   -- update product row with patch level information, if the new
366   -- patch level is higher
367   --
368 
369 -- Bug 3611969 : FIXED FILE.SQL.35 GSCC WARNINGS
370 -- sraghuve (07/05/2004)
371 
372 procedure set_product_patch_level
373            (p_appl_shortname in varchar2,
374             p_patchset_name  in varchar2)
375 is
376 begin
377   set_product_patch_level
378              (p_appl_shortname => p_appl_shortname,
379               p_patchset_name  => p_patchset_name ,
380               p_force_flag     => 'N');
381 end;
382 
383 procedure set_product_patch_level
384            (p_appl_shortname in varchar2,
385             p_patchset_name  in varchar2,
386             p_force_flag     in varchar2)
387 is
388     l_new_patch_level   varchar2(30);
389     l_old_patch_level   varchar2(30);
390     l_error_msg         varchar2(200);
391     l_patchset_revision varchar2(30);
392     l_patchset_name     varchar2(30);
393     l_pos_first         number;
394   begin
395 
396      --
397      -- check to see if revision is specified along with the patchset name.
398      -- if so, split it into individual components
399      --
400      l_pos_first := instr(p_patchset_name, VERCOMP_SEPARATOR);
401      if (l_pos_first > 0) then
402         l_patchset_name     := substr(p_patchset_name,
403                                       1, (l_pos_first - 1));
404         l_patchset_revision := substr(p_patchset_name,
405                                       (l_pos_first+1));
406      else
407         l_patchset_name     := p_patchset_name;
408         l_patchset_revision := null;
409      end if;
410 
411      build_patch_level(p_appl_shortname, l_patchset_name,
412                        l_patchset_revision, l_new_patch_level);
413 
414      if (validate_patch_level(l_new_patch_level,
415                               p_appl_shortname, l_error_msg) = FALSE)
416      then
417         raise_application_error(-20001,
418                                 'Unable to build and validate patch version '||
419                                 'information. ('||l_error_msg||')');
420      end if;
421 
422      get_product_patch_level_priv(p_appl_shortname, l_old_patch_level);
423 
424      if (l_old_patch_level is not null
425          and
426          validate_patch_level(l_old_patch_level,
427                               p_appl_shortname, l_error_msg) = FALSE)
428      then
429         raise_application_error(-20001,
430                                 'Incorrect patch version "'||l_old_patch_level||
431                                 '" in database. ('||l_error_msg||')');
432      end if;
433 
434      if (upper(p_force_flag) = 'Y'
435          or
436          (compare_patch_levels(l_old_patch_level,
437                                l_new_patch_level) = PATCH_LEVEL2_HIGHER))
438      then
439         update fnd_product_installations
440         set    patch_level = l_new_patch_level
441         where  application_id in (
442                     select application_id
443                     from   fnd_application
444                     where  application_short_name = upper(p_appl_shortname));
445      end if;
446   end;
447 
448   --
449   -- get individual components of a patch level namely
450   --        o  base release
451   --        o  application abbreviation
452   --        o  patchset name
453   --
454 
455 procedure get_patch_level_details
456            (p_patch_level       in         varchar2,
460             p_patchset_revision out nocopy varchar2)
457             p_base_release      out nocopy varchar2,
458             p_appl_shortname    out nocopy varchar2,
459             p_patchset_name     out nocopy varchar2,
461 is
462     l_pos_first  number;
463     l_pos_second number;
464     l_pos_third  number;
465   begin
466 
467      p_base_release   := null;
468      p_appl_shortname := null;
469      p_patchset_name  := null;
470      p_patchset_revision := null;
471 
472      if (p_patch_level is null) then
473        return;
474      end if;
475 
476      l_pos_first  := instr(p_patch_level, VERCOMP_SEPARATOR, 1, 1);
477      l_pos_second := instr(p_patch_level, VERCOMP_SEPARATOR, 1, 2);
478      l_pos_third  := instr(p_patch_level, VERCOMP_SEPARATOR, 1, 3);
479 
480      if (l_pos_first = 0) then
481         --
482         -- first seperator not found, use entire string as the
483         -- first component
484         --
485         p_base_release := p_patch_level;
486         return;
487      else
488         p_base_release := substr(p_patch_level, 1, l_pos_first - 1);
489      end if;
490 
491      if (l_pos_second = 0) then
492         --
493         -- second seperator not found, use remaining string as the
494         -- second component
495         --
496         p_appl_shortname := substr(p_patch_level, l_pos_first +1);
497         return;
498      else
499         p_appl_shortname := substr(p_patch_level,
500                                    l_pos_first +1,
501                                    ((l_pos_second) - (l_pos_first+1)));
502      end if;
503 
504      if (l_pos_third = 0) then
505         --
506         -- third seperator not found, use remaining string as the
507         -- third component (patchset name)
508         --
509         p_patchset_name  := substr(p_patch_level,
510                                    l_pos_second+1);
511      else
512         p_patchset_name  := substr(p_patch_level,
513                                    l_pos_second +1,
514                                    ((l_pos_third) - (l_pos_second+1)));
515         p_patchset_revision := substr(p_patch_level,
516                                       l_pos_third+1);
517 
518      end if;
519 
520   end;
521 
522 procedure get_patch_level_details
523            (p_patch_level    in         varchar2,
524             p_base_release   out nocopy varchar2,
525             p_appl_shortname out nocopy varchar2,
526             p_patchset_name  out nocopy varchar2)
527 is
528     l_patchset_revision varchar2(30);
529   begin
530     get_patch_level_details(p_patch_level,
531                             p_base_release,
532                             p_appl_shortname,
533                             p_patchset_name,
534                             l_patchset_revision);
535   end;
536 end;