1 package body STANDARD is -- careful on this line; SED edit occurs!
2
3 subtype Cursor_Handle is binary_integer range 0..255;
4
5 INVALID_USERENV_PARAMETER exception;
6 pragma EXCEPTION_INIT(INVALID_USERENV_PARAMETER, -2003);
7
8 -- This exception is used by several sped-up STANDARD functions' ICDs to
9 -- indicate that the ICD is unable to compute the result, and that SQL should
10 -- be used to do the computation.
11 ICD_UNABLE_TO_COMPUTE exception;
12 pragma EXCEPTION_INIT(ICD_UNABLE_TO_COMPUTE, -6594);
13
14 -- icds
15
16 function pesxlt(ch VARCHAR2 CHARACTER SET ANY_CS,
17 cpy VARCHAR2 CHARACTER SET ch%CHARSET,
18 frm VARCHAR2 CHARACTER SET ch%CHARSET,
19 too VARCHAR2 CHARACTER SET ch%CHARSET)
20 return VARCHAR2 CHARACTER SET ch%CHARSET;
21 pragma interface (c,pesxlt);
22
23 -- trig fns
24 function pesxco(c VARCHAR2 CHARACTER SET ANY_CS, format VARCHAR2) return raw;
25 pragma interface (c,pesxco);
26
27 function pesxup(ch VARCHAR2 CHARACTER SET ANY_CS, format VARCHAR2)
28 return VARCHAR2 CHARACTER SET ch%CHARSET;
29 pragma interface (c,pesxup);
30
31 function pesxlo(ch VARCHAR2 CHARACTER SET ANY_CS, format VARCHAR2)
32 return VARCHAR2 CHARACTER SET ch%CHARSET;
33 pragma interface (c,pesxlo);
34
35 function pesxcp(ch VARCHAR2 CHARACTER SET ANY_CS, format VARCHAR2)
36 return VARCHAR2 CHARACTER SET ch%CHARSET;
37 pragma interface (c,pesxcp);
38
39 -- end of NLS icds
40
41 -- begin trusted icds
42 -- Comparisons
43 -- Conversions
44 -- function peslts(label MLSLABEL,format VARCHAR2) return VARCHAR2;
45 -- pragma interface (c,peslts);
46 -- function pesstl(label varchar2,format VARCHAR2) return MLSLABEL;
47 -- pragma interface (c,pesstl);
48 -- end trusted icds
49 -----------------------------------------------------------
50
51 function sqlerrm return varchar2 is
52 n1 number;
53 begin
54 n1 := sqlcode;
55 return sqlerrm(n1);
56 end sqlerrm;
57
58 function pessdx (ch VARCHAR2 CHARACTER SET ANY_CS)
59 return VARCHAR2 CHARACTER SET ch%CHARSET;
60 pragma interface (c,pessdx);
61
62 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
63 -- the old 'select soundex(...) from dual;' thing. This allows us to do the
64 -- SELECT from PL/SQL rather than having to do it from C (within the ICD.)
65 function SOUNDEX(ch VARCHAR2 CHARACTER SET ANY_CS)
66 return VARCHAR2 CHARACTER SET ch%CHARSET is
67 c VARCHAR2(2000) CHARACTER SET ch%CHARSET;
68 begin
69 c := pessdx(ch);
70 return c;
71 exception
72 when ICD_UNABLE_TO_COMPUTE then
73 select soundex(ch) into c from sys.dual;
74 return c;
75 end SOUNDEX;
76
77 function TRANSLATE(STR1 VARCHAR2 CHARACTER SET ANY_CS,
78 SRC VARCHAR2 CHARACTER SET STR1%CHARSET,
79 DEST VARCHAR2 CHARACTER SET STR1%CHARSET)
80 return VARCHAR2 CHARACTER SET STR1%CHARSET is
81 begin
82 if str1 is null then return str1; else
83 -- The substr and concat in arg list to pesxlt is done to
84 -- allocate a modifiable COPY of the first arg, STR1. This
85 -- operation is a complete cheat, because we pass the copy
86 -- as an IN parm, and modify it on the sly.
87 return pesxlt(STR1, substr(str1,1,1) || substr(str1,2),
88 SRC, DEST);
89 end if;
90 end TRANSLATE;
91
92 function 'REM' (LEFT NUMBER, RIGHT NUMBER) return NUMBER is
93 begin
94 return (LEFT - (trunc(LEFT / RIGHT) * RIGHT));
95 end;
96
97 function 'REM' (LEFT BINARY_FLOAT, RIGHT BINARY_FLOAT)
98 return BINARY_FLOAT is
99 begin
100 return (LEFT - (trunc(LEFT / RIGHT) * RIGHT));
101 end;
102
103 function 'REM' (LEFT BINARY_DOUBLE, RIGHT BINARY_DOUBLE)
104 return BINARY_DOUBLE is
105 begin
106 return (LEFT - (trunc(LEFT / RIGHT) * RIGHT));
107 end;
108
109 -- Just call the other to_char with a null format string.
110 -- Perhaps this can be done more intelligently in the future. JEM 3/14/90.
111 -- function TO_CHAR(LEFT NUMBER) return varchar2 is
112 -- begin
113 -- return TO_CHAR(LEFT, '');
114 -- end TO_CHAR;
115
116 -- Added 3/16/90 by JEM.
117 function TO_NUMBER(LEFT NUMBER) return NUMBER is
118 begin
119 return(LEFT);
120 end to_number;
121
122 function TO_BINARY_FLOAT (LEFT BINARY_FLOAT) return BINARY_FLOAT is
123 begin
124 return(LEFT);
125 end TO_BINARY_FLOAT;
126
127 function TO_BINARY_DOUBLE(LEFT BINARY_DOUBLE) return BINARY_DOUBLE is
128 begin
129 return(LEFT);
130 end TO_BINARY_DOUBLE;
131
132 function 'IS NAN' (N NUMBER) RETURN BOOLEAN is
133 begin
134 if N IS NULL then
135 return NULL;
136 else
137 return FALSE;
138 end if;
139 end 'IS NAN';
140
141 function 'IS NOT NAN' (N NUMBER) RETURN BOOLEAN is
142 begin
143 if N IS NULL then
144 return NULL;
145 else
146 return TRUE;
147 end if;
148 end 'IS NOT NAN';
149
150 function NANVL(n1 NUMBER, n2 NUMBER) return NUMBER is
151 begin
152 return (n1);
153 end NANVL;
154
155 function NANVL(f1 BINARY_FLOAT, f2 BINARY_FLOAT) return BINARY_FLOAT is
156 begin
157 if f1 is nan then return (f2); else return (f1); end if;
158 end NANVL;
159
160 function NANVL(d1 BINARY_DOUBLE, d2 BINARY_DOUBLE) return BINARY_DOUBLE is
161 begin
162 if d1 is nan then return (d2); else return (d1); end if;
163 end NANVL;
164
165 function TO_DATE(LEFT NUMBER, RIGHT VARCHAR2) return DATE IS
166 begin
167 return (TO_DATE(TO_char(LEFT), RIGHT));
168 end TO_DATE;
169
170 function UID return PLS_INTEGER is
171 i pls_integer;
172 begin
173 select uid into i from sys.dual;
174 return i;
175 end;
176
177 function USER return varchar2 is
178 c varchar2(255);
179 begin
180 select user into c from sys.dual;
181 return c;
182 end;
183
184
185 function pesuen(envstr VARCHAR2) return VARCHAR2;
186 pragma interface (c,pesuen);
187
188 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
189 -- the old 'select userenv(...) from dual;' thing. This allows us to do the
190 -- select from PL/SQL rather than having to do it from C (within the ICD.)
191 function USERENV (envstr varchar2) return varchar2 is
192 c varchar2(255);
193 begin
194 c := upper(envstr);
195
196 -- Gaak: we can't replace the following with a single block of code based
197 -- around 'USERENV(c)' because passing USERENV() anything but a string
198 -- literal parameter result in ORA-2003: Invalid USERENV parameter! This
199 -- also means that we must manually update this file whenever RDBMS adds a
200 -- new option.
201 if c = 'COMMITSCN' then
202 raise USERENV_COMMITSCN_ERROR;
203 elsif c = 'TERMINAL' then
204 begin
205 c := pesuen(c);
206 exception
207 when ICD_UNABLE_TO_COMPUTE then
208 select userenv('TERMINAL') into c from sys.dual;
209 end;
210 elsif c = 'ENTRYID' then
211 begin
212 c := pesuen(c);
213 exception
214 when ICD_UNABLE_TO_COMPUTE then
215 select userenv('ENTRYID') into c from sys.dual;
216 end;
217 elsif c = 'SESSIONID' then
218 begin
219 c := pesuen(c);
220 exception
221 when ICD_UNABLE_TO_COMPUTE then
222 select userenv('SESSIONID') into c from sys.dual;
223 end;
224 elsif c = 'LANGUAGE' then
225 begin
226 c := pesuen(c);
227 exception
228 when ICD_UNABLE_TO_COMPUTE then
229 select userenv('LANGUAGE') into c from sys.dual;
230 end;
231 elsif c = 'LANG' then
232 begin
233 c := pesuen(c);
234 exception
235 when ICD_UNABLE_TO_COMPUTE then
236 select userenv('LANG') into c from sys.dual;
237 end;
238 elsif c = 'INSTANCE' then
239 begin
240 c := pesuen(c);
241 exception
242 when ICD_UNABLE_TO_COMPUTE then
243 select userenv('INSTANCE') into c from sys.dual;
244 end;
245 elsif c = 'CLIENT_INFO' then
246 begin
247 c := pesuen(c);
248 exception
249 when ICD_UNABLE_TO_COMPUTE then
250 select userenv('CLIENT_INFO') into c from sys.dual;
251 end;
252 elsif c = 'ISDBA' then
253 begin
254 c := pesuen(c);
255 exception
256 when ICD_UNABLE_TO_COMPUTE then
257 select userenv('ISDBA') into c from sys.dual;
258 end;
259 elsif c = 'SCHEMAID' then
260 begin
261 c := pesuen(c);
262 exception
263 when ICD_UNABLE_TO_COMPUTE then
264 select userenv('SCHEMAID') into c from sys.dual;
265 end;
266 elsif c = 'SID' then
267 begin
268 c := pesuen(c);
269 exception
270 when ICD_UNABLE_TO_COMPUTE then
271 select userenv('SID') into c from sys.dual;
272 end;
273 elsif c = 'PID' then
274 begin
275 c := pesuen(c);
276 exception
277 when ICD_UNABLE_TO_COMPUTE then
278 select userenv('PID') into c from sys.dual;
279 end;
280 else
281 raise INVALID_USERENV_PARAMETER;
282 end if;
283 return c;
284 end;
285
286 -- Trusted*Oracle additions
287
288 Function ROWLABEL return MLSLABEL is
289 begin return null; end;
290 -- removed - now builtin's
291
292 -- Function TO_CHAR(label MLSLABEL, format varchar2 := '')
293 -- return VARCHAR2 is
294 -- begin return peslts(label,format); end;
295 --
296 -- Function TO_LABEL(label varchar2, format varchar2 := '')
297 -- return MLSLABEL is
298 -- begin return pesstl(label,format); end;
299
300 -- group functions
301 Function LUB (label MLSLABEL) return MLSLABEL is
302 begin return null; end;
303 Function GLB (label MLSLABEL) return MLSLABEL is
304 begin return null; end;
305
306 -- end of Trusted*Oracle additions
307
308
309 -- beginning of NLS routines
310 -- replaced with new versions 6/3/92 JEM
311
312 function NLSSORT(c VARCHAR2 CHARACTER SET ANY_CS) return RAW is
313 begin
314 return pesxco(c,'');
315 end NLSSORT;
316
317 function NLS_UPPER(ch VARCHAR2 CHARACTER SET ANY_CS)
318 return VARCHAR2 CHARACTER SET ch%CHARSET is
319 begin
320 return pesxup(ch,'');
321 end NLS_UPPER;
322
323 function NLS_LOWER(ch VARCHAR2 CHARACTER SET ANY_CS)
324 return VARCHAR2 CHARACTER SET ch%CHARSET is
325 begin
326 return pesxlo(ch,'');
327 end NLS_LOWER;
328
329 function NLS_INITCAP(ch VARCHAR2 CHARACTER SET ANY_CS)
330 return VARCHAR2 CHARACTER SET ch%CHARSET is
331 begin
332 return pesxcp(ch,'');
333 end NLS_INITCAP;
334
335 function NLS_CHARSET_NAME(csetid PLS_INTEGER)
336 return VARCHAR2 is
337 v varchar2(2000);
338 begin
339 select nls_charset_name(csetid) into v from sys.dual;
340 return v;
341 end NLS_CHARSET_NAME;
342
343 function NLS_CHARSET_ID(csetname VARCHAR2)
344 return PLS_INTEGER is
345 i PLS_INTEGER;
346 begin
347 select nls_charset_id(csetname) into i from sys.dual;
348 return i;
349 end NLS_CHARSET_ID;
350
351 function NLS_CHARSET_DECL_LEN(bytecnt NUMBER, csetid NUMBER)
352 return PLS_INTEGER is
353 i PLS_INTEGER;
354 begin
355 select nls_charset_decl_len(bytecnt, csetid) into i from sys.dual;
356 return i;
357 end NLS_CHARSET_DECL_LEN;
358 -- end of NLS routines
359
360
361 -- DUMP and VSIZE are now not allowed in non-sql plsql, has code to forbid
362 -- it there, and is defined as a builtin in stdspc. The body will not be
363 -- called in plsql.
364 --- CMB
365 ----
366 -- dump
367 -- dump( expr [,display_format[,start_pos[,length]]]) return varchar2
368 -- how large should the plsql varchar2 string be
369 --
370
371 -- why do we need these dummy bodies for LEVEL and ROWNUM?
372
373 function LEVEL return NUMBER is
374 begin return 0.0; end;
375
376 function ROWNUM return NUMBER is
377 begin return 0.0; end;
378
379 --
380 -- ACOS, ASIN, ATAN, ATAN2
381 -- These functions return NULL if any of the inputs are NULL
382 --
383 function pesacos(n NUMBER) return NUMBER;
384 pragma interface (c,pesacos);
385
386 function pesasin(n NUMBER) return NUMBER;
387 pragma interface (c,pesasin);
388
389 function pesatn2(x NUMBER, y NUMBER) return NUMBER;
390 pragma interface (c,pesatn2);
391
392 function ACOS(n NUMBER) return NUMBER is
393 begin
394 if (n > 1) or (n < -1) then raise VALUE_ERROR; end if;
395 return pesacos(n);
396 end ACOS;
397
398 function ASIN(n NUMBER) return NUMBER is
399 begin
400 if (n > 1) or (n < -1) then raise VALUE_ERROR; end if;
401 return pesasin(n);
402 end ASIN;
403
404 function ATAN2(x NUMBER, y NUMBER) return NUMBER is
405 begin
406 if ((x = 0) and (y = 0)) then raise VALUE_ERROR; end if;
407 return pesatn2(x, y);
408 end ATAN2;
409
410 --****************************************************************
411
412 -- This body is required, and will be called
413 function NVL (B1 "<REF_CURSOR_1>", B2 "<REF_CURSOR_1>")
414 return "<REF_CURSOR_1>" is
415 begin
416 if (B1 IS NULL) then return(B2); else return(B1); end if;
417 end NVL;
418
419 /* these are special internal functions
420 they are potential dangerous and not to be used by customers */
421 function "SYS$LOB_REPLICATION" (x in blob) return blob
422 is begin return x; end;
423 function "SYS$LOB_REPLICATION" (x in clob character set any_cs)
424 return clob character set x%charset
425 is begin return x; end;
426
427 -- Generic SQL DDL routine
428 --
429 -- This used to use plzopn, plzosq, etc. declared above; now we use a
430 -- single bundled call. Move these defs here so new ICD will not disturb
431 -- the ordering of the list.
432
433 FUNCTION plzsql(stmt VARCHAR2) RETURN binary_integer;
434 PRAGMA interface (c,plzsql);
435
436 procedure SQL_DDL(Stmt VARCHAR2) is
437 rc Binary_Integer;
438 DDL_ERROR exception;
439 Begin
440 rc := plzsql(Stmt);
441 if ( rc IS NOT NULL ) then
442 RAISE DDL_ERROR;
443 end if;
444 End;
445
446 -- SQL Transaction routines
447
448 procedure SET_TRANSACTION_USE (vc varchar2) is
449 Begin
450 SQL_DDL('SET TRANSACTION USE ROLLBACK SEGMENT ' || vc);
451 End;
452
453 procedure COMMIT is
454 Begin
455 SQL_DDL('COMMIT');
456 End;
457
458 procedure COMMIT_CM (vc varchar2) is
459 Begin
460 -- bug13944958:
461 -- COMMIT_CM procedure takes the input argument "vs" as the comment string
462 -- to execute the SQL DDL "COMMIT work comment 'vc'" statement.
463 -- The input comment string to the COMMIT statement is vulnerable to
467 SQL_DDL('COMMIT work comment ' || '''' ||
464 -- SQL injection because it may contain single-quotes.
465 -- Before we manually quote the comment string, we need to escape any
466 -- embedded quotes first.
468 replace(vc, '''', '''''') || '''');
469 End;
470
471 procedure ROLLBACK_NR is
472 Begin
473 SQL_DDL('ROLLBACK');
474 End;
475
476 procedure ROLLBACK_SV(Save_Point CHAR) is
477 Begin
478 SQL_DDL('ROLLBACK TO ' || Save_Point);
479 End;
480
481 procedure SAVEPOINT(Save_Point CHAR) is
482 begin
483 SQL_DDL('SAVEPOINT ' || Save_Point);
484 end;
485
486
487 ------ Datetime code starts here ------
488
489
490 -- functions to create intervals from constituent parts.
491
492 function pesn2ymi(numerator number, units number)
493 return yminterval_unconstrained;
494 pragma interface (c,pesn2ymi);
495 function pesn2dsi(numerator number, units number)
496 return dsinterval_unconstrained;
497 pragma interface (c,pesn2dsi);
498
499 function NUMTOYMINTERVAL(numerator number, units number)
500 return yminterval_unconstrained
501 is begin return pesn2ymi(numerator,units); end;
502 function NUMTODSINTERVAL(numerator number, units number)
503 return dsinterval_unconstrained
504 is begin return pesn2dsi(numerator,units); end;
505
506 function NUMTOYMINTERVAL(numerator number, units varchar2 character set any_cs)
507 return yminterval_unconstrained
508 IS unitno NUMBER := 0;
509 unitstr VARCHAR2(5) character set units%charset := upper(trim(units));
510 begin
511 IF (unitstr = 'YEAR') THEN unitno := 1;
512 elsif (unitstr = 'MONTH') THEN unitno := 2;
513 END IF;
514 return pesn2ymi(numerator,unitno);
515 -- IF unitno := 0 core will RAISE correct error
516 end;
517
518 function NUMTODSINTERVAL(numerator number, units varchar2 character set any_cs)
519 return dsinterval_unconstrained
520 IS unitno NUMBER := 0;
521 unitstr VARCHAR2(6) character set units%charset := upper(trim(units));
522 begin
523 IF (unitstr = 'DAY') THEN unitno := 1;
524 elsif (unitstr = 'HOUR') THEN unitno := 2;
525 elsif (unitstr = 'MINUTE') THEN unitno := 3;
526 elsif (unitstr = 'SECOND') THEN unitno := 4;
527 END IF;
528 return pesn2dsi(numerator,unitno);
529 -- IF unitno = 0 core will RAISE correct error
530 end;
531
532 function pessdt return DATE;
533 pragma interface (c,pessdt);
534
535 -- Bug 1287775: back to calling ICD.
536 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
537 -- the old 'SELECT SYSDATE FROM DUAL;' thing. This allows us to do the
538 -- SELECT from PL/SQL rather than having to do it from C (within the ICD.)
539 function sysdate return date is
540 d date;
541 begin
542 d := pessdt;
543 return d;
544 exception
545 when ICD_UNABLE_TO_COMPUTE then
546 select sysdate into d from sys.dual;
547 return d;
548 end;
549
550 function pesguid return RAW;
551 pragma interface (c,pesguid);
552
553 function SYS_GUID return raw is
554 c raw(16);
555 begin
556 c := pesguid;
557 return c;
558 exception
559 when ICD_UNABLE_TO_COMPUTE then
560 select sys_guid() into c from sys.dual;
561 return c;
562 end;
563
564 function pessysctx2(namespace varchar2, attribute varchar2) return varchar2;
565 pragma interface (c,pessysctx2);
566
567 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
568 -- the old 'select sys_context(...) from dual;' thing. This allows us to do
569 -- the select from PL/SQL rather than having to do it from C (within the ICD.)
570 function SYS_CONTEXT(namespace varchar2, attribute varchar2)
571 return varchar2 is
572 c varchar2(4000);
573 BEGIN
574 c := pessysctx2(namespace, attribute);
575 return c;
576 exception
577 when ICD_UNABLE_TO_COMPUTE then
578 select sys_context(namespace,attribute) into c from sys.dual;
579 return c;
580 end;
581
582 -- time zone functions
583
584 function pessts return timestamp_tz_unconstrained;
585 pragma interface (c,pessts);
586
587 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
588 -- the old 'SELECT systimestamp FROM dual;' thing. This allows us to do the
589 -- SELECT from PL/SQL rather than having to do it from C (within the ICD.)
590 FUNCTION systimestamp RETURN timestamp_tz_unconstrained
591 IS t timestamp_tz_unconstrained;
592 BEGIN
593 t := pessts;
594 RETURN t;
595 EXCEPTION
596 WHEN ICD_UNABLE_TO_COMPUTE THEN
597 SELECT systimestamp INTO t FROM sys.dual;
598 RETURN t;
599 END;
600
601 function pesdbtz return varchar2;
602 pragma interface (c,pesdbtz);
603
604 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
605 -- the old 'SELECT dbtimezone FROM dual;' thing. This allows us to do the
606 -- SELECT from PL/SQL rather than having to do it from C (within the ICD.)
607 FUNCTION dbtimezone RETURN varchar2
608 IS t VARCHAR2(75); -- == TZNMSTRLEN [2213965]
609 BEGIN
610 t := pesdbtz;
611 RETURN t;
612 EXCEPTION
613 WHEN ICD_UNABLE_TO_COMPUTE THEN
614 SELECT dbtimezone INTO t FROM sys.dual;
615 RETURN t;
616 END;
617
618 FUNCTION localtimestamp RETURN timestamp_unconstrained
619 IS t timestamp_tz_unconstrained := current_timestamp;
620 BEGIN
621 RETURN (cast(t AS timestamp_unconstrained));
622 END;
623
624 FUNCTION localtime RETURN time_unconstrained
625 IS t time_tz_unconstrained := current_time;
626 BEGIN
627 RETURN (cast(t AS time_unconstrained));
628 END;
629
630 function pessysctx3(namespace varchar2, attribute varchar2,
631 newoptional varchar2) return varchar2;
632 pragma interface (c,pessysctx3);
633
634 -- Special: if the ICD raises ICD_UNABLE_TO_COMPUTE, that means we should do
635 -- the old 'select sys_context(...) from dual;' thing. This allows us to do
636 -- the select from PL/SQL rather than having to do it from C (within the ICD.)
637 function SYS_CONTEXT(namespace varchar2, attribute varchar2,
638 newoptional varchar2)
639 return varchar2 is
640 c varchar2(4000);
641 BEGIN
642 c := pessysctx3(namespace, attribute, newoptional);
643 return c;
644 exception
645 when ICD_UNABLE_TO_COMPUTE then
646 select sys_context(namespace,attribute,newoptional) into c from sys.dual;
647 return c;
648 end;
649
650 function TO_NCLOB(cl CLOB CHARACTER SET ANY_CS) return NCLOB is
651 begin
652 return cl;
653 end;
654 function TO_CLOB(cl CLOB CHARACTER SET ANY_CS) return CLOB is
655 begin
656 return cl;
657 end;
658
659 function NCHR(n INTEGER) return NVARCHAR2 is
660 begin
661 return CHR(n using NCHAR_CS);
662 end;
663
664 -- REFs of opaque types are not yet supported.
665 -- function NVL (B1 REF "<OPAQUE_1>", B2 REF "<OPAQUE_1>")
666 -- return REF "<OPAQUE_1>" is
667 -- begin
668 -- if (B1 IS NULL) then return(B2); else return(B1); end if;
669 -- end NVL;
670
671
672 -- END OF PACKAGE standard
673 end;
674
675